From c71bb08505528663c87f6d0638c4392edef3f0ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jindra=20Pet=C5=99=C3=ADk?= Date: Thu, 16 Feb 2023 09:50:36 +0100 Subject: [PATCH] Fixed #1974 DefineBits image reading problem --- CHANGELOG.md | 2 + .../decompiler/flash/tags/DefineBitsTag.java | 68 +++---------------- 2 files changed, 10 insertions(+), 60 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 60aa3789b..cd012614d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ All notable changes to this project will be documented in this file. - Unresponsive status bar and its icon - [#1973] FLA export - improper calculation of shape instance count - FLA export - XML formatting with blank lines on Java9+ +- [#1974] DefineBits image reading problem ## [18.3.5] - 2023-02-12 ### Added @@ -2961,6 +2962,7 @@ All notable changes to this project will be documented in this file. [#1970]: https://www.free-decompiler.com/flash/issues/1970 [#1972]: https://www.free-decompiler.com/flash/issues/1972 [#1973]: https://www.free-decompiler.com/flash/issues/1973 +[#1974]: https://www.free-decompiler.com/flash/issues/1974 [#1959]: https://www.free-decompiler.com/flash/issues/1959 [#1960]: https://www.free-decompiler.com/flash/issues/1960 [#1964]: https://www.free-decompiler.com/flash/issues/1964 diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineBitsTag.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineBitsTag.java index e7cd329aa..9a56f6599 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineBitsTag.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineBitsTag.java @@ -26,6 +26,7 @@ import com.jpexs.decompiler.flash.types.BasicType; import com.jpexs.decompiler.flash.types.annotations.SWFType; import com.jpexs.decompiler.flash.types.annotations.SWFVersion; import com.jpexs.helpers.ByteArrayRange; +import com.jpexs.helpers.JpegFixer; import com.jpexs.helpers.SerializableImage; import java.awt.Dimension; import java.awt.Graphics; @@ -116,73 +117,20 @@ public class DefineBitsTag extends ImageTag implements TagChangedListener { public ImageFormat getOriginalImageFormat() { return ImageFormat.JPEG; } - - private static List parseJpegChunks(byte[] data) { - //A little inspired by shum way :-) - List ret = new ArrayList<>(); - int pos = 0; - int n = data.length; - // Finding first marker, and skipping the data before this marker. - // (FF 00 - code is escaped FF; FF FF ... (FF xx) - fill bytes before marker). - while (pos < n && ((data[pos] & 0xFF) != 0xFF - || (pos + 1 < n && ((data[pos + 1] & 0xFF) == 0x00 || (data[pos + 1] & 0xFF) == 0xFF)))) { - pos++; - } - - while (pos < n) { - int start = pos++; - int code = data[pos++] & 0xFF; - - // Some tags have length field -- using it - if ((code >= 0xC0 && code <= 0xC7) - || (code >= 0xC9 && code <= 0xCF) - || (code >= 0xDA && code <= 0xEF) - || code == 0xFE) { - int length = (data[pos] & 0xFF) << 8 + (data[pos + 1] & 0xFF); - pos += length; - } - - // Finding next marker. - while (pos < n && ((data[pos] & 0xFF) != 0xFF - || (pos + 1 < n && ((data[pos + 1] & 0xff) == 0x00 || (data[pos + 1] & 0xFF) == 0xFF)))) { - pos++; - } - - if (code == 0xD8 || code == 0xD9) { - // Removing SOI and EOI to avoid wrong EOI-SOI pairs in the middle. - continue; - } - ret.add(Arrays.copyOfRange(data, start, pos)); - } - return ret; - } - + @Override public InputStream getOriginalImageData() { if (swf.getJtt() != null) { try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) { - int errorLength = hasErrorHeader(jpegData) ? 4 : 0; - - List jpegChunks = parseJpegChunks(jpegData.getRangeData(errorLength, jpegData.getLength() - errorLength)); ByteArrayRange jttdata = swf.getJtt().jpegData; if (jttdata.getLength() != 0) { - int jttErrorLength = hasErrorHeader(jttdata) ? 4 : 0; - List chunksJtt = parseJpegChunks(jttdata.getRangeData(jttErrorLength, jttdata.getLength() - jttErrorLength)); - for (int c = 0; c < jpegChunks.size(); c++) { - int chunkType = (jpegChunks.get(c)[1] & 0xFF); - if (chunkType >= 0xC0 && chunkType <= 0xCF) { - jpegChunks.addAll(c, chunksJtt); - break; - } - } + baos.write(jttdata.getRangeData()); } - jpegChunks.add(0, new byte[]{(byte) 0xFF, (byte) 0xD8}); //SOI to beginning - jpegChunks.add(new byte[]{(byte) 0xFF, (byte) 0xD9}); //EOI to the end - - for (byte[] chunk : jpegChunks) { - baos.write(chunk); - } - return new ByteArrayInputStream(baos.toByteArray()); + baos.write(jpegData.getRangeData()); + JpegFixer fixer = new JpegFixer(); + ByteArrayOutputStream baos2 = new ByteArrayOutputStream(); + fixer.fixJpeg(new ByteArrayInputStream(baos.toByteArray()), baos2); + return new ByteArrayInputStream(baos2.toByteArray()); } catch (IOException ex) { // this should never happen, since IOException comes from OutputStream, but ByteArrayOutputStream should never throw it throw new Error(ex);