diff --git a/pom.xml b/pom.xml index 677762fe8..814261ecc 100644 --- a/pom.xml +++ b/pom.xml @@ -17,400 +17,404 @@ --> - 4.0.0 + 4.0.0 - - - + + + - - org.apache.commons - commons-parent - 40 - + + org.apache.commons + commons-parent + 40 + - org.apache.commons - commons-imaging - Apache Commons Imaging + org.apache.commons + commons-imaging + Apache Commons Imaging - 1.0-SNAPSHOT + 1.0-SNAPSHOT - - Apache Commons Imaging (previously Sanselan) is a pure-Java image library. - http://commons.apache.org/proper/commons-imaging/ + + Apache Commons Imaging (previously Sanselan) is a pure-Java image library. + http://commons.apache.org/proper/commons-imaging/ - - 1.7 - 1.7 - imaging - 1.0 - RC5 - IMAGING - 12313421 - org.apache.commons.imaging.*;version=${project.version};-noimport:=true - UTF-8 - UTF-8 - + + 1.7 + 1.7 + imaging + 1.0 + RC5 + IMAGING + 12313421 + org.apache.commons.imaging.*;version=${project.version};-noimport:=true + UTF-8 + UTF-8 + - - scm:svn:http://svn.apache.org/repos/asf/commons/proper/imaging/trunk - scm:svn:https://svn.apache.org/repos/asf/commons/proper/imaging/trunk - http://svn.apache.org/viewvc/commons/proper/imaging/trunk - + + scm:svn:http://svn.apache.org/repos/asf/commons/proper/imaging/trunk + scm:svn:https://svn.apache.org/repos/asf/commons/proper/imaging/trunk + http://svn.apache.org/viewvc/commons/proper/imaging/trunk + - - - stagingSite - Apache Staging Website - ${commons.deployment.protocol}://people.apache.org/www/commons.apache.org/${commons.componentid}/ - - + + + stagingSite + Apache Staging Website + ${commons.deployment.protocol}://people.apache.org/www/commons.apache.org/${commons.componentid}/ + + - - Jira - http://issues.apache.org/jira/browse/IMAGING - - 2007 + + Jira + http://issues.apache.org/jira/browse/IMAGING + + 2007 - - 2.0.7 - + + 2.0.7 + - - - - org.apache.maven.plugins - maven-assembly-plugin - - - src/assembly/bin.xml - src/assembly/src.xml - - gnu - - - - maven-jar-plugin - - - - org.apache.commons.imaging - - - - - - org.apache.maven.plugins - maven-surefire-plugin - - - org.codehaus.mojo - animal-sniffer-maven-plugin - 1.15 - - - org.codehaus.mojo.signature - java17 - 1.0 - - - - - check-java-api - test - - check - - - - - - - - - org.apache.maven.plugins - maven-scm-publish-plugin - - - javadocs** - - - - - - org.eclipse.m2e - lifecycle-mapping - 1.0.0 - - - - - + + + + org.apache.maven.plugins + maven-assembly-plugin + + + src/assembly/bin.xml + src/assembly/src.xml + + gnu + + + + maven-jar-plugin + + + + org.apache.commons.imaging + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + + org.codehaus.mojo + animal-sniffer-maven-plugin + 1.15 + + + org.codehaus.mojo.signature + java17 + 1.0 + + + + + check-java-api + test + + check + + + + + + + + + org.apache.maven.plugins + maven-scm-publish-plugin + + + javadocs** + + + + + + org.eclipse.m2e + lifecycle-mapping + 1.0.0 + + + + + + org.apache.maven.plugins + maven-antrun-plugin + [1.6,) + + run + + + + + false + + + + + + org.apache.felix + maven-bundle-plugin + [2.3.5,) + + manifest + + + + + false + + + + + + + + org.apache.maven.plugins - maven-antrun-plugin - [1.6,) - - run - - - - - false - - - - - - org.apache.felix - maven-bundle-plugin - [2.3.5,) - - manifest - - - - - false - - - - - - - - - org.apache.maven.plugins - maven-javadoc-plugin - - org.apache.commons.imaging.formats.psd.*:org.apache.commons.imaging.formats.png.* - - - - - + maven-javadoc-plugin + + org.apache.commons.imaging.formats.psd.*:org.apache.commons.imaging.formats.png.* + + + + + - - - junit - junit - 4.12 - test - - - commons-io - commons-io - 2.5 - test - - + + + junit + junit + 4.12 + test + + + commons-io + commons-io + 2.5 + + + com.github.jai-imageio + jai-imageio-jpeg2000 + 1.3.0 + + - - - - org.codehaus.mojo - findbugs-maven-plugin - 3.0.3 - - Normal - Default - - - - org.codehaus.mojo - javancss-maven-plugin - 2.1 - - - org.apache.maven.plugins - maven-changes-plugin - ${commons.changes.version} - - %URL%/%ISSUE% - - - - - changes-report - jira-report - - - - - - org.apache.maven.plugins - maven-checkstyle-plugin - 2.11 - false - - ${basedir}/src/conf/checkstyle.xml - ${basedir}/src/conf/checkstyle-suppressions.xml - false - basedir=${basedir} - - - - - - checkstyle - - - - - - org.apache.maven.plugins - maven-pmd-plugin - 3.3 - - ${maven.compiler.target} - - ${basedir}/src/conf/pmd-ruleset.xml - - - - - org.codehaus.mojo - taglist-maven-plugin - 2.4 - - - - - Needs Work - - - TODO - exact - - - FIXME - exact - - - XXX - exact - - - - - Noteable Markers - - - NOTE - exact - - - NOPMD - exact - - - NOSONAR - exact - - - - - - - - - org.apache.rat - apache-rat-plugin - - - src/test/data/images/xpm/1/symbolic.xpm - src/test/data/images/xpm/1/Oregon Scientific DS6639 - DSC_0307 - small.xpm - src/test/data/images/pbm/2/5x5-grayscale.pam - src/test/data/images/pbm/2/5x5-bw.pam - src/test/data/images/pbm/1/Oregon Scientific DS6639 - DSC_0307 - small.pgm - src/test/data/images/xbm/1/Oregon Scientific DS6639 - DSC_0307 - small.xbm - src/main/resources/org/apache/commons/imaging/formats/xpm/rgb.txt - - - - - + + + + org.codehaus.mojo + findbugs-maven-plugin + 3.0.3 + + Normal + Default + + + + org.codehaus.mojo + javancss-maven-plugin + 2.1 + + + org.apache.maven.plugins + maven-changes-plugin + ${commons.changes.version} + + %URL%/%ISSUE% + + + + + changes-report + jira-report + + + + + + org.apache.maven.plugins + maven-checkstyle-plugin + 2.11 + false + + ${basedir}/src/conf/checkstyle.xml + ${basedir}/src/conf/checkstyle-suppressions.xml + false + basedir=${basedir} + + + + + + checkstyle + + + + + + org.apache.maven.plugins + maven-pmd-plugin + 3.3 + + ${maven.compiler.target} + + ${basedir}/src/conf/pmd-ruleset.xml + + + + + org.codehaus.mojo + taglist-maven-plugin + 2.4 + + + + + Needs Work + + + TODO + exact + + + FIXME + exact + + + XXX + exact + + + + + Noteable Markers + + + NOTE + exact + + + NOPMD + exact + + + NOSONAR + exact + + + + + + + + + org.apache.rat + apache-rat-plugin + + + src/test/data/images/xpm/1/symbolic.xpm + src/test/data/images/xpm/1/Oregon Scientific DS6639 - DSC_0307 - small.xpm + src/test/data/images/pbm/2/5x5-grayscale.pam + src/test/data/images/pbm/2/5x5-bw.pam + src/test/data/images/pbm/1/Oregon Scientific DS6639 - DSC_0307 - small.pgm + src/test/data/images/xbm/1/Oregon Scientific DS6639 - DSC_0307 - small.xbm + src/main/resources/org/apache/commons/imaging/formats/xpm/rgb.txt + + + + + - - - jdk8-javadoc - - [1.8,) - - - -Xdoclint:none - - - + + + jdk8-javadoc + + [1.8,) + + + -Xdoclint:none + + + - - - + + + - - - Charles M. Chen - cmchen - - - Philipp Koch - pkoch - - - Jeremias Maerki - jeremias - - - Craig Russell - clr - - - Yoav Shapira - yoavs - - - Carsten Ziegeler - cziegeler - - - Damjan Jovanovic - damjan - - - Matt Benson - mbenson - - + + + Charles M. Chen + cmchen + + + Philipp Koch + pkoch + + + Jeremias Maerki + jeremias + + + Craig Russell + clr + + + Yoav Shapira + yoavs + + + Carsten Ziegeler + cziegeler + + + Damjan Jovanovic + damjan + + + Matt Benson + mbenson + + - - - Adrian Moerchen - - - Alex Vigdor - - - Craig Kelly - - - Gary Lucas - - - Gavin Shiels - - - Peter Royal - - - Piyush Kapoor - - - Tars Joris - - - VVD - - + + + Adrian Moerchen + + + Alex Vigdor + + + Craig Kelly + + + Gary Lucas + + + Gavin Shiels + + + Peter Royal + + + Piyush Kapoor + + + Tars Joris + + + VVD + + diff --git a/src/main/java/org/apache/commons/imaging/formats/icns/IcnsDecoder.java b/src/main/java/org/apache/commons/imaging/formats/icns/IcnsDecoder.java old mode 100644 new mode 100755 index 664e194f8..0846a2890 --- a/src/main/java/org/apache/commons/imaging/formats/icns/IcnsDecoder.java +++ b/src/main/java/org/apache/commons/imaging/formats/icns/IcnsDecoder.java @@ -17,71 +17,24 @@ package org.apache.commons.imaging.formats.icns; import java.awt.image.BufferedImage; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; + +import javax.imageio.ImageIO; import org.apache.commons.imaging.ImageReadException; import org.apache.commons.imaging.common.ImageBuilder; import org.apache.commons.imaging.formats.icns.IcnsImageParser.IcnsElement; final class IcnsDecoder { - private static final int[] PALETTE_4BPP = { 0xffffffff, 0xfffcf305, - 0xffff6402, 0xffdd0806, 0xfff20884, 0xff4600a5, 0xff0000d4, - 0xff02abea, 0xff1fb714, 0xff006411, 0xff562c05, 0xff90713a, - 0xffc0c0c0, 0xff808080, 0xff404040, 0xff000000 }; + private static final int[] PALETTE_4BPP = { 0xffffffff, 0xfffcf305, 0xffff6402, 0xffdd0806, 0xfff20884, 0xff4600a5, 0xff0000d4, 0xff02abea, 0xff1fb714, 0xff006411, 0xff562c05, 0xff90713a, 0xffc0c0c0, 0xff808080, 0xff404040, 0xff000000 }; - private static final int[] PALETTE_8BPP = { 0xFFFFFFFF, 0xFFFFFFCC, - 0xFFFFFF99, 0xFFFFFF66, 0xFFFFFF33, 0xFFFFFF00, 0xFFFFCCFF, - 0xFFFFCCCC, 0xFFFFCC99, 0xFFFFCC66, 0xFFFFCC33, 0xFFFFCC00, - 0xFFFF99FF, 0xFFFF99CC, 0xFFFF9999, 0xFFFF9966, 0xFFFF9933, - 0xFFFF9900, 0xFFFF66FF, 0xFFFF66CC, 0xFFFF6699, 0xFFFF6666, - 0xFFFF6633, 0xFFFF6600, 0xFFFF33FF, 0xFFFF33CC, 0xFFFF3399, - 0xFFFF3366, 0xFFFF3333, 0xFFFF3300, 0xFFFF00FF, 0xFFFF00CC, - 0xFFFF0099, 0xFFFF0066, 0xFFFF0033, 0xFFFF0000, 0xFFCCFFFF, - 0xFFCCFFCC, 0xFFCCFF99, 0xFFCCFF66, 0xFFCCFF33, 0xFFCCFF00, - 0xFFCCCCFF, 0xFFCCCCCC, 0xFFCCCC99, 0xFFCCCC66, 0xFFCCCC33, - 0xFFCCCC00, 0xFFCC99FF, 0xFFCC99CC, 0xFFCC9999, 0xFFCC9966, - 0xFFCC9933, 0xFFCC9900, 0xFFCC66FF, 0xFFCC66CC, 0xFFCC6699, - 0xFFCC6666, 0xFFCC6633, 0xFFCC6600, 0xFFCC33FF, 0xFFCC33CC, - 0xFFCC3399, 0xFFCC3366, 0xFFCC3333, 0xFFCC3300, 0xFFCC00FF, - 0xFFCC00CC, 0xFFCC0099, 0xFFCC0066, 0xFFCC0033, 0xFFCC0000, - 0xFF99FFFF, 0xFF99FFCC, 0xFF99FF99, 0xFF99FF66, 0xFF99FF33, - 0xFF99FF00, 0xFF99CCFF, 0xFF99CCCC, 0xFF99CC99, 0xFF99CC66, - 0xFF99CC33, 0xFF99CC00, 0xFF9999FF, 0xFF9999CC, 0xFF999999, - 0xFF999966, 0xFF999933, 0xFF999900, 0xFF9966FF, 0xFF9966CC, - 0xFF996699, 0xFF996666, 0xFF996633, 0xFF996600, 0xFF9933FF, - 0xFF9933CC, 0xFF993399, 0xFF993366, 0xFF993333, 0xFF993300, - 0xFF9900FF, 0xFF9900CC, 0xFF990099, 0xFF990066, 0xFF990033, - 0xFF990000, 0xFF66FFFF, 0xFF66FFCC, 0xFF66FF99, 0xFF66FF66, - 0xFF66FF33, 0xFF66FF00, 0xFF66CCFF, 0xFF66CCCC, 0xFF66CC99, - 0xFF66CC66, 0xFF66CC33, 0xFF66CC00, 0xFF6699FF, 0xFF6699CC, - 0xFF669999, 0xFF669966, 0xFF669933, 0xFF669900, 0xFF6666FF, - 0xFF6666CC, 0xFF666699, 0xFF666666, 0xFF666633, 0xFF666600, - 0xFF6633FF, 0xFF6633CC, 0xFF663399, 0xFF663366, 0xFF663333, - 0xFF663300, 0xFF6600FF, 0xFF6600CC, 0xFF660099, 0xFF660066, - 0xFF660033, 0xFF660000, 0xFF33FFFF, 0xFF33FFCC, 0xFF33FF99, - 0xFF33FF66, 0xFF33FF33, 0xFF33FF00, 0xFF33CCFF, 0xFF33CCCC, - 0xFF33CC99, 0xFF33CC66, 0xFF33CC33, 0xFF33CC00, 0xFF3399FF, - 0xFF3399CC, 0xFF339999, 0xFF339966, 0xFF339933, 0xFF339900, - 0xFF3366FF, 0xFF3366CC, 0xFF336699, 0xFF336666, 0xFF336633, - 0xFF336600, 0xFF3333FF, 0xFF3333CC, 0xFF333399, 0xFF333366, - 0xFF333333, 0xFF333300, 0xFF3300FF, 0xFF3300CC, 0xFF330099, - 0xFF330066, 0xFF330033, 0xFF330000, 0xFF00FFFF, 0xFF00FFCC, - 0xFF00FF99, 0xFF00FF66, 0xFF00FF33, 0xFF00FF00, 0xFF00CCFF, - 0xFF00CCCC, 0xFF00CC99, 0xFF00CC66, 0xFF00CC33, 0xFF00CC00, - 0xFF0099FF, 0xFF0099CC, 0xFF009999, 0xFF009966, 0xFF009933, - 0xFF009900, 0xFF0066FF, 0xFF0066CC, 0xFF006699, 0xFF006666, - 0xFF006633, 0xFF006600, 0xFF0033FF, 0xFF0033CC, 0xFF003399, - 0xFF003366, 0xFF003333, 0xFF003300, 0xFF0000FF, 0xFF0000CC, - 0xFF000099, 0xFF000066, 0xFF000033, 0xFFEE0000, 0xFFDD0000, - 0xFFBB0000, 0xFFAA0000, 0xFF880000, 0xFF770000, 0xFF550000, - 0xFF440000, 0xFF220000, 0xFF110000, 0xFF00EE00, 0xFF00DD00, - 0xFF00BB00, 0xFF00AA00, 0xFF008800, 0xFF007700, 0xFF005500, - 0xFF004400, 0xFF002200, 0xFF001100, 0xFF0000EE, 0xFF0000DD, - 0xFF0000BB, 0xFF0000AA, 0xFF000088, 0xFF000077, 0xFF000055, - 0xFF000044, 0xFF000022, 0xFF000011, 0xFFEEEEEE, 0xFFDDDDDD, - 0xFFBBBBBB, 0xFFAAAAAA, 0xFF888888, 0xFF777777, 0xFF555555, - 0xFF444444, 0xFF222222, 0xFF111111, 0xFF000000 }; + private static final int[] PALETTE_8BPP = { 0xFFFFFFFF, 0xFFFFFFCC, 0xFFFFFF99, 0xFFFFFF66, 0xFFFFFF33, 0xFFFFFF00, 0xFFFFCCFF, 0xFFFFCCCC, 0xFFFFCC99, 0xFFFFCC66, 0xFFFFCC33, 0xFFFFCC00, 0xFFFF99FF, 0xFFFF99CC, 0xFFFF9999, 0xFFFF9966, 0xFFFF9933, 0xFFFF9900, 0xFFFF66FF, 0xFFFF66CC, 0xFFFF6699, 0xFFFF6666, 0xFFFF6633, 0xFFFF6600, 0xFFFF33FF, 0xFFFF33CC, 0xFFFF3399, 0xFFFF3366, 0xFFFF3333, 0xFFFF3300, 0xFFFF00FF, 0xFFFF00CC, 0xFFFF0099, 0xFFFF0066, 0xFFFF0033, 0xFFFF0000, 0xFFCCFFFF, 0xFFCCFFCC, 0xFFCCFF99, 0xFFCCFF66, 0xFFCCFF33, 0xFFCCFF00, 0xFFCCCCFF, 0xFFCCCCCC, 0xFFCCCC99, 0xFFCCCC66, 0xFFCCCC33, 0xFFCCCC00, 0xFFCC99FF, 0xFFCC99CC, 0xFFCC9999, 0xFFCC9966, 0xFFCC9933, 0xFFCC9900, 0xFFCC66FF, 0xFFCC66CC, 0xFFCC6699, 0xFFCC6666, 0xFFCC6633, 0xFFCC6600, 0xFFCC33FF, 0xFFCC33CC, 0xFFCC3399, 0xFFCC3366, 0xFFCC3333, 0xFFCC3300, 0xFFCC00FF, 0xFFCC00CC, 0xFFCC0099, 0xFFCC0066, 0xFFCC0033, 0xFFCC0000, 0xFF99FFFF, 0xFF99FFCC, 0xFF99FF99, 0xFF99FF66, 0xFF99FF33, 0xFF99FF00, 0xFF99CCFF, 0xFF99CCCC, 0xFF99CC99, 0xFF99CC66, 0xFF99CC33, 0xFF99CC00, 0xFF9999FF, 0xFF9999CC, 0xFF999999, 0xFF999966, 0xFF999933, 0xFF999900, 0xFF9966FF, 0xFF9966CC, 0xFF996699, 0xFF996666, 0xFF996633, 0xFF996600, 0xFF9933FF, 0xFF9933CC, 0xFF993399, 0xFF993366, 0xFF993333, 0xFF993300, 0xFF9900FF, 0xFF9900CC, 0xFF990099, 0xFF990066, 0xFF990033, 0xFF990000, 0xFF66FFFF, 0xFF66FFCC, 0xFF66FF99, 0xFF66FF66, 0xFF66FF33, 0xFF66FF00, 0xFF66CCFF, 0xFF66CCCC, 0xFF66CC99, 0xFF66CC66, 0xFF66CC33, 0xFF66CC00, 0xFF6699FF, 0xFF6699CC, 0xFF669999, 0xFF669966, 0xFF669933, 0xFF669900, 0xFF6666FF, 0xFF6666CC, 0xFF666699, 0xFF666666, 0xFF666633, 0xFF666600, 0xFF6633FF, 0xFF6633CC, 0xFF663399, 0xFF663366, 0xFF663333, 0xFF663300, 0xFF6600FF, 0xFF6600CC, 0xFF660099, 0xFF660066, 0xFF660033, 0xFF660000, 0xFF33FFFF, 0xFF33FFCC, 0xFF33FF99, 0xFF33FF66, 0xFF33FF33, 0xFF33FF00, 0xFF33CCFF, 0xFF33CCCC, 0xFF33CC99, 0xFF33CC66, 0xFF33CC33, 0xFF33CC00, 0xFF3399FF, 0xFF3399CC, 0xFF339999, 0xFF339966, 0xFF339933, 0xFF339900, 0xFF3366FF, 0xFF3366CC, 0xFF336699, 0xFF336666, 0xFF336633, 0xFF336600, 0xFF3333FF, 0xFF3333CC, 0xFF333399, 0xFF333366, 0xFF333333, 0xFF333300, 0xFF3300FF, 0xFF3300CC, 0xFF330099, 0xFF330066, 0xFF330033, 0xFF330000, 0xFF00FFFF, 0xFF00FFCC, 0xFF00FF99, 0xFF00FF66, 0xFF00FF33, 0xFF00FF00, 0xFF00CCFF, 0xFF00CCCC, 0xFF00CC99, 0xFF00CC66, 0xFF00CC33, 0xFF00CC00, 0xFF0099FF, 0xFF0099CC, 0xFF009999, 0xFF009966, 0xFF009933, 0xFF009900, 0xFF0066FF, 0xFF0066CC, 0xFF006699, 0xFF006666, 0xFF006633, 0xFF006600, 0xFF0033FF, 0xFF0033CC, 0xFF003399, 0xFF003366, 0xFF003333, 0xFF003300, 0xFF0000FF, 0xFF0000CC, 0xFF000099, 0xFF000066, 0xFF000033, 0xFFEE0000, 0xFFDD0000, 0xFFBB0000, 0xFFAA0000, 0xFF880000, 0xFF770000, 0xFF550000, 0xFF440000, 0xFF220000, 0xFF110000, 0xFF00EE00, 0xFF00DD00, 0xFF00BB00, 0xFF00AA00, 0xFF008800, 0xFF007700, 0xFF005500, 0xFF004400, 0xFF002200, 0xFF001100, 0xFF0000EE, 0xFF0000DD, 0xFF0000BB, 0xFF0000AA, 0xFF000088, 0xFF000077, 0xFF000055, 0xFF000044, 0xFF000022, 0xFF000011, 0xFFEEEEEE, 0xFFDDDDDD, 0xFFBBBBBB, 0xFFAAAAAA, 0xFF888888, 0xFF777777, 0xFF555555, 0xFF444444, 0xFF222222, 0xFF111111, 0xFF000000 }; private IcnsDecoder() { } @@ -96,7 +49,7 @@ private static void decode1BPPImage(final IcnsType imageType, final byte[] image value = 0xff & imageData[position++]; bitsLeft = 8; } - int argb; + final int argb; if ((value & 0x80) != 0) { argb = 0xff000000; } else { @@ -114,7 +67,7 @@ private static void decode4BPPImage(final IcnsType imageType, final byte[] image boolean visited = false; for (int y = 0; y < imageType.getHeight(); y++) { for (int x = 0; x < imageType.getWidth(); x++) { - int index; + final int index; if (!visited) { index = 0xf & (imageData[i] >> 4); } else { @@ -139,9 +92,9 @@ private static void decode32BPPImage(final IcnsType imageType, final byte[] imag for (int y = 0; y < imageType.getHeight(); y++) { for (int x = 0; x < imageType.getWidth(); x++) { final int argb = 0xff000000 /* the "alpha" is ignored */ - | ((0xff & imageData[4 * (y * imageType.getWidth() + x) + 1]) << 16) - | ((0xff & imageData[4 * (y * imageType.getWidth() + x) + 2]) << 8) - | (0xff & imageData[4 * (y * imageType.getWidth() + x) + 3]); + | ((0xff & imageData[4 * (y * imageType.getWidth() + x) + 1]) << 16) + | ((0xff & imageData[4 * (y * imageType.getWidth() + x) + 2]) << 8) + | (0xff & imageData[4 * (y * imageType.getWidth() + x) + 3]); image.setRGB(x, y, argb); } } @@ -167,7 +120,7 @@ private static void apply1BPPMask(final byte[] maskData, final ImageBuilder imag value = 0xff & maskData[position++]; bitsLeft = 8; } - int alpha; + final int alpha; if ((value & 0x80) != 0) { alpha = 0xff; } else { @@ -184,16 +137,16 @@ private static void apply8BPPMask(final byte[] maskData, final ImageBuilder imag for (int y = 0; y < image.getHeight(); y++) { for (int x = 0; x < image.getWidth(); x++) { final int alpha = 0xff & maskData[y * image.getWidth() + x]; - image.setRGB(x, y, - (alpha << 24) | (0xffffff & image.getRGB(x, y))); + image.setRGB(x, y, (alpha << 24) | (0xffffff & image.getRGB(x, y))); } } } - public static List decodeAllImages(final IcnsImageParser.IcnsElement[] icnsElements) - throws ImageReadException { - final List result = new ArrayList<>(); + public static List> decodeAllImages(final IcnsImageParser.IcnsElement[] icnsElements) throws ImageReadException { + final List> result = new ArrayList<>(); for (final IcnsElement imageElement : icnsElements) { + final Map image = new HashMap<>(); + final IcnsType imageType = IcnsType.findImageType(imageElement.type); if (imageType == null) { continue; @@ -227,44 +180,59 @@ public static List decodeAllImages(final IcnsImageParser.IcnsElem } } - // FIXME: don't skip these when JPEG 2000 support is added: - if (imageType == IcnsType.ICNS_256x256_32BIT_ARGB_IMAGE - || imageType == IcnsType.ICNS_512x512_32BIT_ARGB_IMAGE) { + if (isPngImage(imageElement.data) || isJpeg2000Image(imageElement.data)) { + try { + final InputStream in = new ByteArrayInputStream(imageElement.data); + final BufferedImage bufferedImage = ImageIO.read(in); + if (bufferedImage == null) { + if (isPngImage(imageElement.data)) { + System.out.println("Can not read PNG image. [" + imageType.getTypeName() + "]"); + } + if (isJpeg2000Image(imageElement.data)) { + System.out.println("Can not read Jpeg2000 image. [" + imageType.getTypeName() + "]"); + } + } else { + image.put(bufferedImage, imageType); + result.add(image); + } + } catch (final IOException e) { + throw new ImageReadException(e.getMessage()); + } continue; } - final int expectedSize = (imageType.getWidth() * imageType.getHeight() - * imageType.getBitsPerPixel() + 7) / 8; - byte[] imageData; + final int expectedSize = (imageType.getWidth() + * imageType.getHeight() + * imageType.getBitsPerPixel() + 7) / 8; + final byte[] imageData; if (imageElement.data.length < expectedSize) { if (imageType.getBitsPerPixel() == 32) { - imageData = Rle24Compression.decompress( - imageType.getWidth(), imageType.getHeight(), - imageElement.data); + imageData = Rle24Compression.decompress(imageType.getWidth(), imageType.getHeight(), imageElement.data); } else { - throw new ImageReadException("Short image data but not a 32 bit compressed type"); + System.out.println("Short image data but not a 32 bit compressed type"); + continue; } } else { imageData = imageElement.data; } - final ImageBuilder imageBuilder = new ImageBuilder(imageType.getWidth(), - imageType.getHeight(), true); + final ImageBuilder imageBuilder = new ImageBuilder(imageType.getWidth(), imageType.getHeight(), true); switch (imageType.getBitsPerPixel()) { - case 1: - decode1BPPImage(imageType, imageData, imageBuilder); - break; - case 4: - decode4BPPImage(imageType, imageData, imageBuilder); - break; - case 8: - decode8BPPImage(imageType, imageData, imageBuilder); - break; - case 32: - decode32BPPImage(imageType, imageData, imageBuilder); - break; - default: - throw new ImageReadException("Unsupported bit depth " + imageType.getBitsPerPixel()); + case 1: + decode1BPPImage(imageType, imageData, imageBuilder); + break; + case 4: + decode4BPPImage(imageType, imageData, imageBuilder); + break; + case 8: + decode8BPPImage(imageType, imageData, imageBuilder); + break; + case 32: + decode32BPPImage(imageType, imageData, imageBuilder); + break; + default: + System.out.println("Unsupported bit depth " + imageType.getBitsPerPixel()); + continue; } if (maskElement != null) { @@ -273,12 +241,36 @@ public static List decodeAllImages(final IcnsImageParser.IcnsElem } else if (maskType.getBitsPerPixel() == 8) { apply8BPPMask(maskElement.data, imageBuilder); } else { - throw new ImageReadException("Unsupport mask bit depth " + maskType.getBitsPerPixel()); + System.out.println("Unsupport mask bit depth " + maskType.getBitsPerPixel()); + continue; } } - - result.add(imageBuilder.getBufferedImage()); + image.put(imageBuilder.getBufferedImage(), imageType); + result.add(image); } return result; } + + private static boolean isPngImage(final byte[] data) { + if (data.length > 4) { + if ((char) data[1] == 'P' && (char) data[2] == 'N' && (char) data[3] == 'G') { + return true; + } + } + return false; + } + + private static boolean isJpeg2000Image(final byte[] data) { + final String jpeg2000Signature = "0 0 0 12 106 80 32 32 13 10"; + final StringBuilder stringBuilder = new StringBuilder(); + if (data.length > 10) { + for (int i = 0; i < 10; i++) { + stringBuilder.append(String.valueOf(data[i]) + " "); + } + if (stringBuilder.toString().trim().equals(jpeg2000Signature)) { + return true; + } + } + return false; + } } diff --git a/src/main/java/org/apache/commons/imaging/formats/icns/IcnsImageParser.java b/src/main/java/org/apache/commons/imaging/formats/icns/IcnsImageParser.java index c95321a92..944daccaa 100644 --- a/src/main/java/org/apache/commons/imaging/formats/icns/IcnsImageParser.java +++ b/src/main/java/org/apache/commons/imaging/formats/icns/IcnsImageParser.java @@ -21,27 +21,18 @@ import static org.apache.commons.imaging.common.BinaryFunctions.read4Bytes; import static org.apache.commons.imaging.common.BinaryFunctions.readBytes; -import java.awt.Dimension; +import java.awt.*; import java.awt.image.BufferedImage; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.PrintWriter; +import java.io.*; import java.nio.ByteOrder; -import java.util.ArrayList; -import java.util.HashMap; +import java.util.*; import java.util.List; -import java.util.Map; - -import org.apache.commons.imaging.ImageFormat; -import org.apache.commons.imaging.ImageFormats; -import org.apache.commons.imaging.ImageInfo; -import org.apache.commons.imaging.ImageParser; -import org.apache.commons.imaging.ImageReadException; -import org.apache.commons.imaging.ImageWriteException; + +import org.apache.commons.imaging.*; import org.apache.commons.imaging.common.BinaryOutputStream; import org.apache.commons.imaging.common.ImageMetadata; import org.apache.commons.imaging.common.bytesource.ByteSource; +import org.apache.commons.imaging.common.bytesource.ByteSourceFile; public class IcnsImageParser extends ImageParser { static final int ICNS_MAGIC = IcnsType.typeAsInt("icns"); @@ -74,16 +65,14 @@ protected ImageFormat[] getAcceptedTypes() { // FIXME should throw UOE @Override - public ImageMetadata getMetadata(final ByteSource byteSource, final Map params) - throws ImageReadException, IOException { + public ImageMetadata getMetadata(final ByteSource byteSource, final Map params) throws ImageReadException, IOException { return null; } @Override - public ImageInfo getImageInfo(final ByteSource byteSource, Map params) - throws ImageReadException, IOException { + public ImageInfo getImageInfo(final ByteSource byteSource, Map params) throws ImageReadException, IOException { // make copy of params; we'll clear keys as we consume them. - params = params == null ? new HashMap() : new HashMap<>(params); + params = (params == null) ? new HashMap() : new HashMap<>(params); if (params.containsKey(PARAM_KEY_VERBOSE)) { params.remove(PARAM_KEY_VERBOSE); @@ -95,22 +84,30 @@ public ImageInfo getImageInfo(final ByteSource byteSource, Map p } final IcnsContents contents = readImage(byteSource); - final List images = IcnsDecoder.decodeAllImages(contents.icnsElements); - if (images.isEmpty()) { + final List> list = IcnsDecoder.decodeAllImages(contents.icnsElements); + BufferedImage image0 = null; + if (!list.isEmpty()) { + for (final Map map : list) { + if (!map.isEmpty()) { + final Iterator iterator = map.keySet().iterator(); + if (iterator.hasNext()) { + image0 = iterator.next(); + } else { + throw new ImageReadException("No icons in ICNS file"); + } + } else { + throw new ImageReadException("No icons in ICNS file"); + } + } + } else { throw new ImageReadException("No icons in ICNS file"); } - final BufferedImage image0 = images.get(0); - return new ImageInfo("Icns", 32, new ArrayList(), - ImageFormats.ICNS, "ICNS Apple Icon Image", - image0.getHeight(), "image/x-icns", images.size(), 0, 0, 0, 0, - image0.getWidth(), false, true, false, - ImageInfo.ColorType.RGB, - ImageInfo.CompressionAlgorithm.UNKNOWN); + + return new ImageInfo("Icns", 32, new ArrayList(), ImageFormats.ICNS, "ICNS Apple Icon Image", image0.getHeight(), "image/x-icns", list.size(), 0, 0, 0, 0, image0.getWidth(), false, true, false, ImageInfo.ColorType.RGB, ImageInfo.CompressionAlgorithm.UNKNOWN); } @Override - public Dimension getImageSize(final ByteSource byteSource, Map params) - throws ImageReadException, IOException { + public Dimension getImageSize(final ByteSource byteSource, Map params) throws ImageReadException, IOException { // make copy of params; we'll clear keys as we consume them. params = (params == null) ? new HashMap() : new HashMap<>(params); @@ -124,17 +121,30 @@ public Dimension getImageSize(final ByteSource byteSource, Map p } final IcnsContents contents = readImage(byteSource); - final List images = IcnsDecoder.decodeAllImages(contents.icnsElements); - if (images.isEmpty()) { + final List> list = IcnsDecoder.decodeAllImages(contents.icnsElements); + BufferedImage image0 = null; + if (!list.isEmpty()) { + for (final Map map : list) { + if (!map.isEmpty()) { + final Iterator iterator = map.keySet().iterator(); + if (iterator.hasNext()) { + image0 = iterator.next(); + } else { + throw new ImageReadException("No icons in ICNS file"); + } + } else { + throw new ImageReadException("No icons in ICNS file"); + } + } + } else { throw new ImageReadException("No icons in ICNS file"); } - final BufferedImage image0 = images.get(0); + return new Dimension(image0.getWidth(), image0.getHeight()); } @Override - public byte[] getICCProfileBytes(final ByteSource byteSource, final Map params) - throws ImageReadException, IOException { + public byte[] getICCProfileBytes(final ByteSource byteSource, final Map params) throws ImageReadException, IOException { return null; } @@ -149,15 +159,17 @@ public IcnsHeader(final int magic, final int fileSize) { public void dump(final PrintWriter pw) { pw.println("IcnsHeader"); - pw.println("Magic: 0x" + Integer.toHexString(magic) + " (" - + IcnsType.describeType(magic) + ")"); - pw.println("FileSize: " + fileSize); + pw.println("Magic: 0x" + + Integer.toHexString(this.magic) + + " (" + + IcnsType.describeType(this.magic) + + ")"); + pw.println("FileSize: " + this.fileSize); pw.println(""); } } - private IcnsHeader readIcnsHeader(final InputStream is) - throws ImageReadException, IOException { + private IcnsHeader readIcnsHeader(final InputStream is) throws ImageReadException, IOException { final int magic = read4Bytes("Magic", is, "Not a Valid ICNS File", getByteOrder()); final int fileSize = read4Bytes("FileSize", is, "Not a Valid ICNS File", getByteOrder()); @@ -181,35 +193,38 @@ public IcnsElement(final int type, final int elementSize, final byte[] data) { public void dump(final PrintWriter pw) { pw.println("IcnsElement"); - final IcnsType icnsType = IcnsType.findAnyType(type); - String typeDescription; + final IcnsType icnsType = IcnsType.findAnyType(this.type); + final String typeDescription; if (icnsType == null) { typeDescription = ""; } else { typeDescription = " " + icnsType.toString(); } - pw.println("Type: 0x" + Integer.toHexString(type) + " (" - + IcnsType.describeType(type) + ")" + typeDescription); - pw.println("ElementSize: " + elementSize); + pw.println("Type: 0x" + + Integer.toHexString(this.type) + + " (" + + IcnsType.describeType(this.type) + + ")" + + typeDescription); + pw.println("ElementSize: " + this.elementSize); pw.println(""); } } private IcnsElement readIcnsElement(final InputStream is) throws IOException { final int type = read4Bytes("Type", is, "Not a Valid ICNS File", getByteOrder()); // Icon type - // (4 bytes) + // (4 bytes) final int elementSize = read4Bytes("ElementSize", is, "Not a Valid ICNS File", getByteOrder()); // Length - // of - // data - // (4 - // bytes), - // in - // bytes, - // including - // this - // header - final byte[] data = readBytes("Data", is, elementSize - 8, - "Not a Valid ICNS File"); + // of + // data + // (4 + // bytes), + // in + // bytes, + // including + // this + // header + final byte[] data = readBytes("Data", is, elementSize - 8, "Not a Valid ICNS File"); return new IcnsElement(type, elementSize, data); } @@ -225,8 +240,7 @@ public IcnsContents(final IcnsHeader icnsHeader, final IcnsElement[] icnsElement } } - private IcnsContents readImage(final ByteSource byteSource) - throws ImageReadException, IOException { + private IcnsContents readImage(final ByteSource byteSource) throws ImageReadException, IOException { try (InputStream is = byteSource.getInputStream()) { final IcnsHeader icnsHeader = readIcnsHeader(is); @@ -248,8 +262,7 @@ private IcnsContents readImage(final ByteSource byteSource) } @Override - public boolean dumpImageFile(final PrintWriter pw, final ByteSource byteSource) - throws ImageReadException, IOException { + public boolean dumpImageFile(final PrintWriter pw, final ByteSource byteSource) throws ImageReadException, IOException { final IcnsContents icnsContents = readImage(byteSource); icnsContents.icnsHeader.dump(pw); for (final IcnsElement icnsElement : icnsContents.icnsElements) { @@ -259,26 +272,52 @@ public boolean dumpImageFile(final PrintWriter pw, final ByteSource byteSource) } @Override - public final BufferedImage getBufferedImage(final ByteSource byteSource, - final Map params) throws ImageReadException, IOException { + public final BufferedImage getBufferedImage(final ByteSource byteSource, final Map params) throws ImageReadException, IOException { final IcnsContents icnsContents = readImage(byteSource); - final List result = IcnsDecoder.decodeAllImages(icnsContents.icnsElements); - if (!result.isEmpty()) { - return result.get(0); + final List> list = IcnsDecoder.decodeAllImages(icnsContents.icnsElements); + if (!list.isEmpty()) { + for (final Map map : list) { + if (!map.isEmpty()) { + final Iterator iterator = map.keySet().iterator(); + if (iterator.hasNext()) { + return iterator.next(); + } + } + } } throw new ImageReadException("No icons in ICNS file"); } @Override - public List getAllBufferedImages(final ByteSource byteSource) - throws ImageReadException, IOException { + public List getAllBufferedImages(final ByteSource byteSource) throws ImageReadException, IOException { + final IcnsContents icnsContents = readImage(byteSource); + final List images = new ArrayList<>(); + final List> mapList = IcnsDecoder.decodeAllImages(icnsContents.icnsElements); + for (final Map map : mapList) { + final Iterator iterator = map.keySet().iterator(); + if (iterator.hasNext()) { + images.add(iterator.next()); + continue; + } + } + return images; + } + + public List> getAllBufferedImagesWithType(final ByteSource byteSource) throws ImageReadException, IOException { final IcnsContents icnsContents = readImage(byteSource); return IcnsDecoder.decodeAllImages(icnsContents.icnsElements); } + public final List> getAllBufferedImagesWithType(final File file) throws ImageReadException, IOException { + if (!canAcceptExtension(file)) { + return null; + } + + return getAllBufferedImagesWithType(new ByteSourceFile(file)); + } + @Override - public void writeImage(final BufferedImage src, final OutputStream os, Map params) - throws ImageWriteException, IOException { + public void writeImage(final BufferedImage src, final OutputStream os, Map params) throws ImageWriteException, IOException { // make copy of params; we'll clear keys as we consume them. params = (params == null) ? new HashMap() : new HashMap<>(params); @@ -292,7 +331,7 @@ public void writeImage(final BufferedImage src, final OutputStream os, Map - * - * @param byteSource - * File containing image data. - * @param params - * Map of optional parameters, defined in ImagingConstants. + *

