Add option to preserve alpha channel in export (closes #661)
Default off cause it being on by default had confused quite a few people.
This commit is contained in:
@@ -40,7 +40,7 @@ public class GuiCreateScreenshot extends GuiRenderSettings implements Loadable {
|
||||
new GuiLabel().setI18nText("replaymod.gui.advancedscreenshots.resolution"), videoResolutionPanel,
|
||||
new GuiLabel().setI18nText("replaymod.gui.rendersettings.outputfile"), outputFileButton);
|
||||
|
||||
resetChildren(advancedPanel).addElements(null, nametagCheckbox, new GuiPanel().setLayout(
|
||||
resetChildren(advancedPanel).addElements(null, nametagCheckbox, alphaCheckbox , new GuiPanel().setLayout(
|
||||
new GridLayout().setCellsEqualSize(false).setColumns(2).setSpacingX(5).setSpacingY(15))
|
||||
.addElements(new GridLayout.Data(0, 0.5),
|
||||
new GuiLabel().setI18nText("replaymod.gui.rendersettings.stabilizecamera"), stabilizePanel,
|
||||
|
||||
@@ -28,9 +28,11 @@ import static org.lwjgl.util.tinyexr.TinyEXR.*;
|
||||
public class EXRWriter implements FrameConsumer<BitmapFrame> {
|
||||
|
||||
private final Path outputFolder;
|
||||
private final boolean keepAlpha;
|
||||
|
||||
public EXRWriter(Path outputFolder) throws IOException {
|
||||
public EXRWriter(Path outputFolder, boolean keepAlpha) throws IOException {
|
||||
this.outputFolder = outputFolder;
|
||||
this.keepAlpha = keepAlpha;
|
||||
|
||||
Files.createDirectories(outputFolder);
|
||||
}
|
||||
@@ -92,11 +94,15 @@ public class EXRWriter implements FrameConsumer<BitmapFrame> {
|
||||
bgrChannels[(i + 3) % 4] = channel;
|
||||
}
|
||||
}
|
||||
|
||||
int alphaMask = keepAlpha ? 0 : 0xff;
|
||||
|
||||
for (int y = 0; y < height; y++) {
|
||||
for (int x = 0; x < width; x++) {
|
||||
for (FloatBuffer channel : bgrChannels) {
|
||||
channel.put(((int) bgra.get() & 0xff) / 255f);
|
||||
}
|
||||
bgrChannels[0].put(((int) bgra.get() & 0xff) / 255f); // b
|
||||
bgrChannels[1].put(((int) bgra.get() & 0xff) / 255f); // g
|
||||
bgrChannels[2].put(((int) bgra.get() & 0xff) / 255f); // r
|
||||
bgrChannels[3].put(((int) bgra.get() & 0xff | alphaMask) / 255f); // a
|
||||
}
|
||||
}
|
||||
if (depthFrame != null && depthChannel != null) {
|
||||
|
||||
@@ -19,9 +19,11 @@ import java.util.Map;
|
||||
public class PNGWriter implements FrameConsumer<BitmapFrame> {
|
||||
|
||||
private final Path outputFolder;
|
||||
private final boolean keepAlpha;
|
||||
|
||||
public PNGWriter(Path outputFolder) throws IOException {
|
||||
public PNGWriter(Path outputFolder, boolean keepAlpha) throws IOException {
|
||||
this.outputFolder = outputFolder;
|
||||
this.keepAlpha = keepAlpha;
|
||||
|
||||
Files.createDirectories(outputFolder);
|
||||
}
|
||||
@@ -47,6 +49,7 @@ public class PNGWriter implements FrameConsumer<BitmapFrame> {
|
||||
}
|
||||
|
||||
private void withImage(BitmapFrame frame, IOConsumer<Image> consumer) throws IOException {
|
||||
byte alphaMask = (byte) (keepAlpha ? 0 : 0xff);
|
||||
ByteBuffer buffer = frame.getByteBuffer();
|
||||
ReadableDimension size = frame.getSize();
|
||||
int width = size.getWidth();
|
||||
@@ -58,7 +61,7 @@ public class PNGWriter implements FrameConsumer<BitmapFrame> {
|
||||
byte g = buffer.get();
|
||||
byte r = buffer.get();
|
||||
byte a = buffer.get();
|
||||
image.setRGBA(x, y, r, g, b, a);
|
||||
image.setRGBA(x, y, r, g, b, a | alphaMask);
|
||||
}
|
||||
}
|
||||
consumer.accept(image);
|
||||
|
||||
@@ -151,6 +151,7 @@ public class RenderSettings {
|
||||
private final File outputFile;
|
||||
|
||||
private final boolean renderNameTags;
|
||||
private final boolean includeAlphaChannel;
|
||||
private final boolean stabilizeYaw;
|
||||
private final boolean stabilizePitch;
|
||||
private final boolean stabilizeRoll;
|
||||
@@ -187,6 +188,7 @@ public class RenderSettings {
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
null,
|
||||
360,
|
||||
180,
|
||||
@@ -209,6 +211,7 @@ public class RenderSettings {
|
||||
int bitRate,
|
||||
File outputFile,
|
||||
boolean renderNameTags,
|
||||
boolean includeAlphaChannel,
|
||||
boolean stabilizeYaw,
|
||||
boolean stabilizePitch,
|
||||
boolean stabilizeRoll,
|
||||
@@ -231,6 +234,7 @@ public class RenderSettings {
|
||||
this.bitRate = bitRate;
|
||||
this.outputFile = outputFile;
|
||||
this.renderNameTags = renderNameTags;
|
||||
this.includeAlphaChannel = includeAlphaChannel;
|
||||
this.stabilizeYaw = stabilizeYaw;
|
||||
this.stabilizePitch = stabilizePitch;
|
||||
this.stabilizeRoll = stabilizeRoll;
|
||||
@@ -256,6 +260,7 @@ public class RenderSettings {
|
||||
bitRate,
|
||||
outputFile,
|
||||
renderNameTags,
|
||||
includeAlphaChannel,
|
||||
stabilizeYaw,
|
||||
stabilizePitch,
|
||||
stabilizeRoll,
|
||||
@@ -415,6 +420,10 @@ public class RenderSettings {
|
||||
return renderNameTags;
|
||||
}
|
||||
|
||||
public boolean isIncludeAlphaChannel() {
|
||||
return includeAlphaChannel;
|
||||
}
|
||||
|
||||
public boolean isStabilizeYaw() {
|
||||
return stabilizeYaw;
|
||||
}
|
||||
@@ -478,6 +487,7 @@ public class RenderSettings {
|
||||
", bitRate=" + bitRate +
|
||||
", outputFile=" + outputFile +
|
||||
", renderNameTags=" + renderNameTags +
|
||||
", includeAlphaChannel=" + includeAlphaChannel +
|
||||
", stabilizeYaw=" + stabilizeYaw +
|
||||
", stabilizePitch=" + stabilizePitch +
|
||||
", stabilizeRoll=" + stabilizeRoll +
|
||||
|
||||
@@ -90,6 +90,7 @@ public class GuiExportFailed extends GuiScreen {
|
||||
oldSettings.getBitRate(),
|
||||
oldSettings.getOutputFile(),
|
||||
oldSettings.isRenderNameTags(),
|
||||
oldSettings.isIncludeAlphaChannel(),
|
||||
oldSettings.isStabilizeYaw(),
|
||||
oldSettings.isStabilizePitch(),
|
||||
oldSettings.isStabilizeRoll(),
|
||||
|
||||
@@ -148,6 +148,9 @@ public class GuiRenderSettings extends AbstractGuiPopup<GuiRenderSettings> {
|
||||
public final GuiCheckbox nametagCheckbox = new GuiCheckbox()
|
||||
.setI18nLabel("replaymod.gui.rendersettings.nametags");
|
||||
|
||||
public final GuiCheckbox alphaCheckbox = new GuiCheckbox()
|
||||
.setI18nLabel("replaymod.gui.rendersettings.includealpha");
|
||||
|
||||
public final GuiPanel stabilizePanel = new GuiPanel().setLayout(new HorizontalLayout().setSpacing(10));
|
||||
public final GuiCheckbox stabilizeYaw = new GuiCheckbox(stabilizePanel)
|
||||
.setI18nLabel("replaymod.gui.yaw");
|
||||
@@ -187,7 +190,7 @@ public class GuiRenderSettings extends AbstractGuiPopup<GuiRenderSettings> {
|
||||
.setSize(200, 20).setValues(RenderSettings.AntiAliasing.values()).setSelected(RenderSettings.AntiAliasing.NONE);
|
||||
|
||||
public final GuiPanel advancedPanel = new GuiPanel().setLayout(new VerticalLayout().setSpacing(15))
|
||||
.addElements(null, nametagCheckbox, new GuiPanel().setLayout(
|
||||
.addElements(null, nametagCheckbox, alphaCheckbox, new GuiPanel().setLayout(
|
||||
new GridLayout().setCellsEqualSize(false).setColumns(2).setSpacingX(5).setSpacingY(15))
|
||||
.addElements(new GridLayout.Data(0, 0.5),
|
||||
new GuiLabel().setI18nText("replaymod.gui.rendersettings.stabilizecamera"), stabilizePanel,
|
||||
@@ -522,6 +525,7 @@ public class GuiRenderSettings extends AbstractGuiPopup<GuiRenderSettings> {
|
||||
}
|
||||
outputFileButton.setLabel(this.outputFile.getName());
|
||||
nametagCheckbox.setChecked(settings.isRenderNameTags());
|
||||
alphaCheckbox.setChecked(settings.isIncludeAlphaChannel());
|
||||
stabilizeYaw.setChecked(settings.isStabilizeYaw());
|
||||
stabilizePitch.setChecked(settings.isStabilizePitch());
|
||||
stabilizeRoll.setChecked(settings.isStabilizeRoll());
|
||||
@@ -560,6 +564,7 @@ public class GuiRenderSettings extends AbstractGuiPopup<GuiRenderSettings> {
|
||||
bitRateField.getInteger() << (10 * bitRateUnit.getSelected()),
|
||||
serialize && !userDefinedOutputFileName ? getParentFile(outputFile) : outputFile,
|
||||
nametagCheckbox.isChecked(),
|
||||
alphaCheckbox.isChecked(),
|
||||
stabilizeYaw.isChecked() && (serialize || stabilizeYaw.isEnabled()),
|
||||
stabilizePitch.isChecked() && (serialize || stabilizePitch.isEnabled()),
|
||||
stabilizeRoll.isChecked() && (serialize || stabilizeRoll.isEnabled()),
|
||||
|
||||
@@ -136,12 +136,12 @@ public class VideoRenderer implements RenderInfo {
|
||||
FrameConsumer<BitmapFrame> frameConsumer;
|
||||
if (settings.getEncodingPreset() == RenderSettings.EncodingPreset.EXR) {
|
||||
//#if MC>=11400
|
||||
frameConsumer = new EXRWriter(settings.getOutputFile().toPath());
|
||||
frameConsumer = new EXRWriter(settings.getOutputFile().toPath(), settings.isIncludeAlphaChannel());
|
||||
//#else
|
||||
//$$ throw new UnsupportedOperationException("EXR requires LWJGL3");
|
||||
//#endif
|
||||
} else if (settings.getEncodingPreset() == RenderSettings.EncodingPreset.PNG) {
|
||||
frameConsumer = new PNGWriter(settings.getOutputFile().toPath());
|
||||
frameConsumer = new PNGWriter(settings.getOutputFile().toPath(), settings.isIncludeAlphaChannel());
|
||||
} else {
|
||||
frameConsumer = new FFmpegWriter(this);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user