New code style. No functional changes.

This commit is contained in:
Harald Kuhr
2011-02-17 17:54:50 +01:00
parent 5bd896f80f
commit 770f948e1a
78 changed files with 1401 additions and 1412 deletions
@@ -95,8 +95,8 @@ public class SVGImageReader extends ImageReaderBase {
} }
@Override @Override
public void setInput(Object pInput, boolean pSeekForwardOnly, boolean pIgnoreMetadata) { public void setInput(Object pInput, boolean seekForwardOnly, boolean ignoreMetadata) {
super.setInput(pInput, pSeekForwardOnly, pIgnoreMetadata); super.setInput(pInput, seekForwardOnly, ignoreMetadata);
if (imageInput != null) { if (imageInput != null) {
TranscoderInput input = new TranscoderInput(IIOUtil.createStreamAdapter(imageInput)); TranscoderInput input = new TranscoderInput(IIOUtil.createStreamAdapter(imageInput));
@@ -126,11 +126,11 @@ public class TIFFImageReader extends ImageReaderBase {
checkBounds(pIndex); checkBounds(pIndex);
} }
protected void checkBounds(int pIndex) throws IOException { protected void checkBounds(int index) throws IOException {
if (pIndex < getMinIndex()){ if (index < getMinIndex()){
throw new IndexOutOfBoundsException("index < minIndex"); throw new IndexOutOfBoundsException("index < minIndex");
} }
else if (pIndex >= getNumImages(true)) { else if (index >= getNumImages(true)) {
throw new IndexOutOfBoundsException("index > numImages"); throw new IndexOutOfBoundsException("index > numImages");
} }
} }
@@ -179,9 +179,9 @@ public class TIFFImageReader extends ImageReaderBase {
throw new UnsupportedOperationException("Method getImageTypes not implemented");// TODO: Implement throw new UnsupportedOperationException("Method getImageTypes not implemented");// TODO: Implement
} }
public int getNumImages(boolean pAllowSearch) throws IOException { public int getNumImages(boolean allowSearch) throws IOException {
init(); init();
if (pAllowSearch) { if (allowSearch) {
return mDecoder.getNumPages(); return mDecoder.getNumPages();
} }
return -1; return -1;
@@ -60,9 +60,9 @@ public class TIFFImageWriter extends ImageWriterBase {
} }
@Override @Override
public void setOutput(final Object pOutput) { public void setOutput(final Object output) {
mEncoder = null; mEncoder = null;
super.setOutput(pOutput); super.setOutput(output);
} }
public IIOMetadata getDefaultImageMetadata(final ImageTypeSpecifier imageType, final ImageWriteParam param) { public IIOMetadata getDefaultImageMetadata(final ImageTypeSpecifier imageType, final ImageWriteParam param) {
@@ -71,21 +71,21 @@ public abstract class ImageReaderBase extends ImageReader {
* the extension object is unsuitable, an * the extension object is unsuitable, an
* {@code IllegalArgumentException} should be thrown. * {@code IllegalArgumentException} should be thrown.
* *
* @param pProvider the {@code ImageReaderSpi} that is invoking this constructor, or {@code null}. * @param provider the {@code ImageReaderSpi} that is invoking this constructor, or {@code null}.
*/ */
protected ImageReaderBase(final ImageReaderSpi pProvider) { protected ImageReaderBase(final ImageReaderSpi provider) {
super(pProvider); super(provider);
} }
/** /**
* Overrides {@code setInput}, to allow easy access to the input, in case * Overrides {@code setInput}, to allow easy access to the input, in case
* it is an {@code ImageInputStream}. * it is an {@code ImageInputStream}.
* *
* @param pInput the {@code ImageInputStream} or other * @param input the {@code ImageInputStream} or other
* {@code Object} to use for future decoding. * {@code Object} to use for future decoding.
* @param pSeekForwardOnly if {@code true}, images and metadata * @param seekForwardOnly if {@code true}, images and metadata
* may only be read in ascending order from this input source. * may only be read in ascending order from this input source.
* @param pIgnoreMetadata if {@code true}, metadata * @param ignoreMetadata if {@code true}, metadata
* may be ignored during reads. * may be ignored during reads.
* *
* @exception IllegalArgumentException if {@code input} is * @exception IllegalArgumentException if {@code input} is
@@ -96,11 +96,11 @@ public abstract class ImageReaderBase extends ImageReader {
* @see ImageInputStream * @see ImageInputStream
*/ */
@Override @Override
public void setInput(final Object pInput, final boolean pSeekForwardOnly, final boolean pIgnoreMetadata) { public void setInput(final Object input, final boolean seekForwardOnly, final boolean ignoreMetadata) {
resetMembers(); resetMembers();
super.setInput(pInput, pSeekForwardOnly, pIgnoreMetadata); super.setInput(input, seekForwardOnly, ignoreMetadata);
if (pInput instanceof ImageInputStream) { if (input instanceof ImageInputStream) {
imageInput = (ImageInputStream) pInput; imageInput = (ImageInputStream) input;
} }
} }
@@ -130,11 +130,11 @@ public abstract class ImageReaderBase extends ImageReader {
/** /**
* Default implementation that always returns {@code null}. * Default implementation that always returns {@code null}.
* *
* @param pImageIndex ignored, unless overridden * @param imageIndex ignored, unless overridden
* @return {@code null}, unless overridden * @return {@code null}, unless overridden
* @throws IOException never, unless overridden. * @throws IOException never, unless overridden.
*/ */
public IIOMetadata getImageMetadata(int pImageIndex) throws IOException { public IIOMetadata getImageMetadata(int imageIndex) throws IOException {
return null; return null;
} }
@@ -151,11 +151,11 @@ public abstract class ImageReaderBase extends ImageReader {
/** /**
* Default implementation that always returns {@code 1}. * Default implementation that always returns {@code 1}.
* *
* @param pAllowSearch ignored, unless overridden * @param allowSearch ignored, unless overridden
* @return {@code 1}, unless overridden * @return {@code 1}, unless overridden
* @throws IOException never, unless overridden * @throws IOException never, unless overridden
*/ */
public int getNumImages(boolean pAllowSearch) throws IOException { public int getNumImages(boolean allowSearch) throws IOException {
assertInput(); assertInput();
return 1; return 1;
} }
@@ -163,18 +163,18 @@ public abstract class ImageReaderBase extends ImageReader {
/** /**
* Convenience method to make sure image index is within bounds. * Convenience method to make sure image index is within bounds.
* *
* @param pIndex the image index * @param index the image index
* *
* @throws java.io.IOException if an error occurs during reading * @throws java.io.IOException if an error occurs during reading
* @throws IndexOutOfBoundsException if not {@code minIndex <= pIndex < numImages} * @throws IndexOutOfBoundsException if not {@code minIndex <= index < numImages}
*/ */
protected void checkBounds(int pIndex) throws IOException { protected void checkBounds(int index) throws IOException {
assertInput(); assertInput();
if (pIndex < getMinIndex()) { if (index < getMinIndex()) {
throw new IndexOutOfBoundsException("index < minIndex"); throw new IndexOutOfBoundsException("index < minIndex");
} }
else if (getNumImages(false) != -1 && pIndex >= getNumImages(false)) { else if (getNumImages(false) != -1 && index >= getNumImages(false)) {
throw new IndexOutOfBoundsException("index >= numImages (" + pIndex + " >= " + getNumImages(false) + ")"); throw new IndexOutOfBoundsException("index >= numImages (" + index + " >= " + getNumImages(false) + ")");
} }
} }
@@ -65,10 +65,10 @@ public abstract class ImageWriterBase extends ImageWriter {
* the extension object is unsuitable, an * the extension object is unsuitable, an
* {@code IllegalArgumentException} should be thrown. * {@code IllegalArgumentException} should be thrown.
* *
* @param pProvider the {@code ImageWriterSpi} that is constructing this object, or {@code null}. * @param provider the {@code ImageWriterSpi} that is constructing this object, or {@code null}.
*/ */
protected ImageWriterBase(final ImageWriterSpi pProvider) { protected ImageWriterBase(final ImageWriterSpi provider) {
super(pProvider); super(provider);
} }
public String getFormatName() throws IOException { public String getFormatName() throws IOException {
@@ -76,11 +76,11 @@ public abstract class ImageWriterBase extends ImageWriter {
} }
@Override @Override
public void setOutput(final Object pOutput) { public void setOutput(final Object output) {
super.setOutput(pOutput); super.setOutput(output);
if (pOutput instanceof ImageOutputStream) { if (output instanceof ImageOutputStream) {
imageOutput = (ImageOutputStream) pOutput; imageOutput = (ImageOutputStream) output;
} }
} }
@@ -98,21 +98,21 @@ public abstract class ImageWriterBase extends ImageWriter {
/** /**
* Returns {@code null} * Returns {@code null}
* *
* @param pParam ignored. * @param param ignored.
* @return {@code null}. * @return {@code null}.
*/ */
public IIOMetadata getDefaultStreamMetadata(final ImageWriteParam pParam) { public IIOMetadata getDefaultStreamMetadata(final ImageWriteParam param) {
return null; return null;
} }
/** /**
* Returns {@code null} * Returns {@code null}
* *
* @param pInData ignored. * @param inData ignored.
* @param pParam ignored. * @param param ignored.
* @return {@code null}. * @return {@code null}.
*/ */
public IIOMetadata convertStreamMetadata(final IIOMetadata pInData, final ImageWriteParam pParam) { public IIOMetadata convertStreamMetadata(final IIOMetadata inData, final ImageWriteParam param) {
return null; return null;
} }
@@ -44,51 +44,51 @@ public abstract class ProgressListenerBase implements IIOReadProgressListener, I
protected ProgressListenerBase() { protected ProgressListenerBase() {
} }
public void imageComplete(ImageReader pSource) { public void imageComplete(ImageReader source) {
} }
public void imageProgress(ImageReader pSource, float pPercentageDone) { public void imageProgress(ImageReader source, float percentageDone) {
} }
public void imageStarted(ImageReader pSource, int pImageIndex) { public void imageStarted(ImageReader source, int imageIndex) {
} }
public void readAborted(ImageReader pSource) { public void readAborted(ImageReader source) {
} }
public void sequenceComplete(ImageReader pSource) { public void sequenceComplete(ImageReader source) {
} }
public void sequenceStarted(ImageReader pSource, int pMinIndex) { public void sequenceStarted(ImageReader source, int minIndex) {
} }
public void thumbnailComplete(ImageReader pSource) { public void thumbnailComplete(ImageReader source) {
} }
public void thumbnailProgress(ImageReader pSource, float pPercentageDone) { public void thumbnailProgress(ImageReader source, float percentageDone) {
} }
public void thumbnailStarted(ImageReader pSource, int pImageIndex, int pThumbnailIndex) { public void thumbnailStarted(ImageReader source, int imageIndex, int thumbnailIndex) {
} }
public void imageComplete(ImageWriter pSource) { public void imageComplete(ImageWriter source ) {
} }
public void imageProgress(ImageWriter pSource, float pPercentageDone) { public void imageProgress(ImageWriter source, float percentageDone) {
} }
public void imageStarted(ImageWriter pSource, int pImageIndex) { public void imageStarted(ImageWriter source, int imageIndex) {
} }
public void thumbnailComplete(ImageWriter pSource) { public void thumbnailComplete(ImageWriter source) {
} }
public void thumbnailProgress(ImageWriter pSource, float pPercentageDone) { public void thumbnailProgress(ImageWriter source, float percentageDone) {
} }
public void thumbnailStarted(ImageWriter pSource, int pImageIndex, int pThumbnailIndex) { public void thumbnailStarted(ImageWriter source, int imageIndex, int thumbnailIndex) {
} }
public void writeAborted(ImageWriter pSource) { public void writeAborted(ImageWriter source) {
} }
} }
@@ -39,34 +39,34 @@ import java.awt.image.BufferedImage;
* @version $Id: Bitmap.java,v 1.0 25.feb.2006 00:29:44 haku Exp$ * @version $Id: Bitmap.java,v 1.0 25.feb.2006 00:29:44 haku Exp$
*/ */
abstract class BitmapDescriptor { abstract class BitmapDescriptor {
protected final DirectoryEntry mEntry; protected final DirectoryEntry entry;
protected final DIBHeader mHeader; protected final DIBHeader header;
protected BufferedImage mImage; protected BufferedImage image;
public BitmapDescriptor(final DirectoryEntry pEntry, final DIBHeader pHeader) { public BitmapDescriptor(final DirectoryEntry pEntry, final DIBHeader pHeader) {
Validate.notNull(pEntry, "entry"); Validate.notNull(pEntry, "entry");
Validate.notNull(pHeader, "header"); Validate.notNull(pHeader, "header");
mEntry = pEntry; entry = pEntry;
mHeader = pHeader; header = pHeader;
} }
abstract public BufferedImage getImage(); abstract public BufferedImage getImage();
public final int getWidth() { public final int getWidth() {
return mEntry.getWidth(); return entry.getWidth();
} }
public final int getHeight() { public final int getHeight() {
return mEntry.getHeight(); return entry.getHeight();
} }
protected final int getColorCount() { protected final int getColorCount() {
return mEntry.getColorCount() != 0 ? mEntry.getColorCount() : 1 << getBitCount(); return entry.getColorCount() != 0 ? entry.getColorCount() : 1 << getBitCount();
} }
protected final int getBitCount() { protected final int getBitCount() {
return mEntry.getBitCount() != 0 ? mEntry.getBitCount() : mHeader.getBitCount(); return entry.getBitCount() != 0 ? entry.getBitCount() : header.getBitCount();
} }
} }
@@ -43,17 +43,17 @@ import java.util.Hashtable;
* @version $Id: BitmapIndexed.java,v 1.0 25.feb.2006 00:29:44 haku Exp$ * @version $Id: BitmapIndexed.java,v 1.0 25.feb.2006 00:29:44 haku Exp$
*/ */
class BitmapIndexed extends BitmapDescriptor { class BitmapIndexed extends BitmapDescriptor {
protected final int[] mBits; protected final int[] bits;
protected final int[] mColors; protected final int[] colors;
private BitmapMask mMask; private BitmapMask mask;
public BitmapIndexed(final DirectoryEntry pEntry, final DIBHeader pHeader) { public BitmapIndexed(final DirectoryEntry pEntry, final DIBHeader pHeader) {
super(pEntry, pHeader); super(pEntry, pHeader);
mBits = new int[getWidth() * getHeight()]; bits = new int[getWidth() * getHeight()];
// NOTE: We're adding space for one extra color, for transparency // NOTE: We're adding space for one extra color, for transparency
mColors = new int[getColorCount() + 1]; colors = new int[getColorCount() + 1];
} }
public BufferedImage createImageIndexed() { public BufferedImage createImageIndexed() {
@@ -64,10 +64,9 @@ class BitmapIndexed extends BitmapDescriptor {
// This is slightly obscure, and should probably be moved.. // This is slightly obscure, and should probably be moved..
Hashtable<String, Object> properties = null; Hashtable<String, Object> properties = null;
if (mEntry instanceof DirectoryEntry.CUREntry) { if (entry instanceof DirectoryEntry.CUREntry) {
DirectoryEntry.CUREntry entry = (DirectoryEntry.CUREntry) mEntry;
properties = new Hashtable<String, Object>(1); properties = new Hashtable<String, Object>(1);
properties.put("cursor_hotspot", entry.getHotspot()); properties.put("cursor_hotspot", ((DirectoryEntry.CUREntry) this.entry).getHotspot());
} }
BufferedImage image = new BufferedImage( BufferedImage image = new BufferedImage(
@@ -82,13 +81,13 @@ class BitmapIndexed extends BitmapDescriptor {
final int trans = icm.getTransparentPixel(); final int trans = icm.getTransparentPixel();
for (int y = 0; y < getHeight(); y++) { for (int y = 0; y < getHeight(); y++) {
for (int x = 0; x < getWidth(); x++) { for (int x = 0; x < getWidth(); x++) {
if (mMask.isTransparent(x, y)) { if (mask.isTransparent(x, y)) {
mBits[x + getWidth() * y] = trans; bits[x + getWidth() * y] = trans;
} }
} }
} }
raster.setSamples(0, 0, getWidth(), getHeight(), 0, mBits); raster.setSamples(0, 0, getWidth(), getHeight(), 0, bits);
//System.out.println("Image: " + image); //System.out.println("Image: " + image);
@@ -102,18 +101,18 @@ class BitmapIndexed extends BitmapDescriptor {
// NOTE: This is a hack to make room for transparent pixel for mask // NOTE: This is a hack to make room for transparent pixel for mask
int bits = getBitCount(); int bits = getBitCount();
int colors = mColors.length; int colors = this.colors.length;
int trans = -1; int trans = -1;
// Try to avoid USHORT transfertype, as it results in BufferedImage TYPE_CUSTOM // Try to avoid USHORT transfertype, as it results in BufferedImage TYPE_CUSTOM
// NOTE: This code assumes icons are small, and is NOT optimized for performance... // NOTE: This code assumes icons are small, and is NOT optimized for performance...
if (colors > (1 << getBitCount())) { if (colors > (1 << getBitCount())) {
int index = BitmapIndexed.findTransIndexMaybeRemap(mColors, mBits); int index = BitmapIndexed.findTransIndexMaybeRemap(this.colors, this.bits);
if (index == -1) { if (index == -1) {
// No duplicate found, increase bitcount // No duplicate found, increase bitcount
bits++; bits++;
trans = mColors.length - 1; trans = this.colors.length - 1;
} }
else { else {
// Found a duplicate, use it as trans // Found a duplicate, use it as trans
@@ -124,7 +123,7 @@ class BitmapIndexed extends BitmapDescriptor {
// NOTE: Setting hasAlpha to true, makes things work on 1.2 // NOTE: Setting hasAlpha to true, makes things work on 1.2
return new InverseColorMapIndexColorModel( return new InverseColorMapIndexColorModel(
bits, colors, mColors, 0, true, trans, bits, colors, this.colors, 0, true, trans,
bits <= 8 ? DataBuffer.TYPE_BYTE : DataBuffer.TYPE_USHORT bits <= 8 ? DataBuffer.TYPE_BYTE : DataBuffer.TYPE_USHORT
); );
} }
@@ -170,13 +169,13 @@ class BitmapIndexed extends BitmapDescriptor {
} }
public BufferedImage getImage() { public BufferedImage getImage() {
if (mImage == null) { if (image == null) {
mImage = createImageIndexed(); image = createImageIndexed();
} }
return mImage; return image;
} }
public void setMask(final BitmapMask pMask) { public void setMask(final BitmapMask pMask) {
mMask = pMask; mask = pMask;
} }
} }
@@ -38,19 +38,19 @@ import java.awt.image.BufferedImage;
* @version $Id: BitmapMask.java,v 1.0 25.feb.2006 00:29:44 haku Exp$ * @version $Id: BitmapMask.java,v 1.0 25.feb.2006 00:29:44 haku Exp$
*/ */
class BitmapMask extends BitmapDescriptor { class BitmapMask extends BitmapDescriptor {
protected final BitmapIndexed mMask; protected final BitmapIndexed mask;
public BitmapMask(final DirectoryEntry pParent, final DIBHeader pHeader) { public BitmapMask(final DirectoryEntry pParent, final DIBHeader pHeader) {
super(pParent, pHeader); super(pParent, pHeader);
mMask = new BitmapIndexed(pParent, pHeader); mask = new BitmapIndexed(pParent, pHeader);
} }
boolean isTransparent(final int pX, final int pY) { boolean isTransparent(final int pX, final int pY) {
// NOTE: 1: Fully transparent, 0: Opaque... // NOTE: 1: Fully transparent, 0: Opaque...
return mMask.mBits[pX + pY * getWidth()] != 0; return mask.bits[pX + pY * getWidth()] != 0;
} }
public BufferedImage getImage() { public BufferedImage getImage() {
return mMask.getImage(); return mask.getImage();
} }
} }
@@ -43,6 +43,6 @@ class BitmapRGB extends BitmapDescriptor {
} }
public BufferedImage getImage() { public BufferedImage getImage() {
return mImage; return image;
} }
} }
@@ -38,15 +38,15 @@ import java.awt.image.BufferedImage;
* @version $Id: BitmapUnsupported.java,v 1.0 25.feb.2006 00:29:44 haku Exp$ * @version $Id: BitmapUnsupported.java,v 1.0 25.feb.2006 00:29:44 haku Exp$
*/ */
class BitmapUnsupported extends BitmapDescriptor { class BitmapUnsupported extends BitmapDescriptor {
private String mMessage; private String message;
public BitmapUnsupported(final DirectoryEntry pEntry, final String pMessage) { public BitmapUnsupported(final DirectoryEntry pEntry, final String pMessage) {
super(pEntry, null); super(pEntry, null);
mMessage = pMessage; message = pMessage;
} }
public BufferedImage getImage() { public BufferedImage getImage() {
throw new IllegalStateException(mMessage); throw new IllegalStateException(message);
} }
} }
@@ -41,16 +41,16 @@ import java.io.IOException;
* @see <a href="http://en.wikipedia.org/wiki/BMP_file_format">BMP file format (Wikipedia)</a> * @see <a href="http://en.wikipedia.org/wiki/BMP_file_format">BMP file format (Wikipedia)</a>
*/ */
abstract class DIBHeader { abstract class DIBHeader {
protected int mSize; protected int size;
protected int mWidth; protected int width;
// NOTE: If a bitmask is present, this value includes the height of the mask // NOTE: If a bitmask is present, this value includes the height of the mask
// (so often header.height = entry.height * 2) // (so often header.height = entry.height * 2)
protected int mHeight; protected int height;
protected int mPlanes; protected int planes;
protected int mBitCount; protected int bitCount;
/** /**
* 0 = BI_RGB: No compression * 0 = BI_RGB: No compression
@@ -58,18 +58,18 @@ abstract class DIBHeader {
* 2 = BI_RLE4: 4 bit RLE Compression (4 bit only) * 2 = BI_RLE4: 4 bit RLE Compression (4 bit only)
* 3 = BI_BITFIELDS: No compression (16 & 32 bit only) * 3 = BI_BITFIELDS: No compression (16 & 32 bit only)
*/ */
protected int mCompression; protected int compression;
// May be 0 if not known // May be 0 if not known
protected int mImageSize; protected int imageSize;
protected int mXPixelsPerMeter; protected int xPixelsPerMeter;
protected int mYPixelsPerMeter; protected int yPixelsPerMeter;
protected int mColorsUsed; protected int colorsUsed;
// 0 means all colors are important // 0 means all colors are important
protected int mColorsImportant; protected int colorsImportant;
protected DIBHeader() { protected DIBHeader() {
} }
@@ -102,47 +102,47 @@ abstract class DIBHeader {
protected abstract void read(int pSize, DataInput pStream) throws IOException; protected abstract void read(int pSize, DataInput pStream) throws IOException;
public final int getSize() { public final int getSize() {
return mSize; return size;
} }
public final int getWidth() { public final int getWidth() {
return mWidth; return width;
} }
public final int getHeight() { public final int getHeight() {
return mHeight; return height;
} }
public final int getPlanes() { public final int getPlanes() {
return mPlanes; return planes;
} }
public final int getBitCount() { public final int getBitCount() {
return mBitCount; return bitCount;
} }
public int getCompression() { public int getCompression() {
return mCompression; return compression;
} }
public int getImageSize() { public int getImageSize() {
return mImageSize; return imageSize;
} }
public int getXPixelsPerMeter() { public int getXPixelsPerMeter() {
return mXPixelsPerMeter; return xPixelsPerMeter;
} }
public int getYPixelsPerMeter() { public int getYPixelsPerMeter() {
return mYPixelsPerMeter; return yPixelsPerMeter;
} }
public int getColorsUsed() { public int getColorsUsed() {
return mColorsUsed; return colorsUsed;
} }
public int getColorsImportant() { public int getColorsImportant() {
return mColorsImportant; return colorsImportant;
} }
public String toString() { public String toString() {
@@ -176,22 +176,22 @@ abstract class DIBHeader {
throw new IIOException(String.format("Size: %s !=: %s", pSize, DIB.WINDOWS_V3_HEADER_SIZE)); throw new IIOException(String.format("Size: %s !=: %s", pSize, DIB.WINDOWS_V3_HEADER_SIZE));
} }
mSize = pSize; size = pSize;
mWidth = pStream.readInt(); width = pStream.readInt();
mHeight = pStream.readInt(); height = pStream.readInt();
mPlanes = pStream.readUnsignedShort(); planes = pStream.readUnsignedShort();
mBitCount = pStream.readUnsignedShort(); bitCount = pStream.readUnsignedShort();
mCompression = pStream.readInt(); compression = pStream.readInt();
mImageSize = pStream.readInt(); imageSize = pStream.readInt();
mXPixelsPerMeter = pStream.readInt(); xPixelsPerMeter = pStream.readInt();
mYPixelsPerMeter = pStream.readInt(); yPixelsPerMeter = pStream.readInt();
mColorsUsed = pStream.readInt(); colorsUsed = pStream.readInt();
mColorsImportant = pStream.readInt(); colorsImportant = pStream.readInt();
} }
} }
} }
@@ -41,10 +41,10 @@ import java.util.List;
* @version $Id: Directory.java,v 1.0 25.feb.2006 00:29:44 haku Exp$ * @version $Id: Directory.java,v 1.0 25.feb.2006 00:29:44 haku Exp$
*/ */
class Directory { class Directory {
private final List<DirectoryEntry> mEntries; private final List<DirectoryEntry> entries;
private Directory(int pImageCount) { private Directory(int pImageCount) {
mEntries = Arrays.asList(new DirectoryEntry[pImageCount]); entries = Arrays.asList(new DirectoryEntry[pImageCount]);
} }
public static Directory read(final int pType, final int pImageCount, final DataInput pStream) throws IOException { public static Directory read(final int pType, final int pImageCount, final DataInput pStream) throws IOException {
@@ -54,21 +54,21 @@ class Directory {
} }
private void readEntries(final int pType, final DataInput pStream) throws IOException { private void readEntries(final int pType, final DataInput pStream) throws IOException {
for (int i = 0; i < mEntries.size(); i++) { for (int i = 0; i < entries.size(); i++) {
mEntries.set(i, DirectoryEntry.read(pType, pStream)); entries.set(i, DirectoryEntry.read(pType, pStream));
} }
} }
public DirectoryEntry getEntry(final int pEntryIndex) { public DirectoryEntry getEntry(final int pEntryIndex) {
return mEntries.get(pEntryIndex); return entries.get(pEntryIndex);
} }
public int count() { public int count() {
return mEntries.size(); return entries.size();
} }
@Override @Override
public String toString() { public String toString() {
return String.format("%s%s", getClass().getSimpleName(), mEntries); return String.format("%s%s", getClass().getSimpleName(), entries);
} }
} }
@@ -31,7 +31,6 @@ package com.twelvemonkeys.imageio.plugins.ico;
import javax.imageio.IIOException; import javax.imageio.IIOException;
import java.io.DataInput; import java.io.DataInput;
import java.io.IOException; import java.io.IOException;
import java.awt.image.BufferedImage;
import java.awt.*; import java.awt.*;
/** /**
@@ -43,13 +42,13 @@ import java.awt.*;
* @see <a href="http://en.wikipedia.org/wiki/ICO_(icon_image_file_format)#Directory">Wikipedia</a> * @see <a href="http://en.wikipedia.org/wiki/ICO_(icon_image_file_format)#Directory">Wikipedia</a>
*/ */
abstract class DirectoryEntry { abstract class DirectoryEntry {
private int mWidth; private int width;
private int mHeight; private int height;
private int mColorCount; private int colorCount;
int mPlanes; int planes;
int mBitCount; int bitCount;
private int mSize; private int size;
private int mOffset; private int offset;
private DirectoryEntry() { private DirectoryEntry() {
} }
@@ -79,58 +78,58 @@ abstract class DirectoryEntry {
protected void read(final DataInput pStream) throws IOException { protected void read(final DataInput pStream) throws IOException {
// Width/height = 0, means 256 // Width/height = 0, means 256
int w = pStream.readUnsignedByte(); int w = pStream.readUnsignedByte();
mWidth = w == 0 ? 256 : w; width = w == 0 ? 256 : w;
int h = pStream.readUnsignedByte(); int h = pStream.readUnsignedByte();
mHeight = h == 0 ? 256 : h; height = h == 0 ? 256 : h;
// Color count = 0, means 256 or more colors // Color count = 0, means 256 or more colors
mColorCount = pStream.readUnsignedByte(); colorCount = pStream.readUnsignedByte();
// Ignore. Should be 0, but .NET (System.Drawing.Icon.Save) sets this value to 255, according to Wikipedia // Ignore. Should be 0, but .NET (System.Drawing.Icon.Save) sets this value to 255, according to Wikipedia
pStream.readUnsignedByte(); pStream.readUnsignedByte();
mPlanes = pStream.readUnsignedShort(); // Should be 0 or 1 for ICO, x hotspot for CUR planes = pStream.readUnsignedShort(); // Should be 0 or 1 for ICO, x hotspot for CUR
mBitCount = pStream.readUnsignedShort(); // bit count for ICO, y hotspot for CUR bitCount = pStream.readUnsignedShort(); // bit count for ICO, y hotspot for CUR
// Size of bitmap in bytes // Size of bitmap in bytes
mSize = pStream.readInt(); size = pStream.readInt();
mOffset = pStream.readInt(); offset = pStream.readInt();
} }
public String toString() { public String toString() {
return String.format( return String.format(
"%s: width: %d, height: %d, colors: %d, planes: %d, bit count: %d, size: %d, offset: %d", "%s: width: %d, height: %d, colors: %d, planes: %d, bit count: %d, size: %d, offset: %d",
getClass().getSimpleName(), getClass().getSimpleName(),
mWidth, mHeight, mColorCount, mPlanes, mBitCount, mSize, mOffset width, height, colorCount, planes, bitCount, size, offset
); );
} }
public int getBitCount() { public int getBitCount() {
return mBitCount; return bitCount;
} }
public int getColorCount() { public int getColorCount() {
return mColorCount; return colorCount;
} }
public int getHeight() { public int getHeight() {
return mHeight; return height;
} }
public int getOffset() { public int getOffset() {
return mOffset; return offset;
} }
public int getPlanes() { public int getPlanes() {
return mPlanes; return planes;
} }
public int getSize() { public int getSize() {
return mSize; return size;
} }
public int getWidth() { public int getWidth() {
return mWidth; return width;
} }
/** /**
@@ -145,11 +144,11 @@ abstract class DirectoryEntry {
super.read(pStream); super.read(pStream);
// NOTE: This is a hack... // NOTE: This is a hack...
mXHotspot = mPlanes; mXHotspot = planes;
mYHotspot = mBitCount; mYHotspot = bitCount;
mPlanes = 1; // Always 1 for all BMP types planes = 1; // Always 1 for all BMP types
mBitCount = 0; bitCount = 0;
} }
public Point getHotspot() { public Point getHotspot() {
@@ -69,13 +69,13 @@ import java.util.List;
// Known issue: 256x256 PNG encoded icons does not have IndexColorModel even if stated in DirectoryEntry (seem impossible as the PNGs are all true color) // Known issue: 256x256 PNG encoded icons does not have IndexColorModel even if stated in DirectoryEntry (seem impossible as the PNGs are all true color)
public class ICOImageReader extends ImageReaderBase { public class ICOImageReader extends ImageReaderBase {
// TODO: Consider moving the reading to inner classes (subclasses of BitmapDescriptor) // TODO: Consider moving the reading to inner classes (subclasses of BitmapDescriptor)
private Directory mDirectory; private Directory directory;
// TODO: Review these, make sure we don't have a memory leak // TODO: Review these, make sure we don't have a memory leak
private Map<DirectoryEntry, DIBHeader> mHeaders = new WeakHashMap<DirectoryEntry, DIBHeader>(); private Map<DirectoryEntry, DIBHeader> headers = new WeakHashMap<DirectoryEntry, DIBHeader>();
private Map<DirectoryEntry, BitmapDescriptor> mDescriptors = new WeakWeakMap<DirectoryEntry, BitmapDescriptor>(); private Map<DirectoryEntry, BitmapDescriptor> descriptors = new WeakWeakMap<DirectoryEntry, BitmapDescriptor>();
private ImageReader mPNGImageReader; private ImageReader pngImageReader;
public ICOImageReader() { public ICOImageReader() {
this(DIB.TYPE_ICO); this(DIB.TYPE_ICO);
@@ -101,14 +101,14 @@ public class ICOImageReader extends ImageReaderBase {
} }
protected void resetMembers() { protected void resetMembers() {
mDirectory = null; directory = null;
mHeaders.clear(); headers.clear();
mDescriptors.clear(); descriptors.clear();
if (mPNGImageReader != null) { if (pngImageReader != null) {
mPNGImageReader.dispose(); pngImageReader.dispose();
mPNGImageReader = null; pngImageReader = null;
} }
} }
@@ -158,7 +158,7 @@ public class ICOImageReader extends ImageReaderBase {
} }
@Override @Override
public int getNumImages(final boolean pAllowSearch) throws IOException { public int getNumImages(final boolean allowSearch) throws IOException {
return getDirectory().count(); return getDirectory().count();
} }
@@ -260,38 +260,38 @@ public class ICOImageReader extends ImageReaderBase {
private ImageReader getPNGReader() throws IIOException { private ImageReader getPNGReader() throws IIOException {
// TODO: Prefer Sun's std JDK PNGImagerReader, because it has known behaviour? // TODO: Prefer Sun's std JDK PNGImagerReader, because it has known behaviour?
if (mPNGImageReader == null) { if (pngImageReader == null) {
Iterator<ImageReader> readers = ImageIO.getImageReadersByFormatName("PNG"); Iterator<ImageReader> readers = ImageIO.getImageReadersByFormatName("PNG");
if (readers.hasNext()) { if (readers.hasNext()) {
mPNGImageReader = readers.next(); pngImageReader = readers.next();
} }
else { else {
throw new IIOException("No PNGImageReader found using ImageIO, can't read PNG encoded ICO format."); throw new IIOException("No PNGImageReader found using ImageIO, can't read PNG encoded ICO format.");
} }
} }
else { else {
mPNGImageReader.reset(); pngImageReader.reset();
} }
return mPNGImageReader; return pngImageReader;
} }
private DIBHeader getHeader(final DirectoryEntry pEntry) throws IOException { private DIBHeader getHeader(final DirectoryEntry pEntry) throws IOException {
if (!mHeaders.containsKey(pEntry)) { if (!headers.containsKey(pEntry)) {
imageInput.seek(pEntry.getOffset()); imageInput.seek(pEntry.getOffset());
DIBHeader header = DIBHeader.read(imageInput); DIBHeader header = DIBHeader.read(imageInput);
mHeaders.put(pEntry, header); headers.put(pEntry, header);
} }
return mHeaders.get(pEntry); return headers.get(pEntry);
} }
private BufferedImage readBitmap(final DirectoryEntry pEntry) throws IOException { private BufferedImage readBitmap(final DirectoryEntry pEntry) throws IOException {
// TODO: Get rid of the caching, as the images are mutable // TODO: Get rid of the caching, as the images are mutable
BitmapDescriptor descriptor = mDescriptors.get(pEntry); BitmapDescriptor descriptor = descriptors.get(pEntry);
if (descriptor == null || !mDescriptors.containsKey(pEntry)) { if (descriptor == null || !descriptors.containsKey(pEntry)) {
DIBHeader header = getHeader(pEntry); DIBHeader header = getHeader(pEntry);
int offset = pEntry.getOffset() + header.getSize(); int offset = pEntry.getOffset() + header.getSize();
@@ -333,7 +333,7 @@ public class ICOImageReader extends ImageReaderBase {
} }
} }
mDescriptors.put(pEntry, descriptor); descriptors.put(pEntry, descriptor);
} }
return descriptor.getImage(); return descriptor.getImage();
@@ -354,8 +354,8 @@ public class ICOImageReader extends ImageReaderBase {
break; break;
} }
BitmapMask mask = new BitmapMask(pBitmap.mEntry, pBitmap.mHeader); BitmapMask mask = new BitmapMask(pBitmap.entry, pBitmap.header);
readBitmapIndexed1(mask.mMask, true); readBitmapIndexed1(mask.mask, true);
pBitmap.setMask(mask); pBitmap.setMask(mask);
} }
@@ -364,7 +364,7 @@ public class ICOImageReader extends ImageReaderBase {
for (int i = 0; i < colorCount; i++) { for (int i = 0; i < colorCount; i++) {
// aRGB (a is "Reserved") // aRGB (a is "Reserved")
pBitmap.mColors[i] = (imageInput.readInt() & 0xffffff) | 0xff000000; pBitmap.colors[i] = (imageInput.readInt() & 0xffffff) | 0xff000000;
} }
} }
@@ -379,7 +379,7 @@ public class ICOImageReader extends ImageReaderBase {
int pos = (pBitmap.getHeight() - y - 1) * pBitmap.getWidth(); int pos = (pBitmap.getHeight() - y - 1) * pBitmap.getWidth();
for (int x = 0; x < pBitmap.getWidth(); x++) { for (int x = 0; x < pBitmap.getWidth(); x++) {
pBitmap.mBits[pos++] = ((row[rowPos] & xOrVal) / xOrVal) & 0xFF; pBitmap.bits[pos++] = ((row[rowPos] & xOrVal) / xOrVal) & 0xFF;
if (xOrVal == 1) { if (xOrVal == 1) {
xOrVal = 0x80; xOrVal = 0x80;
@@ -423,7 +423,7 @@ public class ICOImageReader extends ImageReaderBase {
rowPos++; rowPos++;
} }
pBitmap.mBits[pos++] = value & 0xFF; pBitmap.bits[pos++] = value & 0xFF;
high4 = !high4; high4 = !high4;
} }
@@ -447,7 +447,7 @@ public class ICOImageReader extends ImageReaderBase {
int pos = (pBitmap.getHeight() - y - 1) * pBitmap.getWidth(); int pos = (pBitmap.getHeight() - y - 1) * pBitmap.getWidth();
for (int x = 0; x < pBitmap.getWidth(); x++) { for (int x = 0; x < pBitmap.getWidth(); x++) {
pBitmap.mBits[pos++] = row[rowPos++] & 0xFF; pBitmap.bits[pos++] = row[rowPos++] & 0xFF;
} }
if (abortRequested()) { if (abortRequested()) {
@@ -480,7 +480,7 @@ public class ICOImageReader extends ImageReaderBase {
WritableRaster raster = Raster.createPackedRaster( WritableRaster raster = Raster.createPackedRaster(
buffer, pBitmap.getWidth(), pBitmap.getHeight(), pBitmap.getWidth(), cm.getMasks(), null buffer, pBitmap.getWidth(), pBitmap.getHeight(), pBitmap.getWidth(), cm.getMasks(), null
); );
pBitmap.mImage = new BufferedImage(cm, raster, cm.isAlphaPremultiplied(), null); pBitmap.image = new BufferedImage(cm, raster, cm.isAlphaPremultiplied(), null);
for (int y = 0; y < pBitmap.getHeight(); y++) { for (int y = 0; y < pBitmap.getHeight(); y++) {
int offset = (pBitmap.getHeight() - y - 1) * pBitmap.getWidth(); int offset = (pBitmap.getHeight() - y - 1) * pBitmap.getWidth();
@@ -516,7 +516,7 @@ public class ICOImageReader extends ImageReaderBase {
WritableRaster raster = Raster.createInterleavedRaster( WritableRaster raster = Raster.createInterleavedRaster(
buffer, pBitmap.getWidth(), pBitmap.getHeight(), pBitmap.getWidth(), 3, bOffs, null buffer, pBitmap.getWidth(), pBitmap.getHeight(), pBitmap.getWidth(), 3, bOffs, null
); );
pBitmap.mImage = new BufferedImage(cm, raster, cm.isAlphaPremultiplied(), null); pBitmap.image = new BufferedImage(cm, raster, cm.isAlphaPremultiplied(), null);
for (int y = 0; y < pBitmap.getHeight(); y++) { for (int y = 0; y < pBitmap.getHeight(); y++) {
int offset = (pBitmap.getHeight() - y - 1) * pBitmap.getWidth(); int offset = (pBitmap.getHeight() - y - 1) * pBitmap.getWidth();
@@ -542,7 +542,7 @@ public class ICOImageReader extends ImageReaderBase {
WritableRaster raster = Raster.createPackedRaster( WritableRaster raster = Raster.createPackedRaster(
buffer, pBitmap.getWidth(), pBitmap.getHeight(), pBitmap.getWidth(), cm.getMasks(), null buffer, pBitmap.getWidth(), pBitmap.getHeight(), pBitmap.getWidth(), cm.getMasks(), null
); );
pBitmap.mImage = new BufferedImage(cm, raster, cm.isAlphaPremultiplied(), null); pBitmap.image = new BufferedImage(cm, raster, cm.isAlphaPremultiplied(), null);
for (int y = 0; y < pBitmap.getHeight(); y++) { for (int y = 0; y < pBitmap.getHeight(); y++) {
int offset = (pBitmap.getHeight() - y - 1) * pBitmap.getWidth(); int offset = (pBitmap.getHeight() - y - 1) * pBitmap.getWidth();
@@ -559,11 +559,11 @@ public class ICOImageReader extends ImageReaderBase {
private Directory getDirectory() throws IOException { private Directory getDirectory() throws IOException {
assertInput(); assertInput();
if (mDirectory == null) { if (directory == null) {
readFileHeader(); readFileHeader();
} }
return mDirectory; return directory;
} }
private void readFileHeader() throws IOException { private void readFileHeader() throws IOException {
@@ -577,7 +577,7 @@ public class ICOImageReader extends ImageReaderBase {
int imageCount = imageInput.readUnsignedShort(); int imageCount = imageInput.readUnsignedShort();
// Read directory // Read directory
mDirectory = Directory.read(type, imageCount, imageInput); directory = Directory.read(type, imageCount, imageInput);
} }
final DirectoryEntry getEntry(final int pImageIndex) throws IOException { final DirectoryEntry getEntry(final int pImageIndex) throws IOException {
@@ -81,100 +81,98 @@ class BMHDChunk extends IFFChunk {
// words. The number of words per row is words=((w+15)/16) // words. The number of words per row is words=((w+15)/16)
// Dimensions of raster // Dimensions of raster
int mWidth; int width;
int mHeight; int height;
// Source offsets // Source offsets
// Hmm.. Consider making these Image.properties? // Hmm.. Consider making these Image.properties?
int mXPos; int xPos;
int mYPos; int yPos;
// The number of source bitplanes in the BODY chunk (see below) is stored in // The number of source bitplanes in the BODY chunk (see below) is stored in
// nPlanes. An ILBM with a CMAP but no BODY and nPlanes = 0 is the // nPlanes. An ILBM with a CMAP but no BODY and nPlanes = 0 is the
// recommended way to store a color map. // recommended way to store a color map.
int mBitplanes; int bitplanes;
int mMaskType; int maskType;
int mCompressionType; int compressionType;
int mTransparentIndex; int transparentIndex;
// NOTE: Typical values are 10:11 (320 x 200) // NOTE: Typical values are 10:11 (320 x 200)
int mXAspect; int xAspect;
int mYAspect; int yAspect;
// Source page dimension // Source page dimension
// NOTE: The image may be larger than the page, probably ignore these // NOTE: The image may be larger than the page, probably ignore these
int mPageWidth; int pageWidth;
int mPageHeight; int pageHeight;
protected BMHDChunk(int pChunkLength) { protected BMHDChunk(int pChunkLength) {
super(IFF.CHUNK_BMHD, pChunkLength); super(IFF.CHUNK_BMHD, pChunkLength);
} }
protected BMHDChunk(int pWidth, int pHeight, int pBitplanes, protected BMHDChunk(int pWidth, int pHeight, int pBitplanes, int pMaskType, int pCompressionType, int pTransparentIndex) {
int pMaskType, int pCompressionType,
int pTransparentIndex) {
super(IFF.CHUNK_BMHD, 20); super(IFF.CHUNK_BMHD, 20);
mWidth = pWidth; width = pWidth;
mHeight = pHeight; height = pHeight;
mXPos = 0; xPos = 0;
mYPos = 0; yPos = 0;
mBitplanes = pBitplanes; bitplanes = pBitplanes;
mMaskType = pMaskType; maskType = pMaskType;
mCompressionType = pCompressionType; compressionType = pCompressionType;
mTransparentIndex = pTransparentIndex; transparentIndex = pTransparentIndex;
mXAspect = 1; xAspect = 1;
mYAspect = 1; yAspect = 1;
mPageWidth = Math.min(pWidth, Short.MAX_VALUE); // For some reason, these are signed? pageWidth = Math.min(pWidth, Short.MAX_VALUE); // For some reason, these are signed?
mPageHeight = Math.min(pHeight, Short.MAX_VALUE); pageHeight = Math.min(pHeight, Short.MAX_VALUE);
} }
void readChunk(DataInput pInput) throws IOException { void readChunk(DataInput pInput) throws IOException {
if (mChunkLength != 20) { if (chunkLength != 20) {
throw new IIOException("Unknown BMHD chunk length: " + mChunkLength); throw new IIOException("Unknown BMHD chunk length: " + chunkLength);
} }
mWidth = pInput.readUnsignedShort(); width = pInput.readUnsignedShort();
mHeight = pInput.readUnsignedShort(); height = pInput.readUnsignedShort();
mXPos = pInput.readShort(); xPos = pInput.readShort();
mYPos = pInput.readShort(); yPos = pInput.readShort();
mBitplanes = pInput.readUnsignedByte(); bitplanes = pInput.readUnsignedByte();
mMaskType = pInput.readUnsignedByte(); maskType = pInput.readUnsignedByte();
mCompressionType = pInput.readUnsignedByte(); compressionType = pInput.readUnsignedByte();
pInput.readByte(); // PAD pInput.readByte(); // PAD
mTransparentIndex = pInput.readUnsignedShort(); transparentIndex = pInput.readUnsignedShort();
mXAspect = pInput.readUnsignedByte(); xAspect = pInput.readUnsignedByte();
mYAspect = pInput.readUnsignedByte(); yAspect = pInput.readUnsignedByte();
mPageWidth = pInput.readShort(); pageWidth = pInput.readShort();
mPageHeight = pInput.readShort(); pageHeight = pInput.readShort();
} }
void writeChunk(DataOutput pOutput) throws IOException { void writeChunk(DataOutput pOutput) throws IOException {
pOutput.writeInt(mChunkId); pOutput.writeInt(chunkId);
pOutput.writeInt(mChunkLength); pOutput.writeInt(chunkLength);
pOutput.writeShort(mWidth); pOutput.writeShort(width);
pOutput.writeShort(mHeight); pOutput.writeShort(height);
pOutput.writeShort(mXPos); pOutput.writeShort(xPos);
pOutput.writeShort(mYPos); pOutput.writeShort(yPos);
pOutput.writeByte(mBitplanes); pOutput.writeByte(bitplanes);
pOutput.writeByte(mMaskType); pOutput.writeByte(maskType);
pOutput.writeByte(mCompressionType); pOutput.writeByte(compressionType);
pOutput.writeByte(0); // PAD pOutput.writeByte(0); // PAD
pOutput.writeShort(mTransparentIndex); pOutput.writeShort(transparentIndex);
pOutput.writeByte(mXAspect); pOutput.writeByte(xAspect);
pOutput.writeByte(mYAspect); pOutput.writeByte(yAspect);
pOutput.writeShort(mPageWidth); pOutput.writeShort(pageWidth);
pOutput.writeShort(mPageHeight); pOutput.writeShort(pageHeight);
} }
public String toString() { public String toString() {
return super.toString() return super.toString()
+ " {w=" + mWidth + ", h=" + mHeight + " {w=" + width + ", h=" + height
+ ", x=" + mXPos + ", y=" + mYPos + ", x=" + xPos + ", y=" + yPos
+ ", planes=" + mBitplanes + ", mask=" + mMaskType + ", planes=" + bitplanes + ", mask=" + maskType
+ ", compression=" + mCompressionType + ", trans=" + mTransparentIndex + ", compression=" + compressionType + ", trans=" + transparentIndex
+ ", xAspect=" + mXAspect + ", yAspect=" + mYAspect + ", xAspect=" + xAspect + ", yAspect=" + yAspect
+ ", pageWidth=" + mPageWidth + ", pageHeight=" + mPageHeight + "}"; + ", pageWidth=" + pageWidth + ", pageHeight=" + pageHeight + "}";
} }
} }
@@ -40,7 +40,6 @@ import java.io.DataOutput;
* @version $Id: BODYChunk.java,v 1.0 28.feb.2006 01:25:49 haku Exp$ * @version $Id: BODYChunk.java,v 1.0 28.feb.2006 01:25:49 haku Exp$
*/ */
class BODYChunk extends IFFChunk { class BODYChunk extends IFFChunk {
protected BODYChunk(int pChunkLength) { protected BODYChunk(int pChunkLength) {
super(IFF.CHUNK_BODY, pChunkLength); super(IFF.CHUNK_BODY, pChunkLength);
} }
@@ -41,22 +41,21 @@ import java.io.IOException;
* @version $Id: CAMGChunk.java,v 1.0 28.feb.2006 02:10:07 haku Exp$ * @version $Id: CAMGChunk.java,v 1.0 28.feb.2006 02:10:07 haku Exp$
*/ */
class CAMGChunk extends IFFChunk { class CAMGChunk extends IFFChunk {
// HIRES=0x8000, LACE=0x4 // HIRES=0x8000, LACE=0x4
// #define CAMG_HAM 0x800 /* hold and modify */ // #define CAMG_HAM 0x800 /* hold and modify */
// #define CAMG_EHB 0x80 /* extra halfbrite */ // #define CAMG_EHB 0x80 /* extra halfbrite */
private int mCAMG; private int camg;
public CAMGChunk(int pLength) { public CAMGChunk(int pLength) {
super(IFF.CHUNK_CAMG, pLength); super(IFF.CHUNK_CAMG, pLength);
} }
void readChunk(DataInput pInput) throws IOException { void readChunk(DataInput pInput) throws IOException {
if (mChunkLength != 4) { if (chunkLength != 4) {
throw new IIOException("Unknown CAMG chunk length: " + mChunkLength); throw new IIOException("Unknown CAMG chunk length: " + chunkLength);
} }
mCAMG = pInput.readInt(); camg = pInput.readInt();
} }
void writeChunk(DataOutput pOutput) throws IOException { void writeChunk(DataOutput pOutput) throws IOException {
@@ -64,11 +63,11 @@ class CAMGChunk extends IFFChunk {
} }
boolean isHAM() { boolean isHAM() {
return (mCAMG & 0x800) != 0; return (camg & 0x800) != 0;
} }
boolean isEHB() { boolean isEHB() {
return (mCAMG & 0x80) != 0; return (camg & 0x80) != 0;
} }
public String toString() { public String toString() {
@@ -54,34 +54,34 @@ class CMAPChunk extends IFFChunk {
// typedef ColorRegister ColorMap[n]; /* size = 3n bytes */ // typedef ColorRegister ColorMap[n]; /* size = 3n bytes */
byte[] mReds; byte[] reds;
byte[] mGreens; byte[] greens;
byte[] mBlues; byte[] blues;
boolean mEHB; boolean ehb;
final private BMHDChunk mHeader; final private BMHDChunk header;
final private CAMGChunk mCamg; final private CAMGChunk camg;
private IndexColorModel mModel; private IndexColorModel model;
protected CMAPChunk(int pChunkLength, BMHDChunk pHeader, CAMGChunk pCamg) { protected CMAPChunk(int pChunkLength, BMHDChunk pHeader, CAMGChunk pCamg) {
super(IFF.CHUNK_CMAP, pChunkLength); super(IFF.CHUNK_CMAP, pChunkLength);
mHeader = pHeader; header = pHeader;
mCamg = pCamg; camg = pCamg;
} }
public CMAPChunk(IndexColorModel pModel) { public CMAPChunk(IndexColorModel pModel) {
super(IFF.CHUNK_CMAP, pModel.getMapSize() * 3); super(IFF.CHUNK_CMAP, pModel.getMapSize() * 3);
mModel = pModel; model = pModel;
mHeader = null; header = null;
mCamg = null; camg = null;
} }
void readChunk(DataInput pInput) throws IOException { void readChunk(DataInput pInput) throws IOException {
int numColors = mChunkLength / 3; int numColors = chunkLength / 3;
int paletteSize = numColors; int paletteSize = numColors;
boolean isEHB = mCamg != null && mCamg.isEHB(); boolean isEHB = camg != null && camg.isEHB();
if (isEHB) { if (isEHB) {
if (numColors == 32) { if (numColors == 32) {
paletteSize = 64; paletteSize = 64;
@@ -91,22 +91,22 @@ class CMAPChunk extends IFFChunk {
} }
} }
mReds = new byte[paletteSize]; reds = new byte[paletteSize];
mGreens = mReds.clone(); greens = reds.clone();
mBlues = mReds.clone(); blues = reds.clone();
for (int i = 0; i < numColors; i++) { for (int i = 0; i < numColors; i++) {
mReds[i] = pInput.readByte(); reds[i] = pInput.readByte();
mGreens[i] = pInput.readByte(); greens[i] = pInput.readByte();
mBlues[i] = pInput.readByte(); blues[i] = pInput.readByte();
} }
if (isEHB && numColors == 32) { if (isEHB && numColors == 32) {
// Create the half-brite colors // Create the half-brite colors
for (int i = 0; i < numColors; i++) { for (int i = 0; i < numColors; i++) {
mReds[i + numColors] = (byte) ((mReds[i] & 0xff) / 2); reds[i + numColors] = (byte) ((reds[i] & 0xff) / 2);
mGreens[i + numColors] = (byte) ((mGreens[i] & 0xff) / 2); greens[i + numColors] = (byte) ((greens[i] & 0xff) / 2);
mBlues[i + numColors] = (byte) ((mBlues[i] & 0xff) / 2); blues[i + numColors] = (byte) ((blues[i] & 0xff) / 2);
} }
} }
@@ -120,7 +120,7 @@ class CMAPChunk extends IFFChunk {
// R8 := (Rn x 255 ) / maxColor // R8 := (Rn x 255 ) / maxColor
// All chunks are WORD aligned (even sized), may need to read pad... // All chunks are WORD aligned (even sized), may need to read pad...
if (mChunkLength % 2 != 0) { if (chunkLength % 2 != 0) {
pInput.readByte(); pInput.readByte();
} }
@@ -128,33 +128,33 @@ class CMAPChunk extends IFFChunk {
// Would it work to double to numbers of colors, and create an indexcolormodel, // Would it work to double to numbers of colors, and create an indexcolormodel,
// with alpha, where all colors above the original color is all transparent? // with alpha, where all colors above the original color is all transparent?
// This is a waste of time and space, of course... // This is a waste of time and space, of course...
int trans = mHeader.mMaskType == BMHDChunk.MASK_TRANSPARENT_COLOR ? mHeader.mTransparentIndex : -1; int trans = header.maskType == BMHDChunk.MASK_TRANSPARENT_COLOR ? header.transparentIndex : -1;
mModel = new InverseColorMapIndexColorModel(mHeader.mBitplanes, mReds.length, mReds, mGreens, mBlues, trans); model = new InverseColorMapIndexColorModel(header.bitplanes, reds.length, reds, greens, blues, trans);
} }
void writeChunk(DataOutput pOutput) throws IOException { void writeChunk(DataOutput pOutput) throws IOException {
pOutput.writeInt(mChunkId); pOutput.writeInt(chunkId);
pOutput.writeInt(mChunkLength); pOutput.writeInt(chunkLength);
final int length = mModel.getMapSize(); final int length = model.getMapSize();
for (int i = 0; i < length; i++) { for (int i = 0; i < length; i++) {
pOutput.writeByte(mModel.getRed(i)); pOutput.writeByte(model.getRed(i));
pOutput.writeByte(mModel.getGreen(i)); pOutput.writeByte(model.getGreen(i));
pOutput.writeByte(mModel.getBlue(i)); pOutput.writeByte(model.getBlue(i));
} }
if (mChunkLength % 2 != 0) { if (chunkLength % 2 != 0) {
pOutput.writeByte(0); // PAD pOutput.writeByte(0); // PAD
} }
} }
public String toString() { public String toString() {
return super.toString() + " {colorMap=" + mModel + "}"; return super.toString() + " {colorMap=" + model + "}";
} }
IndexColorModel getIndexColorModel() { IndexColorModel getIndexColorModel() {
return mModel; return model;
} }
public BufferedImage createPaletteImage() { public BufferedImage createPaletteImage() {
@@ -47,7 +47,7 @@ class GRABChunk extends IFFChunk {
// WORD x, y; /* relative coordinates (pixels) */ // WORD x, y; /* relative coordinates (pixels) */
// } Point2D; // } Point2D;
Point2D mPoint; Point2D point;
protected GRABChunk(int pChunkLength) { protected GRABChunk(int pChunkLength) {
super(IFF.CHUNK_GRAB, pChunkLength); super(IFF.CHUNK_GRAB, pChunkLength);
@@ -55,22 +55,22 @@ class GRABChunk extends IFFChunk {
protected GRABChunk(Point2D pPoint) { protected GRABChunk(Point2D pPoint) {
super(IFF.CHUNK_GRAB, 4); super(IFF.CHUNK_GRAB, 4);
mPoint = pPoint; point = pPoint;
} }
void readChunk(DataInput pInput) throws IOException { void readChunk(DataInput pInput) throws IOException {
if (mChunkLength != 4) { if (chunkLength != 4) {
throw new IIOException("Unknown GRAB chunk size: " + mChunkLength); throw new IIOException("Unknown GRAB chunk size: " + chunkLength);
} }
mPoint = new Point(pInput.readShort(), pInput.readShort()); point = new Point(pInput.readShort(), pInput.readShort());
} }
void writeChunk(DataOutput pOutput) throws IOException { void writeChunk(DataOutput pOutput) throws IOException {
pOutput.writeShort((int) mPoint.getX()); pOutput.writeShort((int) point.getX());
pOutput.writeShort((int) mPoint.getY()); pOutput.writeShort((int) point.getY());
} }
public String toString() { public String toString() {
return super.toString() + " {point=" + mPoint + "}"; return super.toString() + " {point=" + point + "}";
} }
} }
@@ -41,45 +41,45 @@ import java.io.DataOutput;
*/ */
class GenericChunk extends IFFChunk { class GenericChunk extends IFFChunk {
byte[] mData; byte[] data;
protected GenericChunk(int pChunkId, int pChunkLength) { protected GenericChunk(int pChunkId, int pChunkLength) {
super(pChunkId, pChunkLength); super(pChunkId, pChunkLength);
mData = new byte[pChunkLength <= 50 ? pChunkLength : 47]; data = new byte[pChunkLength <= 50 ? pChunkLength : 47];
} }
protected GenericChunk(int pChunkId, byte[] pChunkData) { protected GenericChunk(int pChunkId, byte[] pChunkData) {
super(pChunkId, pChunkData.length); super(pChunkId, pChunkData.length);
mData = pChunkData; data = pChunkData;
} }
void readChunk(DataInput pInput) throws IOException { void readChunk(DataInput pInput) throws IOException {
pInput.readFully(mData, 0, mData.length); pInput.readFully(data, 0, data.length);
int toSkip = mChunkLength - mData.length; int toSkip = chunkLength - data.length;
while (toSkip > 0) { while (toSkip > 0) {
toSkip -= pInput.skipBytes(toSkip); toSkip -= pInput.skipBytes(toSkip);
} }
// Read pad // Read pad
if (mChunkLength % 2 != 0) { if (chunkLength % 2 != 0) {
pInput.readByte(); pInput.readByte();
} }
} }
void writeChunk(DataOutput pOutput) throws IOException { void writeChunk(DataOutput pOutput) throws IOException {
pOutput.writeInt(mChunkId); pOutput.writeInt(chunkId);
pOutput.writeInt(mChunkLength); pOutput.writeInt(chunkLength);
pOutput.write(mData, 0, mData.length); pOutput.write(data, 0, data.length);
if (mData.length % 2 != 0) { if (data.length % 2 != 0) {
pOutput.writeByte(0); // PAD pOutput.writeByte(0); // PAD
} }
} }
public String toString() { public String toString() {
return super.toString() + " {value=\"" return super.toString() + " {value=\""
+ new String(mData, 0, mData.length <= 50 ? mData.length : 47) + new String(data, 0, data.length <= 50 ? data.length : 47)
+ (mChunkLength <= 50 ? "" : "...") + "\"}"; + (chunkLength <= 50 ? "" : "...") + "\"}";
} }
} }
@@ -40,12 +40,12 @@ import java.io.DataOutput;
* @version $Id: IFFChunk.java,v 1.0 28.feb.2006 00:00:45 haku Exp$ * @version $Id: IFFChunk.java,v 1.0 28.feb.2006 00:00:45 haku Exp$
*/ */
abstract class IFFChunk { abstract class IFFChunk {
int mChunkId; int chunkId;
int mChunkLength; int chunkLength;
protected IFFChunk(int pChunkId, int pChunkLength) { protected IFFChunk(int pChunkId, int pChunkLength) {
mChunkId = pChunkId; chunkId = pChunkId;
mChunkLength = pChunkLength; chunkLength = pChunkLength;
} }
abstract void readChunk(DataInput pInput) throws IOException; abstract void readChunk(DataInput pInput) throws IOException;
@@ -53,6 +53,6 @@ abstract class IFFChunk {
abstract void writeChunk(DataOutput pOutput) throws IOException; abstract void writeChunk(DataOutput pOutput) throws IOException;
public String toString() { public String toString() {
return IFFUtil.toChunkStr(mChunkId) + " chunk (" + mChunkLength + " bytes)"; return IFFUtil.toChunkStr(chunkId) + " chunk (" + chunkLength + " bytes)";
} }
} }
@@ -96,16 +96,17 @@ public class IFFImageReader extends ImageReaderBase {
// - Contains definitions of some "new" chunks, as well as alternative FORM types // - Contains definitions of some "new" chunks, as well as alternative FORM types
// http://amigan.1emu.net/reg/iff.html // http://amigan.1emu.net/reg/iff.html
private BMHDChunk mHeader; private BMHDChunk header;
private CMAPChunk mColorMap; private CMAPChunk colorMap;
private BODYChunk mBody; private BODYChunk body;
private GRABChunk mGrab; @SuppressWarnings({"FieldCanBeLocal"})
private CAMGChunk mViewPort; private GRABChunk grab;
private int mFormType; private CAMGChunk viewPort;
private long mBodyStart; private int formType;
private long bodyStart;
private BufferedImage mImage; private BufferedImage image;
private DataInputStream mByteRunStream; private DataInputStream byteRunStream;
public IFFImageReader() { public IFFImageReader() {
super(IFFImageReaderSpi.sharedProvider()); super(IFFImageReaderSpi.sharedProvider());
@@ -118,20 +119,20 @@ public class IFFImageReader extends ImageReaderBase {
private void init(int pIndex) throws IOException { private void init(int pIndex) throws IOException {
checkBounds(pIndex); checkBounds(pIndex);
if (mHeader == null) { if (header == null) {
readMeta(); readMeta();
} }
} }
protected void resetMembers() { protected void resetMembers() {
mHeader = null; header = null;
mColorMap = null; colorMap = null;
mBody = null; body = null;
mViewPort = null; viewPort = null;
mFormType = 0; formType = 0;
mImage = null; image = null;
mByteRunStream = null; byteRunStream = null;
} }
private void readMeta() throws IOException { private void readMeta() throws IOException {
@@ -141,15 +142,15 @@ public class IFFImageReader extends ImageReaderBase {
int remaining = imageInput.readInt() - 4; // We'll read 4 more in a sec int remaining = imageInput.readInt() - 4; // We'll read 4 more in a sec
mFormType = imageInput.readInt(); formType = imageInput.readInt();
if (mFormType != IFF.TYPE_ILBM && mFormType != IFF.TYPE_PBM) { if (formType != IFF.TYPE_ILBM && formType != IFF.TYPE_PBM) {
throw new IIOException("Only IFF (FORM) type ILBM and PBM supported: " + IFFUtil.toChunkStr(mFormType)); throw new IIOException("Only IFF (FORM) type ILBM and PBM supported: " + IFFUtil.toChunkStr(formType));
} }
//System.out.println("IFF type FORM " + toChunkStr(type)); //System.out.println("IFF type FORM " + toChunkStr(type));
mGrab = null; grab = null;
mViewPort = null; viewPort = null;
while (remaining > 0) { while (remaining > 0) {
int chunkId = imageInput.readInt(); int chunkId = imageInput.readInt();
@@ -163,49 +164,49 @@ public class IFFImageReader extends ImageReaderBase {
switch (chunkId) { switch (chunkId) {
case IFF.CHUNK_BMHD: case IFF.CHUNK_BMHD:
if (mHeader != null) { if (header != null) {
throw new IIOException("Multiple BMHD chunks not allowed"); throw new IIOException("Multiple BMHD chunks not allowed");
} }
mHeader = new BMHDChunk(length); header = new BMHDChunk(length);
mHeader.readChunk(imageInput); header.readChunk(imageInput);
//System.out.println(mHeader); //System.out.println(header);
break; break;
case IFF.CHUNK_CMAP: case IFF.CHUNK_CMAP:
if (mColorMap != null) { if (colorMap != null) {
throw new IIOException("Multiple CMAP chunks not allowed"); throw new IIOException("Multiple CMAP chunks not allowed");
} }
mColorMap = new CMAPChunk(length, mHeader, mViewPort); colorMap = new CMAPChunk(length, header, viewPort);
mColorMap.readChunk(imageInput); colorMap.readChunk(imageInput);
//System.out.println(mColorMap); //System.out.println(colorMap);
break; break;
case IFF.CHUNK_GRAB: case IFF.CHUNK_GRAB:
if (mGrab != null) { if (grab != null) {
throw new IIOException("Multiple GRAB chunks not allowed"); throw new IIOException("Multiple GRAB chunks not allowed");
} }
mGrab = new GRABChunk(length); grab = new GRABChunk(length);
mGrab.readChunk(imageInput); grab.readChunk(imageInput);
//System.out.println(mGrab); //System.out.println(grab);
break; break;
case IFF.CHUNK_CAMG: case IFF.CHUNK_CAMG:
if (mViewPort != null) { if (viewPort != null) {
throw new IIOException("Multiple CAMG chunks not allowed"); throw new IIOException("Multiple CAMG chunks not allowed");
} }
mViewPort = new CAMGChunk(length); viewPort = new CAMGChunk(length);
mViewPort.readChunk(imageInput); viewPort.readChunk(imageInput);
//System.out.println(mViewPort); //System.out.println(viewPort);
break; break;
case IFF.CHUNK_BODY: case IFF.CHUNK_BODY:
if (mBody != null) { if (body != null) {
throw new IIOException("Multiple BODY chunks not allowed"); throw new IIOException("Multiple BODY chunks not allowed");
} }
mBody = new BODYChunk(length); body = new BODYChunk(length);
mBodyStart = imageInput.getStreamPosition(); bodyStart = imageInput.getStreamPosition();
// NOTE: We don't read the body here, it's done later in the read(int, ImageReadParam) method // NOTE: We don't read the body here, it's done later in the read(int, ImageReadParam) method
@@ -228,23 +229,23 @@ public class IFFImageReader extends ImageReaderBase {
processImageStarted(pIndex); processImageStarted(pIndex);
mImage = getDestination(pParam, getImageTypes(pIndex), mHeader.mWidth, mHeader.mHeight); image = getDestination(pParam, getImageTypes(pIndex), header.width, header.height);
//System.out.println(mBody); //System.out.println(body);
if (mBody != null) { if (body != null) {
//System.out.println("Read body"); //System.out.println("Read body");
readBody(pParam); readBody(pParam);
} }
else { else {
// TODO: Remove this hack when we have metadata // TODO: Remove this hack when we have metadata
// In the rare case of an ILBM containing nothing but a CMAP // In the rare case of an ILBM containing nothing but a CMAP
//System.out.println(mColorMap); //System.out.println(colorMap);
if (mColorMap != null) { if (colorMap != null) {
//System.out.println("Creating palette!"); //System.out.println("Creating palette!");
mImage = mColorMap.createPaletteImage(); image = colorMap.createPaletteImage();
} }
} }
BufferedImage result = mImage; BufferedImage result = image;
processImageComplete(); processImageComplete();
@@ -253,12 +254,12 @@ public class IFFImageReader extends ImageReaderBase {
public int getWidth(int pIndex) throws IOException { public int getWidth(int pIndex) throws IOException {
init(pIndex); init(pIndex);
return mHeader.mWidth; return header.width;
} }
public int getHeight(int pIndex) throws IOException { public int getHeight(int pIndex) throws IOException {
init(pIndex); init(pIndex);
return mHeader.mHeight; return header.height;
} }
public Iterator<ImageTypeSpecifier> getImageTypes(int pIndex) throws IOException { public Iterator<ImageTypeSpecifier> getImageTypes(int pIndex) throws IOException {
@@ -266,8 +267,8 @@ public class IFFImageReader extends ImageReaderBase {
List<ImageTypeSpecifier> types = Arrays.asList( List<ImageTypeSpecifier> types = Arrays.asList(
getRawImageType(pIndex), getRawImageType(pIndex),
ImageTypeSpecifier.createFromBufferedImageType(mHeader.mBitplanes == 32 ? BufferedImage.TYPE_4BYTE_ABGR : BufferedImage.TYPE_3BYTE_BGR) ImageTypeSpecifier.createFromBufferedImageType(header.bitplanes == 32 ? BufferedImage.TYPE_4BYTE_ABGR : BufferedImage.TYPE_3BYTE_BGR)
// TODO: ImageTypeSpecifier.createFromBufferedImageType(mHeader.mBitplanes == 32 ? BufferedImage.TYPE_INT_ARGB : BufferedImage.TYPE_INT_RGB), // TODO: ImageTypeSpecifier.createFromBufferedImageType(header.bitplanes == 32 ? BufferedImage.TYPE_INT_ARGB : BufferedImage.TYPE_INT_RGB),
// TODO: Allow 32 bit always. Allow RGB and discard alpha, if present? // TODO: Allow 32 bit always. Allow RGB and discard alpha, if present?
); );
return types.iterator(); return types.iterator();
@@ -278,9 +279,9 @@ public class IFFImageReader extends ImageReaderBase {
init(pIndex); init(pIndex);
// TODO: Stay DRY... // TODO: Stay DRY...
// TODO: Use this for creating the Image/Buffer in the read code below... // TODO: Use this for creating the Image/Buffer in the read code below...
// NOTE: mColorMap may be null for 8 bit (gray), 24 bit or 32 bit only // NOTE: colorMap may be null for 8 bit (gray), 24 bit or 32 bit only
ImageTypeSpecifier specifier; ImageTypeSpecifier specifier;
switch (mHeader.mBitplanes) { switch (header.bitplanes) {
case 1: case 1:
// 1 bit // 1 bit
case 2: case 2:
@@ -297,8 +298,8 @@ public class IFFImageReader extends ImageReaderBase {
// 8 bit // 8 bit
// May be HAM8 // May be HAM8
if (!isHAM()) { if (!isHAM()) {
if (mColorMap != null) { if (colorMap != null) {
IndexColorModel cm = mColorMap.getIndexColorModel(); IndexColorModel cm = colorMap.getIndexColorModel();
specifier = IndexedImageTypeSpecifier.createFromIndexColorModel(cm); specifier = IndexedImageTypeSpecifier.createFromIndexColorModel(cm);
break; break;
} }
@@ -317,18 +318,18 @@ public class IFFImageReader extends ImageReaderBase {
specifier = ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_4BYTE_ABGR); specifier = ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_4BYTE_ABGR);
break; break;
default: default:
throw new IIOException(String.format("Bit depth not implemented: %d", mHeader.mBitplanes)); throw new IIOException(String.format("Bit depth not implemented: %d", header.bitplanes));
} }
return specifier; return specifier;
} }
private void readBody(final ImageReadParam pParam) throws IOException { private void readBody(final ImageReadParam pParam) throws IOException {
imageInput.seek(mBodyStart); imageInput.seek(bodyStart);
mByteRunStream = null; byteRunStream = null;
// NOTE: mColorMap may be null for 8 bit (gray), 24 bit or 32 bit only // NOTE: colorMap may be null for 8 bit (gray), 24 bit or 32 bit only
if (mColorMap != null) { if (colorMap != null) {
IndexColorModel cm = mColorMap.getIndexColorModel(); IndexColorModel cm = colorMap.getIndexColorModel();
readIndexed(pParam, imageInput, cm); readIndexed(pParam, imageInput, cm);
} }
else { else {
@@ -338,8 +339,8 @@ public class IFFImageReader extends ImageReaderBase {
} }
private void readIndexed(final ImageReadParam pParam, final ImageInputStream pInput, final IndexColorModel pModel) throws IOException { private void readIndexed(final ImageReadParam pParam, final ImageInputStream pInput, final IndexColorModel pModel) throws IOException {
final int width = mHeader.mWidth; final int width = header.width;
final int height = mHeader.mHeight; final int height = header.height;
final Rectangle aoi = getSourceRegion(pParam, width, height); final Rectangle aoi = getSourceRegion(pParam, width, height);
final Point offset = pParam == null ? new Point(0, 0) : pParam.getDestinationOffset(); final Point offset = pParam == null ? new Point(0, 0) : pParam.getDestinationOffset();
@@ -360,9 +361,9 @@ public class IFFImageReader extends ImageReaderBase {
} }
// Ensure band settings from param are compatible with images // Ensure band settings from param are compatible with images
checkReadParamBandSettings(pParam, isHAM() ? 3 : 1, mImage.getSampleModel().getNumBands()); checkReadParamBandSettings(pParam, isHAM() ? 3 : 1, image.getSampleModel().getNumBands());
WritableRaster destination = mImage.getRaster(); WritableRaster destination = image.getRaster();
if (destinationBands != null || offset.x != 0 || offset.y != 0) { if (destinationBands != null || offset.x != 0 || offset.y != 0) {
destination = destination.createWritableChild(0, 0, destination.getWidth(), destination.getHeight(), offset.x, offset.y, destinationBands); destination = destination.createWritableChild(0, 0, destination.getWidth(), destination.getHeight(), offset.x, offset.y, destinationBands);
} }
@@ -403,7 +404,7 @@ public class IFFImageReader extends ImageReaderBase {
final byte[] data = ((DataBufferByte) raster.getDataBuffer()).getData(); final byte[] data = ((DataBufferByte) raster.getDataBuffer()).getData();
final int planes = mHeader.mBitplanes; final int planes = header.bitplanes;
Object dataElements = null; Object dataElements = null;
Object outDataElements = null; Object outDataElements = null;
@@ -422,7 +423,7 @@ public class IFFImageReader extends ImageReaderBase {
return; return;
} }
if (mFormType == IFF.TYPE_ILBM) { if (formType == IFF.TYPE_ILBM) {
int pixelPos = 0; int pixelPos = 0;
for (int planePos = 0; planePos < planeWidth; planePos++) { for (int planePos = 0; planePos < planeWidth; planePos++) {
IFFUtil.bitRotateCW(planeData, planePos, planeWidth, row, pixelPos, 1); IFFUtil.bitRotateCW(planeData, planePos, planeWidth, row, pixelPos, 1);
@@ -436,13 +437,13 @@ public class IFFImageReader extends ImageReaderBase {
raster.setDataElements(0, 0, width, 1, row); raster.setDataElements(0, 0, width, 1, row);
} }
} }
else if (mFormType == IFF.TYPE_PBM) { else if (formType == IFF.TYPE_PBM) {
// TODO: Arraycopy might not be necessary, if it's okay with row larger than width // TODO: Arraycopy might not be necessary, if it's okay with row larger than width
System.arraycopy(planeData, 0, row, 0, mHeader.mBitplanes * planeWidth); System.arraycopy(planeData, 0, row, 0, header.bitplanes * planeWidth);
raster.setDataElements(0, 0, width, 1, row); raster.setDataElements(0, 0, width, 1, row);
} }
else { else {
throw new AssertionError(String.format("Unsupported FORM type: %s", mFormType)); throw new AssertionError(String.format("Unsupported FORM type: %s", formType));
} }
int dstY = (srcY - aoi.y) / sourceYSubsampling; int dstY = (srcY - aoi.y) / sourceYSubsampling;
@@ -470,7 +471,7 @@ public class IFFImageReader extends ImageReaderBase {
for (int srcX = 0; srcX < sourceRow.getWidth(); srcX += sourceXSubsampling) { for (int srcX = 0; srcX < sourceRow.getWidth(); srcX += sourceXSubsampling) {
dataElements = sourceRow.getDataElements(srcX, 0, dataElements); dataElements = sourceRow.getDataElements(srcX, 0, dataElements);
int rgb = icm.getRGB(dataElements); int rgb = icm.getRGB(dataElements);
outDataElements = mImage.getColorModel().getDataElements(rgb, outDataElements); outDataElements = image.getColorModel().getDataElements(rgb, outDataElements);
int dstX = srcX / sourceXSubsampling; int dstX = srcX / sourceXSubsampling;
destination.setDataElements(dstX, dstY, outDataElements); destination.setDataElements(dstX, dstY, outDataElements);
} }
@@ -479,7 +480,7 @@ public class IFFImageReader extends ImageReaderBase {
// TODO: This branch is never tested, and is probably "dead" // TODO: This branch is never tested, and is probably "dead"
// ColorConvertOp // ColorConvertOp
if (converter == null) { if (converter == null) {
converter = new ColorConvertOp(cm.getColorSpace(), mImage.getColorModel().getColorSpace(), null); converter = new ColorConvertOp(cm.getColorSpace(), image.getColorModel().getColorSpace(), null);
} }
converter.filter( converter.filter(
raster.createChild(aoi.x, 0, aoi.width, 1, 0, 0, null), raster.createChild(aoi.x, 0, aoi.width, 1, 0, 0, null),
@@ -488,7 +489,7 @@ public class IFFImageReader extends ImageReaderBase {
} }
} }
processImageProgress(srcY * 100f / mHeader.mWidth); processImageProgress(srcY * 100f / header.width);
if (abortRequested()) { if (abortRequested()) {
processReadAborted(); processReadAborted();
break; break;
@@ -502,8 +503,8 @@ public class IFFImageReader extends ImageReaderBase {
// bit of the red value for each pixel, and the last holds the most // bit of the red value for each pixel, and the last holds the most
// significant bit of the blue value. // significant bit of the blue value.
private void readTrueColor(ImageReadParam pParam, final ImageInputStream pInput) throws IOException { private void readTrueColor(ImageReadParam pParam, final ImageInputStream pInput) throws IOException {
final int width = mHeader.mWidth; final int width = header.width;
final int height = mHeader.mHeight; final int height = header.height;
final Rectangle aoi = getSourceRegion(pParam, width, height); final Rectangle aoi = getSourceRegion(pParam, width, height);
final Point offset = pParam == null ? new Point(0, 0) : pParam.getDestinationOffset(); final Point offset = pParam == null ? new Point(0, 0) : pParam.getDestinationOffset();
@@ -524,23 +525,23 @@ public class IFFImageReader extends ImageReaderBase {
} }
// Ensure band settings from param are compatible with images // Ensure band settings from param are compatible with images
checkReadParamBandSettings(pParam, mHeader.mBitplanes / 8, mImage.getSampleModel().getNumBands()); checkReadParamBandSettings(pParam, header.bitplanes / 8, image.getSampleModel().getNumBands());
// NOTE: Each row of the image is stored in an integral number of 16 bit words. // NOTE: Each row of the image is stored in an integral number of 16 bit words.
// The number of words per row is words=((w+15)/16) // The number of words per row is words=((w+15)/16)
int planeWidth = 2 * ((width + 15) / 16); int planeWidth = 2 * ((width + 15) / 16);
final byte[] planeData = new byte[8 * planeWidth]; final byte[] planeData = new byte[8 * planeWidth];
WritableRaster destination = mImage.getRaster(); WritableRaster destination = image.getRaster();
if (destinationBands != null || offset.x != 0 || offset.y != 0) { if (destinationBands != null || offset.x != 0 || offset.y != 0) {
destination = destination.createWritableChild(0, 0, destination.getWidth(), destination.getHeight(), offset.x, offset.y, destinationBands); destination = destination.createWritableChild(0, 0, destination.getWidth(), destination.getHeight(), offset.x, offset.y, destinationBands);
} }
// WritableRaster raster = mImage.getRaster().createCompatibleWritableRaster(width, 1); // WritableRaster raster = image.getRaster().createCompatibleWritableRaster(width, 1);
WritableRaster raster = mImage.getRaster().createCompatibleWritableRaster(8 * planeWidth, 1); WritableRaster raster = image.getRaster().createCompatibleWritableRaster(8 * planeWidth, 1);
Raster sourceRow = raster.createChild(aoi.x, 0, aoi.width, 1, 0, 0, sourceBands); Raster sourceRow = raster.createChild(aoi.x, 0, aoi.width, 1, 0, 0, sourceBands);
final byte[] data = ((DataBufferByte) raster.getDataBuffer()).getData(); final byte[] data = ((DataBufferByte) raster.getDataBuffer()).getData();
final int channels = (mHeader.mBitplanes + 7) / 8; final int channels = (header.bitplanes + 7) / 8;
final int planesPerChannel = 8; final int planesPerChannel = 8;
Object dataElements = null; Object dataElements = null;
@@ -559,7 +560,7 @@ public class IFFImageReader extends ImageReaderBase {
return; return;
} }
if (mFormType == IFF.TYPE_ILBM) { if (formType == IFF.TYPE_ILBM) {
// NOTE: Using (channels - c - 1) instead of just c, // NOTE: Using (channels - c - 1) instead of just c,
// effectively reverses the channel order from RGBA to ABGR // effectively reverses the channel order from RGBA to ABGR
int off = (channels - c - 1); int off = (channels - c - 1);
@@ -570,11 +571,11 @@ public class IFFImageReader extends ImageReaderBase {
pixelPos += 8; pixelPos += 8;
} }
} }
else if (mFormType == IFF.TYPE_PBM) { else if (formType == IFF.TYPE_PBM) {
System.arraycopy(planeData, 0, data, srcY * 8 * planeWidth, planeWidth); System.arraycopy(planeData, 0, data, srcY * 8 * planeWidth, planeWidth);
} }
else { else {
throw new AssertionError(String.format("Unsupported FORM type: %s", mFormType)); throw new AssertionError(String.format("Unsupported FORM type: %s", formType));
} }
} }
@@ -594,7 +595,7 @@ public class IFFImageReader extends ImageReaderBase {
} }
} }
processImageProgress(srcY * 100f / mHeader.mWidth); processImageProgress(srcY * 100f / header.width);
if (abortRequested()) { if (abortRequested()) {
processReadAborted(); processReadAborted();
break; break;
@@ -605,11 +606,11 @@ public class IFFImageReader extends ImageReaderBase {
private void readPlaneData(final ImageInputStream pInput, final byte[] pData, final int pOffset, final int pPlaneWidth) private void readPlaneData(final ImageInputStream pInput, final byte[] pData, final int pOffset, final int pPlaneWidth)
throws IOException { throws IOException {
switch (mHeader.mCompressionType) { switch (header.compressionType) {
case BMHDChunk.COMPRESSION_NONE: case BMHDChunk.COMPRESSION_NONE:
pInput.readFully(pData, pOffset, pPlaneWidth); pInput.readFully(pData, pOffset, pPlaneWidth);
// Uncompressed rows must have even number of bytes // Uncompressed rows must have even number of bytes
if ((mHeader.mBitplanes * pPlaneWidth) % 2 != 0) { if ((header.bitplanes * pPlaneWidth) % 2 != 0) {
pInput.readByte(); pInput.readByte();
} }
break; break;
@@ -620,27 +621,27 @@ public class IFFImageReader extends ImageReaderBase {
// However, we don't know how long each compressed row is, without decoding it... // However, we don't know how long each compressed row is, without decoding it...
// The workaround below, is to use a decode buffer size of pPlaneWidth, // The workaround below, is to use a decode buffer size of pPlaneWidth,
// to make sure we don't decode anything we don't have to (shouldn't). // to make sure we don't decode anything we don't have to (shouldn't).
if (mByteRunStream == null) { if (byteRunStream == null) {
mByteRunStream = new DataInputStream( byteRunStream = new DataInputStream(
new DecoderStream( new DecoderStream(
IIOUtil.createStreamAdapter(pInput, mBody.mChunkLength), IIOUtil.createStreamAdapter(pInput, body.chunkLength),
new PackBitsDecoder(true), new PackBitsDecoder(true),
pPlaneWidth * mHeader.mBitplanes pPlaneWidth * header.bitplanes
) )
); );
} }
mByteRunStream.readFully(pData, pOffset, pPlaneWidth); byteRunStream.readFully(pData, pOffset, pPlaneWidth);
break; break;
default: default:
throw new IIOException(String.format("Unknown compression type: %d", mHeader.mCompressionType)); throw new IIOException(String.format("Unknown compression type: %d", header.compressionType));
} }
} }
private void hamToRGB(final byte[] pIndexed, final IndexColorModel pModel, private void hamToRGB(final byte[] pIndexed, final IndexColorModel pModel,
final byte[] pDest, final int pDestOffset) { final byte[] pDest, final int pDestOffset) {
final int bits = mHeader.mBitplanes; final int bits = header.bitplanes;
final int width = mHeader.mWidth; final int width = header.width;
int lastRed = 0; int lastRed = 0;
int lastGreen = 0; int lastGreen = 0;
int lastBlue = 0; int lastBlue = 0;
@@ -679,7 +680,7 @@ public class IFFImageReader extends ImageReaderBase {
} }
private boolean isHAM() { private boolean isHAM() {
return mViewPort != null && mViewPort.isHAM(); return viewPort != null && viewPort.isHAM();
} }
public static void main(String[] pArgs) throws IOException { public static void main(String[] pArgs) throws IOException {
@@ -208,9 +208,9 @@ public class IFFImageWriter extends ImageWriterBase {
} }
// ILBM(4) + anno(8+len) + header(8+20) + cmap(8+len)? + body(8+len); // ILBM(4) + anno(8+len) + header(8+20) + cmap(8+len)? + body(8+len);
int size = 4 + 8 + anno.mChunkLength + 28 + 8 + pBodyLength; int size = 4 + 8 + anno.chunkLength + 28 + 8 + pBodyLength;
if (cmap != null) { if (cmap != null) {
size += 8 + cmap.mChunkLength; size += 8 + cmap.chunkLength;
} }
imageOutput.writeInt(IFF.CHUNK_FORM); imageOutput.writeInt(IFF.CHUNK_FORM);
@@ -51,7 +51,6 @@ public class IFFImageWriterSpi extends ImageWriterSpi {
*/ */
public IFFImageWriterSpi() { public IFFImageWriterSpi() {
this(IIOUtil.getProviderInfo(IFFImageWriterSpi.class)); this(IIOUtil.getProviderInfo(IFFImageWriterSpi.class));
} }
private IFFImageWriterSpi(final ProviderInfo pProviderInfo) { private IFFImageWriterSpi(final ProviderInfo pProviderInfo) {
@@ -41,17 +41,17 @@ import java.util.List;
* @version $Id: AbstractDirectory.java,v 1.0 Nov 11, 2009 5:31:04 PM haraldk Exp$ * @version $Id: AbstractDirectory.java,v 1.0 Nov 11, 2009 5:31:04 PM haraldk Exp$
*/ */
public abstract class AbstractDirectory implements Directory { public abstract class AbstractDirectory implements Directory {
private final List<Entry> mEntries = new ArrayList<Entry>(); private final List<Entry> entries = new ArrayList<Entry>();
protected AbstractDirectory(final Collection<? extends Entry> pEntries) { protected AbstractDirectory(final Collection<? extends Entry> pEntries) {
if (pEntries != null) { if (pEntries != null) {
mEntries.addAll(pEntries); entries.addAll(pEntries);
} }
} }
public Entry getEntryById(final Object pIdentifier) { public Entry getEntryById(final Object identifier) {
for (Entry entry : this) { for (Entry entry : this) {
if (entry.getIdentifier().equals(pIdentifier)) { if (entry.getIdentifier().equals(identifier)) {
return entry; return entry;
} }
} }
@@ -59,9 +59,9 @@ public abstract class AbstractDirectory implements Directory {
return null; return null;
} }
public Entry getEntryByFieldName(final String pFieldName) { public Entry getEntryByFieldName(final String fieldName) {
for (Entry entry : this) { for (Entry entry : this) {
if (entry.getFieldName() != null && entry.getFieldName().equals(pFieldName)) { if (entry.getFieldName() != null && entry.getFieldName().equals(fieldName)) {
return entry; return entry;
} }
} }
@@ -70,7 +70,7 @@ public abstract class AbstractDirectory implements Directory {
} }
public Iterator<Entry> iterator() { public Iterator<Entry> iterator() {
return mEntries.iterator(); return entries.iterator();
} }
/** /**
@@ -85,23 +85,23 @@ public abstract class AbstractDirectory implements Directory {
} }
} }
public boolean add(final Entry pEntry) { public boolean add(final Entry entry) {
assertMutable(); assertMutable();
// TODO: Replace if entry is already present? // TODO: Replace if entry is already present?
// Some directories may need special ordering, or may/may not support multiple entries for certain ids... // Some directories may need special ordering, or may/may not support multiple entries for certain ids...
return mEntries.add(pEntry); return entries.add(entry);
} }
@SuppressWarnings({"SuspiciousMethodCalls"}) @SuppressWarnings({"SuspiciousMethodCalls"})
public boolean remove(final Object pEntry) { public boolean remove(final Object entry) {
assertMutable(); assertMutable();
return mEntries.remove(pEntry); return entries.remove(entry);
} }
public int size() { public int size() {
return mEntries.size(); return entries.size();
} }
/** /**
@@ -118,7 +118,7 @@ public abstract class AbstractDirectory implements Directory {
@Override @Override
public int hashCode() { public int hashCode() {
return mEntries.hashCode(); return entries.hashCode();
} }
@Override @Override
@@ -134,11 +134,11 @@ public abstract class AbstractDirectory implements Directory {
// Safe cast, as it must be a subclass for the classes to be equal // Safe cast, as it must be a subclass for the classes to be equal
AbstractDirectory other = (AbstractDirectory) pOther; AbstractDirectory other = (AbstractDirectory) pOther;
return mEntries.equals(other.mEntries); return entries.equals(other.entries);
} }
@Override @Override
public String toString() { public String toString() {
return String.format("%s%s", getClass().getSimpleName(), mEntries.toString()); return String.format("%s%s", getClass().getSimpleName(), entries.toString());
} }
} }
@@ -42,18 +42,18 @@ import java.util.Arrays;
*/ */
public abstract class AbstractEntry implements Entry { public abstract class AbstractEntry implements Entry {
private final Object mIdentifier; private final Object identifier;
private final Object mValue; // TODO: Might need to be mutable.. private final Object value; // TODO: Might need to be mutable..
protected AbstractEntry(final Object pIdentifier, final Object pValue) { protected AbstractEntry(final Object identifier, final Object value) {
Validate.notNull(pIdentifier, "identifier"); Validate.notNull(identifier, "identifier");
mIdentifier = pIdentifier; this.identifier = identifier;
mValue = pValue; this.value = value;
} }
public final Object getIdentifier() { public final Object getIdentifier() {
return mIdentifier; return identifier;
} }
/** /**
@@ -66,64 +66,64 @@ public abstract class AbstractEntry implements Entry {
} }
public Object getValue() { public Object getValue() {
return mValue; return value;
} }
public String getValueAsString() { public String getValueAsString() {
if (valueCount() > 1) { if (valueCount() > 1) {
if (valueCount() < 16) { if (valueCount() < 16) {
Class<?> type = mValue.getClass().getComponentType(); Class<?> type = value.getClass().getComponentType();
if (type.isPrimitive()) { if (type.isPrimitive()) {
if (type.equals(boolean.class)) { if (type.equals(boolean.class)) {
return Arrays.toString((boolean[]) mValue); return Arrays.toString((boolean[]) value);
} }
else if (type.equals(byte.class)) { else if (type.equals(byte.class)) {
return Arrays.toString((byte[]) mValue); return Arrays.toString((byte[]) value);
} }
else if (type.equals(char.class)) { else if (type.equals(char.class)) {
return new String((char[]) mValue); return new String((char[]) value);
} }
else if (type.equals(double.class)) { else if (type.equals(double.class)) {
return Arrays.toString((double[]) mValue); return Arrays.toString((double[]) value);
} }
else if (type.equals(float.class)) { else if (type.equals(float.class)) {
return Arrays.toString((float[]) mValue); return Arrays.toString((float[]) value);
} }
else if (type.equals(int.class)) { else if (type.equals(int.class)) {
return Arrays.toString((int[]) mValue); return Arrays.toString((int[]) value);
} }
else if (type.equals(long.class)) { else if (type.equals(long.class)) {
return Arrays.toString((long[]) mValue); return Arrays.toString((long[]) value);
} }
else if (type.equals(short.class)) { else if (type.equals(short.class)) {
return Arrays.toString((short[]) mValue); return Arrays.toString((short[]) value);
} }
// Fall through should never happen // Fall through should never happen
} }
else { else {
return Arrays.toString((Object[]) mValue); return Arrays.toString((Object[]) value);
} }
} }
return String.valueOf(mValue) + " (" + valueCount() + ")"; return String.valueOf(value) + " (" + valueCount() + ")";
} }
return String.valueOf(mValue); return String.valueOf(value);
} }
public String getTypeName() { public String getTypeName() {
if (mValue == null) { if (value == null) {
return null; return null;
} }
return mValue.getClass().getSimpleName(); return value.getClass().getSimpleName();
} }
public int valueCount() { public int valueCount() {
// TODO: Collection support? // TODO: Collection support?
if (mValue != null && mValue.getClass().isArray()) { if (value != null && value.getClass().isArray()) {
return Array.getLength(mValue); return Array.getLength(value);
} }
return 1; return 1;
@@ -135,7 +135,7 @@ public abstract class AbstractEntry implements Entry {
@Override @Override
public int hashCode() { public int hashCode() {
return mIdentifier.hashCode() + 31 * mValue.hashCode(); return identifier.hashCode() + 31 * value.hashCode();
} }
@Override @Override
@@ -149,8 +149,8 @@ public abstract class AbstractEntry implements Entry {
AbstractEntry other = (AbstractEntry) pOther; AbstractEntry other = (AbstractEntry) pOther;
return mIdentifier.equals(other.mIdentifier) && ( return identifier.equals(other.identifier) && (
mValue == null && other.mValue == null || mValue != null && mValue.equals(other.mValue) value == null && other.value == null || value != null && value.equals(other.value)
); );
} }
@@ -38,9 +38,9 @@ package com.twelvemonkeys.imageio.metadata;
public interface Directory extends Iterable<Entry> { public interface Directory extends Iterable<Entry> {
// TODO: Spec when more entries exist? Or make Entry support multi-values!? // TODO: Spec when more entries exist? Or make Entry support multi-values!?
// For multiple entries with same id in directory, the first entry (using the order from the stream) will be returned // For multiple entries with same id in directory, the first entry (using the order from the stream) will be returned
Entry getEntryById(Object pIdentifier); Entry getEntryById(Object identifier);
Entry getEntryByFieldName(String pName); Entry getEntryByFieldName(String fieldName);
// Iterator containing the entries in // Iterator containing the entries in
//Iterator<Entry> getBestEntries(Object pIdentifier, Object pQualifier, String pLanguage); //Iterator<Entry> getBestEntries(Object pIdentifier, Object pQualifier, String pLanguage);
@@ -51,9 +51,9 @@ public interface Directory extends Iterable<Entry> {
// boolean replace(Entry pEntry)?? // boolean replace(Entry pEntry)??
// boolean contains(Object pIdentifier)? // boolean contains(Object pIdentifier)?
boolean add(Entry pEntry); boolean add(Entry entry);
boolean remove(Object pEntry); // Object in case we retro-fit Collection/Map.. boolean remove(Object entry); // Object in case we retro-fit Collection/Map..
int size(); int size();
@@ -39,5 +39,5 @@ import java.io.IOException;
* @version $Id: MetadataReader.java,v 1.0 Nov 13, 2009 8:38:11 PM haraldk Exp$ * @version $Id: MetadataReader.java,v 1.0 Nov 13, 2009 8:38:11 PM haraldk Exp$
*/ */
public abstract class MetadataReader { public abstract class MetadataReader {
public abstract Directory read(ImageInputStream pInput) throws IOException; public abstract Directory read(ImageInputStream input) throws IOException;
} }
@@ -41,7 +41,7 @@ import java.util.Collection;
* @version $Id: EXIFDirectory.java,v 1.0 Nov 11, 2009 5:02:59 PM haraldk Exp$ * @version $Id: EXIFDirectory.java,v 1.0 Nov 11, 2009 5:02:59 PM haraldk Exp$
*/ */
final class EXIFDirectory extends AbstractDirectory { final class EXIFDirectory extends AbstractDirectory {
EXIFDirectory(final Collection<? extends Entry> pEntries) { EXIFDirectory(final Collection<? extends Entry> entries) {
super(pEntries); super(entries);
} }
} }
@@ -38,20 +38,20 @@ import com.twelvemonkeys.imageio.metadata.AbstractEntry;
* @version $Id: EXIFEntry.java,v 1.0 Nov 13, 2009 5:47:35 PM haraldk Exp$ * @version $Id: EXIFEntry.java,v 1.0 Nov 13, 2009 5:47:35 PM haraldk Exp$
*/ */
final class EXIFEntry extends AbstractEntry { final class EXIFEntry extends AbstractEntry {
final private short mType; final private short type;
EXIFEntry(final int pIdentifier, final Object pValue, final short pType) { EXIFEntry(final int identifier, final Object value, final short type) {
super(pIdentifier, pValue); super(identifier, value);
// if (pType < 1 || pType > TIFF.TYPE_NAMES.length) { // if (type < 1 || type > TIFF.TYPE_NAMES.length) {
// throw new IllegalArgumentException(String.format("Illegal EXIF type: %s", pType)); // throw new IllegalArgumentException(String.format("Illegal EXIF type: %s", type));
// } // }
mType = pType; this.type = type;
} }
public short getType() { public short getType() {
return mType; return type;
} }
@Override @Override
@@ -110,6 +110,6 @@ final class EXIFEntry extends AbstractEntry {
@Override @Override
public String getTypeName() { public String getTypeName() {
return TIFF.TYPE_NAMES[mType - 1]; return TIFF.TYPE_NAMES[type - 1];
} }
} }
@@ -56,14 +56,14 @@ public final class EXIFReader extends MetadataReader {
static final Collection<Integer> KNOWN_IFDS = Arrays.asList(TIFF.TAG_EXIF_IFD, TIFF.TAG_GPS_IFD, TIFF.TAG_INTEROP_IFD); static final Collection<Integer> KNOWN_IFDS = Arrays.asList(TIFF.TAG_EXIF_IFD, TIFF.TAG_GPS_IFD, TIFF.TAG_INTEROP_IFD);
@Override @Override
public Directory read(final ImageInputStream pInput) throws IOException { public Directory read(final ImageInputStream input) throws IOException {
byte[] bom = new byte[2]; byte[] bom = new byte[2];
pInput.readFully(bom); input.readFully(bom);
if (bom[0] == 'I' && bom[1] == 'I') { if (bom[0] == 'I' && bom[1] == 'I') {
pInput.setByteOrder(ByteOrder.LITTLE_ENDIAN); input.setByteOrder(ByteOrder.LITTLE_ENDIAN);
} }
else if (bom[0] == 'M' && bom[1] == 'M') { else if (bom[0] == 'M' && bom[1] == 'M') {
pInput.setByteOrder(ByteOrder.BIG_ENDIAN); input.setByteOrder(ByteOrder.BIG_ENDIAN);
} }
else { else {
throw new IIOException(String.format("Invalid TIFF byte order mark '%s', expected: 'II' or 'MM'", StringUtil.decode(bom, 0, bom.length, "ASCII"))); throw new IIOException(String.format("Invalid TIFF byte order mark '%s', expected: 'II' or 'MM'", StringUtil.decode(bom, 0, bom.length, "ASCII")));
@@ -71,14 +71,14 @@ public final class EXIFReader extends MetadataReader {
// TODO: BigTiff uses version 43 instead of TIFF's 42, and header is slightly different, see // TODO: BigTiff uses version 43 instead of TIFF's 42, and header is slightly different, see
// http://www.awaresystems.be/imaging/tiff/bigtiff.html // http://www.awaresystems.be/imaging/tiff/bigtiff.html
int magic = pInput.readUnsignedShort(); int magic = input.readUnsignedShort();
if (magic != TIFF.TIFF_MAGIC) { if (magic != TIFF.TIFF_MAGIC) {
throw new IIOException(String.format("Wrong TIFF magic in EXIF data: %04x, expected: %04x", magic, TIFF.TIFF_MAGIC)); throw new IIOException(String.format("Wrong TIFF magic in EXIF data: %04x, expected: %04x", magic, TIFF.TIFF_MAGIC));
} }
long directoryOffset = pInput.readUnsignedInt(); long directoryOffset = input.readUnsignedInt();
return readDirectory(pInput, directoryOffset); return readDirectory(input, directoryOffset);
} }
private EXIFDirectory readDirectory(final ImageInputStream pInput, final long pOffset) throws IOException { private EXIFDirectory readDirectory(final ImageInputStream pInput, final long pOffset) throws IOException {
@@ -54,8 +54,8 @@ public final class Rational extends Number implements Comparable<Rational> {
// Inspired by http://www.cs.princeton.edu/introcs/92symbolic/Rational.java.html and java.lang.Integer // Inspired by http://www.cs.princeton.edu/introcs/92symbolic/Rational.java.html and java.lang.Integer
static final Rational ZERO = new Rational(0, 1); static final Rational ZERO = new Rational(0, 1);
private final long mNumerator; private final long numerator;
private final long mDenominator; private final long denominator;
public Rational(final long pNumber) { public Rational(final long pNumber) {
this(pNumber, 1); this(pNumber, 1);
@@ -74,8 +74,8 @@ public final class Rational extends Number implements Comparable<Rational> {
long num = pNumerator / gcd; long num = pNumerator / gcd;
long den = pDenominator / gcd; long den = pDenominator / gcd;
mNumerator = pDenominator >= 0 ? num : -num; numerator = pDenominator >= 0 ? num : -num;
mDenominator = pDenominator >= 0 ? den : -den; denominator = pDenominator >= 0 ? den : -den;
} }
private static long gcd(final long m, final long n) { private static long gcd(final long m, final long n) {
@@ -95,11 +95,11 @@ public final class Rational extends Number implements Comparable<Rational> {
} }
public long numerator() { public long numerator() {
return mNumerator; return numerator;
} }
public long denominator() { public long denominator() {
return mDenominator; return denominator;
} }
/// Number implementation /// Number implementation
@@ -121,7 +121,7 @@ public final class Rational extends Number implements Comparable<Rational> {
@Override @Override
public double doubleValue() { public double doubleValue() {
return mNumerator / (double) mDenominator; return numerator / (double) denominator;
} }
/// Comparable implementation /// Comparable implementation
@@ -147,7 +147,7 @@ public final class Rational extends Number implements Comparable<Rational> {
@Override @Override
public String toString() { public String toString() {
return mDenominator == 1 ? Long.toString(mNumerator) : String.format("%s/%s", mNumerator, mDenominator); return denominator == 1 ? Long.toString(numerator) : String.format("%s/%s", numerator, denominator);
} }
/// Operations (adapted from http://www.cs.princeton.edu/introcs/92symbolic/Rational.java.html) /// Operations (adapted from http://www.cs.princeton.edu/introcs/92symbolic/Rational.java.html)
@@ -161,10 +161,10 @@ public final class Rational extends Number implements Comparable<Rational> {
} }
// reduce p1/q2 and p2/q1, then multiply, where a = p1/q1 and b = p2/q2 // reduce p1/q2 and p2/q1, then multiply, where a = p1/q1 and b = p2/q2
Rational c = new Rational(mNumerator, pOther.mDenominator); Rational c = new Rational(numerator, pOther.denominator);
Rational d = new Rational(pOther.mNumerator, mDenominator); Rational d = new Rational(pOther.numerator, denominator);
return new Rational(c.mNumerator * d.mNumerator, c.mDenominator * d.mDenominator); return new Rational(c.numerator * d.numerator, c.denominator * d.denominator);
} }
// return a + b, staving off overflow // return a + b, staving off overflow
@@ -178,20 +178,20 @@ public final class Rational extends Number implements Comparable<Rational> {
} }
// Find gcd of numerators and denominators // Find gcd of numerators and denominators
long f = gcd(mNumerator, pOther.mNumerator); long f = gcd(numerator, pOther.numerator);
long g = gcd(mDenominator, pOther.mDenominator); long g = gcd(denominator, pOther.denominator);
// add cross-product terms for numerator // add cross-product terms for numerator
// multiply back in // multiply back in
return new Rational( return new Rational(
((mNumerator / f) * (pOther.mDenominator / g) + (pOther.mNumerator / f) * (mDenominator / g)) * f, ((numerator / f) * (pOther.denominator / g) + (pOther.numerator / f) * (denominator / g)) * f,
lcm(mDenominator, pOther.mDenominator) lcm(denominator, pOther.denominator)
); );
} }
// return -a // return -a
public Rational negate() { public Rational negate() {
return new Rational(-mNumerator, mDenominator); return new Rational(-numerator, denominator);
} }
// return a - b // return a - b
@@ -200,7 +200,7 @@ public final class Rational extends Number implements Comparable<Rational> {
} }
public Rational reciprocal() { public Rational reciprocal() {
return new Rational(mDenominator, mNumerator); return new Rational(denominator, numerator);
} }
// return a / b // return a / b
@@ -41,7 +41,7 @@ import java.util.Collection;
* @version $Id: IPTCDirectory.java,v 1.0 Nov 11, 2009 5:02:59 PM haraldk Exp$ * @version $Id: IPTCDirectory.java,v 1.0 Nov 11, 2009 5:02:59 PM haraldk Exp$
*/ */
final class IPTCDirectory extends AbstractDirectory { final class IPTCDirectory extends AbstractDirectory {
IPTCDirectory(final Collection<? extends Entry> pEntries) { IPTCDirectory(final Collection<? extends Entry> entries) {
super(pEntries); super(entries);
} }
} }
@@ -38,8 +38,8 @@ import com.twelvemonkeys.imageio.metadata.AbstractEntry;
* @version $Id: IPTCEntry.java,v 1.0 Nov 13, 2009 8:57:04 PM haraldk Exp$ * @version $Id: IPTCEntry.java,v 1.0 Nov 13, 2009 8:57:04 PM haraldk Exp$
*/ */
class IPTCEntry extends AbstractEntry { class IPTCEntry extends AbstractEntry {
public IPTCEntry(final int pTagId, final Object pValue) { public IPTCEntry(final int tagId, final Object value) {
super(pTagId, pValue); super(tagId, value);
} }
@Override @Override
@@ -57,18 +57,18 @@ public final class IPTCReader extends MetadataReader {
private static final int ENCODING_UNSPECIFIED = 0; private static final int ENCODING_UNSPECIFIED = 0;
private static final int ENCODING_UTF_8 = 0x1b2547; private static final int ENCODING_UTF_8 = 0x1b2547;
private int mEncoding = ENCODING_UNSPECIFIED; private int encoding = ENCODING_UNSPECIFIED;
@Override @Override
public Directory read(final ImageInputStream pInput) throws IOException { public Directory read(final ImageInputStream input) throws IOException {
final List<Entry> entries = new ArrayList<Entry>(); final List<Entry> entries = new ArrayList<Entry>();
// 0x1c identifies start of a tag // 0x1c identifies start of a tag
while (pInput.read() == 0x1c) { while (input.read() == 0x1c) {
short tagId = pInput.readShort(); short tagId = input.readShort();
int tagByteCount = pInput.readUnsignedShort(); int tagByteCount = input.readUnsignedShort();
Entry entry = readEntry(pInput, tagId, tagByteCount); Entry entry = readEntry(input, tagId, tagByteCount);
if (entry != null) { if (entry != null) {
entries.add(entry); entries.add(entry);
@@ -85,7 +85,7 @@ public final class IPTCReader extends MetadataReader {
case IPTC.TAG_CODED_CHARACTER_SET: case IPTC.TAG_CODED_CHARACTER_SET:
// TODO: Mapping from ISO 646 to Java supported character sets? // TODO: Mapping from ISO 646 to Java supported character sets?
// TODO: Move somewhere else? // TODO: Move somewhere else?
mEncoding = parseEncoding(pInput, pLength); encoding = parseEncoding(pInput, pLength);
return null; return null;
case IPTC.TAG_RECORD_VERSION: case IPTC.TAG_RECORD_VERSION:
// A single unsigned short value // A single unsigned short value
@@ -140,7 +140,7 @@ public final class IPTCReader extends MetadataReader {
return chars.toString(); return chars.toString();
} }
catch (CharacterCodingException notUTF8) { catch (CharacterCodingException notUTF8) {
if (mEncoding == ENCODING_UTF_8) { if (encoding == ENCODING_UTF_8) {
throw new IIOException("Wrong encoding of IPTC data, explicitly set to UTF-8 in DataSet 1:90", notUTF8); throw new IIOException("Wrong encoding of IPTC data, explicitly set to UTF-8 in DataSet 1:90", notUTF8);
} }
@@ -45,7 +45,7 @@ final class XMPDirectory extends AbstractDirectory {
// TODO: XMPDirectory, maybe not even an AbstractDirectory // TODO: XMPDirectory, maybe not even an AbstractDirectory
// - Keeping the Document would allow for easier serialization // - Keeping the Document would allow for easier serialization
// TODO: Or use direct SAX parsing // TODO: Or use direct SAX parsing
public XMPDirectory(List<Entry> pEntries) { public XMPDirectory(List<Entry> entries) {
super(pEntries); super(entries);
} }
} }
@@ -38,20 +38,20 @@ import com.twelvemonkeys.imageio.metadata.AbstractEntry;
* @version $Id: XMPEntry.java,v 1.0 Nov 17, 2009 9:38:39 PM haraldk Exp$ * @version $Id: XMPEntry.java,v 1.0 Nov 17, 2009 9:38:39 PM haraldk Exp$
*/ */
final class XMPEntry extends AbstractEntry { final class XMPEntry extends AbstractEntry {
private final String mFieldName; private final String fieldName;
public XMPEntry(final String pIdentifier, final Object pValue) { public XMPEntry(final String identifier, final Object pValue) {
this(pIdentifier, null, pValue); this(identifier, null, pValue);
} }
public XMPEntry(final String pIdentifier, final String pFieldName, final Object pValue) { public XMPEntry(final String identifier, final String fieldName, final Object value) {
super(pIdentifier, pValue); super(identifier, value);
mFieldName = pFieldName; this.fieldName = fieldName;
} }
@SuppressWarnings({"SuspiciousMethodCalls"}) @SuppressWarnings({"SuspiciousMethodCalls"})
@Override @Override
public String getFieldName() { public String getFieldName() {
return mFieldName != null ? mFieldName : XMP.DEFAULT_NS_MAPPING.get(getIdentifier()); return fieldName != null ? fieldName : XMP.DEFAULT_NS_MAPPING.get(getIdentifier());
} }
} }
@@ -56,7 +56,7 @@ import java.util.*;
*/ */
public final class XMPReader extends MetadataReader { public final class XMPReader extends MetadataReader {
@Override @Override
public Directory read(final ImageInputStream pInput) throws IOException { public Directory read(final ImageInputStream input) throws IOException {
// pInput.mark(); // pInput.mark();
// //
// BufferedReader reader = new BufferedReader(new InputStreamReader(IIOUtil.createStreamAdapter(pInput), Charset.forName("UTF-8"))); // BufferedReader reader = new BufferedReader(new InputStreamReader(IIOUtil.createStreamAdapter(pInput), Charset.forName("UTF-8")));
@@ -75,7 +75,7 @@ public final class XMPReader extends MetadataReader {
// TODO: Determine encoding and parse using a Reader... // TODO: Determine encoding and parse using a Reader...
// TODO: Refactor scanner to return inputstream? // TODO: Refactor scanner to return inputstream?
DocumentBuilder builder = factory.newDocumentBuilder(); DocumentBuilder builder = factory.newDocumentBuilder();
Document document = builder.parse(new InputSource(IIOUtil.createStreamAdapter(pInput))); Document document = builder.parse(new InputSource(IIOUtil.createStreamAdapter(input)));
// XMLSerializer serializer = new XMLSerializer(System.err, System.getProperty("file.encoding")); // XMLSerializer serializer = new XMLSerializer(System.err, System.getProperty("file.encoding"));
// serializer.serialize(document); // serializer.serialize(document);
@@ -110,23 +110,23 @@ public class PICTImageReader extends ImageReaderBase {
static boolean DEBUG = false; static boolean DEBUG = false;
// Private fields // Private fields
private QuickDrawContext mContext; private QuickDrawContext context;
private Rectangle mFrame; private Rectangle frame;
private int mVersion; private int version;
// Variables for storing draw status // Variables for storing draw status
private Point mPenPosition = new Point(0, 0); private Point penPosition = new Point(0, 0);
private Rectangle mLastRectangle = new Rectangle(0, 0); private Rectangle lastRectangle = new Rectangle(0, 0);
// Ratio between the screen resolution and the image resolution // Ratio between the screen resolution and the image resolution
private double mScreenImageXRatio; private double screenImageXRatio;
private double mScreenImageYRatio; private double screenImageYRatio;
// List of images created during image import // List of images created during image import
private List<BufferedImage> mImages = new ArrayList<BufferedImage>(); private List<BufferedImage> images = new ArrayList<BufferedImage>();
private long mImageStartStreamPos; private long imageStartStreamPos;
protected int mPicSize; protected int picSize;
public PICTImageReader() { public PICTImageReader() {
this(null); this(null);
@@ -137,9 +137,9 @@ public class PICTImageReader extends ImageReaderBase {
} }
protected void resetMembers() { protected void resetMembers() {
mContext = null; context = null;
mFrame = null; frame = null;
mImages.clear(); images.clear();
} }
/** /**
@@ -149,14 +149,16 @@ public class PICTImageReader extends ImageReaderBase {
* @throws IOException if an I/O error occurs while reading the image. * @throws IOException if an I/O error occurs while reading the image.
*/ */
private Rectangle getPICTFrame() throws IOException { private Rectangle getPICTFrame() throws IOException {
if (mFrame == null) { if (frame == null) {
// Read in header information // Read in header information
readPICTHeader(imageInput); readPICTHeader(imageInput);
if (DEBUG) { if (DEBUG) {
System.out.println("Done reading PICT header!"); System.out.println("Done reading PICT header!");
} }
} }
return mFrame;
return frame;
} }
/** /**
@@ -184,9 +186,10 @@ public class PICTImageReader extends ImageReaderBase {
private void readPICTHeader0(final ImageInputStream pStream) throws IOException { private void readPICTHeader0(final ImageInputStream pStream) throws IOException {
// Get size // Get size
mPicSize = pStream.readUnsignedShort(); picSize = pStream.readUnsignedShort();
if (DEBUG) { if (DEBUG) {
System.out.println("picSize: " + mPicSize); System.out.println("picSize: " + picSize);
} }
// Get frame at 72 dpi // Get frame at 72 dpi
@@ -197,17 +200,17 @@ public class PICTImageReader extends ImageReaderBase {
int h = pStream.readUnsignedShort(); int h = pStream.readUnsignedShort();
int w = pStream.readUnsignedShort(); int w = pStream.readUnsignedShort();
mFrame = new Rectangle(x, y, w - x, h - y); frame = new Rectangle(x, y, w - x, h - y);
if (mFrame.width < 0 || mFrame.height < 0) { if (frame.width < 0 || frame.height < 0) {
throw new IIOException("Error in PICT header: Invalid frame " + mFrame); throw new IIOException("Error in PICT header: Invalid frame " + frame);
} }
if (DEBUG) { if (DEBUG) {
System.out.println("mFrame: " + mFrame); System.out.println("frame: " + frame);
} }
// Set default display ratios. 72 dpi is the standard Macintosh resolution. // Set default display ratios. 72 dpi is the standard Macintosh resolution.
mScreenImageXRatio = 1.0; screenImageXRatio = 1.0;
mScreenImageYRatio = 1.0; screenImageYRatio = 1.0;
// Get the version, since the way of reading the rest depends on it // Get the version, since the way of reading the rest depends on it
boolean isExtendedV2 = false; boolean isExtendedV2 = false;
@@ -217,10 +220,10 @@ public class PICTImageReader extends ImageReaderBase {
} }
if (version == (PICT.OP_VERSION << 8) + 0x01) { if (version == (PICT.OP_VERSION << 8) + 0x01) {
mVersion = 1; this.version = 1;
} }
else if (version == PICT.OP_VERSION && pStream.readShort() == PICT.OP_VERSION_2) { else if (version == PICT.OP_VERSION && pStream.readShort() == PICT.OP_VERSION_2) {
mVersion = 2; this.version = 2;
// Read in version 2 header op and test that it is valid: HeaderOp 0x0C00 // Read in version 2 header op and test that it is valid: HeaderOp 0x0C00
if (pStream.readShort() != PICT.OP_HEADER_OP) { if (pStream.readShort() != PICT.OP_HEADER_OP) {
@@ -249,10 +252,10 @@ public class PICTImageReader extends ImageReaderBase {
// int h (fixed point) // int h (fixed point)
double h2 = PICTUtil.readFixedPoint(pStream); double h2 = PICTUtil.readFixedPoint(pStream);
mScreenImageXRatio = (w - x) / (w2 - x2); screenImageXRatio = (w - x) / (w2 - x2);
mScreenImageYRatio = (h - y) / (h2 - y2); screenImageYRatio = (h - y) / (h2 - y2);
if (mScreenImageXRatio < 0 || mScreenImageYRatio < 0) { if (screenImageXRatio < 0 || screenImageYRatio < 0) {
throw new IIOException("Error in PICT header: Invalid bounds " + new Rectangle.Double(x2, y2, w2 - x2, h2 - y2)); throw new IIOException("Error in PICT header: Invalid bounds " + new Rectangle.Double(x2, y2, w2 - x2, h2 - y2));
} }
if (DEBUG) { if (DEBUG) {
@@ -288,10 +291,10 @@ public class PICTImageReader extends ImageReaderBase {
// short w // short w
short w2 = pStream.readShort(); short w2 = pStream.readShort();
mScreenImageXRatio = (w - x) / (double) (w2 - x2); screenImageXRatio = (w - x) / (double) (w2 - x2);
mScreenImageYRatio = (h - y) / (double) (h2 - y2); screenImageYRatio = (h - y) / (double) (h2 - y2);
if (mScreenImageXRatio < 0 || mScreenImageYRatio < 0) { if (screenImageXRatio < 0 || screenImageYRatio < 0) {
throw new IIOException("Error in PICT header: Invalid bounds " + new Rectangle.Double(x2, y2, w2 - x2, h2 - y2)); throw new IIOException("Error in PICT header: Invalid bounds " + new Rectangle.Double(x2, y2, w2 - x2, h2 - y2));
} }
if (DEBUG) { if (DEBUG) {
@@ -303,8 +306,8 @@ public class PICTImageReader extends ImageReaderBase {
} }
if (DEBUG) { if (DEBUG) {
System.out.println("screenImageXRatio: " + mScreenImageXRatio); System.out.println("screenImageXRatio: " + screenImageXRatio);
System.out.println("screenImageYRatio: " + mScreenImageYRatio); System.out.println("screenImageYRatio: " + screenImageYRatio);
} }
} }
else { else {
@@ -313,13 +316,13 @@ public class PICTImageReader extends ImageReaderBase {
} }
if (DEBUG) { if (DEBUG) {
System.out.println("Version: " + mVersion + (isExtendedV2 ? " extended" : "")); System.out.println("Version: " + this.version + (isExtendedV2 ? " extended" : ""));
} }
mImageStartStreamPos = pStream.getStreamPosition(); imageStartStreamPos = pStream.getStreamPosition();
// Won't need header data again (NOTE: We'll only get here if no exception is thrown) // Won't need header data again (NOTE: We'll only get here if no exception is thrown)
pStream.flushBefore(mImageStartStreamPos); pStream.flushBefore(imageStartStreamPos);
} }
static void skipNullHeader(final ImageInputStream pStream) throws IOException { static void skipNullHeader(final ImageInputStream pStream) throws IOException {
@@ -341,7 +344,7 @@ public class PICTImageReader extends ImageReaderBase {
* @throws IOException if an I/O error occurs while reading the image. * @throws IOException if an I/O error occurs while reading the image.
*/ */
private void drawOnto(Graphics2D pGraphics) throws IOException { private void drawOnto(Graphics2D pGraphics) throws IOException {
mContext = new QuickDrawContext(pGraphics); context = new QuickDrawContext(pGraphics);
readPICTopcodes(imageInput); readPICTopcodes(imageInput);
if (DEBUG) { if (DEBUG) {
@@ -360,7 +363,7 @@ public class PICTImageReader extends ImageReaderBase {
* @throws java.io.IOException if an I/O error occurs while reading the image. * @throws java.io.IOException if an I/O error occurs while reading the image.
*/ */
private void readPICTopcodes(ImageInputStream pStream) throws IOException { private void readPICTopcodes(ImageInputStream pStream) throws IOException {
pStream.seek(mImageStartStreamPos); pStream.seek(imageStartStreamPos);
int opCode, dh, dv, dataLength; int opCode, dh, dv, dataLength;
byte[] colorBuffer = new byte[3 * PICT.COLOR_COMP_SIZE]; byte[] colorBuffer = new byte[3 * PICT.COLOR_COMP_SIZE];
@@ -386,7 +389,7 @@ public class PICTImageReader extends ImageReaderBase {
// Read from file until we read the end of picture opcode // Read from file until we read the end of picture opcode
do { do {
// Read opcode, version 1: byte, version 2: short // Read opcode, version 1: byte, version 2: short
if (mVersion == 1) { if (version == 1) {
opCode = pStream.readUnsignedByte(); opCode = pStream.readUnsignedByte();
} }
else { else {
@@ -431,7 +434,7 @@ public class PICTImageReader extends ImageReaderBase {
case PICT.OP_BK_PAT: case PICT.OP_BK_PAT:
// Get the data // Get the data
mContext.setBackgroundPattern(PICTUtil.readPattern(pStream)); context.setBackgroundPattern(PICTUtil.readPattern(pStream));
if (DEBUG) { if (DEBUG) {
System.out.println("bkPat"); System.out.println("bkPat");
} }
@@ -490,7 +493,7 @@ public class PICTImageReader extends ImageReaderBase {
// Get the two words // Get the two words
// NOTE: This is out of order, compared to other Points // NOTE: This is out of order, compared to other Points
Dimension pnsize = new Dimension(pStream.readUnsignedShort(), pStream.readUnsignedShort()); Dimension pnsize = new Dimension(pStream.readUnsignedShort(), pStream.readUnsignedShort());
mContext.setPenSize(pnsize); context.setPenSize(pnsize);
if (DEBUG) { if (DEBUG) {
System.out.println("pnsize: " + pnsize); System.out.println("pnsize: " + pnsize);
} }
@@ -503,12 +506,12 @@ public class PICTImageReader extends ImageReaderBase {
System.out.println("pnMode: " + mode); System.out.println("pnMode: " + mode);
} }
mContext.setPenMode(mode); context.setPenMode(mode);
break; break;
case PICT.OP_PN_PAT: case PICT.OP_PN_PAT:
mContext.setPenPattern(PICTUtil.readPattern(pStream)); context.setPenPattern(PICTUtil.readPattern(pStream));
if (DEBUG) { if (DEBUG) {
System.out.println("pnPat"); System.out.println("pnPat");
} }
@@ -557,7 +560,7 @@ public class PICTImageReader extends ImageReaderBase {
// currentFont = mGraphics.getFont(); // currentFont = mGraphics.getFont();
// mGraphics.setFont(new Font(currentFont.getName(), currentFont.getStyle(), tx_size)); // mGraphics.setFont(new Font(currentFont.getName(), currentFont.getStyle(), tx_size));
//} //}
mContext.setTextSize(tx_size); context.setTextSize(tx_size);
if (DEBUG) { if (DEBUG) {
System.out.println("txSize: " + tx_size); System.out.println("txSize: " + tx_size);
} }
@@ -599,15 +602,15 @@ public class PICTImageReader extends ImageReaderBase {
case 0x0012: // BkPixPat case 0x0012: // BkPixPat
bg = PICTUtil.readColorPattern(pStream); bg = PICTUtil.readColorPattern(pStream);
mContext.setBackgroundPattern(bg); context.setBackgroundPattern(bg);
break; break;
case 0x0013: // PnPixPat case 0x0013: // PnPixPat
pen = PICTUtil.readColorPattern(pStream); pen = PICTUtil.readColorPattern(pStream);
mContext.setBackgroundPattern(pen); context.setBackgroundPattern(pen);
break; break;
case 0x0014: // FillPixPat case 0x0014: // FillPixPat
fill = PICTUtil.readColorPattern(pStream); fill = PICTUtil.readColorPattern(pStream);
mContext.setBackgroundPattern(fill); context.setBackgroundPattern(fill);
break; break;
case PICT.OP_PN_LOC_H_FRAC:// TO BE DONE??? case PICT.OP_PN_LOC_H_FRAC:// TO BE DONE???
@@ -650,7 +653,7 @@ public class PICTImageReader extends ImageReaderBase {
case PICT.OP_HILITE_MODE: case PICT.OP_HILITE_MODE:
// Change color to hilite color // Change color to hilite color
mContext.setPenPattern(new BitMapPattern(hilight)); context.setPenPattern(new BitMapPattern(hilight));
if (DEBUG) { if (DEBUG) {
System.out.println("opHiliteMode"); System.out.println("opHiliteMode");
} }
@@ -691,14 +694,14 @@ public class PICTImageReader extends ImageReaderBase {
y = getYPtCoord(pStream.readUnsignedShort()); y = getYPtCoord(pStream.readUnsignedShort());
x = getXPtCoord(pStream.readUnsignedShort()); x = getXPtCoord(pStream.readUnsignedShort());
mPenPosition.setLocation(x, y); penPosition.setLocation(x, y);
// Move pen to new position, draw line // Move pen to new position, draw line
mContext.moveTo(origin); context.moveTo(origin);
mContext.lineTo(mPenPosition); context.lineTo(penPosition);
if (DEBUG) { if (DEBUG) {
System.out.println("line from: " + origin + " to: " + mPenPosition); System.out.println("line from: " + origin + " to: " + penPosition);
} }
break; break;
@@ -708,10 +711,10 @@ public class PICTImageReader extends ImageReaderBase {
x = getXPtCoord(pStream.readUnsignedShort()); x = getXPtCoord(pStream.readUnsignedShort());
// Draw line // Draw line
mContext.line(x, y); context.line(x, y);
if (DEBUG) { if (DEBUG) {
System.out.println("lineFrom to: " + mPenPosition); System.out.println("lineFrom to: " + penPosition);
} }
break; break;
@@ -726,8 +729,8 @@ public class PICTImageReader extends ImageReaderBase {
dh_dv = new Point(x, y); dh_dv = new Point(x, y);
// Move pen to new position, draw line if we have a graphics // Move pen to new position, draw line if we have a graphics
mPenPosition.setLocation(origin.x + dh_dv.x, origin.y + dh_dv.y); penPosition.setLocation(origin.x + dh_dv.x, origin.y + dh_dv.y);
mContext.lineTo(mPenPosition); context.lineTo(penPosition);
if (DEBUG) { if (DEBUG) {
System.out.println("Short line origin: " + origin + ", dh,dv: " + dh_dv); System.out.println("Short line origin: " + origin + ", dh,dv: " + dh_dv);
@@ -740,7 +743,7 @@ public class PICTImageReader extends ImageReaderBase {
x = getXPtCoord(pStream.readByte()); x = getXPtCoord(pStream.readByte());
// Draw line // Draw line
mContext.line(x, y); context.line(x, y);
if (DEBUG) { if (DEBUG) {
System.out.println("Short line from dh,dv: " + x + "," + y); System.out.println("Short line from dh,dv: " + x + "," + y);
@@ -765,30 +768,30 @@ public class PICTImageReader extends ImageReaderBase {
y = getYPtCoord(pStream.readUnsignedShort()); y = getYPtCoord(pStream.readUnsignedShort());
x = getXPtCoord(pStream.readUnsignedShort()); x = getXPtCoord(pStream.readUnsignedShort());
origin = new Point(x, y); origin = new Point(x, y);
mPenPosition = origin; penPosition = origin;
mContext.moveTo(mPenPosition); context.moveTo(penPosition);
text = PICTUtil.readPascalString(pStream); text = PICTUtil.readPascalString(pStream);
// TODO // TODO
//if (mGraphics != null) { //if (mGraphics != null) {
// mGraphics.drawString(text, mPenPosition.x, mPenPosition.y); // mGraphics.drawString(text, penPosition.x, penPosition.y);
//} //}
mContext.drawString(text); context.drawString(text);
if (DEBUG) { if (DEBUG) {
System.out.println("longText origin: " + mPenPosition + ", text:" + text); System.out.println("longText origin: " + penPosition + ", text:" + text);
} }
break; break;
case PICT.OP_DH_TEXT:// OK, not tested case PICT.OP_DH_TEXT:// OK, not tested
// Get dh // Get dh
dh = getXPtCoord(pStream.readByte()); dh = getXPtCoord(pStream.readByte());
mPenPosition.translate(dh, 0); penPosition.translate(dh, 0);
mContext.moveTo(mPenPosition); context.moveTo(penPosition);
text = PICTUtil.readPascalString(pStream); text = PICTUtil.readPascalString(pStream);
// TODO // TODO
// if (mGraphics != null) { // if (mGraphics != null) {
// mGraphics.drawString(text, mPenPosition.x, mPenPosition.y); // mGraphics.drawString(text, penPosition.x, penPosition.y);
// } // }
mContext.drawString(text); context.drawString(text);
if (DEBUG) { if (DEBUG) {
System.out.println("DHText dh: " + dh + ", text:" + text); System.out.println("DHText dh: " + dh + ", text:" + text);
} }
@@ -797,14 +800,14 @@ public class PICTImageReader extends ImageReaderBase {
case PICT.OP_DV_TEXT:// OK, not tested case PICT.OP_DV_TEXT:// OK, not tested
// Get dh // Get dh
dv = getYPtCoord(pStream.readByte()); dv = getYPtCoord(pStream.readByte());
mPenPosition.translate(0, dv); penPosition.translate(0, dv);
mContext.moveTo(mPenPosition); context.moveTo(penPosition);
text = PICTUtil.readPascalString(pStream); text = PICTUtil.readPascalString(pStream);
// TODO // TODO
//if (mGraphics != null) { //if (mGraphics != null) {
// mGraphics.drawString(text, mPenPosition.x, mPenPosition.y); // mGraphics.drawString(text, penPosition.x, penPosition.y);
//} //}
mContext.drawString(text); context.drawString(text);
if (DEBUG) { if (DEBUG) {
System.out.println("DVText dv: " + dv + ", text:" + text); System.out.println("DVText dv: " + dv + ", text:" + text);
} }
@@ -814,16 +817,16 @@ public class PICTImageReader extends ImageReaderBase {
// Get dh, dv // Get dh, dv
y = getYPtCoord(pStream.readByte()); y = getYPtCoord(pStream.readByte());
x = getXPtCoord(pStream.readByte()); x = getXPtCoord(pStream.readByte());
mPenPosition.translate(x, y); penPosition.translate(x, y);
mContext.moveTo(mPenPosition); context.moveTo(penPosition);
text = PICTUtil.readPascalString(pStream); text = PICTUtil.readPascalString(pStream);
// TODO // TODO
//if (mGraphics != null) { //if (mGraphics != null) {
// mGraphics.drawString(text, mPenPosition.x, mPenPosition.y); // mGraphics.drawString(text, penPosition.x, penPosition.y);
//} //}
mContext.drawString(text); context.drawString(text);
if (DEBUG) { if (DEBUG) {
System.out.println("DHDVText penPosition: " + mPenPosition + ", text:" + text); System.out.println("DHDVText penPosition: " + penPosition + ", text:" + text);
} }
break; break;
@@ -843,7 +846,7 @@ public class PICTImageReader extends ImageReaderBase {
// mGraphics.setFont(Font.decode(text) // mGraphics.setFont(Font.decode(text)
// .deriveFont(currentFont.getStyle(), currentFont.getSize())); // .deriveFont(currentFont.getStyle(), currentFont.getSize()));
//} //}
mContext.drawString(text); context.drawString(text);
if (DEBUG) { if (DEBUG) {
System.out.println("fontName: \"" + text +"\""); System.out.println("fontName: \"" + text +"\"");
} }
@@ -882,7 +885,7 @@ public class PICTImageReader extends ImageReaderBase {
case PICT.OP_INVERT_RECT:// OK, not tested case PICT.OP_INVERT_RECT:// OK, not tested
case PICT.OP_FILL_RECT:// OK, not tested case PICT.OP_FILL_RECT:// OK, not tested
// Get the frame rectangle // Get the frame rectangle
readRectangle(pStream, mLastRectangle); readRectangle(pStream, lastRectangle);
case PICT.OP_FRAME_SAME_RECT:// OK, not tested case PICT.OP_FRAME_SAME_RECT:// OK, not tested
case PICT.OP_PAINT_SAME_RECT:// OK, not tested case PICT.OP_PAINT_SAME_RECT:// OK, not tested
@@ -893,23 +896,23 @@ public class PICTImageReader extends ImageReaderBase {
switch (opCode) { switch (opCode) {
case PICT.OP_FRAME_RECT: case PICT.OP_FRAME_RECT:
case PICT.OP_FRAME_SAME_RECT: case PICT.OP_FRAME_SAME_RECT:
mContext.frameRect(mLastRectangle); context.frameRect(lastRectangle);
break; break;
case PICT.OP_PAINT_RECT: case PICT.OP_PAINT_RECT:
case PICT.OP_PAINT_SAME_RECT: case PICT.OP_PAINT_SAME_RECT:
mContext.paintRect(mLastRectangle); context.paintRect(lastRectangle);
break; break;
case PICT.OP_ERASE_RECT: case PICT.OP_ERASE_RECT:
case PICT.OP_ERASE_SAME_RECT: case PICT.OP_ERASE_SAME_RECT:
mContext.eraseRect(mLastRectangle); context.eraseRect(lastRectangle);
break; break;
case PICT.OP_INVERT_RECT: case PICT.OP_INVERT_RECT:
case PICT.OP_INVERT_SAME_RECT: case PICT.OP_INVERT_SAME_RECT:
mContext.invertRect(mLastRectangle); context.invertRect(lastRectangle);
break; break;
case PICT.OP_FILL_RECT: case PICT.OP_FILL_RECT:
case PICT.OP_FILL_SAME_RECT: case PICT.OP_FILL_SAME_RECT:
mContext.fillRect(mLastRectangle, fill); context.fillRect(lastRectangle, fill);
break; break;
} }
@@ -917,34 +920,34 @@ public class PICTImageReader extends ImageReaderBase {
if (DEBUG) { if (DEBUG) {
switch (opCode) { switch (opCode) {
case PICT.OP_FRAME_RECT: case PICT.OP_FRAME_RECT:
System.out.println("frameRect: " + mLastRectangle); System.out.println("frameRect: " + lastRectangle);
break; break;
case PICT.OP_PAINT_RECT: case PICT.OP_PAINT_RECT:
System.out.println("paintRect: " + mLastRectangle); System.out.println("paintRect: " + lastRectangle);
break; break;
case PICT.OP_ERASE_RECT: case PICT.OP_ERASE_RECT:
System.out.println("eraseRect: " + mLastRectangle); System.out.println("eraseRect: " + lastRectangle);
break; break;
case PICT.OP_INVERT_RECT: case PICT.OP_INVERT_RECT:
System.out.println("invertRect: " + mLastRectangle); System.out.println("invertRect: " + lastRectangle);
break; break;
case PICT.OP_FILL_RECT: case PICT.OP_FILL_RECT:
System.out.println("fillRect: " + mLastRectangle); System.out.println("fillRect: " + lastRectangle);
break; break;
case PICT.OP_FRAME_SAME_RECT: case PICT.OP_FRAME_SAME_RECT:
System.out.println("frameSameRect: " + mLastRectangle); System.out.println("frameSameRect: " + lastRectangle);
break; break;
case PICT.OP_PAINT_SAME_RECT: case PICT.OP_PAINT_SAME_RECT:
System.out.println("paintSameRect: " + mLastRectangle); System.out.println("paintSameRect: " + lastRectangle);
break; break;
case PICT.OP_ERASE_SAME_RECT: case PICT.OP_ERASE_SAME_RECT:
System.out.println("eraseSameRect: " + mLastRectangle); System.out.println("eraseSameRect: " + lastRectangle);
break; break;
case PICT.OP_INVERT_SAME_RECT: case PICT.OP_INVERT_SAME_RECT:
System.out.println("invertSameRect: " + mLastRectangle); System.out.println("invertSameRect: " + lastRectangle);
break; break;
case PICT.OP_FILL_SAME_RECT: case PICT.OP_FILL_SAME_RECT:
System.out.println("fillSameRect: " + mLastRectangle); System.out.println("fillSameRect: " + lastRectangle);
break; break;
} }
} }
@@ -969,7 +972,7 @@ public class PICTImageReader extends ImageReaderBase {
case PICT.OP_INVERT_R_RECT:// OK, not tested case PICT.OP_INVERT_R_RECT:// OK, not tested
case PICT.OP_FILL_R_RECT:// OK, not tested case PICT.OP_FILL_R_RECT:// OK, not tested
// Get the frame rectangle // Get the frame rectangle
readRectangle(pStream, mLastRectangle); readRectangle(pStream, lastRectangle);
case PICT.OP_FRAME_SAME_R_RECT:// OK, not tested case PICT.OP_FRAME_SAME_R_RECT:// OK, not tested
case PICT.OP_PAINT_SAME_R_RECT:// OK, not tested case PICT.OP_PAINT_SAME_R_RECT:// OK, not tested
@@ -980,23 +983,23 @@ public class PICTImageReader extends ImageReaderBase {
switch (opCode) { switch (opCode) {
case PICT.OP_FRAME_R_RECT: case PICT.OP_FRAME_R_RECT:
case PICT.OP_FRAME_SAME_R_RECT: case PICT.OP_FRAME_SAME_R_RECT:
mContext.frameRoundRect(mLastRectangle, ovSize.x, ovSize.y); context.frameRoundRect(lastRectangle, ovSize.x, ovSize.y);
break; break;
case PICT.OP_PAINT_R_RECT: case PICT.OP_PAINT_R_RECT:
case PICT.OP_PAINT_SAME_R_RECT: case PICT.OP_PAINT_SAME_R_RECT:
mContext.paintRoundRect(mLastRectangle, ovSize.x, ovSize.y); context.paintRoundRect(lastRectangle, ovSize.x, ovSize.y);
break; break;
case PICT.OP_ERASE_R_RECT: case PICT.OP_ERASE_R_RECT:
case PICT.OP_ERASE_SAME_R_RECT: case PICT.OP_ERASE_SAME_R_RECT:
mContext.eraseRoundRect(mLastRectangle, ovSize.x, ovSize.y); context.eraseRoundRect(lastRectangle, ovSize.x, ovSize.y);
break; break;
case PICT.OP_INVERT_R_RECT: case PICT.OP_INVERT_R_RECT:
case PICT.OP_INVERT_SAME_R_RECT: case PICT.OP_INVERT_SAME_R_RECT:
mContext.invertRoundRect(mLastRectangle, ovSize.x, ovSize.y); context.invertRoundRect(lastRectangle, ovSize.x, ovSize.y);
break; break;
case PICT.OP_FILL_R_RECT: case PICT.OP_FILL_R_RECT:
case PICT.OP_FILL_SAME_R_RECT: case PICT.OP_FILL_SAME_R_RECT:
mContext.fillRoundRect(mLastRectangle, ovSize.x, ovSize.y, fill); context.fillRoundRect(lastRectangle, ovSize.x, ovSize.y, fill);
break; break;
} }
@@ -1004,34 +1007,34 @@ public class PICTImageReader extends ImageReaderBase {
if (DEBUG) { if (DEBUG) {
switch (opCode) { switch (opCode) {
case PICT.OP_FRAME_R_RECT: case PICT.OP_FRAME_R_RECT:
System.out.println("frameRRect: " + mLastRectangle); System.out.println("frameRRect: " + lastRectangle);
break; break;
case PICT.OP_PAINT_R_RECT: case PICT.OP_PAINT_R_RECT:
System.out.println("paintRRect: " + mLastRectangle); System.out.println("paintRRect: " + lastRectangle);
break; break;
case PICT.OP_ERASE_R_RECT: case PICT.OP_ERASE_R_RECT:
System.out.println("eraseRRect: " + mLastRectangle); System.out.println("eraseRRect: " + lastRectangle);
break; break;
case PICT.OP_INVERT_R_RECT: case PICT.OP_INVERT_R_RECT:
System.out.println("invertRRect: " + mLastRectangle); System.out.println("invertRRect: " + lastRectangle);
break; break;
case PICT.OP_FILL_R_RECT: case PICT.OP_FILL_R_RECT:
System.out.println("fillRRect: " + mLastRectangle); System.out.println("fillRRect: " + lastRectangle);
break; break;
case PICT.OP_FRAME_SAME_R_RECT: case PICT.OP_FRAME_SAME_R_RECT:
System.out.println("frameSameRRect: " + mLastRectangle); System.out.println("frameSameRRect: " + lastRectangle);
break; break;
case PICT.OP_PAINT_SAME_R_RECT: case PICT.OP_PAINT_SAME_R_RECT:
System.out.println("paintSameRRect: " + mLastRectangle); System.out.println("paintSameRRect: " + lastRectangle);
break; break;
case PICT.OP_ERASE_SAME_R_RECT: case PICT.OP_ERASE_SAME_R_RECT:
System.out.println("eraseSameRRect: " + mLastRectangle); System.out.println("eraseSameRRect: " + lastRectangle);
break; break;
case PICT.OP_INVERT_SAME_R_RECT: case PICT.OP_INVERT_SAME_R_RECT:
System.out.println("invertSameRRect: " + mLastRectangle); System.out.println("invertSameRRect: " + lastRectangle);
break; break;
case PICT.OP_FILL_SAME_R_RECT: case PICT.OP_FILL_SAME_R_RECT:
System.out.println("fillSameRRect: " + mLastRectangle); System.out.println("fillSameRRect: " + lastRectangle);
break; break;
} }
} }
@@ -1048,7 +1051,7 @@ public class PICTImageReader extends ImageReaderBase {
case PICT.OP_INVERT_OVAL:// OK, not tested case PICT.OP_INVERT_OVAL:// OK, not tested
case PICT.OP_FILL_OVAL:// OK, not tested case PICT.OP_FILL_OVAL:// OK, not tested
// Get the frame rectangle // Get the frame rectangle
readRectangle(pStream, mLastRectangle); readRectangle(pStream, lastRectangle);
case PICT.OP_FRAME_SAME_OVAL:// OK, not tested case PICT.OP_FRAME_SAME_OVAL:// OK, not tested
case PICT.OP_PAINT_SAME_OVAL:// OK, not tested case PICT.OP_PAINT_SAME_OVAL:// OK, not tested
case PICT.OP_ERASE_SAME_OVAL:// OK, not tested case PICT.OP_ERASE_SAME_OVAL:// OK, not tested
@@ -1058,23 +1061,23 @@ public class PICTImageReader extends ImageReaderBase {
switch (opCode) { switch (opCode) {
case PICT.OP_FRAME_OVAL: case PICT.OP_FRAME_OVAL:
case PICT.OP_FRAME_SAME_OVAL: case PICT.OP_FRAME_SAME_OVAL:
mContext.frameOval(mLastRectangle); context.frameOval(lastRectangle);
break; break;
case PICT.OP_PAINT_OVAL: case PICT.OP_PAINT_OVAL:
case PICT.OP_PAINT_SAME_OVAL: case PICT.OP_PAINT_SAME_OVAL:
mContext.paintOval(mLastRectangle); context.paintOval(lastRectangle);
break; break;
case PICT.OP_ERASE_OVAL: case PICT.OP_ERASE_OVAL:
case PICT.OP_ERASE_SAME_OVAL: case PICT.OP_ERASE_SAME_OVAL:
mContext.eraseOval(mLastRectangle); context.eraseOval(lastRectangle);
break; break;
case PICT.OP_INVERT_OVAL: case PICT.OP_INVERT_OVAL:
case PICT.OP_INVERT_SAME_OVAL: case PICT.OP_INVERT_SAME_OVAL:
mContext.invertOval(mLastRectangle); context.invertOval(lastRectangle);
break; break;
case PICT.OP_FILL_OVAL: case PICT.OP_FILL_OVAL:
case PICT.OP_FILL_SAME_OVAL: case PICT.OP_FILL_SAME_OVAL:
mContext.fillOval(mLastRectangle, fill); context.fillOval(lastRectangle, fill);
break; break;
} }
@@ -1082,34 +1085,34 @@ public class PICTImageReader extends ImageReaderBase {
if (DEBUG) { if (DEBUG) {
switch (opCode) { switch (opCode) {
case PICT.OP_FRAME_OVAL: case PICT.OP_FRAME_OVAL:
System.out.println("frameOval: " + mLastRectangle); System.out.println("frameOval: " + lastRectangle);
break; break;
case PICT.OP_PAINT_OVAL: case PICT.OP_PAINT_OVAL:
System.out.println("paintOval: " + mLastRectangle); System.out.println("paintOval: " + lastRectangle);
break; break;
case PICT.OP_ERASE_OVAL: case PICT.OP_ERASE_OVAL:
System.out.println("eraseOval: " + mLastRectangle); System.out.println("eraseOval: " + lastRectangle);
break; break;
case PICT.OP_INVERT_OVAL: case PICT.OP_INVERT_OVAL:
System.out.println("invertOval: " + mLastRectangle); System.out.println("invertOval: " + lastRectangle);
break; break;
case PICT.OP_FILL_OVAL: case PICT.OP_FILL_OVAL:
System.out.println("fillOval: " + mLastRectangle); System.out.println("fillOval: " + lastRectangle);
break; break;
case PICT.OP_FRAME_SAME_OVAL: case PICT.OP_FRAME_SAME_OVAL:
System.out.println("frameSameOval: " + mLastRectangle); System.out.println("frameSameOval: " + lastRectangle);
break; break;
case PICT.OP_PAINT_SAME_OVAL: case PICT.OP_PAINT_SAME_OVAL:
System.out.println("paintSameOval: " + mLastRectangle); System.out.println("paintSameOval: " + lastRectangle);
break; break;
case PICT.OP_ERASE_SAME_OVAL: case PICT.OP_ERASE_SAME_OVAL:
System.out.println("eraseSameOval: " + mLastRectangle); System.out.println("eraseSameOval: " + lastRectangle);
break; break;
case PICT.OP_INVERT_SAME_OVAL: case PICT.OP_INVERT_SAME_OVAL:
System.out.println("invertSameOval: " + mLastRectangle); System.out.println("invertSameOval: " + lastRectangle);
break; break;
case PICT.OP_FILL_SAME_OVAL: case PICT.OP_FILL_SAME_OVAL:
System.out.println("fillSameOval: " + mLastRectangle); System.out.println("fillSameOval: " + lastRectangle);
break; break;
} }
} }
@@ -1141,7 +1144,7 @@ public class PICTImageReader extends ImageReaderBase {
case PICT.OP_INVERT_ARC:// OK, not tested case PICT.OP_INVERT_ARC:// OK, not tested
case PICT.OP_FILL_ARC:// OK, not tested case PICT.OP_FILL_ARC:// OK, not tested
// Get the frame rectangle // Get the frame rectangle
readRectangle(pStream, mLastRectangle); readRectangle(pStream, lastRectangle);
case PICT.OP_FRAME_SAME_ARC:// OK, not tested case PICT.OP_FRAME_SAME_ARC:// OK, not tested
case PICT.OP_PAINT_SAME_ARC:// OK, not tested case PICT.OP_PAINT_SAME_ARC:// OK, not tested
case PICT.OP_ERASE_SAME_ARC:// OK, not tested case PICT.OP_ERASE_SAME_ARC:// OK, not tested
@@ -1159,23 +1162,23 @@ public class PICTImageReader extends ImageReaderBase {
switch (opCode) { switch (opCode) {
case PICT.OP_FRAME_ARC: case PICT.OP_FRAME_ARC:
case PICT.OP_FRAME_SAME_ARC: case PICT.OP_FRAME_SAME_ARC:
mContext.frameArc(mLastRectangle, arcAngles.x, arcAngles.y); context.frameArc(lastRectangle, arcAngles.x, arcAngles.y);
break; break;
case PICT.OP_PAINT_ARC: case PICT.OP_PAINT_ARC:
case PICT.OP_PAINT_SAME_ARC: case PICT.OP_PAINT_SAME_ARC:
mContext.paintArc(mLastRectangle, arcAngles.x, arcAngles.y); context.paintArc(lastRectangle, arcAngles.x, arcAngles.y);
break; break;
case PICT.OP_ERASE_ARC: case PICT.OP_ERASE_ARC:
case PICT.OP_ERASE_SAME_ARC: case PICT.OP_ERASE_SAME_ARC:
mContext.eraseArc(mLastRectangle, arcAngles.x, arcAngles.y); context.eraseArc(lastRectangle, arcAngles.x, arcAngles.y);
break; break;
case PICT.OP_INVERT_ARC: case PICT.OP_INVERT_ARC:
case PICT.OP_INVERT_SAME_ARC: case PICT.OP_INVERT_SAME_ARC:
mContext.invertArc(mLastRectangle, arcAngles.x, arcAngles.y); context.invertArc(lastRectangle, arcAngles.x, arcAngles.y);
break; break;
case PICT.OP_FILL_ARC: case PICT.OP_FILL_ARC:
case PICT.OP_FILL_SAME_ARC: case PICT.OP_FILL_SAME_ARC:
mContext.fillArc(mLastRectangle, arcAngles.x, arcAngles.y, fill); context.fillArc(lastRectangle, arcAngles.x, arcAngles.y, fill);
break; break;
} }
@@ -1183,34 +1186,34 @@ public class PICTImageReader extends ImageReaderBase {
if (DEBUG) { if (DEBUG) {
switch (opCode) { switch (opCode) {
case PICT.OP_FRAME_ARC: case PICT.OP_FRAME_ARC:
System.out.println("frameArc: " + mLastRectangle + ", angles:" + arcAngles); System.out.println("frameArc: " + lastRectangle + ", angles:" + arcAngles);
break; break;
case PICT.OP_PAINT_ARC: case PICT.OP_PAINT_ARC:
System.out.println("paintArc: " + mLastRectangle + ", angles:" + arcAngles); System.out.println("paintArc: " + lastRectangle + ", angles:" + arcAngles);
break; break;
case PICT.OP_ERASE_ARC: case PICT.OP_ERASE_ARC:
System.out.println("eraseArc: " + mLastRectangle + ", angles:" + arcAngles); System.out.println("eraseArc: " + lastRectangle + ", angles:" + arcAngles);
break; break;
case PICT.OP_INVERT_ARC: case PICT.OP_INVERT_ARC:
System.out.println("invertArc: " + mLastRectangle + ", angles:" + arcAngles); System.out.println("invertArc: " + lastRectangle + ", angles:" + arcAngles);
break; break;
case PICT.OP_FILL_ARC: case PICT.OP_FILL_ARC:
System.out.println("fillArc: " + mLastRectangle + ", angles:" + arcAngles); System.out.println("fillArc: " + lastRectangle + ", angles:" + arcAngles);
break; break;
case PICT.OP_FRAME_SAME_ARC: case PICT.OP_FRAME_SAME_ARC:
System.out.println("frameSameArc: " + mLastRectangle + ", angles:" + arcAngles); System.out.println("frameSameArc: " + lastRectangle + ", angles:" + arcAngles);
break; break;
case PICT.OP_PAINT_SAME_ARC: case PICT.OP_PAINT_SAME_ARC:
System.out.println("paintSameArc: " + mLastRectangle + ", angles:" + arcAngles); System.out.println("paintSameArc: " + lastRectangle + ", angles:" + arcAngles);
break; break;
case PICT.OP_ERASE_SAME_ARC: case PICT.OP_ERASE_SAME_ARC:
System.out.println("eraseSameArc: " + mLastRectangle + ", angles:" + arcAngles); System.out.println("eraseSameArc: " + lastRectangle + ", angles:" + arcAngles);
break; break;
case PICT.OP_INVERT_SAME_ARC: case PICT.OP_INVERT_SAME_ARC:
System.out.println("invertSameArc: " + mLastRectangle + ", angles:" + arcAngles); System.out.println("invertSameArc: " + lastRectangle + ", angles:" + arcAngles);
break; break;
case PICT.OP_FILL_SAME_ARC: case PICT.OP_FILL_SAME_ARC:
System.out.println("fillSameArc: " + mLastRectangle + ", angles:" + arcAngles); System.out.println("fillSameArc: " + lastRectangle + ", angles:" + arcAngles);
break; break;
} }
} }
@@ -1256,23 +1259,23 @@ public class PICTImageReader extends ImageReaderBase {
switch (opCode) { switch (opCode) {
case PICT.OP_FRAME_POLY: case PICT.OP_FRAME_POLY:
case PICT.OP_FRAME_SAME_POLY: case PICT.OP_FRAME_SAME_POLY:
mContext.framePoly(polygon); context.framePoly(polygon);
break; break;
case PICT.OP_PAINT_POLY: case PICT.OP_PAINT_POLY:
case PICT.OP_PAINT_SAME_POLY: case PICT.OP_PAINT_SAME_POLY:
mContext.paintPoly(polygon); context.paintPoly(polygon);
break; break;
case PICT.OP_ERASE_POLY: case PICT.OP_ERASE_POLY:
case PICT.OP_ERASE_SAME_POLY: case PICT.OP_ERASE_SAME_POLY:
mContext.erasePoly(polygon); context.erasePoly(polygon);
break; break;
case PICT.OP_INVERT_POLY: case PICT.OP_INVERT_POLY:
case PICT.OP_INVERT_SAME_POLY: case PICT.OP_INVERT_SAME_POLY:
mContext.invertPoly(polygon); context.invertPoly(polygon);
break; break;
case PICT.OP_FILL_POLY: case PICT.OP_FILL_POLY:
case PICT.OP_FILL_SAME_POLY: case PICT.OP_FILL_SAME_POLY:
mContext.fillPoly(polygon, fill); context.fillPoly(polygon, fill);
break; break;
} }
@@ -1346,23 +1349,23 @@ public class PICTImageReader extends ImageReaderBase {
switch (opCode) { switch (opCode) {
case PICT.OP_FRAME_RGN: case PICT.OP_FRAME_RGN:
case PICT.OP_FRAME_SAME_RGN: case PICT.OP_FRAME_SAME_RGN:
mContext.frameRegion(new Area(region)); context.frameRegion(new Area(region));
break; break;
case PICT.OP_PAINT_RGN: case PICT.OP_PAINT_RGN:
case PICT.OP_PAINT_SAME_RGN: case PICT.OP_PAINT_SAME_RGN:
mContext.paintRegion(new Area(region)); context.paintRegion(new Area(region));
break; break;
case PICT.OP_ERASE_RGN: case PICT.OP_ERASE_RGN:
case PICT.OP_ERASE_SAME_RGN: case PICT.OP_ERASE_SAME_RGN:
mContext.eraseRegion(new Area(region)); context.eraseRegion(new Area(region));
break; break;
case PICT.OP_INVERT_RGN: case PICT.OP_INVERT_RGN:
case PICT.OP_INVERT_SAME_RGN: case PICT.OP_INVERT_SAME_RGN:
mContext.invertRegion(new Area(region)); context.invertRegion(new Area(region));
break; break;
case PICT.OP_FILL_RGN: case PICT.OP_FILL_RGN:
case PICT.OP_FILL_SAME_RGN: case PICT.OP_FILL_SAME_RGN:
mContext.fillRegion(new Area(region), fill); context.fillRegion(new Area(region), fill);
break; break;
} }
} }
@@ -1461,7 +1464,7 @@ public class PICTImageReader extends ImageReaderBase {
readRectangle(pStream, dstRect); readRectangle(pStream, dstRect);
mode = pStream.readUnsignedShort(); mode = pStream.readUnsignedShort();
mContext.setPenMode(mode); // TODO: Or parameter? context.setPenMode(mode); // TODO: Or parameter?
if (DEBUG) { if (DEBUG) {
System.out.print("bitsRect, rowBytes: " + rowBytes); System.out.print("bitsRect, rowBytes: " + rowBytes);
@@ -1491,7 +1494,7 @@ public class PICTImageReader extends ImageReaderBase {
// Draw pixel data // Draw pixel data
Rectangle rect = new Rectangle(srcRect); Rectangle rect = new Rectangle(srcRect);
rect.translate(-bounds.x, -bounds.y); rect.translate(-bounds.x, -bounds.y);
mContext.copyBits(image, rect, dstRect, mode, null); context.copyBits(image, rect, dstRect, mode, null);
//mGraphics.drawImage(image, //mGraphics.drawImage(image,
// dstRect.x, dstRect.y, // dstRect.x, dstRect.y,
// dstRect.x + dstRect.width, dstRect.y + dstRect.height, // dstRect.x + dstRect.width, dstRect.y + dstRect.height,
@@ -1729,7 +1732,7 @@ public class PICTImageReader extends ImageReaderBase {
BufferedImage image = QuickTime.decompress(pStream); BufferedImage image = QuickTime.decompress(pStream);
if (image != null) { if (image != null) {
mContext.copyBits(image, new Rectangle(image.getWidth(), image.getHeight()), destination, QuickDraw.SRC_COPY, null); context.copyBits(image, new Rectangle(image.getWidth(), image.getHeight()), destination, QuickDraw.SRC_COPY, null);
pStream.seek(pos + dataLength); // Might be word-align mismatch here pStream.seek(pos + dataLength); // Might be word-align mismatch here
@@ -2068,7 +2071,7 @@ public class PICTImageReader extends ImageReaderBase {
// We add all new images to it. If we are just replaying, then // We add all new images to it. If we are just replaying, then
// "pPixmapCount" will never be greater than the size of the vector // "pPixmapCount" will never be greater than the size of the vector
if (mImages.size() <= pPixmapCount) { if (images.size() <= pPixmapCount) {
// Create BufferedImage and add buffer it for multiple reads // Create BufferedImage and add buffer it for multiple reads
// DirectColorModel cm = (DirectColorModel) ColorModel.getRGBdefault(); // DirectColorModel cm = (DirectColorModel) ColorModel.getRGBdefault();
// DataBuffer db = new DataBufferInt(pixArray, pixArray.length); // DataBuffer db = new DataBufferInt(pixArray, pixArray.length);
@@ -2077,15 +2080,15 @@ public class PICTImageReader extends ImageReaderBase {
WritableRaster raster = Raster.createPackedRaster(db, pBounds.width, pBounds.height, cmpSize, null); // TODO: last param should ideally be srcRect.getLocation() WritableRaster raster = Raster.createPackedRaster(db, pBounds.width, pBounds.height, cmpSize, null); // TODO: last param should ideally be srcRect.getLocation()
BufferedImage img = new BufferedImage(colorModel, raster, colorModel.isAlphaPremultiplied(), null); BufferedImage img = new BufferedImage(colorModel, raster, colorModel.isAlphaPremultiplied(), null);
mImages.add(img); images.add(img);
} }
// Draw the image // Draw the image
BufferedImage img = mImages.get(pPixmapCount); BufferedImage img = images.get(pPixmapCount);
if (img != null) { if (img != null) {
// TODO: FixMe.. Seems impossible to create a bufferedImage with a raster not starting at 0,0 // TODO: FixMe.. Seems impossible to create a bufferedImage with a raster not starting at 0,0
srcRect.setLocation(0, 0); // should not require this line.. srcRect.setLocation(0, 0); // should not require this line..
mContext.copyBits(img, srcRect, dstRect, transferMode, null); context.copyBits(img, srcRect, dstRect, transferMode, null);
} }
// Line break at the end // Line break at the end
@@ -2378,7 +2381,7 @@ public class PICTImageReader extends ImageReaderBase {
// We add all new images to it. If we are just replaying, then // We add all new images to it. If we are just replaying, then
// "pPixmapCount" will never be greater than the size of the vector // "pPixmapCount" will never be greater than the size of the vector
if (mImages.size() <= pPixmapCount) { if (images.size() <= pPixmapCount) {
// Create BufferedImage and add buffer it for multiple reads // Create BufferedImage and add buffer it for multiple reads
DirectColorModel cm; DirectColorModel cm;
WritableRaster raster; WritableRaster raster;
@@ -2396,15 +2399,15 @@ public class PICTImageReader extends ImageReaderBase {
BufferedImage img = new BufferedImage(cm, raster, cm.isAlphaPremultiplied(), null); BufferedImage img = new BufferedImage(cm, raster, cm.isAlphaPremultiplied(), null);
mImages.add(img); images.add(img);
} }
// Draw the image // Draw the image
BufferedImage img = mImages.get(pPixmapCount); BufferedImage img = images.get(pPixmapCount);
if (img != null) { if (img != null) {
// TODO: FixMe.. Something wrong here, might be the copyBits methods. // TODO: FixMe.. Something wrong here, might be the copyBits methods.
srcRect.setLocation(0, 0); // should not require this line.. srcRect.setLocation(0, 0); // should not require this line..
mContext.copyBits(img, srcRect, dstRect, transferMode, null); context.copyBits(img, srcRect, dstRect, transferMode, null);
} }
// Line break at the end // Line break at the end
@@ -2551,7 +2554,7 @@ public class PICTImageReader extends ImageReaderBase {
* image resolution ratio. * image resolution ratio.
*/ */
private int getXPtCoord(int pPoint) { private int getXPtCoord(int pPoint) {
return (int) (pPoint / mScreenImageXRatio); return (int) (pPoint / screenImageXRatio);
} }
/* /*
@@ -2560,7 +2563,7 @@ public class PICTImageReader extends ImageReaderBase {
* image resolution ratio. * image resolution ratio.
*/ */
private int getYPtCoord(int pPoint) { private int getYPtCoord(int pPoint) {
return (int) (pPoint / mScreenImageYRatio); return (int) (pPoint / screenImageYRatio);
} }
/* /*
@@ -2621,7 +2624,7 @@ public class PICTImageReader extends ImageReaderBase {
try { try {
// TODO: Might need to clear background // TODO: Might need to clear background
g.setTransform(AffineTransform.getScaleInstance(mScreenImageXRatio / subX, mScreenImageYRatio / subY)); g.setTransform(AffineTransform.getScaleInstance(screenImageXRatio / subX, screenImageYRatio / subY));
// try { // try {
drawOnto(g); drawOnto(g);
// } // }
@@ -75,8 +75,8 @@ public class PICTImageReaderSpi extends ImageReaderSpi {
} }
ImageInputStream stream = (ImageInputStream) pSource; ImageInputStream stream = (ImageInputStream) pSource;
stream.mark(); stream.mark();
try { try {
if (isPICT(stream)) { if (isPICT(stream)) {
// If PICT Clipping format, return true immediately // If PICT Clipping format, return true immediately
@@ -87,6 +87,7 @@ public class PICTImageReaderSpi extends ImageReaderSpi {
stream.reset(); stream.reset();
PICTImageReader.skipNullHeader(stream); PICTImageReader.skipNullHeader(stream);
} }
return isPICT(stream); return isPICT(stream);
} }
catch (EOFException ignore) { catch (EOFException ignore) {
@@ -86,9 +86,9 @@ import java.io.*;
public class PICTImageWriter extends ImageWriterBase { public class PICTImageWriter extends ImageWriterBase {
// TODO: Inline these? // TODO: Inline these?
private int mRowBytes; private int rowBytes;
private byte[] mScanlineBytes; private byte[] scanlineBytes;
private int mScanWidthLeft; private int scanWidthLeft;
public PICTImageWriter() { public PICTImageWriter() {
this(null); this(null);
@@ -171,8 +171,8 @@ public class PICTImageWriter extends ImageWriterBase {
// Write rowBytes, this is 4 times the width. // Write rowBytes, this is 4 times the width.
// Set the high bit, to indicate a PixMap. // Set the high bit, to indicate a PixMap.
mRowBytes = 4 * pImage.getWidth(); rowBytes = 4 * pImage.getWidth();
imageOutput.writeShort(0x8000 | mRowBytes); imageOutput.writeShort(0x8000 | rowBytes);
// Write bounds rectangle (same as image bounds) // Write bounds rectangle (same as image bounds)
imageOutput.writeShort(0); imageOutput.writeShort(0);
@@ -235,14 +235,14 @@ public class PICTImageWriter extends ImageWriterBase {
// TODO: Move to writePICTData? // TODO: Move to writePICTData?
// TODO: Alpha support // TODO: Alpha support
// Set up the buffers for storing scanline bytes // Set up the buffers for storing scanline bytes
mScanlineBytes = new byte[3 * pImage.getWidth()]; scanlineBytes = new byte[3 * pImage.getWidth()];
mScanWidthLeft = pImage.getWidth(); scanWidthLeft = pImage.getWidth();
} }
private void writePICTData(int x, int y, int w, int h, ColorModel model, private void writePICTData(int x, int y, int w, int h, ColorModel model,
byte[] pixels, int off, int scansize) throws IOException { byte[] pixels, int off, int scansize) throws IOException {
ByteArrayOutputStream bytes = new FastByteArrayOutputStream(mScanlineBytes.length / 2); ByteArrayOutputStream bytes = new FastByteArrayOutputStream(scanlineBytes.length / 2);
int components = model.getNumComponents(); int components = model.getNumComponents();
@@ -252,36 +252,36 @@ public class PICTImageWriter extends ImageWriterBase {
// lines (h > 1) and (w < width). This should never be the case. // lines (h > 1) and (w < width). This should never be the case.
for (int i = 0; i < h; i++) { for (int i = 0; i < h; i++) {
// Reduce the counter of bytes left on the scanline. // Reduce the counter of bytes left on the scanline.
mScanWidthLeft -= w; scanWidthLeft -= w;
// Treat the scanline. // Treat the scanline.
for (int j = 0; j < w; j++) { for (int j = 0; j < w; j++) {
if (model instanceof ComponentColorModel && model.getColorSpace().getType() == ColorSpace.TYPE_RGB) { if (model instanceof ComponentColorModel && model.getColorSpace().getType() == ColorSpace.TYPE_RGB) {
// TODO: Component order? // TODO: Component order?
// TODO: Alpha support // TODO: Alpha support
mScanlineBytes[x + j] = pixels[off + i * scansize * components + components * j + 2]; scanlineBytes[x + j] = pixels[off + i * scansize * components + components * j + 2];
mScanlineBytes[x + w + j] = pixels[off + i * scansize * components + components * j + 1]; scanlineBytes[x + w + j] = pixels[off + i * scansize * components + components * j + 1];
mScanlineBytes[x + 2 * w + j] = pixels[off + i * scansize * components + components * j]; scanlineBytes[x + 2 * w + j] = pixels[off + i * scansize * components + components * j];
} }
else { else {
int rgb = model.getRGB(pixels[off + i * scansize + j] & 0xFF); int rgb = model.getRGB(pixels[off + i * scansize + j] & 0xFF);
// Set red, green and blue components. // Set red, green and blue components.
mScanlineBytes[x + j] = (byte) ((rgb >> 16) & 0xFF); scanlineBytes[x + j] = (byte) ((rgb >> 16) & 0xFF);
mScanlineBytes[x + w + j] = (byte) ((rgb >> 8) & 0xFF); scanlineBytes[x + w + j] = (byte) ((rgb >> 8) & 0xFF);
mScanlineBytes[x + 2 * w + j] = (byte) (rgb & 0xFF); scanlineBytes[x + 2 * w + j] = (byte) (rgb & 0xFF);
} }
} }
// If we have a complete scanline, then pack it and write it out. // If we have a complete scanline, then pack it and write it out.
if (mScanWidthLeft == 0) { if (scanWidthLeft == 0) {
// Pack using PackBitsEncoder/EncoderStream // Pack using PackBitsEncoder/EncoderStream
bytes.reset(); bytes.reset();
DataOutput packBits = new DataOutputStream(new EncoderStream(bytes, new PackBitsEncoder(), true)); DataOutput packBits = new DataOutputStream(new EncoderStream(bytes, new PackBitsEncoder(), true));
packBits.write(mScanlineBytes); packBits.write(scanlineBytes);
if (mRowBytes > 250) { if (rowBytes > 250) {
imageOutput.writeShort(bytes.size()); imageOutput.writeShort(bytes.size());
} }
else { else {
@@ -290,7 +290,7 @@ public class PICTImageWriter extends ImageWriterBase {
bytes.writeTo(IIOUtil.createStreamAdapter(imageOutput)); bytes.writeTo(IIOUtil.createStreamAdapter(imageOutput));
mScanWidthLeft = w; scanWidthLeft = w;
} }
} }
} }
@@ -298,7 +298,7 @@ public class PICTImageWriter extends ImageWriterBase {
private void writePICTData(int x, int y, int w, int h, ColorModel model, private void writePICTData(int x, int y, int w, int h, ColorModel model,
int[] pixels, int off, int scansize) throws IOException { int[] pixels, int off, int scansize) throws IOException {
ByteArrayOutputStream bytes = new FastByteArrayOutputStream(mScanlineBytes.length / 2); ByteArrayOutputStream bytes = new FastByteArrayOutputStream(scanlineBytes.length / 2);
// TODO: Clean up, as we only have complete scanlines // TODO: Clean up, as we only have complete scanlines
@@ -306,27 +306,27 @@ public class PICTImageWriter extends ImageWriterBase {
// lines (h > 1) and (w < width). This should never be the case. // lines (h > 1) and (w < width). This should never be the case.
for (int i = 0; i < h; i++) { for (int i = 0; i < h; i++) {
// Reduce the counter of bytes left on the scanline. // Reduce the counter of bytes left on the scanline.
mScanWidthLeft -= w; scanWidthLeft -= w;
// Treat the scanline. // Treat the scanline.
for (int j = 0; j < w; j++) { for (int j = 0; j < w; j++) {
int rgb = model.getRGB(pixels[off + i * scansize + j]); int rgb = model.getRGB(pixels[off + i * scansize + j]);
// Set red, green and blue components. // Set red, green and blue components.
mScanlineBytes[x + j] = (byte) ((rgb >> 16) & 0xFF); scanlineBytes[x + j] = (byte) ((rgb >> 16) & 0xFF);
mScanlineBytes[x + w + j] = (byte) ((rgb >> 8) & 0xFF); scanlineBytes[x + w + j] = (byte) ((rgb >> 8) & 0xFF);
mScanlineBytes[x + 2 * w + j] = (byte) (rgb & 0xFF); scanlineBytes[x + 2 * w + j] = (byte) (rgb & 0xFF);
} }
// If we have a complete scanline, then pack it and write it out. // If we have a complete scanline, then pack it and write it out.
if (mScanWidthLeft == 0) { if (scanWidthLeft == 0) {
// Pack using PackBitsEncoder/EncoderStream // Pack using PackBitsEncoder/EncoderStream
bytes.reset(); bytes.reset();
DataOutput packBits = new DataOutputStream(new EncoderStream(bytes, new PackBitsEncoder(), true)); DataOutput packBits = new DataOutputStream(new EncoderStream(bytes, new PackBitsEncoder(), true));
packBits.write(mScanlineBytes); packBits.write(scanlineBytes);
if (mRowBytes > 250) { if (rowBytes > 250) {
imageOutput.writeShort(bytes.size()); imageOutput.writeShort(bytes.size());
} }
else { else {
@@ -335,7 +335,7 @@ public class PICTImageWriter extends ImageWriterBase {
bytes.writeTo(IIOUtil.createStreamAdapter(imageOutput)); bytes.writeTo(IIOUtil.createStreamAdapter(imageOutput));
mScanWidthLeft = w; scanWidthLeft = w;
} }
} }
} }
@@ -42,16 +42,16 @@ import java.util.Collections;
* @version $Id: Pattern.java,v 1.0 Oct 9, 2007 1:21:38 AM haraldk Exp$ * @version $Id: Pattern.java,v 1.0 Oct 9, 2007 1:21:38 AM haraldk Exp$
*/ */
abstract class Pattern implements Paint { abstract class Pattern implements Paint {
private final Paint mPaint; private final Paint paint;
Pattern(final Paint pPaint) { Pattern(final Paint pPaint) {
mPaint = pPaint; paint = pPaint;
} }
public PaintContext createContext(final ColorModel pModel, final Rectangle pDeviceBounds, public PaintContext createContext(final ColorModel pModel, final Rectangle pDeviceBounds,
final Rectangle2D pUserBounds, final AffineTransform pTransform, final Rectangle2D pUserBounds, final AffineTransform pTransform,
final RenderingHints pHints) { final RenderingHints pHints) {
return mPaint.createContext( return paint.createContext(
pModel, pDeviceBounds, pModel, pDeviceBounds,
pUserBounds, pTransform, pUserBounds, pTransform,
pHints != null ? pHints : new RenderingHints(Collections.<RenderingHints.Key, Object>emptyMap()) pHints != null ? pHints : new RenderingHints(Collections.<RenderingHints.Key, Object>emptyMap())
@@ -59,6 +59,6 @@ abstract class Pattern implements Paint {
} }
public int getTransparency() { public int getTransparency() {
return mPaint.getTransparency(); return paint.getTransparency();
} }
} }
@@ -38,15 +38,15 @@ import java.awt.*;
* @version $Id: PenState.java,v 1.0 Oct 9, 2007 1:56:33 AM haraldk Exp$ * @version $Id: PenState.java,v 1.0 Oct 9, 2007 1:56:33 AM haraldk Exp$
*/ */
class PenState { class PenState {
public final Point mPenLocation; /* pen location */ public final Point penLocation; /* pen location */
public final Dimension mPenSize; /* pen size */ public final Dimension penSize; /* pen size */
public final int mPenMode; /* pen's pattern mode */ public final int penMode; /* pen's pattern mode */
public final Pattern mPenPattern; /* pen pattern */ public final Pattern penPattern; /* pen pattern */
public PenState(final Point pPenLocation, final int pPenMode, final Pattern pPenPattern, final Dimension pPenSize) { public PenState(final Point pPenLocation, final int pPenMode, final Pattern pPenPattern, final Dimension pPenSize) {
mPenLocation = pPenLocation; penLocation = pPenLocation;
mPenMode = pPenMode; penMode = pPenMode;
mPenPattern = pPenPattern; penPattern = pPenPattern;
mPenSize = pPenSize; penSize = pPenSize;
} }
} }
@@ -38,17 +38,17 @@ import java.awt.*;
* @version $Id: PixMapPattern.java,v 1.0 Mar 1, 2009 11:36:10 PM haraldk Exp$ * @version $Id: PixMapPattern.java,v 1.0 Mar 1, 2009 11:36:10 PM haraldk Exp$
*/ */
final class PixMapPattern extends Pattern { final class PixMapPattern extends Pattern {
private final Pattern mFallback; private final Pattern fallback;
PixMapPattern(final Paint pPaint, final Pattern pBitMapFallback) { PixMapPattern(final Paint pPaint, final Pattern pBitMapFallback) {
super(pPaint); super(pPaint);
mFallback = pBitMapFallback; fallback = pBitMapFallback;
} }
/** /**
* @return the fallback B/W pattern * @return the fallback B/W pattern
*/ */
public Pattern getPattern() { public Pattern getPattern() {
return mFallback; return fallback;
} }
} }
@@ -28,6 +28,8 @@
package com.twelvemonkeys.imageio.plugins.pict; package com.twelvemonkeys.imageio.plugins.pict;
import com.twelvemonkeys.lang.Validate;
import java.awt.*; import java.awt.*;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
import java.awt.geom.*; import java.awt.geom.*;
@@ -101,9 +103,9 @@ class QuickDrawContext {
rgnSave: Handle; {region being saved, used internally} rgnSave: Handle; {region being saved, used internally}
polySave: Handle; {polygon being saved, used internally} polySave: Handle; {polygon being saved, used internally}
*/ */
private final Graphics2D mGraphics; private final Graphics2D graphics;
private Pattern mBackground; private Pattern background;
// http://developer.apple.com/documentation/mac/quickdraw/QuickDraw-68.html#HEADING68-0 // http://developer.apple.com/documentation/mac/quickdraw/QuickDraw-68.html#HEADING68-0
// Upon the creation of a graphics port, QuickDraw assigns these initial // Upon the creation of a graphics port, QuickDraw assigns these initial
@@ -113,23 +115,20 @@ class QuickDrawContext {
// graphics pen. // graphics pen.
// TODO: Consider creating a Pen/PenState class? // TODO: Consider creating a Pen/PenState class?
private int mPenVisibility = 0; private int penVisibility = 0;
private Point2D mPenPosition = new Point(); private Point2D penPosition = new Point();
private Pattern mPenPattern; private Pattern penPattern;
private Dimension2D mPenSize = new Dimension(); private Dimension2D penSize = new Dimension();
private int mPenMode; private int penMode;
QuickDrawContext(Graphics2D pGraphics) { QuickDrawContext(Graphics2D pGraphics) {
if (pGraphics == null) { graphics = Validate.notNull(pGraphics, "graphics");
throw new IllegalArgumentException("graphics == null");
}
mGraphics = pGraphics;
setPenNormal(); setPenNormal();
} }
protected void dispose() { protected void dispose() {
mGraphics.dispose(); graphics.dispose();
} }
// ClosePicture // ClosePicture
@@ -139,7 +138,7 @@ class QuickDrawContext {
// ClipRgn // ClipRgn
public void setClipRegion(Shape pClip) { public void setClipRegion(Shape pClip) {
mGraphics.setClip(pClip); graphics.setClip(pClip);
} }
// Font number (sic), integer // Font number (sic), integer
@@ -160,7 +159,7 @@ class QuickDrawContext {
} }
public void setTextSize(int pSize) { public void setTextSize(int pSize) {
mGraphics.setFont(mGraphics.getFont().deriveFont((float) pSize)); graphics.setFont(graphics.getFont().deriveFont((float) pSize));
} }
// Numerator (Point), denominator (Point) // Numerator (Point), denominator (Point)
@@ -173,16 +172,16 @@ class QuickDrawContext {
// TODO: chExtra added width for nonspace characters // TODO: chExtra added width for nonspace characters
public void setOrigin(Point2D pOrigin) { public void setOrigin(Point2D pOrigin) {
mGraphics.translate(pOrigin.getX(), pOrigin.getY()); graphics.translate(pOrigin.getX(), pOrigin.getY());
} }
public void setForeground(Color pColor) { public void setForeground(Color pColor) {
// TODO: Is this really correct? Or does it depend on pattern mode? // TODO: Is this really correct? Or does it depend on pattern mode?
mPenPattern = new BitMapPattern(pColor); penPattern = new BitMapPattern(pColor);
} }
public void setBackground(Color pColor) { public void setBackground(Color pColor) {
mBackground = new BitMapPattern(pColor); background = new BitMapPattern(pColor);
} }
/* /*
@@ -197,14 +196,14 @@ class QuickDrawContext {
* HidePen Visibility (decrements visibility by one!) * HidePen Visibility (decrements visibility by one!)
*/ */
public void hidePen() { public void hidePen() {
mPenVisibility--; penVisibility--;
} }
/** /**
* ShowPen Visibility (increments visibility by one!) * ShowPen Visibility (increments visibility by one!)
*/ */
public void showPen() { public void showPen() {
mPenVisibility++; penVisibility++;
} }
/** /**
@@ -213,7 +212,7 @@ class QuickDrawContext {
* @return {@code true} if pen is visible * @return {@code true} if pen is visible
*/ */
private boolean isPenVisible() { private boolean isPenVisible() {
return mPenVisibility >= 0; return penVisibility >= 0;
} }
/** /**
@@ -223,7 +222,7 @@ class QuickDrawContext {
* @return the current pen position * @return the current pen position
*/ */
public Point2D getPenPosition() { public Point2D getPenPosition() {
return (Point2D) mPenPosition.clone(); return (Point2D) penPosition.clone();
} }
/** /**
@@ -233,8 +232,8 @@ class QuickDrawContext {
* @param pSize the new size * @param pSize the new size
*/ */
public void setPenSize(Dimension2D pSize) { public void setPenSize(Dimension2D pSize) {
mPenSize.setSize(pSize); penSize.setSize(pSize);
mGraphics.setStroke(getStroke(mPenSize)); graphics.setStroke(getStroke(penSize));
} }
/** /**
@@ -274,7 +273,7 @@ class QuickDrawContext {
case QuickDraw.SUB_OVER: case QuickDraw.SUB_OVER:
case QuickDraw.AD_MIN: case QuickDraw.AD_MIN:
case QuickDraw.GRAYISH_TEXT_OR: case QuickDraw.GRAYISH_TEXT_OR:
mPenMode = pPenMode; penMode = pPenMode;
break; break;
default: default:
@@ -288,7 +287,7 @@ class QuickDrawContext {
* @param pPattern the new pattern * @param pPattern the new pattern
*/ */
public void setPenPattern(final Pattern pPattern) { public void setPenPattern(final Pattern pPattern) {
mPenPattern = pPattern; penPattern = pPattern;
} }
/** /**
@@ -299,7 +298,7 @@ class QuickDrawContext {
// TODO: What about visibility? Probably not touch // TODO: What about visibility? Probably not touch
setPenPattern(QuickDraw.BLACK); setPenPattern(QuickDraw.BLACK);
setPenSize(new Dimension(1, 1)); setPenSize(new Dimension(1, 1));
mPenMode = QuickDraw.SRC_COPY; penMode = QuickDraw.SRC_COPY;
} }
/* /*
@@ -308,7 +307,7 @@ class QuickDrawContext {
*BackPixPat *BackPixPat
*/ */
public void setBackgroundPattern(Pattern pPaint) { public void setBackgroundPattern(Pattern pPaint) {
mBackground = pPaint; background = pPaint;
} }
private Composite getCompositeFor(final int pMode) { private Composite getCompositeFor(final int pMode) {
@@ -354,9 +353,9 @@ class QuickDrawContext {
* Sets up context for line drawing/painting. * Sets up context for line drawing/painting.
*/ */
protected void setupForPaint() { protected void setupForPaint() {
mGraphics.setPaint(mPenPattern); graphics.setPaint(penPattern);
mGraphics.setComposite(getCompositeFor(mPenMode)); graphics.setComposite(getCompositeFor(penMode));
//mGraphics.setStroke(getStroke(mPenSize)); //graphics.setStroke(getStroke(penSize));
} }
private Stroke getStroke(final Dimension2D pPenSize) { private Stroke getStroke(final Dimension2D pPenSize) {
@@ -373,19 +372,19 @@ class QuickDrawContext {
* @param pPattern the pattern to use for filling. * @param pPattern the pattern to use for filling.
*/ */
protected void setupForFill(final Pattern pPattern) { protected void setupForFill(final Pattern pPattern) {
mGraphics.setPaint(pPattern); graphics.setPaint(pPattern);
mGraphics.setComposite(getCompositeFor(QuickDraw.PAT_COPY)); graphics.setComposite(getCompositeFor(QuickDraw.PAT_COPY));
} }
protected void setupForErase() { protected void setupForErase() {
mGraphics.setPaint(mBackground); graphics.setPaint(background);
mGraphics.setComposite(getCompositeFor(QuickDraw.PAT_COPY)); // TODO: Check spec graphics.setComposite(getCompositeFor(QuickDraw.PAT_COPY)); // TODO: Check spec
} }
protected void setupForInvert() { protected void setupForInvert() {
// TODO: Setup for invert // TODO: Setup for invert
mGraphics.setColor(Color.BLACK); graphics.setColor(Color.BLACK);
mGraphics.setXORMode(Color.WHITE); graphics.setXORMode(Color.WHITE);
} }
/* /*
@@ -398,7 +397,7 @@ class QuickDrawContext {
*/ */
public void moveTo(final double pX, final double pY) { public void moveTo(final double pX, final double pY) {
mPenPosition.setLocation(pX, pY); penPosition.setLocation(pX, pY);
} }
public final void moveTo(final Point2D pPosition) { public final void moveTo(final Point2D pPosition) {
@@ -406,18 +405,18 @@ class QuickDrawContext {
} }
public final void move(final double pDeltaX, final double pDeltaY) { public final void move(final double pDeltaX, final double pDeltaY) {
moveTo(mPenPosition.getX() + pDeltaX, mPenPosition.getY() + pDeltaY); moveTo(penPosition.getX() + pDeltaX, penPosition.getY() + pDeltaY);
} }
public void lineTo(final double pX, final double pY) { public void lineTo(final double pX, final double pY) {
Shape line = new Line2D.Double(mPenPosition.getX(), mPenPosition.getY(), pX, pY); Shape line = new Line2D.Double(penPosition.getX(), penPosition.getY(), pX, pY);
// TODO: Add line to current shape if recording... // TODO: Add line to current shape if recording...
if (isPenVisible()) { if (isPenVisible()) {
// NOTE: Workaround for known Mac JDK bug: Paint, not frame // NOTE: Workaround for known Mac JDK bug: Paint, not frame
//mGraphics.setStroke(getStroke(mPenSize)); // Make sure we have correct stroke //graphics.setStroke(getStroke(penSize)); // Make sure we have correct stroke
paintShape(mGraphics.getStroke().createStrokedShape(line)); paintShape(graphics.getStroke().createStrokedShape(line));
} }
@@ -429,7 +428,7 @@ class QuickDrawContext {
} }
public final void line(final double pDeltaX, final double pDeltaY) { public final void line(final double pDeltaX, final double pDeltaY) {
lineTo(mPenPosition.getX() + pDeltaX, mPenPosition.getY() + pDeltaY); lineTo(penPosition.getX() + pDeltaX, penPosition.getY() + pDeltaY);
} }
/* /*
@@ -813,27 +812,27 @@ class QuickDrawContext {
// TODO: All other operations can delegate to these! :-) // TODO: All other operations can delegate to these! :-)
private void frameShape(final Shape pShape) { private void frameShape(final Shape pShape) {
setupForPaint(); setupForPaint();
mGraphics.draw(pShape); graphics.draw(pShape);
} }
private void paintShape(final Shape pShape) { private void paintShape(final Shape pShape) {
setupForPaint(); setupForPaint();
mGraphics.fill(pShape); graphics.fill(pShape);
} }
private void fillShape(final Shape pShape, final Pattern pPattern) { private void fillShape(final Shape pShape, final Pattern pPattern) {
setupForFill(pPattern); setupForFill(pPattern);
mGraphics.fill(pShape); graphics.fill(pShape);
} }
private void invertShape(final Shape pShape) { private void invertShape(final Shape pShape) {
setupForInvert(); setupForInvert();
mGraphics.fill(pShape); graphics.fill(pShape);
} }
private void eraseShape(final Shape pShape) { private void eraseShape(final Shape pShape) {
setupForErase(); setupForErase();
mGraphics.fill(pShape); graphics.fill(pShape);
} }
/* /*
@@ -862,12 +861,12 @@ class QuickDrawContext {
* @param pMaskRgn the mask region * @param pMaskRgn the mask region
*/ */
public void copyBits(BufferedImage pSrcBitmap, Rectangle pSrcRect, Rectangle pDstRect, int pMode, Shape pMaskRgn) { public void copyBits(BufferedImage pSrcBitmap, Rectangle pSrcRect, Rectangle pDstRect, int pMode, Shape pMaskRgn) {
mGraphics.setComposite(getCompositeFor(pMode)); graphics.setComposite(getCompositeFor(pMode));
if (pMaskRgn != null) { if (pMaskRgn != null) {
setClipRegion(pMaskRgn); setClipRegion(pMaskRgn);
} }
mGraphics.drawImage( graphics.drawImage(
pSrcBitmap, pSrcBitmap,
pDstRect.x, pDstRect.x,
pDstRect.y, pDstRect.y,
@@ -927,7 +926,7 @@ class QuickDrawContext {
* @param pString a Pascal string (a string of length less than or equal to 255 chars). * @param pString a Pascal string (a string of length less than or equal to 255 chars).
*/ */
public void drawString(String pString) { public void drawString(String pString) {
mGraphics.drawString(pString, (float) getPenPosition().getX(), (float) getPenPosition().getY()); graphics.drawString(pString, (float) getPenPosition().getX(), (float) getPenPosition().getY());
} }
/* /*
@@ -953,14 +952,14 @@ class QuickDrawContext {
// Color Constants // Color Constants
ÝwhiteColor =Ý30; whiteColor =30;
ÝblackColor = 33 blackColor = 33
ÝyellowColor = 69; yellowColor = 69;
magentaColor =Ý137; magentaColor =137;
ÝredColor =Ý205; redColor =205;
ÝcyanColor =Ý273; cyanColor =273;
ÝgreenColor =Ý341; greenColor =341;
ÝblueColor =Ý409; blueColor =409;
*/ */
// TODO: Simplify! Extract to upper level class // TODO: Simplify! Extract to upper level class
@@ -62,12 +62,12 @@ public class TestPICTClippingApp {
} }
private static class ImageDropHandler extends TransferHandler { private static class ImageDropHandler extends TransferHandler {
private final JLabel mLabel; private final JLabel label;
private final ExecutorService mExecutor = Executors.newSingleThreadExecutor(); private final ExecutorService executor = Executors.newSingleThreadExecutor();
public ImageDropHandler(JLabel pLabel) { public ImageDropHandler(JLabel pLabel) {
super(null); super(null);
mLabel = pLabel; label = pLabel;
} }
private DataFlavor getSupportedFlavor(final DataFlavor[] transferFlavors) { private DataFlavor getSupportedFlavor(final DataFlavor[] transferFlavors) {
@@ -126,7 +126,7 @@ public class TestPICTClippingApp {
if (readers.hasNext()) { if (readers.hasNext()) {
final ImageReader imageReader = readers.next(); final ImageReader imageReader = readers.next();
mExecutor.execute(new Runnable() { executor.execute(new Runnable() {
public void run() { public void run() {
try { try {
readAndInstallImage(stream, imageReader); readAndInstallImage(stream, imageReader);
@@ -186,7 +186,7 @@ public class TestPICTClippingApp {
System.out.print("Scaling image... "); System.out.print("Scaling image... ");
BufferedImage scaled = box(image, maxDimension); BufferedImage scaled = box(image, maxDimension);
System.out.printf("Done (%dx%d).%n", scaled.getWidth(), scaled.getHeight()); System.out.printf("Done (%dx%d).%n", scaled.getWidth(), scaled.getHeight());
mLabel.setIcon(new BufferedImageIcon(scaled)); label.setIcon(new BufferedImageIcon(scaled));
} }
}); });
} }
@@ -43,7 +43,7 @@ import java.io.InputStream;
* @version $Id: ICCProfile.java,v 1.0 May 20, 2008 6:24:10 PM haraldk Exp$ * @version $Id: ICCProfile.java,v 1.0 May 20, 2008 6:24:10 PM haraldk Exp$
*/ */
class ICCProfile extends PSDImageResource { class ICCProfile extends PSDImageResource {
private ICC_Profile mProfile; private ICC_Profile profile;
ICCProfile(final short pId, final ImageInputStream pInput) throws IOException { ICCProfile(final short pId, final ImageInputStream pInput) throws IOException {
super(pId, pInput); super(pId, pInput);
@@ -51,9 +51,9 @@ class ICCProfile extends PSDImageResource {
@Override @Override
protected void readData(ImageInputStream pInput) throws IOException { protected void readData(ImageInputStream pInput) throws IOException {
InputStream stream = IIOUtil.createStreamAdapter(pInput, mSize); InputStream stream = IIOUtil.createStreamAdapter(pInput, size);
try { try {
mProfile = ICC_Profile.getInstance(stream); profile = ICC_Profile.getInstance(stream);
} }
finally { finally {
// Make sure stream has correct position after read // Make sure stream has correct position after read
@@ -62,14 +62,14 @@ class ICCProfile extends PSDImageResource {
} }
public ICC_Profile getProfile() { public ICC_Profile getProfile() {
return mProfile; return profile;
} }
@Override @Override
public String toString() { public String toString() {
StringBuilder builder = toStringBuilder(); StringBuilder builder = toStringBuilder();
builder.append(", profile: ").append(mProfile); builder.append(", profile: ").append(profile);
builder.append("]"); builder.append("]");
return builder.toString(); return builder.toString();
@@ -41,7 +41,7 @@ import java.util.List;
* @version $Id: PSDAlphaChannelInfo.java,v 1.0 May 2, 2008 5:33:40 PM haraldk Exp$ * @version $Id: PSDAlphaChannelInfo.java,v 1.0 May 2, 2008 5:33:40 PM haraldk Exp$
*/ */
class PSDAlphaChannelInfo extends PSDImageResource { class PSDAlphaChannelInfo extends PSDImageResource {
List<String> mNames; List<String> names;
public PSDAlphaChannelInfo(short pId, final ImageInputStream pInput) throws IOException { public PSDAlphaChannelInfo(short pId, final ImageInputStream pInput) throws IOException {
super(pId, pInput); super(pId, pInput);
@@ -49,12 +49,12 @@ class PSDAlphaChannelInfo extends PSDImageResource {
@Override @Override
protected void readData(final ImageInputStream pInput) throws IOException { protected void readData(final ImageInputStream pInput) throws IOException {
mNames = new ArrayList<String>(); names = new ArrayList<String>();
long left = mSize; long left = size;
while (left > 0) { while (left > 0) {
String name = PSDUtil.readPascalString(pInput); String name = PSDUtil.readPascalString(pInput);
mNames.add(name); names.add(name);
left -= name.length() + 1; left -= name.length() + 1;
} }
} }
@@ -62,7 +62,7 @@ class PSDAlphaChannelInfo extends PSDImageResource {
@Override @Override
public String toString() { public String toString() {
StringBuilder builder = toStringBuilder(); StringBuilder builder = toStringBuilder();
builder.append(", alpha channels: ").append(mNames).append("]"); builder.append(", alpha channels: ").append(names).append("]");
return builder.toString(); return builder.toString();
} }
} }
@@ -36,8 +36,8 @@ package com.twelvemonkeys.imageio.plugins.psd;
* @version $Id: PSDChannelInfo.java,v 1.0 May 6, 2008 2:46:23 PM haraldk Exp$ * @version $Id: PSDChannelInfo.java,v 1.0 May 6, 2008 2:46:23 PM haraldk Exp$
*/ */
class PSDChannelInfo { class PSDChannelInfo {
final short mChannelId; final short channelId;
final long mLength; final long length;
// typedef struct _CLI // typedef struct _CLI
// { // {
@@ -45,16 +45,16 @@ class PSDChannelInfo {
// LONG LengthOfChannelData; /* Channel Length Info field two */ // LONG LengthOfChannelData; /* Channel Length Info field two */
// } CLI; // } CLI;
public PSDChannelInfo(short pChannelId, long pLength) { public PSDChannelInfo(short pChannelId, long pLength) {
mChannelId = pChannelId; channelId = pChannelId;
mLength = pLength; length = pLength;
} }
@Override @Override
public String toString() { public String toString() {
StringBuilder builder = new StringBuilder(getClass().getSimpleName()); StringBuilder builder = new StringBuilder(getClass().getSimpleName());
builder.append("["); builder.append("[");
builder.append("channelId: ").append(mChannelId); builder.append("channelId: ").append(channelId);
builder.append(", length: ").append(mLength); builder.append(", length: ").append(length);
builder.append("]"); builder.append("]");
return builder.toString(); return builder.toString();
} }
@@ -39,29 +39,29 @@ import java.io.IOException;
* @version $Id: PSDChannelSourceDestinationRange.java,v 1.0 May 6, 2008 5:14:13 PM haraldk Exp$ * @version $Id: PSDChannelSourceDestinationRange.java,v 1.0 May 6, 2008 5:14:13 PM haraldk Exp$
*/ */
class PSDChannelSourceDestinationRange { class PSDChannelSourceDestinationRange {
private String mChannel; private String channel;
private short mSourceBlack; private short sourceBlack;
private short mSourceWhite; private short sourceWhite;
private short mDestBlack; private short destBlack;
private short mDestWhite; private short destWhite;
public PSDChannelSourceDestinationRange(ImageInputStream pInput, String pChannel) throws IOException { public PSDChannelSourceDestinationRange(ImageInputStream pInput, String pChannel) throws IOException {
mChannel = pChannel; channel = pChannel;
mSourceBlack = pInput.readShort(); sourceBlack = pInput.readShort();
mSourceWhite = pInput.readShort(); sourceWhite = pInput.readShort();
mDestBlack = pInput.readShort(); destBlack = pInput.readShort();
mDestWhite = pInput.readShort(); destWhite = pInput.readShort();
} }
@Override @Override
public String toString() { public String toString() {
StringBuilder builder = new StringBuilder(getClass().getSimpleName()); StringBuilder builder = new StringBuilder(getClass().getSimpleName());
builder.append("[(").append(mChannel); builder.append("[(").append(channel);
builder.append("): sourceBlack: ").append(Integer.toHexString(mSourceBlack & 0xffff)); builder.append("): sourceBlack: ").append(Integer.toHexString(sourceBlack & 0xffff));
builder.append(", sourceWhite: ").append(Integer.toHexString(mSourceWhite & 0xffff)); builder.append(", sourceWhite: ").append(Integer.toHexString(sourceWhite & 0xffff));
builder.append(", destBlack: ").append(Integer.toHexString(mDestBlack & 0xffff)); builder.append(", destBlack: ").append(Integer.toHexString(destBlack & 0xffff));
builder.append(", destWhite: ").append(Integer.toHexString(mDestWhite & 0xffff)); builder.append(", destWhite: ").append(Integer.toHexString(destWhite & 0xffff));
builder.append("]"); builder.append("]");
return builder.toString(); return builder.toString();
@@ -44,8 +44,8 @@ import java.io.IOException;
* @version $Id: PSDColorData.java,v 1.0 Apr 29, 2008 5:33:01 PM haraldk Exp$ * @version $Id: PSDColorData.java,v 1.0 Apr 29, 2008 5:33:01 PM haraldk Exp$
*/ */
class PSDColorData { class PSDColorData {
final byte[] mColors; final byte[] colors;
private IndexColorModel mColorModel; private IndexColorModel colorModel;
PSDColorData(final ImageInputStream pInput) throws IOException { PSDColorData(final ImageInputStream pInput) throws IOException {
int length = pInput.readInt(); int length = pInput.readInt();
@@ -57,19 +57,19 @@ class PSDColorData {
} }
// NOTE: Spec says length may only be 768 bytes (256 RGB triplets) // NOTE: Spec says length may only be 768 bytes (256 RGB triplets)
mColors = new byte[length]; colors = new byte[length];
pInput.readFully(mColors); pInput.readFully(colors);
// NOTE: Could be a padding byte here, if not even.. // NOTE: Could be a padding byte here, if not even..
} }
IndexColorModel getIndexColorModel() { IndexColorModel getIndexColorModel() {
if (mColorModel == null) { if (colorModel == null) {
int[] rgb = toInterleavedRGB(mColors); int[] rgb = toInterleavedRGB(colors);
mColorModel = new InverseColorMapIndexColorModel(8, rgb.length, rgb, 0, false, -1, DataBuffer.TYPE_BYTE); colorModel = new InverseColorMapIndexColorModel(8, rgb.length, rgb, 0, false, -1, DataBuffer.TYPE_BYTE);
} }
return mColorModel; return colorModel;
} }
private static int[] toInterleavedRGB(final byte[] pColors) { private static int[] toInterleavedRGB(final byte[] pColors) {
@@ -65,10 +65,10 @@ class PSDDisplayInfo extends PSDImageResource {
// BYTE Padding; /* Always zero */ // BYTE Padding; /* Always zero */
//} DISPLAYINFO; //} DISPLAYINFO;
int mColorSpace; int colorSpace;
short[] mColors; short[] colors;
short mOpacity; short opacity;
byte mKind; byte kind;
PSDDisplayInfo(final short pId, final ImageInputStream pInput) throws IOException { PSDDisplayInfo(final short pId, final ImageInputStream pInput) throws IOException {
super(pId, pInput); super(pId, pInput);
@@ -76,46 +76,46 @@ class PSDDisplayInfo extends PSDImageResource {
@Override @Override
protected void readData(ImageInputStream pInput) throws IOException { protected void readData(ImageInputStream pInput) throws IOException {
if (mSize % 14 != 0) { if (size % 14 != 0) {
throw new IIOException("Display info length expected to be mod 14: " + mSize); throw new IIOException("Display info length expected to be mod 14: " + size);
} }
// long left = mSize; // long left = size;
// while (left > 0) { // while (left > 0) {
mColorSpace = pInput.readShort(); colorSpace = pInput.readShort();
// Color[4]...? // Color[4]...?
mColors = new short[4]; colors = new short[4];
mColors[0] = pInput.readShort(); colors[0] = pInput.readShort();
mColors[1] = pInput.readShort(); colors[1] = pInput.readShort();
mColors[2] = pInput.readShort(); colors[2] = pInput.readShort();
mColors[3] = pInput.readShort(); colors[3] = pInput.readShort();
mOpacity = pInput.readShort(); opacity = pInput.readShort();
mKind = pInput.readByte(); kind = pInput.readByte();
pInput.readByte(); // Pad pInput.readByte(); // Pad
// left -= 14; // left -= 14;
// } // }
pInput.skipBytes(mSize - 14); pInput.skipBytes(size - 14);
} }
@Override @Override
public String toString() { public String toString() {
StringBuilder builder = toStringBuilder(); StringBuilder builder = toStringBuilder();
builder.append(", ColorSpace: ").append(mColorSpace); builder.append(", ColorSpace: ").append(colorSpace);
builder.append(", Colors: {"); builder.append(", Colors: {");
builder.append(mColors[0]); builder.append(colors[0]);
builder.append(", "); builder.append(", ");
builder.append(mColors[1]); builder.append(colors[1]);
builder.append(", "); builder.append(", ");
builder.append(mColors[2]); builder.append(colors[2]);
builder.append(", "); builder.append(", ");
builder.append(mColors[3]); builder.append(colors[3]);
builder.append("}, Opacity: ").append(mOpacity); builder.append("}, Opacity: ").append(opacity);
builder.append(", Kind: ").append(kind(mKind)); builder.append(", Kind: ").append(kind(kind));
builder.append("]"); builder.append("]");
@@ -18,7 +18,7 @@ import java.io.IOException;
* @see <a href="http://partners.adobe.com/public/developer/tiff/index.html">Adobe TIFF developer resources</a> * @see <a href="http://partners.adobe.com/public/developer/tiff/index.html">Adobe TIFF developer resources</a>
*/ */
final class PSDEXIF1Data extends PSDImageResource { final class PSDEXIF1Data extends PSDImageResource {
protected Directory mDirectory; protected Directory directory;
PSDEXIF1Data(final short pId, final ImageInputStream pInput) throws IOException { PSDEXIF1Data(final short pId, final ImageInputStream pInput) throws IOException {
super(pId, pInput); super(pId, pInput);
@@ -28,13 +28,13 @@ 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: Instead, read the byte data, store for later parsing (or better yet, store offset, and read on request) // TODO: Instead, read the byte data, store for later parsing (or better yet, store offset, and read on request)
mDirectory = new EXIFReader().read(pInput); directory = new EXIFReader().read(pInput);
} }
@Override @Override
public String toString() { public String toString() {
StringBuilder builder = toStringBuilder(); StringBuilder builder = toStringBuilder();
builder.append(", ").append(mDirectory); builder.append(", ").append(directory);
builder.append("]"); builder.append("]");
return builder.toString(); return builder.toString();
@@ -39,25 +39,25 @@ import java.io.IOException;
* @version $Id: PSDGlobalLayerMask.java,v 1.0 May 8, 2008 5:33:48 PM haraldk Exp$ * @version $Id: PSDGlobalLayerMask.java,v 1.0 May 8, 2008 5:33:48 PM haraldk Exp$
*/ */
class PSDGlobalLayerMask { class PSDGlobalLayerMask {
final int mColorSpace; final int colorSpace;
final int mColor1; final int color1;
final int mColor2; final int color2;
final int mColor3; final int color3;
final int mColor4; final int color4;
final int mOpacity; final int opacity;
final int mKind; final int kind;
PSDGlobalLayerMask(final ImageInputStream pInput) throws IOException { PSDGlobalLayerMask(final ImageInputStream pInput) throws IOException {
mColorSpace = pInput.readUnsignedShort(); // Undocumented colorSpace = pInput.readUnsignedShort(); // Undocumented
mColor1 = pInput.readUnsignedShort(); color1 = pInput.readUnsignedShort();
mColor2 = pInput.readUnsignedShort(); color2 = pInput.readUnsignedShort();
mColor3 = pInput.readUnsignedShort(); color3 = pInput.readUnsignedShort();
mColor4 = pInput.readUnsignedShort(); color4 = pInput.readUnsignedShort();
mOpacity = pInput.readUnsignedShort(); // 0-100 opacity = pInput.readUnsignedShort(); // 0-100
mKind = pInput.readUnsignedByte(); // 0: Selected (ie inverted), 1: Color protected, 128: Use value stored per layer kind = pInput.readUnsignedByte(); // 0: Selected (ie inverted), 1: Color protected, 128: Use value stored per layer
// TODO: Variable: Filler zeros // TODO: Variable: Filler zeros
@@ -68,13 +68,13 @@ class PSDGlobalLayerMask {
public String toString() { public String toString() {
StringBuilder builder = new StringBuilder(getClass().getSimpleName()); StringBuilder builder = new StringBuilder(getClass().getSimpleName());
builder.append("["); builder.append("[");
builder.append("color space: 0x").append(Integer.toHexString(mColorSpace)); builder.append("color space: 0x").append(Integer.toHexString(colorSpace));
builder.append(", colors: [0x").append(Integer.toHexString(mColor1)); builder.append(", colors: [0x").append(Integer.toHexString(color1));
builder.append(", 0x").append(Integer.toHexString(mColor2)); builder.append(", 0x").append(Integer.toHexString(color2));
builder.append(", 0x").append(Integer.toHexString(mColor3)); builder.append(", 0x").append(Integer.toHexString(color3));
builder.append(", 0x").append(Integer.toHexString(mColor4)); builder.append(", 0x").append(Integer.toHexString(color4));
builder.append("], opacity: ").append(mOpacity); builder.append("], opacity: ").append(opacity);
builder.append(", kind: ").append(mKind); builder.append(", kind: ").append(kind);
builder.append("]"); builder.append("]");
return builder.toString(); return builder.toString();
} }
@@ -25,12 +25,12 @@ final class PSDGridAndGuideInfo extends PSDImageResource {
// gchar fDirection; /* Guide orientation */ // gchar fDirection; /* Guide orientation */
//} GuideResource; //} GuideResource;
int mVersion; int version;
int mGridCycleVertical; int gridCycleVertical;
int mGridCycleHorizontal; int gridCycleHorizontal;
int mGuideCount; int guideCount;
GuideResource[] mGuides; GuideResource[] guides;
PSDGridAndGuideInfo(final short pId, final ImageInputStream pInput) throws IOException { PSDGridAndGuideInfo(final short pId, final ImageInputStream pInput) throws IOException {
super(pId, pInput); super(pId, pInput);
@@ -38,21 +38,21 @@ final class PSDGridAndGuideInfo extends PSDImageResource {
@Override @Override
protected void readData(final ImageInputStream pInput) throws IOException { protected void readData(final ImageInputStream pInput) throws IOException {
mVersion = pInput.readInt(); version = pInput.readInt();
mGridCycleVertical = pInput.readInt(); gridCycleVertical = pInput.readInt();
mGridCycleHorizontal = pInput.readInt(); gridCycleHorizontal = pInput.readInt();
mGuideCount = pInput.readInt(); guideCount = pInput.readInt();
mGuides = new GuideResource[mGuideCount]; guides = new GuideResource[guideCount];
for (GuideResource guide : mGuides) { for (GuideResource guide : guides) {
guide.mLocation = pInput.readInt(); guide.location = pInput.readInt();
guide.mDirection = pInput.readByte(); guide.direction = pInput.readByte();
} }
} }
static class GuideResource { static class GuideResource {
int mLocation; int location;
byte mDirection; // 0: vertical, 1: horizontal byte direction; // 0: vertical, 1: horizontal
} }
} }
@@ -28,9 +28,6 @@
package com.twelvemonkeys.imageio.plugins.psd; package com.twelvemonkeys.imageio.plugins.psd;
import org.w3c.dom.Node;
import javax.imageio.metadata.IIOMetadataNode;
import javax.imageio.stream.ImageInputStream; import javax.imageio.stream.ImageInputStream;
import javax.imageio.IIOException; import javax.imageio.IIOException;
import java.io.IOException; import java.io.IOException;
@@ -58,11 +55,11 @@ class PSDHeader {
// WORD Mode; /* Color mode */ // WORD Mode; /* Color mode */
// } PSD_HEADER; // } PSD_HEADER;
final short mChannels; final short channels;
final int mWidth; final int width;
final int mHeight; final int height;
final short mBits; final short bits;
final short mMode; final short mode;
PSDHeader(final ImageInputStream pInput) throws IOException { PSDHeader(final ImageInputStream pInput) throws IOException {
int signature = pInput.readInt(); int signature = pInput.readInt();
@@ -84,27 +81,27 @@ class PSDHeader {
byte[] reserved = new byte[6]; byte[] reserved = new byte[6];
pInput.readFully(reserved); pInput.readFully(reserved);
mChannels = pInput.readShort(); channels = pInput.readShort();
mHeight = pInput.readInt(); // Rows height = pInput.readInt(); // Rows
mWidth = pInput.readInt(); // Columns width = pInput.readInt(); // Columns
mBits = pInput.readShort(); bits = pInput.readShort();
mMode = pInput.readShort(); mode = pInput.readShort();
} }
@Override @Override
public String toString() { public String toString() {
StringBuilder builder = new StringBuilder(getClass().getSimpleName()); StringBuilder builder = new StringBuilder(getClass().getSimpleName());
builder.append("[Channels: "); builder.append("[Channels: ");
builder.append(mChannels); builder.append(channels);
builder.append(", width: "); builder.append(", width: ");
builder.append(mWidth); builder.append(width);
builder.append(", height: "); builder.append(", height: ");
builder.append(mHeight); builder.append(height);
builder.append(", depth: "); builder.append(", depth: ");
builder.append(mBits); builder.append(bits);
builder.append(", mode: "); builder.append(", mode: ");
builder.append(mMode); builder.append(mode);
switch (mMode) { switch (mode) {
case PSD.COLOR_MODE_MONOCHROME: case PSD.COLOR_MODE_MONOCHROME:
builder.append(" (Monochrome)"); builder.append(" (Monochrome)");
break; break;
@@ -14,7 +14,7 @@ import java.io.IOException;
* @version $Id: PSDIPTCData.java,v 1.0 Nov 7, 2009 9:52:14 PM haraldk Exp$ * @version $Id: PSDIPTCData.java,v 1.0 Nov 7, 2009 9:52:14 PM haraldk Exp$
*/ */
final class PSDIPTCData extends PSDImageResource { final class PSDIPTCData extends PSDImageResource {
Directory mDirectory; Directory directory;
PSDIPTCData(final short pId, final ImageInputStream pInput) throws IOException { PSDIPTCData(final short pId, final ImageInputStream pInput) throws IOException {
super(pId, pInput); super(pId, pInput);
@@ -23,13 +23,13 @@ final class PSDIPTCData extends PSDImageResource {
@Override @Override
protected void readData(final ImageInputStream pInput) throws IOException { protected void readData(final ImageInputStream pInput) throws IOException {
// Read IPTC directory // Read IPTC directory
mDirectory = new IPTCReader().read(pInput); directory = new IPTCReader().read(pInput);
} }
@Override @Override
public String toString() { public String toString() {
StringBuilder builder = toStringBuilder(); StringBuilder builder = toStringBuilder();
builder.append(", ").append(mDirectory); builder.append(", ").append(directory);
builder.append("]"); builder.append("]");
return builder.toString(); return builder.toString();
@@ -72,36 +72,30 @@ import java.util.List;
// See http://www.codeproject.com/KB/graphics/PSDParser.aspx // See http://www.codeproject.com/KB/graphics/PSDParser.aspx
// See http://www.adobeforums.com/webx?14@@.3bc381dc/0 // See http://www.adobeforums.com/webx?14@@.3bc381dc/0
public class PSDImageReader extends ImageReaderBase { public class PSDImageReader extends ImageReaderBase {
private PSDHeader mHeader; private PSDHeader header;
// private PSDColorData mColorData; private ICC_ColorSpace colorSpace;
// private List<PSDImageResource> mImageResources; protected PSDMetadata metadata;
// private PSDGlobalLayerMask mGlobalLayerMask;
// private List<PSDLayerInfo> mLayerInfo;
private ICC_ColorSpace mColorSpace;
protected PSDMetadata mMetadata;
protected PSDImageReader(final ImageReaderSpi pOriginatingProvider) { protected PSDImageReader(final ImageReaderSpi pOriginatingProvider) {
super(pOriginatingProvider); super(pOriginatingProvider);
} }
protected void resetMembers() { protected void resetMembers() {
mHeader = null; header = null;
// mColorData = null; metadata = null;
// mImageResources = null; colorSpace = null;
mMetadata = null;
mColorSpace = null;
} }
public int getWidth(final int pIndex) throws IOException { public int getWidth(final int pIndex) throws IOException {
checkBounds(pIndex); checkBounds(pIndex);
readHeader(); readHeader();
return mHeader.mWidth; return header.width;
} }
public int getHeight(final int pIndex) throws IOException { public int getHeight(final int pIndex) throws IOException {
checkBounds(pIndex); checkBounds(pIndex);
readHeader(); readHeader();
return mHeader.mHeight; return header.height;
} }
@Override @Override
@@ -115,39 +109,39 @@ public class PSDImageReader extends ImageReaderBase {
ColorSpace cs; ColorSpace cs;
switch (mHeader.mMode) { switch (header.mode) {
case PSD.COLOR_MODE_MONOCHROME: case PSD.COLOR_MODE_MONOCHROME:
if (mHeader.mChannels == 1 && mHeader.mBits == 1) { if (header.channels == 1 && header.bits == 1) {
return ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_BYTE_BINARY); return ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_BYTE_BINARY);
} }
throw new IIOException( throw new IIOException(
String.format("Unsupported channel count/bit depth for Monochrome PSD: %d channels/%d bits", mHeader.mChannels, mHeader.mBits) String.format("Unsupported channel count/bit depth for Monochrome PSD: %d channels/%d bits", header.channels, header.bits)
); );
case PSD.COLOR_MODE_INDEXED: case PSD.COLOR_MODE_INDEXED:
// TODO: 16 bit indexed?! Does it exist? // TODO: 16 bit indexed?! Does it exist?
if (mHeader.mChannels == 1 && mHeader.mBits == 8) { if (header.channels == 1 && header.bits == 8) {
return IndexedImageTypeSpecifier.createFromIndexColorModel(mMetadata.mColorData.getIndexColorModel()); return IndexedImageTypeSpecifier.createFromIndexColorModel(metadata.colorData.getIndexColorModel());
} }
throw new IIOException( throw new IIOException(
String.format("Unsupported channel count/bit depth for Indexed Color PSD: %d channels/%d bits", mHeader.mChannels, mHeader.mBits) String.format("Unsupported channel count/bit depth for Indexed Color PSD: %d channels/%d bits", header.channels, header.bits)
); );
case PSD.COLOR_MODE_DUOTONE: case PSD.COLOR_MODE_DUOTONE:
// NOTE: Duotone (whatever that is) should be treated as gray scale // NOTE: Duotone (whatever that is) should be treated as gray scale
// Fall-through // Fall-through
case PSD.COLOR_MODE_GRAYSCALE: case PSD.COLOR_MODE_GRAYSCALE:
if (mHeader.mChannels == 1 && mHeader.mBits == 8) { if (header.channels == 1 && header.bits == 8) {
return ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_BYTE_GRAY); return ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_BYTE_GRAY);
} }
else if (mHeader.mChannels == 1 && mHeader.mBits == 16) { else if (header.channels == 1 && header.bits == 16) {
return ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_USHORT_GRAY); return ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_USHORT_GRAY);
} }
throw new IIOException( throw new IIOException(
String.format("Unsupported channel count/bit depth for Gray Scale PSD: %d channels/%d bits", mHeader.mChannels, mHeader.mBits) String.format("Unsupported channel count/bit depth for Gray Scale PSD: %d channels/%d bits", header.channels, header.bits)
); );
case PSD.COLOR_MODE_RGB: case PSD.COLOR_MODE_RGB:
@@ -157,21 +151,21 @@ public class PSDImageReader extends ImageReaderBase {
cs = ColorSpace.getInstance(ColorSpace.CS_sRGB); cs = ColorSpace.getInstance(ColorSpace.CS_sRGB);
} }
if (mHeader.mChannels == 3 && mHeader.mBits == 8) { if (header.channels == 3 && header.bits == 8) {
return ImageTypeSpecifier.createBanded(cs, new int[] {0, 1, 2}, new int[] {0, 0, 0}, DataBuffer.TYPE_BYTE, false, false); return ImageTypeSpecifier.createBanded(cs, new int[] {0, 1, 2}, new int[] {0, 0, 0}, DataBuffer.TYPE_BYTE, false, false);
} }
else if (mHeader.mChannels >= 4 && mHeader.mBits == 8) { else if (header.channels >= 4 && header.bits == 8) {
return ImageTypeSpecifier.createBanded(cs, new int[] {0, 1, 2, 3}, new int[] {0, 0, 0, 0}, DataBuffer.TYPE_BYTE, true, false); return ImageTypeSpecifier.createBanded(cs, new int[] {0, 1, 2, 3}, new int[] {0, 0, 0, 0}, DataBuffer.TYPE_BYTE, true, false);
} }
else if (mHeader.mChannels == 3 && mHeader.mBits == 16) { else if (header.channels == 3 && header.bits == 16) {
return ImageTypeSpecifier.createBanded(cs, new int[] {0, 1, 2}, new int[] {0, 0, 0}, DataBuffer.TYPE_USHORT, false, false); return ImageTypeSpecifier.createBanded(cs, new int[] {0, 1, 2}, new int[] {0, 0, 0}, DataBuffer.TYPE_USHORT, false, false);
} }
else if (mHeader.mChannels >= 4 && mHeader.mBits == 16) { else if (header.channels >= 4 && header.bits == 16) {
return ImageTypeSpecifier.createBanded(cs, new int[] {0, 1, 2, 3}, new int[] {0, 0, 0, 0}, DataBuffer.TYPE_USHORT, true, false); return ImageTypeSpecifier.createBanded(cs, new int[] {0, 1, 2, 3}, new int[] {0, 0, 0, 0}, DataBuffer.TYPE_USHORT, true, false);
} }
throw new IIOException( throw new IIOException(
String.format("Unsupported channel count/bit depth for RGB PSD: %d channels/%d bits", mHeader.mChannels, mHeader.mBits) String.format("Unsupported channel count/bit depth for RGB PSD: %d channels/%d bits", header.channels, header.bits)
); );
case PSD.COLOR_MODE_CMYK: case PSD.COLOR_MODE_CMYK:
@@ -180,21 +174,21 @@ public class PSDImageReader extends ImageReaderBase {
cs = ColorSpaces.getColorSpace(ColorSpaces.CS_GENERIC_CMYK); cs = ColorSpaces.getColorSpace(ColorSpaces.CS_GENERIC_CMYK);
} }
if (mHeader.mChannels == 4 && mHeader.mBits == 8) { if (header.channels == 4 && header.bits == 8) {
return ImageTypeSpecifier.createBanded(cs, new int[] {0, 1, 2, 3}, new int[] {0, 0, 0, 0}, DataBuffer.TYPE_BYTE, false, false); return ImageTypeSpecifier.createBanded(cs, new int[] {0, 1, 2, 3}, new int[] {0, 0, 0, 0}, DataBuffer.TYPE_BYTE, false, false);
} }
else if (mHeader.mChannels == 5 && mHeader.mBits == 8) { else if (header.channels == 5 && header.bits == 8) {
return ImageTypeSpecifier.createBanded(cs, new int[] {0, 1, 2, 3, 4}, new int[] {0, 0, 0, 0, 0}, DataBuffer.TYPE_BYTE, true, false); return ImageTypeSpecifier.createBanded(cs, new int[] {0, 1, 2, 3, 4}, new int[] {0, 0, 0, 0, 0}, DataBuffer.TYPE_BYTE, true, false);
} }
else if (mHeader.mChannels == 4 && mHeader.mBits == 16) { else if (header.channels == 4 && header.bits == 16) {
return ImageTypeSpecifier.createBanded(cs, new int[] {0, 1, 2, 3}, new int[] {0, 0, 0, 0}, DataBuffer.TYPE_USHORT, false, false); return ImageTypeSpecifier.createBanded(cs, new int[] {0, 1, 2, 3}, new int[] {0, 0, 0, 0}, DataBuffer.TYPE_USHORT, false, false);
} }
else if (mHeader.mChannels == 5 && mHeader.mBits == 16) { else if (header.channels == 5 && header.bits == 16) {
return ImageTypeSpecifier.createBanded(cs, new int[] {0, 1, 2, 3, 4}, new int[] {0, 0, 0, 0, 0}, DataBuffer.TYPE_USHORT, true, false); return ImageTypeSpecifier.createBanded(cs, new int[] {0, 1, 2, 3, 4}, new int[] {0, 0, 0, 0, 0}, DataBuffer.TYPE_USHORT, true, false);
} }
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", header.channels, header.bits)
); );
case PSD.COLOR_MODE_MULTICHANNEL: case PSD.COLOR_MODE_MULTICHANNEL:
@@ -204,7 +198,7 @@ public class PSDImageReader extends ImageReaderBase {
// TODO: If there's a color profile embedded, it should be easy, otherwise we're out of luck... // TODO: If there's a color profile embedded, it should be easy, otherwise we're out of luck...
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)", header.mode, header.channels, header.bits)
); );
} }
} }
@@ -219,10 +213,10 @@ public class PSDImageReader extends ImageReaderBase {
ColorSpace cs = rawType.getColorModel().getColorSpace(); ColorSpace cs = rawType.getColorModel().getColorSpace();
List<ImageTypeSpecifier> types = new ArrayList<ImageTypeSpecifier>(); List<ImageTypeSpecifier> types = new ArrayList<ImageTypeSpecifier>();
switch (mHeader.mMode) { switch (header.mode) {
case PSD.COLOR_MODE_RGB: case PSD.COLOR_MODE_RGB:
// Prefer interleaved versions as they are much faster to display // Prefer interleaved versions as they are much faster to display
if (mHeader.mChannels == 3 && mHeader.mBits == 8) { if (header.channels == 3 && header.bits == 8) {
// TODO: ColorConvertOp to CS_sRGB // TODO: ColorConvertOp to CS_sRGB
// TODO: Integer raster // TODO: Integer raster
// types.add(ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.INT_RGB)); // types.add(ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.INT_RGB));
@@ -233,7 +227,7 @@ public class PSDImageReader extends ImageReaderBase {
types.add(ImageTypeSpecifier.createInterleaved(cs, new int[] {2, 1, 0}, DataBuffer.TYPE_BYTE, false, false)); types.add(ImageTypeSpecifier.createInterleaved(cs, new int[] {2, 1, 0}, DataBuffer.TYPE_BYTE, false, false));
} }
} }
else if (mHeader.mChannels >= 4 && mHeader.mBits == 8) { else if (header.channels >= 4 && header.bits == 8) {
// TODO: ColorConvertOp to CS_sRGB // TODO: ColorConvertOp to CS_sRGB
// TODO: Integer raster // TODO: Integer raster
// types.add(ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.INT_ARGB)); // types.add(ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.INT_ARGB));
@@ -244,10 +238,10 @@ public class PSDImageReader extends ImageReaderBase {
types.add(ImageTypeSpecifier.createInterleaved(cs, new int[] {3, 2, 1, 0}, DataBuffer.TYPE_BYTE, true, false)); types.add(ImageTypeSpecifier.createInterleaved(cs, new int[] {3, 2, 1, 0}, DataBuffer.TYPE_BYTE, true, false));
} }
} }
else if (mHeader.mChannels == 3 && mHeader.mBits == 16) { else if (header.channels == 3 && header.bits == 16) {
types.add(ImageTypeSpecifier.createInterleaved(cs, new int[] {2, 1, 0}, DataBuffer.TYPE_USHORT, false, false)); types.add(ImageTypeSpecifier.createInterleaved(cs, new int[] {2, 1, 0}, DataBuffer.TYPE_USHORT, false, false));
} }
else if (mHeader.mChannels >= 4 && mHeader.mBits == 16) { else if (header.channels >= 4 && header.bits == 16) {
types.add(ImageTypeSpecifier.createInterleaved(cs, new int[] {3, 2, 1, 0}, DataBuffer.TYPE_USHORT, true, false)); types.add(ImageTypeSpecifier.createInterleaved(cs, new int[] {3, 2, 1, 0}, DataBuffer.TYPE_USHORT, true, false));
} }
break; break;
@@ -258,16 +252,16 @@ public class PSDImageReader extends ImageReaderBase {
// as Java2D is extremely slow displaying custom images. // as Java2D is extremely slow displaying custom images.
// Converting to RGB is also correct behaviour, according to the docs. // Converting to RGB is also correct behaviour, according to the docs.
// Doing this, will require rewriting the image reading, as the raw image data is channelled, not interleaved :-/ // Doing this, will require rewriting the image reading, as the raw image data is channelled, not interleaved :-/
if (mHeader.mChannels == 4 && mHeader.mBits == 8) { if (header.channels == 4 && header.bits == 8) {
types.add(ImageTypeSpecifier.createInterleaved(cs, new int[] {3, 2, 1, 0}, DataBuffer.TYPE_BYTE, false, false)); types.add(ImageTypeSpecifier.createInterleaved(cs, new int[] {3, 2, 1, 0}, DataBuffer.TYPE_BYTE, false, false));
} }
else if (mHeader.mChannels == 5 && mHeader.mBits == 8) { else if (header.channels == 5 && header.bits == 8) {
types.add(ImageTypeSpecifier.createInterleaved(cs, new int[] {4, 3, 2, 1, 0}, DataBuffer.TYPE_BYTE, true, false)); types.add(ImageTypeSpecifier.createInterleaved(cs, new int[] {4, 3, 2, 1, 0}, DataBuffer.TYPE_BYTE, true, false));
} }
else if (mHeader.mChannels == 4 && mHeader.mBits == 16) { else if (header.channels == 4 && header.bits == 16) {
types.add(ImageTypeSpecifier.createInterleaved(cs, new int[]{3, 2, 1, 0}, DataBuffer.TYPE_USHORT, false, false)); types.add(ImageTypeSpecifier.createInterleaved(cs, new int[]{3, 2, 1, 0}, DataBuffer.TYPE_USHORT, false, false));
} }
else if (mHeader.mChannels == 5 && mHeader.mBits == 16) { else if (header.channels == 5 && header.bits == 16) {
types.add(ImageTypeSpecifier.createInterleaved(cs, new int[] {4, 3, 2, 1, 0}, DataBuffer.TYPE_USHORT, true, false)); types.add(ImageTypeSpecifier.createInterleaved(cs, new int[] {4, 3, 2, 1, 0}, DataBuffer.TYPE_USHORT, true, false));
} }
break; break;
@@ -286,19 +280,19 @@ public class PSDImageReader extends ImageReaderBase {
// TODO: Skip this, requires storing some stream offsets // TODO: Skip this, requires storing some stream offsets
readLayerAndMaskInfo(false); readLayerAndMaskInfo(false);
if (mColorSpace == null) { if (colorSpace == null) {
ICC_Profile profile = null; ICC_Profile profile = null;
for (PSDImageResource resource : mMetadata.mImageResources) { for (PSDImageResource resource : metadata.imageResources) {
if (resource instanceof ICCProfile) { if (resource instanceof ICCProfile) {
profile = ((ICCProfile) resource).getProfile(); profile = ((ICCProfile) resource).getProfile();
break; break;
} }
} }
mColorSpace = profile == null ? null : ColorSpaces.createColorSpace(profile); colorSpace = profile == null ? null : ColorSpaces.createColorSpace(profile);
} }
return mColorSpace; return colorSpace;
} }
public BufferedImage read(final int pIndex, final ImageReadParam pParam) throws IOException { public BufferedImage read(final int pIndex, final ImageReadParam pParam) throws IOException {
@@ -309,13 +303,13 @@ public class PSDImageReader extends ImageReaderBase {
readImageResources(false); readImageResources(false);
readLayerAndMaskInfo(false); readLayerAndMaskInfo(false);
BufferedImage image = getDestination(pParam, getImageTypes(pIndex), mHeader.mWidth, mHeader.mHeight); BufferedImage image = getDestination(pParam, getImageTypes(pIndex), header.width, header.height);
ImageTypeSpecifier rawType = getRawImageType(pIndex); ImageTypeSpecifier rawType = getRawImageType(pIndex);
checkReadParamBandSettings(pParam, rawType.getNumBands(), image.getSampleModel().getNumBands()); checkReadParamBandSettings(pParam, rawType.getNumBands(), image.getSampleModel().getNumBands());
final Rectangle source = new Rectangle(); final Rectangle source = new Rectangle();
final Rectangle dest = new Rectangle(); final Rectangle dest = new Rectangle();
computeRegions(pParam, mHeader.mWidth, mHeader.mHeight, image, source, dest); computeRegions(pParam, header.width, header.height, image, source, dest);
/* /*
NOTE: It seems safe to just leave this out for now. The only thing we need is to support sub sampling. NOTE: It seems safe to just leave this out for now. The only thing we need is to support sub sampling.
@@ -360,14 +354,14 @@ public class PSDImageReader extends ImageReaderBase {
int[] byteCounts = null; int[] byteCounts = null;
int compression = imageInput.readShort(); int compression = imageInput.readShort();
// TODO: Need to make sure compression is set in metadata, even without reading the image data! // TODO: Need to make sure compression is set in metadata, even without reading the image data!
mMetadata.mCompression = compression; metadata.compression = compression;
switch (compression) { switch (compression) {
case PSD.COMPRESSION_NONE: case PSD.COMPRESSION_NONE:
break; break;
case PSD.COMPRESSION_RLE: case PSD.COMPRESSION_RLE:
// NOTE: Byte counts will allow us to easily skip rows before AOI // NOTE: Byte counts will allow us to easily skip rows before AOI
byteCounts = new int[mHeader.mChannels * mHeader.mHeight]; byteCounts = new int[header.channels * header.height];
for (int i = 0; i < byteCounts.length; i++) { for (int i = 0; i < byteCounts.length; i++) {
byteCounts[i] = imageInput.readUnsignedShort(); byteCounts[i] = imageInput.readUnsignedShort();
} }
@@ -410,7 +404,7 @@ public class PSDImageReader extends ImageReaderBase {
final ColorModel destCM = pImage.getColorModel(); final ColorModel destCM = pImage.getColorModel();
// TODO: This raster is 3-5 times longer than needed, depending on number of channels... // TODO: This raster is 3-5 times longer than needed, depending on number of channels...
final WritableRaster rowRaster = pSourceCM.createCompatibleWritableRaster(mHeader.mWidth, 1); final WritableRaster rowRaster = pSourceCM.createCompatibleWritableRaster(header.width, 1);
final int channels = rowRaster.getNumBands(); final int channels = rowRaster.getNumBands();
final boolean banded = raster.getDataBuffer().getNumBanks() > 1; final boolean banded = raster.getDataBuffer().getNumBanks() > 1;
@@ -419,21 +413,21 @@ public class PSDImageReader extends ImageReaderBase {
for (int c = 0; c < channels; c++) { for (int c = 0; c < channels; c++) {
int bandOffset = banded ? 0 : interleavedBands - 1 - c; int bandOffset = banded ? 0 : interleavedBands - 1 - c;
switch (mHeader.mBits) { switch (header.bits) {
case 1: case 1:
byte[] row1 = ((DataBufferByte) rowRaster.getDataBuffer()).getData(); byte[] row1 = ((DataBufferByte) rowRaster.getDataBuffer()).getData();
read1bitChannel(c, mHeader.mChannels, raster.getDataBuffer(), interleavedBands, bandOffset, pSourceCM, row1, pSource, pDest, pXSub, pYSub, mHeader.mWidth, mHeader.mHeight, pByteCounts, pCompression == PSD.COMPRESSION_RLE); read1bitChannel(c, header.channels, raster.getDataBuffer(), interleavedBands, bandOffset, pSourceCM, row1, pSource, pDest, pXSub, pYSub, header.width, header.height, pByteCounts, pCompression == PSD.COMPRESSION_RLE);
break; break;
case 8: case 8:
byte[] row8 = ((DataBufferByte) rowRaster.getDataBuffer()).getData(); byte[] row8 = ((DataBufferByte) rowRaster.getDataBuffer()).getData();
read8bitChannel(c, mHeader.mChannels, raster.getDataBuffer(), interleavedBands, bandOffset, pSourceCM, row8, pSource, pDest, pXSub, pYSub, mHeader.mWidth, mHeader.mHeight, pByteCounts, c * mHeader.mHeight, pCompression == PSD.COMPRESSION_RLE); read8bitChannel(c, header.channels, raster.getDataBuffer(), interleavedBands, bandOffset, pSourceCM, row8, pSource, pDest, pXSub, pYSub, header.width, header.height, pByteCounts, c * header.height, pCompression == PSD.COMPRESSION_RLE);
break; break;
case 16: case 16:
short[] row16 = ((DataBufferUShort) rowRaster.getDataBuffer()).getData(); short[] row16 = ((DataBufferUShort) rowRaster.getDataBuffer()).getData();
read16bitChannel(c, mHeader.mChannels, raster.getDataBuffer(), interleavedBands, bandOffset, pSourceCM, row16, pSource, pDest, pXSub, pYSub, mHeader.mWidth, mHeader.mHeight, pByteCounts, c * mHeader.mHeight, pCompression == PSD.COMPRESSION_RLE); read16bitChannel(c, header.channels, raster.getDataBuffer(), interleavedBands, bandOffset, pSourceCM, row16, pSource, pDest, pXSub, pYSub, header.width, header.height, pByteCounts, c * header.height, pCompression == PSD.COMPRESSION_RLE);
break; break;
default: default:
throw new IIOException(String.format("Unknown PSD bit depth: %s", mHeader.mBits)); throw new IIOException(String.format("Unknown PSD bit depth: %s", header.bits));
} }
if (abortRequested()) { if (abortRequested()) {
@@ -441,7 +435,7 @@ public class PSDImageReader extends ImageReaderBase {
} }
} }
if (mHeader.mBits == 8) { if (header.bits == 8) {
// Compose out the background of the semi-transparent pixels, as PS somehow has the background composed in // Compose out the background of the semi-transparent pixels, as PS somehow has the background composed in
decomposeAlpha(destCM, raster.getDataBuffer(), pDest.width, pDest.height, raster.getNumBands()); decomposeAlpha(destCM, raster.getDataBuffer(), pDest.width, pDest.height, raster.getNumBands());
} }
@@ -713,11 +707,11 @@ public class PSDImageReader extends ImageReaderBase {
private void readHeader() throws IOException { private void readHeader() throws IOException {
assertInput(); assertInput();
if (mHeader == null) { if (header == null) {
mHeader = new PSDHeader(imageInput); header = new PSDHeader(imageInput);
mMetadata = new PSDMetadata(); metadata = new PSDMetadata();
mMetadata.mHeader = mHeader; metadata.header = header;
/* /*
Contains the required data to define the color mode. Contains the required data to define the color mode.
@@ -730,8 +724,8 @@ public class PSDImageReader extends ImageReaderBase {
the duotone image as a grayscale image, and keep the duotone specification the duotone image as a grayscale image, and keep the duotone specification
around as a black box for use when saving the file. around as a black box for use when saving the file.
*/ */
if (mHeader.mMode == PSD.COLOR_MODE_INDEXED) { if (header.mode == PSD.COLOR_MODE_INDEXED) {
mMetadata.mColorData = new PSDColorData(imageInput); metadata.colorData = new PSDColorData(imageInput);
} }
else { else {
// TODO: We need to store the duotone spec if we decide to create a writer... // TODO: We need to store the duotone spec if we decide to create a writer...
@@ -755,14 +749,14 @@ public class PSDImageReader extends ImageReaderBase {
long length = imageInput.readUnsignedInt(); long length = imageInput.readUnsignedInt();
if (pParseData && length > 0) { if (pParseData && length > 0) {
if (mMetadata.mImageResources == null) { if (metadata.imageResources == null) {
mMetadata.mImageResources = new ArrayList<PSDImageResource>(); metadata.imageResources = new ArrayList<PSDImageResource>();
long expectedEnd = imageInput.getStreamPosition() + length; long expectedEnd = imageInput.getStreamPosition() + length;
while (imageInput.getStreamPosition() < expectedEnd) { while (imageInput.getStreamPosition() < expectedEnd) {
// TODO: Have PSDImageResources defer actual parsing? (Just store stream offsets) // TODO: Have PSDImageResources defer actual parsing? (Just store stream offsets)
PSDImageResource resource = PSDImageResource.read(imageInput); PSDImageResource resource = PSDImageResource.read(imageInput);
mMetadata.mImageResources.add(resource); metadata.imageResources.add(resource);
} }
if (imageInput.getStreamPosition() != expectedEnd) { if (imageInput.getStreamPosition() != expectedEnd) {
@@ -796,7 +790,7 @@ public class PSDImageReader extends ImageReaderBase {
for (int i = 0; i < layerInfos.length; i++) { for (int i = 0; i < layerInfos.length; i++) {
layerInfos[i] = new PSDLayerInfo(imageInput); layerInfos[i] = new PSDLayerInfo(imageInput);
} }
mMetadata.mLayerInfo = Arrays.asList(layerInfos); metadata.layerInfo = Arrays.asList(layerInfos);
// TODO: Clean-up // TODO: Clean-up
imageInput.mark(); imageInput.mark();
@@ -810,7 +804,7 @@ public class PSDImageReader extends ImageReaderBase {
// TODO: Don't show! Store in meta data somehow... // TODO: Don't show! Store in meta data somehow...
// if (layer != null) { // if (layer != null) {
// showIt(layer, layerInfo.mLayerName + " " + layerInfo.mBlendMode.toString()); // showIt(layer, layerInfo.layerName + " " + layerInfo.blendMode.toString());
// } // }
} }
@@ -825,8 +819,8 @@ public class PSDImageReader extends ImageReaderBase {
long layerMaskInfoLength = imageInput.readUnsignedInt(); long layerMaskInfoLength = imageInput.readUnsignedInt();
// System.out.println("GlobalLayerMaskInfo length: " + layerMaskInfoLength); // System.out.println("GlobalLayerMaskInfo length: " + layerMaskInfoLength);
if (layerMaskInfoLength > 0) { if (layerMaskInfoLength > 0) {
mMetadata.mGlobalLayerMask = new PSDGlobalLayerMask(imageInput); metadata.globalLayerMask = new PSDGlobalLayerMask(imageInput);
// System.out.println("mGlobalLayerMask: " + mGlobalLayerMask); // System.out.println("globalLayerMask: " + globalLayerMask);
} }
read = imageInput.getStreamPosition() - pos; read = imageInput.getStreamPosition() - pos;
@@ -842,8 +836,8 @@ public class PSDImageReader extends ImageReaderBase {
} }
private BufferedImage readLayerData(final PSDLayerInfo pLayerInfo, final ImageTypeSpecifier pRawType, final ImageTypeSpecifier pImageType) throws IOException { private BufferedImage readLayerData(final PSDLayerInfo pLayerInfo, final ImageTypeSpecifier pRawType, final ImageTypeSpecifier pImageType) throws IOException {
final int width = pLayerInfo.mRight - pLayerInfo.mLeft; final int width = pLayerInfo.right - pLayerInfo.left;
final int height = pLayerInfo.mBottom - pLayerInfo.mTop; final int height = pLayerInfo.bottom - pLayerInfo.top;
// Even if raw/imageType has no alpha, the layers may still have alpha... // Even if raw/imageType has no alpha, the layers may still have alpha...
ImageTypeSpecifier imageType = getImageTypeForLayer(pImageType, pLayerInfo); ImageTypeSpecifier imageType = getImageTypeForLayer(pImageType, pLayerInfo);
@@ -869,19 +863,19 @@ public class PSDImageReader extends ImageReaderBase {
final boolean banded = raster.getDataBuffer().getNumBanks() > 1; final boolean banded = raster.getDataBuffer().getNumBanks() > 1;
final int interleavedBands = banded ? 1 : raster.getNumBands(); final int interleavedBands = banded ? 1 : raster.getNumBands();
for (PSDChannelInfo channelInfo : pLayerInfo.mChannelInfo) { for (PSDChannelInfo channelInfo : pLayerInfo.channelInfo) {
int compression = imageInput.readUnsignedShort(); int compression = imageInput.readUnsignedShort();
// Skip layer if we can't read it // Skip layer if we can't read it
// channelId == -2 means "user supplied layer mask", whatever that is... // channelId == -2 means "user supplied layer mask", whatever that is...
if (width <= 0 || height <= 0 || channelInfo.mChannelId == -2 || if (width <= 0 || height <= 0 || channelInfo.channelId == -2 ||
(compression != PSD.COMPRESSION_NONE && compression != PSD.COMPRESSION_RLE)) { (compression != PSD.COMPRESSION_NONE && compression != PSD.COMPRESSION_RLE)) {
imageInput.skipBytes(channelInfo.mLength - 2); imageInput.skipBytes(channelInfo.length - 2);
} }
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.channelId == -1 ? pLayerInfo.channelInfo.length - 1 : channelInfo.channelId;
// 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
// byte counts are written for all channels before the image data. // byte counts are written for all channels before the image data.
@@ -896,7 +890,7 @@ public class PSDImageReader extends ImageReaderBase {
// If RLE, the the image data starts with the byte counts // If RLE, the the image data starts with the byte counts
// for all the scan lines in the channel (LayerBottom-LayerTop), with // for all the scan lines in the channel (LayerBottom-LayerTop), with
// each count stored as a two*byte value. // each count stored as a two*byte value.
byteCounts = new int[pLayerInfo.mBottom - pLayerInfo.mTop]; byteCounts = new int[pLayerInfo.bottom - pLayerInfo.top];
for (int i = 0; i < byteCounts.length; i++) { for (int i = 0; i < byteCounts.length; i++) {
byteCounts[i] = imageInput.readUnsignedShort(); byteCounts[i] = imageInput.readUnsignedShort();
} }
@@ -911,7 +905,7 @@ public class PSDImageReader extends ImageReaderBase {
int bandOffset = banded ? 0 : interleavedBands - 1 - c; int bandOffset = banded ? 0 : interleavedBands - 1 - c;
switch (mHeader.mBits) { switch (header.bits) {
case 1: case 1:
byte[] row1 = ((DataBufferByte) rowRaster.getDataBuffer()).getData(); byte[] row1 = ((DataBufferByte) rowRaster.getDataBuffer()).getData();
// DataBufferByte buffer1 = (DataBufferByte) raster.getDataBuffer(); // DataBufferByte buffer1 = (DataBufferByte) raster.getDataBuffer();
@@ -935,7 +929,7 @@ public class PSDImageReader extends ImageReaderBase {
read16bitChannel(c, imageType.getNumBands(), raster.getDataBuffer(), interleavedBands, bandOffset, sourceCM, row16, area, area, xsub, ysub, width, height, byteCounts, 0, compression == PSD.COMPRESSION_RLE); read16bitChannel(c, imageType.getNumBands(), raster.getDataBuffer(), 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(String.format("Unknown PSD bit depth: %s", header.bits));
} }
if (abortRequested()) { if (abortRequested()) {
@@ -949,17 +943,17 @@ public class PSDImageReader extends ImageReaderBase {
private ImageTypeSpecifier getImageTypeForLayer(final ImageTypeSpecifier pOriginal, final PSDLayerInfo pLayerInfo) { private ImageTypeSpecifier getImageTypeForLayer(final ImageTypeSpecifier pOriginal, final PSDLayerInfo pLayerInfo) {
// If layer has more channels than composite data, it's normally extra alpha... // If layer has more channels than composite data, it's normally extra alpha...
if (pLayerInfo.mChannelInfo.length > pOriginal.getNumBands()) { if (pLayerInfo.channelInfo.length > pOriginal.getNumBands()) {
// ...but, it could also be just the user mask... // ...but, it could also be just the user mask...
boolean userMask = false; boolean userMask = false;
for (PSDChannelInfo channelInfo : pLayerInfo.mChannelInfo) { for (PSDChannelInfo channelInfo : pLayerInfo.channelInfo) {
if (channelInfo.mChannelId == -2) { if (channelInfo.channelId == -2) {
userMask = true; userMask = true;
break; break;
} }
} }
int newBandNum = pLayerInfo.mChannelInfo.length - (userMask ? 1 : 0); int newBandNum = pLayerInfo.channelInfo.length - (userMask ? 1 : 0);
// If there really is more channels, then create new imageTypeSpec // If there really is more channels, then create new imageTypeSpec
if (newBandNum > pOriginal.getNumBands()) { if (newBandNum > pOriginal.getNumBands()) {
@@ -1004,22 +998,22 @@ public class PSDImageReader extends ImageReaderBase {
} }
@Override @Override
public IIOMetadata getImageMetadata(final int pImageIndex) throws IOException { public IIOMetadata getImageMetadata(final int imageIndex) throws IOException {
// TODO: Implement // TODO: Implement
checkBounds(pImageIndex); checkBounds(imageIndex);
readHeader(); readHeader();
readImageResources(true); readImageResources(true);
readLayerAndMaskInfo(true); readLayerAndMaskInfo(true);
// TODO: Need to make sure compression is set in metadata, even without reading the image data! // TODO: Need to make sure compression is set in metadata, even without reading the image data!
mMetadata.mCompression = imageInput.readShort(); metadata.compression = imageInput.readShort();
// mMetadata.mHeader = mHeader; // metadata.header = header;
// mMetadata.mColorData = mColorData; // metadata.colorData = colorData;
// mMetadata.mImageResources = mImageResources; // metadata.imageResources = imageResources;
return mMetadata; // TODO: clone if we change to mutable metadata return metadata; // TODO: clone if we change to mutable metadata
} }
@Override @Override
@@ -1041,14 +1035,14 @@ public class PSDImageReader extends ImageReaderBase {
List<PSDThumbnail> thumbnails = null; List<PSDThumbnail> thumbnails = null;
if (mMetadata.mImageResources == null) { if (metadata.imageResources == null) {
// TODO: Need flag here, to specify what resources to read... // TODO: Need flag here, to specify what resources to read...
readImageResources(true); readImageResources(true);
// TODO: Skip this, requires storing some stream offsets // TODO: Skip this, requires storing some stream offsets
readLayerAndMaskInfo(false); readLayerAndMaskInfo(false);
} }
for (PSDImageResource resource : mMetadata.mImageResources) { for (PSDImageResource resource : metadata.imageResources) {
if (resource instanceof PSDThumbnail) { if (resource instanceof PSDThumbnail) {
if (thumbnails == null) { if (thumbnails == null) {
thumbnails = new ArrayList<PSDThumbnail>(); thumbnails = new ArrayList<PSDThumbnail>();
@@ -1147,15 +1141,15 @@ public class PSDImageReader extends ImageReaderBase {
imageReader.setInput(stream); imageReader.setInput(stream);
imageReader.readHeader(); imageReader.readHeader();
// System.out.println("imageReader.mHeader: " + imageReader.mHeader); // System.out.println("imageReader.header: " + imageReader.header);
imageReader.readImageResources(true); imageReader.readImageResources(true);
System.out.println("imageReader.mImageResources: " + imageReader.mMetadata.mImageResources); System.out.println("imageReader.imageResources: " + imageReader.metadata.imageResources);
System.out.println(); System.out.println();
imageReader.readLayerAndMaskInfo(true); imageReader.readLayerAndMaskInfo(true);
System.out.println("imageReader.mLayerInfo: " + imageReader.mMetadata.mLayerInfo); System.out.println("imageReader.layerInfo: " + imageReader.metadata.layerInfo);
// System.out.println("imageReader.mGlobalLayerMask: " + imageReader.mGlobalLayerMask); // System.out.println("imageReader.globalLayerMask: " + imageReader.globalLayerMask);
System.out.println(); System.out.println();
IIOMetadata metadata = imageReader.getImageMetadata(0); IIOMetadata metadata = imageReader.getImageMetadata(0);
@@ -47,33 +47,33 @@ public class PSDImageResource {
// TODO: Refactor image resources to separate package // TODO: Refactor image resources to separate package
// TODO: Change constructor to store stream offset and length only (+ possibly the name), defer reading // TODO: Change constructor to store stream offset and length only (+ possibly the name), defer reading
final short mId; final short id;
final String mName; final String name;
final long mSize; final long size;
PSDImageResource(final short pId, final ImageInputStream pInput) throws IOException { PSDImageResource(final short pId, final ImageInputStream pInput) throws IOException {
mId = pId; id = pId;
mName = PSDUtil.readPascalString(pInput); name = PSDUtil.readPascalString(pInput);
// Skip pad // Skip pad
int nameSize = mName.length() + 1; int nameSize = name.length() + 1;
if (nameSize % 2 != 0) { if (nameSize % 2 != 0) {
pInput.readByte(); pInput.readByte();
} }
mSize = pInput.readUnsignedInt(); size = pInput.readUnsignedInt();
long startPos = pInput.getStreamPosition(); long startPos = pInput.getStreamPosition();
readData(new SubImageInputStream(pInput, mSize)); readData(new SubImageInputStream(pInput, size));
// NOTE: This should never happen, however it's safer to keep it here to // NOTE: This should never happen, however it's safer to keep it here to
if (pInput.getStreamPosition() != startPos + mSize) { if (pInput.getStreamPosition() != startPos + size) {
pInput.seek(startPos + mSize); pInput.seek(startPos + size);
} }
// Data is even-padded (word aligned) // Data is even-padded (word aligned)
if (mSize % 2 != 0) { if (size % 2 != 0) {
pInput.read(); pInput.read();
} }
} }
@@ -86,7 +86,7 @@ public class PSDImageResource {
*/ */
protected void readData(final ImageInputStream pInput) throws IOException { protected void readData(final ImageInputStream pInput) throws IOException {
// TODO: This design is ugly, as subclasses readData is invoked BEFORE their respective constructor... // TODO: This design is ugly, as subclasses readData is invoked BEFORE their respective constructor...
pInput.skipBytes(mSize); pInput.skipBytes(size);
} }
@Override @Override
@@ -94,7 +94,7 @@ public class PSDImageResource {
StringBuilder builder = toStringBuilder(); StringBuilder builder = toStringBuilder();
builder.append(", data length: "); builder.append(", data length: ");
builder.append(mSize); builder.append(size);
builder.append("]"); builder.append("]");
return builder.toString(); return builder.toString();
@@ -103,16 +103,16 @@ public class PSDImageResource {
protected StringBuilder toStringBuilder() { protected StringBuilder toStringBuilder() {
StringBuilder builder = new StringBuilder(getClass().getSimpleName()); StringBuilder builder = new StringBuilder(getClass().getSimpleName());
String fakeType = resourceTypeForId(mId); String fakeType = resourceTypeForId(id);
if (fakeType != null) { if (fakeType != null) {
builder.append("(").append(fakeType).append(")"); builder.append("(").append(fakeType).append(")");
} }
builder.append("[ID: 0x"); builder.append("[ID: 0x");
builder.append(Integer.toHexString(mId)); builder.append(Integer.toHexString(id));
if (mName != null && mName.trim().length() != 0) { if (name != null && name.trim().length() != 0) {
builder.append(", name: \""); builder.append(", name: \"");
builder.append(mName); builder.append(name);
builder.append("\""); builder.append("\"");
} }
@@ -40,10 +40,10 @@ import java.io.IOException;
* @version $Id: PSDLayerBlendMode.java,v 1.0 May 8, 2008 4:34:35 PM haraldk Exp$ * @version $Id: PSDLayerBlendMode.java,v 1.0 May 8, 2008 4:34:35 PM haraldk Exp$
*/ */
class PSDLayerBlendMode { class PSDLayerBlendMode {
final int mBlendMode; final int blendMode;
final int mOpacity; // 0-255 final int opacity; // 0-255
final int mClipping; // 0: base, 1: non-base final int clipping; // 0: base, 1: non-base
final int mFlags; final int flags;
public PSDLayerBlendMode(final ImageInputStream pInput) throws IOException { public PSDLayerBlendMode(final ImageInputStream pInput) throws IOException {
int blendModeSig = pInput.readInt(); int blendModeSig = pInput.readInt();
@@ -51,11 +51,11 @@ class PSDLayerBlendMode {
throw new IIOException("Illegal PSD Blend Mode signature, expected 8BIM: " + PSDUtil.intToStr(blendModeSig)); throw new IIOException("Illegal PSD Blend Mode signature, expected 8BIM: " + PSDUtil.intToStr(blendModeSig));
} }
mBlendMode = pInput.readInt(); blendMode = pInput.readInt();
mOpacity = pInput.readUnsignedByte(); opacity = pInput.readUnsignedByte();
mClipping = pInput.readUnsignedByte(); clipping = pInput.readUnsignedByte();
mFlags = pInput.readUnsignedByte(); flags = pInput.readUnsignedByte();
pInput.readByte(); // Pad pInput.readByte(); // Pad
} }
@@ -65,10 +65,10 @@ class PSDLayerBlendMode {
StringBuilder builder = new StringBuilder(getClass().getSimpleName()); StringBuilder builder = new StringBuilder(getClass().getSimpleName());
builder.append("["); builder.append("[");
builder.append("mode: \"").append(PSDUtil.intToStr(mBlendMode)); builder.append("mode: \"").append(PSDUtil.intToStr(blendMode));
builder.append("\", opacity: ").append(mOpacity); builder.append("\", opacity: ").append(opacity);
builder.append(", clipping: ").append(mClipping); builder.append(", clipping: ").append(clipping);
switch (mClipping) { switch (clipping) {
case 0: case 0:
builder.append(" (base)"); builder.append(" (base)");
break; break;
@@ -79,40 +79,40 @@ class PSDLayerBlendMode {
builder.append(" (unknown)"); builder.append(" (unknown)");
break; break;
} }
builder.append(", flags: ").append(byteToBinary(mFlags)); builder.append(", flags: ").append(byteToBinary(flags));
/* /*
bit 0 = transparency protected; bit 1 = visible; bit 2 = obsolete; bit 0 = transparency protected; bit 1 = visible; bit 2 = obsolete;
bit 3 = 1 for Photoshop 5.0 and later, tells if bit 4 has useful information; bit 3 = 1 for Photoshop 5.0 and later, tells if bit 4 has useful information;
bit 4 = pixel data irrelevant to appearance of document bit 4 = pixel data irrelevant to appearance of document
*/ */
builder.append(" ("); builder.append(" (");
if ((mFlags & 0x01) != 0) { if ((flags & 0x01) != 0) {
builder.append("Transp. protected, "); builder.append("Transp. protected, ");
} }
if ((mFlags & 0x02) != 0) { if ((flags & 0x02) != 0) {
builder.append("Hidden, "); builder.append("Hidden, ");
} }
if ((mFlags & 0x04) != 0) { if ((flags & 0x04) != 0) {
builder.append("Obsolete bit, "); builder.append("Obsolete bit, ");
} }
if ((mFlags & 0x08) != 0) { if ((flags & 0x08) != 0) {
builder.append("PS 5.0 data present, "); // "tells if next bit has useful information"... builder.append("PS 5.0 data present, "); // "tells if next bit has useful information"...
} }
if ((mFlags & 0x10) != 0) { if ((flags & 0x10) != 0) {
builder.append("Pixel data irrelevant, "); builder.append("Pixel data irrelevant, ");
} }
if ((mFlags & 0x20) != 0) { if ((flags & 0x20) != 0) {
builder.append("Unknown bit 5, "); builder.append("Unknown bit 5, ");
} }
if ((mFlags & 0x40) != 0) { if ((flags & 0x40) != 0) {
builder.append("Unknown bit 6, "); builder.append("Unknown bit 6, ");
} }
if ((mFlags & 0x80) != 0) { if ((flags & 0x80) != 0) {
builder.append("Unknown bit 7, "); builder.append("Unknown bit 7, ");
} }
// Stupidity... // Stupidity...
if (mFlags != 0) { if (flags != 0) {
builder.delete(builder.length() - 2, builder.length()); builder.delete(builder.length() - 2, builder.length());
} }
@@ -41,34 +41,34 @@ import java.util.Arrays;
* @version $Id: PSDLayerInfo.java,v 1.0 Apr 29, 2008 6:01:12 PM haraldk Exp$ * @version $Id: PSDLayerInfo.java,v 1.0 Apr 29, 2008 6:01:12 PM haraldk Exp$
*/ */
class PSDLayerInfo { class PSDLayerInfo {
final int mTop; final int top;
final int mLeft; final int left;
final int mBottom; final int bottom;
final int mRight; final int right;
final PSDChannelInfo[] mChannelInfo; final PSDChannelInfo[] channelInfo;
final PSDLayerBlendMode mBlendMode; final PSDLayerBlendMode blendMode;
final PSDLayerMaskData mLayerMaskData; final PSDLayerMaskData layerMaskData;
final PSDChannelSourceDestinationRange[] mRanges; final PSDChannelSourceDestinationRange[] ranges;
final String mLayerName; final String layerName;
PSDLayerInfo(ImageInputStream pInput) throws IOException { PSDLayerInfo(ImageInputStream pInput) throws IOException {
mTop = pInput.readInt(); top = pInput.readInt();
mLeft = pInput.readInt(); left = pInput.readInt();
mBottom = pInput.readInt(); bottom = pInput.readInt();
mRight = pInput.readInt(); right = pInput.readInt();
int channels = pInput.readUnsignedShort(); int channels = pInput.readUnsignedShort();
mChannelInfo = new PSDChannelInfo[channels]; channelInfo = new PSDChannelInfo[channels];
for (int i = 0; i < channels; i++) { for (int i = 0; i < channels; i++) {
short channelId = pInput.readShort(); short channelId = pInput.readShort();
long length = pInput.readUnsignedInt(); long length = pInput.readUnsignedInt();
mChannelInfo[i] = new PSDChannelInfo(channelId, length); channelInfo[i] = new PSDChannelInfo(channelId, length);
} }
mBlendMode = new PSDLayerBlendMode(pInput); blendMode = new PSDLayerBlendMode(pInput);
// Lenght of layer mask data // Lenght of layer mask data
long extraDataSize = pInput.readUnsignedInt(); long extraDataSize = pInput.readUnsignedInt();
@@ -78,10 +78,10 @@ class PSDLayerInfo {
// Layer mask/adjustment layer data // Layer mask/adjustment layer data
int layerMaskDataSize = pInput.readInt(); // May be 0, 20 or 36 bytes... int layerMaskDataSize = pInput.readInt(); // May be 0, 20 or 36 bytes...
if (layerMaskDataSize != 0) { if (layerMaskDataSize != 0) {
mLayerMaskData = new PSDLayerMaskData(pInput, layerMaskDataSize); layerMaskData = new PSDLayerMaskData(pInput, layerMaskDataSize);
} }
else { else {
mLayerMaskData = null; layerMaskData = null;
} }
int layerBlendingDataSize = pInput.readInt(); int layerBlendingDataSize = pInput.readInt();
@@ -89,15 +89,15 @@ class PSDLayerInfo {
throw new IIOException("Illegal PSD Layer Blending Data size: " + layerBlendingDataSize + ", expected multiple of 8"); throw new IIOException("Illegal PSD Layer Blending Data size: " + layerBlendingDataSize + ", expected multiple of 8");
} }
mRanges = new PSDChannelSourceDestinationRange[layerBlendingDataSize / 8]; ranges = new PSDChannelSourceDestinationRange[layerBlendingDataSize / 8];
for (int i = 0; i < mRanges.length; i++) { for (int i = 0; i < ranges.length; i++) {
mRanges[i] = new PSDChannelSourceDestinationRange(pInput, (i == 0 ? "Gray" : "Channel " + (i - 1))); ranges[i] = new PSDChannelSourceDestinationRange(pInput, (i == 0 ? "Gray" : "Channel " + (i - 1)));
} }
mLayerName = PSDUtil.readPascalString(pInput); layerName = PSDUtil.readPascalString(pInput);
int layerNameSize = mLayerName.length() + 1; int layerNameSize = layerName.length() + 1;
// Skip pad bytes for long word alignment // Skip pad bytes for long word alignment
if (layerNameSize % 4 != 0) { if (layerNameSize % 4 != 0) {
@@ -115,18 +115,18 @@ class PSDLayerInfo {
public String toString() { public String toString() {
StringBuilder builder = new StringBuilder(getClass().getSimpleName()); StringBuilder builder = new StringBuilder(getClass().getSimpleName());
builder.append("["); builder.append("[");
builder.append("top: ").append(mTop); builder.append("top: ").append(top);
builder.append(", left: ").append(mLeft); builder.append(", left: ").append(left);
builder.append(", bottom: ").append(mBottom); builder.append(", bottom: ").append(bottom);
builder.append(", right: ").append(mRight); builder.append(", right: ").append(right);
builder.append(", channels: ").append(Arrays.toString(mChannelInfo)); builder.append(", channels: ").append(Arrays.toString(channelInfo));
builder.append(", blend mode: ").append(mBlendMode); builder.append(", blend mode: ").append(blendMode);
if (mLayerMaskData != null) { if (layerMaskData != null) {
builder.append(", layer mask data: ").append(mLayerMaskData); builder.append(", layer mask data: ").append(layerMaskData);
} }
builder.append(", ranges: ").append(Arrays.toString(mRanges)); builder.append(", ranges: ").append(Arrays.toString(ranges));
builder.append(", layer name: \"").append(mLayerName).append("\""); builder.append(", layer name: \"").append(layerName).append("\"");
builder.append("]"); builder.append("]");
return builder.toString(); return builder.toString();
@@ -40,48 +40,48 @@ import java.io.IOException;
* @version $Id: PSDLayerMaskData.java,v 1.0 May 6, 2008 5:15:05 PM haraldk Exp$ * @version $Id: PSDLayerMaskData.java,v 1.0 May 6, 2008 5:15:05 PM haraldk Exp$
*/ */
class PSDLayerMaskData { class PSDLayerMaskData {
private int mTop; private int top;
private int mLeft; private int left;
private int mBottom; private int bottom;
private int mRight; private int right;
private int mDefaultColor; private int defaultColor;
private int mFlags; private int flags;
private boolean mLarge; private boolean large;
private int mRealFlags; private int realFlags;
private int mRealUserBackground; private int realUserBackground;
private int mRealTop; private int realTop;
private int mRealLeft; private int realLeft;
private int mRealBottom; private int realBottom;
private int mRealRight; private int realRight;
PSDLayerMaskData(ImageInputStream pInput, int pSize) throws IOException { PSDLayerMaskData(ImageInputStream pInput, int pSize) throws IOException {
if (pSize != 20 && pSize != 36) { if (pSize != 20 && pSize != 36) {
throw new IIOException("Illegal PSD Layer Mask data size: " + pSize + " (expeced 20 or 36)"); throw new IIOException("Illegal PSD Layer Mask data size: " + pSize + " (expeced 20 or 36)");
} }
mTop = pInput.readInt(); top = pInput.readInt();
mLeft = pInput.readInt(); left = pInput.readInt();
mBottom = pInput.readInt(); bottom = pInput.readInt();
mRight = pInput.readInt(); right = pInput.readInt();
mDefaultColor = pInput.readUnsignedByte(); defaultColor = pInput.readUnsignedByte();
mFlags = pInput.readUnsignedByte(); flags = pInput.readUnsignedByte();
if (pSize == 20) { if (pSize == 20) {
pInput.readShort(); // Pad pInput.readShort(); // Pad
} }
else { else {
// TODO: What to make out of this? // TODO: What to make out of this?
mLarge = true; large = true;
mRealFlags = pInput.readUnsignedByte(); realFlags = pInput.readUnsignedByte();
mRealUserBackground = pInput.readUnsignedByte(); realUserBackground = pInput.readUnsignedByte();
mRealTop = pInput.readInt(); realTop = pInput.readInt();
mRealLeft = pInput.readInt(); realLeft = pInput.readInt();
mRealBottom = pInput.readInt(); realBottom = pInput.readInt();
mRealRight = pInput.readInt(); realRight = pInput.readInt();
} }
} }
@@ -89,43 +89,43 @@ class PSDLayerMaskData {
public String toString() { public String toString() {
StringBuilder builder = new StringBuilder(getClass().getSimpleName()); StringBuilder builder = new StringBuilder(getClass().getSimpleName());
builder.append("["); builder.append("[");
builder.append("top: ").append(mTop); builder.append("top: ").append(top);
builder.append(", left: ").append(mLeft); builder.append(", left: ").append(left);
builder.append(", bottom: ").append(mBottom); builder.append(", bottom: ").append(bottom);
builder.append(", right: ").append(mRight); builder.append(", right: ").append(right);
builder.append(", default color: ").append(mDefaultColor); builder.append(", default color: ").append(defaultColor);
builder.append(", flags: ").append(Integer.toBinaryString(mFlags)); builder.append(", flags: ").append(Integer.toBinaryString(flags));
// TODO: Maybe the flag bits have oposite order? // TODO: Maybe the flag bits have oposite order?
builder.append(" ("); builder.append(" (");
if ((mFlags & 0x01) != 0) { if ((flags & 0x01) != 0) {
builder.append("Pos. rel. to layer"); builder.append("Pos. rel. to layer");
} }
else { else {
builder.append("Pos. abs."); builder.append("Pos. abs.");
} }
if ((mFlags & 0x02) != 0) { if ((flags & 0x02) != 0) {
builder.append(", Mask disabled"); builder.append(", Mask disabled");
} }
else { else {
builder.append(", Mask enabled"); builder.append(", Mask enabled");
} }
if ((mFlags & 0x04) != 0) { if ((flags & 0x04) != 0) {
builder.append(", Invert mask"); builder.append(", Invert mask");
} }
if ((mFlags & 0x08) != 0) { if ((flags & 0x08) != 0) {
builder.append(", Unknown bit 3"); builder.append(", Unknown bit 3");
} }
if ((mFlags & 0x10) != 0) { if ((flags & 0x10) != 0) {
builder.append(", Unknown bit 4"); builder.append(", Unknown bit 4");
} }
if ((mFlags & 0x20) != 0) { if ((flags & 0x20) != 0) {
builder.append(", Unknown bit 5"); builder.append(", Unknown bit 5");
} }
if ((mFlags & 0x40) != 0) { if ((flags & 0x40) != 0) {
builder.append(", Unknown bit 6"); builder.append(", Unknown bit 6");
} }
if ((mFlags & 0x80) != 0) { if ((flags & 0x80) != 0) {
builder.append(", Unknown bit 7"); builder.append(", Unknown bit 7");
} }
builder.append(")"); builder.append(")");
@@ -27,12 +27,12 @@ public final class PSDMetadata extends AbstractMetadata {
static final String NATIVE_METADATA_FORMAT_NAME = "com_twelvemonkeys_imageio_psd_image_1.0"; static final String NATIVE_METADATA_FORMAT_NAME = "com_twelvemonkeys_imageio_psd_image_1.0";
static final String NATIVE_METADATA_FORMAT_CLASS_NAME = "com.twelvemonkeys.imageio.plugins.psd.PSDMetadataFormat"; static final String NATIVE_METADATA_FORMAT_CLASS_NAME = "com.twelvemonkeys.imageio.plugins.psd.PSDMetadataFormat";
PSDHeader mHeader; PSDHeader header;
PSDColorData mColorData; PSDColorData colorData;
int mCompression = -1; int compression = -1;
List<PSDImageResource> mImageResources; List<PSDImageResource> imageResources;
PSDGlobalLayerMask mGlobalLayerMask; PSDGlobalLayerMask globalLayerMask;
List<PSDLayerInfo> mLayerInfo; List<PSDLayerInfo> layerInfo;
static final String[] COLOR_MODES = { static final String[] COLOR_MODES = {
"MONOCHROME", "GRAYSCALE", "INDEXED", "RGB", "CMYK", null, null, "MULTICHANNEL", "DUOTONE", "LAB" "MONOCHROME", "GRAYSCALE", "INDEXED", "RGB", "CMYK", null, null, "MULTICHANNEL", "DUOTONE", "LAB"
@@ -70,11 +70,11 @@ public final class PSDMetadata extends AbstractMetadata {
root.appendChild(createHeaderNode()); root.appendChild(createHeaderNode());
if (mHeader.mMode == PSD.COLOR_MODE_INDEXED) { if (header.mode == PSD.COLOR_MODE_INDEXED) {
root.appendChild(createPaletteNode()); root.appendChild(createPaletteNode());
} }
if (mImageResources != null && !mImageResources.isEmpty()) { if (imageResources != null && !imageResources.isEmpty()) {
root.appendChild(createImageResourcesNode()); root.appendChild(createImageResourcesNode());
} }
@@ -86,11 +86,11 @@ public final class PSDMetadata extends AbstractMetadata {
header.setAttribute("type", "PSD"); header.setAttribute("type", "PSD");
header.setAttribute("version", "1"); header.setAttribute("version", "1");
header.setAttribute("channels", Integer.toString(mHeader.mChannels)); header.setAttribute("channels", Integer.toString(this.header.channels));
header.setAttribute("height", Integer.toString(mHeader.mHeight)); header.setAttribute("height", Integer.toString(this.header.height));
header.setAttribute("width", Integer.toString(mHeader.mWidth)); header.setAttribute("width", Integer.toString(this.header.width));
header.setAttribute("bits", Integer.toString(mHeader.mBits)); header.setAttribute("bits", Integer.toString(this.header.bits));
header.setAttribute("mode", COLOR_MODES[mHeader.mMode]); header.setAttribute("mode", COLOR_MODES[this.header.mode]);
return header; return header;
} }
@@ -99,7 +99,7 @@ public final class PSDMetadata extends AbstractMetadata {
IIOMetadataNode resource = new IIOMetadataNode("ImageResources"); IIOMetadataNode resource = new IIOMetadataNode("ImageResources");
IIOMetadataNode node; IIOMetadataNode node;
for (PSDImageResource imageResource : mImageResources) { for (PSDImageResource imageResource : imageResources) {
// TODO: Always add name (if set) and id (as resourceId) to all nodes? // TODO: Always add name (if set) and id (as resourceId) to all nodes?
// Resource Id is useful for people with access to the PSD spec.. // Resource Id is useful for people with access to the PSD spec..
@@ -128,7 +128,7 @@ public final class PSDMetadata extends AbstractMetadata {
node = new IIOMetadataNode("AlphaChannelInfo"); node = new IIOMetadataNode("AlphaChannelInfo");
for (String name : alphaChannelInfo.mNames) { for (String name : alphaChannelInfo.names) {
IIOMetadataNode nameNode = new IIOMetadataNode("Name"); IIOMetadataNode nameNode = new IIOMetadataNode("Name");
nameNode.setAttribute("value", name); nameNode.setAttribute("value", name);
node.appendChild(nameNode); node.appendChild(nameNode);
@@ -138,11 +138,11 @@ public final class PSDMetadata extends AbstractMetadata {
PSDDisplayInfo displayInfo = (PSDDisplayInfo) imageResource; PSDDisplayInfo displayInfo = (PSDDisplayInfo) imageResource;
node = new IIOMetadataNode("DisplayInfo"); node = new IIOMetadataNode("DisplayInfo");
node.setAttribute("colorSpace", DISPLAY_INFO_CS[displayInfo.mColorSpace]); node.setAttribute("colorSpace", DISPLAY_INFO_CS[displayInfo.colorSpace]);
StringBuilder builder = new StringBuilder(); StringBuilder builder = new StringBuilder();
for (short color : displayInfo.mColors) { for (short color : displayInfo.colors) {
if (builder.length() > 0) { if (builder.length() > 0) {
builder.append(" "); builder.append(" ");
} }
@@ -151,79 +151,79 @@ public final class PSDMetadata extends AbstractMetadata {
} }
node.setAttribute("colors", builder.toString()); node.setAttribute("colors", builder.toString());
node.setAttribute("opacity", Integer.toString(displayInfo.mOpacity)); node.setAttribute("opacity", Integer.toString(displayInfo.opacity));
node.setAttribute("kind", DISPLAY_INFO_KINDS[displayInfo.mKind]); node.setAttribute("kind", DISPLAY_INFO_KINDS[displayInfo.kind]);
} }
else if (imageResource instanceof PSDGridAndGuideInfo) { else if (imageResource instanceof PSDGridAndGuideInfo) {
PSDGridAndGuideInfo info = (PSDGridAndGuideInfo) imageResource; PSDGridAndGuideInfo info = (PSDGridAndGuideInfo) imageResource;
node = new IIOMetadataNode("GridAndGuideInfo"); node = new IIOMetadataNode("GridAndGuideInfo");
node.setAttribute("version", String.valueOf(info.mVersion)); node.setAttribute("version", String.valueOf(info.version));
node.setAttribute("verticalGridCycle", String.valueOf(info.mGridCycleVertical)); node.setAttribute("verticalGridCycle", String.valueOf(info.gridCycleVertical));
node.setAttribute("horizontalGridCycle", String.valueOf(info.mGridCycleHorizontal)); node.setAttribute("horizontalGridCycle", String.valueOf(info.gridCycleHorizontal));
for (PSDGridAndGuideInfo.GuideResource guide : info.mGuides) { for (PSDGridAndGuideInfo.GuideResource guide : info.guides) {
IIOMetadataNode guideNode = new IIOMetadataNode("Guide"); IIOMetadataNode guideNode = new IIOMetadataNode("Guide");
guideNode.setAttribute("location", Integer.toString(guide.mLocation)); guideNode.setAttribute("location", Integer.toString(guide.location));
guideNode.setAttribute("orientation", GUIDE_ORIENTATIONS[guide.mDirection]); guideNode.setAttribute("orientation", GUIDE_ORIENTATIONS[guide.direction]);
} }
} }
else if (imageResource instanceof PSDPixelAspectRatio) { else if (imageResource instanceof PSDPixelAspectRatio) {
PSDPixelAspectRatio aspectRatio = (PSDPixelAspectRatio) imageResource; PSDPixelAspectRatio aspectRatio = (PSDPixelAspectRatio) imageResource;
node = new IIOMetadataNode("PixelAspectRatio"); node = new IIOMetadataNode("PixelAspectRatio");
node.setAttribute("version", String.valueOf(aspectRatio.mVersion)); node.setAttribute("version", String.valueOf(aspectRatio.version));
node.setAttribute("aspectRatio", String.valueOf(aspectRatio.mAspect)); node.setAttribute("aspectRatio", String.valueOf(aspectRatio.aspect));
} }
else if (imageResource instanceof PSDPrintFlags) { else if (imageResource instanceof PSDPrintFlags) {
PSDPrintFlags flags = (PSDPrintFlags) imageResource; PSDPrintFlags flags = (PSDPrintFlags) imageResource;
node = new IIOMetadataNode("PrintFlags"); node = new IIOMetadataNode("PrintFlags");
node.setAttribute("labels", String.valueOf(flags.mLabels)); node.setAttribute("labels", String.valueOf(flags.labels));
node.setAttribute("cropMarks", String.valueOf(flags.mCropMasks)); node.setAttribute("cropMarks", String.valueOf(flags.cropMasks));
node.setAttribute("colorBars", String.valueOf(flags.mColorBars)); node.setAttribute("colorBars", String.valueOf(flags.colorBars));
node.setAttribute("registrationMarks", String.valueOf(flags.mRegistrationMarks)); node.setAttribute("registrationMarks", String.valueOf(flags.registrationMarks));
node.setAttribute("negative", String.valueOf(flags.mNegative)); node.setAttribute("negative", String.valueOf(flags.negative));
node.setAttribute("flip", String.valueOf(flags.mFlip)); node.setAttribute("flip", String.valueOf(flags.flip));
node.setAttribute("interpolate", String.valueOf(flags.mInterpolate)); node.setAttribute("interpolate", String.valueOf(flags.interpolate));
node.setAttribute("caption", String.valueOf(flags.mCaption)); node.setAttribute("caption", String.valueOf(flags.caption));
} }
else if (imageResource instanceof PSDPrintFlagsInformation) { else if (imageResource instanceof PSDPrintFlagsInformation) {
PSDPrintFlagsInformation information = (PSDPrintFlagsInformation) imageResource; PSDPrintFlagsInformation information = (PSDPrintFlagsInformation) imageResource;
node = new IIOMetadataNode("PrintFlagsInformation"); node = new IIOMetadataNode("PrintFlagsInformation");
node.setAttribute("version", String.valueOf(information.mVersion)); node.setAttribute("version", String.valueOf(information.version));
node.setAttribute("cropMarks", String.valueOf(information.mCropMasks)); node.setAttribute("cropMarks", String.valueOf(information.cropMasks));
node.setAttribute("field", String.valueOf(information.mField)); node.setAttribute("field", String.valueOf(information.field));
node.setAttribute("bleedWidth", String.valueOf(information.mBleedWidth)); node.setAttribute("bleedWidth", String.valueOf(information.bleedWidth));
node.setAttribute("bleedScale", String.valueOf(information.mBleedScale)); node.setAttribute("bleedScale", String.valueOf(information.bleedScale));
} }
else if (imageResource instanceof PSDPrintScale) { else if (imageResource instanceof PSDPrintScale) {
PSDPrintScale printScale = (PSDPrintScale) imageResource; PSDPrintScale printScale = (PSDPrintScale) imageResource;
node = new IIOMetadataNode("PrintScale"); node = new IIOMetadataNode("PrintScale");
node.setAttribute("style", PRINT_SCALE_STYLES[printScale.mStyle]); node.setAttribute("style", PRINT_SCALE_STYLES[printScale.style]);
node.setAttribute("xLocation", String.valueOf(printScale.mXLocation)); node.setAttribute("xLocation", String.valueOf(printScale.xLocation));
node.setAttribute("yLocation", String.valueOf(printScale.mYlocation)); node.setAttribute("yLocation", String.valueOf(printScale.ylocation));
node.setAttribute("scale", String.valueOf(printScale.mScale)); node.setAttribute("scale", String.valueOf(printScale.scale));
} }
else if (imageResource instanceof PSDResolutionInfo) { else if (imageResource instanceof PSDResolutionInfo) {
PSDResolutionInfo information = (PSDResolutionInfo) imageResource; PSDResolutionInfo information = (PSDResolutionInfo) imageResource;
node = new IIOMetadataNode("ResolutionInfo"); node = new IIOMetadataNode("ResolutionInfo");
node.setAttribute("horizontalResolution", String.valueOf(information.mHRes)); node.setAttribute("horizontalResolution", String.valueOf(information.hRes));
node.setAttribute("horizontalResolutionUnit", RESOLUTION_UNITS[information.mHResUnit]); node.setAttribute("horizontalResolutionUnit", RESOLUTION_UNITS[information.hResUnit]);
node.setAttribute("widthUnit", DIMENSION_UNITS[information.mWidthUnit]); node.setAttribute("widthUnit", DIMENSION_UNITS[information.widthUnit]);
node.setAttribute("verticalResolution", String.valueOf(information.mVRes)); node.setAttribute("verticalResolution", String.valueOf(information.vRes));
node.setAttribute("verticalResolutionUnit", RESOLUTION_UNITS[information.mVResUnit]); node.setAttribute("verticalResolutionUnit", RESOLUTION_UNITS[information.vResUnit]);
node.setAttribute("heightUnit", DIMENSION_UNITS[information.mHeightUnit]); node.setAttribute("heightUnit", DIMENSION_UNITS[information.heightUnit]);
} }
else if (imageResource instanceof PSDUnicodeAlphaNames) { else if (imageResource instanceof PSDUnicodeAlphaNames) {
PSDUnicodeAlphaNames alphaNames = (PSDUnicodeAlphaNames) imageResource; PSDUnicodeAlphaNames alphaNames = (PSDUnicodeAlphaNames) imageResource;
node = new IIOMetadataNode("UnicodeAlphaNames"); node = new IIOMetadataNode("UnicodeAlphaNames");
for (String name : alphaNames.mNames) { for (String name : alphaNames.names) {
IIOMetadataNode nameNode = new IIOMetadataNode("Name"); IIOMetadataNode nameNode = new IIOMetadataNode("Name");
nameNode.setAttribute("value", name); nameNode.setAttribute("value", name);
node.appendChild(nameNode); node.appendChild(nameNode);
@@ -233,11 +233,11 @@ public final class PSDMetadata extends AbstractMetadata {
PSDVersionInfo information = (PSDVersionInfo) imageResource; PSDVersionInfo information = (PSDVersionInfo) imageResource;
node = new IIOMetadataNode("VersionInfo"); node = new IIOMetadataNode("VersionInfo");
node.setAttribute("version", String.valueOf(information.mVersion)); node.setAttribute("version", String.valueOf(information.version));
node.setAttribute("hasRealMergedData", String.valueOf(information.mHasRealMergedData)); node.setAttribute("hasRealMergedData", String.valueOf(information.hasRealMergedData));
node.setAttribute("writer", information.mWriter); node.setAttribute("writer", information.writer);
node.setAttribute("reader", information.mReader); node.setAttribute("reader", information.reader);
node.setAttribute("fileVersion", String.valueOf(information.mFileVersion)); node.setAttribute("fileVersion", String.valueOf(information.fileVersion));
} }
else if (imageResource instanceof PSDThumbnail) { else if (imageResource instanceof PSDThumbnail) {
// TODO: Revise/rethink this... // TODO: Revise/rethink this...
@@ -253,9 +253,9 @@ public final class PSDMetadata extends AbstractMetadata {
node = new IIOMetadataNode("DirectoryResource"); node = new IIOMetadataNode("DirectoryResource");
node.setAttribute("type", "IPTC"); node.setAttribute("type", "IPTC");
node.setUserObject(iptc.mDirectory); node.setUserObject(iptc.directory);
appendEntries(node, "IPTC", iptc.mDirectory); appendEntries(node, "IPTC", iptc.directory);
} }
else if (imageResource instanceof PSDEXIF1Data) { else if (imageResource instanceof PSDEXIF1Data) {
// TODO: Revise/rethink this... // TODO: Revise/rethink this...
@@ -264,9 +264,9 @@ public final class PSDMetadata extends AbstractMetadata {
node = new IIOMetadataNode("DirectoryResource"); node = new IIOMetadataNode("DirectoryResource");
node.setAttribute("type", "EXIF"); node.setAttribute("type", "EXIF");
// TODO: Set byte[] data instead // TODO: Set byte[] data instead
node.setUserObject(exif.mDirectory); node.setUserObject(exif.directory);
appendEntries(node, "EXIF", exif.mDirectory); appendEntries(node, "EXIF", exif.directory);
} }
else if (imageResource instanceof PSDXMPData) { else if (imageResource instanceof PSDXMPData) {
// TODO: Revise/rethink this... Would it be possible to parse XMP as IIOMetadataNodes? Or is that just stupid... // TODO: Revise/rethink this... Would it be possible to parse XMP as IIOMetadataNodes? Or is that just stupid...
@@ -275,25 +275,25 @@ public final class PSDMetadata extends AbstractMetadata {
node = new IIOMetadataNode("DirectoryResource"); node = new IIOMetadataNode("DirectoryResource");
node.setAttribute("type", "XMP"); node.setAttribute("type", "XMP");
appendEntries(node, "XMP", xmp.mDirectory); appendEntries(node, "XMP", xmp.directory);
// Set the entire XMP document as user data // Set the entire XMP document as user data
node.setUserObject(xmp.mData); node.setUserObject(xmp.data);
} }
else { else {
// Generic resource.. // Generic resource..
node = new IIOMetadataNode("ImageResource"); node = new IIOMetadataNode("ImageResource");
String value = PSDImageResource.resourceTypeForId(imageResource.mId); String value = PSDImageResource.resourceTypeForId(imageResource.id);
if (!"UnknownResource".equals(value)) { if (!"UnknownResource".equals(value)) {
node.setAttribute("name", value); node.setAttribute("name", value);
} }
node.setAttribute("length", String.valueOf(imageResource.mSize)); node.setAttribute("length", String.valueOf(imageResource.size));
// TODO: Set user object: byte array // TODO: Set user object: byte array
} }
// TODO: More resources // TODO: More resources
node.setAttribute("resourceId", String.format("0x%04x", imageResource.mId)); node.setAttribute("resourceId", String.format("0x%04x", imageResource.id));
resource.appendChild(node); resource.appendChild(node);
} }
@@ -343,7 +343,7 @@ public final class PSDMetadata extends AbstractMetadata {
node = new IIOMetadataNode("ColorSpaceType"); node = new IIOMetadataNode("ColorSpaceType");
String cs; String cs;
switch (mHeader.mMode) { switch (header.mode) {
case PSD.COLOR_MODE_MONOCHROME: case PSD.COLOR_MODE_MONOCHROME:
case PSD.COLOR_MODE_GRAYSCALE: case PSD.COLOR_MODE_GRAYSCALE:
case PSD.COLOR_MODE_DUOTONE: // Rationale: Spec says treat as gray... case PSD.COLOR_MODE_DUOTONE: // Rationale: Spec says treat as gray...
@@ -357,7 +357,7 @@ public final class PSDMetadata extends AbstractMetadata {
cs = "CMYK"; cs = "CMYK";
break; break;
case PSD.COLOR_MODE_MULTICHANNEL: case PSD.COLOR_MODE_MULTICHANNEL:
cs = getMultiChannelCS(mHeader.mChannels); cs = getMultiChannelCS(header.channels);
break; break;
case PSD.COLOR_MODE_LAB: case PSD.COLOR_MODE_LAB:
cs = "Lab"; cs = "Lab";
@@ -370,7 +370,7 @@ public final class PSDMetadata extends AbstractMetadata {
// TODO: Channels might be 5 for RGB + A + Mask... Probably not correct // TODO: Channels might be 5 for RGB + A + Mask... Probably not correct
node = new IIOMetadataNode("NumChannels"); node = new IIOMetadataNode("NumChannels");
node.setAttribute("value", Integer.toString(mHeader.mChannels)); node.setAttribute("value", Integer.toString(header.channels));
chroma_node.appendChild(node); chroma_node.appendChild(node);
// TODO: Check if this is correct with bitmap (monchrome) // TODO: Check if this is correct with bitmap (monchrome)
@@ -378,7 +378,7 @@ public final class PSDMetadata extends AbstractMetadata {
node.setAttribute("value", "true"); node.setAttribute("value", "true");
chroma_node.appendChild(node); chroma_node.appendChild(node);
if (mHeader.mMode == PSD.COLOR_MODE_INDEXED) { if (header.mode == PSD.COLOR_MODE_INDEXED) {
node = createPaletteNode(); node = createPaletteNode();
chroma_node.appendChild(node); chroma_node.appendChild(node);
} }
@@ -411,7 +411,7 @@ public final class PSDMetadata extends AbstractMetadata {
private IIOMetadataNode createPaletteNode() { private IIOMetadataNode createPaletteNode() {
IIOMetadataNode node = new IIOMetadataNode("Palette"); IIOMetadataNode node = new IIOMetadataNode("Palette");
IndexColorModel cm = mColorData.getIndexColorModel(); IndexColorModel cm = colorData.getIndexColorModel();
for (int i = 0; i < cm.getMapSize(); i++) { for (int i = 0; i < cm.getMapSize(); i++) {
IIOMetadataNode entry = new IIOMetadataNode("PaletteEntry"); IIOMetadataNode entry = new IIOMetadataNode("PaletteEntry");
@@ -442,7 +442,7 @@ public final class PSDMetadata extends AbstractMetadata {
node = new IIOMetadataNode("CompressionTypeName"); node = new IIOMetadataNode("CompressionTypeName");
String compression; String compression;
switch (mCompression) { switch (this.compression) {
case PSD.COMPRESSION_NONE: case PSD.COMPRESSION_NONE:
compression = "none"; compression = "none";
break; break;
@@ -478,13 +478,13 @@ public final class PSDMetadata extends AbstractMetadata {
dataNode.appendChild(node); dataNode.appendChild(node);
node = new IIOMetadataNode("SampleFormat"); node = new IIOMetadataNode("SampleFormat");
node.setAttribute("value", mHeader.mMode == PSD.COLOR_MODE_INDEXED ? "Index" : "UnsignedIntegral"); node.setAttribute("value", header.mode == PSD.COLOR_MODE_INDEXED ? "Index" : "UnsignedIntegral");
dataNode.appendChild(node); dataNode.appendChild(node);
String bitDepth = Integer.toString(mHeader.mBits); // bits per plane String bitDepth = Integer.toString(header.bits); // bits per plane
// TODO: Channels might be 5 for RGB + A + Mask... // TODO: Channels might be 5 for RGB + A + Mask...
String[] bps = new String[mHeader.mChannels]; String[] bps = new String[header.channels];
Arrays.fill(bps, bitDepth); Arrays.fill(bps, bitDepth);
node = new IIOMetadataNode("BitsPerSample"); node = new IIOMetadataNode("BitsPerSample");
@@ -509,7 +509,7 @@ public final class PSDMetadata extends AbstractMetadata {
Iterator<PSDPixelAspectRatio> ratios = getResources(PSDPixelAspectRatio.class); Iterator<PSDPixelAspectRatio> ratios = getResources(PSDPixelAspectRatio.class);
if (ratios.hasNext()) { if (ratios.hasNext()) {
PSDPixelAspectRatio ratio = ratios.next(); PSDPixelAspectRatio ratio = ratios.next();
aspect = (float) ratio.mAspect; aspect = (float) ratio.aspect;
} }
node.setAttribute("value", Float.toString(aspect)); node.setAttribute("value", Float.toString(aspect));
@@ -525,11 +525,11 @@ public final class PSDMetadata extends AbstractMetadata {
PSDResolutionInfo resolutionInfo = resolutionInfos.next(); PSDResolutionInfo resolutionInfo = resolutionInfos.next();
node = new IIOMetadataNode("HorizontalPixelSize"); node = new IIOMetadataNode("HorizontalPixelSize");
node.setAttribute("value", Float.toString(asMM(resolutionInfo.mHResUnit, resolutionInfo.mHRes))); node.setAttribute("value", Float.toString(asMM(resolutionInfo.hResUnit, resolutionInfo.hRes)));
dimensionNode.appendChild(node); dimensionNode.appendChild(node);
node = new IIOMetadataNode("VerticalPixelSize"); node = new IIOMetadataNode("VerticalPixelSize");
node.setAttribute("value", Float.toString(asMM(resolutionInfo.mVResUnit, resolutionInfo.mVRes))); node.setAttribute("value", Float.toString(asMM(resolutionInfo.vResUnit, resolutionInfo.vRes)));
dimensionNode.appendChild(node); dimensionNode.appendChild(node);
} }
@@ -583,7 +583,7 @@ public final class PSDMetadata extends AbstractMetadata {
PSDEXIF1Data data = exif.next(); PSDEXIF1Data data = exif.next();
// Get the EXIF DateTime (aka ModifyDate) tag if present // Get the EXIF DateTime (aka ModifyDate) tag if present
Entry dateTime = data.mDirectory.getEntryById(TIFF.TAG_DATE_TIME); Entry dateTime = data.directory.getEntryById(TIFF.TAG_DATE_TIME);
if (dateTime != null) { if (dateTime != null) {
node = new IIOMetadataNode("ImageCreationTime"); // As TIFF, but could just as well be ImageModificationTime node = new IIOMetadataNode("ImageCreationTime"); // As TIFF, but could just as well be ImageModificationTime
// Format: "YYYY:MM:DD hh:mm:ss" // Format: "YYYY:MM:DD hh:mm:ss"
@@ -629,7 +629,7 @@ public final class PSDMetadata extends AbstractMetadata {
if (textResource instanceof PSDIPTCData) { if (textResource instanceof PSDIPTCData) {
PSDIPTCData iptc = (PSDIPTCData) textResource; PSDIPTCData iptc = (PSDIPTCData) textResource;
appendTextEntriesFlat(text, iptc.mDirectory, new FilterIterator.Filter<Entry>() { appendTextEntriesFlat(text, iptc.directory, new FilterIterator.Filter<Entry>() {
public boolean accept(final Entry pEntry) { public boolean accept(final Entry pEntry) {
Integer tagId = (Integer) pEntry.getIdentifier(); Integer tagId = (Integer) pEntry.getIdentifier();
@@ -645,7 +645,7 @@ public final class PSDMetadata extends AbstractMetadata {
else if (textResource instanceof PSDEXIF1Data) { else if (textResource instanceof PSDEXIF1Data) {
PSDEXIF1Data exif = (PSDEXIF1Data) textResource; PSDEXIF1Data exif = (PSDEXIF1Data) textResource;
appendTextEntriesFlat(text, exif.mDirectory, new FilterIterator.Filter<Entry>() { appendTextEntriesFlat(text, exif.directory, new FilterIterator.Filter<Entry>() {
public boolean accept(final Entry pEntry) { public boolean accept(final Entry pEntry) {
Integer tagId = (Integer) pEntry.getIdentifier(); Integer tagId = (Integer) pEntry.getIdentifier();
@@ -714,14 +714,14 @@ public final class PSDMetadata extends AbstractMetadata {
} }
private boolean hasAlpha() { private boolean hasAlpha() {
return mHeader.mMode == PSD.COLOR_MODE_RGB && mHeader.mChannels >= 4 || return header.mode == PSD.COLOR_MODE_RGB && header.channels >= 4 ||
mHeader.mMode == PSD.COLOR_MODE_CMYK & mHeader.mChannels >= 5; header.mode == PSD.COLOR_MODE_CMYK & header.channels >= 5;
} }
<T extends PSDImageResource> Iterator<T> getResources(final Class<T> pResourceType) { <T extends PSDImageResource> Iterator<T> getResources(final Class<T> pResourceType) {
// NOTE: The cast here is wrong, strictly speaking, but it does not matter... // NOTE: The cast here is wrong, strictly speaking, but it does not matter...
@SuppressWarnings({"unchecked"}) @SuppressWarnings({"unchecked"})
Iterator<T> iterator = (Iterator<T>) mImageResources.iterator(); Iterator<T> iterator = (Iterator<T>) imageResources.iterator();
return new FilterIterator<T>(iterator, new FilterIterator.Filter<T>() { return new FilterIterator<T>(iterator, new FilterIterator.Filter<T>() {
public boolean accept(final T pElement) { public boolean accept(final T pElement) {
@@ -731,12 +731,12 @@ public final class PSDMetadata extends AbstractMetadata {
} }
Iterator<PSDImageResource> getResources(final int... pResourceTypes) { Iterator<PSDImageResource> getResources(final int... pResourceTypes) {
Iterator<PSDImageResource> iterator = mImageResources.iterator(); Iterator<PSDImageResource> iterator = imageResources.iterator();
return new FilterIterator<PSDImageResource>(iterator, new FilterIterator.Filter<PSDImageResource>() { return new FilterIterator<PSDImageResource>(iterator, new FilterIterator.Filter<PSDImageResource>() {
public boolean accept(final PSDImageResource pResource) { public boolean accept(final PSDImageResource pResource) {
for (int type : pResourceTypes) { for (int type : pResourceTypes) {
if (type == pResource.mId) { if (type == pResource.id) {
return true; return true;
} }
} }
@@ -12,8 +12,8 @@ import java.io.IOException;
*/ */
final class PSDPixelAspectRatio extends PSDImageResource { final class PSDPixelAspectRatio extends PSDImageResource {
// 4 bytes (version = 1), 8 bytes double, x / y of a pixel // 4 bytes (version = 1), 8 bytes double, x / y of a pixel
int mVersion; int version;
double mAspect; double aspect;
PSDPixelAspectRatio(final short pId, final ImageInputStream pInput) throws IOException { PSDPixelAspectRatio(final short pId, final ImageInputStream pInput) throws IOException {
super(pId, pInput); super(pId, pInput);
@@ -21,7 +21,7 @@ final class PSDPixelAspectRatio extends PSDImageResource {
@Override @Override
protected void readData(final ImageInputStream pInput) throws IOException { protected void readData(final ImageInputStream pInput) throws IOException {
mVersion = pInput.readInt(); version = pInput.readInt();
mAspect = pInput.readDouble(); aspect = pInput.readDouble();
} }
} }
@@ -11,14 +11,14 @@ import java.io.IOException;
* @version $Id: PSDPrintFlagsInfo.java,v 1.0 Jul 28, 2009 5:16:27 PM haraldk Exp$ * @version $Id: PSDPrintFlagsInfo.java,v 1.0 Jul 28, 2009 5:16:27 PM haraldk Exp$
*/ */
final class PSDPrintFlags extends PSDImageResource { final class PSDPrintFlags extends PSDImageResource {
boolean mLabels; boolean labels;
boolean mCropMasks; boolean cropMasks;
boolean mColorBars; boolean colorBars;
boolean mRegistrationMarks; boolean registrationMarks;
boolean mNegative; boolean negative;
boolean mFlip; boolean flip;
boolean mInterpolate; boolean interpolate;
boolean mCaption; boolean caption;
PSDPrintFlags(final short pId, final ImageInputStream pInput) throws IOException { PSDPrintFlags(final short pId, final ImageInputStream pInput) throws IOException {
super(pId, pInput); super(pId, pInput);
@@ -26,30 +26,30 @@ final class PSDPrintFlags extends PSDImageResource {
@Override @Override
protected void readData(final ImageInputStream pInput) throws IOException { protected void readData(final ImageInputStream pInput) throws IOException {
mLabels = pInput.readBoolean(); labels = pInput.readBoolean();
mCropMasks = pInput.readBoolean(); cropMasks = pInput.readBoolean();
mColorBars = pInput.readBoolean(); colorBars = pInput.readBoolean();
mRegistrationMarks = pInput.readBoolean(); registrationMarks = pInput.readBoolean();
mNegative = pInput.readBoolean(); negative = pInput.readBoolean();
mFlip = pInput.readBoolean(); flip = pInput.readBoolean();
mInterpolate = pInput.readBoolean(); interpolate = pInput.readBoolean();
mCaption = pInput.readBoolean(); caption = pInput.readBoolean();
pInput.skipBytes(mSize - 8); pInput.skipBytes(size - 8);
} }
@Override @Override
public String toString() { public String toString() {
StringBuilder builder = toStringBuilder(); StringBuilder builder = toStringBuilder();
builder.append(", labels: ").append(mLabels); builder.append(", labels: ").append(labels);
builder.append(", crop masks: ").append(mCropMasks); builder.append(", crop masks: ").append(cropMasks);
builder.append(", color bars: ").append(mColorBars); builder.append(", color bars: ").append(colorBars);
builder.append(", registration marks: ").append(mRegistrationMarks); builder.append(", registration marks: ").append(registrationMarks);
builder.append(", negative: ").append(mNegative); builder.append(", negative: ").append(negative);
builder.append(", flip: ").append(mFlip); builder.append(", flip: ").append(flip);
builder.append(", interpolate: ").append(mInterpolate); builder.append(", interpolate: ").append(interpolate);
builder.append(", caption: ").append(mCaption); builder.append(", caption: ").append(caption);
builder.append("]"); builder.append("]");
@@ -11,11 +11,11 @@ import java.io.IOException;
* @version $Id: PSDPrintFlagsInfo.java,v 1.0 Jul 28, 2009 5:16:27 PM haraldk Exp$ * @version $Id: PSDPrintFlagsInfo.java,v 1.0 Jul 28, 2009 5:16:27 PM haraldk Exp$
*/ */
final class PSDPrintFlagsInformation extends PSDImageResource { final class PSDPrintFlagsInformation extends PSDImageResource {
int mVersion; int version;
boolean mCropMasks; boolean cropMasks;
int mField; int field;
long mBleedWidth; long bleedWidth;
int mBleedScale; int bleedScale;
PSDPrintFlagsInformation(final short pId, final ImageInputStream pInput) throws IOException { PSDPrintFlagsInformation(final short pId, final ImageInputStream pInput) throws IOException {
super(pId, pInput); super(pId, pInput);
@@ -23,24 +23,24 @@ final class PSDPrintFlagsInformation extends PSDImageResource {
@Override @Override
protected void readData(final ImageInputStream pInput) throws IOException { protected void readData(final ImageInputStream pInput) throws IOException {
mVersion = pInput.readUnsignedShort(); version = pInput.readUnsignedShort();
mCropMasks = pInput.readBoolean(); cropMasks = pInput.readBoolean();
mField = pInput.readUnsignedByte(); // TODO: Is this really pad? field = pInput.readUnsignedByte(); // TODO: Is this really pad?
mBleedWidth = pInput.readUnsignedInt(); bleedWidth = pInput.readUnsignedInt();
mBleedScale = pInput.readUnsignedShort(); bleedScale = pInput.readUnsignedShort();
pInput.skipBytes(mSize - 10); pInput.skipBytes(size - 10);
} }
@Override @Override
public String toString() { public String toString() {
StringBuilder builder = toStringBuilder(); StringBuilder builder = toStringBuilder();
builder.append(", version: ").append(mVersion); builder.append(", version: ").append(version);
builder.append(", crop masks: ").append(mCropMasks); builder.append(", crop masks: ").append(cropMasks);
builder.append(", field: ").append(mField); builder.append(", field: ").append(field);
builder.append(", bleed width: ").append(mBleedWidth); builder.append(", bleed width: ").append(bleedWidth);
builder.append(", bleed scale: ").append(mBleedScale); builder.append(", bleed scale: ").append(bleedScale);
builder.append("]"); builder.append("]");
@@ -16,10 +16,10 @@ final class PSDPrintScale extends PSDImageResource {
// 4 bytes y location (floating point). // 4 bytes y location (floating point).
// 4 bytes scale (floating point) // 4 bytes scale (floating point)
short mStyle; short style;
float mXLocation; float xLocation;
float mYlocation; float ylocation;
float mScale; float scale;
PSDPrintScale(final short pId, final ImageInputStream pInput) throws IOException { PSDPrintScale(final short pId, final ImageInputStream pInput) throws IOException {
super(pId, pInput); super(pId, pInput);
@@ -27,9 +27,9 @@ final class PSDPrintScale extends PSDImageResource {
@Override @Override
protected void readData(final ImageInputStream pInput) throws IOException { protected void readData(final ImageInputStream pInput) throws IOException {
mStyle = pInput.readShort(); style = pInput.readShort();
mXLocation = pInput.readFloat(); xLocation = pInput.readFloat();
mYlocation = pInput.readFloat(); ylocation = pInput.readFloat();
mScale = pInput.readFloat(); scale = pInput.readFloat();
} }
} }
@@ -50,12 +50,12 @@ 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; float hRes;
short mHResUnit; short hResUnit;
short mWidthUnit; short widthUnit;
float mVRes; float vRes;
short mVResUnit; short vResUnit;
short mHeightUnit; short heightUnit;
PSDResolutionInfo(final short pId, final ImageInputStream pInput) throws IOException { PSDResolutionInfo(final short pId, final ImageInputStream pInput) throws IOException {
super(pId, pInput); super(pId, pInput);
@@ -63,32 +63,32 @@ class PSDResolutionInfo extends PSDImageResource {
@Override @Override
protected void readData(ImageInputStream pInput) throws IOException { protected void readData(ImageInputStream pInput) throws IOException {
if (mSize != 16) { if (size != 16) {
throw new IIOException("Resolution info length expected to be 16: " + mSize); throw new IIOException("Resolution info length expected to be 16: " + size);
} }
mHRes = PSDUtil.fixedPointToFloat(pInput.readInt()); hRes = PSDUtil.fixedPointToFloat(pInput.readInt());
mHResUnit = pInput.readShort(); hResUnit = pInput.readShort();
mWidthUnit = pInput.readShort(); widthUnit = pInput.readShort();
mVRes = PSDUtil.fixedPointToFloat(pInput.readInt()); vRes = PSDUtil.fixedPointToFloat(pInput.readInt());
mVResUnit = pInput.readShort(); vResUnit = pInput.readShort();
mHeightUnit = pInput.readShort(); heightUnit = pInput.readShort();
} }
@Override @Override
public String toString() { public String toString() {
StringBuilder builder = toStringBuilder(); StringBuilder builder = toStringBuilder();
builder.append(", hRes: ").append(mHRes); builder.append(", hRes: ").append(hRes);
builder.append(" "); builder.append(" ");
builder.append(resUnit(mHResUnit)); builder.append(resUnit(hResUnit));
builder.append(", width unit: "); builder.append(", width unit: ");
builder.append(dimUnit(mWidthUnit)); builder.append(dimUnit(widthUnit));
builder.append(", vRes: ").append(mVRes); builder.append(", vRes: ").append(vRes);
builder.append(" "); builder.append(" ");
builder.append(resUnit(mVResUnit)); builder.append(resUnit(vResUnit));
builder.append(", height unit: "); builder.append(", height unit: ");
builder.append(dimUnit(mHeightUnit)); builder.append(dimUnit(heightUnit));
builder.append("]"); builder.append("]");
@@ -16,9 +16,9 @@ import java.io.IOException;
* @version $Id: PSDThumbnail.java,v 1.0 Jul 29, 2009 4:41:06 PM haraldk Exp$ * @version $Id: PSDThumbnail.java,v 1.0 Jul 29, 2009 4:41:06 PM haraldk Exp$
*/ */
class PSDThumbnail extends PSDImageResource { class PSDThumbnail extends PSDImageResource {
private BufferedImage mThumbnail; private BufferedImage thumbnail;
private int mWidth; private int width;
private int mHeight; private int height;
public PSDThumbnail(final short pId, final ImageInputStream pInput) throws IOException { public PSDThumbnail(final short pId, final ImageInputStream pInput) throws IOException {
super(pId, pInput); super(pId, pInput);
@@ -50,8 +50,8 @@ class PSDThumbnail extends PSDImageResource {
throw new IIOException(String.format("Unsupported thumbnail format (%s) in PSD document", format)); throw new IIOException(String.format("Unsupported thumbnail format (%s) in PSD document", format));
} }
mWidth = pInput.readInt(); width = pInput.readInt();
mHeight = pInput.readInt(); height = pInput.readInt();
// This data isn't really useful, unless we're dealing with raw bytes // This data isn't really useful, unless we're dealing with raw bytes
int widthBytes = pInput.readInt(); int widthBytes = pInput.readInt();
@@ -59,7 +59,7 @@ class PSDThumbnail extends PSDImageResource {
// Consistency check // Consistency check
int sizeCompressed = pInput.readInt(); int sizeCompressed = pInput.readInt();
if (sizeCompressed != (mSize - 28)) { if (sizeCompressed != (size - 28)) {
throw new IIOException("Corrupt thumbnail in PSD document"); throw new IIOException("Corrupt thumbnail in PSD document");
} }
@@ -72,26 +72,26 @@ class PSDThumbnail extends PSDImageResource {
// TODO: Defer decoding until getThumbnail? // TODO: Defer decoding until getThumbnail?
// TODO: Support BGR if id == RES_THUMBNAIL_PS4? Or is that already supported in the JPEG? // TODO: Support BGR if id == RES_THUMBNAIL_PS4? Or is that already supported in the JPEG?
mThumbnail = ImageIO.read(IIOUtil.createStreamAdapter(pInput, sizeCompressed)); thumbnail = ImageIO.read(IIOUtil.createStreamAdapter(pInput, sizeCompressed));
} }
public final int getWidth() { public final int getWidth() {
return mWidth; return width;
} }
public final int getHeight() { public final int getHeight() {
return mHeight; return height;
} }
public final BufferedImage getThumbnail() { public final BufferedImage getThumbnail() {
return mThumbnail; return thumbnail;
} }
@Override @Override
public String toString() { public String toString() {
StringBuilder builder = toStringBuilder(); StringBuilder builder = toStringBuilder();
builder.append(", ").append(mThumbnail); builder.append(", ").append(thumbnail);
builder.append("]"); builder.append("]");
@@ -13,7 +13,7 @@ import java.util.List;
* @version $Id: PSDUnicodeAlphaNames.java,v 1.0 Nov 7, 2009 9:16:56 PM haraldk Exp$ * @version $Id: PSDUnicodeAlphaNames.java,v 1.0 Nov 7, 2009 9:16:56 PM haraldk Exp$
*/ */
final class PSDUnicodeAlphaNames extends PSDImageResource { final class PSDUnicodeAlphaNames extends PSDImageResource {
List<String> mNames; List<String> names;
PSDUnicodeAlphaNames(final short pId, final ImageInputStream pInput) throws IOException { PSDUnicodeAlphaNames(final short pId, final ImageInputStream pInput) throws IOException {
super(pId, pInput); super(pId, pInput);
@@ -21,12 +21,12 @@ final class PSDUnicodeAlphaNames extends PSDImageResource {
@Override @Override
protected void readData(final ImageInputStream pInput) throws IOException { protected void readData(final ImageInputStream pInput) throws IOException {
mNames = new ArrayList<String>(); names = new ArrayList<String>();
long left = mSize; long left = size;
while (left > 0) { while (left > 0) {
String name = PSDUtil.readUnicodeString(pInput); String name = PSDUtil.readUnicodeString(pInput);
mNames.add(name); names.add(name);
left -= name.length() * 2 + 4; left -= name.length() * 2 + 4;
} }
} }
@@ -12,11 +12,11 @@ import java.io.IOException;
*/ */
final class PSDVersionInfo extends PSDImageResource { final class PSDVersionInfo extends PSDImageResource {
int mVersion; int version;
boolean mHasRealMergedData; boolean hasRealMergedData;
String mWriter; String writer;
String mReader; String reader;
int mFileVersion; int fileVersion;
PSDVersionInfo(final short pId, final ImageInputStream pInput) throws IOException { PSDVersionInfo(final short pId, final ImageInputStream pInput) throws IOException {
super(pId, pInput); super(pId, pInput);
@@ -32,24 +32,24 @@ final class PSDVersionInfo extends PSDImageResource {
4 bytes file version. 4 bytes file version.
*/ */
mVersion = pInput.readInt(); version = pInput.readInt();
mHasRealMergedData = pInput.readBoolean(); hasRealMergedData = pInput.readBoolean();
mWriter = PSDUtil.readUnicodeString(pInput); writer = PSDUtil.readUnicodeString(pInput);
mReader = PSDUtil.readUnicodeString(pInput); reader = PSDUtil.readUnicodeString(pInput);
mFileVersion = pInput.readInt(); fileVersion = pInput.readInt();
} }
@Override @Override
public String toString() { public String toString() {
StringBuilder builder = toStringBuilder(); StringBuilder builder = toStringBuilder();
builder.append(", version: ").append(mVersion); builder.append(", version: ").append(version);
builder.append(", hasRealMergedData: ").append(mHasRealMergedData); builder.append(", hasRealMergedData: ").append(hasRealMergedData);
builder.append(", writer: ").append(mWriter); builder.append(", writer: ").append(writer);
builder.append(", reader: ").append(mReader); builder.append(", reader: ").append(reader);
builder.append(", file version: ").append(mFileVersion); builder.append(", file version: ").append(fileVersion);
builder.append("]"); builder.append("]");
return builder.toString(); return builder.toString();
@@ -22,8 +22,8 @@ import java.nio.charset.Charset;
* @see <a href="http://www.adobe.com/devnet/xmp/">Adobe XMP Developer Center</a> * @see <a href="http://www.adobe.com/devnet/xmp/">Adobe XMP Developer Center</a>
*/ */
final class PSDXMPData extends PSDImageResource { final class PSDXMPData extends PSDImageResource {
protected byte[] mData; protected byte[] data;
Directory mDirectory; Directory directory;
PSDXMPData(final short pId, final ImageInputStream pInput) throws IOException { PSDXMPData(final short pId, final ImageInputStream pInput) throws IOException {
super(pId, pInput); super(pId, pInput);
@@ -31,21 +31,21 @@ final class PSDXMPData extends PSDImageResource {
@Override @Override
protected void readData(final ImageInputStream pInput) throws IOException { protected void readData(final ImageInputStream pInput) throws IOException {
mData = new byte[(int) mSize]; // TODO: Fix potential overflow, or document why that can't happen (read spec) data = new byte[(int) size]; // TODO: Fix potential overflow, or document why that can't happen (read spec)
//pInput.readFully(mData); //pInput.readFully(data);
mDirectory = new XMPReader().read(pInput); directory = new XMPReader().read(pInput);
} }
@Override @Override
public String toString() { public String toString() {
StringBuilder builder = toStringBuilder(); StringBuilder builder = toStringBuilder();
int length = Math.min(256, mData.length); int length = Math.min(256, data.length);
String data = StringUtil.decode(mData, 0, length, "UTF-8").replace('\n', ' ').replaceAll("\\s+", " "); String data = StringUtil.decode(this.data, 0, length, "UTF-8").replace('\n', ' ').replaceAll("\\s+", " ");
builder.append(", data: \"").append(data); builder.append(", data: \"").append(data);
if (length < mData.length) { if (length < this.data.length) {
builder.append("..."); builder.append("...");
} }
@@ -60,6 +60,6 @@ final class PSDXMPData extends PSDImageResource {
* @return the XMP metadata. * @return the XMP metadata.
*/ */
public Reader getData() { public Reader getData() {
return new InputStreamReader(new ByteArrayInputStream(mData), Charset.forName("UTF-8")); return new InputStreamReader(new ByteArrayInputStream(data), Charset.forName("UTF-8"));
} }
} }
@@ -22,7 +22,7 @@ import java.io.IOException;
public class JPEGImageReaderTestCase extends ImageReaderAbstractTestCase<JPEGImageReader> { public class JPEGImageReaderTestCase extends ImageReaderAbstractTestCase<JPEGImageReader> {
private static final boolean IS_JAVA_6 = SystemUtil.isClassAvailable("java.util.Deque"); private static final boolean IS_JAVA_6 = SystemUtil.isClassAvailable("java.util.Deque");
protected JPEGImageReaderSpi mProvider = new JPEGImageReaderSpi(); protected JPEGImageReaderSpi provider = new JPEGImageReaderSpi();
@Override @Override
protected List<TestData> getTestData() { protected List<TestData> getTestData() {
@@ -33,7 +33,7 @@ public class JPEGImageReaderTestCase extends ImageReaderAbstractTestCase<JPEGIma
@Override @Override
protected ImageReaderSpi createProvider() { protected ImageReaderSpi createProvider() {
return mProvider; return provider;
} }
@Override @Override
@@ -44,7 +44,7 @@ public class JPEGImageReaderTestCase extends ImageReaderAbstractTestCase<JPEGIma
@Override @Override
protected JPEGImageReader createReader() { protected JPEGImageReader createReader() {
try { try {
return (JPEGImageReader) mProvider.createReaderInstance(); return (JPEGImageReader) provider.createReaderInstance();
} }
catch (IOException e) { catch (IOException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
@@ -54,17 +54,17 @@ public class JPEGImageReaderTestCase extends ImageReaderAbstractTestCase<JPEGIma
// These are NOT correct implementations, but I don't really care here // These are NOT correct implementations, but I don't really care here
@Override @Override
protected List<String> getFormatNames() { protected List<String> getFormatNames() {
return Arrays.asList(mProvider.getFormatNames()); return Arrays.asList(provider.getFormatNames());
} }
@Override @Override
protected List<String> getSuffixes() { protected List<String> getSuffixes() {
return Arrays.asList(mProvider.getFileSuffixes()); return Arrays.asList(provider.getFileSuffixes());
} }
@Override @Override
protected List<String> getMIMETypes() { protected List<String> getMIMETypes() {
return Arrays.asList(mProvider.getMIMETypes()); return Arrays.asList(provider.getMIMETypes());
} }
@Override @Override
@@ -19,7 +19,7 @@ import java.util.List;
* @version $Id: PNGImageReaderTestCase.java,v 1.0 Oct 9, 2009 3:37:25 PM haraldk Exp$ * @version $Id: PNGImageReaderTestCase.java,v 1.0 Oct 9, 2009 3:37:25 PM haraldk Exp$
*/ */
public class PNGImageReaderTestCase extends ImageReaderAbstractTestCase<PNGImageReader> { public class PNGImageReaderTestCase extends ImageReaderAbstractTestCase<PNGImageReader> {
protected PNGImageReaderSpi mProvider = new PNGImageReaderSpi(); protected PNGImageReaderSpi provider = new PNGImageReaderSpi();
@Override @Override
protected List<TestData> getTestData() { protected List<TestData> getTestData() {
@@ -30,7 +30,7 @@ public class PNGImageReaderTestCase extends ImageReaderAbstractTestCase<PNGImage
@Override @Override
protected ImageReaderSpi createProvider() { protected ImageReaderSpi createProvider() {
return mProvider; return provider;
} }
@Override @Override
@@ -41,7 +41,7 @@ public class PNGImageReaderTestCase extends ImageReaderAbstractTestCase<PNGImage
@Override @Override
protected PNGImageReader createReader() { protected PNGImageReader createReader() {
try { try {
return (PNGImageReader) mProvider.createReaderInstance(); return (PNGImageReader) provider.createReaderInstance();
} }
catch (IOException e) { catch (IOException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
@@ -51,17 +51,17 @@ public class PNGImageReaderTestCase extends ImageReaderAbstractTestCase<PNGImage
// These are NOT correct implementations, but I don't really care here // These are NOT correct implementations, but I don't really care here
@Override @Override
protected List<String> getFormatNames() { protected List<String> getFormatNames() {
return Arrays.asList(mProvider.getFormatNames()); return Arrays.asList(provider.getFormatNames());
} }
@Override @Override
protected List<String> getSuffixes() { protected List<String> getSuffixes() {
return Arrays.asList(mProvider.getFileSuffixes()); return Arrays.asList(provider.getFileSuffixes());
} }
@Override @Override
protected List<String> getMIMETypes() { protected List<String> getMIMETypes() {
return Arrays.asList(mProvider.getMIMETypes()); return Arrays.asList(provider.getMIMETypes());
} }
@Override @Override
@@ -50,12 +50,12 @@ import java.util.Date;
// TODO: Consider moving this one to io.ole2 // TODO: Consider moving this one to io.ole2
public final class Catalog implements Iterable<Catalog.CatalogItem> { public final class Catalog implements Iterable<Catalog.CatalogItem> {
private final CatalogHeader mHeader; private final CatalogHeader header;
private final CatalogItem[] mItems; private final CatalogItem[] items;
Catalog(final CatalogHeader pHeader, final CatalogItem[] pItems) { Catalog(final CatalogHeader pHeader, final CatalogItem[] pItems) {
mHeader = pHeader; header = pHeader;
mItems = pItems; items = pItems;
} }
/** /**
@@ -95,32 +95,32 @@ public final class Catalog implements Iterable<Catalog.CatalogItem> {
} }
public final int getThumbnailCount() { public final int getThumbnailCount() {
return mHeader.mThumbCount; return header.mThumbCount;
} }
public final int getMaxThumbnailWidth() { public final int getMaxThumbnailWidth() {
return mHeader.mThumbWidth; return header.mThumbWidth;
} }
public final int getMaxThumbnailHeight() { public final int getMaxThumbnailHeight() {
return mHeader.mThumbHeight; return header.mThumbHeight;
} }
final CatalogItem getItem(final int pIndex) { final CatalogItem getItem(final int pIndex) {
return mItems[pIndex]; return items[pIndex];
} }
final CatalogItem getItem(final String pName) { final CatalogItem getItem(final String pName) {
return mItems[getIndex(pName)]; return items[getIndex(pName)];
} }
final int getItemId(final int pIndex) { final int getItemId(final int pIndex) {
return mItems[pIndex].getItemId(); return items[pIndex].getItemId();
} }
public final int getIndex(final String pName) { public final int getIndex(final String pName) {
for (int i = 0; i < mItems.length; i++) { for (int i = 0; i < items.length; i++) {
CatalogItem item = mItems[i]; CatalogItem item = items[i];
if (item.getName().equals(pName)) { if (item.getName().equals(pName)) {
return i; return i;
@@ -139,12 +139,12 @@ public final class Catalog implements Iterable<Catalog.CatalogItem> {
} }
final String getName(int pItemId) { final String getName(int pItemId) {
return mItems[pItemId - 1].getName(); return items[pItemId - 1].getName();
} }
@Override @Override
public String toString() { public String toString() {
return String.format("%s[%s]", getClass().getSimpleName(), mHeader); return String.format("%s[%s]", getClass().getSimpleName(), header);
} }
public Iterator<CatalogItem> iterator() { public Iterator<CatalogItem> iterator() {
@@ -152,11 +152,11 @@ public final class Catalog implements Iterable<Catalog.CatalogItem> {
int mCurrentIdx; int mCurrentIdx;
public boolean hasNext() { public boolean hasNext() {
return mCurrentIdx < mItems.length; return mCurrentIdx < items.length;
} }
public CatalogItem next() { public CatalogItem next() {
return mItems[mCurrentIdx++]; return items[mCurrentIdx++];
} }
public void remove() { public void remove() {
@@ -64,14 +64,14 @@ import java.util.SortedSet;
*/ */
public class ThumbsDBImageReader extends ImageReaderBase { public class ThumbsDBImageReader extends ImageReaderBase {
private static final int THUMBNAIL_OFFSET = 12; private static final int THUMBNAIL_OFFSET = 12;
private Entry mRoot; private Entry root;
private Catalog mCatalog; private Catalog catalog;
private BufferedImage[] mThumbnails; private BufferedImage[] thumbnails;
private final ImageReader mReader; private final ImageReader reader;
private int mCurrentImage = -1; private int currentImage = -1;
private boolean mLoadEagerly; private boolean loadEagerly;
public ThumbsDBImageReader() { public ThumbsDBImageReader() {
this(new ThumbsDBImageReaderSpi()); this(new ThumbsDBImageReaderSpi());
@@ -79,14 +79,14 @@ public class ThumbsDBImageReader extends ImageReaderBase {
protected ThumbsDBImageReader(final ThumbsDBImageReaderSpi pProvider) { protected ThumbsDBImageReader(final ThumbsDBImageReaderSpi pProvider) {
super(pProvider); super(pProvider);
mReader = createJPEGReader(pProvider); reader = createJPEGReader(pProvider);
initReaderListeners(); initReaderListeners();
} }
protected void resetMembers() { protected void resetMembers() {
mRoot = null; root = null;
mCatalog = null; catalog = null;
mThumbnails = null; thumbnails = null;
} }
private static ImageReader createJPEGReader(final ThumbsDBImageReaderSpi pProvider) { private static ImageReader createJPEGReader(final ThumbsDBImageReaderSpi pProvider) {
@@ -94,12 +94,12 @@ public class ThumbsDBImageReader extends ImageReaderBase {
} }
public void dispose() { public void dispose() {
mReader.dispose(); reader.dispose();
super.dispose(); super.dispose();
} }
public boolean isLoadEagerly() { public boolean isLoadEagerly() {
return mLoadEagerly; return loadEagerly;
} }
/** /**
@@ -113,7 +113,7 @@ public class ThumbsDBImageReader extends ImageReaderBase {
* @param pLoadEagerly {@code true} if the reader should read all thumbs on first read * @param pLoadEagerly {@code true} if the reader should read all thumbs on first read
*/ */
public void setLoadEagerly(final boolean pLoadEagerly) { public void setLoadEagerly(final boolean pLoadEagerly) {
mLoadEagerly = pLoadEagerly; loadEagerly = pLoadEagerly;
} }
/** /**
@@ -135,19 +135,19 @@ public class ThumbsDBImageReader extends ImageReaderBase {
// Quick look-up // Quick look-up
BufferedImage image = null; BufferedImage image = null;
if (pIndex < mThumbnails.length) { if (pIndex < thumbnails.length) {
image = mThumbnails[pIndex]; image = thumbnails[pIndex];
} }
if (image == null) { if (image == null) {
// Read the image, it's a JFIF stream, inside the OLE 2 CompoundDocument // Read the image, it's a JFIF stream, inside the OLE 2 CompoundDocument
init(pIndex); init(pIndex);
image = mReader.read(0, pParam); image = reader.read(0, pParam);
mReader.reset(); reader.reset();
if (pParam == null) { if (pParam == null) {
mThumbnails[pIndex] = image; // TODO: Caching is not kosher, as images are mutable!! thumbnails[pIndex] = image; // TODO: Caching is not kosher, as images are mutable!!
} }
} }
else { else {
@@ -193,7 +193,7 @@ public class ThumbsDBImageReader extends ImageReaderBase {
public BufferedImage read(final String pName, final ImageReadParam pParam) throws IOException { public BufferedImage read(final String pName, final ImageReadParam pParam) throws IOException {
initCatalog(); initCatalog();
int index = mCatalog.getIndex(pName); int index = catalog.getIndex(pName);
if (index < 0) { if (index < 0) {
throw new FileNotFoundException("Name not found in \"Catalog\" entry: " + pName); throw new FileNotFoundException("Name not found in \"Catalog\" entry: " + pName);
} }
@@ -203,39 +203,40 @@ public class ThumbsDBImageReader extends ImageReaderBase {
public void abort() { public void abort() {
super.abort(); super.abort();
mReader.abort(); reader.abort();
} }
@Override @Override
public void setInput(Object pInput, boolean pSeekForwardOnly, boolean pIgnoreMetadata) { public void setInput(Object input, boolean seekForwardOnly, boolean ignoreMetadata) {
super.setInput(pInput, pSeekForwardOnly, pIgnoreMetadata); super.setInput(input, seekForwardOnly, ignoreMetadata);
if (imageInput != null) { if (imageInput != null) {
imageInput.setByteOrder(ByteOrder.LITTLE_ENDIAN); imageInput.setByteOrder(ByteOrder.LITTLE_ENDIAN);
} }
} }
private void init(final int pIndex) throws IOException { private void init(final int pIndex) throws IOException {
if (mCurrentImage == -1 || pIndex != mCurrentImage || mReader.getInput() == null) { if (currentImage == -1 || pIndex != currentImage || reader.getInput() == null) {
init(); init();
checkBounds(pIndex); checkBounds(pIndex);
mCurrentImage = pIndex; currentImage = pIndex;
initReader(pIndex); initReader(pIndex);
} }
} }
private void initReader(final int pIndex) throws IOException { private void initReader(final int pIndex) throws IOException {
String name = mCatalog.getStreamName(pIndex); init();
Entry entry = mRoot.getChildEntry(name); String name = catalog.getStreamName(pIndex);
Entry entry = root.getChildEntry(name);
// TODO: It might be possible to speed this up, with less wrapping... // TODO: It might be possible to speed this up, with less wrapping...
// Use in-memory input stream for max speed, images are small // Use in-memory input stream for max speed, images are small
ImageInputStream input = new MemoryCacheImageInputStream(entry.getInputStream()); ImageInputStream input = new MemoryCacheImageInputStream(entry.getInputStream());
input.skipBytes(THUMBNAIL_OFFSET); input.skipBytes(THUMBNAIL_OFFSET);
mReader.setInput(input); reader.setInput(input);
} }
private void initReaderListeners() { private void initReaderListeners() {
mReader.addIIOReadProgressListener(new ProgressListenerBase() { reader.addIIOReadProgressListener(new ProgressListenerBase() {
@Override @Override
public void imageComplete(ImageReader pSource) { public void imageComplete(ImageReader pSource) {
processImageComplete(); processImageComplete();
@@ -243,7 +244,7 @@ public class ThumbsDBImageReader extends ImageReaderBase {
@Override @Override
public void imageStarted(ImageReader pSource, int pImageIndex) { public void imageStarted(ImageReader pSource, int pImageIndex) {
processImageStarted(mCurrentImage); processImageStarted(currentImage);
} }
@Override @Override
@@ -262,66 +263,66 @@ public class ThumbsDBImageReader extends ImageReaderBase {
private void init() throws IOException { private void init() throws IOException {
assertInput(); assertInput();
if (mRoot == null) { if (root == null) {
mRoot = new CompoundDocument(imageInput).getRootEntry(); root = new CompoundDocument(imageInput).getRootEntry();
SortedSet children = mRoot.getChildEntries(); SortedSet children = root.getChildEntries();
mThumbnails = new BufferedImage[children.size() - 1]; thumbnails = new BufferedImage[children.size() - 1];
initCatalog(); initCatalog();
// NOTE: This is usually slower, unless you need all images // NOTE: This is usually slower, unless you need all images
// TODO: Use as many threads as there are CPU cores? :-) // TODO: Use as many threads as there are CPU cores? :-)
if (mLoadEagerly) { if (loadEagerly) {
for (int i = 0; i < mThumbnails.length; i++) { for (int i = 0; i < thumbnails.length; i++) {
initReader(i); initReader(i);
ImageReader reader = mReader; ImageReader reader = this.reader;
// TODO: If stream was detached, we could probably create a // TODO: If stream was detached, we could probably create a
// new reader, then fire this off in a separate thread... // new reader, then fire this off in a separate thread...
mThumbnails[i] = reader.read(0, null); thumbnails[i] = reader.read(0, null);
} }
} }
} }
} }
private void initCatalog() throws IOException { private void initCatalog() throws IOException {
if (mCatalog == null) { if (catalog == null) {
Entry catalog = mRoot.getChildEntry("Catalog"); Entry catalog = root.getChildEntry("Catalog");
if (catalog.length() <= 16L) { if (catalog.length() <= 16L) {
// TODO: Throw exception? Return empty catalog? // TODO: Throw exception? Return empty catalog?
} }
mCatalog = Catalog.read(catalog.getInputStream()); this.catalog = Catalog.read(catalog.getInputStream());
} }
} }
public int getNumImages(boolean pAllowSearch) throws IOException { public int getNumImages(boolean allowSearch) throws IOException {
if (pAllowSearch) { if (allowSearch) {
init(); init();
} }
return mCatalog != null ? mCatalog.getThumbnailCount() : super.getNumImages(false); return catalog != null ? catalog.getThumbnailCount() : super.getNumImages(false);
} }
public int getWidth(int pIndex) throws IOException { public int getWidth(int pIndex) throws IOException {
init(pIndex); init(pIndex);
BufferedImage image = mThumbnails[pIndex]; BufferedImage image = thumbnails[pIndex];
return image != null ? image.getWidth() : mReader.getWidth(0); return image != null ? image.getWidth() : reader.getWidth(0);
} }
public int getHeight(int pIndex) throws IOException { public int getHeight(int pIndex) throws IOException {
init(pIndex); init(pIndex);
BufferedImage image = mThumbnails[pIndex]; BufferedImage image = thumbnails[pIndex];
return image != null ? image.getHeight() : mReader.getHeight(0); return image != null ? image.getHeight() : reader.getHeight(0);
} }
public Iterator<ImageTypeSpecifier> getImageTypes(int pIndex) throws IOException { public Iterator<ImageTypeSpecifier> getImageTypes(int pIndex) throws IOException {
init(pIndex); init(pIndex);
initReader(pIndex); initReader(pIndex);
return mReader.getImageTypes(0); return reader.getImageTypes(0);
} }
public boolean isPresent(final String pFileName) { public boolean isPresent(final String pFileName) {
@@ -344,7 +345,7 @@ public class ThumbsDBImageReader extends ImageReaderBase {
} }
extension = extension.toLowerCase(); extension = extension.toLowerCase();
return !"psd".equals(extension) && !"svg".equals(extension) && mCatalog != null && mCatalog.getIndex(pFileName) != -1; return !"psd".equals(extension) && !"svg".equals(extension) && catalog != null && catalog.getIndex(pFileName) != -1;
} }
/// Test code below /// Test code below
@@ -357,7 +358,7 @@ public class ThumbsDBImageReader extends ImageReaderBase {
if (pArgs.length > 1) { if (pArgs.length > 1) {
long start = System.currentTimeMillis(); long start = System.currentTimeMillis();
reader.init(); reader.init();
for (Catalog.CatalogItem item : reader.mCatalog) { for (Catalog.CatalogItem item : reader.catalog) {
reader.read(item.getName(), null); reader.read(item.getName(), null);
} }
long end = System.currentTimeMillis(); long end = System.currentTimeMillis();
@@ -371,8 +372,8 @@ public class ThumbsDBImageReader extends ImageReaderBase {
long start = System.currentTimeMillis(); long start = System.currentTimeMillis();
reader.init(); reader.init();
for (Catalog.CatalogItem item : reader.mCatalog) { for (Catalog.CatalogItem item : reader.catalog) {
addImage(panel, reader, reader.mCatalog.getIndex(item.getName()), item.getName()); addImage(panel, reader, reader.catalog.getIndex(item.getName()), item.getName());
} }
long end = System.currentTimeMillis(); long end = System.currentTimeMillis();
System.out.println("Time: " + (end - start) + " ms"); System.out.println("Time: " + (end - start) + " ms");
@@ -49,7 +49,7 @@ import java.util.Locale;
* @version $Id: ThumbsDBImageReaderSpi.java,v 1.0 28.feb.2006 19:21:05 haku Exp$ * @version $Id: ThumbsDBImageReaderSpi.java,v 1.0 28.feb.2006 19:21:05 haku Exp$
*/ */
public class ThumbsDBImageReaderSpi extends ImageReaderSpi { public class ThumbsDBImageReaderSpi extends ImageReaderSpi {
private ImageReaderSpi mJPEGProvider; private ImageReaderSpi jpegProvider;
/** /**
* Creates a {@code ThumbsDBImageReaderSpi}. * Creates a {@code ThumbsDBImageReaderSpi}.
@@ -81,7 +81,7 @@ public class ThumbsDBImageReaderSpi extends ImageReaderSpi {
maybeInitJPEGProvider(); maybeInitJPEGProvider();
// If this is a OLE 2 CompoundDocument, we could try... // 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? // TODO: How do we know it's thumbs.db format (structure), without reading quite a lot?
return mJPEGProvider != null && CompoundDocument.canRead(pInput); return jpegProvider != null && CompoundDocument.canRead(pInput);
} }
public ImageReader createReaderInstance(Object extension) throws IOException { public ImageReader createReaderInstance(Object extension) throws IOException {
@@ -98,7 +98,7 @@ public class ThumbsDBImageReaderSpi extends ImageReaderSpi {
// - Class path lookup of properties file with reader? // - Class path lookup of properties file with reader?
// This way we could deregister immediately // This way we could deregister immediately
if (mJPEGProvider == null) { if (jpegProvider == null) {
ImageReaderSpi provider = null; ImageReaderSpi provider = null;
try { try {
Iterator<ImageReaderSpi> providers = getJPEGProviders(); Iterator<ImageReaderSpi> providers = getJPEGProviders();
@@ -117,7 +117,7 @@ public class ThumbsDBImageReaderSpi extends ImageReaderSpi {
// In any case, we deregister the provider if there isn't one // In any case, we deregister the provider if there isn't one
IIORegistry.getDefaultInstance().deregisterServiceProvider(this, ImageReaderSpi.class); IIORegistry.getDefaultInstance().deregisterServiceProvider(this, ImageReaderSpi.class);
} }
mJPEGProvider = provider; jpegProvider = provider;
} }
} }
@@ -149,12 +149,12 @@ public class ThumbsDBImageReaderSpi extends ImageReaderSpi {
*/ */
ImageReader createJPEGReader() { ImageReader createJPEGReader() {
maybeInitJPEGProvider(); maybeInitJPEGProvider();
if (mJPEGProvider == null) { if (jpegProvider == null) {
throw new IllegalStateException("No suitable JPEG reader provider found"); throw new IllegalStateException("No suitable JPEG reader provider found");
} }
try { try {
return mJPEGProvider.createReaderInstance(); return jpegProvider.createReaderInstance();
} }
catch (IOException e) { catch (IOException e) {
// NOTE: The default Sun version never throws IOException here // NOTE: The default Sun version never throws IOException here
@@ -170,7 +170,7 @@ public class ThumbsDBImageReaderSpi extends ImageReaderSpi {
// public void onRegistration(ServiceRegistry registry, Class<?> category) { // public void onRegistration(ServiceRegistry registry, Class<?> category) {
// System.out.println("ThumbsDBImageReaderSpi.onRegistration"); // System.out.println("ThumbsDBImageReaderSpi.onRegistration");
// maybeInitJPEGProvider(); // maybeInitJPEGProvider();
// if (mJPEGProvider == null) { // if (jpegProvider == null) {
// System.out.println("Deregistering"); // System.out.println("Deregistering");
// registry.deregisterServiceProvider(this, ImageReaderSpi.class); // registry.deregisterServiceProvider(this, ImageReaderSpi.class);
// } // }