allow to specify tag type on image and shape import

This commit is contained in:
honfika@gmail.com
2015-07-20 13:20:31 +02:00
parent ebd6b5760c
commit 37dc877b16
9 changed files with 248 additions and 91 deletions

View File

@@ -21,10 +21,13 @@ import com.jpexs.decompiler.flash.helpers.ImageHelper;
import com.jpexs.decompiler.flash.tags.DefineBitsJPEG2Tag;
import com.jpexs.decompiler.flash.tags.DefineBitsJPEG3Tag;
import com.jpexs.decompiler.flash.tags.DefineBitsJPEG4Tag;
import com.jpexs.decompiler.flash.tags.DefineBitsLossless2Tag;
import com.jpexs.decompiler.flash.tags.DefineBitsLosslessTag;
import com.jpexs.decompiler.flash.tags.DefineBitsTag;
import com.jpexs.decompiler.flash.tags.Tag;
import com.jpexs.decompiler.flash.tags.base.ImageTag;
import com.jpexs.decompiler.flash.tags.enums.ImageFormat;
import com.jpexs.helpers.ByteArrayRange;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
@@ -36,7 +39,10 @@ import java.io.IOException;
public class ImageImporter extends TagImporter {
public Tag importImage(ImageTag it, byte[] newData) throws IOException {
return importImage(it, newData, 0);
}
public Tag importImage(ImageTag it, byte[] newData, int tagType) throws IOException {
if (newData[0] == 'B' && newData[1] == 'M') {
BufferedImage b = ImageHelper.read(newData);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
@@ -44,16 +50,56 @@ public class ImageImporter extends TagImporter {
newData = baos.toByteArray();
}
if (it instanceof DefineBitsTag) {
SWF swf = it.getSwf();
DefineBitsJPEG2Tag jpeg2Tag = new DefineBitsJPEG2Tag(swf, it.getOriginalRange(), it.getCharacterId(), newData);
jpeg2Tag.setModified(true);
swf.tags.set(swf.tags.indexOf(it), jpeg2Tag);
swf.updateCharacters();
return jpeg2Tag;
} else {
it.setImage(newData);
if (tagType == 0) {
if (it instanceof DefineBitsTag) {
tagType = DefineBitsTag.ID;
} else {
tagType = it.getId();
}
}
if (it.getId() == tagType) {
it.setImage(newData);
} else {
SWF swf = it.getSwf();
ImageTag imageTag;
ByteArrayRange range = it.getOriginalRange();
int characterId = it.getCharacterId();
switch (tagType) {
case DefineBitsJPEG2Tag.ID: {
imageTag = new DefineBitsJPEG2Tag(swf, range, characterId, newData);
break;
}
case DefineBitsJPEG3Tag.ID: {
imageTag = new DefineBitsJPEG3Tag(swf, range, characterId, newData);
break;
}
case DefineBitsJPEG4Tag.ID: {
imageTag = new DefineBitsJPEG4Tag(swf, range, characterId, newData);
break;
}
case DefineBitsLosslessTag.ID: {
DefineBitsLosslessTag losslessTag = new DefineBitsLosslessTag(swf, range, characterId);
losslessTag.setImage(newData);
imageTag = losslessTag;
break;
}
case DefineBitsLossless2Tag.ID: {
DefineBitsLossless2Tag lossless2Tag = new DefineBitsLossless2Tag(swf, range, characterId);
lossless2Tag.setImage(newData);
imageTag = lossless2Tag;
break;
}
default:
throw new Error("Unsupported image type tag.");
}
imageTag.setModified(true);
swf.tags.set(swf.tags.indexOf(it), imageTag);
swf.updateCharacters();
return imageTag;
}
return null;
}

View File

@@ -19,7 +19,10 @@ package com.jpexs.decompiler.flash.importers;
import com.jpexs.decompiler.flash.SWF;
import com.jpexs.decompiler.flash.helpers.ImageHelper;
import com.jpexs.decompiler.flash.tags.DefineBitsJPEG2Tag;
import com.jpexs.decompiler.flash.tags.DefineBitsJPEG3Tag;
import com.jpexs.decompiler.flash.tags.DefineBitsJPEG4Tag;
import com.jpexs.decompiler.flash.tags.DefineBitsLossless2Tag;
import com.jpexs.decompiler.flash.tags.DefineBitsLosslessTag;
import com.jpexs.decompiler.flash.tags.Tag;
import com.jpexs.decompiler.flash.tags.base.ImageTag;
import com.jpexs.decompiler.flash.tags.base.ShapeTag;
@@ -36,6 +39,10 @@ import java.io.IOException;
public class ShapeImporter {
public Tag importImage(ShapeTag st, byte[] newData) throws IOException {
return importImage(st, newData, 0);
}
public Tag importImage(ShapeTag st, byte[] newData, int tagType) throws IOException {
SWF swf = st.getSwf();
if (newData[0] == 'B' && newData[1] == 'M') {
@@ -45,14 +52,42 @@ public class ShapeImporter {
newData = baos.toByteArray();
}
if (tagType == 0) {
if (ImageTag.getImageFormat(newData) == ImageFormat.JPEG) {
tagType = DefineBitsJPEG2Tag.ID;
} else {
tagType = DefineBitsLossless2Tag.ID;
}
}
ImageTag imageTag;
if (ImageTag.getImageFormat(newData) == ImageFormat.JPEG) {
DefineBitsJPEG2Tag jpeg2Tag = new DefineBitsJPEG2Tag(swf, null, swf.getNextCharacterId(), newData);
imageTag = jpeg2Tag;
} else {
DefineBitsLossless2Tag lossless2Tag = new DefineBitsLossless2Tag(swf);
lossless2Tag.setImage(newData);
imageTag = lossless2Tag;
switch (tagType) {
case DefineBitsJPEG2Tag.ID: {
imageTag = new DefineBitsJPEG2Tag(swf, null, swf.getNextCharacterId(), newData);
break;
}
case DefineBitsJPEG3Tag.ID: {
imageTag = new DefineBitsJPEG3Tag(swf, null, swf.getNextCharacterId(), newData);
break;
}
case DefineBitsJPEG4Tag.ID: {
imageTag = new DefineBitsJPEG4Tag(swf, null, swf.getNextCharacterId(), newData);
break;
}
case DefineBitsLosslessTag.ID: {
DefineBitsLosslessTag losslessTag = new DefineBitsLosslessTag(swf);
losslessTag.setImage(newData);
imageTag = losslessTag;
break;
}
case DefineBitsLossless2Tag.ID: {
DefineBitsLossless2Tag lossless2Tag = new DefineBitsLossless2Tag(swf);
lossless2Tag.setImage(newData);
imageTag = lossless2Tag;
break;
}
default:
throw new Error("Unsupported image type tag.");
}
int idx = swf.tags.indexOf(st);

View File

@@ -67,13 +67,13 @@ public class DefineBitsJPEG2Tag extends ImageTag implements AloneTag {
this.imageData = new ByteArrayRange(imageData);
}
private byte[] createEmptyImage() {
BufferedImage img = new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB);
ByteArrayOutputStream bitmapDataOS = new ByteArrayOutputStream();
ImageHelper.write(img, ImageFormat.JPEG, bitmapDataOS);
return bitmapDataOS.toByteArray();
}
/**
* Constructor
*
* @param sis
* @param data
* @throws IOException
*/
public DefineBitsJPEG2Tag(SWFInputStream sis, ByteArrayRange data) throws IOException {
super(sis.getSwf(), ID, NAME, data);
readData(sis, data, 0, false, false, false);
@@ -97,6 +97,20 @@ public class DefineBitsJPEG2Tag extends ImageTag implements AloneTag {
sos.write(imageData);
}
private byte[] createEmptyImage() {
BufferedImage img = new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB);
ByteArrayOutputStream bitmapDataOS = new ByteArrayOutputStream();
ImageHelper.write(img, ImageFormat.JPEG, bitmapDataOS);
return bitmapDataOS.toByteArray();
}
@Override
public void setImage(byte[] data) {
imageData = new ByteArrayRange(data);
clearCache();
setModified(true);
}
@Override
public ImageFormat getImageFormat() {
return ImageTag.getImageFormat(imageData);
@@ -120,22 +134,15 @@ public class DefineBitsJPEG2Tag extends ImageTag implements AloneTag {
return null;
}
SerializableImage ret = new SerializableImage(image);
SerializableImage img = new SerializableImage(image);
if (Configuration.cacheImages.get()) {
cachedImage = ret;
cachedImage = img;
}
return ret;
return img;
} catch (IOException ex) {
Logger.getLogger(DefineBitsJPEG2Tag.class.getName()).log(Level.SEVERE, "Failed to get image", ex);
}
return null;
}
@Override
public void setImage(byte[] data) {
imageData = new ByteArrayRange(data);
clearCache();
setModified(true);
}
}

View File

@@ -66,6 +66,14 @@ public class DefineBitsJPEG3Tag extends ImageTag implements AloneTag {
forceWriteAsLong = true;
}
public DefineBitsJPEG3Tag(SWF swf, ByteArrayRange data, int characterID, byte[] imageData) throws IOException {
super(swf, ID, NAME, data);
this.characterID = characterID;
this.imageData = new ByteArrayRange(imageData);
bitmapAlphaData = ByteArrayRange.EMPTY;
forceWriteAsLong = true;
}
/**
* Constructor
*
@@ -153,7 +161,7 @@ public class DefineBitsJPEG3Tag extends ImageTag implements AloneTag {
@Override
public InputStream getOriginalImageData() {
if (bitmapAlphaData.getLength() == 0) { //No alpha, then its JPEG
if (bitmapAlphaData.getLength() == 0) { // No alpha
int errorLength = hasErrorHeader(imageData) ? 4 : 0;
return new ByteArrayInputStream(imageData.getArray(), imageData.getPos() + errorLength, imageData.getLength() - errorLength);
}

View File

@@ -69,6 +69,14 @@ public class DefineBitsJPEG4Tag extends ImageTag implements AloneTag {
forceWriteAsLong = true;
}
public DefineBitsJPEG4Tag(SWF swf, ByteArrayRange data, int characterID, byte[] imageData) throws IOException {
super(swf, ID, NAME, data);
this.characterID = characterID;
this.imageData = new ByteArrayRange(imageData);
bitmapAlphaData = ByteArrayRange.EMPTY;
forceWriteAsLong = true;
}
/**
* Constructor
*
@@ -158,7 +166,7 @@ public class DefineBitsJPEG4Tag extends ImageTag implements AloneTag {
@Override
public InputStream getOriginalImageData() {
if (bitmapAlphaData.getLength() == 0) { //No alpha, then its JPEG
if (bitmapAlphaData.getLength() == 0) { // No alpha
return new ByteArrayInputStream(imageData.getArray(), imageData.getPos(), imageData.getLength());
}

View File

@@ -87,8 +87,12 @@ public class DefineBitsLossless2Tag extends ImageTag implements AloneTag {
* @param swf
*/
public DefineBitsLossless2Tag(SWF swf) {
super(swf, ID, NAME, null);
characterID = swf.getNextCharacterId();
this(swf, null, swf.getNextCharacterId());
}
public DefineBitsLossless2Tag(SWF swf, ByteArrayRange data, int characterID) {
super(swf, ID, NAME, data);
this.characterID = characterID;
bitmapFormat = DefineBitsLossless2Tag.FORMAT_32BIT_ARGB;
bitmapWidth = 1;
bitmapHeight = 1;
@@ -202,11 +206,11 @@ public class DefineBitsLossless2Tag extends ImageTag implements AloneTag {
private void uncompressData() {
try {
SWFInputStream sis = new SWFInputStream(swf, Helper.readStream(new InflaterInputStream(new ByteArrayInputStream(zlibBitmapData.getArray(), zlibBitmapData.getPos(), zlibBitmapData.getLength()))));
byte[] uncompressedData = Helper.readStream(new InflaterInputStream(new ByteArrayInputStream(zlibBitmapData.getArray(), zlibBitmapData.getPos(), zlibBitmapData.getLength())));
SWFInputStream sis = new SWFInputStream(swf, uncompressedData);
if (bitmapFormat == FORMAT_8BIT_COLORMAPPED) {
colorMapData = sis.readALPHACOLORMAPDATA(bitmapColorTableSize, bitmapWidth, bitmapHeight, "colorMapData");
}
if (bitmapFormat == FORMAT_32BIT_ARGB) {
} else if (bitmapFormat == FORMAT_32BIT_ARGB) {
bitmapData = sis.readALPHABITMAPDATA(bitmapFormat, bitmapWidth, bitmapHeight, "bitmapData");
}
} catch (IOException ex) {

View File

@@ -89,8 +89,12 @@ public class DefineBitsLosslessTag extends ImageTag implements AloneTag {
* @param swf
*/
public DefineBitsLosslessTag(SWF swf) {
super(swf, ID, NAME, null);
characterID = swf.getNextCharacterId();
this(swf, null, swf.getNextCharacterId());
}
public DefineBitsLosslessTag(SWF swf, ByteArrayRange data, int characterID) {
super(swf, ID, NAME, data);
this.characterID = characterID;
bitmapFormat = DefineBitsLosslessTag.FORMAT_24BIT_RGB;
bitmapWidth = 1;
bitmapHeight = 1;
@@ -181,6 +185,39 @@ public class DefineBitsLosslessTag extends ImageTag implements AloneTag {
setModified(true);
}
public COLORMAPDATA getColorMapData() {
if (!decompressed) {
uncompressData();
}
return colorMapData;
}
public BITMAPDATA getBitmapData() {
if (!decompressed) {
uncompressData();
}
return bitmapData;
}
private void uncompressData() {
try {
byte[] uncompressedData = Helper.readStream(new InflaterInputStream(new ByteArrayInputStream(zlibBitmapData.getArray(), zlibBitmapData.getPos(), zlibBitmapData.getLength())));
SWFInputStream sis = new SWFInputStream(swf, uncompressedData);
if (bitmapFormat == FORMAT_8BIT_COLORMAPPED) {
colorMapData = sis.readCOLORMAPDATA(bitmapColorTableSize, bitmapWidth, bitmapHeight, "colorMapData");
} else if ((bitmapFormat == FORMAT_15BIT_RGB) || (bitmapFormat == FORMAT_24BIT_RGB)) {
bitmapData = sis.readBITMAPDATA(bitmapFormat, bitmapWidth, bitmapHeight, "bitmapData");
}
} catch (IOException ex) {
}
decompressed = true;
}
@Override
public ImageFormat getImageFormat() {
return ImageFormat.PNG;
}
@Override
public InputStream getOriginalImageData() {
return null;
@@ -238,37 +275,4 @@ public class DefineBitsLosslessTag extends ImageTag implements AloneTag {
return bi;
}
public COLORMAPDATA getColorMapData() {
if (!decompressed) {
uncompressData();
}
return colorMapData;
}
public BITMAPDATA getBitmapData() {
if (!decompressed) {
uncompressData();
}
return bitmapData;
}
private void uncompressData() {
try {
byte[] uncompressedData = Helper.readStream(new InflaterInputStream(new ByteArrayInputStream(zlibBitmapData.getArray(), zlibBitmapData.getPos(), zlibBitmapData.getLength())));
SWFInputStream sis = new SWFInputStream(swf, uncompressedData);
if (bitmapFormat == FORMAT_8BIT_COLORMAPPED) {
colorMapData = sis.readCOLORMAPDATA(bitmapColorTableSize, bitmapWidth, bitmapHeight, "colorMapData");
} else if ((bitmapFormat == FORMAT_15BIT_RGB) || (bitmapFormat == FORMAT_24BIT_RGB)) {
bitmapData = sis.readBITMAPDATA(bitmapFormat, bitmapWidth, bitmapHeight, "bitmapData");
}
} catch (IOException ex) {
}
decompressed = true;
}
@Override
public ImageFormat getImageFormat() {
return ImageFormat.PNG;
}
}

View File

@@ -60,6 +60,13 @@ public class DefineBitsTag extends ImageTag implements TagChangedListener {
forceWriteAsLong = true;
}
/**
* Constructor
*
* @param sis
* @param data
* @throws IOException
*/
public DefineBitsTag(SWFInputStream sis, ByteArrayRange data) throws IOException {
super(sis.getSwf(), ID, NAME, data);
readData(sis, data, 0, false, false, false);
@@ -83,15 +90,20 @@ public class DefineBitsTag extends ImageTag implements TagChangedListener {
sos.write(jpegData);
}
@Override
public boolean importSupported() {
// importing a new image will replace the current DefineBitsTag with a new DefineBitsJPEG2Tag
return true;
}
@Override
public void setImage(byte[] data) {
throw new UnsupportedOperationException("Set image is not supported for DefineBits");
}
@Override
public boolean importSupported() {
// importing a new image will replace the current DefineBitsTag with a new DefineBitsJPEG2Tag
return true;
public ImageFormat getImageFormat() {
return ImageFormat.JPEG;
}
@Override
@@ -132,12 +144,12 @@ public class DefineBitsTag extends ImageTag implements TagChangedListener {
return null;
}
SerializableImage ret = new SerializableImage(image);
SerializableImage img = new SerializableImage(image);
if (Configuration.cacheImages.get()) {
cachedImage = ret;
cachedImage = img;
}
return ret;
return img;
} catch (IOException ex) {
Logger.getLogger(DefineBitsTag.class.getName()).log(Level.SEVERE, "Failed to get image", ex);
}
@@ -146,11 +158,6 @@ public class DefineBitsTag extends ImageTag implements TagChangedListener {
return null;
}
@Override
public ImageFormat getImageFormat() {
return ImageFormat.JPEG;
}
@Override
public void handleEvent(Tag tag) {
// cache should be cleared when Jtt tag changes