+ * + * @param byteSource File containing image data. + * @param params Map of optional parameters, defined in ImagingConstants. * @return Xmp Xml as String, if present. Otherwise, returns null. */ @Override - public String getXmpXml(final ByteSource byteSource, final Map params) - throws ImageReadException, IOException { + public String getXmpXml(final ByteSource byteSource, final Map params) throws ImageReadException, IOException { return null; } } diff --git a/src/main/java/org/apache/commons/imaging/formats/icns/IcnsType.java b/src/main/java/org/apache/commons/imaging/formats/icns/IcnsType.java old mode 100644 new mode 100755 index 276da924a..4e27697df --- a/src/main/java/org/apache/commons/imaging/formats/icns/IcnsType.java +++ b/src/main/java/org/apache/commons/imaging/formats/icns/IcnsType.java @@ -20,104 +20,88 @@ enum IcnsType { - ICNS_16x12_1BIT_IMAGE_AND_MASK("icm#", 16, 12, 1, true), - ICNS_16x12_4BIT_IMAGE("icm4", 16, 12, 4, false), - ICNS_16x12_8BIT_IMAGE("icm8", 16, 12, 8, false), - - ICNS_16x16_8BIT_MASK("s8mk", 16, 16, 8, true), - ICNS_16x16_1BIT_IMAGE_AND_MASK("ics#", 16, 16, 1, true), - ICNS_16x16_4BIT_IMAGE("ics4", 16, 16, 4, false), - ICNS_16x16_8BIT_IMAGE("ics8", 16, 16, 8, false), - ICNS_16x16_32BIT_IMAGE("is32", 16, 16, 32, false), - - ICNS_32x32_8BIT_MASK("l8mk", 32, 32, 8, true), - ICNS_32x32_1BIT_IMAGE_AND_MASK("ICN#", 32, 32, 1, true), - ICNS_32x32_4BIT_IMAGE("icl4", 32, 32, 4, false), - ICNS_32x32_8BIT_IMAGE("icl8", 32, 32, 8, false), - ICNS_32x32_32BIT_IMAGE("il32", 32, 32, 32, false), - - ICNS_48x48_8BIT_MASK("h8mk", 48, 48, 8, true), - ICNS_48x48_1BIT_IMAGE_AND_MASK("ich#", 48, 48, 1, true), - ICNS_48x48_4BIT_IMAGE("ich4", 48, 48, 4, false), - ICNS_48x48_8BIT_IMAGE("ich8", 48, 48, 8, false), - ICNS_48x48_32BIT_IMAGE("ih32", 48, 48, 32, false), - - ICNS_128x128_8BIT_MASK("t8mk", 128, 128, 8, true), - ICNS_128x128_32BIT_IMAGE("it32", 128, 128, 32, false), - - ICNS_256x256_32BIT_ARGB_IMAGE("ic08", 256, 256, 32, false), - - ICNS_512x512_32BIT_ARGB_IMAGE("ic09", 512, 512, 32, false); - - private static final IcnsType[] ALL_IMAGE_TYPES = { - ICNS_16x12_1BIT_IMAGE_AND_MASK, - ICNS_16x12_4BIT_IMAGE, - ICNS_16x12_8BIT_IMAGE, - ICNS_16x16_1BIT_IMAGE_AND_MASK, - ICNS_16x16_4BIT_IMAGE, - ICNS_16x16_8BIT_IMAGE, - ICNS_16x16_32BIT_IMAGE, - ICNS_32x32_1BIT_IMAGE_AND_MASK, - ICNS_32x32_4BIT_IMAGE, - ICNS_32x32_8BIT_IMAGE, - ICNS_32x32_32BIT_IMAGE, - ICNS_48x48_1BIT_IMAGE_AND_MASK, - ICNS_48x48_4BIT_IMAGE, - ICNS_48x48_8BIT_IMAGE, - ICNS_48x48_32BIT_IMAGE, - ICNS_128x128_32BIT_IMAGE, - ICNS_256x256_32BIT_ARGB_IMAGE, - ICNS_512x512_32BIT_ARGB_IMAGE}; - - private static final IcnsType[] ALL_MASK_TYPES = { - ICNS_16x12_1BIT_IMAGE_AND_MASK, - ICNS_16x16_1BIT_IMAGE_AND_MASK, - ICNS_16x16_8BIT_MASK, - ICNS_32x32_1BIT_IMAGE_AND_MASK, - ICNS_32x32_8BIT_MASK, - ICNS_48x48_1BIT_IMAGE_AND_MASK, - ICNS_48x48_8BIT_MASK, - ICNS_128x128_8BIT_MASK}; + ICNS_16x12_1BIT_IMAGE_AND_MASK("icm#", 16, 12, 1, true, false), ICNS_16x12_4BIT_IMAGE("icm4", 16, 12, 4, false, false), ICNS_16x12_8BIT_IMAGE("icm8", 16, 12, 8, false, false), ICNS_16x16_8BIT_MASK("s8mk", 16, 16, 8, true, false), ICNS_16x16_1BIT_IMAGE_AND_MASK("ics#", 16, 16, 1, true, false), ICNS_16x16_4BIT_IMAGE("ics4", 16, 16, 4, false, false), ICNS_16x16_8BIT_IMAGE("ics8", 16, 16, 8, false, false), ICNS_16x16_32BIT_IMAGE("is32", 16, 16, 32, false, false), ICNS_16x16_32BIT_ARGB_IMAGE("icp4", 16, 16, 32, false, true), + + ICNS_32x32_1BIT_MONO_IMAGE("ICON", 32, 32, 1, false, false), ICNS_32x32_1BIT_IMAGE_AND_MASK("ICN#", 32, 32, 1, true, false), ICNS_32x32_4BIT_IMAGE("icl4", 32, 32, 4, false, false), ICNS_32x32_8BIT_IMAGE("icl8", 32, 32, 8, false, false), ICNS_32x32_8BIT_MASK("l8mk", 32, 32, 8, true, false), ICNS_32x32_32BIT_IMAGE("il32", 32, 32, 32, false, false), ICNS_32x32_32BIT_ARGB_IMAGE("icp5", 32, 32, 32, false, true), ICNS_32x32_32BIT_RETINA_IMAGE("ic11", 32, 32, 32, false, true), + + ICNS_48x48_1BIT_IMAGE_AND_MASK("ich#", 48, 48, 1, true, false), ICNS_48x48_4BIT_IMAGE("ich4", 48, 48, 4, false, false), ICNS_48x48_8BIT_IMAGE("ich8", 48, 48, 8, false, false), ICNS_48x48_8BIT_MASK("h8mk", 48, 48, 8, true, false), ICNS_48x48_32BIT_IMAGE("ih32", 48, 48, 32, false, false), + + ICNS_64x64_32BIT_ARGB_IMAGE("icp6", 64, 64, 32, false, true), ICNS_64x64_32BIT_RETINA_IMAGE("ic12", 64, 64, 32, false, true), + + ICNS_128x128_8BIT_MASK("t8mk", 128, 128, 8, true, false), ICNS_128x128_32BIT_IMAGE("it32", 128, 128, 32, false, false), ICNS_128x128_32BIT_ARGB_IMAGE("ic07", 128, 128, 32, false, true), + + ICNS_256x256_32BIT_ARGB_IMAGE("ic08", 256, 256, 32, false, true), ICNS_256x256_32BIT_RETINA_IMAGE("ic13", 256, 256, 32, false, true), + + ICNS_512x512_32BIT_ARGB_IMAGE("ic09", 512, 512, 32, false, true), ICNS_512x512_32BIT_RETINA_IMAGE("ic14", 512, 512, 32, false, true), + + ICNS_1024x1024_32BIT_ARGB_IMAGE("ic10", 1024, 1024, 32, false, true); + + private static final IcnsType[] ALL_IMAGE_TYPES = { ICNS_16x12_1BIT_IMAGE_AND_MASK, ICNS_16x12_4BIT_IMAGE, ICNS_16x12_8BIT_IMAGE, ICNS_16x16_1BIT_IMAGE_AND_MASK, ICNS_16x16_4BIT_IMAGE, ICNS_16x16_8BIT_IMAGE, ICNS_16x16_32BIT_IMAGE, ICNS_16x16_32BIT_ARGB_IMAGE, ICNS_32x32_1BIT_MONO_IMAGE, ICNS_32x32_1BIT_IMAGE_AND_MASK, ICNS_32x32_4BIT_IMAGE, ICNS_32x32_8BIT_IMAGE, ICNS_32x32_32BIT_IMAGE, ICNS_32x32_32BIT_ARGB_IMAGE, ICNS_32x32_32BIT_RETINA_IMAGE, ICNS_48x48_1BIT_IMAGE_AND_MASK, ICNS_48x48_4BIT_IMAGE, ICNS_48x48_8BIT_IMAGE, ICNS_48x48_32BIT_IMAGE, ICNS_64x64_32BIT_ARGB_IMAGE, ICNS_64x64_32BIT_RETINA_IMAGE, ICNS_128x128_32BIT_IMAGE, ICNS_128x128_32BIT_ARGB_IMAGE, ICNS_256x256_32BIT_ARGB_IMAGE, ICNS_256x256_32BIT_RETINA_IMAGE, ICNS_512x512_32BIT_ARGB_IMAGE, ICNS_512x512_32BIT_RETINA_IMAGE, ICNS_1024x1024_32BIT_ARGB_IMAGE }; + + private static final IcnsType[] ALL_MASK_TYPES = { ICNS_16x12_1BIT_IMAGE_AND_MASK, ICNS_16x16_1BIT_IMAGE_AND_MASK, ICNS_16x16_8BIT_MASK, ICNS_32x32_1BIT_IMAGE_AND_MASK, ICNS_32x32_8BIT_MASK, ICNS_48x48_1BIT_IMAGE_AND_MASK, ICNS_48x48_8BIT_MASK, ICNS_128x128_8BIT_MASK }; private final int type; + private final String typeName; private final int width; private final int height; private final int bitsPerPixel; private final boolean hasMask; + private final boolean isPngOrJpeg2000; - private IcnsType(final String type, final int width, final int height, final int bitsPerPixel, final boolean hasMask) { + private IcnsType(final String type, final int width, final int height, final int bitsPerPixel, final boolean hasMask, final boolean isPngOrJpeg2000) { this.type = typeAsInt(type); + this.typeName = type; this.width = width; this.height = height; this.bitsPerPixel = bitsPerPixel; this.hasMask = hasMask; + this.isPngOrJpeg2000 = isPngOrJpeg2000; } public int getType() { - return type; + return this.type; + } + + public String getTypeName() { + return this.typeName; } public int getWidth() { - return width; + return this.width; } public int getHeight() { - return height; + return this.height; } public int getBitsPerPixel() { - return bitsPerPixel; + return this.bitsPerPixel; } public boolean hasMask() { - return hasMask; + return this.hasMask; + } + + public boolean isPngOrJpeg2000() { + return this.isPngOrJpeg2000; } @Override public String toString() { - return getClass().getName() + "[" + "width=" + width + "," + "height=" - + height + "," + "bpp=" + bitsPerPixel + "," + "hasMask=" - + hasMask + "]"; + return getClass().getName() + + "[" + + "width=" + + this.width + + "," + + "height=" + + this.height + + "," + + "bpp=" + + this.bitsPerPixel + + "," + + "hasMask=" + + this.hasMask + + "]"; } public static IcnsType findAnyType(final int type) { @@ -146,8 +130,8 @@ public static IcnsType findImageType(final int type) { public static IcnsType find8BPPMaskType(final IcnsType imageType) { for (final IcnsType allMaskType : ALL_MASK_TYPES) { if (allMaskType.getBitsPerPixel() == 8 - && allMaskType.getWidth() == imageType.getWidth() - && allMaskType.getHeight() == imageType.getHeight()) { + && allMaskType.getWidth() == imageType.getWidth() + && allMaskType.getHeight() == imageType.getHeight()) { return allMaskType; } } @@ -157,8 +141,8 @@ public static IcnsType find8BPPMaskType(final IcnsType imageType) { public static IcnsType find1BPPMaskType(final IcnsType imageType) { for (final IcnsType allMaskType : ALL_MASK_TYPES) { if (allMaskType.getBitsPerPixel() == 1 - && allMaskType.getWidth() == imageType.getWidth() - && allMaskType.getHeight() == imageType.getHeight()) { + && allMaskType.getWidth() == imageType.getWidth() + && allMaskType.getHeight() == imageType.getHeight()) { return allMaskType; } } @@ -166,7 +150,7 @@ public static IcnsType find1BPPMaskType(final IcnsType imageType) { } public static int typeAsInt(final String type) { - byte[] bytes; + final byte[] bytes; try { bytes = type.getBytes("US-ASCII"); } catch (final UnsupportedEncodingException unsupportedEncodingException) { @@ -175,10 +159,10 @@ public static int typeAsInt(final String type) { if (bytes.length != 4) { throw new IllegalArgumentException("Invalid ICNS type"); } - return ((0xff & bytes[0]) << 24) - | ((0xff & bytes[1]) << 16) - | ((0xff & bytes[2]) << 8) - | (0xff & bytes[3]); + return ((0xff & bytes[0]) << 24) + | ((0xff & bytes[1]) << 16) + | ((0xff & bytes[2]) << 8) + | (0xff & bytes[3]); } public static String describeType(final int type) { diff --git a/src/test/data/images/icns/2/AppIcon.icns b/src/test/data/images/icns/2/AppIcon.icns new file mode 100644 index 000000000..0ee4e4111 Binary files /dev/null and b/src/test/data/images/icns/2/AppIcon.icns differ diff --git a/src/test/data/images/icns/2/Google Chrome.icns b/src/test/data/images/icns/2/Google Chrome.icns new file mode 100644 index 000000000..384f3bc58 Binary files /dev/null and b/src/test/data/images/icns/2/Google Chrome.icns differ diff --git a/src/test/data/images/icns/2/MSWD.icns b/src/test/data/images/icns/2/MSWD.icns new file mode 100644 index 000000000..a31b047d2 Binary files /dev/null and b/src/test/data/images/icns/2/MSWD.icns differ diff --git a/src/test/data/images/icns/2/Wireshark.icns b/src/test/data/images/icns/2/Wireshark.icns new file mode 100644 index 000000000..21dcd6c0a Binary files /dev/null and b/src/test/data/images/icns/2/Wireshark.icns differ diff --git a/src/test/data/images/icns/2/XCEL.icns b/src/test/data/images/icns/2/XCEL.icns new file mode 100644 index 000000000..0fe2e03db Binary files /dev/null and b/src/test/data/images/icns/2/XCEL.icns differ diff --git a/src/test/data/images/icns/2/compass.icns b/src/test/data/images/icns/2/compass.icns new file mode 100644 index 000000000..282beec00 Binary files /dev/null and b/src/test/data/images/icns/2/compass.icns differ diff --git a/src/test/data/images/icns/2/sourcetree.icns b/src/test/data/images/icns/2/sourcetree.icns new file mode 100644 index 000000000..5c8f67a2b Binary files /dev/null and b/src/test/data/images/icns/2/sourcetree.icns differ diff --git a/src/test/java/org/apache/commons/imaging/formats/icns/IcnsGetAllBufferedImagesTest.java b/src/test/java/org/apache/commons/imaging/formats/icns/IcnsGetAllBufferedImagesTest.java new file mode 100644 index 000000000..7558f195f --- /dev/null +++ b/src/test/java/org/apache/commons/imaging/formats/icns/IcnsGetAllBufferedImagesTest.java @@ -0,0 +1,75 @@ +package org.apache.commons.imaging.formats.icns; + +import java.awt.image.BufferedImage; +import java.io.File; +import java.util.*; + +import org.apache.commons.imaging.ImageFormat; +import org.apache.commons.imaging.ImageFormats; +import org.apache.commons.imaging.Imaging; +import org.junit.Assert; +import org.junit.Test; + +/** + * Created by mw on 15.09.16. + */ +public class IcnsGetAllBufferedImagesTest { + + private static final String ICNS_FILES = "src/test/data/images/icns/2/"; + private static final String DIR_ICONS_CACHE = "src/test/data/images/icns/extractedICNS/"; + + @Test + public void testGetAllBufferedImagesWithType_aFewIcnsFiles_containsJpegFormat() { + + if (!new File(DIR_ICONS_CACHE).exists()) { + new File(DIR_ICONS_CACHE).mkdir(); + } + + final Set imageTypeProofList = new HashSet<>(); + //As of Wikipedia: JPEG 2000 or PNG format + final List jpegImageTypes = new ArrayList<>(Arrays.asList("icp4", "icp5", "icp6", "ic07", "ic08", "ic09", "ic10", "ic11", "ic12", "ic13", "ic14")); + final ImageFormat format = ImageFormats.PNG; + final Map params = new HashMap<>(); + + final File icnsTestFiles = new File(ICNS_FILES); + final File[] files = icnsTestFiles.listFiles(); + final IcnsImageParser icnsImageParser = new IcnsImageParser(); + for (final File icnsFile : files) { + try { + final List> bufferedImages = icnsImageParser.getAllBufferedImagesWithType(icnsFile); + + int counterExtracted = 0; + for (final Map map : bufferedImages) { + final Iterator iterator = map.keySet().iterator(); + while (iterator.hasNext()) { + final BufferedImage image = iterator.next(); + final String name = icnsFile.getName(); + final String type = map.get(image).getTypeName(); + final int width = image.getWidth(); + final int height = image.getHeight(); + final int pixelSize = image.getColorModel().getPixelSize(); + + //Add imageType to proof list if image type could be of JPEG2000 format + for (final String jpegImageType : jpegImageTypes) { + if (jpegImageType.equals(type)) { + imageTypeProofList.add(type); + } + } + + System.out.println(name + " -> [" + type + "] " + pixelSize + " bit | " + width + "x" + height); + final File cachedImageFile = new File(DIR_ICONS_CACHE + name + "_[" + type + "]_" + width + "x" + height + "_" + pixelSize + "bit_" + counterExtracted + "." + format.getExtension()); + Imaging.writeImage(image, cachedImageFile, format, params); + counterExtracted++; + } + } + + //Check if JPEG is supported + Assert.assertEquals(true, imageTypeProofList.size() > 0); + System.out.println("--------------- " + imageTypeProofList.size() + " potential JPEGs and " + counterExtracted + " images extracted ---------------"); + + } catch (final Exception e) { + continue; + } + } + } +}