mirror of
https://github.com/haraldk/TwelveMonkeys.git
synced 2025-08-03 11:35:29 -04:00
Revert "Work in progress for PSD metadata support:"
This reverts commit b5f6c96583a486896b5532a5785d488d56762d4b.
This commit is contained in:
parent
e8a4cc048c
commit
27553dc47a
@ -36,7 +36,6 @@ import org.jmock.core.Stub;
|
|||||||
|
|
||||||
import javax.imageio.*;
|
import javax.imageio.*;
|
||||||
import javax.imageio.event.IIOReadProgressListener;
|
import javax.imageio.event.IIOReadProgressListener;
|
||||||
import javax.imageio.metadata.IIOMetadata;
|
|
||||||
import javax.imageio.spi.IIORegistry;
|
import javax.imageio.spi.IIORegistry;
|
||||||
import javax.imageio.spi.ImageReaderSpi;
|
import javax.imageio.spi.ImageReaderSpi;
|
||||||
import javax.imageio.stream.ImageInputStream;
|
import javax.imageio.stream.ImageInputStream;
|
||||||
@ -1321,9 +1320,7 @@ public abstract class ImageReaderAbstractTestCase<T extends ImageReader> extends
|
|||||||
|
|
||||||
assertEquals(type.getColorModel(), result.getColorModel());
|
assertEquals(type.getColorModel(), result.getColorModel());
|
||||||
|
|
||||||
// The following logically tests
|
// assertEquals(type.getSampleModel(), result.getSampleModel());
|
||||||
// assertEquals(type.getSampleModel(), result.getSampleModel());
|
|
||||||
// but SampleModel does not have a proper equals method.
|
|
||||||
SampleModel expectedModel = type.getSampleModel();
|
SampleModel expectedModel = type.getSampleModel();
|
||||||
SampleModel resultModel = result.getSampleModel();
|
SampleModel resultModel = result.getSampleModel();
|
||||||
|
|
||||||
@ -1338,6 +1335,10 @@ public abstract class ImageReaderAbstractTestCase<T extends ImageReader> extends
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// public void testSetDestinationTypeIllegal() throws IOException {
|
||||||
|
// throw new UnsupportedOperationException("Method testSetDestinationTypeIllegal not implemented"); // TODO: Implement
|
||||||
|
// }
|
||||||
|
//
|
||||||
// public void testSetDestinationBands() throws IOException {
|
// public void testSetDestinationBands() throws IOException {
|
||||||
// throw new UnsupportedOperationException("Method testSetDestinationBands not implemented"); // TODO: Implement
|
// throw new UnsupportedOperationException("Method testSetDestinationBands not implemented"); // TODO: Implement
|
||||||
// }
|
// }
|
||||||
@ -1346,24 +1347,6 @@ public abstract class ImageReaderAbstractTestCase<T extends ImageReader> extends
|
|||||||
// throw new UnsupportedOperationException("Method testSetDestinationBands not implemented"); // TODO: Implement
|
// throw new UnsupportedOperationException("Method testSetDestinationBands not implemented"); // TODO: Implement
|
||||||
// }
|
// }
|
||||||
|
|
||||||
public void testProviderAndMetadataFormatNamesMatch() throws IOException {
|
|
||||||
ImageReaderSpi provider = createProvider();
|
|
||||||
|
|
||||||
ImageReader reader = createReader();
|
|
||||||
reader.setInput(getTestData().get(0).getInputStream());
|
|
||||||
|
|
||||||
IIOMetadata imageMetadata = reader.getImageMetadata(0);
|
|
||||||
if (imageMetadata != null) {
|
|
||||||
assertEquals(provider.getNativeImageMetadataFormatName(), imageMetadata.getNativeMetadataFormatName());
|
|
||||||
}
|
|
||||||
|
|
||||||
IIOMetadata streamMetadata = reader.getStreamMetadata();
|
|
||||||
if (streamMetadata != null) {
|
|
||||||
assertEquals(provider.getNativeStreamMetadataFormatName(), streamMetadata.getNativeMetadataFormatName());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
protected URL getClassLoaderResource(final String pName) {
|
protected URL getClassLoaderResource(final String pName) {
|
||||||
return getClass().getResource(pName);
|
return getClass().getResource(pName);
|
||||||
}
|
}
|
||||||
|
@ -47,7 +47,7 @@ class PSDColorData {
|
|||||||
final byte[] mColors;
|
final byte[] mColors;
|
||||||
private IndexColorModel mColorModel;
|
private IndexColorModel mColorModel;
|
||||||
|
|
||||||
PSDColorData(final ImageInputStream pInput) throws IOException {
|
PSDColorData(ImageInputStream pInput) throws IOException {
|
||||||
int length = pInput.readInt();
|
int length = pInput.readInt();
|
||||||
if (length == 0) {
|
if (length == 0) {
|
||||||
throw new IIOException("No palette information in PSD");
|
throw new IIOException("No palette information in PSD");
|
||||||
@ -72,7 +72,7 @@ class PSDColorData {
|
|||||||
return mColorModel;
|
return mColorModel;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int[] toInterleavedRGB(final byte[] pColors) {
|
private int[] toInterleavedRGB(byte[] pColors) {
|
||||||
int[] rgb = new int[pColors.length / 3];
|
int[] rgb = new int[pColors.length / 3];
|
||||||
|
|
||||||
for (int i = 0; i < rgb.length; i++) {
|
for (int i = 0; i < rgb.length; i++) {
|
||||||
|
@ -40,7 +40,7 @@ import java.io.IOException;
|
|||||||
* @version $Id: PSDResolutionInfo.java,v 1.0 May 2, 2008 3:58:19 PM haraldk Exp$
|
* @version $Id: PSDResolutionInfo.java,v 1.0 May 2, 2008 3:58:19 PM haraldk Exp$
|
||||||
*/
|
*/
|
||||||
class PSDDisplayInfo extends PSDImageResource {
|
class PSDDisplayInfo extends PSDImageResource {
|
||||||
// TODO: Size of this struct should be 14.. Does not compute... Something bogus here
|
// TODO: Size of this struct should be 14.. Does not compute...
|
||||||
//typedef _DisplayInfo
|
//typedef _DisplayInfo
|
||||||
//{
|
//{
|
||||||
// WORD ColorSpace;
|
// WORD ColorSpace;
|
||||||
@ -67,20 +67,20 @@ class PSDDisplayInfo extends PSDImageResource {
|
|||||||
|
|
||||||
// long left = mSize;
|
// long left = mSize;
|
||||||
// while (left > 0) {
|
// while (left > 0) {
|
||||||
mColorSpace = pInput.readShort();
|
mColorSpace = pInput.readShort();
|
||||||
|
|
||||||
// Color[4]...?
|
// Color[4]...?
|
||||||
mColors = new short[4];
|
mColors = new short[4];
|
||||||
mColors[0] = pInput.readShort();
|
mColors[0] = pInput.readShort();
|
||||||
mColors[1] = pInput.readShort();
|
mColors[1] = pInput.readShort();
|
||||||
mColors[2] = pInput.readShort();
|
mColors[2] = pInput.readShort();
|
||||||
mColors[3] = pInput.readShort();
|
mColors[3] = pInput.readShort();
|
||||||
|
|
||||||
mOpacity = pInput.readShort();
|
mOpacity = pInput.readShort();
|
||||||
|
|
||||||
mKind = pInput.readByte();
|
mKind = pInput.readByte();
|
||||||
|
|
||||||
pInput.readByte(); // Pad
|
pInput.readByte(); // Pad
|
||||||
// left -= 14;
|
// left -= 14;
|
||||||
// }
|
// }
|
||||||
pInput.skipBytes(mSize - 14);
|
pInput.skipBytes(mSize - 14);
|
||||||
|
@ -35,7 +35,7 @@ final class PSDEXIF1Data extends PSDImageResource {
|
|||||||
protected void readData(final ImageInputStream pInput) throws IOException {
|
protected void readData(final ImageInputStream pInput) throws IOException {
|
||||||
// This is in essence an embedded TIFF file.
|
// This is in essence an embedded TIFF file.
|
||||||
// TODO: Extract TIFF parsing to more general purpose package
|
// TODO: Extract TIFF parsing to more general purpose package
|
||||||
// TODO: Instead, read the byte data, store for later parsing (or store offset, and read on request)
|
// TODO: Instead, read the byte data, store for later parsing
|
||||||
MemoryCacheImageInputStream stream = new MemoryCacheImageInputStream(IIOUtil.createStreamAdapter(pInput, mSize));
|
MemoryCacheImageInputStream stream = new MemoryCacheImageInputStream(IIOUtil.createStreamAdapter(pInput, mSize));
|
||||||
|
|
||||||
byte[] bom = new byte[2];
|
byte[] bom = new byte[2];
|
||||||
|
@ -31,15 +31,8 @@ package com.twelvemonkeys.imageio.plugins.psd;
|
|||||||
import com.twelvemonkeys.image.ImageUtil;
|
import com.twelvemonkeys.image.ImageUtil;
|
||||||
import com.twelvemonkeys.imageio.ImageReaderBase;
|
import com.twelvemonkeys.imageio.ImageReaderBase;
|
||||||
import com.twelvemonkeys.imageio.util.IndexedImageTypeSpecifier;
|
import com.twelvemonkeys.imageio.util.IndexedImageTypeSpecifier;
|
||||||
import com.twelvemonkeys.xml.XMLSerializer;
|
|
||||||
import org.w3c.dom.Node;
|
|
||||||
|
|
||||||
import javax.imageio.IIOException;
|
import javax.imageio.*;
|
||||||
import javax.imageio.ImageIO;
|
|
||||||
import javax.imageio.ImageReadParam;
|
|
||||||
import javax.imageio.ImageTypeSpecifier;
|
|
||||||
import javax.imageio.metadata.IIOMetadata;
|
|
||||||
import javax.imageio.metadata.IIOMetadataFormatImpl;
|
|
||||||
import javax.imageio.spi.ImageReaderSpi;
|
import javax.imageio.spi.ImageReaderSpi;
|
||||||
import javax.imageio.stream.ImageInputStream;
|
import javax.imageio.stream.ImageInputStream;
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
@ -50,11 +43,13 @@ import java.awt.image.*;
|
|||||||
import java.io.DataInputStream;
|
import java.io.DataInputStream;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.*;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ImageReader for Adobe Photoshop Document (PSD) format.
|
* ImageReader for Adobe Photoshop Document format.
|
||||||
*
|
*
|
||||||
* @see <a href="http://www.fileformat.info/format/psd/egff.htm">Adobe Photoshop File Format Summary<a>
|
* @see <a href="http://www.fileformat.info/format/psd/egff.htm">Adobe Photoshop File Format Summary<a>
|
||||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||||
@ -62,7 +57,7 @@ import java.util.List;
|
|||||||
* @version $Id: PSDImageReader.java,v 1.0 Apr 29, 2008 4:45:52 PM haraldk Exp$
|
* @version $Id: PSDImageReader.java,v 1.0 Apr 29, 2008 4:45:52 PM haraldk Exp$
|
||||||
*/
|
*/
|
||||||
// TODO: Implement ImageIO meta data interface
|
// TODO: Implement ImageIO meta data interface
|
||||||
// TODO: API for reading separate layers
|
// TODO: Allow reading separate (or some?) layers
|
||||||
// TODO: Consider Romain Guy's Java 2D implementation of PS filters for the blending modes in layers
|
// TODO: Consider Romain Guy's Java 2D implementation of PS filters for the blending modes in layers
|
||||||
// http://www.curious-creature.org/2006/09/20/new-blendings-modes-for-java2d/
|
// http://www.curious-creature.org/2006/09/20/new-blendings-modes-for-java2d/
|
||||||
// See http://www.codeproject.com/KB/graphics/PSDParser.aspx
|
// See http://www.codeproject.com/KB/graphics/PSDParser.aspx
|
||||||
@ -120,7 +115,7 @@ public class PSDImageReader extends ImageReaderBase {
|
|||||||
);
|
);
|
||||||
|
|
||||||
case PSD.COLOR_MODE_INDEXED:
|
case PSD.COLOR_MODE_INDEXED:
|
||||||
// TODO: 16 bit indexed?! Does it exist?
|
// TODO: 16 bit indexed?!
|
||||||
if (mHeader.mChannels == 1 && mHeader.mBits == 8) {
|
if (mHeader.mChannels == 1 && mHeader.mBits == 8) {
|
||||||
return IndexedImageTypeSpecifier.createFromIndexColorModel(mColorData.getIndexColorModel());
|
return IndexedImageTypeSpecifier.createFromIndexColorModel(mColorData.getIndexColorModel());
|
||||||
}
|
}
|
||||||
@ -189,11 +184,6 @@ public class PSDImageReader extends ImageReaderBase {
|
|||||||
throw new IIOException(
|
throw new IIOException(
|
||||||
String.format("Unsupported channel count/bit depth for CMYK PSD: %d channels/%d bits", mHeader.mChannels, mHeader.mBits)
|
String.format("Unsupported channel count/bit depth for CMYK PSD: %d channels/%d bits", mHeader.mChannels, mHeader.mBits)
|
||||||
);
|
);
|
||||||
|
|
||||||
case PSD.COLOR_MODE_MULTICHANNEL:
|
|
||||||
// TODO: Implement
|
|
||||||
case PSD.COLOR_MODE_LAB:
|
|
||||||
// TODO: Implement
|
|
||||||
default:
|
default:
|
||||||
throw new IIOException(
|
throw new IIOException(
|
||||||
String.format("Unsupported PSD MODE: %s (%d channels/%d bits)", mHeader.mMode, mHeader.mChannels, mHeader.mBits)
|
String.format("Unsupported PSD MODE: %s (%d channels/%d bits)", mHeader.mMode, mHeader.mChannels, mHeader.mBits)
|
||||||
@ -414,7 +404,7 @@ public class PSDImageReader extends ImageReaderBase {
|
|||||||
read16bitChannel(c, mHeader.mChannels, data16, interleavedBands, bandOffset, pSourceCM, row16, pSource, pDest, pXSub, pYSub, mHeader.mWidth, mHeader.mHeight, pByteCounts, c * mHeader.mHeight, pCompression == PSD.COMPRESSION_RLE);
|
read16bitChannel(c, mHeader.mChannels, data16, interleavedBands, bandOffset, pSourceCM, row16, pSource, pDest, pXSub, pYSub, mHeader.mWidth, mHeader.mHeight, pByteCounts, c * mHeader.mHeight, pCompression == PSD.COMPRESSION_RLE);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new IIOException(String.format("Unknown PSD bit depth: %s", mHeader.mBits));
|
throw new IIOException("Unknown PSD bit depth: " + mHeader.mBits);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (abortRequested()) {
|
if (abortRequested()) {
|
||||||
@ -546,7 +536,6 @@ public class PSDImageReader extends ImageReaderBase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings({"UnusedDeclaration"})
|
|
||||||
private void read1bitChannel(final int pChannel, final int pChannelCount,
|
private void read1bitChannel(final int pChannel, final int pChannelCount,
|
||||||
final byte[] pData, final int pBands, final int pBandOffset,
|
final byte[] pData, final int pBands, final int pBandOffset,
|
||||||
final ColorModel pSourceColorModel,
|
final ColorModel pSourceColorModel,
|
||||||
@ -708,7 +697,6 @@ public class PSDImageReader extends ImageReaderBase {
|
|||||||
mColorData = new PSDColorData(mImageInput);
|
mColorData = new PSDColorData(mImageInput);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// TODO: We need to store the duotone spec if we decide to create a writer...
|
|
||||||
// Skip color mode data for other modes
|
// Skip color mode data for other modes
|
||||||
long length = mImageInput.readUnsignedInt();
|
long length = mImageInput.readUnsignedInt();
|
||||||
mImageInput.skipBytes(length);
|
mImageInput.skipBytes(length);
|
||||||
@ -720,7 +708,6 @@ public class PSDImageReader extends ImageReaderBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Flags or list of interesting resources to parse
|
// TODO: Flags or list of interesting resources to parse
|
||||||
// TODO: Obey ignoreMetadata
|
|
||||||
private void readImageResources(final boolean pParseData) throws IOException {
|
private void readImageResources(final boolean pParseData) throws IOException {
|
||||||
// TODO: Avoid unnecessary stream repositioning
|
// TODO: Avoid unnecessary stream repositioning
|
||||||
long pos = mImageInput.getFlushedPosition();
|
long pos = mImageInput.getFlushedPosition();
|
||||||
@ -748,8 +735,6 @@ public class PSDImageReader extends ImageReaderBase {
|
|||||||
mImageInput.seek(pos + length + 4);
|
mImageInput.seek(pos + length + 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Flags or list of interesting resources to parse
|
|
||||||
// TODO: Obey ignoreMetadata
|
|
||||||
private void readLayerAndMaskInfo(final boolean pParseData) throws IOException {
|
private void readLayerAndMaskInfo(final boolean pParseData) throws IOException {
|
||||||
// TODO: Make sure we are positioned correctly
|
// TODO: Make sure we are positioned correctly
|
||||||
long length = mImageInput.readUnsignedInt();
|
long length = mImageInput.readUnsignedInt();
|
||||||
@ -782,7 +767,7 @@ public class PSDImageReader extends ImageReaderBase {
|
|||||||
// TODO: If not explicitly needed, skip layers...
|
// TODO: If not explicitly needed, skip layers...
|
||||||
BufferedImage layer = readLayerData(layerInfo, raw, imageType);
|
BufferedImage layer = readLayerData(layerInfo, raw, imageType);
|
||||||
|
|
||||||
// TODO: Don't show! Store in meta data somehow...
|
// TODO: Don't show! Store in metadata somehow...
|
||||||
if (layer != null) {
|
if (layer != null) {
|
||||||
showIt(layer, layerInfo.mLayerName + " " + layerInfo.mBlendMode.toString());
|
showIt(layer, layerInfo.mLayerName + " " + layerInfo.mBlendMode.toString());
|
||||||
}
|
}
|
||||||
@ -810,7 +795,6 @@ public class PSDImageReader extends ImageReaderBase {
|
|||||||
mImageInput.skipBytes(toSkip);
|
mImageInput.skipBytes(toSkip);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// Skip entire layer and mask section
|
|
||||||
mImageInput.skipBytes(length);
|
mImageInput.skipBytes(length);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -854,7 +838,7 @@ public class PSDImageReader extends ImageReaderBase {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// 0 = red, 1 = green, etc
|
// 0 = red, 1 = green, etc
|
||||||
// -1 = transparency mask; -2 = user supplied layer mask
|
// ?1 = transparency mask; ?2 = user supplied layer mask
|
||||||
int c = channelInfo.mChannelId == -1 ? pLayerInfo.mChannelInfo.length - 1 : channelInfo.mChannelId;
|
int c = channelInfo.mChannelId == -1 ? pLayerInfo.mChannelInfo.length - 1 : channelInfo.mChannelId;
|
||||||
|
|
||||||
// NOTE: For layers, byte counts are written per channel, while for the composite data
|
// NOTE: For layers, byte counts are written per channel, while for the composite data
|
||||||
@ -908,7 +892,7 @@ public class PSDImageReader extends ImageReaderBase {
|
|||||||
read16bitChannel(c, imageType.getNumBands(), data16, interleavedBands, bandOffset, sourceCM, row16, area, area, xsub, ysub, width, height, byteCounts, 0, compression == PSD.COMPRESSION_RLE);
|
read16bitChannel(c, imageType.getNumBands(), data16, interleavedBands, bandOffset, sourceCM, row16, area, area, xsub, ysub, width, height, byteCounts, 0, compression == PSD.COMPRESSION_RLE);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new IIOException(String.format("Unknown PSD bit depth: %s", mHeader.mBits));
|
throw new IIOException("Unknown PSD bit depth: " + mHeader.mBits);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (abortRequested()) {
|
if (abortRequested()) {
|
||||||
@ -947,57 +931,6 @@ public class PSDImageReader extends ImageReaderBase {
|
|||||||
return pOriginal;
|
return pOriginal;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Layer support
|
|
||||||
// TODO: For now, leave as Metadata
|
|
||||||
|
|
||||||
/*
|
|
||||||
int getNumLayers(int pImageIndex) throws IOException;
|
|
||||||
|
|
||||||
boolean hasLayers(int pImageIndex) throws IOException;
|
|
||||||
|
|
||||||
BufferedImage readLayer(int pImageIndex, int pLayerIndex, ImageReadParam pParam) throws IOException;
|
|
||||||
|
|
||||||
int getLayerWidth(int pImageIndex, int pLayerIndex) throws IOException;
|
|
||||||
|
|
||||||
int getLayerHeight(int pImageIndex, int pLayerIndex) throws IOException;
|
|
||||||
|
|
||||||
// ?
|
|
||||||
Point getLayerOffset(int pImageIndex, int pLayerIndex) throws IOException;
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
/// Metadata support
|
|
||||||
// TODO
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public IIOMetadata getStreamMetadata() throws IOException {
|
|
||||||
// null might be appropriate here
|
|
||||||
// "For image formats that contain a single image, only image metadata is used."
|
|
||||||
return super.getStreamMetadata();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public IIOMetadata getImageMetadata(final int pImageIndex) throws IOException {
|
|
||||||
// TODO: Implement
|
|
||||||
checkBounds(pImageIndex);
|
|
||||||
|
|
||||||
readHeader();
|
|
||||||
readImageResources(true);
|
|
||||||
readLayerAndMaskInfo(true);
|
|
||||||
|
|
||||||
PSDMetadata metadata = new PSDMetadata();
|
|
||||||
metadata.mHeader = mHeader;
|
|
||||||
metadata.mColorData = mColorData;
|
|
||||||
metadata.mImageResources = mImageResources;
|
|
||||||
return metadata;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public IIOMetadata getImageMetadata(final int imageIndex, final String formatName, final Set<String> nodeNames) throws IOException {
|
|
||||||
// TODO: This might make sense, as there's loads of meta data in the file
|
|
||||||
return super.getImageMetadata(imageIndex, formatName, nodeNames);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Thumbnail support
|
/// Thumbnail support
|
||||||
@Override
|
@Override
|
||||||
public boolean readerSupportsThumbnails() {
|
public boolean readerSupportsThumbnails() {
|
||||||
@ -1032,13 +965,13 @@ public class PSDImageReader extends ImageReaderBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getNumThumbnails(final int pIndex) throws IOException {
|
public int getNumThumbnails(int pIndex) throws IOException {
|
||||||
List<PSDThumbnail> thumbnails = getThumbnailResources(pIndex);
|
List<PSDThumbnail> thumbnails = getThumbnailResources(pIndex);
|
||||||
|
|
||||||
return thumbnails == null ? 0 : thumbnails.size();
|
return thumbnails == null ? 0 : thumbnails.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
private PSDThumbnail getThumbnailResource(final int pImageIndex, final int pThumbnailIndex) throws IOException {
|
private PSDThumbnail getThumbnailResource(int pImageIndex, int pThumbnailIndex) throws IOException {
|
||||||
List<PSDThumbnail> thumbnails = getThumbnailResources(pImageIndex);
|
List<PSDThumbnail> thumbnails = getThumbnailResources(pImageIndex);
|
||||||
|
|
||||||
if (thumbnails == null) {
|
if (thumbnails == null) {
|
||||||
@ -1049,17 +982,17 @@ public class PSDImageReader extends ImageReaderBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getThumbnailWidth(final int pImageIndex, final int pThumbnailIndex) throws IOException {
|
public int getThumbnailWidth(int pImageIndex, int pThumbnailIndex) throws IOException {
|
||||||
return getThumbnailResource(pImageIndex, pThumbnailIndex).getWidth();
|
return getThumbnailResource(pImageIndex, pThumbnailIndex).getWidth();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getThumbnailHeight(final int pImageIndex, final int pThumbnailIndex) throws IOException {
|
public int getThumbnailHeight(int pImageIndex, int pThumbnailIndex) throws IOException {
|
||||||
return getThumbnailResource(pImageIndex, pThumbnailIndex).getHeight();
|
return getThumbnailResource(pImageIndex, pThumbnailIndex).getHeight();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BufferedImage readThumbnail(final int pImageIndex, final int pThumbnailIndex) throws IOException {
|
public BufferedImage readThumbnail(int pImageIndex, int pThumbnailIndex) throws IOException {
|
||||||
// TODO: Thumbnail progress listeners...
|
// TODO: Thumbnail progress listeners...
|
||||||
PSDThumbnail thumbnail = getThumbnailResource(pImageIndex, pThumbnailIndex);
|
PSDThumbnail thumbnail = getThumbnailResource(pImageIndex, pThumbnailIndex);
|
||||||
|
|
||||||
@ -1068,7 +1001,6 @@ public class PSDImageReader extends ImageReaderBase {
|
|||||||
processThumbnailStarted(pImageIndex, pThumbnailIndex);
|
processThumbnailStarted(pImageIndex, pThumbnailIndex);
|
||||||
processThumbnailComplete();
|
processThumbnailComplete();
|
||||||
|
|
||||||
// TODO: Returning a cached mutable thumbnail is not really safe...
|
|
||||||
return thumbnail.getThumbnail();
|
return thumbnail.getThumbnail();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1120,17 +1052,12 @@ public class PSDImageReader extends ImageReaderBase {
|
|||||||
// System.out.println("imageReader.mHeader: " + imageReader.mHeader);
|
// System.out.println("imageReader.mHeader: " + imageReader.mHeader);
|
||||||
|
|
||||||
imageReader.readImageResources(true);
|
imageReader.readImageResources(true);
|
||||||
System.out.println("imageReader.mImageResources: " + imageReader.mImageResources);
|
// System.out.println("imageReader.mImageResources: " + imageReader.mImageResources);
|
||||||
|
|
||||||
imageReader.readLayerAndMaskInfo(true);
|
imageReader.readLayerAndMaskInfo(true);
|
||||||
System.out.println("imageReader.mLayerInfo: " + imageReader.mLayerInfo);
|
System.out.println("imageReader.mLayerInfo: " + imageReader.mLayerInfo);
|
||||||
// System.out.println("imageReader.mGlobalLayerMask: " + imageReader.mGlobalLayerMask);
|
// System.out.println("imageReader.mGlobalLayerMask: " + imageReader.mGlobalLayerMask);
|
||||||
|
|
||||||
IIOMetadata metadata = imageReader.getImageMetadata(0);
|
|
||||||
Node node = metadata.getAsTree(IIOMetadataFormatImpl.standardMetadataFormatName);
|
|
||||||
XMLSerializer serializer = new XMLSerializer(System.out, System.getProperty("file.encoding"));
|
|
||||||
serializer.serialize(node, true);
|
|
||||||
|
|
||||||
if (imageReader.hasThumbnails(0)) {
|
if (imageReader.hasThumbnails(0)) {
|
||||||
int thumbnails = imageReader.getNumThumbnails(0);
|
int thumbnails = imageReader.getNumThumbnails(0);
|
||||||
for (int i = 0; i < thumbnails; i++) {
|
for (int i = 0; i < thumbnails; i++) {
|
||||||
|
@ -67,12 +67,8 @@ public class PSDImageReaderSpi extends ImageReaderSpi {
|
|||||||
STANDARD_INPUT_TYPE,
|
STANDARD_INPUT_TYPE,
|
||||||
// new String[]{"com.twelvemkonkeys.imageio.plugins.psd.PSDImageWriterSpi"},
|
// new String[]{"com.twelvemkonkeys.imageio.plugins.psd.PSDImageWriterSpi"},
|
||||||
null,
|
null,
|
||||||
true, // supports standard stream metadata
|
true, null, null, null, null,
|
||||||
null, null, // native stream format name and class
|
true, null, null, null, null
|
||||||
null, null, // extra stream formats
|
|
||||||
true, // supports standard image metadata
|
|
||||||
PSDMetadata.NATIVE_METADATA_FORMAT_NAME, PSDMetadata.NATIVE_METADATA_FORMAT_CLASS_NAME,
|
|
||||||
null, null // extra image metadata formats
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,446 +0,0 @@
|
|||||||
package com.twelvemonkeys.imageio.plugins.psd;
|
|
||||||
|
|
||||||
import com.twelvemonkeys.lang.StringUtil;
|
|
||||||
import org.w3c.dom.Node;
|
|
||||||
|
|
||||||
import javax.imageio.metadata.IIOInvalidTreeException;
|
|
||||||
import javax.imageio.metadata.IIOMetadata;
|
|
||||||
import javax.imageio.metadata.IIOMetadataFormatImpl;
|
|
||||||
import javax.imageio.metadata.IIOMetadataNode;
|
|
||||||
import java.awt.image.IndexColorModel;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* PSDMetadata
|
|
||||||
*
|
|
||||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
|
||||||
* @author last modified by $Author: haraldk$
|
|
||||||
* @version $Id: PSDMetadata.java,v 1.0 Nov 4, 2009 5:28:12 PM haraldk Exp$
|
|
||||||
*/
|
|
||||||
public final class PSDMetadata extends IIOMetadata implements Cloneable {
|
|
||||||
|
|
||||||
static final String NATIVE_METADATA_FORMAT_NAME = "com_twelvemonkeys_imageio_psd_1.0";
|
|
||||||
static final String NATIVE_METADATA_FORMAT_CLASS_NAME = "com.twelvemonkeys.imageio.plugins.psd.PSDMetadataFormat";
|
|
||||||
|
|
||||||
// TODO: Move fields from PSDImageReader (header, color map, resources, etc) here
|
|
||||||
PSDHeader mHeader;
|
|
||||||
PSDColorData mColorData;
|
|
||||||
List<PSDImageResource> mImageResources;
|
|
||||||
PSDGlobalLayerMask mGlobalLayerMask;
|
|
||||||
List<PSDLayerInfo> mLayerInfo;
|
|
||||||
|
|
||||||
protected PSDMetadata() {
|
|
||||||
// TODO: Allow XMP, EXIF and IPTC as extra formats?
|
|
||||||
super(true, NATIVE_METADATA_FORMAT_NAME, NATIVE_METADATA_FORMAT_CLASS_NAME, null, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isReadOnly() {
|
|
||||||
// TODO: Extract to abstract metadata impl class?
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Node getAsTree(final String pFormatName) {
|
|
||||||
validateFormatName(pFormatName);
|
|
||||||
|
|
||||||
if (pFormatName.equals(nativeMetadataFormatName)) {
|
|
||||||
return getNativeTree();
|
|
||||||
}
|
|
||||||
else if (pFormatName.equals(IIOMetadataFormatImpl.standardMetadataFormatName)) {
|
|
||||||
return getStandardTree();
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new AssertionError("Unreachable");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void mergeTree(final String pFormatName, final Node pRoot) throws IIOInvalidTreeException {
|
|
||||||
// TODO: Extract to abstract metadata impl class?
|
|
||||||
assertMutable();
|
|
||||||
|
|
||||||
validateFormatName(pFormatName);
|
|
||||||
|
|
||||||
if (!pRoot.getNodeName().equals(nativeMetadataFormatName)) {
|
|
||||||
throw new IIOInvalidTreeException("Root must be " + nativeMetadataFormatName, pRoot);
|
|
||||||
}
|
|
||||||
|
|
||||||
Node node = pRoot.getFirstChild();
|
|
||||||
while (node != null) {
|
|
||||||
// TODO: Merge values from node into this
|
|
||||||
|
|
||||||
// Move to the next sibling
|
|
||||||
node = node.getNextSibling();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void reset() {
|
|
||||||
// TODO: Extract to abstract metadata impl class?
|
|
||||||
assertMutable();
|
|
||||||
|
|
||||||
throw new UnsupportedOperationException("Method reset not implemented"); // TODO: Implement
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Extract to abstract metadata impl class?
|
|
||||||
private void assertMutable() {
|
|
||||||
if (isReadOnly()) {
|
|
||||||
throw new IllegalStateException("Metadata is read-only");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Extract to abstract metadata impl class?
|
|
||||||
private void validateFormatName(final String pFormatName) {
|
|
||||||
String[] metadataFormatNames = getMetadataFormatNames();
|
|
||||||
|
|
||||||
if (metadataFormatNames != null) {
|
|
||||||
for (String metadataFormatName : metadataFormatNames) {
|
|
||||||
if (metadataFormatName.equals(pFormatName)) {
|
|
||||||
return; // Found, we're ok!
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new IllegalArgumentException(
|
|
||||||
String.format("Bad format name: \"%s\". Expected one of %s", pFormatName, Arrays.toString(metadataFormatNames))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object clone() {
|
|
||||||
// TODO: Make it a deep clone
|
|
||||||
try {
|
|
||||||
return super.clone();
|
|
||||||
}
|
|
||||||
catch (CloneNotSupportedException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private Node getNativeTree() {
|
|
||||||
throw new UnsupportedOperationException("getNativeTree");
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Standard format support
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected IIOMetadataNode getStandardChromaNode() {
|
|
||||||
IIOMetadataNode chroma_node = new IIOMetadataNode("Chroma");
|
|
||||||
IIOMetadataNode node; // scratch node
|
|
||||||
|
|
||||||
node = new IIOMetadataNode("ColorSpaceType");
|
|
||||||
String cs;
|
|
||||||
switch (mHeader.mMode) {
|
|
||||||
case PSD.COLOR_MODE_MONOCHROME:
|
|
||||||
case PSD.COLOR_MODE_GRAYSCALE:
|
|
||||||
case PSD.COLOR_MODE_DUOTONE: // Rationale is spec says treat as gray...
|
|
||||||
cs = "GRAY";
|
|
||||||
break;
|
|
||||||
case PSD.COLOR_MODE_RGB:
|
|
||||||
case PSD.COLOR_MODE_INDEXED:
|
|
||||||
cs = "RGB";
|
|
||||||
break;
|
|
||||||
case PSD.COLOR_MODE_CMYK:
|
|
||||||
cs = "CMYK";
|
|
||||||
break;
|
|
||||||
case PSD.COLOR_MODE_MULTICHANNEL:
|
|
||||||
// TODO: FixMe
|
|
||||||
cs = "???";
|
|
||||||
break;
|
|
||||||
case PSD.COLOR_MODE_LAB:
|
|
||||||
cs = "Lab";
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw new AssertionError("Unreachable");
|
|
||||||
}
|
|
||||||
node.setAttribute("name", cs);
|
|
||||||
chroma_node.appendChild(node);
|
|
||||||
|
|
||||||
// TODO: Channels might be 5 for RGB + A + Mask...
|
|
||||||
node = new IIOMetadataNode("NumChannels");
|
|
||||||
node.setAttribute("value", Integer.toString(mHeader.mChannels));
|
|
||||||
chroma_node.appendChild(node);
|
|
||||||
|
|
||||||
// if (gAMA_present) {
|
|
||||||
// node = new IIOMetadataNode("Gamma");
|
|
||||||
// node.setAttribute("value", Float.toString(gAMA_gamma*1.0e-5F));
|
|
||||||
// chroma_node.appendChild(node);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// TODO: Check if this is correct with bitmap (monchrome)
|
|
||||||
node = new IIOMetadataNode("BlackIsZero");
|
|
||||||
node.setAttribute("value", "true");
|
|
||||||
chroma_node.appendChild(node);
|
|
||||||
|
|
||||||
if (mHeader.mMode == PSD.COLOR_MODE_INDEXED) {
|
|
||||||
node = new IIOMetadataNode("Palette");
|
|
||||||
|
|
||||||
IndexColorModel cm = mColorData.getIndexColorModel();
|
|
||||||
for (int i = 0; i < cm.getMapSize(); i++) {
|
|
||||||
IIOMetadataNode entry =
|
|
||||||
new IIOMetadataNode("PaletteEntry");
|
|
||||||
entry.setAttribute("index", Integer.toString(i));
|
|
||||||
entry.setAttribute("red",
|
|
||||||
Integer.toString(cm.getRed(i)));
|
|
||||||
entry.setAttribute("green",
|
|
||||||
Integer.toString(cm.getGreen(i)));
|
|
||||||
entry.setAttribute("blue",
|
|
||||||
Integer.toString(cm.getBlue(i)));
|
|
||||||
|
|
||||||
node.appendChild(entry);
|
|
||||||
}
|
|
||||||
chroma_node.appendChild(node);
|
|
||||||
}
|
|
||||||
|
|
||||||
// if (bKGD_present) {
|
|
||||||
// if (bKGD_colorType == PNGImageReader.PNG_COLOR_PALETTE) {
|
|
||||||
// node = new IIOMetadataNode("BackgroundIndex");
|
|
||||||
// node.setAttribute("value", Integer.toString(bKGD_index));
|
|
||||||
// } else {
|
|
||||||
// node = new IIOMetadataNode("BackgroundColor");
|
|
||||||
// int r, g, b;
|
|
||||||
//
|
|
||||||
// if (bKGD_colorType == PNGImageReader.PNG_COLOR_GRAY) {
|
|
||||||
// r = g = b = bKGD_gray;
|
|
||||||
// } else {
|
|
||||||
// r = bKGD_red;
|
|
||||||
// g = bKGD_green;
|
|
||||||
// b = bKGD_blue;
|
|
||||||
// }
|
|
||||||
// node.setAttribute("red", Integer.toString(r));
|
|
||||||
// node.setAttribute("green", Integer.toString(g));
|
|
||||||
// node.setAttribute("blue", Integer.toString(b));
|
|
||||||
// }
|
|
||||||
// chroma_node.appendChild(node);
|
|
||||||
// }
|
|
||||||
|
|
||||||
return chroma_node;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected IIOMetadataNode getStandardCompressionNode() {
|
|
||||||
IIOMetadataNode compression_node = new IIOMetadataNode("Compression");
|
|
||||||
IIOMetadataNode node; // scratch node
|
|
||||||
|
|
||||||
node = new IIOMetadataNode("CompressionTypeName");
|
|
||||||
// TODO: Only if set...
|
|
||||||
node.setAttribute("value", "PackBits");
|
|
||||||
compression_node.appendChild(node);
|
|
||||||
|
|
||||||
node = new IIOMetadataNode("Lossless");
|
|
||||||
node.setAttribute("value", "true");
|
|
||||||
compression_node.appendChild(node);
|
|
||||||
|
|
||||||
// compression_node.appendChild(node);
|
|
||||||
|
|
||||||
return compression_node;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected IIOMetadataNode getStandardDataNode() {
|
|
||||||
IIOMetadataNode data_node = new IIOMetadataNode("Data");
|
|
||||||
IIOMetadataNode node; // scratch node
|
|
||||||
|
|
||||||
node = new IIOMetadataNode("PlanarConfiguration");
|
|
||||||
node.setAttribute("value", "PlaneInterleaved"); // TODO: Check with spec
|
|
||||||
data_node.appendChild(node);
|
|
||||||
|
|
||||||
node = new IIOMetadataNode("SampleFormat");
|
|
||||||
node.setAttribute("value", mHeader.mMode == PSD.COLOR_MODE_INDEXED ? "Index" : "UnsignedIntegral");
|
|
||||||
data_node.appendChild(node);
|
|
||||||
|
|
||||||
String bitDepth = Integer.toString(mHeader.mBits); // bits per plane
|
|
||||||
// TODO: Channels might be 5 for RGB + A + Mask...
|
|
||||||
String[] bps = new String[mHeader.mChannels];
|
|
||||||
Arrays.fill(bps, bitDepth);
|
|
||||||
|
|
||||||
node = new IIOMetadataNode("BitsPerSample");
|
|
||||||
node.setAttribute("value", StringUtil.toCSVString(bps, " "));
|
|
||||||
data_node.appendChild(node);
|
|
||||||
|
|
||||||
// TODO: SampleMSB? Or is network (aka Motorola/big endian) byte order assumed?
|
|
||||||
|
|
||||||
return data_node;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected IIOMetadataNode getStandardDimensionNode() {
|
|
||||||
IIOMetadataNode dimension_node = new IIOMetadataNode("Dimension");
|
|
||||||
IIOMetadataNode node; // scratch node
|
|
||||||
|
|
||||||
node = new IIOMetadataNode("PixelAspectRatio");
|
|
||||||
// TODO: This is not incorrect wrt resolution info
|
|
||||||
float ratio = 1f;
|
|
||||||
node.setAttribute("value", Float.toString(ratio));
|
|
||||||
dimension_node.appendChild(node);
|
|
||||||
|
|
||||||
node = new IIOMetadataNode("ImageOrientation");
|
|
||||||
node.setAttribute("value", "Normal");
|
|
||||||
dimension_node.appendChild(node);
|
|
||||||
|
|
||||||
List<PSDResolutionInfo> resolutionInfos = getResources(PSDResolutionInfo.class);
|
|
||||||
if (!resolutionInfos.isEmpty()) {
|
|
||||||
PSDResolutionInfo resolutionInfo = resolutionInfos.get(0);
|
|
||||||
|
|
||||||
node = new IIOMetadataNode("HorizontalPixelSize");
|
|
||||||
node.setAttribute("value", Float.toString(asMM(resolutionInfo.mHResUnit, resolutionInfo.mHRes)));
|
|
||||||
dimension_node.appendChild(node);
|
|
||||||
|
|
||||||
node = new IIOMetadataNode("VerticalPixelSize");
|
|
||||||
node.setAttribute("value", Float.toString(asMM(resolutionInfo.mVResUnit, resolutionInfo.mVRes)));
|
|
||||||
dimension_node.appendChild(node);
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO:
|
|
||||||
/*
|
|
||||||
<!ELEMENT "HorizontalPixelOffset" EMPTY>
|
|
||||||
<!-- The horizonal position, in pixels, where the image should be
|
|
||||||
rendered onto a raster display -->
|
|
||||||
<!ATTLIST "HorizontalPixelOffset" "value" #CDATA #REQUIRED>
|
|
||||||
<!-- Data type: Integer -->
|
|
||||||
|
|
||||||
<!ELEMENT "VerticalPixelOffset" EMPTY>
|
|
||||||
<!-- The vertical position, in pixels, where the image should be
|
|
||||||
rendered onto a raster display -->
|
|
||||||
<!ATTLIST "VerticalPixelOffset" "value" #CDATA #REQUIRED>
|
|
||||||
<!-- Data type: Integer -->
|
|
||||||
|
|
||||||
<!ELEMENT "HorizontalScreenSize" EMPTY>
|
|
||||||
<!-- The width, in pixels, of the raster display into which the
|
|
||||||
image should be rendered -->
|
|
||||||
<!ATTLIST "HorizontalScreenSize" "value" #CDATA #REQUIRED>
|
|
||||||
<!-- Data type: Integer -->
|
|
||||||
|
|
||||||
<!ELEMENT "VerticalScreenSize" EMPTY>
|
|
||||||
<!-- The height, in pixels, of the raster display into which the
|
|
||||||
image should be rendered -->
|
|
||||||
<!ATTLIST "VerticalScreenSize" "value" #CDATA #REQUIRED>
|
|
||||||
<!-- Data type: Integer -->
|
|
||||||
|
|
||||||
*/
|
|
||||||
return dimension_node;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static float asMM(final short pUnit, final float pResolution) {
|
|
||||||
// Unit: 1 -> pixels per inch, 2 -> pixels pr cm
|
|
||||||
return (pUnit == 1 ? 25.4f : 10) / pResolution;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected IIOMetadataNode getStandardDocumentNode() {
|
|
||||||
// TODO: PSDVersionInfo
|
|
||||||
|
|
||||||
// if (!tIME_present) {
|
|
||||||
// return null;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// IIOMetadataNode document_node = new IIOMetadataNode("Document");
|
|
||||||
// IIOMetadataNode node = null; // scratch node
|
|
||||||
//
|
|
||||||
// node = new IIOMetadataNode("ImageModificationTime");
|
|
||||||
// node.setAttribute("year", Integer.toString(tIME_year));
|
|
||||||
// node.setAttribute("month", Integer.toString(tIME_month));
|
|
||||||
// node.setAttribute("day", Integer.toString(tIME_day));
|
|
||||||
// node.setAttribute("hour", Integer.toString(tIME_hour));
|
|
||||||
// node.setAttribute("minute", Integer.toString(tIME_minute));
|
|
||||||
// node.setAttribute("second", Integer.toString(tIME_second));
|
|
||||||
// document_node.appendChild(node);
|
|
||||||
//
|
|
||||||
// return document_node;
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected IIOMetadataNode getStandardTextNode() {
|
|
||||||
// TODO: CaptionDigest?, EXIF, XMP
|
|
||||||
|
|
||||||
// int numEntries = tEXt_keyword.size() +
|
|
||||||
// iTXt_keyword.size() + zTXt_keyword.size();
|
|
||||||
// if (numEntries == 0) {
|
|
||||||
// return null;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// IIOMetadataNode text_node = new IIOMetadataNode("Text");
|
|
||||||
// IIOMetadataNode node = null; // scratch node
|
|
||||||
//
|
|
||||||
// for (int i = 0; i < tEXt_keyword.size(); i++) {
|
|
||||||
// node = new IIOMetadataNode("TextEntry");
|
|
||||||
// node.setAttribute("keyword", (String)tEXt_keyword.get(i));
|
|
||||||
// node.setAttribute("value", (String)tEXt_text.get(i));
|
|
||||||
// node.setAttribute("encoding", "ISO-8859-1");
|
|
||||||
// node.setAttribute("compression", "none");
|
|
||||||
//
|
|
||||||
// text_node.appendChild(node);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// for (int i = 0; i < iTXt_keyword.size(); i++) {
|
|
||||||
// node = new IIOMetadataNode("TextEntry");
|
|
||||||
// node.setAttribute("keyword", iTXt_keyword.get(i));
|
|
||||||
// node.setAttribute("value", iTXt_text.get(i));
|
|
||||||
// node.setAttribute("language",
|
|
||||||
// iTXt_languageTag.get(i));
|
|
||||||
// if (iTXt_compressionFlag.get(i)) {
|
|
||||||
// node.setAttribute("compression", "deflate");
|
|
||||||
// } else {
|
|
||||||
// node.setAttribute("compression", "none");
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// text_node.appendChild(node);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// for (int i = 0; i < zTXt_keyword.size(); i++) {
|
|
||||||
// node = new IIOMetadataNode("TextEntry");
|
|
||||||
// node.setAttribute("keyword", (String)zTXt_keyword.get(i));
|
|
||||||
// node.setAttribute("value", (String)zTXt_text.get(i));
|
|
||||||
// node.setAttribute("compression", "deflate");
|
|
||||||
//
|
|
||||||
// text_node.appendChild(node);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// return text_node;
|
|
||||||
return null;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected IIOMetadataNode getStandardTileNode() {
|
|
||||||
return super.getStandardTileNode();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected IIOMetadataNode getStandardTransparencyNode() {
|
|
||||||
IIOMetadataNode transparency_node =
|
|
||||||
new IIOMetadataNode("Transparency");
|
|
||||||
IIOMetadataNode node; // scratch node
|
|
||||||
|
|
||||||
node = new IIOMetadataNode("Alpha");
|
|
||||||
node.setAttribute("value", hasAlpha() ? "nonpremultipled" : "none"); // TODO: Check spec
|
|
||||||
transparency_node.appendChild(node);
|
|
||||||
|
|
||||||
return transparency_node;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean hasAlpha() {
|
|
||||||
return mHeader.mMode == PSD.COLOR_MODE_RGB && mHeader.mChannels >= 4 ||
|
|
||||||
mHeader.mMode == PSD.COLOR_MODE_CMYK & mHeader.mChannels >= 5;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Replace with filter iterator?
|
|
||||||
<T extends PSDImageResource> List<T> getResources(final Class<T> pResourceType) {
|
|
||||||
List<T> filtered = null;
|
|
||||||
|
|
||||||
for (PSDImageResource resource : mImageResources) {
|
|
||||||
if (pResourceType.isInstance(resource)) {
|
|
||||||
if (filtered == null) {
|
|
||||||
filtered = new ArrayList<T>();
|
|
||||||
}
|
|
||||||
|
|
||||||
filtered.add(pResourceType.cast(resource));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return filtered;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,165 +0,0 @@
|
|||||||
package com.twelvemonkeys.imageio.plugins.psd;
|
|
||||||
|
|
||||||
import javax.imageio.ImageTypeSpecifier;
|
|
||||||
import javax.imageio.metadata.IIOMetadataFormatImpl;
|
|
||||||
import java.util.Arrays;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* PSDMetadataFormat
|
|
||||||
*
|
|
||||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
|
||||||
* @author last modified by $Author: haraldk$
|
|
||||||
* @version $Id: PSDMetadataFormat.java,v 1.0 Nov 4, 2009 5:27:53 PM haraldk Exp$
|
|
||||||
*/
|
|
||||||
public final class PSDMetadataFormat extends IIOMetadataFormatImpl {
|
|
||||||
|
|
||||||
private final static PSDMetadataFormat sInstance = new PSDMetadataFormat();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Private constructor.
|
|
||||||
* <p/>
|
|
||||||
* The {@link javax.imageio.metadata.IIOMetadata} class will instantiate this class
|
|
||||||
* by reflection, invoking the static {@code getInstance()} method.
|
|
||||||
*
|
|
||||||
* @see javax.imageio.metadata.IIOMetadata#getMetadataFormat
|
|
||||||
* @see #getInstance()
|
|
||||||
*/
|
|
||||||
private PSDMetadataFormat() {
|
|
||||||
// Defines the root element
|
|
||||||
super(PSDMetadata.NATIVE_METADATA_FORMAT_NAME, CHILD_POLICY_SOME);
|
|
||||||
|
|
||||||
// root -> PSDHeader
|
|
||||||
// TODO: How do I specify that the header is required?
|
|
||||||
addElement("PSDHeader", PSDMetadata.NATIVE_METADATA_FORMAT_NAME, CHILD_POLICY_EMPTY);
|
|
||||||
|
|
||||||
// TODO: Do the first two make sense?
|
|
||||||
addAttribute("PSDHeader", "signature", DATATYPE_STRING, false, "8BPS", Arrays.asList("8BPS"));
|
|
||||||
addAttribute("PSDHeader", "version", DATATYPE_INTEGER, false, "1", Arrays.asList("1"));
|
|
||||||
|
|
||||||
addAttribute("PSDHeader", "channels", DATATYPE_INTEGER, true, null, "1", "24", true, true);
|
|
||||||
// rows?
|
|
||||||
addAttribute("PSDHeader", "height", DATATYPE_INTEGER, true, null, "1", "30000", true, true);
|
|
||||||
// columns?
|
|
||||||
addAttribute("PSDHeader", "width", DATATYPE_INTEGER, true, null, "1", "30000", true, true);
|
|
||||||
addAttribute("PSDHeader", "bits", DATATYPE_INTEGER, true, null, Arrays.asList("1", "8", "16"));
|
|
||||||
addAttribute("PSDHeader", "mode", DATATYPE_INTEGER, true, null, Arrays.asList(
|
|
||||||
String.valueOf(PSD.COLOR_MODE_MONOCHROME),
|
|
||||||
String.valueOf(PSD.COLOR_MODE_GRAYSCALE),
|
|
||||||
String.valueOf(PSD.COLOR_MODE_INDEXED),
|
|
||||||
String.valueOf(PSD.COLOR_MODE_RGB),
|
|
||||||
String.valueOf(PSD.COLOR_MODE_CMYK),
|
|
||||||
String.valueOf(PSD.COLOR_MODE_MULTICHANNEL),
|
|
||||||
String.valueOf(PSD.COLOR_MODE_DUOTONE),
|
|
||||||
String.valueOf(PSD.COLOR_MODE_LAB)
|
|
||||||
));
|
|
||||||
|
|
||||||
/*
|
|
||||||
Contains the required data to define the color mode.
|
|
||||||
|
|
||||||
For indexed color images, the count will be equal to 768, and the mode data
|
|
||||||
will contain the color table for the image, in non-interleaved order.
|
|
||||||
|
|
||||||
For duotone images, the mode data will contain the duotone specification,
|
|
||||||
the format of which is not documented. Non-Photoshop readers can treat
|
|
||||||
the duotone image as a grayscale image, and keep the duotone specification
|
|
||||||
around as a black box for use when saving the file.
|
|
||||||
*/
|
|
||||||
// root -> Palette
|
|
||||||
// Color map for indexed, optional
|
|
||||||
// NOTE: Palette, PaletteEntry naming taken from the standard format, native PSD naming is ColorModeData
|
|
||||||
// NOTE: PSD stores these as 256 Red, 256 Green, 256 Blue.. Should we do the same in the meta data?
|
|
||||||
addElement("Palette", PSDMetadata.NATIVE_METADATA_FORMAT_NAME, 256, 256); // 768 = 256 * 3
|
|
||||||
addElement("PaletteEntry", "PSDColorData", CHILD_POLICY_EMPTY);
|
|
||||||
addAttribute("PaletteEntry", "index", DATATYPE_INTEGER, true, null, "0", "255", true, true);
|
|
||||||
addAttribute("PaletteEntry", "red", DATATYPE_INTEGER, true, null, "0", "255", true, true);
|
|
||||||
addAttribute("PaletteEntry", "green", DATATYPE_INTEGER, true, null, "0", "255", true, true);
|
|
||||||
addAttribute("PaletteEntry", "blue", DATATYPE_INTEGER, true, null, "0", "255", true, true);
|
|
||||||
// No alpha allowed in indexed color PSD
|
|
||||||
|
|
||||||
// TODO: Duotone spec, optional (use same element as palette?)
|
|
||||||
// Or use object or raw bytes..
|
|
||||||
|
|
||||||
// root -> ImageResources
|
|
||||||
// Image resources, optional
|
|
||||||
addElement("ImageResources", PSDMetadata.NATIVE_METADATA_FORMAT_NAME, CHILD_POLICY_SEQUENCE); // SOME?
|
|
||||||
|
|
||||||
// root -> ImageResources -> ImageResource
|
|
||||||
// Generic resource
|
|
||||||
addElement("ImageResource", "ImageResources", CHILD_POLICY_ALL);
|
|
||||||
// TODO: Allow arbitrary values to be added as a generic resource...
|
|
||||||
|
|
||||||
// root -> ImageResources -> AlphaChannelInfo
|
|
||||||
addElement("AlphaChannelInfo", "ImageResources", CHILD_POLICY_EMPTY);
|
|
||||||
addAttribute("AlphaChannelInfo", "names", DATATYPE_STRING, true, 0, Integer.MAX_VALUE);
|
|
||||||
|
|
||||||
// root -> ImageResources -> DisplayInfo
|
|
||||||
addElement("DisplayInfo", "ImageResources", CHILD_POLICY_EMPTY);
|
|
||||||
addAttribute("DisplayInfo", "colorSpace", DATATYPE_INTEGER, true, null);
|
|
||||||
addAttribute("DisplayInfo", "colors", DATATYPE_INTEGER, true, 4, 4);
|
|
||||||
addAttribute("DisplayInfo", "opacity", DATATYPE_INTEGER, true, null, "0", "100", true, true);
|
|
||||||
addAttribute("DisplayInfo", "kind", DATATYPE_INTEGER, true, null, Arrays.asList("0", "1"));
|
|
||||||
|
|
||||||
// root -> ImageResources -> EXIF1Data
|
|
||||||
addElement("EXIF1Data", "ImageResources", CHILD_POLICY_ALL);
|
|
||||||
// TODO: Incorporate EXIF / TIFF metadata here somehow... (or treat as opaque bytes?)
|
|
||||||
|
|
||||||
// root -> ImageResources -> PrintFlags
|
|
||||||
addElement("PrintFlags", "ImageResources", CHILD_POLICY_EMPTY);
|
|
||||||
addBooleanAttribute("PrintFlags", "labels", false, false);
|
|
||||||
addBooleanAttribute("PrintFlags", "cropMasks", false, false);
|
|
||||||
addBooleanAttribute("PrintFlags", "colorBars", false, false);
|
|
||||||
addBooleanAttribute("PrintFlags", "registrationMarks", false, false);
|
|
||||||
addBooleanAttribute("PrintFlags", "negative", false, false);
|
|
||||||
addBooleanAttribute("PrintFlags", "flip", false, false);
|
|
||||||
addBooleanAttribute("PrintFlags", "interpolate", false, false);
|
|
||||||
addBooleanAttribute("PrintFlags", "caption", false, false);
|
|
||||||
|
|
||||||
// root -> ImageResources -> PrintFlagsInformation
|
|
||||||
addElement("PrintFlagsInformation", "ImageResources", CHILD_POLICY_EMPTY);
|
|
||||||
addAttribute("PrintFlagsInformation", "version", DATATYPE_INTEGER, true, null);
|
|
||||||
addBooleanAttribute("PrintFlagsInformation", "cropMarks", false, false);
|
|
||||||
addAttribute("PrintFlagsInformation", "field", DATATYPE_INTEGER, true, null);
|
|
||||||
addAttribute("PrintFlagsInformation", "bleedWidth", DATATYPE_INTEGER, true, null, "0", String.valueOf(Long.MAX_VALUE), true, true); // TODO: LONG??!
|
|
||||||
addAttribute("PrintFlagsInformation", "bleedScale", DATATYPE_INTEGER, true, null, "0", String.valueOf(Integer.MAX_VALUE), true, true);
|
|
||||||
|
|
||||||
// root -> ImageResources -> ResolutionInfo
|
|
||||||
addElement("ResolutionInfo", "ImageResources", CHILD_POLICY_EMPTY);
|
|
||||||
addAttribute("ResolutionInfo", "hRes", DATATYPE_FLOAT, true, null);
|
|
||||||
// TODO: Or use string and more friendly names? "pixels/inch"/"pixels/cm" and "inch"/"cm"/"pt"/"pica"/"column"
|
|
||||||
addAttribute("ResolutionInfo", "hResUnit", DATATYPE_INTEGER, true, null, Arrays.asList("1", "2"));
|
|
||||||
addAttribute("ResolutionInfo", "widthUnit", DATATYPE_INTEGER, true, null, Arrays.asList("1", "2", "3", "4", "5"));
|
|
||||||
addAttribute("ResolutionInfo", "vRes", DATATYPE_FLOAT, true, null);
|
|
||||||
// TODO: Or use more friendly names?
|
|
||||||
addAttribute("ResolutionInfo", "vResUnit", DATATYPE_INTEGER, true, null, Arrays.asList("1", "2"));
|
|
||||||
addAttribute("ResolutionInfo", "heightUnit", DATATYPE_INTEGER, true, null, Arrays.asList("1", "2", "3", "4", "5"));
|
|
||||||
|
|
||||||
// ??? addElement("Thumbnail", "ImageResources", CHILD_POLICY_CHOICE);
|
|
||||||
|
|
||||||
// root -> ImageResources -> XMPData
|
|
||||||
addElement("XMPData", "ImageResources", CHILD_POLICY_CHOICE);
|
|
||||||
// TODO: Incorporate XMP metadata here somehow (or treat as opaque bytes?)
|
|
||||||
|
|
||||||
// TODO: Layers
|
|
||||||
//addElement("ChannelSourceDestinationRange", "LayerSomething", CHILD_POLICY_CHOICE);
|
|
||||||
|
|
||||||
// TODO: Global layer mask info
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean canNodeAppear(final String pElementName, final ImageTypeSpecifier pImageType) {
|
|
||||||
// TODO: PSDColorData and PaletteEntry only for indexed color model
|
|
||||||
throw new UnsupportedOperationException("Method canNodeAppear not implemented"); // TODO: Implement
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the shared instance of the {@code PSDMetadataFormat}.
|
|
||||||
*
|
|
||||||
* @return the shared instance.
|
|
||||||
* @see javax.imageio.metadata.IIOMetadata#getMetadataFormat
|
|
||||||
*/
|
|
||||||
public static PSDMetadataFormat getInstance() {
|
|
||||||
return sInstance;
|
|
||||||
}
|
|
||||||
}
|
|
@ -50,12 +50,13 @@ class PSDResolutionInfo extends PSDImageResource {
|
|||||||
// WORD HeightUnit; /* 1=in, 2=cm, 3=pt, 4=picas, 5=columns */
|
// WORD HeightUnit; /* 1=in, 2=cm, 3=pt, 4=picas, 5=columns */
|
||||||
// } RESOLUTIONINFO;
|
// } RESOLUTIONINFO;
|
||||||
|
|
||||||
float mHRes;
|
private float mHRes;
|
||||||
short mHResUnit;
|
private short mHResUnit;
|
||||||
short mWidthUnit;
|
private short mWidthUnit;
|
||||||
float mVRes;
|
private float mVRes;
|
||||||
short mVResUnit;
|
private short mVResUnit;
|
||||||
short mHeightUnit;
|
private short mHeightUnit;
|
||||||
|
|
||||||
|
|
||||||
PSDResolutionInfo(final short pId, final ImageInputStream pInput) throws IOException {
|
PSDResolutionInfo(final short pId, final ImageInputStream pInput) throws IOException {
|
||||||
super(pId, pInput);
|
super(pId, pInput);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user