Skip to content
Permalink
Browse files

DefineBits (with JPEGTables) tags export fixed

  • Loading branch information
jindrapetrik committed May 28, 2018
1 parent 02660f3 commit 83d42253c494d1bfb7c17fff6794261b0bf6de5d
Showing with 63 additions and 5 deletions.
  1. +1 −0 CHANGELOG.md
  2. +62 −5 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineBitsTag.java
@@ -24,6 +24,7 @@ All notable changes to this project will be documented in this file.
- AS1/2 callmethod action arguments
- Fixed §§push after continue - should be before (usually on obfuscated code)
- AS1/2 Delete operator with nonIdentifier parameters (e.g. spaces or obfuscated)
- DefineBits (with JPEGTables) tag export

## [11.1.0] - 2018-05-24
### Added
@@ -12,7 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. */
* License along with this library.
*/
package com.jpexs.decompiler.flash.tags;

import com.jpexs.decompiler.flash.SWF;
@@ -25,13 +26,17 @@
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.Helper;
import com.jpexs.helpers.SerializableImage;
import java.awt.Dimension;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

@@ -112,19 +117,71 @@ 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;
baos.write(jttdata.getArray(), jttdata.getPos() + jttErrorLength, jttdata.getLength() - jttErrorLength);
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;
}
}
}
jpegChunks.add(0, new byte[]{(byte) 0xFF, (byte) 0xD8}); //SOI to beginning
jpegChunks.add(new byte[]{(byte) 0xFF, (byte) 0xD9}); //EOI to the end

int errorLength = hasErrorHeader(jpegData) ? 4 : 0;
baos.write(jpegData.getArray(), jpegData.getPos() + errorLength, jpegData.getLength() - errorLength);

for (byte[] chunk : jpegChunks) {
baos.write(chunk);
}
return new ByteArrayInputStream(baos.toByteArray());
} catch (IOException ex) {
// this should never happen, since IOException comes from OutputStream, but ByteArrayOutputStream should never throw it

0 comments on commit 83d4225

Please sign in to comment.
You can’t perform that action at this time.