Fixed #1974 DefineBits image reading problem

This commit is contained in:
Jindra Petřík
2023-02-16 09:50:36 +01:00
committed by Jindra Petřík
parent bd6a0ea829
commit c71bb08505
2 changed files with 10 additions and 60 deletions

View File

@@ -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<byte[]> parseJpegChunks(byte[] data) {
//A little inspired by shum way :-)
List<byte[]> 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<byte[]> jpegChunks = parseJpegChunks(jpegData.getRangeData(errorLength, jpegData.getLength() - errorLength));
ByteArrayRange jttdata = swf.getJtt().jpegData;
if (jttdata.getLength() != 0) {
int jttErrorLength = hasErrorHeader(jttdata) ? 4 : 0;
List<byte[]> 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);