diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWFInputStream.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWFInputStream.java index f85969225..04e61554a 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWFInputStream.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWFInputStream.java @@ -890,7 +890,11 @@ public class SWFInputStream implements AutoCloseable { } public static byte[] uncompressByteArray(byte[] data) throws IOException { - InflaterInputStream dis = new InflaterInputStream(new ByteArrayInputStream(data)); + return uncompressByteArray(data, 0, data.length); + } + + public static byte[] uncompressByteArray(byte[] data, int offset, int length) throws IOException { + InflaterInputStream dis = new InflaterInputStream(new ByteArrayInputStream(data, offset, length)); ByteArrayOutputStream baos = new ByteArrayOutputStream(); byte[] buf = new byte[4096]; int c = 0; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineBitsLossless2Tag.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineBitsLossless2Tag.java index c57972a9d..fcc4a4fd1 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineBitsLossless2Tag.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineBitsLossless2Tag.java @@ -31,17 +31,14 @@ import com.jpexs.decompiler.flash.types.annotations.HideInRawEdit; import com.jpexs.decompiler.flash.types.annotations.Internal; import com.jpexs.decompiler.flash.types.annotations.SWFType; import com.jpexs.helpers.ByteArrayRange; -import com.jpexs.helpers.Helper; import com.jpexs.helpers.SerializableImage; import java.awt.Dimension; import java.awt.image.DataBufferInt; -import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.util.logging.Level; import java.util.logging.Logger; -import java.util.zip.InflaterInputStream; /** * @@ -206,7 +203,7 @@ public class DefineBitsLossless2Tag extends ImageTag implements AloneTag { private void uncompressData() { try { - byte[] uncompressedData = Helper.readStream(new InflaterInputStream(new ByteArrayInputStream(zlibBitmapData.getArray(), zlibBitmapData.getPos(), zlibBitmapData.getLength()))); + byte[] uncompressedData = SWFInputStream.uncompressByteArray(zlibBitmapData.getArray(), zlibBitmapData.getPos(), zlibBitmapData.getLength()); SWFInputStream sis = new SWFInputStream(swf, uncompressedData); if (bitmapFormat == FORMAT_8BIT_COLORMAPPED) { colorMapData = sis.readALPHACOLORMAPDATA(bitmapColorTableSize, bitmapWidth, bitmapHeight, "colorMapData"); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineBitsLosslessTag.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineBitsLosslessTag.java index 33d0a1255..aaae65b4b 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineBitsLosslessTag.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineBitsLosslessTag.java @@ -31,17 +31,14 @@ import com.jpexs.decompiler.flash.types.annotations.HideInRawEdit; import com.jpexs.decompiler.flash.types.annotations.Internal; import com.jpexs.decompiler.flash.types.annotations.SWFType; import com.jpexs.helpers.ByteArrayRange; -import com.jpexs.helpers.Helper; import com.jpexs.helpers.SerializableImage; import java.awt.Dimension; import java.awt.image.DataBufferInt; -import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.util.logging.Level; import java.util.logging.Logger; -import java.util.zip.InflaterInputStream; /** * @@ -201,7 +198,7 @@ public class DefineBitsLosslessTag extends ImageTag implements AloneTag { private void uncompressData() { try { - byte[] uncompressedData = Helper.readStream(new InflaterInputStream(new ByteArrayInputStream(zlibBitmapData.getArray(), zlibBitmapData.getPos(), zlibBitmapData.getLength()))); + byte[] uncompressedData = SWFInputStream.uncompressByteArray(zlibBitmapData.getArray(), zlibBitmapData.getPos(), zlibBitmapData.getLength()); SWFInputStream sis = new SWFInputStream(swf, uncompressedData); if (bitmapFormat == FORMAT_8BIT_COLORMAPPED) { colorMapData = sis.readCOLORMAPDATA(bitmapColorTableSize, bitmapWidth, bitmapHeight, "colorMapData"); diff --git a/src/com/jpexs/decompiler/flash/gui/dumpview/DumpTree.java b/src/com/jpexs/decompiler/flash/gui/dumpview/DumpTree.java index 0d05b6737..767dbad79 100644 --- a/src/com/jpexs/decompiler/flash/gui/dumpview/DumpTree.java +++ b/src/com/jpexs/decompiler/flash/gui/dumpview/DumpTree.java @@ -98,6 +98,10 @@ public class DumpTree extends JTree { saveToFileMenuItem.addActionListener(this::saveToFileButtonActionPerformed); contextPopupMenu.add(saveToFileMenuItem); + final JMenuItem saveUncompressedToFileMenuItem = new JMenuItem(mainPanel.translate("contextmenu.saveUncompressedToFile")); + saveUncompressedToFileMenuItem.addActionListener(this::saveUncompressedToFileButtonActionPerformed); + contextPopupMenu.add(saveUncompressedToFileMenuItem); + final JMenuItem closeSelectionMenuItem = new JMenuItem(mainPanel.translate("contextmenu.closeSwf")); closeSelectionMenuItem.addActionListener(this::closeSwfButtonActionPerformed); contextPopupMenu.add(closeSelectionMenuItem); @@ -129,9 +133,11 @@ public class DumpTree extends JTree { if (paths == null || paths.length == 0) { return; } + closeSelectionMenuItem.setVisible(false); expandRecursiveMenuItem.setVisible(false); saveToFileMenuItem.setVisible(false); + saveUncompressedToFileMenuItem.setVisible(false); parseActionsMenuItem.setVisible(false); parseAbcMenuItem.setVisible(false); parseInstructionsMenuItem.setVisible(false); @@ -145,6 +151,9 @@ public class DumpTree extends JTree { if (treeNode.getEndByte() - treeNode.startByte > 3) { saveToFileMenuItem.setVisible(true); + if (treeNode.name.equals("bitmapAlphaData") || treeNode.name.equals("zlibBitmapData")) { + saveUncompressedToFileMenuItem.setVisible(true); + } } // todo honfika: do not use string names, because it has conflicts e.g with DefineFont.code @@ -179,6 +188,14 @@ public class DumpTree extends JTree { } private void saveToFileButtonActionPerformed(ActionEvent evt) { + saveToFileButtonActionPerformed(false); + } + + private void saveUncompressedToFileButtonActionPerformed(ActionEvent evt) { + saveToFileButtonActionPerformed(true); + } + + private void saveToFileButtonActionPerformed(boolean decompress) { TreePath[] paths = getSelectionPaths(); DumpInfo dumpInfo = (DumpInfo) paths[0].getLastPathComponent(); JFileChooser fc = new JFileChooser(); @@ -189,8 +206,13 @@ public class DumpTree extends JTree { if (fc.showSaveDialog(f) == JFileChooser.APPROVE_OPTION) { File sf = Helper.fixDialogFile(fc.getSelectedFile()); try (OutputStream fos = new BufferedOutputStream(new FileOutputStream(sf))) { - byte[] data = DumpInfoSwfNode.getSwfNode(dumpInfo).getSwf().originalUncompressedData; - fos.write(data, (int) dumpInfo.startByte, (int) (dumpInfo.getEndByte() - dumpInfo.startByte + 1)); + if (decompress) { + byte[] data = DumpInfoSwfNode.getSwfNode(dumpInfo).getSwf().originalUncompressedData; + fos.write(SWFInputStream.uncompressByteArray(data, (int) dumpInfo.startByte, (int) (dumpInfo.getEndByte() - dumpInfo.startByte + 1))); + } else { + byte[] data = DumpInfoSwfNode.getSwfNode(dumpInfo).getSwf().originalUncompressedData; + fos.write(data, (int) dumpInfo.startByte, (int) (dumpInfo.getEndByte() - dumpInfo.startByte + 1)); + } } catch (IOException ex) { logger.log(Level.SEVERE, null, ex); } diff --git a/src/com/jpexs/decompiler/flash/gui/locales/MainFrame.properties b/src/com/jpexs/decompiler/flash/gui/locales/MainFrame.properties index 1d71f84a6..f2b262379 100644 --- a/src/com/jpexs/decompiler/flash/gui/locales/MainFrame.properties +++ b/src/com/jpexs/decompiler/flash/gui/locales/MainFrame.properties @@ -626,3 +626,6 @@ import.script.as12warning = Import script can import only AS1/2 scripts. error.constantPoolTooBig = Constant pool is too big. index=%index%, size=%size% error.image.alpha.invalid = Invalid alpha channel data. + +#after version 6.0.2 +contextmenu.saveUncompressedToFile = Save to Uncompressed File