mirror of
https://git.huckle.dev/Huckles-Minecraft-Archive/jpexs-decompiler.git
synced 2026-06-06 10:06:45 +00:00
Issue #895 Correct handling CMYK JPEG images (Monte Video library)
Correct JPEG to Image conversion when it has alpha
This commit is contained in:
@@ -1,108 +1,111 @@
|
||||
/*
|
||||
* Copyright (C) 2010-2015 JPEXS, All rights reserved.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3.0 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library.
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.exporters;
|
||||
|
||||
import com.jpexs.decompiler.flash.AbortRetryIgnoreHandler;
|
||||
import com.jpexs.decompiler.flash.EventListener;
|
||||
import com.jpexs.decompiler.flash.RetryTask;
|
||||
import com.jpexs.decompiler.flash.exporters.modes.ImageExportMode;
|
||||
import com.jpexs.decompiler.flash.exporters.settings.ImageExportSettings;
|
||||
import com.jpexs.decompiler.flash.helpers.BMPFile;
|
||||
import com.jpexs.decompiler.flash.helpers.ImageHelper;
|
||||
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.Helper;
|
||||
import com.jpexs.helpers.Path;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class ImageExporter {
|
||||
|
||||
public List<File> exportImages(AbortRetryIgnoreHandler handler, String outdir, List<Tag> tags, ImageExportSettings settings, EventListener evl) throws IOException {
|
||||
List<File> ret = new ArrayList<>();
|
||||
if (tags.isEmpty()) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
File foutdir = new File(outdir);
|
||||
Path.createDirectorySafe(foutdir);
|
||||
|
||||
int count = 0;
|
||||
for (Tag t : tags) {
|
||||
if (t instanceof ImageTag) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
if (count == 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
int currentIndex = 1;
|
||||
for (Tag t : tags) {
|
||||
if (t instanceof ImageTag) {
|
||||
if (evl != null) {
|
||||
evl.handleExportingEvent("image", currentIndex, count, t.getName());
|
||||
}
|
||||
|
||||
final ImageTag imageTag = (ImageTag) t;
|
||||
|
||||
ImageFormat fileFormat = imageTag.getImageFormat();
|
||||
if (settings.mode == ImageExportMode.PNG) {
|
||||
fileFormat = ImageFormat.PNG;
|
||||
}
|
||||
|
||||
if (settings.mode == ImageExportMode.JPEG) {
|
||||
fileFormat = ImageFormat.JPEG;
|
||||
}
|
||||
|
||||
if (settings.mode == ImageExportMode.BMP) {
|
||||
fileFormat = ImageFormat.BMP;
|
||||
}
|
||||
|
||||
{
|
||||
final File file = new File(outdir + File.separator + Helper.makeFileName(imageTag.getCharacterExportFileName() + "." + ImageHelper.getImageFormatString(fileFormat)));
|
||||
final ImageFormat ffileFormat = fileFormat;
|
||||
|
||||
new RetryTask(() -> {
|
||||
if (ffileFormat == ImageFormat.BMP) {
|
||||
BMPFile.saveBitmap(imageTag.getImage().getBufferedImage(), file);
|
||||
} else {
|
||||
ImageHelper.write(imageTag.getImage().getBufferedImage(), ffileFormat, file);
|
||||
}
|
||||
}, handler).run();
|
||||
ret.add(file);
|
||||
}
|
||||
|
||||
if (evl != null) {
|
||||
evl.handleExportedEvent("image", currentIndex, count, t.getName());
|
||||
}
|
||||
|
||||
currentIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Copyright (C) 2010-2015 JPEXS, All rights reserved.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3.0 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library.
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.exporters;
|
||||
|
||||
import com.jpexs.decompiler.flash.AbortRetryIgnoreHandler;
|
||||
import com.jpexs.decompiler.flash.EventListener;
|
||||
import com.jpexs.decompiler.flash.RetryTask;
|
||||
import com.jpexs.decompiler.flash.exporters.modes.ImageExportMode;
|
||||
import com.jpexs.decompiler.flash.exporters.settings.ImageExportSettings;
|
||||
import com.jpexs.decompiler.flash.helpers.BMPFile;
|
||||
import com.jpexs.decompiler.flash.helpers.ImageHelper;
|
||||
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.Helper;
|
||||
import com.jpexs.helpers.Path;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class ImageExporter {
|
||||
|
||||
public List<File> exportImages(AbortRetryIgnoreHandler handler, String outdir, List<Tag> tags, ImageExportSettings settings, EventListener evl) throws IOException {
|
||||
List<File> ret = new ArrayList<>();
|
||||
if (tags.isEmpty()) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
File foutdir = new File(outdir);
|
||||
Path.createDirectorySafe(foutdir);
|
||||
|
||||
int count = 0;
|
||||
for (Tag t : tags) {
|
||||
if (t instanceof ImageTag) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
if (count == 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
int currentIndex = 1;
|
||||
for (Tag t : tags) {
|
||||
if (t instanceof ImageTag) {
|
||||
if (evl != null) {
|
||||
evl.handleExportingEvent("image", currentIndex, count, t.getName());
|
||||
}
|
||||
|
||||
final ImageTag imageTag = (ImageTag) t;
|
||||
|
||||
ImageFormat fileFormat = imageTag.getImageFormat();
|
||||
ImageFormat originalFormat = fileFormat;
|
||||
if (settings.mode == ImageExportMode.PNG) {
|
||||
fileFormat = ImageFormat.PNG;
|
||||
}
|
||||
|
||||
if (settings.mode == ImageExportMode.JPEG) {
|
||||
fileFormat = ImageFormat.JPEG;
|
||||
}
|
||||
|
||||
if (settings.mode == ImageExportMode.BMP) {
|
||||
fileFormat = ImageFormat.BMP;
|
||||
}
|
||||
|
||||
{
|
||||
final File file = new File(outdir + File.separator + Helper.makeFileName(imageTag.getCharacterExportFileName() + "." + ImageHelper.getImageFormatString(fileFormat)));
|
||||
final ImageFormat ffileFormat = fileFormat;
|
||||
|
||||
new RetryTask(() -> {
|
||||
if (ffileFormat == originalFormat) {
|
||||
|
||||
} else if (ffileFormat == ImageFormat.BMP) {
|
||||
BMPFile.saveBitmap(imageTag.getImage().getBufferedImage(), file);
|
||||
} else {
|
||||
ImageHelper.write(imageTag.getImage().getBufferedImage(), ffileFormat, file);
|
||||
}
|
||||
}, handler).run();
|
||||
ret.add(file);
|
||||
}
|
||||
|
||||
if (evl != null) {
|
||||
evl.handleExportedEvent("image", currentIndex, count, t.getName());
|
||||
}
|
||||
|
||||
currentIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ package com.jpexs.decompiler.flash.helpers;
|
||||
|
||||
import com.jpexs.decompiler.flash.tags.base.ImageTag;
|
||||
import com.jpexs.decompiler.flash.tags.enums.ImageFormat;
|
||||
import com.jpexs.helpers.Helper;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
@@ -25,10 +26,15 @@ import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.Iterator;
|
||||
import java.util.Locale;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.imageio.ImageReader;
|
||||
import javax.imageio.stream.ImageInputStream;
|
||||
import org.monte.media.jpeg.CMYKJPEGImageReader;
|
||||
import org.monte.media.jpeg.CMYKJPEGImageReaderSpi;
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -41,9 +47,18 @@ public class ImageHelper {
|
||||
}
|
||||
|
||||
public static BufferedImage read(InputStream input) throws IOException {
|
||||
BufferedImage in = ImageIO.read(input);
|
||||
if (in == null) {
|
||||
return null;
|
||||
BufferedImage in;
|
||||
byte data[] = Helper.readStream(input);
|
||||
try (ImageInputStream iis = ImageIO.createImageInputStream(new ByteArrayInputStream(data))) {
|
||||
CMYKJPEGImageReader r = new CMYKJPEGImageReader(new CMYKJPEGImageReaderSpi());
|
||||
r.setInput(iis);
|
||||
in = r.read(0);
|
||||
} catch (IOException ex) {
|
||||
try {
|
||||
return ImageIO.read(ImageIO.createImageInputStream(new ByteArrayInputStream(data)));
|
||||
} catch (IOException ex1) {
|
||||
in = null;
|
||||
}
|
||||
}
|
||||
|
||||
int type = in.getType();
|
||||
|
||||
@@ -58,7 +58,7 @@ public class DefineBitsJPEG2Tag extends ImageTag implements AloneTag {
|
||||
public DefineBitsJPEG2Tag(SWF swf) {
|
||||
super(swf, ID, NAME, null);
|
||||
characterID = swf.getNextCharacterId();
|
||||
imageData = ByteArrayRange.EMPTY;
|
||||
imageData = new ByteArrayRange(createEmptyImage());
|
||||
forceWriteAsLong = true;
|
||||
}
|
||||
|
||||
@@ -68,6 +68,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();
|
||||
}
|
||||
|
||||
public DefineBitsJPEG2Tag(SWFInputStream sis, ByteArrayRange data) throws IOException {
|
||||
super(sis.getSwf(), ID, NAME, data);
|
||||
readData(sis, data, 0, false, false, false);
|
||||
|
||||
@@ -153,7 +153,7 @@ public class DefineBitsJPEG3Tag extends ImageTag implements AloneTag {
|
||||
@Override
|
||||
public ImageFormat getImageFormat() {
|
||||
ImageFormat fmt = ImageTag.getImageFormat(imageData);
|
||||
if (fmt == ImageFormat.JPEG) {
|
||||
if (fmt == ImageFormat.JPEG && bitmapAlphaData.getLength() > 0) {
|
||||
fmt = ImageFormat.PNG; //transparency
|
||||
}
|
||||
return fmt;
|
||||
@@ -161,8 +161,17 @@ public class DefineBitsJPEG3Tag extends ImageTag implements AloneTag {
|
||||
|
||||
@Override
|
||||
public InputStream getImageData() {
|
||||
int errorLength = hasErrorHeader(imageData) ? 4 : 0;
|
||||
return new ByteArrayInputStream(imageData.getArray(), imageData.getPos() + errorLength, imageData.getLength() - errorLength);
|
||||
|
||||
if (bitmapAlphaData.getLength() == 0) { //No alpha, then its JPEG
|
||||
int errorLength = hasErrorHeader(imageData) ? 4 : 0;
|
||||
return new ByteArrayInputStream(imageData.getArray(), imageData.getPos() + errorLength, imageData.getLength() - errorLength);
|
||||
}
|
||||
|
||||
//Make PNG
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
ImageHelper.write(getImage().getBufferedImage(), ImageFormat.PNG, baos);
|
||||
return new ByteArrayInputStream(baos.toByteArray());
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -171,7 +180,10 @@ public class DefineBitsJPEG3Tag extends ImageTag implements AloneTag {
|
||||
return cachedImage;
|
||||
}
|
||||
try {
|
||||
BufferedImage image = ImageHelper.read(getImageData());
|
||||
int errorLength = hasErrorHeader(imageData) ? 4 : 0;
|
||||
ByteArrayInputStream bis = new ByteArrayInputStream(imageData.getArray(), imageData.getPos() + errorLength, imageData.getLength() - errorLength);
|
||||
|
||||
BufferedImage image = ImageHelper.read(bis);
|
||||
if (image == null) {
|
||||
Logger.getLogger(DefineBitsJPEG3Tag.class.getName()).log(Level.SEVERE, "Failed to load image");
|
||||
return null;
|
||||
|
||||
@@ -158,7 +158,7 @@ public class DefineBitsJPEG4Tag extends ImageTag implements AloneTag {
|
||||
@Override
|
||||
public ImageFormat getImageFormat() {
|
||||
ImageFormat fmt = ImageTag.getImageFormat(imageData);
|
||||
if (fmt == ImageFormat.JPEG) {
|
||||
if (fmt == ImageFormat.JPEG && bitmapAlphaData.getLength() > 0) {
|
||||
fmt = ImageFormat.PNG; //transparency
|
||||
}
|
||||
return fmt;
|
||||
@@ -166,7 +166,15 @@ public class DefineBitsJPEG4Tag extends ImageTag implements AloneTag {
|
||||
|
||||
@Override
|
||||
public InputStream getImageData() {
|
||||
return new ByteArrayInputStream(imageData.getArray(), imageData.getPos(), imageData.getLength());
|
||||
|
||||
if (bitmapAlphaData.getLength() == 0) { //No alpha, then its JPEG
|
||||
return new ByteArrayInputStream(imageData.getArray(), imageData.getPos(), imageData.getLength());
|
||||
}
|
||||
//Make PNG
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
ImageHelper.write(getImage().getBufferedImage(), ImageFormat.PNG, baos);
|
||||
return new ByteArrayInputStream(baos.toByteArray());
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -175,7 +183,8 @@ public class DefineBitsJPEG4Tag extends ImageTag implements AloneTag {
|
||||
return cachedImage;
|
||||
}
|
||||
try {
|
||||
BufferedImage image = ImageHelper.read(getImageData());
|
||||
|
||||
BufferedImage image = ImageHelper.read(new ByteArrayInputStream(imageData.getArray(), imageData.getPos(), imageData.getLength()));
|
||||
if (image == null) {
|
||||
Logger.getLogger(DefineBitsJPEG4Tag.class.getName()).log(Level.SEVERE, "Failed to load image");
|
||||
return null;
|
||||
|
||||
Reference in New Issue
Block a user