diff --git a/imageio/imageio-core/src/main/java/com/twelvemonkeys/imageio/color/ColorSpaces.java b/imageio/imageio-core/src/main/java/com/twelvemonkeys/imageio/color/ColorSpaces.java index c3203daf..1e5337fa 100644 --- a/imageio/imageio-core/src/main/java/com/twelvemonkeys/imageio/color/ColorSpaces.java +++ b/imageio/imageio-core/src/main/java/com/twelvemonkeys/imageio/color/ColorSpaces.java @@ -100,7 +100,8 @@ public final class ColorSpaces { * * @param profile the ICC color profile. May not be {@code null}. * @return an ICC color space - * @throws IllegalArgumentException if {@code profile} is {@code null} + * @throws IllegalArgumentException if {@code profile} is {@code null}. + * @throws java.awt.color.CMMException if {@code profile} is invalid. */ public static ICC_ColorSpace createColorSpace(final ICC_Profile profile) { Validate.notNull(profile, "profile"); diff --git a/imageio/imageio-psd/src/main/java/com/twelvemonkeys/imageio/plugins/psd/PSD.java b/imageio/imageio-psd/src/main/java/com/twelvemonkeys/imageio/plugins/psd/PSD.java index 24e3554e..82f506de 100755 --- a/imageio/imageio-psd/src/main/java/com/twelvemonkeys/imageio/plugins/psd/PSD.java +++ b/imageio/imageio-psd/src/main/java/com/twelvemonkeys/imageio/plugins/psd/PSD.java @@ -51,6 +51,7 @@ interface PSD { /** PSD Resource type identifier "8BIM" */ int RESOURCE_TYPE = ('8' << 24) + ('B' << 16) + ('I' << 8) + 'M'; + int RESOURCE_TYPE_LONG = ('8' << 24) + ('B' << 16) + ('6' << 8) + '4';; // Blending modes /** Pass through blending mode "pass"*/ @@ -689,4 +690,22 @@ interface PSD { /** Plug-In resource(s). Resources added by a plug-in. See the plug-in API found in the SDK documentation */ int RES_PLUGIN_MAX = 0x1387; + + // TODO: Better naming of these.. It's a kind of resource blocks as well.. + // "Additional Layer Information" + int LMsk = 'L' << 24 | 'M' << 16 | 's' << 8 | 'k'; + int Lr16 = 'L' << 24 | 'r' << 16 | '1' << 8 | '6'; + int Lr32 = 'L' << 24 | 'r' << 16 | '3' << 8 | '2'; + int Layr = 'L' << 24 | 'a' << 16 | 'y' << 8 | 'r'; + int Mt16 = 'M' << 24 | 't' << 16 | '1' << 8 | '6'; + int Mt32 = 'M' << 24 | 't' << 16 | '3' << 8 | '2'; + int Mtrn = 'M' << 24 | 't' << 16 | 'r' << 8 | 'n'; + int Alph = 'A' << 24 | 'l' << 16 | 'p' << 8 | 'h'; + int FMsk = 'F' << 24 | 'M' << 16 | 's' << 8 | 'k'; + int lnk2 = 'l' << 24 | 'n' << 16 | 'k' << 8 | '2'; + int FEid = 'F' << 24 | 'E' << 16 | 'i' << 8 | 'd'; + int FXid = 'F' << 24 | 'X' << 16 | 'i' << 8 | 'd'; + int PxSD = 'P' << 24 | 'x' << 16 | 'S' << 8 | 'D'; + int luni = 'l' << 24 | 'u' << 16 | 'n' << 8 | 'i'; + int lyid = 'l' << 24 | 'y' << 16 | 'i' << 8 | 'd'; } diff --git a/imageio/imageio-psd/src/main/java/com/twelvemonkeys/imageio/plugins/psd/PSDLayerInfo.java b/imageio/imageio-psd/src/main/java/com/twelvemonkeys/imageio/plugins/psd/PSDLayerInfo.java index 237ad729..7b92883c 100755 --- a/imageio/imageio-psd/src/main/java/com/twelvemonkeys/imageio/plugins/psd/PSDLayerInfo.java +++ b/imageio/imageio-psd/src/main/java/com/twelvemonkeys/imageio/plugins/psd/PSDLayerInfo.java @@ -50,7 +50,10 @@ final class PSDLayerInfo { final PSDLayerBlendMode blendMode; final PSDLayerMaskData layerMaskData; final PSDChannelSourceDestinationRange[] ranges; - final String layerName; + private final String layerName; + + private String unicodeLayerName; + private int layerId; PSDLayerInfo(final boolean largeFormat, final ImageInputStream pInput) throws IOException { top = pInput.readInt(); @@ -70,7 +73,7 @@ final class PSDLayerInfo { blendMode = new PSDLayerBlendMode(pInput); - // Length of layer mask data + // Length of layer extra data long extraDataSize = pInput.readUnsignedInt(); // Layer mask/adjustment layer data @@ -92,19 +95,78 @@ final class PSDLayerInfo { ranges[i] = new PSDChannelSourceDestinationRange(pInput, (i == 0 ? "Gray" : "Channel " + (i - 1))); } + // Layer name layerName = PSDUtil.readPascalString(pInput); - int layerNameSize = layerName.length() + 1; // Skip pad bytes for long word alignment if (layerNameSize % 4 != 0) { - int skip = layerNameSize % 4; + int skip = 4 - (layerNameSize % 4); pInput.skipBytes(skip); layerNameSize += skip; } - // TODO: Consider reading this: Adjustment layer info etc... - pInput.skipBytes(extraDataSize - layerMaskDataSize - 4 - layerBlendingDataSize - 4 - layerNameSize); + // Parse "Additional layer data" + long additionalLayerInfoStart = pInput.getStreamPosition(); + long expectedEnd = additionalLayerInfoStart + extraDataSize - layerMaskDataSize - 4 - layerBlendingDataSize - 4 - layerNameSize; + while (pInput.getStreamPosition() < expectedEnd) { + // 8BIM or 8B64 + int resourceSignature = pInput.readInt(); + + if (resourceSignature != PSD.RESOURCE_TYPE && resourceSignature != PSD.RESOURCE_TYPE_LONG) { + // Could be a corrupt document, or some new resource (type) we don't know about, + // we'll just leave it and carry on, as this is all secondary information for the reader. + break; + } + + int resourceKey = pInput.readInt(); + + // NOTE: Only SOME resources have long length fields... + boolean largeResource = resourceSignature != PSD.RESOURCE_TYPE; + long resourceLength = largeResource ? pInput.readLong() : pInput.readUnsignedInt(); + long resourceStart = pInput.getStreamPosition(); + +// System.out.printf("signature: %s 0x%08x\n", PSDUtil.intToStr(resourceSignature), resourceSignature); +// System.out.println("key: " + PSDUtil.intToStr(resourceKey)); +// System.out.println("length: " + resourceLength); + + switch (resourceKey) { + case PSD.luni: + unicodeLayerName = PSDUtil.readUnicodeString(pInput); + // There's usually a 0-pad here, but it is skipped in the general re-aligning code below + break; + + case PSD.lyid: + if (resourceLength != 4) { + throw new IIOException(String.format("Expected layerId length == 4: %d", resourceLength)); + } + layerId = pInput.readInt(); + break; + + default: + // TODO: Parse more data... + pInput.skipBytes(resourceLength); + break; + } + + // Re-align in case we got the length incorrect + if (pInput.getStreamPosition() != resourceStart + resourceLength) { + pInput.seek(resourceStart + resourceLength); + } + } + + // Re-align in case we got the length incorrect + if (pInput.getStreamPosition() != expectedEnd) { + pInput.seek(expectedEnd); + } + } + + String getLayerName() { + return unicodeLayerName != null ? unicodeLayerName : layerName; + } + + int getLayerId() { + return layerId; } @Override @@ -122,7 +184,7 @@ final class PSDLayerInfo { builder.append(", layer mask data: ").append(layerMaskData); } builder.append(", ranges: ").append(Arrays.toString(ranges)); - builder.append(", layer name: \"").append(layerName).append("\""); + builder.append(", layer name: \"").append(getLayerName()).append("\""); builder.append("]"); return builder.toString(); diff --git a/imageio/imageio-psd/src/main/java/com/twelvemonkeys/imageio/plugins/psd/PSDMetadata.java b/imageio/imageio-psd/src/main/java/com/twelvemonkeys/imageio/plugins/psd/PSDMetadata.java index cb9c83f5..f59cb0b3 100755 --- a/imageio/imageio-psd/src/main/java/com/twelvemonkeys/imageio/plugins/psd/PSDMetadata.java +++ b/imageio/imageio-psd/src/main/java/com/twelvemonkeys/imageio/plugins/psd/PSDMetadata.java @@ -375,7 +375,7 @@ public final class PSDMetadata extends AbstractMetadata { for (PSDLayerInfo psdLayerInfo : layerInfo) { // TODO: Group in layer and use sub node for blend mode? node = new IIOMetadataNode("LayerInfo"); - node.setAttribute("name", psdLayerInfo.layerName); + node.setAttribute("name", psdLayerInfo.getLayerName()); node.setAttribute("top", String.valueOf(psdLayerInfo.top)); node.setAttribute("left", String.valueOf(psdLayerInfo.left)); node.setAttribute("bottom", String.valueOf(psdLayerInfo.bottom)); diff --git a/imageio/imageio-psd/src/test/java/com/twelvemonkeys/imageio/plugins/psd/PSDImageReaderTest.java b/imageio/imageio-psd/src/test/java/com/twelvemonkeys/imageio/plugins/psd/PSDImageReaderTest.java index cc3235f5..73ca0e32 100755 --- a/imageio/imageio-psd/src/test/java/com/twelvemonkeys/imageio/plugins/psd/PSDImageReaderTest.java +++ b/imageio/imageio-psd/src/test/java/com/twelvemonkeys/imageio/plugins/psd/PSDImageReaderTest.java @@ -31,11 +31,16 @@ package com.twelvemonkeys.imageio.plugins.psd; import com.twelvemonkeys.imageio.util.ImageReaderAbstractTest; import com.twelvemonkeys.imageio.util.ProgressListenerBase; import org.junit.Test; +import org.w3c.dom.NodeList; +import javax.imageio.ImageIO; import javax.imageio.ImageReadParam; import javax.imageio.ImageReader; import javax.imageio.ImageTypeSpecifier; +import javax.imageio.metadata.IIOMetadata; +import javax.imageio.metadata.IIOMetadataNode; import javax.imageio.spi.ImageReaderSpi; +import javax.imageio.stream.ImageInputStream; import java.awt.*; import java.awt.image.BufferedImage; import java.io.IOException; @@ -385,4 +390,20 @@ public class PSDImageReaderTest extends ImageReaderAbstractTest } } } + + @Test + public void testReadUnicodeLayerName() throws IOException { + PSDImageReader imageReader = createReader(); + + try (ImageInputStream stream = ImageIO.createImageInputStream(getClassLoaderResource("/psd/long-layer-names.psd"))) { + imageReader.setInput(stream); + + IIOMetadata metadata = imageReader.getImageMetadata(0); + IIOMetadataNode root = (IIOMetadataNode) metadata.getAsTree(PSDMetadata.NATIVE_METADATA_FORMAT_NAME); + NodeList layerInfo = root.getElementsByTagName("LayerInfo"); + + assertEquals(1, layerInfo.getLength()); // Sanity + assertEquals("If_The_Layer_Name_Is_Really_Long_Oh_No_What_Do_I_Do", ((IIOMetadataNode) layerInfo.item(0)).getAttribute("name")); + } + } } \ No newline at end of file diff --git a/imageio/imageio-psd/src/test/resources/psd/long-layer-names.psd b/imageio/imageio-psd/src/test/resources/psd/long-layer-names.psd new file mode 100644 index 00000000..452d61e6 Binary files /dev/null and b/imageio/imageio-psd/src/test/resources/psd/long-layer-names.psd differ diff --git a/imageio/imageio-thumbsdb/src/main/java/com/twelvemonkeys/imageio/plugins/thumbsdb/ThumbsDBImageReader.java b/imageio/imageio-thumbsdb/src/main/java/com/twelvemonkeys/imageio/plugins/thumbsdb/ThumbsDBImageReader.java index 13152c22..6d31b19f 100644 --- a/imageio/imageio-thumbsdb/src/main/java/com/twelvemonkeys/imageio/plugins/thumbsdb/ThumbsDBImageReader.java +++ b/imageio/imageio-thumbsdb/src/main/java/com/twelvemonkeys/imageio/plugins/thumbsdb/ThumbsDBImageReader.java @@ -62,7 +62,7 @@ import java.util.SortedSet; * @see com.twelvemonkeys.io.ole2.CompoundDocument * @see Harald Kuhr * @version $Id: ThumbsDBImageReaderSpi.java,v 1.0 28.feb.2006 19:21:05 haku Exp$ */ -public class ThumbsDBImageReaderSpi extends ImageReaderSpiBase { +public final class ThumbsDBImageReaderSpi extends ImageReaderSpiBase { private ImageReaderSpi jpegProvider; /** @@ -61,7 +61,7 @@ public class ThumbsDBImageReaderSpi extends ImageReaderSpiBase { return source instanceof ImageInputStream && canDecode((ImageInputStream) source); } - public boolean canDecode(final ImageInputStream pInput) throws IOException { + boolean canDecode(final ImageInputStream pInput) throws IOException { maybeInitJPEGProvider(); // If this is a OLE 2 CompoundDocument, we could try... // TODO: How do we know it's thumbs.db format (structure), without reading quite a lot? diff --git a/imageio/imageio-tiff/src/main/java/com/twelvemonkeys/imageio/plugins/tiff/TIFFImageReader.java b/imageio/imageio-tiff/src/main/java/com/twelvemonkeys/imageio/plugins/tiff/TIFFImageReader.java index 47195b39..557ad840 100755 --- a/imageio/imageio-tiff/src/main/java/com/twelvemonkeys/imageio/plugins/tiff/TIFFImageReader.java +++ b/imageio/imageio-tiff/src/main/java/com/twelvemonkeys/imageio/plugins/tiff/TIFFImageReader.java @@ -314,7 +314,7 @@ public class TIFFImageReader extends ImageReaderBase { readIFD(imageIndex); int sampleFormat = getSampleFormat(); - int planarConfiguration = getValueAsIntWithDefault(TIFF.TAG_PLANAR_CONFIGURATION, TIFFExtension.PLANARCONFIG_PLANAR); + int planarConfiguration = getValueAsIntWithDefault(TIFF.TAG_PLANAR_CONFIGURATION, TIFFBaseline.PLANARCONFIG_CHUNKY); int interpretation = getValueAsInt(TIFF.TAG_PHOTOMETRIC_INTERPRETATION, "PhotometricInterpretation"); int samplesPerPixel = getValueAsIntWithDefault(TIFF.TAG_SAMPLES_PER_PIXEL, 1); int bitsPerSample = getBitsPerSample(); diff --git a/pom.xml b/pom.xml index 050ccf28..638444fa 100755 --- a/pom.xml +++ b/pom.xml @@ -12,6 +12,14 @@ pom Twelvemonkeys + + + The BSD License + https://github.com/haraldk/TwelveMonkeys#license + repo + + + common servlet @@ -43,8 +51,27 @@ maven-guru + + Oliver Schmidtmer + mail@trek7891.de + + contributor + + + + Jason Palmer + jpalmer@itemmaster.com + + contributor + + + + GitHub + https://github.com/haraldk/TwelveMonkeys/issues + + scm:git:https://github.com/haraldk/TwelveMonkeys scm:git:https://github.com/haraldk/TwelveMonkeys