From 0b48eab7f71ea55cf93ac02856c5c82996cad44c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jindra=20Pet=C5=99=C3=ADk?= Date: Sat, 27 Jul 2024 17:35:32 +0200 Subject: [PATCH] Added #2011, #2215 Option to ignore frame background color when exporting (make transparent) --- CHANGELOG.md | 3 ++ .../src/com/jpexs/decompiler/flash/SWF.java | 2 +- .../flash/configuration/Configuration.java | 4 +++ .../flash/exporters/FrameExporter.java | 19 +++++------- .../exporters/commonshape/SVGExporter.java | 21 ++++++++++++-- .../settings/FrameExportSettings.java | 5 +++- .../console/CommandLineArgumentParser.java | 10 +++++-- .../jpexs/decompiler/flash/console/help.txt | 5 ++++ .../decompiler/flash/gui/ExportDialog.java | 29 ++++++++++++++++++- .../jpexs/decompiler/flash/gui/MainPanel.java | 6 ++-- .../locales/AdvancedSettingsDialog.properties | 2 ++ .../flash/gui/locales/ExportDialog.properties | 3 +- .../gui/locales/ExportDialog_cs.properties | 3 +- 13 files changed, 88 insertions(+), 24 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 740d41ee4..a375f70ce 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,7 @@ All notable changes to this project will be documented in this file. - [#2259] Optional resampling sound to 44kHz on playback and on export - Set class to character mapping tool (via SymbolClass) context menu on characters - [#2189] Search bar in replace character (+ replace references) window +- [#2011], [#2215] Option to ignore frame background color when exporting (make transparent) ### Fixed - Debugger - getting children of top level variables @@ -3410,6 +3411,8 @@ Major version of SWF to XML export changed to 2. [#2185]: https://www.free-decompiler.com/flash/issues/2185 [#2259]: https://www.free-decompiler.com/flash/issues/2259 [#2189]: https://www.free-decompiler.com/flash/issues/2189 +[#2011]: https://www.free-decompiler.com/flash/issues/2011 +[#2215]: https://www.free-decompiler.com/flash/issues/2215 [#2149]: https://www.free-decompiler.com/flash/issues/2149 [#2172]: https://www.free-decompiler.com/flash/issues/2172 [#2174]: https://www.free-decompiler.com/flash/issues/2174 diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java index 67fee6e4f..c4cdb9dc3 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java @@ -3605,7 +3605,7 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { renderContext.cursorPosition = cursorPosition; renderContext.mouseButton = mouseButton; ExportRectangle viewRect = new ExportRectangle(rect); - timeline.toImage(frame, time, renderContext, image, image, false, m, new Matrix(), m, colorTransform, zoom, false, viewRect, m, true, Timeline.DRAW_MODE_ALL, 0, canUseSmoothing); + timeline.toImage(frame, time, renderContext, image, image, false, m, new Matrix(), m, colorTransform, zoom, true, viewRect, m, true, Timeline.DRAW_MODE_ALL, 0, canUseSmoothing); return image; } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/configuration/Configuration.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/configuration/Configuration.java index 4c7b5eb9e..b48d224af 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/configuration/Configuration.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/configuration/Configuration.java @@ -1001,6 +1001,10 @@ public final class Configuration { @ConfigurationCategory("display") public static ConfigurationItem previewResampleSound = null; + @ConfigurationDefaultBoolean(false) + @ConfigurationCategory("export") + public static ConfigurationItem lastExportTransparentBackground = null; + private enum OSId { WINDOWS, OSX, UNIX } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/FrameExporter.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/FrameExporter.java index a351ad3b5..ea1efabce 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/FrameExporter.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/FrameExporter.java @@ -128,7 +128,7 @@ public class FrameExporter { frames.add(0); // todo: export all frames } - FrameExportSettings fes = new FrameExportSettings(fem, settings.zoom); + FrameExportSettings fes = new FrameExportSettings(fem, settings.zoom, true); return exportFrames(handler, outdir, swf, containerId, frames, fes, evl); } @@ -163,7 +163,7 @@ public class FrameExporter { throw new Error("Unsupported sprite export mode"); } - FrameExportSettings fes = new FrameExportSettings(fem, settings.zoom); + FrameExportSettings fes = new FrameExportSettings(fem, settings.zoom, true); return exportFrames(handler, outdir, swf, containerId, frames, fes, evl); } @@ -224,7 +224,7 @@ public class FrameExporter { } int fframe = fframes.get(pos++); - BufferedImage result = SWF.frameToImageGet(tim, fframe, 0, null, 0, tim.displayRect, new Matrix(), null, usesTransparency ? null : backgroundColor, settings.zoom, true).getBufferedImage(); + BufferedImage result = SWF.frameToImageGet(tim, fframe, 0, null, 0, tim.displayRect, new Matrix(), null, backgroundColor == null && !usesTransparency ? Color.white : backgroundColor, settings.zoom, true).getBufferedImage(); if (Thread.currentThread().isInterrupted()) { return null; } @@ -286,7 +286,7 @@ public class FrameExporter { Color backgroundColor = null; SetBackgroundColorTag setBgColorTag = swf.getBackgroundColor(); - if (setBgColorTag != null) { + if (!settings.transparentBackground && setBgColorTag != null) { backgroundColor = setBgColorTag.backgroundColor.toColor(); } @@ -298,7 +298,7 @@ public class FrameExporter { } final int fi = i; - final Color fbackgroundColor = null; + final Color fbackgroundColor = backgroundColor; for (File foutdir : foutdirs) { new RetryTask(() -> { int frame = fframes.get(fi); @@ -309,11 +309,8 @@ public class FrameExporter { rect.yMax *= settings.zoom; rect.xMin *= settings.zoom; rect.yMin *= settings.zoom; - SVGExporter exporter = new SVGExporter(rect, settings.zoom, "frame"); - if (fbackgroundColor != null) { - exporter.setBackGroundColor(fbackgroundColor); - } - + SVGExporter exporter = new SVGExporter(rect, settings.zoom, "frame", fbackgroundColor); + tim.toSVG(frame, 0, null, 0, exporter, null, 0); fos.write(Utf8Helper.getBytes(exporter.getSVG())); } @@ -379,7 +376,7 @@ public class FrameExporter { } sb.append("\r\n"); RGB backgroundColor1 = new RGB(255, 255, 255); - if (setBgColorTag != null) { + if (!settings.transparentBackground && setBgColorTag != null) { backgroundColor1 = setBgColorTag.backgroundColor; } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/commonshape/SVGExporter.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/commonshape/SVGExporter.java index 1eeb69ee6..a66e1b6e3 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/commonshape/SVGExporter.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/commonshape/SVGExporter.java @@ -89,7 +89,10 @@ public class SVGExporter { public boolean useTextTag = Configuration.textExportExportFontFace.get(); public SVGExporter(ExportRectangle bounds, double zoom, String objectType) { + this(bounds, zoom, objectType, null); + } + public SVGExporter(ExportRectangle bounds, double zoom, String objectType, Color backgroundColor) { DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance(); try { DocumentBuilder docBuilder = docFactory.newDocumentBuilder(); @@ -109,8 +112,22 @@ public class SVGExporter { svgRoot.setAttribute("height", (bounds.getHeight() / SWF.unitDivisor) + "px"); } createDefGroup(bounds, null, zoom); + + if (backgroundColor != null) { + Element rect = _svg.createElement("rect"); + rect.setAttribute("fill", new RGBA(backgroundColor).toHexRGB()); + if (Configuration.svgRetainBounds.get()) { + rect.setAttribute("width", (bounds.xMax / SWF.unitDivisor) + "px"); + rect.setAttribute("height", (bounds.yMax / SWF.unitDivisor) + "px"); + } else { + rect.setAttribute("width", (bounds.getWidth() / SWF.unitDivisor) + "px"); + rect.setAttribute("height", (bounds.getHeight() / SWF.unitDivisor) + "px"); + } + _svgGs.peek().appendChild(rect); + } } svgRoot.setAttribute("ffdec:objectType", objectType); + } catch (ParserConfigurationException ex) { Logger.getLogger(SVGExporter.class.getName()).log(Level.SEVERE, null, ex); } @@ -227,10 +244,10 @@ public class SVGExporter { return writer.toString(); } - public void setBackGroundColor(Color backGroundColor) { + /*public void setBackGroundColor(Color backGroundColor) { Attr attr = _svg.createAttribute("style"); attr.setValue("background: " + new RGBA(backGroundColor).toHexARGB()); - } + }*/ private String addClip(String path) { lastClipId++; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/settings/FrameExportSettings.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/settings/FrameExportSettings.java index e7dc49840..1207f14b6 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/settings/FrameExportSettings.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/settings/FrameExportSettings.java @@ -29,9 +29,12 @@ public class FrameExportSettings { public FrameExportMode mode; public double zoom; + + public boolean transparentBackground; - public FrameExportSettings(FrameExportMode mode, double zoom) { + public FrameExportSettings(FrameExportMode mode, double zoom, boolean transparentBackground) { this.mode = mode; this.zoom = zoom; + this.transparentBackground = transparentBackground; } } diff --git a/src/com/jpexs/decompiler/flash/console/CommandLineArgumentParser.java b/src/com/jpexs/decompiler/flash/console/CommandLineArgumentParser.java index c133a3918..434337cd0 100644 --- a/src/com/jpexs/decompiler/flash/console/CommandLineArgumentParser.java +++ b/src/com/jpexs/decompiler/flash/console/CommandLineArgumentParser.java @@ -503,6 +503,7 @@ public class CommandLineArgumentParser { boolean air = false; boolean exportEmbed = false; boolean resampleWav = false; + boolean transparentBackground = false; Selection selection = new Selection(); Selection selectionIds = new Selection(); List selectionClasses = null; @@ -539,6 +540,9 @@ public class CommandLineArgumentParser { case "-resamplewav": resampleWav = true; break; + case "-ignorebackground": + transparentBackground = true; + break; case "-zoom": zoom = parseZoom(args); break; @@ -653,7 +657,7 @@ public class CommandLineArgumentParser { } else if (command.equals("proxy")) { parseProxy(args); } else if (command.equals("export")) { - parseExport(selectionClasses, selection, selectionIds, args, handler, traceLevel, format, zoom, charset, exportEmbed, resampleWav); + parseExport(selectionClasses, selection, selectionIds, args, handler, traceLevel, format, zoom, charset, exportEmbed, resampleWav, transparentBackground); System.exit(0); } else if (command.equals("compress")) { parseCompress(args); @@ -1918,7 +1922,7 @@ public class CommandLineArgumentParser { } - private static void parseExport(List selectionClasses, Selection selection, Selection selectionIds, Stack args, AbortRetryIgnoreHandler handler, Level traceLevel, Map formats, double zoom, String charset, boolean exportEmbed, boolean resampleWav) { + private static void parseExport(List selectionClasses, Selection selection, Selection selectionIds, Stack args, AbortRetryIgnoreHandler handler, Level traceLevel, Map formats, double zoom, String charset, boolean exportEmbed, boolean resampleWav, boolean transparentBackground) { if (args.size() < 3) { badArguments("export"); } @@ -2147,7 +2151,7 @@ public class CommandLineArgumentParser { frames.add(i); } } - FrameExportSettings fes = new FrameExportSettings(enumFromStr(formats.get("frame"), FrameExportMode.class), zoom); + FrameExportSettings fes = new FrameExportSettings(enumFromStr(formats.get("frame"), FrameExportMode.class), zoom, transparentBackground); frameExporter.exportFrames(handler, outDir + (multipleExportTypes ? File.separator + FrameExportSettings.EXPORT_FOLDER_NAME : ""), swf, 0, frames, fes, evl); } diff --git a/src/com/jpexs/decompiler/flash/console/help.txt b/src/com/jpexs/decompiler/flash/console/help.txt index a16e83851..8b57c00fd 100644 --- a/src/com/jpexs/decompiler/flash/console/help.txt +++ b/src/com/jpexs/decompiler/flash/console/help.txt @@ -432,3 +432,8 @@ Pre-options: Applies to: -export Enables resampling exported WAV sound files to 44kHz. +-ignorebackground + Applies to: -export + Ignores SWF background color when exporting frames + and thus make background transparent. + diff --git a/src/com/jpexs/decompiler/flash/gui/ExportDialog.java b/src/com/jpexs/decompiler/flash/gui/ExportDialog.java index 8ad0def3e..944ad7fb7 100644 --- a/src/com/jpexs/decompiler/flash/gui/ExportDialog.java +++ b/src/com/jpexs/decompiler/flash/gui/ExportDialog.java @@ -149,6 +149,8 @@ public class ExportDialog extends AppDialog { private JCheckBox embedCheckBox; private JCheckBox resampleWavCheckBox; + + private JCheckBox transparentFrameBackgroundCheckBox; public E getValue(Class option) { for (int i = 0; i < optionClasses.length; i++) { @@ -178,6 +180,10 @@ public class ExportDialog extends AppDialog { public boolean isResampleWavEnabled() { return resampleWavCheckBox.isSelected(); } + + public boolean isTransparentFrameBackgroundEnabled() { + return transparentFrameBackgroundCheckBox.isSelected(); + } public double getZoom() { return Double.parseDouble(zoomTextField.getText()) / 100; @@ -204,6 +210,9 @@ public class ExportDialog extends AppDialog { if (resampleWavCheckBox.isVisible()) { Configuration.lastExportResampleWav.set(resampleWavCheckBox.isSelected()); } + if (transparentFrameBackgroundCheckBox.isVisible()) { + Configuration.lastExportTransparentBackground.set(transparentFrameBackgroundCheckBox.isSelected()); + } } private boolean optionCanHandle(int optionIndex, Object e) { @@ -392,7 +401,25 @@ public class ExportDialog extends AppDialog { if (resampleWavCheckBox.getWidth() + 10 > w) { w = resampleWavCheckBox.getWidth() + 10; } - } + } + + transparentFrameBackgroundCheckBox = new JCheckBox(translate("transparentFrameBackground")); + transparentFrameBackgroundCheckBox.setVisible(false); + if (visibleOptionClasses.contains(FrameExportMode.class)) { + top += 2; + transparentFrameBackgroundCheckBox.setVisible(true); + comboPanel.add(transparentFrameBackgroundCheckBox); + if (Configuration.lastExportTransparentBackground.get()) { + transparentFrameBackgroundCheckBox.setSelected(true); + } + + transparentFrameBackgroundCheckBox.setBounds(10, top, transparentFrameBackgroundCheckBox.getPreferredSize().width, transparentFrameBackgroundCheckBox.getPreferredSize().height); + top += transparentFrameBackgroundCheckBox.getHeight(); + + if (transparentFrameBackgroundCheckBox.getWidth() + 10 > w) { + w = transparentFrameBackgroundCheckBox.getWidth() + 10; + } + } int zoomWidth = 50; if (zoomable) { diff --git a/src/com/jpexs/decompiler/flash/gui/MainPanel.java b/src/com/jpexs/decompiler/flash/gui/MainPanel.java index 023b1270b..0d5d49090 100644 --- a/src/com/jpexs/decompiler/flash/gui/MainPanel.java +++ b/src/com/jpexs/decompiler/flash/gui/MainPanel.java @@ -2220,7 +2220,7 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se FrameExporter frameExporter = new FrameExporter(); if (export.isOptionEnabled(FrameExportMode.class)) { - FrameExportSettings fes = new FrameExportSettings(export.getValue(FrameExportMode.class), export.getZoom()); + FrameExportSettings fes = new FrameExportSettings(export.getValue(FrameExportMode.class), export.getZoom(), export.isTransparentFrameBackgroundEnabled()); if (frames.containsKey(0)) { String subFolder = FrameExportSettings.EXPORT_FOLDER_NAME; ret.addAll(frameExporter.exportFrames(handler, selFile2 + File.separator + subFolder, swf, 0, frames.get(0), fes, evl)); @@ -2333,7 +2333,7 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se FrameExporter frameExporter = new FrameExporter(); if (export.isOptionEnabled(FrameExportMode.class)) { - FrameExportSettings fes = new FrameExportSettings(export.getValue(FrameExportMode.class), export.getZoom()); + FrameExportSettings fes = new FrameExportSettings(export.getValue(FrameExportMode.class), export.getZoom(), export.isTransparentFrameBackgroundEnabled()); frameExporter.exportFrames(handler, Path.combine(selFile, FrameExportSettings.EXPORT_FOLDER_NAME), swf, 0, null, fes, evl); } @@ -2444,7 +2444,7 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se if (export.isOptionEnabled(FrameExportMode.class)) { for (FrameExportMode exportMode : FrameExportMode.values()) { - FrameExportSettings fes = new FrameExportSettings(exportMode, export.getZoom()); + FrameExportSettings fes = new FrameExportSettings(exportMode, export.getZoom(), export.isTransparentFrameBackgroundEnabled()); frameExporter.exportFrames(handler, Path.combine(selFile, FrameExportSettings.EXPORT_FOLDER_NAME, exportMode.name()), swf, 0, null, fes, evl); } } diff --git a/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog.properties b/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog.properties index 80e2b68f6..973412fc4 100644 --- a/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog.properties +++ b/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog.properties @@ -767,3 +767,5 @@ config.description.lastExportResampleWav = Last setting of resampling wav to 44k config.name.previewResampleSound = Resample in sound previews config.description.previewResampleSound = Resample to 44kHz in sound previews +config.name.lastExportTransparentBackground = Last setting of ignoring background color in frame export +config.description.lastExportTransparentBackground = Last setting of ignoring background color for frame export to make background transparency \ No newline at end of file diff --git a/src/com/jpexs/decompiler/flash/gui/locales/ExportDialog.properties b/src/com/jpexs/decompiler/flash/gui/locales/ExportDialog.properties index 744f6bf72..67ce10695 100644 --- a/src/com/jpexs/decompiler/flash/gui/locales/ExportDialog.properties +++ b/src/com/jpexs/decompiler/flash/gui/locales/ExportDialog.properties @@ -112,4 +112,5 @@ fonts4.cff = CFF embed = Export embedded assets via [Embed] #after 20.1.0 -resampleWav = Resample Wav to 44kHz \ No newline at end of file +resampleWav = Resample Wav to 44kHz +transparentFrameBackground = Ignore background color (make transparent) \ No newline at end of file diff --git a/src/com/jpexs/decompiler/flash/gui/locales/ExportDialog_cs.properties b/src/com/jpexs/decompiler/flash/gui/locales/ExportDialog_cs.properties index 702046ac7..f6e92d00a 100644 --- a/src/com/jpexs/decompiler/flash/gui/locales/ExportDialog_cs.properties +++ b/src/com/jpexs/decompiler/flash/gui/locales/ExportDialog_cs.properties @@ -107,4 +107,5 @@ images.png_gif_jpeg_alpha = PNG/GIF/JPEG+alpha embed = Exportovat vlo\u017een\u00e9 zdroje skrze [Embed] #after 20.1.0 -resampleWav = P\u0159evzorkovat Wav na 44kHz \ No newline at end of file +resampleWav = P\u0159evzorkovat Wav na 44kHz +transparentFrameBackground = Ignorovat barvu pozad\u00ed (pou\u017e\u00edt pr\u016fhlednou) \ No newline at end of file