Added test case for icon containing TOC_ + IC10 resources + fixed PNG reading and skipping of unknown resources.

Added test case for icon with no 8 bit mask + fixed fallback to 1 bit mask.
Added test case for icon with no mask + fixed transparency issue.
This commit is contained in:
Harald Kuhr 2011-11-14 15:25:21 +01:00
parent 3a9ad582f2
commit 9742af9a5d
7 changed files with 286 additions and 107 deletions

View File

@ -96,9 +96,12 @@ interface ICNS {
/** 1024×1024 PNG icon (10.7+)*/
int ic10 = ('i' << 24) + ('c' << 16) + ('1' << 8) + '0';
/** Unknown */
/** Unknown (Version) */
int icnV = ('i' << 24) + ('c' << 16) + ('n' << 8) + 'V';
/** Unknown (Table of Contents) */
int TOC_ = ('T' << 24) + ('O' << 16) + ('C' << 8) + ' ';
/** JPEG 2000 magic header */
byte[] JPEG_2000_MAGIC = new byte[] {0x00, 0x00, 0x00, 0x0C, 'j', 'P', 0x20, 0x20, 0x0D, 0x0A, (byte) 0x87, 0x0A};

View File

@ -59,9 +59,14 @@ import java.util.List;
* @see <a href="http://en.wikipedia.org/wiki/Apple_Icon_Image_format">Apple Icon Image format (Wikipedia)</a>
*/
public final class ICNSImageReader extends ImageReaderBase {
private static final int HEADER_SIZE = 8;
private List<IconHeader> icons = new ArrayList<IconHeader>();
private List<IconHeader> masks = new ArrayList<IconHeader>();
// TODO: Support ToC resource for faster parsing/faster determine number of icons?
// TODO: Subsampled reading for completeness, even if never used?
private static final int RESOURCE_HEADER_SIZE = 8;
private List<IconResource> icons = new ArrayList<IconResource>();
private List<IconResource> masks = new ArrayList<IconResource>();
private IconResource lastResourceRead;
private int length;
@ -76,26 +81,27 @@ public final class ICNSImageReader extends ImageReaderBase {
@Override
protected void resetMembers() {
length = 0;
lastResourceRead = null;
icons.clear();
masks.clear();
}
@Override
public int getWidth(int imageIndex) throws IOException {
return readIconHeader(imageIndex).size().width;
return readIconResource(imageIndex).size().width;
}
@Override
public int getHeight(int imageIndex) throws IOException {
return readIconHeader(imageIndex).size().height;
return readIconResource(imageIndex).size().height;
}
@Override
public ImageTypeSpecifier getRawImageType(int imageIndex) throws IOException {
IconHeader header = readIconHeader(imageIndex);
IconResource resource = readIconResource(imageIndex);
switch (header.depth()) {
switch (resource.depth()) {
case 1:
return IndexedImageTypeSpecifier.createFromIndexColorModel(ICNS1BitColorModel.INSTANCE);
case 4:
@ -103,13 +109,22 @@ public final class ICNSImageReader extends ImageReaderBase {
case 8:
return IndexedImageTypeSpecifier.createFromIndexColorModel(ICNS8BitColorModel.INSTANCE);
case 32:
return ImageTypeSpecifier.createBanded(
ColorSpace.getInstance(ColorSpace.CS_sRGB),
new int[]{0, 1, 2, 3}, createBandOffsets(header.size().width * header.size().height),
DataBuffer.TYPE_BYTE, true, false
);
if (resource.isCompressed()) {
return ImageTypeSpecifier.createBanded(
ColorSpace.getInstance(ColorSpace.CS_sRGB),
new int[]{0, 1, 2, 3}, createBandOffsets(resource.size().width * resource.size().height),
DataBuffer.TYPE_BYTE, true, false
);
}
else {
return ImageTypeSpecifier.createInterleaved(
ColorSpace.getInstance(ColorSpace.CS_sRGB),
new int[]{1, 2, 3, 0},
DataBuffer.TYPE_BYTE, true, false
);
}
default:
throw new IllegalStateException(String.format("Unknown bit depth: %d", header.depth()));
throw new IllegalStateException(String.format("Unknown bit depth: %d", resource.depth()));
}
}
@ -120,11 +135,11 @@ public final class ICNSImageReader extends ImageReaderBase {
@Override
public Iterator<ImageTypeSpecifier> getImageTypes(int imageIndex) throws IOException {
ImageTypeSpecifier rawType = getRawImageType(imageIndex);
IconHeader header = readIconHeader(imageIndex);
IconResource resource = readIconResource(imageIndex);
List<ImageTypeSpecifier> specifiers = new ArrayList<ImageTypeSpecifier>();
switch (header.depth()) {
switch (resource.depth()) {
case 1:
case 4:
case 8:
@ -134,7 +149,7 @@ public final class ICNSImageReader extends ImageReaderBase {
specifiers.add(ImageTypeSpecifier.createInterleaved(ColorSpace.getInstance(ColorSpace.CS_sRGB), new int[]{3, 2, 1, 0}, DataBuffer.TYPE_BYTE, true, false));
break;
default:
throw new IllegalStateException(String.format("Unknown bit depth: %d", header.depth()));
throw new IllegalStateException(String.format("Unknown bit depth: %d", resource.depth()));
}
specifiers.add(rawType);
@ -154,7 +169,7 @@ public final class ICNSImageReader extends ImageReaderBase {
int num = icons.size();
while (true) {
try {
readIconHeader(num++);
readIconResource(num++);
}
catch (IndexOutOfBoundsException expected) {
break;
@ -166,20 +181,20 @@ public final class ICNSImageReader extends ImageReaderBase {
@Override
public BufferedImage read(int imageIndex, ImageReadParam param) throws IOException {
IconHeader header = readIconHeader(imageIndex);
IconResource resource = readIconResource(imageIndex);
imageInput.seek(header.start + HEADER_SIZE);
imageInput.seek(resource.start + RESOURCE_HEADER_SIZE);
// Special handling of PNG/JPEG 2000 icons
if (header.isForeignFormat()) {
return readForeignFormat(param, header);
if (resource.isForeignFormat()) {
return readForeignFormat(param, resource);
}
return readICNSFormat(imageIndex, param, header);
return readICNSFormat(imageIndex, param, resource);
}
private BufferedImage readICNSFormat(final int imageIndex, final ImageReadParam param, final IconHeader header) throws IOException {
Dimension size = header.size();
private BufferedImage readICNSFormat(final int imageIndex, final ImageReadParam param, final IconResource resource) throws IOException {
Dimension size = resource.size();
int width = size.width;
int height = size.height;
@ -202,11 +217,11 @@ public final class ICNSImageReader extends ImageReaderBase {
// Read image data
byte[] data;
if (header.isCompressed()) {
if (resource.isCompressed()) {
// Only 32 bit icons may be compressed
data = new byte[width * height * header.depth() / 8];
data = new byte[width * height * resource.depth() / 8];
int packedSize = header.length - HEADER_SIZE;
int packedSize = resource.length - RESOURCE_HEADER_SIZE;
if (width >= 128 && height >= 128) {
// http://www.macdisk.com/maciconen.php:
@ -225,14 +240,14 @@ public final class ICNSImageReader extends ImageReaderBase {
}
}
else {
data = new byte[header.length - HEADER_SIZE];
data = new byte[resource.length - RESOURCE_HEADER_SIZE];
imageInput.readFully(data);
}
if (header.depth() == 1) {
if (resource.depth() == 1) {
// Binary
DataBufferByte buffer = new DataBufferByte(data, data.length / 2, 0);
WritableRaster raster = Raster.createPackedRaster(buffer, width, height, header.depth(), null);
WritableRaster raster = Raster.createPackedRaster(buffer, width, height, resource.depth(), null);
if (image.getType() == rawType.getBufferedImageType() && ((IndexColorModel) image.getColorModel()).getMapSize() == 2) {
// Preserve raw data as read (binary), discard mask
@ -241,7 +256,7 @@ public final class ICNSImageReader extends ImageReaderBase {
else {
// Convert to 32 bit ARGB
DataBufferByte maskBuffer = new DataBufferByte(data, data.length / 2, data.length / 2);
WritableRaster mask = Raster.createPackedRaster(maskBuffer, width, height, header.depth(), null);
WritableRaster mask = Raster.createPackedRaster(maskBuffer, width, height, resource.depth(), null);
Graphics2D graphics = image.createGraphics();
@ -261,10 +276,10 @@ public final class ICNSImageReader extends ImageReaderBase {
}
}
}
else if (header.depth() <= 8) {
else if (resource.depth() <= 8) {
// Indexed
DataBufferByte buffer = new DataBufferByte(data, data.length);
WritableRaster raster = Raster.createPackedRaster(buffer, width, height, header.depth(), null);
WritableRaster raster = Raster.createPackedRaster(buffer, width, height, resource.depth(), null);
if (image.getType() == rawType.getBufferedImageType()) {
// Preserve raw data as read (indexed), discard mask
@ -285,8 +300,12 @@ public final class ICNSImageReader extends ImageReaderBase {
processImageProgress(50f);
// Read mask and apply
Raster mask = readMask(findMask(header));
image.getAlphaRaster().setRect(mask);
IconResource maskResource = findMaskResource(resource);
if (maskResource != null) {
Raster mask = readMask(maskResource);
image.getAlphaRaster().setRect(mask);
}
}
}
else {
@ -294,14 +313,35 @@ public final class ICNSImageReader extends ImageReaderBase {
int bandLen = data.length / 4;
DataBufferByte buffer = new DataBufferByte(data, data.length);
WritableRaster raster = Raster.createBandedRaster(buffer, width, height, width, new int[]{0, 0, 0, 0}, createBandOffsets(bandLen), null);
WritableRaster raster;
if (resource.isCompressed()) {
raster = Raster.createBandedRaster(buffer, width, height, width, new int[]{0, 0, 0, 0}, createBandOffsets(bandLen), null);
}
else {
// NOTE: Uncompressed 32bit is interleaved RGBA, not banded...
raster = Raster.createInterleavedRaster(buffer, width, height, width * 4, 4, new int[]{1, 2, 3, 0}, null);
}
image.setData(raster);
processImageProgress(75f);
// Read mask and apply
Raster mask = readMask(findMask(header));
image.getAlphaRaster().setRect(mask);
IconResource maskResource = findMaskResource(resource);
if (maskResource != null) {
Raster mask = readMask(maskResource);
image.getAlphaRaster().setRect(mask);
}
else {
// TODO: This is simply stupid. Rewrite to use no alpha instead?
byte[] solid = new byte[width * height];
Arrays.fill(solid, (byte) -1);
WritableRaster mask = Raster.createBandedRaster(new DataBufferByte(solid, solid.length), width, height, width, new int[]{0}, new int[]{0}, null);
image.getAlphaRaster().setRect(mask);
}
}
// For now: Make listener tests happy
@ -318,28 +358,52 @@ public final class ICNSImageReader extends ImageReaderBase {
return image;
}
private Raster readMask(IconHeader header) throws IOException {
Dimension size = header.size();
private Raster readMask(final IconResource resource) throws IOException {
Dimension size = resource.size();
int width = size.width;
int height = size.height;
byte[] alpha = new byte[header.length - HEADER_SIZE];
byte[] mask = new byte[width * height];
imageInput.seek(resource.start + RESOURCE_HEADER_SIZE);
imageInput.seek(header.start + HEADER_SIZE);
imageInput.readFully(alpha);
if (resource.isMaskType()) {
// 8 bit mask
imageInput.readFully(mask, 0, resource.length - RESOURCE_HEADER_SIZE);
}
else if (resource.hasMask()) {
// Embedded 1bit mask
byte[] maskData = new byte[(resource.length - RESOURCE_HEADER_SIZE) / 2];
imageInput.skipBytes(maskData.length); // Skip the 1 bit image data
imageInput.readFully(maskData);
return Raster.createBandedRaster(new DataBufferByte(alpha, alpha.length), width, height, width, new int[]{0}, new int[]{0}, null);
// Unpack 1bit mask to 8 bit
int bitPos = 0x80;
for (int i = 0, maskLength = mask.length; i < maskLength; i++) {
mask[i] = (byte) ((maskData[i / 8] & bitPos) != 0 ? 0xff : 0x00);
if ((bitPos >>= 1) == 0) {
bitPos = 0x80;
}
}
}
else {
throw new IllegalArgumentException(String.format("Not a mask resource: %s", resource));
}
return Raster.createBandedRaster(new DataBufferByte(mask, mask.length), width, height, width, new int[]{0}, new int[]{0}, null);
}
private IconHeader findMask(final IconHeader icon) throws IOException {
private IconResource findMaskResource(final IconResource iconResource) throws IOException {
// Find 8 bit mask
try {
int i = 0;
while (true) {
IconHeader mask = i < masks.size() ? masks.get(i++) : readNextIconHeader();
IconResource mask = i < masks.size() ? masks.get(i++) : readNextIconResource();
if (mask.isMask() && mask.size().equals(icon.size())) {
if (mask.isMaskType() && mask.size().equals(iconResource.size())) {
return mask;
}
}
@ -347,11 +411,18 @@ public final class ICNSImageReader extends ImageReaderBase {
catch (IndexOutOfBoundsException ignore) {
}
throw new IIOException(String.format("No mask for icon: %s", icon));
// Fall back to mask from 1 bit resource if no 8 bit mask
for (IconResource resource : icons) {
if (resource.hasMask() && resource.size().equals(iconResource.size())) {
return resource;
}
}
return null;
}
private BufferedImage readForeignFormat(final ImageReadParam param, final IconHeader header) throws IOException {
ImageInputStream stream = ImageIO.createImageInputStream(IIOUtil.createStreamAdapter(imageInput, header.length));
private BufferedImage readForeignFormat(final ImageReadParam param, final IconResource resource) throws IOException {
ImageInputStream stream = ImageIO.createImageInputStream(IIOUtil.createStreamAdapter(imageInput, resource.length));
try {
Iterator<ImageReader> readers = ImageIO.getImageReaders(stream);
@ -364,9 +435,12 @@ public final class ICNSImageReader extends ImageReaderBase {
return reader.read(0, param);
}
catch (IOException ignore) {
}
finally {
stream.seek(0);
if (stream.getFlushedPosition() <= 0) {
stream.seek(0);
}
else {
stream = ImageIO.createImageInputStream(IIOUtil.createStreamAdapter(imageInput, resource.length));
}
}
}
@ -377,7 +451,7 @@ public final class ICNSImageReader extends ImageReaderBase {
// TODO: Create JPEG 2000 reader..? :-P
throw new IIOException(String.format(
"Cannot read %s format in type '%s' icon (no reader; installed: %s)",
getForeignFormat(stream), ICNSUtil.intToStr(header.type), Arrays.toString(ImageIO.getReaderFormatNames())
getForeignFormat(stream), ICNSUtil.intToStr(resource.type), Arrays.toString(ImageIO.getReaderFormatNames())
));
}
finally {
@ -454,25 +528,19 @@ public final class ICNSImageReader extends ImageReaderBase {
}
}
private IconHeader readIconHeader(final int imageIndex) throws IOException {
private IconResource readIconResource(final int imageIndex) throws IOException {
checkBounds(imageIndex);
readeFileHeader();
while (icons.size() <= imageIndex) {
readNextIconHeader();
readNextIconResource();
}
return icons.get(imageIndex);
}
private IconHeader readNextIconHeader() throws IOException {
IconHeader lastIcon = icons.isEmpty() ? null : icons.get(icons.size() - 1);
IconHeader lastMask = masks.isEmpty() ? null : masks.get(masks.size() - 1);
long lastReadPos = Math.max(
lastIcon == null ? HEADER_SIZE : lastIcon.start + lastIcon.length,
lastMask == null ? HEADER_SIZE : lastMask.start + lastMask.length
);
private IconResource readNextIconResource() throws IOException {
long lastReadPos = lastResourceRead == null ? RESOURCE_HEADER_SIZE : lastResourceRead.start + lastResourceRead.length;
imageInput.seek(lastReadPos);
@ -480,17 +548,20 @@ public final class ICNSImageReader extends ImageReaderBase {
throw new IndexOutOfBoundsException();
}
IconHeader header = IconHeader.read(imageInput);
IconResource resource = IconResource.read(imageInput);
// System.err.println("resource: " + resource);
// Filter out special case icnV (version?), as this isn't really an icon..
if (header.isMask() || header.type == ICNS.icnV) {
masks.add(header);
lastResourceRead = resource;
// Filter out special cases like 'icnV' or 'TOC ' resources
if (resource.isMaskType()) {
masks.add(resource);
}
else {
icons.add(header);
else if (!resource.isUnknownType()) {
icons.add(resource);
}
return header;
return resource;
}
private void readeFileHeader() throws IOException {
@ -507,13 +578,13 @@ public final class ICNSImageReader extends ImageReaderBase {
}
}
// TODO: Rewrite using subclasses!
static final class IconHeader {
// TODO: Rewrite using subclasses/instances!
static final class IconResource {
private final long start;
private final int type;
private final int length;
IconHeader(long start, int type, int length) {
IconResource(long start, int type, int length) {
validate(type, length);
this.start = start;
@ -521,8 +592,8 @@ public final class ICNSImageReader extends ImageReaderBase {
this.length = length;
}
public static IconHeader read(ImageInputStream input) throws IOException {
return new IconHeader(input.getStreamPosition(), input.readInt(), input.readInt());
public static IconResource read(ImageInputStream input) throws IOException {
return new IconResource(input.getStreamPosition(), input.readInt(), input.readInt());
}
private void validate(int type, int length) {
@ -534,7 +605,7 @@ public final class ICNSImageReader extends ImageReaderBase {
validateLengthForType(type, length, 256);
break;
case ICNS.icm_:
validateLengthForType(type, length, 24);
validateLengthForType(type, length, 48);
break;
case ICNS.icm4:
validateLengthForType(type, length, 96);
@ -579,25 +650,28 @@ public final class ICNSImageReader extends ImageReaderBase {
case ICNS.ic08:
case ICNS.ic09:
case ICNS.ic10:
if (length > 0) {
if (length > RESOURCE_HEADER_SIZE) {
break;
}
throw new IllegalArgumentException(String.format("Wrong combination of icon type '%s' and length: %d", ICNSUtil.intToStr(type), length));
case ICNS.icnV:
validateLengthForType(type, length, 4);
break;
case ICNS.TOC_:
default:
throw new IllegalStateException(String.format("Unknown icon type: '%s'", ICNSUtil.intToStr(type)));
if (length > RESOURCE_HEADER_SIZE) {
break;
}
throw new IllegalStateException(String.format("Unknown icon type: '%s' length: %d", ICNSUtil.intToStr(type), length));
}
}
private void validateLengthForType(int type, int length, final int expectedLength) {
Validate.isTrue(
length == expectedLength + HEADER_SIZE, // Compute to make lengths more logical
length == expectedLength + RESOURCE_HEADER_SIZE, // Compute to make lengths more logical
String.format(
"Wrong combination of icon type '%s' and length: %d (expected: %d)",
ICNSUtil.intToStr(type), length - HEADER_SIZE, expectedLength
ICNSUtil.intToStr(type), length - RESOURCE_HEADER_SIZE, expectedLength
)
);
}
@ -677,7 +751,52 @@ public final class ICNSImageReader extends ImageReaderBase {
}
}
public boolean isMask() {
public boolean isUnknownType() {
// These should simply be skipped
switch (type) {
case ICNS.ICON:
case ICNS.ICN_:
case ICNS.icm_:
case ICNS.ics_:
case ICNS.ich_:
case ICNS.icm4:
case ICNS.ics4:
case ICNS.icl4:
case ICNS.ich4:
case ICNS.icm8:
case ICNS.ics8:
case ICNS.icl8:
case ICNS.ich8:
case ICNS.s8mk:
case ICNS.l8mk:
case ICNS.h8mk:
case ICNS.t8mk:
case ICNS.is32:
case ICNS.il32:
case ICNS.ih32:
case ICNS.it32:
case ICNS.ic08:
case ICNS.ic09:
case ICNS.ic10:
return false;
}
return true;
}
public boolean hasMask() {
switch (type) {
case ICNS.ICN_:
case ICNS.icm_:
case ICNS.ics_:
case ICNS.ich_:
return true;
}
return false;
}
public boolean isMaskType() {
switch (type) {
case ICNS.s8mk:
case ICNS.l8mk:
@ -698,7 +817,7 @@ public final class ICNSImageReader extends ImageReaderBase {
// http://www.macdisk.com/maciconen.php
// "One should check whether the data length corresponds to the theoretical length (width * height)."
Dimension size = size();
if (length != size.width * size.height) {
if (length != (size.width * size.height * depth() / 8 + RESOURCE_HEADER_SIZE)) {
return true;
}
}
@ -723,16 +842,16 @@ public final class ICNSImageReader extends ImageReaderBase {
@Override
public boolean equals(Object other) {
return other == this || other != null && other.getClass() == getClass() && isEqual((IconHeader) other);
return other == this || other != null && other.getClass() == getClass() && isEqual((IconResource) other);
}
private boolean isEqual(IconHeader other) {
private boolean isEqual(IconResource other) {
return start == other.start && type == other.type && length == other.length;
}
@Override
public String toString() {
return String.format("%s['%s' start: %d, length: %d]", getClass().getSimpleName(), ICNSUtil.intToStr(type), start, length);
return String.format("%s['%s' start: %d, length: %d%s]", getClass().getSimpleName(), ICNSUtil.intToStr(type), start, length, isCompressed() ? " (compressed)" : "");
}
}
@ -746,22 +865,50 @@ public final class ICNSImageReader extends ImageReaderBase {
requested = Integer.parseInt(args[argIndex++]);
}
File input = new File(args[argIndex++]);
int imagesRead = 0;
int imagesSkipped = 0;
ImageReader reader = new ICNSImageReader();
reader.setInput(ImageIO.createImageInputStream(input));
int start = requested != -1 ? requested : 0;
int numImages = requested != -1 ? requested + 1 : reader.getNumImages(true);
for (int i = start; i < numImages; i++) {
try {
BufferedImage image = reader.read(i);
// System.err.println("image: " + image);
showIt(image, String.format("%s - %d", input.getName(), i));
while(argIndex < args.length) {
File input = new File(args[argIndex++]);
ImageInputStream stream = ImageIO.createImageInputStream(input);
if (stream == null) {
System.err.printf("Cannot read: %s\n", input.getAbsolutePath());
continue;
}
catch (IIOException e) {
try {
reader.setInput(stream);
int start = requested != -1 ? requested : 0;
int numImages = requested != -1 ? requested + 1 : reader.getNumImages(true);
for (int i = start; i < numImages; i++) {
try {
BufferedImage image = reader.read(i);
imagesRead++;
// System.err.println("image: " + image);
showIt(image, String.format("%s - %d", input.getName(), i));
}
catch (IOException e) {
imagesSkipped++;
if (e.getMessage().contains("JPEG 2000")) {
// System.err.printf("%s: %s\n", input, e.getMessage());
}
else {
System.err.printf("%s: ", input);
e.printStackTrace();
}
}
}
}
catch (Exception e) {
System.err.printf("%s: ", input);
e.printStackTrace();
}
}
System.err.printf("Read %s images (%d skipped) in %d files\n", imagesRead, imagesSkipped, args.length);
}
private static final class ICNSBitMaskColorModel extends IndexColorModel {

View File

@ -50,10 +50,10 @@ public class ICNSImageReaderTest extends ImageReaderAbstractTestCase {
new TestData(
getClassLoaderResource("/icns/GenericJavaApp.icns"),
new Dimension(16, 16), // 1 bit + 1 bit mask
new Dimension(16, 16), new Dimension(16, 16), // 8 bit CMAP, 32 bit
new Dimension(16, 16), new Dimension(16, 16), // 8 bit CMAP, 24 bit + 8 bit mask
new Dimension(32, 32), // 1 bit + 1 bit mask
new Dimension(32, 32), new Dimension(32, 32), // 8 bit CMAP, 32 bit
new Dimension(128, 128) // 32 bit
new Dimension(32, 32), new Dimension(32, 32), // 8 bit CMAP, 24 bit + 8 bit mask
new Dimension(128, 128) // 24 bit + 8 bit mask
),
new TestData(
getClassLoaderResource("/icns/Apple Retro.icns"),
@ -61,16 +61,40 @@ public class ICNSImageReaderTest extends ImageReaderAbstractTestCase {
new Dimension(32, 32), // 24 bit + 8 bit mask
new Dimension(48, 48), // 24 bit + 8 bit mask
new Dimension(128, 128) // 24 bit + 8 bit mask
//, new Dimension(256, 256), // JPEG 2000, not readable without JAI or other JPEG 2000 support
// new Dimension(512, 512) // JPEG 2000
//, new Dimension(256, 256), // JPEG 2000 ic08, not readable without JAI or other JPEG 2000 support
// new Dimension(512, 512) // JPEG 2000 ic09
),
new TestData(
getClassLoaderResource("/icns/7zIcon.icns"), // Contains the icnV resource, that isn't an icon
getClassLoaderResource("/icns/7zIcon.icns"), // Contains the icnV resource, that isn't an icon
new Dimension(16, 16), // 24 bit + 8 bit mask
new Dimension(32, 32), // 24 bit + 8 bit mask
new Dimension(128, 128) // 24 bit + 8 bit mask
//, new Dimension(256, 256), // JPEG 2000
// new Dimension(512, 512) // JPEG 2000
//, new Dimension(256, 256), // JPEG 2000 ic08
// new Dimension(512, 512) // JPEG 2000 ic09
),
new TestData(
getClassLoaderResource("/icns/appStore.icns"), // Contains the 'TOC ' and icnV resources
new Dimension(16, 16), // 24 bit + 8 bit mask
new Dimension(32, 32), // 24 bit + 8 bit mask
new Dimension(128, 128), // 24 bit + 8 bit mask
new Dimension(256, 256), // PNG ic08
new Dimension(512, 512), // PNG ic09
new Dimension(1024, 1024) // PNG ic10
),
new TestData(
getClassLoaderResource("/icns/XLW.icns"), // No 8 bit mask for 16x16 & 32x32, test fall back to 1 bit mask
new Dimension(16, 16), // 1 bit + 1 bit mask
new Dimension(16, 16), new Dimension(16, 16), // 4 bit CMAP, 8 bit CMAP (no 8 bit mask)
new Dimension(32, 32), // 1 bit + 1 bit mask
new Dimension(32, 32), new Dimension(32, 32), // 4 bit CMAP, 8 bit CMAP (no 8 bit mask)
new Dimension(128, 128) // 24 bit + 8 bit mask
),
new TestData(
getClassLoaderResource("/icns/XMLExport.icns"), // No masks at all, uncompressed 32 bit data
new Dimension(128, 128), // 32 bit interleaved
new Dimension(48, 48), // 32 bit interleaved
new Dimension(32, 32), // 32 bit interleaved
new Dimension(16, 16) // 32 bit interleaved
)
);
}

Binary file not shown.

View File

@ -0,0 +1,5 @@
The icon files in this folder may contain copyrighted artwork. However, I believe that using them for test purposes
(without actually displaying the artwork) must be considered fair use.
If you disagree for any reason, please send me a note, and I will remove your icon from the distribution.
-- harald.kuhr@gmail.com