diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/helpers/ImageHelper.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/helpers/ImageHelper.java index 7be668608..32cdae721 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/helpers/ImageHelper.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/helpers/ImageHelper.java @@ -1,207 +1,207 @@ -/* - * Copyright (C) 2010-2016 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.helpers; - -import com.jpexs.decompiler.flash.tags.enums.ImageFormat; -import com.jpexs.decompiler.flash.types.RGBA; -import com.jpexs.helpers.Helper; -import java.awt.Dimension; -import java.awt.image.BufferedImage; -import java.awt.image.DataBufferInt; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -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; - -/** - * - * @author JPEXS - */ -public class ImageHelper { - - static { - ImageIO.setUseCache(false); - } - - public static BufferedImage read(byte[] data) throws IOException { - return read(new ByteArrayInputStream(data)); - } - - public static BufferedImage read(InputStream input) throws IOException { - 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 | ArrayIndexOutOfBoundsException ex) { - try { - in = ImageIO.read(ImageIO.createImageInputStream(new ByteArrayInputStream(data))); - } catch (IOException ex1) { - return null; - } - } - - int type = in.getType(); - if (type != BufferedImage.TYPE_INT_ARGB_PRE && type != BufferedImage.TYPE_INT_RGB) { - // convert to ARGB - int width = in.getWidth(); - int height = in.getHeight(); - int[] imgData = in.getRGB(0, 0, width, height, null, 0, width); - BufferedImage newImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB_PRE); - newImage.getRaster().setDataElements(0, 0, width, height, imgData); - return newImage; - } - - return in; - } - - public static void write(BufferedImage image, ImageFormat format, File output) throws IOException { - String formatName = getImageFormatString(format).toUpperCase(Locale.ENGLISH); - if (format == ImageFormat.JPEG) { - image = fixImageIOJpegBug(image); - } - - ImageIO.write(image, formatName, output); - } - - public static void write(BufferedImage image, ImageFormat format, OutputStream output) throws IOException { - String formatName = getImageFormatString(format).toUpperCase(Locale.ENGLISH); - if (format == ImageFormat.JPEG) { - image = fixImageIOJpegBug(image); - } - - ImageIO.write(image, formatName, output); - } - - public static void write(BufferedImage image, ImageFormat format, ByteArrayOutputStream output) { - String formatName = getImageFormatString(format).toUpperCase(Locale.ENGLISH); - if (format == ImageFormat.JPEG) { - image = fixImageIOJpegBug(image); - } else { - if (image.getType() == BufferedImage.TYPE_INT_ARGB_PRE) { - BufferedImage image2 = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_INT_ARGB); - int[] pixels = ((DataBufferInt) image.getRaster().getDataBuffer()).getData(); - divideAlpha(pixels); - - int[] pixels2 = ((DataBufferInt) image2.getRaster().getDataBuffer()).getData(); - for (int i = 0; i < pixels.length; i++) { - pixels2[i] = pixels[i]; - } - - image = image2; - } - } - - try { - ImageIO.write(image, formatName, output); - } catch (IOException ex) { - Logger.getLogger(ImageHelper.class.getName()).log(Level.SEVERE, null, ex); - } - } - - private static int max255(float val) { - if (val > 255) { - return 255; - } - return (int) val; - } - - private static void divideAlpha(int[] pixels) { - for (int i = 0; i < pixels.length; i++) { - pixels[i] = divideAlpha(pixels[i]); - } - } - - private static int divideAlpha(int value) { - int a = (value >> 24) & 0xFF; - int r = (value >> 16) & 0xFF; - int g = (value >> 8) & 0xFF; - int b = value & 0xFF; - float multiplier = a == 0 ? 0 : 255.0f / a; - r = max255(r * multiplier); - g = max255(g * multiplier); - b = max255(b * multiplier); - return RGBA.toInt(r, g, b, a); - } - - private static BufferedImage fixImageIOJpegBug(BufferedImage image) { - int type = image.getType(); - if (type != BufferedImage.TYPE_INT_RGB) { - // convert to RGB without alpha channel - int width = image.getWidth(); - int height = image.getHeight(); - BufferedImage newImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); - int[] pixels2 = ((DataBufferInt) image.getRaster().getDataBuffer()).getData(); - int[] pixels = image.getRGB(0, 0, width, height, null, 0, width); - for (int i = 0; i < pixels.length; i++) { - pixels2[i] = pixels[i] & 0xffffff; - } - - return newImage; - } - - return image; - } - - public static String getImageFormatString(ImageFormat format) { - switch (format) { - case UNKNOWN: - return "unk"; - case JPEG: - return "jpg"; - case GIF: - return "gif"; - case PNG: - return "png"; - case BMP: - return "bmp"; - } - - throw new Error("Unsuported image format: " + format); - } - - public static Dimension getDimesion(InputStream input) throws IOException { - try (ImageInputStream in = ImageIO.createImageInputStream(input)) { - final Iterator readers = ImageIO.getImageReaders(in); - if (readers.hasNext()) { - ImageReader reader = readers.next(); - try { - reader.setInput(in); - return new Dimension(reader.getWidth(0), reader.getHeight(0)); - } finally { - reader.dispose(); - } - } - } catch (IOException ex) { - } - - BufferedImage image = read(input); - return new Dimension(image.getWidth(), image.getHeight()); - } -} +/* + * Copyright (C) 2010-2016 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.helpers; + +import com.jpexs.decompiler.flash.tags.enums.ImageFormat; +import com.jpexs.decompiler.flash.types.RGBA; +import com.jpexs.helpers.Helper; +import java.awt.Dimension; +import java.awt.image.BufferedImage; +import java.awt.image.DataBufferInt; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +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; + +/** + * + * @author JPEXS + */ +public class ImageHelper { + + static { + ImageIO.setUseCache(false); + } + + public static BufferedImage read(byte[] data) throws IOException { + return read(new ByteArrayInputStream(data)); + } + + public static BufferedImage read(InputStream input) throws IOException { + 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 | ArrayIndexOutOfBoundsException ex) { + try { + in = ImageIO.read(ImageIO.createImageInputStream(new ByteArrayInputStream(data))); + } catch (IOException ex1) { + return null; + } + } + + int type = in.getType(); + if (type != BufferedImage.TYPE_INT_ARGB_PRE && type != BufferedImage.TYPE_INT_RGB) { + // convert to ARGB + int width = in.getWidth(); + int height = in.getHeight(); + int[] imgData = in.getRGB(0, 0, width, height, null, 0, width); + BufferedImage newImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB_PRE); + newImage.getRaster().setDataElements(0, 0, width, height, imgData); + return newImage; + } + + return in; + } + + public static void write(BufferedImage image, ImageFormat format, File output) throws IOException { + String formatName = getImageFormatString(format).toUpperCase(Locale.ENGLISH); + if (format == ImageFormat.JPEG) { + image = fixImageIOJpegBug(image); + } + + ImageIO.write(image, formatName, output); + } + + public static void write(BufferedImage image, ImageFormat format, OutputStream output) throws IOException { + String formatName = getImageFormatString(format).toUpperCase(Locale.ENGLISH); + if (format == ImageFormat.JPEG) { + image = fixImageIOJpegBug(image); + } + + ImageIO.write(image, formatName, output); + } + + public static void write(BufferedImage image, ImageFormat format, ByteArrayOutputStream output) { + String formatName = getImageFormatString(format).toUpperCase(Locale.ENGLISH); + if (format == ImageFormat.JPEG) { + image = fixImageIOJpegBug(image); + } else { + if (image.getType() == BufferedImage.TYPE_INT_ARGB_PRE) { + BufferedImage image2 = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_INT_ARGB); + int[] pixels = ((DataBufferInt) image.getRaster().getDataBuffer()).getData(); + divideAlpha(pixels); + + int[] pixels2 = ((DataBufferInt) image2.getRaster().getDataBuffer()).getData(); + for (int i = 0; i < pixels.length; i++) { + pixels2[i] = pixels[i]; + } + + image = image2; + } + } + + try { + ImageIO.write(image, formatName, output); + } catch (IOException ex) { + Logger.getLogger(ImageHelper.class.getName()).log(Level.SEVERE, null, ex); + } + } + + private static int max255(float val) { + if (val > 255) { + return 255; + } + return (int) val; + } + + private static void divideAlpha(int[] pixels) { + for (int i = 0; i < pixels.length; i++) { + pixels[i] = divideAlpha(pixels[i]); + } + } + + private static int divideAlpha(int value) { + int a = (value >> 24) & 0xFF; + int r = (value >> 16) & 0xFF; + int g = (value >> 8) & 0xFF; + int b = value & 0xFF; + float multiplier = a == 0 ? 0 : 255.0f / a; + r = max255(r * multiplier); + g = max255(g * multiplier); + b = max255(b * multiplier); + return RGBA.toInt(r, g, b, a); + } + + private static BufferedImage fixImageIOJpegBug(BufferedImage image) { + int type = image.getType(); + if (type != BufferedImage.TYPE_INT_RGB) { + // convert to RGB without alpha channel + int width = image.getWidth(); + int height = image.getHeight(); + BufferedImage newImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); + int[] pixels2 = ((DataBufferInt) image.getRaster().getDataBuffer()).getData(); + int[] pixels = image.getRGB(0, 0, width, height, null, 0, width); + for (int i = 0; i < pixels.length; i++) { + pixels2[i] = pixels[i] & 0xffffff; + } + + return newImage; + } + + return image; + } + + public static String getImageFormatString(ImageFormat format) { + switch (format) { + case UNKNOWN: + return "unk"; + case JPEG: + return "jpg"; + case GIF: + return "gif"; + case PNG: + return "png"; + case BMP: + return "bmp"; + } + + throw new Error("Unsuported image format: " + format); + } + + public static Dimension getDimesion(InputStream input) throws IOException { + try (ImageInputStream in = ImageIO.createImageInputStream(input)) { + final Iterator readers = ImageIO.getImageReaders(in); + if (readers.hasNext()) { + ImageReader reader = readers.next(); + try { + reader.setInput(in); + return new Dimension(reader.getWidth(0), reader.getHeight(0)); + } finally { + reader.dispose(); + } + } + } catch (IOException ex) { + } + + BufferedImage image = read(input); + return new Dimension(image.getWidth(), image.getHeight()); + } +}