package net.pms.image; import java.awt.color.ColorSpace; import java.awt.image.ColorModel; import net.pms.util.ParseException; import com.drew.metadata.Directory; import com.drew.metadata.Metadata; import com.drew.metadata.photoshop.PsdHeaderDirectory; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; @SuppressWarnings("serial") @SuppressFBWarnings("SE_NO_SERIALVERSIONID") public class PSDInfo extends ImageInfo { protected final ColorMode colorMode; protected final Integer channelCount; /** * Use * {@link ImageInfo#create(int, int, ImageFormat, long, ColorModel, Metadata, boolean, boolean)} * to instantiate. */ protected PSDInfo( int width, int height, ImageFormat format, long size, ColorModel colorModel, Metadata metadata, boolean applyExifOrientation, boolean imageIOSupport ) throws ParseException { super(width, height, format, size, colorModel, metadata, applyExifOrientation, imageIOSupport); colorMode = ((PSDParseInfo) parsedInfo).colorMode; channelCount = ((PSDParseInfo) parsedInfo).channelCount; } /** * Use * {@link ImageInfo#create(int, int, ImageFormat, long, int, int, ColorSpace, ColorSpaceType, Metadata, boolean, boolean)} * to instantiate. */ protected PSDInfo( int width, int height, ImageFormat format, long size, int bitDepth, int numComponents, ColorSpace colorSpace, ColorSpaceType colorSpaceType, Metadata metadata, boolean applyExifOrientation, boolean imageIOSupport ) throws ParseException { super( width, height, format, size, bitDepth, numComponents, colorSpace, colorSpaceType, metadata, applyExifOrientation, imageIOSupport ); colorMode = ((PSDParseInfo) parsedInfo).colorMode; channelCount = ((PSDParseInfo) parsedInfo).channelCount; } /** * Use * {@link ImageInfo#create(int, int, Metadata, ImageFormat, long, boolean, boolean)} * to instantiate. */ protected PSDInfo( int width, int height, Metadata metadata, ImageFormat format, long size, boolean applyExifOrientation, boolean throwOnParseFailure ) throws ParseException { super(width, height, metadata, format, size, applyExifOrientation, throwOnParseFailure); colorMode = ((PSDParseInfo) parsedInfo).colorMode; channelCount = ((PSDParseInfo) parsedInfo).channelCount; } /** * Copy constructor */ protected PSDInfo( int width, int height, ImageFormat format, long size, int bitDepth, int numComponents, ColorSpace colorSpace, ColorSpaceType colorSpaceType, boolean imageIOSupport, ColorMode colorMode, Integer channelCount ) { super(width, height, format, size, bitDepth, numComponents, colorSpace, colorSpaceType, imageIOSupport); this.colorMode = colorMode; this.channelCount = channelCount; } @Override protected ParseInfo createParseInfo() { return new PSDParseInfo(); } @SuppressFBWarnings("SF_SWITCH_NO_DEFAULT") @Override protected void parseMetadata(Metadata metadata) { if (metadata == null) { return; } for (Directory directory : metadata.getDirectories()) { if (directory instanceof PsdHeaderDirectory) { parsedInfo.format = ImageFormat.PSD; if ( ((PsdHeaderDirectory) directory).containsTag(PsdHeaderDirectory.TAG_IMAGE_WIDTH) && ((PsdHeaderDirectory) directory).containsTag(PsdHeaderDirectory.TAG_IMAGE_HEIGHT) ) { parsedInfo.width = ((PsdHeaderDirectory) directory).getInteger(PsdHeaderDirectory.TAG_IMAGE_WIDTH); parsedInfo.height = ((PsdHeaderDirectory) directory).getInteger(PsdHeaderDirectory.TAG_IMAGE_HEIGHT); } if (((PsdHeaderDirectory) directory).containsTag(PsdHeaderDirectory.TAG_BITS_PER_CHANNEL)) { Integer i = ((PsdHeaderDirectory) directory).getInteger(PsdHeaderDirectory.TAG_BITS_PER_CHANNEL); if (i != null) { parsedInfo.bitDepth = i; } } if (((PsdHeaderDirectory) directory).containsTag(PsdHeaderDirectory.TAG_COLOR_MODE)) { Integer i = ((PsdHeaderDirectory) directory).getInteger(PsdHeaderDirectory.TAG_COLOR_MODE); if (i != null) { ((PSDParseInfo) parsedInfo).colorMode = ColorMode.typeOf(i.intValue()); /* * Bitmap = 0; Grayscale = 1; Indexed = 2; RGB = 3; CMYK = 4; Multichannel = 7; Duotone = 8; Lab = 9. */ switch (((PSDParseInfo) parsedInfo).colorMode) { case GRAYSCALE: parsedInfo.numComponents = 1; parsedInfo.colorSpaceType = ColorSpaceType.TYPE_GRAY; break; case INDEXED: case RGB: parsedInfo.numComponents = 3; parsedInfo.colorSpaceType = ColorSpaceType.TYPE_RGB; break; case CMYK: parsedInfo.numComponents = 4; parsedInfo.colorSpaceType = ColorSpaceType.TYPE_CMYK; break; case LAB: parsedInfo.numComponents = 3; parsedInfo.colorSpaceType = ColorSpaceType.TYPE_Lab; default: } } } if (((PsdHeaderDirectory) directory).containsTag(PsdHeaderDirectory.TAG_CHANNEL_COUNT)) { Integer i = ((PsdHeaderDirectory) directory).getInteger(PsdHeaderDirectory.TAG_CHANNEL_COUNT); if (i != null) { ((PSDParseInfo) parsedInfo).channelCount = i; } } } } } /** * @return The {@link ColorMode} or {@code null} if unknown. */ public ColorMode getColorMode() { return colorMode; } /** * The number of channels in the image, including any alpha channels. * Supported range is 1 to 56. * * @return The number of channels in the image or {@code null} if unknown. */ public Integer getChannelCount() { return channelCount; } @Override public PSDInfo copy() { return new PSDInfo( width, height, format, size, bitDepth, numComponents, colorSpace, colorSpaceType, imageIOSupport, colorMode, channelCount ); } public enum ColorMode { BITMAP, GRAYSCALE, INDEXED, RGB, CMYK, MULTI_CHANNEL, DUOTONE, LAB; public static ColorMode typeOf(int value) { switch (value) { case 0: return BITMAP; case 1: return GRAYSCALE; case 2: return INDEXED; case 3: return RGB; case 4: return CMYK; case 7: return MULTI_CHANNEL; case 8: return DUOTONE; case 9: return LAB; default: return null; } } } protected static class PSDParseInfo extends ParseInfo { ColorMode colorMode; Integer channelCount; } @Override protected void buildToString(StringBuilder sb) { if (colorMode != null) { sb.append(", Color Mode = ").append(colorMode); } if (channelCount != null) { sb.append(", Channel Count = ").append(channelCount); } } }