diff --git a/imageio/imageio-batik/src/main/java/com/twelvemonkeys/imageio/plugins/svg/SVGImageReader.java b/imageio/imageio-batik/src/main/java/com/twelvemonkeys/imageio/plugins/svg/SVGImageReader.java
index ec0bd874..8a4ea85d 100755
--- a/imageio/imageio-batik/src/main/java/com/twelvemonkeys/imageio/plugins/svg/SVGImageReader.java
+++ b/imageio/imageio-batik/src/main/java/com/twelvemonkeys/imageio/plugins/svg/SVGImageReader.java
@@ -98,8 +98,8 @@ public class SVGImageReader extends ImageReaderBase {
public void setInput(Object pInput, boolean pSeekForwardOnly, boolean pIgnoreMetadata) {
super.setInput(pInput, pSeekForwardOnly, pIgnoreMetadata);
- if (mImageInput != null) {
- TranscoderInput input = new TranscoderInput(IIOUtil.createStreamAdapter(mImageInput));
+ if (imageInput != null) {
+ TranscoderInput input = new TranscoderInput(IIOUtil.createStreamAdapter(imageInput));
mRasterizer.setInput(input);
}
}
diff --git a/imageio/imageio-batik/src/main/java/com/twelvemonkeys/imageio/plugins/tiff/TIFFImageReader.java b/imageio/imageio-batik/src/main/java/com/twelvemonkeys/imageio/plugins/tiff/TIFFImageReader.java
index caab3b4c..3eebd02d 100755
--- a/imageio/imageio-batik/src/main/java/com/twelvemonkeys/imageio/plugins/tiff/TIFFImageReader.java
+++ b/imageio/imageio-batik/src/main/java/com/twelvemonkeys/imageio/plugins/tiff/TIFFImageReader.java
@@ -137,25 +137,25 @@ public class TIFFImageReader extends ImageReaderBase {
private synchronized void init() {
if (mDecoder == null) {
- if (mImageInput == null) {
+ if (imageInput == null) {
throw new IllegalStateException("input == null");
}
mDecoder = new TIFFImageDecoder(new SeekableStream() {
public int read() throws IOException {
- return mImageInput.read();
+ return imageInput.read();
}
public int read(final byte[] pBytes, final int pStart, final int pLength) throws IOException {
- return mImageInput.read(pBytes, pStart, pLength);
+ return imageInput.read(pBytes, pStart, pLength);
}
public long getFilePointer() throws IOException {
- return mImageInput.getStreamPosition();
+ return imageInput.getStreamPosition();
}
public void seek(final long pPos) throws IOException {
- mImageInput.seek(pPos);
+ imageInput.seek(pPos);
}
}, null);
}
diff --git a/imageio/imageio-batik/src/main/java/com/twelvemonkeys/imageio/plugins/tiff/TIFFImageWriter.java b/imageio/imageio-batik/src/main/java/com/twelvemonkeys/imageio/plugins/tiff/TIFFImageWriter.java
index 212dc2f4..ccf33c48 100755
--- a/imageio/imageio-batik/src/main/java/com/twelvemonkeys/imageio/plugins/tiff/TIFFImageWriter.java
+++ b/imageio/imageio-batik/src/main/java/com/twelvemonkeys/imageio/plugins/tiff/TIFFImageWriter.java
@@ -124,7 +124,7 @@ public class TIFFImageWriter extends ImageWriterBase {
processImageStarted(0);
mEncoder.encode(image);
- mImageOutput.flush();
+ imageOutput.flush();
processImageComplete();
}
@@ -136,10 +136,10 @@ public class TIFFImageWriter extends ImageWriterBase {
private synchronized void init() {
if (mEncoder == null) {
- if (mImageOutput == null) {
+ if (imageOutput == null) {
throw new IllegalStateException("output == null");
}
- mEncoder = new TIFFImageEncoder(IIOUtil.createStreamAdapter(mImageOutput), null);
+ mEncoder = new TIFFImageEncoder(IIOUtil.createStreamAdapter(imageOutput), null);
}
}
}
diff --git a/imageio/imageio-batik/src/main/java/com/twelvemonkeys/imageio/plugins/wmf/WMFImageReader.java b/imageio/imageio-batik/src/main/java/com/twelvemonkeys/imageio/plugins/wmf/WMFImageReader.java
index 9f78ed5c..96b4c6f8 100755
--- a/imageio/imageio-batik/src/main/java/com/twelvemonkeys/imageio/plugins/wmf/WMFImageReader.java
+++ b/imageio/imageio-batik/src/main/java/com/twelvemonkeys/imageio/plugins/wmf/WMFImageReader.java
@@ -88,7 +88,7 @@ public class WMFImageReader extends ImageReaderBase {
private synchronized void init() throws IOException {
// Need the extra test, to avoid throwing an IOException from the Transcoder
- if (mImageInput == null) {
+ if (imageInput == null) {
throw new IllegalStateException("input == null");
}
@@ -98,7 +98,7 @@ public class WMFImageReader extends ImageReaderBase {
ByteArrayOutputStream output = new ByteArrayOutputStream();
Writer writer = new OutputStreamWriter(output, "UTF8");
try {
- TranscoderInput in = new TranscoderInput(IIOUtil.createStreamAdapter(mImageInput));
+ TranscoderInput in = new TranscoderInput(IIOUtil.createStreamAdapter(imageInput));
TranscoderOutput out = new TranscoderOutput(writer);
// TODO: Transcodinghints?
diff --git a/imageio/imageio-core/src/main/java/com/twelvemonkeys/imageio/ImageReaderBase.java b/imageio/imageio-core/src/main/java/com/twelvemonkeys/imageio/ImageReaderBase.java
index 4646bf48..4b1bed97 100644
--- a/imageio/imageio-core/src/main/java/com/twelvemonkeys/imageio/ImageReaderBase.java
+++ b/imageio/imageio-core/src/main/java/com/twelvemonkeys/imageio/ImageReaderBase.java
@@ -37,9 +37,7 @@ import javax.imageio.spi.ImageReaderSpi;
import javax.imageio.stream.ImageInputStream;
import javax.swing.*;
import java.awt.*;
-import java.awt.event.ActionEvent;
-import java.awt.event.MouseAdapter;
-import java.awt.event.MouseEvent;
+import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.awt.image.IndexColorModel;
import java.io.File;
@@ -61,7 +59,7 @@ public abstract class ImageReaderBase extends ImageReader {
* For convenience. Only set if the input is an {@code ImageInputStream}.
* @see #setInput(Object, boolean, boolean)
*/
- protected ImageInputStream mImageInput;
+ protected ImageInputStream imageInput;
/**
* Constructs an {@code ImageReader} and sets its
@@ -102,7 +100,7 @@ public abstract class ImageReaderBase extends ImageReader {
resetMembers();
super.setInput(pInput, pSeekForwardOnly, pIgnoreMetadata);
if (pInput instanceof ImageInputStream) {
- mImageInput = (ImageInputStream) pInput;
+ imageInput = (ImageInputStream) pInput;
}
}
@@ -229,7 +227,7 @@ public abstract class ImageReaderBase extends ImageReader {
if (dest != null) {
boolean found = false;
- // NOTE: This is bad, as it relies on implementation details of super method...
+ // NOTE: This is bad, as it relies on implementation details of "super" method...
// We know that the iterator has not been touched if explicit destination..
while (pTypes.hasNext()) {
ImageTypeSpecifier specifier = pTypes.next();
@@ -318,7 +316,27 @@ public abstract class ImageReaderBase extends ImageReader {
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
JFrame frame = new JFrame(pTitle);
- frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+
+ frame.getRootPane().getActionMap().put("window-close", new AbstractAction() {
+ public void actionPerformed(ActionEvent e) {
+ Window window = SwingUtilities.getWindowAncestor((Component) e.getSource());
+ window.setVisible(false);
+ window.dispose();
+ }
+ });
+ frame.getRootPane().getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_W, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()), "window-close");
+
+ frame.addWindowListener(new WindowAdapter() {
+ @Override
+ public void windowClosed(WindowEvent e) {
+ Window[] windows = Window.getWindows();
+ if (windows == null || windows.length == 0) {
+ System.exit(0);
+ }
+ }
+ });
+ frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
+
frame.setLocationByPlatform(true);
JPanel pane = new JPanel(new BorderLayout());
JScrollPane scroll = new JScrollPane(new ImageLabel(pImage));
@@ -338,6 +356,10 @@ public abstract class ImageReaderBase extends ImageReader {
}
}
+ protected static boolean hasExplicitDestination(final ImageReadParam pParam) {
+ return (pParam != null && (pParam.getDestination() != null || pParam.getDestinationType() != null || pParam.getDestinationOffset() != null));
+ }
+
private static class ImageLabel extends JLabel {
Paint mBackground;
diff --git a/imageio/imageio-core/src/main/java/com/twelvemonkeys/imageio/ImageWriterBase.java b/imageio/imageio-core/src/main/java/com/twelvemonkeys/imageio/ImageWriterBase.java
index 8c60c2d2..5f18b336 100755
--- a/imageio/imageio-core/src/main/java/com/twelvemonkeys/imageio/ImageWriterBase.java
+++ b/imageio/imageio-core/src/main/java/com/twelvemonkeys/imageio/ImageWriterBase.java
@@ -52,7 +52,7 @@ public abstract class ImageWriterBase extends ImageWriter {
* For convenience. Only set if the output is an {@code ImageInputStream}.
* @see #setOutput(Object)
*/
- protected ImageOutputStream mImageOutput;
+ protected ImageOutputStream imageOutput;
/**
* Constructs an {@code ImageWriter} and sets its
@@ -80,7 +80,7 @@ public abstract class ImageWriterBase extends ImageWriter {
super.setOutput(pOutput);
if (pOutput instanceof ImageOutputStream) {
- mImageOutput = (ImageOutputStream) pOutput;
+ imageOutput = (ImageOutputStream) pOutput;
}
}
diff --git a/imageio/imageio-core/src/main/java/com/twelvemonkeys/imageio/spi/ProviderInfo.java b/imageio/imageio-core/src/main/java/com/twelvemonkeys/imageio/spi/ProviderInfo.java
index f9deb312..f78bbbe5 100644
--- a/imageio/imageio-core/src/main/java/com/twelvemonkeys/imageio/spi/ProviderInfo.java
+++ b/imageio/imageio-core/src/main/java/com/twelvemonkeys/imageio/spi/ProviderInfo.java
@@ -16,9 +16,9 @@ public class ProviderInfo {
// TODO: Consider reading the META-INF/MANIFEST.MF from the class path using java.util.jar.Manifest.
// Use the manifest that is located in the same class path folder as the package.
- private final String mTitle;
- private final String mVendorName;
- private final String mVersion;
+ private final String title;
+ private final String vendorName;
+ private final String version;
/**
* Creates a provider information instance based on the given package.
@@ -32,13 +32,13 @@ public class ProviderInfo {
Validate.notNull(pPackage, "package");
String title = pPackage.getImplementationTitle();
- mTitle = title != null ? title : pPackage.getName();
+ this.title = title != null ? title : pPackage.getName();
String vendor = pPackage.getImplementationVendor();
- mVendorName = vendor != null ? vendor : fakeVendor(pPackage);
+ vendorName = vendor != null ? vendor : fakeVendor(pPackage);
String version = pPackage.getImplementationVersion();
- mVersion = version != null ? version : fakeVersion(pPackage);
+ this.version = version != null ? version : fakeVersion(pPackage);
}
private static String fakeVendor(final Package pPackage) {
@@ -60,7 +60,7 @@ public class ProviderInfo {
* @return the implementation title
*/
final String getImplementationTitle() {
- return mTitle;
+ return title;
}
/**
@@ -72,7 +72,7 @@ public class ProviderInfo {
* @return the vendor name.
*/
public final String getVendorName() {
- return mVendorName;
+ return vendorName;
}
/**
@@ -83,11 +83,11 @@ public class ProviderInfo {
* @return the vendor name.
*/
public final String getVersion() {
- return mVersion;
+ return version;
}
@Override
public String toString() {
- return mTitle + ", " + mVersion + " by " + mVendorName;
+ return title + ", " + version + " by " + vendorName;
}
}
diff --git a/imageio/imageio-core/src/main/java/com/twelvemonkeys/imageio/stream/BufferedImageInputStream.java b/imageio/imageio-core/src/main/java/com/twelvemonkeys/imageio/stream/BufferedImageInputStream.java
index 9c75baa2..221a22ba 100644
--- a/imageio/imageio-core/src/main/java/com/twelvemonkeys/imageio/stream/BufferedImageInputStream.java
+++ b/imageio/imageio-core/src/main/java/com/twelvemonkeys/imageio/stream/BufferedImageInputStream.java
@@ -23,12 +23,12 @@ public final class BufferedImageInputStream extends ImageInputStreamImpl impleme
static final int DEFAULT_BUFFER_SIZE = 8192;
- private ImageInputStream mStream;
+ private ImageInputStream stream;
- private byte[] mBuffer;
- private long mBufferStart = 0;
- private int mBufferPos = 0;
- private int mBufferLength = 0;
+ private byte[] buffer;
+ private long bufferStart = 0;
+ private int bufferPos = 0;
+ private int bufferLength = 0;
public BufferedImageInputStream(final ImageInputStream pStream) throws IOException {
this(pStream, DEFAULT_BUFFER_SIZE);
@@ -37,19 +37,19 @@ public final class BufferedImageInputStream extends ImageInputStreamImpl impleme
private BufferedImageInputStream(final ImageInputStream pStream, final int pBufferSize) throws IOException {
Validate.notNull(pStream, "stream");
- mStream = pStream;
+ stream = pStream;
streamPos = pStream.getStreamPosition();
- mBuffer = new byte[pBufferSize];
+ buffer = new byte[pBufferSize];
}
private void fillBuffer() throws IOException {
- mBufferStart = streamPos;
- mBufferLength = mStream.read(mBuffer, 0, mBuffer.length);
- mBufferPos = 0;
+ bufferStart = streamPos;
+ bufferLength = stream.read(buffer, 0, buffer.length);
+ bufferPos = 0;
}
private boolean isBufferValid() throws IOException {
- return mBufferPos < mBufferLength && mBufferStart == mStream.getStreamPosition() - mBufferLength;
+ return bufferPos < bufferLength && bufferStart == stream.getStreamPosition() - bufferLength;
}
@Override
@@ -58,14 +58,14 @@ public final class BufferedImageInputStream extends ImageInputStreamImpl impleme
fillBuffer();
}
- if (mBufferLength <= 0) {
+ if (bufferLength <= 0) {
return -1;
}
bitOffset = 0;
streamPos++;
- return mBuffer[mBufferPos++] & 0xff;
+ return buffer[bufferPos++] & 0xff;
}
@Override
@@ -74,7 +74,7 @@ public final class BufferedImageInputStream extends ImageInputStreamImpl impleme
if (!isBufferValid()) {
// Bypass cache if cache is empty for reads longer than buffer
- if (pLength >= mBuffer.length) {
+ if (pLength >= buffer.length) {
return readDirect(pBuffer, pOffset, pLength);
}
else {
@@ -87,30 +87,30 @@ public final class BufferedImageInputStream extends ImageInputStreamImpl impleme
private int readDirect(final byte[] pBuffer, final int pOffset, final int pLength) throws IOException {
// TODO: Figure out why reading more than the buffer length causes alignment issues...
- int read = mStream.read(pBuffer, pOffset, Math.min(mBuffer.length, pLength));
+ int read = stream.read(pBuffer, pOffset, Math.min(buffer.length, pLength));
if (read > 0) {
streamPos += read;
}
- mBufferStart = mStream.getStreamPosition();
- mBufferLength = 0;
+ bufferStart = stream.getStreamPosition();
+ bufferLength = 0;
return read;
}
private int readBuffered(final byte[] pBuffer, final int pOffset, final int pLength) {
- if (mBufferLength <= 0) {
+ if (bufferLength <= 0) {
return -1;
}
// Read as much as possible from buffer
- int length = Math.min(mBufferLength - mBufferPos, pLength);
+ int length = Math.min(bufferLength - bufferPos, pLength);
if (length > 0) {
- System.arraycopy(mBuffer, mBufferPos, pBuffer, pOffset, length);
- mBufferPos += length;
+ System.arraycopy(buffer, bufferPos, pBuffer, pOffset, length);
+ bufferPos += length;
}
streamPos += length;
@@ -121,42 +121,42 @@ public final class BufferedImageInputStream extends ImageInputStreamImpl impleme
@Override
public void seek(long pPosition) throws IOException {
// TODO: Could probably be optimized to not invalidate buffer if new position is within current buffer
- mStream.seek(pPosition);
- mBufferLength = 0; // Will invalidate buffer
- streamPos = mStream.getStreamPosition();
+ stream.seek(pPosition);
+ bufferLength = 0; // Will invalidate buffer
+ streamPos = stream.getStreamPosition();
}
@Override
public void flushBefore(long pos) throws IOException {
- mStream.flushBefore(pos);
+ stream.flushBefore(pos);
}
@Override
public long getFlushedPosition() {
- return mStream.getFlushedPosition();
+ return stream.getFlushedPosition();
}
@Override
public boolean isCached() {
- return mStream.isCached();
+ return stream.isCached();
}
@Override
public boolean isCachedMemory() {
- return mStream.isCachedMemory();
+ return stream.isCachedMemory();
}
@Override
public boolean isCachedFile() {
- return mStream.isCachedFile();
+ return stream.isCachedFile();
}
@Override
public void close() throws IOException {
- if (mStream != null) {
- //mStream.close();
- mStream = null;
- mBuffer = null;
+ if (stream != null) {
+ //stream.close();
+ stream = null;
+ buffer = null;
}
super.close();
}
@@ -170,7 +170,7 @@ public final class BufferedImageInputStream extends ImageInputStreamImpl impleme
public long length() {
// WTF?! This method is allowed to throw IOException in the interface...
try {
- return mStream.length();
+ return stream.length();
}
catch (IOException ignore) {
}
diff --git a/imageio/imageio-core/src/main/java/com/twelvemonkeys/imageio/stream/ByteArrayImageInputStream.java b/imageio/imageio-core/src/main/java/com/twelvemonkeys/imageio/stream/ByteArrayImageInputStream.java
index 1c2119df..b4feb8bf 100755
--- a/imageio/imageio-core/src/main/java/com/twelvemonkeys/imageio/stream/ByteArrayImageInputStream.java
+++ b/imageio/imageio-core/src/main/java/com/twelvemonkeys/imageio/stream/ByteArrayImageInputStream.java
@@ -13,35 +13,39 @@ import java.io.IOException;
* @version $Id: ByteArrayImageInputStream.java,v 1.0 May 15, 2008 2:12:12 PM haraldk Exp$
*/
public final class ByteArrayImageInputStream extends ImageInputStreamImpl {
- private final byte[] mData;
+ private final byte[] data;
public ByteArrayImageInputStream(final byte[] pData) {
Validate.notNull(pData, "data");
- mData = pData;
+ data = pData;
}
public int read() throws IOException {
- if (streamPos >= mData.length) {
+ if (streamPos >= data.length) {
return -1;
}
+
bitOffset = 0;
- return mData[((int) streamPos++)] & 0xff;
+
+ return data[((int) streamPos++)] & 0xff;
}
public int read(byte[] pBuffer, int pOffset, int pLength) throws IOException {
- if (streamPos >= mData.length) {
+ if (streamPos >= data.length) {
return -1;
}
- int length = (int) Math.min(mData.length - streamPos, pLength);
+
+ int length = (int) Math.min(data.length - streamPos, pLength);
bitOffset = 0;
- System.arraycopy(mData, (int) streamPos, pBuffer, pOffset, length);
+ System.arraycopy(data, (int) streamPos, pBuffer, pOffset, length);
streamPos += length;
+
return length;
}
@Override
public long length() {
- return mData.length;
+ return data.length;
}
@Override
diff --git a/imageio/imageio-core/src/main/java/com/twelvemonkeys/imageio/stream/SubImageInputStream.java b/imageio/imageio-core/src/main/java/com/twelvemonkeys/imageio/stream/SubImageInputStream.java
index 2c4ce03c..46600aa3 100644
--- a/imageio/imageio-core/src/main/java/com/twelvemonkeys/imageio/stream/SubImageInputStream.java
+++ b/imageio/imageio-core/src/main/java/com/twelvemonkeys/imageio/stream/SubImageInputStream.java
@@ -16,9 +16,9 @@ import java.io.IOException;
public final class SubImageInputStream extends ImageInputStreamImpl {
// NOTE: This class is based on com.sun.imageio.plugins.common.SubImageInputStream, but fixes some of its bugs.
- private final ImageInputStream mStream;
- private final long mStartPos;
- private final long mLength;
+ private final ImageInputStream stream;
+ private final long startPos;
+ private final long length;
/**
* Creates a {@link ImageInputStream}, reading up to a maximum number of bytes from the underlying stream.
@@ -32,21 +32,19 @@ public final class SubImageInputStream extends ImageInputStreamImpl {
*/
public SubImageInputStream(final ImageInputStream pStream, final long pLength) throws IOException {
Validate.notNull(pStream, "stream");
- if (pLength < 0) {
- throw new IllegalArgumentException("length < 0");
- }
+ Validate.isTrue(pLength >= 0, pLength, "length < 0: %d");
- mStream = pStream;
- mStartPos = pStream.getStreamPosition();
- mLength = pLength;
+ stream = pStream;
+ startPos = pStream.getStreamPosition();
+ length = pLength;
}
public int read() throws IOException {
- if (streamPos >= mLength) { // Local EOF
+ if (streamPos >= length) { // Local EOF
return -1;
}
else {
- int read = mStream.read();
+ int read = stream.read();
if (read >= 0) {
streamPos++;
@@ -57,13 +55,13 @@ public final class SubImageInputStream extends ImageInputStreamImpl {
}
public int read(final byte[] pBytes, final int pOffset, final int pLength) throws IOException {
- if (streamPos >= mLength) { // Local EOF
+ if (streamPos >= length) { // Local EOF
return -1;
}
// Safe cast, as pLength can never cause int overflow
- int length = (int) Math.min(pLength, mLength - streamPos);
- int count = mStream.read(pBytes, pOffset, length);
+ int length = (int) Math.min(pLength, this.length - streamPos);
+ int count = stream.read(pBytes, pOffset, length);
if (count >= 0) {
streamPos += count;
@@ -75,8 +73,8 @@ public final class SubImageInputStream extends ImageInputStreamImpl {
@Override
public long length() {
try {
- long length = mStream.length();
- return length < 0 ? -1 : Math.min(length - mStartPos, mLength);
+ long length = stream.length();
+ return length < 0 ? -1 : Math.min(length - startPos, this.length);
}
catch (IOException ignore) {
}
@@ -90,7 +88,7 @@ public final class SubImageInputStream extends ImageInputStreamImpl {
throw new IndexOutOfBoundsException("pos < flushedPosition");
}
- mStream.seek(mStartPos + pPosition);
+ stream.seek(startPos + pPosition);
streamPos = pPosition;
}
diff --git a/imageio/imageio-core/src/main/java/com/twelvemonkeys/imageio/util/IIOInputStreamAdapter.java b/imageio/imageio-core/src/main/java/com/twelvemonkeys/imageio/util/IIOInputStreamAdapter.java
index 1941efff..be74f179 100755
--- a/imageio/imageio-core/src/main/java/com/twelvemonkeys/imageio/util/IIOInputStreamAdapter.java
+++ b/imageio/imageio-core/src/main/java/com/twelvemonkeys/imageio/util/IIOInputStreamAdapter.java
@@ -43,10 +43,10 @@ import java.io.InputStream;
* @version $Id: IIOInputStreamAdapter.java,v 1.0 Sep 26, 2007 11:35:59 AM haraldk Exp$
*/
class IIOInputStreamAdapter extends InputStream {
- private ImageInputStream mInput;
- private final boolean mHasLength;
- private long mLeft;
- private long mMarkPosition;
+ private ImageInputStream input;
+ private final boolean hasLength;
+ private long left;
+ private long markPosition;
// TODO: Enforce stream boundaries!
// TODO: Stream start position....
@@ -82,9 +82,9 @@ class IIOInputStreamAdapter extends InputStream {
throw new IllegalArgumentException("length < 0");
}
- mInput = pInput;
- mHasLength = pHasLength;
- mLeft = pLength;
+ input = pInput;
+ hasLength = pHasLength;
+ left = pLength;
}
@@ -93,17 +93,17 @@ class IIOInputStreamAdapter extends InputStream {
* This implementation does not close the underlying stream.
*/
public void close() throws IOException {
- if (mHasLength) {
- mInput.seek(mInput.getStreamPosition() + mLeft);
+ if (hasLength) {
+ input.seek(input.getStreamPosition() + left);
}
- mLeft = 0;
- mInput = null;
+ left = 0;
+ input = null;
}
public int available() throws IOException {
- if (mHasLength) {
- return mLeft > 0 ? (int) Math.min(Integer.MAX_VALUE, mLeft) : 0;
+ if (hasLength) {
+ return left > 0 ? (int) Math.min(Integer.MAX_VALUE, left) : 0;
}
return 0; // We don't really know, so we say 0 to be safe.
}
@@ -115,7 +115,7 @@ class IIOInputStreamAdapter extends InputStream {
public void mark(int pReadLimit) {
try {
- mMarkPosition = mInput.getStreamPosition();
+ markPosition = input.getStreamPosition();
}
catch (IOException e) {
// Let's hope this never happens, because it's not possible to reset then...
@@ -124,17 +124,17 @@ class IIOInputStreamAdapter extends InputStream {
}
public void reset() throws IOException {
- long diff = mInput.getStreamPosition() - mMarkPosition;
- mInput.seek(mMarkPosition);
- mLeft += diff;
+ long diff = input.getStreamPosition() - markPosition;
+ input.seek(markPosition);
+ left += diff;
}
public int read() throws IOException {
- if (mHasLength && mLeft-- <= 0) {
- mLeft = 0;
+ if (hasLength && left-- <= 0) {
+ left = 0;
return -1;
}
- return mInput.read();
+ return input.read();
}
public final int read(byte[] pBytes) throws IOException {
@@ -142,13 +142,13 @@ class IIOInputStreamAdapter extends InputStream {
}
public int read(final byte[] pBytes, final int pOffset, final int pLength) throws IOException {
- if (mHasLength && mLeft <= 0) {
+ if (hasLength && left <= 0) {
return -1;
}
- int read = mInput.read(pBytes, pOffset, (int) findMaxLen(pLength));
- if (mHasLength) {
- mLeft = read < 0 ? 0 : mLeft - read;
+ int read = input.read(pBytes, pOffset, (int) findMaxLen(pLength));
+ if (hasLength) {
+ left = read < 0 ? 0 : left - read;
}
return read;
}
@@ -161,8 +161,8 @@ class IIOInputStreamAdapter extends InputStream {
* @return the maximum number of bytes to read
*/
private long findMaxLen(long pLength) {
- if (mHasLength && mLeft < pLength) {
- return Math.max(mLeft, 0);
+ if (hasLength && left < pLength) {
+ return Math.max(left, 0);
}
else {
return Math.max(pLength, 0);
@@ -170,8 +170,8 @@ class IIOInputStreamAdapter extends InputStream {
}
public long skip(long pLength) throws IOException {
- long skipped = mInput.skipBytes(findMaxLen(pLength)); // Skips 0 or more, never -1
- mLeft -= skipped;
+ long skipped = input.skipBytes(findMaxLen(pLength)); // Skips 0 or more, never -1
+ left -= skipped;
return skipped;
}
}
diff --git a/imageio/imageio-core/src/main/java/com/twelvemonkeys/imageio/util/IIOOutputStreamAdapter.java b/imageio/imageio-core/src/main/java/com/twelvemonkeys/imageio/util/IIOOutputStreamAdapter.java
index 9927b983..38a3031f 100755
--- a/imageio/imageio-core/src/main/java/com/twelvemonkeys/imageio/util/IIOOutputStreamAdapter.java
+++ b/imageio/imageio-core/src/main/java/com/twelvemonkeys/imageio/util/IIOOutputStreamAdapter.java
@@ -40,34 +40,34 @@ import java.io.OutputStream;
* @version $Id: IIOOutputStreamAdapter.java,v 1.0 Sep 26, 2007 11:50:38 AM haraldk Exp$
*/
class IIOOutputStreamAdapter extends OutputStream {
- private ImageOutputStream mOutput;
+ private ImageOutputStream output;
public IIOOutputStreamAdapter(final ImageOutputStream pOutput) {
- mOutput = pOutput;
+ output = pOutput;
}
@Override
public void write(final byte[] pBytes) throws IOException {
- mOutput.write(pBytes);
+ output.write(pBytes);
}
@Override
public void write(final byte[] pBytes, final int pOffset, final int pLength) throws IOException {
- mOutput.write(pBytes, pOffset, pLength);
+ output.write(pBytes, pOffset, pLength);
}
@Override
public void write(final int pByte) throws IOException {
- mOutput.write(pByte);
+ output.write(pByte);
}
@Override
public void flush() throws IOException {
- mOutput.flush();
+ output.flush();
}
@Override
public void close() throws IOException {
- mOutput = null;
+ output = null;
}
}
diff --git a/imageio/imageio-core/src/main/java/com/twelvemonkeys/imageio/util/ReaderFileSuffixFilter.java b/imageio/imageio-core/src/main/java/com/twelvemonkeys/imageio/util/ReaderFileSuffixFilter.java
index bdad8e28..e94b61b0 100755
--- a/imageio/imageio-core/src/main/java/com/twelvemonkeys/imageio/util/ReaderFileSuffixFilter.java
+++ b/imageio/imageio-core/src/main/java/com/twelvemonkeys/imageio/util/ReaderFileSuffixFilter.java
@@ -47,15 +47,15 @@ import java.util.Map;
* @version $Id: ReaderFileSuffixFilter.java,v 1.0 11.okt.2006 20:05:36 haku Exp$
*/
public final class ReaderFileSuffixFilter extends FileFilter implements java.io.FileFilter {
- private final String mDescription;
- private final Map mKnownSuffixes = new HashMap(32);
+ private final String description;
+ private final Map knownSuffixes = new HashMap(32);
public ReaderFileSuffixFilter() {
this("Images (all supported input formats)");
}
public ReaderFileSuffixFilter(String pDescription) {
- mDescription = pDescription;
+ description = pDescription;
}
public boolean accept(File pFile) {
@@ -71,19 +71,20 @@ public final class ReaderFileSuffixFilter extends FileFilter implements java.io.
}
private boolean hasReaderForSuffix(String pSuffix) {
- if (mKnownSuffixes.get(pSuffix) == Boolean.TRUE) {
+ if (knownSuffixes.get(pSuffix) == Boolean.TRUE) {
return true;
}
try {
// Cahce lookup
Iterator iterator = ImageIO.getImageReadersBySuffix(pSuffix);
+
if (iterator.hasNext()) {
- mKnownSuffixes.put(pSuffix, Boolean.TRUE);
+ knownSuffixes.put(pSuffix, Boolean.TRUE);
return true;
}
else {
- mKnownSuffixes.put(pSuffix, Boolean.FALSE);
+ knownSuffixes.put(pSuffix, Boolean.FALSE);
return false;
}
}
@@ -93,6 +94,6 @@ public final class ReaderFileSuffixFilter extends FileFilter implements java.io.
}
public String getDescription() {
- return mDescription;
+ return description;
}
}
diff --git a/imageio/imageio-core/src/main/java/com/twelvemonkeys/imageio/util/WriterFileSuffixFilter.java b/imageio/imageio-core/src/main/java/com/twelvemonkeys/imageio/util/WriterFileSuffixFilter.java
index 935faebd..20a43ae4 100755
--- a/imageio/imageio-core/src/main/java/com/twelvemonkeys/imageio/util/WriterFileSuffixFilter.java
+++ b/imageio/imageio-core/src/main/java/com/twelvemonkeys/imageio/util/WriterFileSuffixFilter.java
@@ -47,15 +47,15 @@ import java.util.Map;
* @version $Id: WriterFileSuffixFilter.java,v 1.0 11.okt.2006 20:05:36 haku Exp$
*/
public final class WriterFileSuffixFilter extends FileFilter implements java.io.FileFilter {
- private final String mDescription;
- private MapmKnownSuffixes = new HashMap(32);
+ private final String description;
+ private Map knownSuffixes = new HashMap(32);
public WriterFileSuffixFilter() {
this("Images (all supported output formats)");
}
public WriterFileSuffixFilter(String pDescription) {
- mDescription = pDescription;
+ description = pDescription;
}
public boolean accept(File pFile) {
@@ -66,24 +66,25 @@ public final class WriterFileSuffixFilter extends FileFilter implements java.io.
// Test if we have an ImageWriter for this suffix
String suffix = FileUtil.getExtension(pFile);
- return !StringUtil.isEmpty(suffix) && hasWriterForSuffix(suffix);
+ return !StringUtil.isEmpty(suffix) && hasWriterForSuffix(suffix);
}
private boolean hasWriterForSuffix(String pSuffix) {
- if (mKnownSuffixes.get(pSuffix) == Boolean.TRUE) {
+ if (knownSuffixes.get(pSuffix) == Boolean.TRUE) {
return true;
}
try {
// Cahce lookup
Iterator iterator = ImageIO.getImageWritersBySuffix(pSuffix);
+
if (iterator.hasNext()) {
- mKnownSuffixes.put(pSuffix, Boolean.TRUE);
+ knownSuffixes.put(pSuffix, Boolean.TRUE);
return true;
}
else {
- mKnownSuffixes.put(pSuffix, Boolean.FALSE);
+ knownSuffixes.put(pSuffix, Boolean.FALSE);
return false;
}
}
@@ -93,6 +94,6 @@ public final class WriterFileSuffixFilter extends FileFilter implements java.io.
}
public String getDescription() {
- return mDescription;
+ return description;
}
}
diff --git a/imageio/imageio-core/src/test/java/com/twelvemonkeys/imageio/stream/BufferedImageInputStreamTestCase.java b/imageio/imageio-core/src/test/java/com/twelvemonkeys/imageio/stream/BufferedImageInputStreamTestCase.java
index 8c04d347..90e4b12b 100644
--- a/imageio/imageio-core/src/test/java/com/twelvemonkeys/imageio/stream/BufferedImageInputStreamTestCase.java
+++ b/imageio/imageio-core/src/test/java/com/twelvemonkeys/imageio/stream/BufferedImageInputStreamTestCase.java
@@ -18,7 +18,7 @@ import java.util.Random;
* @version $Id: BufferedImageInputStreamTestCase.java,v 1.0 Jun 30, 2008 3:07:42 PM haraldk Exp$
*/
public class BufferedImageInputStreamTestCase extends TestCase {
- protected final Random mRandom = new Random();
+ protected final Random random = new Random();
public void testCreate() throws IOException {
new BufferedImageInputStream(new ByteArrayImageInputStream(new byte[0]));
@@ -58,7 +58,7 @@ public class BufferedImageInputStreamTestCase extends TestCase {
// Fill bytes
byte[] bytes = new byte[size * 2];
- mRandom.nextBytes(bytes);
+ random.nextBytes(bytes);
// Create wrapper stream
BufferedImageInputStream stream = new BufferedImageInputStream(new ByteArrayImageInputStream(bytes));
@@ -79,7 +79,7 @@ public class BufferedImageInputStreamTestCase extends TestCase {
public void testBufferPositionCorrect() throws IOException {
// Fill bytes
byte[] bytes = new byte[1024];
- mRandom.nextBytes(bytes);
+ random.nextBytes(bytes);
ByteArrayImageInputStream input = new ByteArrayImageInputStream(bytes);
diff --git a/imageio/imageio-core/src/test/java/com/twelvemonkeys/imageio/stream/ByteArrayImageInputStreamTestCase.java b/imageio/imageio-core/src/test/java/com/twelvemonkeys/imageio/stream/ByteArrayImageInputStreamTestCase.java
index 372fe6ed..2405ede3 100755
--- a/imageio/imageio-core/src/test/java/com/twelvemonkeys/imageio/stream/ByteArrayImageInputStreamTestCase.java
+++ b/imageio/imageio-core/src/test/java/com/twelvemonkeys/imageio/stream/ByteArrayImageInputStreamTestCase.java
@@ -1,11 +1,12 @@
package com.twelvemonkeys.imageio.stream;
-import static com.twelvemonkeys.imageio.stream.BufferedImageInputStreamTestCase.rangeEquals;
import junit.framework.TestCase;
import java.io.IOException;
import java.util.Random;
+import static com.twelvemonkeys.imageio.stream.BufferedImageInputStreamTestCase.rangeEquals;
+
/**
* ByteArrayImageInputStreamTestCase
*
@@ -14,7 +15,7 @@ import java.util.Random;
* @version $Id: ByteArrayImageInputStreamTestCase.java,v 1.0 Apr 21, 2009 10:58:48 AM haraldk Exp$
*/
public class ByteArrayImageInputStreamTestCase extends TestCase {
- protected final Random mRandom = new Random();
+ protected final Random random = new Random();
public void testCreate() {
ByteArrayImageInputStream stream = new ByteArrayImageInputStream(new byte[0]);
@@ -36,7 +37,7 @@ public class ByteArrayImageInputStreamTestCase extends TestCase {
public void testRead() throws IOException {
byte[] data = new byte[1024 * 1024];
- mRandom.nextBytes(data);
+ random.nextBytes(data);
ByteArrayImageInputStream stream = new ByteArrayImageInputStream(data);
@@ -49,7 +50,7 @@ public class ByteArrayImageInputStreamTestCase extends TestCase {
public void testReadArray() throws IOException {
byte[] data = new byte[1024 * 1024];
- mRandom.nextBytes(data);
+ random.nextBytes(data);
ByteArrayImageInputStream stream = new ByteArrayImageInputStream(data);
@@ -65,7 +66,7 @@ public class ByteArrayImageInputStreamTestCase extends TestCase {
public void testReadSkip() throws IOException {
byte[] data = new byte[1024 * 14];
- mRandom.nextBytes(data);
+ random.nextBytes(data);
ByteArrayImageInputStream stream = new ByteArrayImageInputStream(data);
@@ -82,7 +83,7 @@ public class ByteArrayImageInputStreamTestCase extends TestCase {
public void testReadSeek() throws IOException {
byte[] data = new byte[1024 * 18];
- mRandom.nextBytes(data);
+ random.nextBytes(data);
ByteArrayImageInputStream stream = new ByteArrayImageInputStream(data);
diff --git a/imageio/imageio-core/src/test/java/com/twelvemonkeys/imageio/stream/SubImageInputStreamTestCase.java b/imageio/imageio-core/src/test/java/com/twelvemonkeys/imageio/stream/SubImageInputStreamTestCase.java
index 665582d8..674afa18 100644
--- a/imageio/imageio-core/src/test/java/com/twelvemonkeys/imageio/stream/SubImageInputStreamTestCase.java
+++ b/imageio/imageio-core/src/test/java/com/twelvemonkeys/imageio/stream/SubImageInputStreamTestCase.java
@@ -19,12 +19,12 @@ import java.util.Random;
*/
public class SubImageInputStreamTestCase extends TestCase {
// TODO: Extract super test case for all stream tests
- private final Random mRandom = new Random(837468l);
+ private final Random random = new Random(837468l);
private ImageInputStream createStream(final int pSize) {
byte[] bytes = new byte[pSize];
- mRandom.nextBytes(bytes);
+ random.nextBytes(bytes);
return new MemoryCacheImageInputStream(new ByteArrayInputStream(bytes)) {
@Override
diff --git a/imageio/imageio-core/src/test/java/com/twelvemonkeys/imageio/util/ImageReaderAbstractTestCase.java b/imageio/imageio-core/src/test/java/com/twelvemonkeys/imageio/util/ImageReaderAbstractTestCase.java
index 601ff974..bbf7bcf3 100644
--- a/imageio/imageio-core/src/test/java/com/twelvemonkeys/imageio/util/ImageReaderAbstractTestCase.java
+++ b/imageio/imageio-core/src/test/java/com/twelvemonkeys/imageio/util/ImageReaderAbstractTestCase.java
@@ -116,6 +116,10 @@ public abstract class ImageReaderAbstractTestCase extends
protected abstract List getMIMETypes();
+ protected boolean allowsNullRawImageType() {
+ return false;
+ }
+
protected void assertProviderInstalledForName(final String pFormat, final Class extends ImageReader> pReaderClass) {
assertProviderInstalled0(pFormat.toUpperCase(), pReaderClass, ImageIO.getImageReadersByFormatName(pFormat.toUpperCase()));
assertProviderInstalled0(pFormat.toLowerCase(), pReaderClass, ImageIO.getImageReadersByFormatName(pFormat.toLowerCase()));
@@ -1111,30 +1115,34 @@ public abstract class ImageReaderAbstractTestCase extends
public void testGetTypeSpecifiers() throws IOException {
final ImageReader reader = createReader();
- TestData data = getTestData().get(0);
- reader.setInput(data.getInputStream());
+ for (TestData data : getTestData()) {
+ reader.setInput(data.getInputStream());
- ImageTypeSpecifier rawType = reader.getRawImageType(0);
- assertNotNull(rawType);
-
- Iterator types = reader.getImageTypes(0);
-
- assertNotNull(types);
- assertTrue(types.hasNext());
-
- // TODO: This might fail even though the specifiers are obviously equal, if the
- // color spaces they use are not the SAME instance, as ColorSpace uses identity equals
- // and Interleaved ImageTypeSpecifiers are only equal if color spaces are equal...
- boolean rawFound = false;
- while (types.hasNext()) {
- ImageTypeSpecifier type = types.next();
- if (type.equals(rawType)) {
- rawFound = true;
- break;
+ ImageTypeSpecifier rawType = reader.getRawImageType(0);
+ if (rawType == null && allowsNullRawImageType()) {
+ continue;
}
- }
+ assertNotNull(rawType);
- assertTrue("ImageTypeSepcifier from getRawImageType should be in the iterator from getImageTypes", rawFound);
+ Iterator types = reader.getImageTypes(0);
+
+ assertNotNull(types);
+ assertTrue(types.hasNext());
+
+ // TODO: This might fail even though the specifiers are obviously equal, if the
+ // color spaces they use are not the SAME instance, as ColorSpace uses identity equals
+ // and Interleaved ImageTypeSpecifiers are only equal if color spaces are equal...
+ boolean rawFound = false;
+ while (types.hasNext()) {
+ ImageTypeSpecifier type = types.next();
+ if (type.equals(rawType)) {
+ rawFound = true;
+ break;
+ }
+ }
+
+ assertTrue("ImageTypeSepcifier from getRawImageType should be in the iterator from getImageTypes", rawFound);
+ }
}
public void testSetDestination() throws IOException {
@@ -1164,12 +1172,18 @@ public abstract class ImageReaderAbstractTestCase extends
ImageReadParam param = reader.getDefaultReadParam();
ImageTypeSpecifier type = reader.getRawImageType(0);
- BufferedImage destination = type.createBufferedImage(reader.getWidth(0), reader.getHeight(0));
- param.setDestination(destination);
- BufferedImage result = reader.read(0, param);
+ if (type != null) {
+ BufferedImage destination = type.createBufferedImage(reader.getWidth(0), reader.getHeight(0));
+ param.setDestination(destination);
- assertSame(destination, result);
+ BufferedImage result = reader.read(0, param);
+
+ assertSame(destination, result);
+ }
+ else {
+ System.err.println("WARNING: Test skipped due to reader.getRawImageType(0) returning null");
+ }
}
public void testSetDestinationIllegal() throws IOException {
@@ -1258,7 +1272,7 @@ public abstract class ImageReaderAbstractTestCase extends
boolean removed = illegalTypes.remove(valid);
// TODO: 4BYTE_ABGR (6) and 4BYTE_ABGR_PRE (7) is essentially the same type...
- // !#$#§%$! ImageTypeSpecifier.equals is not well-defined
+ // !#$#�%$! ImageTypeSpecifier.equals is not well-defined
if (!removed) {
for (Iterator iterator = illegalTypes.iterator(); iterator.hasNext();) {
ImageTypeSpecifier illegalType = iterator.next();
diff --git a/imageio/imageio-core/todo.txt b/imageio/imageio-core/todo.txt
index c2644570..4e48a7fa 100755
--- a/imageio/imageio-core/todo.txt
+++ b/imageio/imageio-core/todo.txt
@@ -1,7 +1,7 @@
- Rename to imageio-common?
- Separate modules for more for more plugins
- - The BMP reader spports some special formats not supported by Sun reader
- - PNM package is pretty complete, but useless, as it's provided by Sun? Licencse?
+ - The BMP reader supports some special formats not supported by Sun reader
+ - PNM package is pretty complete, but useless, as it's provided by Sun? License?
- WBMP?
- XBM?
DONE:
diff --git a/imageio/imageio-ico/src/main/java/com/twelvemonkeys/imageio/plugins/ico/BitmapIndexed.java b/imageio/imageio-ico/src/main/java/com/twelvemonkeys/imageio/plugins/ico/BitmapIndexed.java
index bd73dd75..2b0e88c5 100755
--- a/imageio/imageio-ico/src/main/java/com/twelvemonkeys/imageio/plugins/ico/BitmapIndexed.java
+++ b/imageio/imageio-ico/src/main/java/com/twelvemonkeys/imageio/plugins/ico/BitmapIndexed.java
@@ -78,7 +78,7 @@ class BitmapIndexed extends BitmapDescriptor {
WritableRaster raster = image.getRaster();
- // Make pixels transparant according to mask
+ // Make pixels transparent according to mask
final int trans = icm.getTransparentPixel();
for (int y = 0; y < getHeight(); y++) {
for (int x = 0; x < getWidth(); x++) {
diff --git a/imageio/imageio-ico/src/main/java/com/twelvemonkeys/imageio/plugins/ico/ICOImageReader.java b/imageio/imageio-ico/src/main/java/com/twelvemonkeys/imageio/plugins/ico/ICOImageReader.java
index 8bf47ebd..bd62a431 100644
--- a/imageio/imageio-ico/src/main/java/com/twelvemonkeys/imageio/plugins/ico/ICOImageReader.java
+++ b/imageio/imageio-ico/src/main/java/com/twelvemonkeys/imageio/plugins/ico/ICOImageReader.java
@@ -132,8 +132,8 @@ public class ICOImageReader extends ImageReaderBase {
case 8:
// TODO: This is slightly QnD...
int offset = entry.getOffset() + header.getSize();
- if (offset != mImageInput.getStreamPosition()) {
- mImageInput.seek(offset);
+ if (offset != imageInput.getStreamPosition()) {
+ imageInput.seek(offset);
}
BitmapIndexed indexed = new BitmapIndexed(entry, header);
readColorMap(indexed);
@@ -220,21 +220,17 @@ public class ICOImageReader extends ImageReaderBase {
return destination;
}
- private boolean hasExplicitDestination(final ImageReadParam pParam) {
- return (pParam != null && (pParam.getDestination() != null || pParam.getDestinationType() != null || pParam.getDestinationOffset() != null));
- }
-
private boolean isPNG(final DirectoryEntry pEntry) throws IOException {
long magic;
- mImageInput.seek(pEntry.getOffset());
- mImageInput.setByteOrder(ByteOrder.BIG_ENDIAN);
+ imageInput.seek(pEntry.getOffset());
+ imageInput.setByteOrder(ByteOrder.BIG_ENDIAN);
try {
- magic = mImageInput.readLong();
+ magic = imageInput.readLong();
}
finally {
- mImageInput.setByteOrder(ByteOrder.LITTLE_ENDIAN);
+ imageInput.setByteOrder(ByteOrder.LITTLE_ENDIAN);
}
return magic == DIB.PNG_MAGIC;
@@ -252,8 +248,8 @@ public class ICOImageReader extends ImageReaderBase {
private ImageReader initPNGReader(final DirectoryEntry pEntry) throws IOException {
ImageReader pngReader = getPNGReader();
- mImageInput.seek(pEntry.getOffset());
- InputStream inputStream = IIOUtil.createStreamAdapter(mImageInput, pEntry.getSize());
+ imageInput.seek(pEntry.getOffset());
+ InputStream inputStream = IIOUtil.createStreamAdapter(imageInput, pEntry.getSize());
ImageInputStream stream = ImageIO.createImageInputStream(inputStream);
// NOTE: Will throw IOException on later reads if input is not PNG
@@ -283,8 +279,8 @@ public class ICOImageReader extends ImageReaderBase {
private DIBHeader getHeader(final DirectoryEntry pEntry) throws IOException {
if (!mHeaders.containsKey(pEntry)) {
- mImageInput.seek(pEntry.getOffset());
- DIBHeader header = DIBHeader.read(mImageInput);
+ imageInput.seek(pEntry.getOffset());
+ DIBHeader header = DIBHeader.read(imageInput);
mHeaders.put(pEntry, header);
}
@@ -299,8 +295,8 @@ public class ICOImageReader extends ImageReaderBase {
DIBHeader header = getHeader(pEntry);
int offset = pEntry.getOffset() + header.getSize();
- if (offset != mImageInput.getStreamPosition()) {
- mImageInput.seek(offset);
+ if (offset != imageInput.getStreamPosition()) {
+ imageInput.seek(offset);
}
// TODO: Support this, it's already in the BMP reader, spec allows RLE4 and RLE8
@@ -368,7 +364,7 @@ public class ICOImageReader extends ImageReaderBase {
for (int i = 0; i < colorCount; i++) {
// aRGB (a is "Reserved")
- pBitmap.mColors[i] = (mImageInput.readInt() & 0xffffff) | 0xff000000;
+ pBitmap.mColors[i] = (imageInput.readInt() & 0xffffff) | 0xff000000;
}
}
@@ -377,7 +373,7 @@ public class ICOImageReader extends ImageReaderBase {
byte[] row = new byte[width];
for (int y = 0; y < pBitmap.getHeight(); y++) {
- mImageInput.readFully(row, 0, width);
+ imageInput.readFully(row, 0, width);
int rowPos = 0;
int xOrVal = 0x80;
int pos = (pBitmap.getHeight() - y - 1) * pBitmap.getWidth();
@@ -411,7 +407,7 @@ public class ICOImageReader extends ImageReaderBase {
byte[] row = new byte[width];
for (int y = 0; y < pBitmap.getHeight(); y++) {
- mImageInput.readFully(row, 0, width);
+ imageInput.readFully(row, 0, width);
int rowPos = 0;
boolean high4 = true;
int pos = (pBitmap.getHeight() - y - 1) * pBitmap.getWidth();
@@ -446,7 +442,7 @@ public class ICOImageReader extends ImageReaderBase {
byte[] row = new byte[width];
for (int y = 0; y < pBitmap.getHeight(); y++) {
- mImageInput.readFully(row, 0, width);
+ imageInput.readFully(row, 0, width);
int rowPos = 0;
int pos = (pBitmap.getHeight() - y - 1) * pBitmap.getWidth();
@@ -488,12 +484,12 @@ public class ICOImageReader extends ImageReaderBase {
for (int y = 0; y < pBitmap.getHeight(); y++) {
int offset = (pBitmap.getHeight() - y - 1) * pBitmap.getWidth();
- mImageInput.readFully(pixels, offset, pBitmap.getWidth());
+ imageInput.readFully(pixels, offset, pBitmap.getWidth());
// Skip to 32 bit boundary
if (pBitmap.getWidth() % 2 != 0) {
- mImageInput.readShort();
+ imageInput.readShort();
}
if (abortRequested()) {
@@ -524,7 +520,7 @@ public class ICOImageReader extends ImageReaderBase {
for (int y = 0; y < pBitmap.getHeight(); y++) {
int offset = (pBitmap.getHeight() - y - 1) * pBitmap.getWidth();
- mImageInput.readFully(pixels, offset, pBitmap.getWidth() * 3);
+ imageInput.readFully(pixels, offset, pBitmap.getWidth() * 3);
// TODO: Possibly read padding byte here!
@@ -550,7 +546,7 @@ public class ICOImageReader extends ImageReaderBase {
for (int y = 0; y < pBitmap.getHeight(); y++) {
int offset = (pBitmap.getHeight() - y - 1) * pBitmap.getWidth();
- mImageInput.readFully(pixels, offset, pBitmap.getWidth());
+ imageInput.readFully(pixels, offset, pBitmap.getWidth());
if (abortRequested()) {
processReadAborted();
@@ -571,17 +567,17 @@ public class ICOImageReader extends ImageReaderBase {
}
private void readFileHeader() throws IOException {
- mImageInput.setByteOrder(ByteOrder.LITTLE_ENDIAN);
+ imageInput.setByteOrder(ByteOrder.LITTLE_ENDIAN);
// Read file header
- mImageInput.readUnsignedShort(); // Reserved
+ imageInput.readUnsignedShort(); // Reserved
// Should be same as type as the provider
- int type = mImageInput.readUnsignedShort();
- int imageCount = mImageInput.readUnsignedShort();
+ int type = imageInput.readUnsignedShort();
+ int imageCount = imageInput.readUnsignedShort();
// Read directory
- mDirectory = Directory.read(type, imageCount, mImageInput);
+ mDirectory = Directory.read(type, imageCount, imageInput);
}
final DirectoryEntry getEntry(final int pImageIndex) throws IOException {
diff --git a/imageio/imageio-iff/src/main/java/com/twelvemonkeys/imageio/plugins/iff/IFFImageReader.java b/imageio/imageio-iff/src/main/java/com/twelvemonkeys/imageio/plugins/iff/IFFImageReader.java
index dd06892f..7a65350f 100755
--- a/imageio/imageio-iff/src/main/java/com/twelvemonkeys/imageio/plugins/iff/IFFImageReader.java
+++ b/imageio/imageio-iff/src/main/java/com/twelvemonkeys/imageio/plugins/iff/IFFImageReader.java
@@ -135,13 +135,13 @@ public class IFFImageReader extends ImageReaderBase {
}
private void readMeta() throws IOException {
- if (mImageInput.readInt() != IFF.CHUNK_FORM) {
+ if (imageInput.readInt() != IFF.CHUNK_FORM) {
throw new IIOException("Unknown file format for IFFImageReader");
}
- int remaining = mImageInput.readInt() - 4; // We'll read 4 more in a sec
+ int remaining = imageInput.readInt() - 4; // We'll read 4 more in a sec
- mFormType = mImageInput.readInt();
+ mFormType = imageInput.readInt();
if (mFormType != IFF.TYPE_ILBM && mFormType != IFF.TYPE_PBM) {
throw new IIOException("Only IFF (FORM) type ILBM and PBM supported: " + IFFUtil.toChunkStr(mFormType));
}
@@ -152,8 +152,8 @@ public class IFFImageReader extends ImageReaderBase {
mViewPort = null;
while (remaining > 0) {
- int chunkId = mImageInput.readInt();
- int length = mImageInput.readInt();
+ int chunkId = imageInput.readInt();
+ int length = imageInput.readInt();
remaining -= 8;
remaining -= length % 2 == 0 ? length : length + 1;
@@ -168,7 +168,7 @@ public class IFFImageReader extends ImageReaderBase {
}
mHeader = new BMHDChunk(length);
- mHeader.readChunk(mImageInput);
+ mHeader.readChunk(imageInput);
//System.out.println(mHeader);
break;
@@ -177,7 +177,7 @@ public class IFFImageReader extends ImageReaderBase {
throw new IIOException("Multiple CMAP chunks not allowed");
}
mColorMap = new CMAPChunk(length, mHeader, mViewPort);
- mColorMap.readChunk(mImageInput);
+ mColorMap.readChunk(imageInput);
//System.out.println(mColorMap);
break;
@@ -186,7 +186,7 @@ public class IFFImageReader extends ImageReaderBase {
throw new IIOException("Multiple GRAB chunks not allowed");
}
mGrab = new GRABChunk(length);
- mGrab.readChunk(mImageInput);
+ mGrab.readChunk(imageInput);
//System.out.println(mGrab);
break;
@@ -195,7 +195,7 @@ public class IFFImageReader extends ImageReaderBase {
throw new IIOException("Multiple CAMG chunks not allowed");
}
mViewPort = new CAMGChunk(length);
- mViewPort.readChunk(mImageInput);
+ mViewPort.readChunk(imageInput);
//System.out.println(mViewPort);
break;
@@ -205,7 +205,7 @@ public class IFFImageReader extends ImageReaderBase {
}
mBody = new BODYChunk(length);
- mBodyStart = mImageInput.getStreamPosition();
+ mBodyStart = imageInput.getStreamPosition();
// NOTE: We don't read the body here, it's done later in the read(int, ImageReadParam) method
@@ -215,7 +215,7 @@ public class IFFImageReader extends ImageReaderBase {
// TODO: We probably want to store anno chunks as Metadata
// ANNO, DEST, SPRT and more
IFFChunk generic = new GenericChunk(chunkId, length);
- generic.readChunk(mImageInput);
+ generic.readChunk(imageInput);
//System.out.println(generic);
break;
@@ -323,16 +323,16 @@ public class IFFImageReader extends ImageReaderBase {
}
private void readBody(final ImageReadParam pParam) throws IOException {
- mImageInput.seek(mBodyStart);
+ imageInput.seek(mBodyStart);
mByteRunStream = null;
// NOTE: mColorMap may be null for 8 bit (gray), 24 bit or 32 bit only
if (mColorMap != null) {
IndexColorModel cm = mColorMap.getIndexColorModel();
- readIndexed(pParam, mImageInput, cm);
+ readIndexed(pParam, imageInput, cm);
}
else {
- readTrueColor(pParam, mImageInput);
+ readTrueColor(pParam, imageInput);
}
}
diff --git a/imageio/imageio-iff/src/main/java/com/twelvemonkeys/imageio/plugins/iff/IFFImageWriter.java b/imageio/imageio-iff/src/main/java/com/twelvemonkeys/imageio/plugins/iff/IFFImageWriter.java
index 62e9bb08..e1a3d845 100755
--- a/imageio/imageio-iff/src/main/java/com/twelvemonkeys/imageio/plugins/iff/IFFImageWriter.java
+++ b/imageio/imageio-iff/src/main/java/com/twelvemonkeys/imageio/plugins/iff/IFFImageWriter.java
@@ -99,22 +99,22 @@ public class IFFImageWriter extends ImageWriterBase {
}
private void writeBody(ByteArrayOutputStream pImageData) throws IOException {
- mImageOutput.writeInt(IFF.CHUNK_BODY);
- mImageOutput.writeInt(pImageData.size());
+ imageOutput.writeInt(IFF.CHUNK_BODY);
+ imageOutput.writeInt(pImageData.size());
// NOTE: This is much faster than mOutput.write(pImageData.toByteArray())
// as the data array is not duplicated
- pImageData.writeTo(IIOUtil.createStreamAdapter(mImageOutput));
+ pImageData.writeTo(IIOUtil.createStreamAdapter(imageOutput));
if (pImageData.size() % 2 == 0) {
- mImageOutput.writeByte(0); // PAD
+ imageOutput.writeByte(0); // PAD
}
// NOTE: Most progress is done in packImageData, however, as we need to
// buffer, to write correct size, we defer the last 10 percent until now.
processImageProgress(100f);
- mImageOutput.flush();
+ imageOutput.flush();
}
private void packImageData(OutputStream pOutput, RenderedImage pImage, ImageWriteParam pParam) throws IOException {
@@ -213,16 +213,16 @@ public class IFFImageWriter extends ImageWriterBase {
size += 8 + cmap.mChunkLength;
}
- mImageOutput.writeInt(IFF.CHUNK_FORM);
- mImageOutput.writeInt(size);
+ imageOutput.writeInt(IFF.CHUNK_FORM);
+ imageOutput.writeInt(size);
- mImageOutput.writeInt(IFF.TYPE_ILBM);
+ imageOutput.writeInt(IFF.TYPE_ILBM);
- anno.writeChunk(mImageOutput);
- header.writeChunk(mImageOutput);
+ anno.writeChunk(imageOutput);
+ header.writeChunk(imageOutput);
if (cmap != null) {
//System.out.println("CMAP written");
- cmap.writeChunk(mImageOutput);
+ cmap.writeChunk(imageOutput);
}
}
diff --git a/imageio/imageio-jmagick/src/main/java/com/twelvemonkeys/imageio/plugins/jmagick/JMagickReader.java b/imageio/imageio-jmagick/src/main/java/com/twelvemonkeys/imageio/plugins/jmagick/JMagickReader.java
index 20c96a58..7d51b6c1 100755
--- a/imageio/imageio-jmagick/src/main/java/com/twelvemonkeys/imageio/plugins/jmagick/JMagickReader.java
+++ b/imageio/imageio-jmagick/src/main/java/com/twelvemonkeys/imageio/plugins/jmagick/JMagickReader.java
@@ -286,11 +286,11 @@ abstract class JMagickReader extends ImageReaderBase {
// TODO: If ImageInputStream is already file-backed, maybe we can peek into that file?
// At the moment, the cache/file is not accessible, but we could create our own
// FileImageInputStream provider that gives us this access.
- if (!mUseTempFile && mImageInput.length() >= 0 && mImageInput.length() <= Integer.MAX_VALUE) {
+ if (!mUseTempFile && imageInput.length() >= 0 && imageInput.length() <= Integer.MAX_VALUE) {
// This works for most file formats, as long as ImageMagick
// uses the file magic to decide file format
- byte[] bytes = new byte[(int) mImageInput.length()];
- mImageInput.readFully(bytes);
+ byte[] bytes = new byte[(int) imageInput.length()];
+ imageInput.readFully(bytes);
// Unfortunately, this is a waste of space & time...
ImageInfo info = new ImageInfo();
@@ -309,7 +309,7 @@ abstract class JMagickReader extends ImageReaderBase {
byte[] buffer = new byte[FileUtil.BUF_SIZE];
int count;
- while ((count = mImageInput.read(buffer)) != -1) {
+ while ((count = imageInput.read(buffer)) != -1) {
out.write(buffer, 0, count);
}
diff --git a/imageio/imageio-jmagick/src/main/java/com/twelvemonkeys/imageio/plugins/jmagick/JMagickWriter.java b/imageio/imageio-jmagick/src/main/java/com/twelvemonkeys/imageio/plugins/jmagick/JMagickWriter.java
index 8106bbee..9a7dfc4b 100755
--- a/imageio/imageio-jmagick/src/main/java/com/twelvemonkeys/imageio/plugins/jmagick/JMagickWriter.java
+++ b/imageio/imageio-jmagick/src/main/java/com/twelvemonkeys/imageio/plugins/jmagick/JMagickWriter.java
@@ -113,8 +113,8 @@ abstract class JMagickWriter extends ImageWriterBase {
processImageProgress(67);
// Write blob to output
- mImageOutput.write(bytes);
- mImageOutput.flush();
+ imageOutput.write(bytes);
+ imageOutput.flush();
processImageProgress(100);
}
catch (MagickException e) {
diff --git a/imageio/imageio-jpeg/src/main/java/com/twelvemonkeys/imageio/plugins/jpeg/JPEGImageReader.java b/imageio/imageio-jpeg/src/main/java/com/twelvemonkeys/imageio/plugins/jpeg/JPEGImageReader.java
index 1b24e819..69ec6f9b 100644
--- a/imageio/imageio-jpeg/src/main/java/com/twelvemonkeys/imageio/plugins/jpeg/JPEGImageReader.java
+++ b/imageio/imageio-jpeg/src/main/java/com/twelvemonkeys/imageio/plugins/jpeg/JPEGImageReader.java
@@ -506,12 +506,12 @@ public class JPEGImageReader extends ImageReaderBase {
}
private void readSegments() throws IOException {
- long pos = mImageInput.getStreamPosition();
+ long pos = imageInput.getStreamPosition();
try {
- mImageInput.seek(0); // TODO: Seek to wanted image
+ imageInput.seek(0); // TODO: Seek to wanted image
- segments = JPEGSegmentUtil.readSegments(mImageInput, SEGMENT_IDENTIFIERS);
+ segments = JPEGSegmentUtil.readSegments(imageInput, SEGMENT_IDENTIFIERS);
}
catch (IOException ignore) {
}
@@ -519,7 +519,7 @@ public class JPEGImageReader extends ImageReaderBase {
foo.printStackTrace();
}
finally {
- mImageInput.seek(pos);
+ imageInput.seek(pos);
}
}
diff --git a/imageio/imageio-metadata/src/main/java/com/twelvemonkeys/imageio/metadata/AbstractEntry.java b/imageio/imageio-metadata/src/main/java/com/twelvemonkeys/imageio/metadata/AbstractEntry.java
index 75b8b456..cbd850f6 100644
--- a/imageio/imageio-metadata/src/main/java/com/twelvemonkeys/imageio/metadata/AbstractEntry.java
+++ b/imageio/imageio-metadata/src/main/java/com/twelvemonkeys/imageio/metadata/AbstractEntry.java
@@ -31,6 +31,7 @@ package com.twelvemonkeys.imageio.metadata;
import com.twelvemonkeys.lang.Validate;
import java.lang.reflect.Array;
+import java.util.Arrays;
/**
* AbstractEntry
@@ -69,6 +70,45 @@ public abstract class AbstractEntry implements Entry {
}
public String getValueAsString() {
+ if (valueCount() > 1) {
+ if (valueCount() < 16) {
+ Class> type = mValue.getClass().getComponentType();
+
+ if (type.isPrimitive()) {
+ if (type.equals(boolean.class)) {
+ return Arrays.toString((boolean[]) mValue);
+ }
+ else if (type.equals(byte.class)) {
+ return Arrays.toString((byte[]) mValue);
+ }
+ else if (type.equals(char.class)) {
+ return new String((char[]) mValue);
+ }
+ else if (type.equals(double.class)) {
+ return Arrays.toString((double[]) mValue);
+ }
+ else if (type.equals(float.class)) {
+ return Arrays.toString((float[]) mValue);
+ }
+ else if (type.equals(int.class)) {
+ return Arrays.toString((int[]) mValue);
+ }
+ else if (type.equals(long.class)) {
+ return Arrays.toString((long[]) mValue);
+ }
+ else if (type.equals(short.class)) {
+ return Arrays.toString((short[]) mValue);
+ }
+ // Fall through should never happen
+ }
+ else {
+ return Arrays.toString((Object[]) mValue);
+ }
+ }
+
+ return String.valueOf(mValue) + " (" + valueCount() + ")";
+ }
+
return String.valueOf(mValue);
}
diff --git a/imageio/imageio-metadata/src/main/java/com/twelvemonkeys/imageio/metadata/exif/EXIFEntry.java b/imageio/imageio-metadata/src/main/java/com/twelvemonkeys/imageio/metadata/exif/EXIFEntry.java
index fef71f37..39c23ba9 100644
--- a/imageio/imageio-metadata/src/main/java/com/twelvemonkeys/imageio/metadata/exif/EXIFEntry.java
+++ b/imageio/imageio-metadata/src/main/java/com/twelvemonkeys/imageio/metadata/exif/EXIFEntry.java
@@ -43,16 +43,35 @@ final class EXIFEntry extends AbstractEntry {
EXIFEntry(final int pIdentifier, final Object pValue, final short pType) {
super(pIdentifier, pValue);
- if (pType < 1 || pType > TIFF.TYPE_NAMES.length) {
- throw new IllegalArgumentException(String.format("Illegal EXIF type: %s", pType));
- }
+// if (pType < 1 || pType > TIFF.TYPE_NAMES.length) {
+// throw new IllegalArgumentException(String.format("Illegal EXIF type: %s", pType));
+// }
mType = pType;
}
+ public short getType() {
+ return mType;
+ }
+
@Override
public String getFieldName() {
switch ((Integer) getIdentifier()) {
+ case TIFF.TAG_EXIF_IFD:
+ return "EXIF";
+ case TIFF.TAG_XMP:
+ return "XMP";
+ case TIFF.TAG_IPTC:
+ return "IPTC";
+ case TIFF.TAG_PHOTOSHOP:
+ return "Adobe";
+ case TIFF.TAG_ICC_PROFILE:
+ return "ICC Profile";
+
+ case TIFF.TAG_IMAGE_WIDTH:
+ return "ImageWidth";
+ case TIFF.TAG_IMAGE_HEIGHT:
+ return "ImageHeight";
case TIFF.TAG_COMPRESSION:
return "Compression";
case TIFF.TAG_ORIENTATION:
@@ -82,6 +101,7 @@ final class EXIFEntry extends AbstractEntry {
return "PixelXDimension";
case EXIF.TAG_PIXEL_Y_DIMENSION:
return "PixelYDimension";
+
// TODO: More field names
}
diff --git a/imageio/imageio-metadata/src/main/java/com/twelvemonkeys/imageio/metadata/exif/EXIFReader.java b/imageio/imageio-metadata/src/main/java/com/twelvemonkeys/imageio/metadata/exif/EXIFReader.java
index 2118bc57..e4113a11 100644
--- a/imageio/imageio-metadata/src/main/java/com/twelvemonkeys/imageio/metadata/exif/EXIFReader.java
+++ b/imageio/imageio-metadata/src/main/java/com/twelvemonkeys/imageio/metadata/exif/EXIFReader.java
@@ -34,10 +34,15 @@ import com.twelvemonkeys.imageio.metadata.MetadataReader;
import com.twelvemonkeys.lang.StringUtil;
import javax.imageio.IIOException;
+import javax.imageio.ImageIO;
import javax.imageio.stream.ImageInputStream;
+import java.io.File;
import java.io.IOException;
import java.nio.ByteOrder;
+import java.nio.charset.Charset;
import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
import java.util.List;
/**
@@ -48,6 +53,7 @@ import java.util.List;
* @version $Id: EXIFReader.java,v 1.0 Nov 13, 2009 5:42:51 PM haraldk Exp$
*/
public final class EXIFReader extends MetadataReader {
+ static final Collection KNOWN_IFDS = Arrays.asList(TIFF.TAG_EXIF_IFD, TIFF.TAG_GPS_IFD, TIFF.TAG_INTEROP_IFD);
@Override
public Directory read(final ImageInputStream pInput) throws IOException {
@@ -56,10 +62,15 @@ public final class EXIFReader extends MetadataReader {
if (bom[0] == 'I' && bom[1] == 'I') {
pInput.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);
+ }
+ else {
throw new IIOException(String.format("Invalid TIFF byte order mark '%s', expected: 'II' or 'MM'", StringUtil.decode(bom, 0, bom.length, "ASCII")));
}
+ // TODO: BigTiff uses version 43 instead of TIFF's 42, and header is slightly different, see
+ // http://www.awaresystems.be/imaging/tiff/bigtiff.html
int magic = pInput.readUnsignedShort();
if (magic != TIFF.TIFF_MAGIC) {
throw new IIOException(String.format("Wrong TIFF magic in EXIF data: %04x, expected: %04x", magic, TIFF.TIFF_MAGIC));
@@ -72,7 +83,6 @@ public final class EXIFReader extends MetadataReader {
private EXIFDirectory readDirectory(final ImageInputStream pInput, final long pOffset) throws IOException {
List entries = new ArrayList();
-
pInput.seek(pOffset);
int entryCount = pInput.readUnsignedShort();
@@ -82,6 +92,7 @@ public final class EXIFReader extends MetadataReader {
long nextOffset = pInput.readUnsignedInt();
+ // Read linked IFDs
if (nextOffset != 0) {
EXIFDirectory next = readDirectory(pInput, nextOffset);
@@ -90,50 +101,158 @@ public final class EXIFReader extends MetadataReader {
}
}
+ // TODO: Make what sub-IFDs to parse optional? Or leave this to client code? At least skip the non-TIFF data?
+ readSubdirectories(pInput, entries,
+ Arrays.asList(TIFF.TAG_EXIF_IFD, TIFF.TAG_GPS_IFD, TIFF.TAG_INTEROP_IFD
+// , TIFF.TAG_IPTC, TIFF.TAG_XMP
+// , TIFF.TAG_ICC_PROFILE
+// , TIFF.TAG_PHOTOSHOP
+// ,TIFF.TAG_MODI_OLE_PROPERTY_SET
+ )
+ );
+
return new EXIFDirectory(entries);
}
+// private Directory readForeignMetadata(final MetadataReader reader, final byte[] bytes) throws IOException {
+// return reader.read(ImageIO.createImageInputStream(new ByteArrayInputStream(bytes)));
+// }
+
+ // TODO: Might be better to leave this for client code, as it's tempting go really overboard and support any possible embedded format..
+ private void readSubdirectories(ImageInputStream input, List entries, List subIFDs) throws IOException {
+ if (subIFDs == null || subIFDs.isEmpty()) {
+ return;
+ }
+
+ for (int i = 0, entriesSize = entries.size(); i < entriesSize; i++) {
+ EXIFEntry entry = (EXIFEntry) entries.get(i);
+ int tagId = (Integer) entry.getIdentifier();
+
+ if (subIFDs.contains(tagId)) {
+ try {
+ Object directory;
+
+ /*
+ if (tagId == TIFF.TAG_IPTC) {
+ directory = readForeignMetadata(new IPTCReader(), (byte[]) entry.getValue());
+ }
+ else if (tagId == TIFF.TAG_XMP) {
+ directory = readForeignMetadata(new XMPReader(), (byte[]) entry.getValue());
+ }
+ else if (tagId == TIFF.TAG_PHOTOSHOP) {
+ // TODO: This is waaay too fragile.. Might need registry-based meta data parsers?
+ try {
+ Class cl = Class.forName("com.twelvemonkeys.imageio.plugins.psd.PSDImageResource");
+ Method method = cl.getMethod("read", ImageInputStream.class);
+ method.setAccessible(true);
+ directory = method.invoke(null, ImageIO.createImageInputStream(new ByteArrayInputStream((byte[]) entry.getValue())));
+ }
+ catch (Exception ignore) {
+ continue;
+ }
+ }
+ else if (tagId == TIFF.TAG_ICC_PROFILE) {
+ directory = ICC_Profile.getInstance((byte[]) entry.getValue());
+ }
+ else if (tagId == TIFF.TAG_MODI_OLE_PROPERTY_SET) {
+ // TODO: Encapsulate in something more useful?
+ directory = new CompoundDocument(new ByteArrayInputStream((byte[]) entry.getValue())).getRootEntry();
+ }
+ else*/ if (KNOWN_IFDS.contains(tagId)) {
+ directory = readDirectory(input, getPointerOffset(entry));
+ }
+ else {
+ continue;
+ }
+
+ // Replace the entry with parsed data
+ entries.set(i, new EXIFEntry(tagId, directory, entry.getType()));
+ }
+ catch (IIOException e) {
+ // TODO: Issue warning without crashing...?
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+
+ private long getPointerOffset(final Entry entry) throws IIOException {
+ long offset;
+ Object value = entry.getValue();
+
+ if (value instanceof Byte) {
+ offset = ((Byte) value & 0xff);
+ }
+ else if (value instanceof Short) {
+ offset = ((Short) value & 0xffff);
+ }
+ else if (value instanceof Integer) {
+ offset = ((Integer) value & 0xffffffffL);
+ }
+ else if (value instanceof Long) {
+ offset = (Long) value;
+ }
+ else {
+ throw new IIOException(String.format("Unknown pointer type: %s", (value != null ? value.getClass() : null)));
+ }
+
+ return offset;
+ }
+
private EXIFEntry readEntry(final ImageInputStream pInput) throws IOException {
+ // TODO: BigTiff entries are different
int tagId = pInput.readUnsignedShort();
short type = pInput.readShort();
int count = pInput.readInt(); // Number of values
- Object value;
+ if (count < 0) {
+ throw new IIOException(String.format("Illegal count %d for tag %s type %s @%08x", count, tagId, type, pInput.getStreamPosition()));
+ }
+
+ Object value;
+ int valueLength = getValueLength(type, count);
+
+ if (type < 0 || type > 13) {
+ // Invalid tag, this is just for debugging
+ System.err.printf("offset: %08x%n", pInput.getStreamPosition() - 8l);
+ System.err.println("tagId: " + tagId);
+ System.err.println("type: " + type + " (INVALID)");
+ System.err.println("count: " + count);
- if (tagId == TIFF.IFD_EXIF || tagId == TIFF.IFD_GPS || tagId == TIFF.IFD_INTEROP) {
- // Parse sub IFDs
- long offset = pInput.readUnsignedInt();
pInput.mark();
+ pInput.seek(pInput.getStreamPosition() - 8);
try {
- value = readDirectory(pInput, offset);
+ byte[] bytes = new byte[8 + Math.max(20, valueLength)];
+ pInput.readFully(bytes);
+
+ System.err.print("data: " + HexDump.dump(bytes));
+ System.err.println(bytes.length < valueLength ? "..." : "");
}
finally {
pInput.reset();
}
}
- else {
- int valueLength = getValueLength(type, count);
- if (valueLength > 0 && valueLength <= 4) {
- value = readValueInLine(pInput, type, count);
- pInput.skipBytes(4 - valueLength);
- }
- else {
- long valueOffset = pInput.readUnsignedInt(); // This is the *value* iff the value size is <= 4 bytes
- value = readValue(pInput, valueOffset, type, count);
- }
+ // TODO: For BigTiff allow size <= 8
+ if (valueLength > 0 && valueLength <= 4) {
+ value = readValueInLine(pInput, type, count);
+ pInput.skipBytes(4 - valueLength);
+ }
+ else {
+ long valueOffset = pInput.readUnsignedInt(); // This is the *value* iff the value size is <= 4 bytes
+ value = readValueAt(pInput, valueOffset, type, count);
}
return new EXIFEntry(tagId, value, type);
}
- private Object readValue(final ImageInputStream pInput, final long pOffset, final short pType, final int pCount) throws IOException {
+ private Object readValueAt(final ImageInputStream pInput, final long pOffset, final short pType, final int pCount) throws IOException {
long pos = pInput.getStreamPosition();
try {
pInput.seek(pOffset);
- return readValueInLine(pInput, pType, pCount);
+ return readValue(pInput, pType, pCount);
}
finally {
pInput.seek(pos);
@@ -141,53 +260,82 @@ public final class EXIFReader extends MetadataReader {
}
private Object readValueInLine(final ImageInputStream pInput, final short pType, final int pCount) throws IOException {
- return readValueDirect(pInput, pType, pCount);
+ return readValue(pInput, pType, pCount);
}
- private static Object readValueDirect(final ImageInputStream pInput, final short pType, final int pCount) throws IOException {
+ private static Object readValue(final ImageInputStream pInput, final short pType, final int pCount) throws IOException {
+ // TODO: Review value "widening" for the unsigned types. Right now it's inconsistent. Should we leave it to client code?
+
+ long pos = pInput.getStreamPosition();
+
switch (pType) {
- case 2:
- // TODO: This might be UTF-8 or ISO-8859-1, even though spec says ASCII
+ case 2: // ASCII
+ // TODO: This might be UTF-8 or ISO-8859-x, even though spec says ASCII
byte[] ascii = new byte[pCount];
pInput.readFully(ascii);
return StringUtil.decode(ascii, 0, ascii.length, "UTF-8"); // UTF-8 is ASCII compatible
- case 1:
+ case 1: // BYTE
if (pCount == 1) {
return pInput.readUnsignedByte();
}
- case 6:
+ // else fall through
+ case 6: // SBYTE
if (pCount == 1) {
return pInput.readByte();
}
- case 7:
+ // else fall through
+ case 7: // UNDEFINED
byte[] bytes = new byte[pCount];
pInput.readFully(bytes);
+
+ // NOTE: We don't change (unsigned) BYTE array wider Java type, as most often BYTE array means
+ // binary data and we want to keep that as a byte array for clients to parse futher
+
return bytes;
- case 3:
+ case 3: // SHORT
if (pCount == 1) {
return pInput.readUnsignedShort();
}
- case 8:
+ case 8: // SSHORT
if (pCount == 1) {
return pInput.readShort();
}
short[] shorts = new short[pCount];
pInput.readFully(shorts, 0, shorts.length);
+
+ if (pType == 3) {
+ int[] ints = new int[pCount];
+ for (int i = 0; i < pCount; i++) {
+ ints[i] = shorts[i] & 0xffff;
+ }
+ return ints;
+ }
+
return shorts;
- case 4:
+ case 13: // IFD
+ case 4: // LONG
if (pCount == 1) {
return pInput.readUnsignedInt();
}
- case 9:
+ case 9: // SLONG
if (pCount == 1) {
return pInput.readInt();
}
int[] ints = new int[pCount];
pInput.readFully(ints, 0, ints.length);
+
+ if (pType == 4 || pType == 13) {
+ long[] longs = new long[pCount];
+ for (int i = 0; i < pCount; i++) {
+ longs[i] = ints[i] & 0xffffffffL;
+ }
+ return longs;
+ }
+
return ints;
- case 11:
+ case 11: // FLOAT
if (pCount == 1) {
return pInput.readFloat();
}
@@ -195,7 +343,7 @@ public final class EXIFReader extends MetadataReader {
float[] floats = new float[pCount];
pInput.readFully(floats, 0, floats.length);
return floats;
- case 12:
+ case 12: // DOUBLE
if (pCount == 1) {
return pInput.readDouble();
}
@@ -204,7 +352,7 @@ public final class EXIFReader extends MetadataReader {
pInput.readFully(doubles, 0, doubles.length);
return doubles;
- case 5:
+ case 5: // RATIONAL
if (pCount == 1) {
return new Rational(pInput.readUnsignedInt(), pInput.readUnsignedInt());
}
@@ -215,7 +363,7 @@ public final class EXIFReader extends MetadataReader {
}
return rationals;
- case 10:
+ case 10: // SRATIONAL
if (pCount == 1) {
return new Rational(pInput.readInt(), pInput.readInt());
}
@@ -227,8 +375,32 @@ public final class EXIFReader extends MetadataReader {
return srationals;
+ // BigTiff:
+ case 16: // LONG8
+ case 17: // SLONG8
+ case 18: // IFD8
+ // TODO: Assert BigTiff (version == 43)
+
+ if (pCount == 1) {
+ long val = pInput.readLong();
+ if (pType != 17 && val < 0) {
+ throw new IIOException(String.format("Value > %s", Long.MAX_VALUE));
+ }
+ return val;
+ }
+
+ long[] longs = new long[pCount];
+ for (int i = 0; i < pCount; i++) {
+ longs[i] = pInput.readLong();
+ }
+
+ return longs;
+
default:
- throw new IIOException(String.format("Unknown EXIF type '%s'", pType));
+ // Spec says skip unknown values:
+ // TODO: Rather just return null, UNKNOWN_TYPE or new Unknown(type, count, offset) for value?
+ return new Unknown(pType, pCount, pos);
+// throw new IIOException(String.format("Unknown EXIF type '%s' at pos %d", pType, pInput.getStreamPosition()));
}
}
@@ -239,4 +411,115 @@ public final class EXIFReader extends MetadataReader {
return -1;
}
+
+ public static void main(String[] args) throws IOException {
+ EXIFReader reader = new EXIFReader();
+ ImageInputStream stream = ImageIO.createImageInputStream(new File(args[0]));
+
+ long pos = 0;
+ if (args.length > 1) {
+ if (args[1].startsWith("0x")) {
+ pos = Integer.parseInt(args[1].substring(2), 16);
+ }
+ else {
+ pos = Long.parseLong(args[1]);
+ }
+
+ stream.setByteOrder(pos < 0 ? ByteOrder.LITTLE_ENDIAN : ByteOrder.BIG_ENDIAN);
+
+ pos = Math.abs(pos);
+
+ stream.seek(pos);
+ }
+
+ try {
+ Directory directory;
+
+ if (args.length > 1) {
+ directory = reader.readDirectory(stream, pos);
+ }
+ else {
+ directory = reader.read(stream);
+ }
+
+ for (Entry entry : directory) {
+ System.err.println(entry);
+
+ Object value = entry.getValue();
+ if (value instanceof byte[]) {
+ byte[] bytes = (byte[]) value;
+ System.err.println(HexDump.dump(bytes, 0, Math.min(bytes.length, 128)));
+ }
+ }
+ }
+ finally {
+ stream.close();
+ }
+ }
+
+ //////////////////////
+ // TODO: Stream based hex dump util?
+ public static class HexDump {
+ private HexDump() {}
+
+ private static final int WIDTH = 32;
+
+ public static String dump(byte[] bytes) {
+ return dump(bytes, 0, bytes.length);
+ }
+
+ public static String dump(byte[] bytes, int off, int len) {
+ StringBuilder builder = new StringBuilder();
+
+ int i;
+ for (i = 0; i < len; i++) {
+ if (i % WIDTH == 0) {
+ if (i > 0 ) {
+ builder.append("\n");
+ }
+ builder.append(String.format("%08x: ", i + off));
+ }
+ else if (i > 0 && i % 2 == 0) {
+ builder.append(" ");
+ }
+
+ builder.append(String.format("%02x", bytes[i + off]));
+
+ int next = i + 1;
+ if (next % WIDTH == 0 || next == len) {
+ int leftOver = (WIDTH - (next % WIDTH)) % WIDTH;
+
+ if (leftOver != 0) {
+ // Pad: 5 spaces for every 2 bytes... Special care if padding is non-even.
+ int pad = leftOver / 2;
+
+ if (len % 2 != 0) {
+ builder.append(" ");
+ }
+
+ for (int j = 0; j < pad; j++) {
+ builder.append(" ");
+ }
+ }
+
+ builder.append(" ");
+ builder.append(toAsciiString(bytes, next - (WIDTH - leftOver) + off, next + off));
+ }
+ }
+
+ return builder.toString();
+ }
+
+ private static String toAsciiString(final byte[] bytes, final int from, final int to) {
+ byte[] range = Arrays.copyOfRange(bytes, from, to);
+
+ for (int i = 0; i < range.length; i++) {
+ if (range[i] < 32 || range[i] > 126) {
+ range[i] = '.'; // Unreadable char
+ }
+ }
+
+ return new String(range, Charset.forName("ascii"));
+ }
+ }
}
diff --git a/imageio/imageio-metadata/src/main/java/com/twelvemonkeys/imageio/metadata/exif/TIFF.java b/imageio/imageio-metadata/src/main/java/com/twelvemonkeys/imageio/metadata/exif/TIFF.java
index c7fc6e27..00194d2e 100644
--- a/imageio/imageio-metadata/src/main/java/com/twelvemonkeys/imageio/metadata/exif/TIFF.java
+++ b/imageio/imageio-metadata/src/main/java/com/twelvemonkeys/imageio/metadata/exif/TIFF.java
@@ -47,7 +47,7 @@ public interface TIFF {
5 = RATIONAL Two LONGs: the first represents the numerator of a
fraction; the second, the denominator.
- TIFF 6.0 and above:
+ TIFF 6.0 and above:
6 = SBYTE An 8-bit signed (twos-complement) integer.
7 = UNDEFINED An 8-bit byte that may contain anything, depending on
the definition of the field.
@@ -57,21 +57,39 @@ public interface TIFF {
fraction, the second the denominator.
11 = FLOAT Single precision (4-byte) IEEE format.
12 = DOUBLE Double precision (8-byte) IEEE format.
+
+ TODO: Verify IFD type
+ See http://www.awaresystems.be/imaging/tiff/tifftags/subifds.html
+ 13 = IFD, same as LONG
+
+ TODO: BigTiff specifies more types
+ See http://www.awaresystems.be/imaging/tiff/bigtiff.html, http://www.remotesensing.org/libtiff/bigtiffdesign.html
+ (what about 14-15??)
+ 16 = TIFF_LONG8, being unsigned 8byte integer
+ 17 = TIFF_SLONG8, being signed 8byte integer
+ 18 = TIFF_IFD8, being a new unsigned 8byte IFD offset.
+ Should probably all map to Java long (and fail if high bit is set for the unsigned types???)
*/
String[] TYPE_NAMES = {
"BYTE", "ASCII", "SHORT", "LONG", "RATIONAL",
-
"SBYTE", "UNDEFINED", "SSHORT", "SLONG", "SRATIONAL", "FLOAT", "DOUBLE",
+ "IFD",
+ null, null,
+ "LONG8", "SLONG8", "IFD8"
};
int[] TYPE_LENGTHS = {
1, 1, 2, 4, 8,
-
1, 1, 2, 4, 8, 4, 8,
+ 4,
+ -1, -1,
+ 8, 8, 8
};
- int IFD_EXIF = 0x8769;
- int IFD_GPS = 0x8825;
- int IFD_INTEROP = 0xA005;
+ /// EXIF defined TIFF tags
+
+ int TAG_EXIF_IFD = 34665;
+ int TAG_GPS_IFD = 34853;
+ int TAG_INTEROP_IFD = 40965;
/// A. Tags relating to image data structure:
@@ -114,4 +132,22 @@ public interface TIFF {
int TAG_SOFTWARE = 305;
int TAG_ARTIST = 315;
int TAG_COPYRIGHT = 33432;
+
+ int TAG_SUB_IFD = 330;
+
+ int TAG_XMP = 700;
+ int TAG_IPTC = 33723;
+ int TAG_PHOTOSHOP = 34377;
+ int TAG_ICC_PROFILE = 34675;
+
+ // Microsoft Office Document Imaging (MODI)
+ // http://msdn.microsoft.com/en-us/library/aa167596%28office.11%29.aspx
+ int TAG_MODI_BLC = 34718;
+ int TAG_MODI_VECTOR = 34719;
+ int TAG_MODI_PTC = 34720;
+
+ // http://blogs.msdn.com/b/openspecification/archive/2009/12/08/details-of-three-tiff-tag-extensions-that-microsoft-office-document-imaging-modi-software-may-write-into-the-tiff-files-it-generates.aspx
+ int TAG_MODI_PLAIN_TEXT = 37679;
+ int TAG_MODI_OLE_PROPERTY_SET = 37680;
+ int TAG_MODI_TEXT_POS_INFO = 37681;
}
diff --git a/imageio/imageio-metadata/src/main/java/com/twelvemonkeys/imageio/metadata/exif/Unknown.java b/imageio/imageio-metadata/src/main/java/com/twelvemonkeys/imageio/metadata/exif/Unknown.java
new file mode 100644
index 00000000..dc5fb965
--- /dev/null
+++ b/imageio/imageio-metadata/src/main/java/com/twelvemonkeys/imageio/metadata/exif/Unknown.java
@@ -0,0 +1,45 @@
+package com.twelvemonkeys.imageio.metadata.exif;
+
+/**
+ * Unknown
+ *
+ * @author Harald Kuhr
+ * @author last modified by $Author: haraldk$
+ * @version $Id: Unknown.java,v 1.0 Oct 8, 2010 3:38:45 PM haraldk Exp$
+ */
+final class Unknown {
+ private final short type;
+ private final int count;
+ private final long pos;
+
+ public Unknown(final short type, final int count, final long pos) {
+ this.type = type;
+ this.count = count;
+ this.pos = pos;
+ }
+
+ @Override
+ public int hashCode() {
+ return (int) (pos ^ (pos >>> 32)) + count * 37 + type * 97;
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (other != null && other.getClass() == getClass()){
+ Unknown unknown = (Unknown) other;
+ return pos == unknown.pos && type == unknown.type && count == unknown.count;
+ }
+
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ if (count == 1) {
+ return String.format("Unknown(%d)@%08x", type, pos);
+ }
+ else {
+ return String.format("Unknown(%d)[%d]@%08x", type, count, pos);
+ }
+ }
+}
diff --git a/imageio/imageio-metadata/src/main/java/com/twelvemonkeys/imageio/metadata/jpeg/JPEGSegmentUtil.java b/imageio/imageio-metadata/src/main/java/com/twelvemonkeys/imageio/metadata/jpeg/JPEGSegmentUtil.java
index 5e674057..9d1ba02f 100644
--- a/imageio/imageio-metadata/src/main/java/com/twelvemonkeys/imageio/metadata/jpeg/JPEGSegmentUtil.java
+++ b/imageio/imageio-metadata/src/main/java/com/twelvemonkeys/imageio/metadata/jpeg/JPEGSegmentUtil.java
@@ -49,12 +49,12 @@ public final class JPEGSegmentUtil {
private JPEGSegmentUtil() {}
- // TODO: Allow for multiple images (multiple SOI markers), using specified index?
- public static List readSegments(final ImageInputStream stream, final int appMarker, final String segmentName) throws IOException {
+ // TODO: Allow for multiple images (multiple SOI markers), using specified index, or document that stream must be placed before SOI of wanted image
+ public static List readSegments(final ImageInputStream stream, final int imageIndex, final int appMarker, final String segmentName) throws IOException {
return readSegments(stream, Collections.singletonMap(appMarker, Collections.singletonList(segmentName)));
}
- public static List readSegments(final ImageInputStream stream, Map> segmentIdentifiers) throws IOException {
+ public static List readSegments(final ImageInputStream stream, final Map> segmentIdentifiers) throws IOException {
readSOI(stream);
List segments = Collections.emptyList();
diff --git a/imageio/imageio-metadata/src/test/java/com/twelvemonkeys/imageio/metadata/xmp/XMPScannerTestCase.java b/imageio/imageio-metadata/src/test/java/com/twelvemonkeys/imageio/metadata/xmp/XMPScannerTestCase.java
index 9d4e9a96..4115998a 100644
--- a/imageio/imageio-metadata/src/test/java/com/twelvemonkeys/imageio/metadata/xmp/XMPScannerTestCase.java
+++ b/imageio/imageio-metadata/src/test/java/com/twelvemonkeys/imageio/metadata/xmp/XMPScannerTestCase.java
@@ -69,7 +69,7 @@ public class XMPScannerTestCase extends TestCase {
}
public void testScanForUTF8singleQuote() throws IOException {
- InputStream stream = createXMPStream(XMP, "UTF-8".replace("\"", "'"));
+ InputStream stream = createXMPStream(XMP.replace("\"", "'"), "UTF-8");
Reader reader = XMPScanner.scanForXMPPacket(stream);
@@ -85,7 +85,7 @@ public class XMPScannerTestCase extends TestCase {
}
public void testScanForUTF16BEsingleQuote() throws IOException {
- InputStream stream = createXMPStream(XMP, "UTF-16BE".replace("\"", "'"));
+ InputStream stream = createXMPStream(XMP.replace("\"", "'"), "UTF-16BE");
Reader reader = XMPScanner.scanForXMPPacket(stream);
@@ -101,7 +101,7 @@ public class XMPScannerTestCase extends TestCase {
}
public void testScanForUTF16LEsingleQuote() throws IOException {
- InputStream stream = createXMPStream(XMP, "UTF-16LE".replace("\"", "'"));
+ InputStream stream = createXMPStream(XMP.replace("\"", "'"), "UTF-16LE");
Reader reader = XMPScanner.scanForXMPPacket(stream);
diff --git a/imageio/imageio-pict/src/main/java/com/twelvemonkeys/imageio/plugins/pict/PICTImageReader.java b/imageio/imageio-pict/src/main/java/com/twelvemonkeys/imageio/plugins/pict/PICTImageReader.java
index bce32188..1ab9fff8 100644
--- a/imageio/imageio-pict/src/main/java/com/twelvemonkeys/imageio/plugins/pict/PICTImageReader.java
+++ b/imageio/imageio-pict/src/main/java/com/twelvemonkeys/imageio/plugins/pict/PICTImageReader.java
@@ -28,9 +28,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Parts of this software is based on JVG/JIS.
See http://www.cs.hut.fi/~framling/JVG/index.html for more information.
-Redistribution under BSD authorized by Kary Främling:
+Redistribution under BSD authorized by Kary Fr�mling:
-Copyright (c) 2003, Kary Främling
+Copyright (c) 2003, Kary Fr�mling
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -85,7 +85,7 @@ import java.util.List;
*
*
* @author Harald Kuhr
- * @author Kary Främling (original PICT/QuickDraw parsing)
+ * @author Kary Fr�mling (original PICT/QuickDraw parsing)
* @author Matthias Wiesmann (original embedded QuickTime parsing)
* @version $Id: PICTReader.java,v 1.0 05.apr.2006 15:20:48 haku Exp$
*/
@@ -151,7 +151,7 @@ public class PICTImageReader extends ImageReaderBase {
private Rectangle getPICTFrame() throws IOException {
if (mFrame == null) {
// Read in header information
- readPICTHeader(mImageInput);
+ readPICTHeader(imageInput);
if (DEBUG) {
System.out.println("Done reading PICT header!");
}
@@ -343,7 +343,7 @@ public class PICTImageReader extends ImageReaderBase {
private void drawOnto(Graphics2D pGraphics) throws IOException {
mContext = new QuickDrawContext(pGraphics);
- readPICTopcodes(mImageInput);
+ readPICTopcodes(imageInput);
if (DEBUG) {
System.out.println("Done reading PICT body!");
}
@@ -1666,7 +1666,7 @@ public class PICTImageReader extends ImageReaderBase {
catch (EOFException e) {
String pos;
try {
- pos = String.format("position %d", mImageInput.getStreamPosition());
+ pos = String.format("position %d", imageInput.getStreamPosition());
}
catch (IOException ignore) {
pos = "unknown position";
@@ -1977,7 +1977,7 @@ public class PICTImageReader extends ImageReaderBase {
unPackBits.readFully(pixArray, pixBufOffset, pBounds.width);
/*}
else {
- mImageInput.readFully(dstBytes);
+ imageInput.readFully(dstBytes);
}*/
// TODO: Use TYPE_USHORT_555_RGB for 16 bit
@@ -2294,7 +2294,7 @@ public class PICTImageReader extends ImageReaderBase {
unPackBits.readFully(dstBytes);
}
else {
- mImageInput.readFully(dstBytes);
+ imageInput.readFully(dstBytes);
}
if (packType == 3) {
diff --git a/imageio/imageio-pict/src/main/java/com/twelvemonkeys/imageio/plugins/pict/PICTImageWriter.java b/imageio/imageio-pict/src/main/java/com/twelvemonkeys/imageio/plugins/pict/PICTImageWriter.java
index 9149fb5b..84d6267c 100755
--- a/imageio/imageio-pict/src/main/java/com/twelvemonkeys/imageio/plugins/pict/PICTImageWriter.java
+++ b/imageio/imageio-pict/src/main/java/com/twelvemonkeys/imageio/plugins/pict/PICTImageWriter.java
@@ -28,9 +28,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Parts of this software is based on JVG/JIS.
See http://www.cs.hut.fi/~framling/JVG/index.html for more information.
-Redistribution under BSD authorized by Kary Främling:
+Redistribution under BSD authorized by Kary Fr�mling:
-Copyright (c) 2003, Kary Främling
+Copyright (c) 2003, Kary Fr�mling
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -79,7 +79,7 @@ import java.io.*;
* Images are stored using the "opDirectBitsRect" opcode, which directly
* stores RGB values (using PackBits run-length encoding).
*
- * @author Kary Främling
+ * @author Kary Fr�mling
* @author Harald Kuhr
* @version $Id: PICTWriter.java,v 1.0 05.apr.2006 15:20:48 haku Exp$
*/
@@ -116,121 +116,121 @@ public class PICTImageWriter extends ImageWriterBase {
// TODO: Make 512 byte header optional
// Write empty 512-byte header
byte[] buf = new byte[PICT.PICT_NULL_HEADER_SIZE];
- mImageOutput.write(buf);
+ imageOutput.write(buf);
// Write out the size, leave as 0, this is ok
- mImageOutput.writeShort(0);
+ imageOutput.writeShort(0);
// Write image frame (same as image bounds)
- mImageOutput.writeShort(0);
- mImageOutput.writeShort(0);
- mImageOutput.writeShort(pImage.getHeight());
- mImageOutput.writeShort(pImage.getWidth());
+ imageOutput.writeShort(0);
+ imageOutput.writeShort(0);
+ imageOutput.writeShort(pImage.getHeight());
+ imageOutput.writeShort(pImage.getWidth());
// Write version, version 2
- mImageOutput.writeShort(PICT.OP_VERSION);
- mImageOutput.writeShort(PICT.OP_VERSION_2);
+ imageOutput.writeShort(PICT.OP_VERSION);
+ imageOutput.writeShort(PICT.OP_VERSION_2);
// Version 2 HEADER_OP, extended version.
- mImageOutput.writeShort(PICT.OP_HEADER_OP);
- mImageOutput.writeInt(PICT.HEADER_V2_EXT); // incl 2 bytes reseverd
+ imageOutput.writeShort(PICT.OP_HEADER_OP);
+ imageOutput.writeInt(PICT.HEADER_V2_EXT); // incl 2 bytes reseverd
// Image resolution, 72 dpi
- mImageOutput.writeShort(PICT.MAC_DEFAULT_DPI);
- mImageOutput.writeShort(0);
- mImageOutput.writeShort(PICT.MAC_DEFAULT_DPI);
- mImageOutput.writeShort(0);
+ imageOutput.writeShort(PICT.MAC_DEFAULT_DPI);
+ imageOutput.writeShort(0);
+ imageOutput.writeShort(PICT.MAC_DEFAULT_DPI);
+ imageOutput.writeShort(0);
// Optimal source rectangle (same as image bounds)
- mImageOutput.writeShort(0);
- mImageOutput.writeShort(0);
- mImageOutput.writeShort(pImage.getHeight());
- mImageOutput.writeShort(pImage.getWidth());
+ imageOutput.writeShort(0);
+ imageOutput.writeShort(0);
+ imageOutput.writeShort(pImage.getHeight());
+ imageOutput.writeShort(pImage.getWidth());
// Reserved (4 bytes)
- mImageOutput.writeInt(0);
+ imageOutput.writeInt(0);
// TODO: The header really ends here...
// Highlight
- mImageOutput.writeShort(PICT.OP_DEF_HILITE);
+ imageOutput.writeShort(PICT.OP_DEF_HILITE);
// Set the clip rectangle
- mImageOutput.writeShort(PICT.OP_CLIP_RGN);
- mImageOutput.writeShort(10);
- mImageOutput.writeShort(0);
- mImageOutput.writeShort(0);
- mImageOutput.writeShort(pImage.getHeight());
- mImageOutput.writeShort(pImage.getWidth());
+ imageOutput.writeShort(PICT.OP_CLIP_RGN);
+ imageOutput.writeShort(10);
+ imageOutput.writeShort(0);
+ imageOutput.writeShort(0);
+ imageOutput.writeShort(pImage.getHeight());
+ imageOutput.writeShort(pImage.getWidth());
// Pixmap operation
- mImageOutput.writeShort(PICT.OP_DIRECT_BITS_RECT);
+ imageOutput.writeShort(PICT.OP_DIRECT_BITS_RECT);
// PixMap pointer (always 0x000000FF);
- mImageOutput.writeInt(0x000000ff);
+ imageOutput.writeInt(0x000000ff);
// Write rowBytes, this is 4 times the width.
// Set the high bit, to indicate a PixMap.
mRowBytes = 4 * pImage.getWidth();
- mImageOutput.writeShort(0x8000 | mRowBytes);
+ imageOutput.writeShort(0x8000 | mRowBytes);
// Write bounds rectangle (same as image bounds)
- mImageOutput.writeShort(0);
- mImageOutput.writeShort(0);
- mImageOutput.writeShort(pImage.getHeight()); // TODO: Handle overflow?
- mImageOutput.writeShort(pImage.getWidth());
+ imageOutput.writeShort(0);
+ imageOutput.writeShort(0);
+ imageOutput.writeShort(pImage.getHeight()); // TODO: Handle overflow?
+ imageOutput.writeShort(pImage.getWidth());
// PixMap record version
- mImageOutput.writeShort(0);
+ imageOutput.writeShort(0);
// Packing format (always 4: PackBits)
- mImageOutput.writeShort(4);
+ imageOutput.writeShort(4);
// Size of packed data (leave as 0)
- mImageOutput.writeInt(0);
+ imageOutput.writeInt(0);
// Pixmap resolution, 72 dpi
- mImageOutput.writeShort(PICT.MAC_DEFAULT_DPI);
- mImageOutput.writeShort(0);
- mImageOutput.writeShort(PICT.MAC_DEFAULT_DPI);
- mImageOutput.writeShort(0);
+ imageOutput.writeShort(PICT.MAC_DEFAULT_DPI);
+ imageOutput.writeShort(0);
+ imageOutput.writeShort(PICT.MAC_DEFAULT_DPI);
+ imageOutput.writeShort(0);
// Pixel type, 16 is allright for direct pixels
- mImageOutput.writeShort(16);
+ imageOutput.writeShort(16);
// Pixel size
- mImageOutput.writeShort(32);
+ imageOutput.writeShort(32);
// TODO: Allow alpha? Allow 5 bit per pixel component (16 bit)?
// Pixel component count
- mImageOutput.writeShort(3);
+ imageOutput.writeShort(3);
// Pixel component size
- mImageOutput.writeShort(8);
+ imageOutput.writeShort(8);
// PlaneBytes, ignored for now
- mImageOutput.writeInt(0);
+ imageOutput.writeInt(0);
// TODO: Allow IndexColorModel?
// ColorTable record (for RGB direct pixels, just write 0)
- mImageOutput.writeInt(0);
+ imageOutput.writeInt(0);
// Reserved (4 bytes)
- mImageOutput.writeInt(0);
+ imageOutput.writeInt(0);
// Source and dest rect (both are same as image bounds)
- mImageOutput.writeShort(0);
- mImageOutput.writeShort(0);
- mImageOutput.writeShort(pImage.getHeight());
- mImageOutput.writeShort(pImage.getWidth());
+ imageOutput.writeShort(0);
+ imageOutput.writeShort(0);
+ imageOutput.writeShort(pImage.getHeight());
+ imageOutput.writeShort(pImage.getWidth());
- mImageOutput.writeShort(0);
- mImageOutput.writeShort(0);
- mImageOutput.writeShort(pImage.getHeight());
- mImageOutput.writeShort(pImage.getWidth());
+ imageOutput.writeShort(0);
+ imageOutput.writeShort(0);
+ imageOutput.writeShort(pImage.getHeight());
+ imageOutput.writeShort(pImage.getWidth());
// Transfer mode
- mImageOutput.writeShort(QuickDraw.SRC_COPY);
+ imageOutput.writeShort(QuickDraw.SRC_COPY);
// TODO: Move to writePICTData?
// TODO: Alpha support
@@ -282,13 +282,13 @@ public class PICTImageWriter extends ImageWriterBase {
packBits.write(mScanlineBytes);
if (mRowBytes > 250) {
- mImageOutput.writeShort(bytes.size());
+ imageOutput.writeShort(bytes.size());
}
else {
- mImageOutput.writeByte(bytes.size());
+ imageOutput.writeByte(bytes.size());
}
- bytes.writeTo(IIOUtil.createStreamAdapter(mImageOutput));
+ bytes.writeTo(IIOUtil.createStreamAdapter(imageOutput));
mScanWidthLeft = w;
}
@@ -327,13 +327,13 @@ public class PICTImageWriter extends ImageWriterBase {
packBits.write(mScanlineBytes);
if (mRowBytes > 250) {
- mImageOutput.writeShort(bytes.size());
+ imageOutput.writeShort(bytes.size());
}
else {
- mImageOutput.writeByte(bytes.size());
+ imageOutput.writeByte(bytes.size());
}
- bytes.writeTo(IIOUtil.createStreamAdapter(mImageOutput));
+ bytes.writeTo(IIOUtil.createStreamAdapter(imageOutput));
mScanWidthLeft = w;
}
@@ -342,15 +342,15 @@ public class PICTImageWriter extends ImageWriterBase {
private void writePICTTrailer() throws IOException {
// Write out end opcode. Be sure to be word-aligned.
- long length = mImageOutput.length();
+ long length = imageOutput.length();
if (length == -1) {
throw new IIOException("Cannot write trailer without knowing length");
}
if ((length & 1) > 0) {
- mImageOutput.writeByte(0);
+ imageOutput.writeByte(0);
}
- mImageOutput.writeShort(PICT.OP_END_OF_PICTURE);
+ imageOutput.writeShort(PICT.OP_END_OF_PICTURE);
}
public void write(IIOMetadata pStreamMetadata, IIOImage pImage, ImageWriteParam pParam) throws IOException {
diff --git a/imageio/imageio-psd/src/main/java/com/twelvemonkeys/imageio/plugins/psd/PSDImageReader.java b/imageio/imageio-psd/src/main/java/com/twelvemonkeys/imageio/plugins/psd/PSDImageReader.java
index 6adb8e65..81c41483 100644
--- a/imageio/imageio-psd/src/main/java/com/twelvemonkeys/imageio/plugins/psd/PSDImageReader.java
+++ b/imageio/imageio-psd/src/main/java/com/twelvemonkeys/imageio/plugins/psd/PSDImageReader.java
@@ -30,6 +30,7 @@ package com.twelvemonkeys.imageio.plugins.psd;
import com.twelvemonkeys.image.ImageUtil;
import com.twelvemonkeys.imageio.ImageReaderBase;
+import com.twelvemonkeys.imageio.color.ColorSpaces;
import com.twelvemonkeys.imageio.util.IndexedImageTypeSpecifier;
import com.twelvemonkeys.xml.XMLSerializer;
import org.w3c.dom.Node;
@@ -63,6 +64,7 @@ import java.util.List;
*/
// TODO: Implement ImageIO meta data interface
// TODO: Allow reading the extra alpha channels (index after composite data)
+// TODO: Figure out of we should assume Adobe RGB (1998) color model, if no embedded profile?
// TODO: Support for PSDVersionInfo hasRealMergedData=false (no real composite data, layers will be in index 0)
// TODO: Support for API for reading separate layers (index after composite data, and optional alpha channels)
// TODO: Consider Romain Guy's Java 2D implementation of PS filters for the blending modes in layers
@@ -151,6 +153,7 @@ public class PSDImageReader extends ImageReaderBase {
case PSD.COLOR_MODE_RGB:
cs = getEmbeddedColorSpace();
if (cs == null) {
+ // TODO: Should probably be Adobe RGB (1998), not sRGB. Or..?
cs = ColorSpace.getInstance(ColorSpace.CS_sRGB);
}
@@ -174,7 +177,7 @@ public class PSDImageReader extends ImageReaderBase {
case PSD.COLOR_MODE_CMYK:
cs = getEmbeddedColorSpace();
if (cs == null) {
- cs = CMYKColorSpace.getInstance();
+ cs = ColorSpaces.getColorSpace(ColorSpaces.CS_GENERIC_CMYK);
}
if (mHeader.mChannels == 4 && mHeader.mBits == 8) {
@@ -198,6 +201,7 @@ public class PSDImageReader extends ImageReaderBase {
// TODO: Implement
case PSD.COLOR_MODE_LAB:
// TODO: Implement
+ // TODO: If there's a color profile embedded, it should be easy, otherwise we're out of luck...
default:
throw new IIOException(
String.format("Unsupported PSD MODE: %s (%d channels/%d bits)", mHeader.mMode, mHeader.mChannels, mHeader.mBits)
@@ -219,12 +223,26 @@ public class PSDImageReader extends ImageReaderBase {
case PSD.COLOR_MODE_RGB:
// Prefer interleaved versions as they are much faster to display
if (mHeader.mChannels == 3 && mHeader.mBits == 8) {
- // Basically same as BufferedImage.TYPE_3BYTE_BGR
- types.add(ImageTypeSpecifier.createInterleaved(cs, new int[] {2, 1, 0}, DataBuffer.TYPE_BYTE, false, false));
+ // TODO: ColorConvertOp to CS_sRGB
+ // TODO: Integer raster
+ // types.add(ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.INT_RGB));
+ types.add(ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_3BYTE_BGR));
+
+ if (!cs.isCS_sRGB()) {
+ // Basically BufferedImage.TYPE_3BYTE_BGR, with corrected ColorSpace. Possibly slow.
+ types.add(ImageTypeSpecifier.createInterleaved(cs, new int[] {2, 1, 0}, DataBuffer.TYPE_BYTE, false, false));
+ }
}
else if (mHeader.mChannels >= 4 && mHeader.mBits == 8) {
- // Basically same as BufferedImage.TYPE_4BYTE_ABGR
- types.add(ImageTypeSpecifier.createInterleaved(cs, new int[] {3, 2, 1, 0}, DataBuffer.TYPE_BYTE, true, false));
+ // TODO: ColorConvertOp to CS_sRGB
+ // TODO: Integer raster
+ // types.add(ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.INT_ARGB));
+ types.add(ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_4BYTE_ABGR));
+//
+ if (!cs.isCS_sRGB()) {
+ // Basically BufferedImage.TYPE_4BYTE_ABGR, with corrected ColorSpace. Possibly slow.
+ types.add(ImageTypeSpecifier.createInterleaved(cs, new int[] {3, 2, 1, 0}, DataBuffer.TYPE_BYTE, true, false));
+ }
}
else if (mHeader.mChannels == 3 && mHeader.mBits == 16) {
types.add(ImageTypeSpecifier.createInterleaved(cs, new int[] {2, 1, 0}, DataBuffer.TYPE_USHORT, false, false));
@@ -235,9 +253,11 @@ public class PSDImageReader extends ImageReaderBase {
break;
case PSD.COLOR_MODE_CMYK:
// Prefer interleaved versions as they are much faster to display
+ // TODO: ColorConvertOp to CS_sRGB
// TODO: We should convert these to their RGB equivalents while reading for the common-case,
// as Java2D is extremely slow displaying custom images.
// 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 :-/
if (mHeader.mChannels == 4 && mHeader.mBits == 8) {
types.add(ImageTypeSpecifier.createInterleaved(cs, new int[] {3, 2, 1, 0}, DataBuffer.TYPE_BYTE, false, false));
}
@@ -255,7 +275,7 @@ public class PSDImageReader extends ImageReaderBase {
// Just stick to the raw type
}
- // Finally add the
+ // Finally add the raw type
types.add(rawType);
return types.iterator();
@@ -275,7 +295,7 @@ public class PSDImageReader extends ImageReaderBase {
}
}
- mColorSpace = profile == null ? null : new ICC_ColorSpace(profile);
+ mColorSpace = profile == null ? null : ColorSpaces.createColorSpace(profile);
}
return mColorSpace;
@@ -307,6 +327,8 @@ public class PSDImageReader extends ImageReaderBase {
// Otherwise, copy "through" ColorModel?
// Copy pixels from temp raster
// If possible, leave the destination image "untouched" (accelerated)
+ // See Jim Grahams comments:
+ // http://forums.java.net/jive/message.jspa?messageID=295758#295758
// TODO: Doing a per line color convert will be expensive, as data is channelled...
// Will need to either convert entire image, or skip back/forth between channels...
@@ -336,7 +358,7 @@ public class PSDImageReader extends ImageReaderBase {
processImageStarted(pIndex);
int[] byteCounts = null;
- int compression = mImageInput.readShort();
+ int compression = imageInput.readShort();
// TODO: Need to make sure compression is set in metadata, even without reading the image data!
mMetadata.mCompression = compression;
@@ -347,7 +369,7 @@ public class PSDImageReader extends ImageReaderBase {
// NOTE: Byte counts will allow us to easily skip rows before AOI
byteCounts = new int[mHeader.mChannels * mHeader.mHeight];
for (int i = 0; i < byteCounts.length; i++) {
- byteCounts[i] = mImageInput.readUnsignedShort();
+ byteCounts[i] = imageInput.readUnsignedShort();
}
break;
case PSD.COMPRESSION_ZIP:
@@ -400,24 +422,15 @@ public class PSDImageReader extends ImageReaderBase {
switch (mHeader.mBits) {
case 1:
byte[] row1 = ((DataBufferByte) rowRaster.getDataBuffer()).getData();
- DataBufferByte buffer1 = (DataBufferByte) raster.getDataBuffer();
- byte[] data1 = banded ? buffer1.getData(c) : buffer1.getData();
-
- read1bitChannel(c, mHeader.mChannels, data1, interleavedBands, bandOffset, pSourceCM, row1, pSource, pDest, pXSub, pYSub, mHeader.mWidth, mHeader.mHeight, pByteCounts, pCompression == PSD.COMPRESSION_RLE);
+ read1bitChannel(c, mHeader.mChannels, raster.getDataBuffer(), interleavedBands, bandOffset, pSourceCM, row1, pSource, pDest, pXSub, pYSub, mHeader.mWidth, mHeader.mHeight, pByteCounts, pCompression == PSD.COMPRESSION_RLE);
break;
case 8:
byte[] row8 = ((DataBufferByte) rowRaster.getDataBuffer()).getData();
- DataBufferByte buffer8 = (DataBufferByte) raster.getDataBuffer();
- byte[] data8 = banded ? buffer8.getData(c) : buffer8.getData();
-
- read8bitChannel(c, mHeader.mChannels, data8, interleavedBands, bandOffset, pSourceCM, row8, pSource, pDest, pXSub, pYSub, mHeader.mWidth, mHeader.mHeight, pByteCounts, c * mHeader.mHeight, pCompression == PSD.COMPRESSION_RLE);
+ 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);
break;
case 16:
short[] row16 = ((DataBufferUShort) rowRaster.getDataBuffer()).getData();
- DataBufferUShort buffer16 = (DataBufferUShort) raster.getDataBuffer();
- short[] data16 = banded ? buffer16.getData(c) : buffer16.getData();
-
- read16bitChannel(c, mHeader.mChannels, data16, interleavedBands, bandOffset, pSourceCM, row16, pSource, pDest, pXSub, pYSub, mHeader.mWidth, mHeader.mHeight, pByteCounts, c * mHeader.mHeight, pCompression == PSD.COMPRESSION_RLE);
+ read16bitChannel(c, mHeader.mChannels, raster.getDataBuffer(), interleavedBands, bandOffset, pSourceCM, row16, pSource, pDest, pXSub, pYSub, mHeader.mWidth, mHeader.mHeight, pByteCounts, c * mHeader.mHeight, pCompression == PSD.COMPRESSION_RLE);
break;
default:
throw new IIOException(String.format("Unknown PSD bit depth: %s", mHeader.mBits));
@@ -430,12 +443,16 @@ public class PSDImageReader extends ImageReaderBase {
if (mHeader.mBits == 8) {
// Compose out the background of the semi-transparent pixels, as PS somehow has the background composed in
- decomposeAlpha(destCM, (DataBufferByte) raster.getDataBuffer(), pDest.width, pDest.height, raster.getNumBands());
+ decomposeAlpha(destCM, raster.getDataBuffer(), pDest.width, pDest.height, raster.getNumBands());
}
}
+ private void processImageProgressForChannel(int channel, int channelCount, int y, int height) {
+ processImageProgress(100f * channel / channelCount + 100f * y / (height * channelCount));
+ }
+
private void read16bitChannel(final int pChannel, final int pChannelCount,
- final short[] pData, final int pBands, final int pBandOffset,
+ final DataBuffer pData, final int pBands, final int pBandOffset,
final ColorModel pSourceColorModel,
final short[] pRow,
final Rectangle pSource, final Rectangle pDest,
@@ -446,6 +463,7 @@ public class PSDImageReader extends ImageReaderBase {
final boolean isCMYK = pSourceColorModel.getColorSpace().getType() == ColorSpace.TYPE_CMYK;
final int colorComponents = pSourceColorModel.getColorSpace().getNumComponents();
+ final boolean banded = pData.getNumBanks() > 1;
for (int y = 0; y < pChannelHeight; y++) {
// NOTE: Length is in *16 bit values* (shorts)
@@ -455,7 +473,7 @@ public class PSDImageReader extends ImageReaderBase {
// Read entire line, if within source region and sampling
if (y >= pSource.y && y < pSource.y + pSource.height && y % pYSub == 0) {
if (pRLECompressed) {
- DataInputStream input = PSDUtil.createPackBitsStream(mImageInput, length);
+ DataInputStream input = PSDUtil.createPackBitsStream(imageInput, length);
try {
for (int x = 0; x < pChannelWidth; x++) {
pRow[x] = input.readShort();
@@ -466,7 +484,7 @@ public class PSDImageReader extends ImageReaderBase {
}
}
else {
- mImageInput.readFully(pRow, 0, pChannelWidth);
+ imageInput.readFully(pRow, 0, pChannelWidth);
}
// TODO: Destination offset...??
@@ -480,22 +498,22 @@ public class PSDImageReader extends ImageReaderBase {
value = (short) (65535 - value & 0xffff);
}
- pData[offset + x * pBands] = value;
+ pData.setElem(banded ? pChannel : 0, offset + x * pBands, value);
}
}
else {
- mImageInput.skipBytes(length);
+ imageInput.skipBytes(length);
}
if (abortRequested()) {
break;
}
- processImageProgress((pChannel * y * 100) / pChannelCount * pChannelHeight);
+ processImageProgressForChannel(pChannel, pChannelCount, y, pChannelHeight);
}
}
private void read8bitChannel(final int pChannel, final int pChannelCount,
- final byte[] pData, final int pBands, final int pBandOffset,
+ final DataBuffer pData, final int pBands, final int pBandOffset,
final ColorModel pSourceColorModel,
final byte[] pRow,
final Rectangle pSource, final Rectangle pDest,
@@ -506,6 +524,7 @@ public class PSDImageReader extends ImageReaderBase {
final boolean isCMYK = pSourceColorModel.getColorSpace().getType() == ColorSpace.TYPE_CMYK;
final int colorComponents = pSourceColorModel.getColorSpace().getNumComponents();
+ final boolean banded = pData.getNumBanks() > 1;
for (int y = 0; y < pChannelHeight; y++) {
int length = pRLECompressed ? pRowByteCounts[pRowOffset + y] : pChannelWidth;
@@ -514,7 +533,7 @@ public class PSDImageReader extends ImageReaderBase {
// Read entire line, if within source region and sampling
if (y >= pSource.y && y < pSource.y + pSource.height && y % pYSub == 0) {
if (pRLECompressed) {
- DataInputStream input = PSDUtil.createPackBitsStream(mImageInput, length);
+ DataInputStream input = PSDUtil.createPackBitsStream(imageInput, length);
try {
input.readFully(pRow, 0, pChannelWidth);
}
@@ -523,7 +542,7 @@ public class PSDImageReader extends ImageReaderBase {
}
}
else {
- mImageInput.readFully(pRow, 0, pChannelWidth);
+ imageInput.readFully(pRow, 0, pChannelWidth);
}
// TODO: If banded and not sub sampling/cmyk, we could just copy using System.arraycopy
@@ -538,23 +557,23 @@ public class PSDImageReader extends ImageReaderBase {
value = (byte) (255 - value & 0xff);
}
- pData[offset + x * pBands] = value;
+ pData.setElem(banded ? pChannel : 0, offset + x * pBands, value);
}
}
else {
- mImageInput.skipBytes(length);
+ imageInput.skipBytes(length);
}
if (abortRequested()) {
break;
}
- processImageProgress((pChannel * y * 100) / pChannelCount * pChannelHeight);
+ processImageProgressForChannel(pChannel, pChannelCount, y, pChannelHeight);
}
}
@SuppressWarnings({"UnusedDeclaration"})
private void read1bitChannel(final int pChannel, final int pChannelCount,
- final byte[] pData, final int pBands, final int pBandOffset,
+ final DataBuffer pData, final int pBands, final int pBandOffset,
final ColorModel pSourceColorModel,
final byte[] pRow,
final Rectangle pSource, final Rectangle pDest,
@@ -564,6 +583,7 @@ public class PSDImageReader extends ImageReaderBase {
// NOTE: 1 bit channels only occurs once
final int destWidth = (pDest.width + 7) / 8;
+ final boolean banded = pData.getNumBanks() > 1;
for (int y = 0; y < pChannelHeight; y++) {
int length = pRLECompressed ? pRowByteCounts[y] : pChannelWidth;
@@ -572,7 +592,7 @@ public class PSDImageReader extends ImageReaderBase {
// Read entire line, if within source region and sampling
if (y >= pSource.y && y < pSource.y + pSource.height && y % pYSub == 0) {
if (pRLECompressed) {
- DataInputStream input = PSDUtil.createPackBitsStream(mImageInput, length);
+ DataInputStream input = PSDUtil.createPackBitsStream(imageInput, length);
try {
input.readFully(pRow, 0, pRow.length);
}
@@ -581,7 +601,7 @@ public class PSDImageReader extends ImageReaderBase {
}
}
else {
- mImageInput.readFully(pRow, 0, pRow.length);
+ imageInput.readFully(pRow, 0, pRow.length);
}
// TODO: Destination offset...??
@@ -591,7 +611,7 @@ public class PSDImageReader extends ImageReaderBase {
for (int i = 0; i < destWidth; i++) {
byte value = pRow[pSource.x / 8 + i * pXSub];
// NOTE: Invert bits to match Java's default monochrome
- pData[offset + i] = (byte) (~value & 0xff);
+ pData.setElem(banded ? pChannel : 0, offset + i, (byte) (~value & 0xff));
}
}
else {
@@ -615,22 +635,22 @@ public class PSDImageReader extends ImageReaderBase {
}
// NOTE: Invert bits to match Java's default monochrome
- pData[offset + i] = (byte) (~result & 0xff);
+ pData.setElem(banded ? pChannel : 0, offset + i, (byte) (~result & 0xff));
}
}
}
else {
- mImageInput.skipBytes(length);
+ imageInput.skipBytes(length);
}
if (abortRequested()) {
break;
}
- processImageProgress((pChannel * y * 100) / pChannelCount * pChannelHeight);
+ processImageProgressForChannel(pChannel, pChannelCount, y, pChannelHeight);
}
}
- private void decomposeAlpha(final ColorModel pModel, final DataBufferByte pBuffer,
+ private void decomposeAlpha(final ColorModel pModel, final DataBuffer pBuffer,
final int pWidth, final int pHeight, final int pChannels) {
// TODO: Is the document background always white!?
// TODO: What about CMYK + alpha?
@@ -638,48 +658,45 @@ public class PSDImageReader extends ImageReaderBase {
// TODO: Probably faster to do this in line..
if (pBuffer.getNumBanks() > 1) {
- byte[][] data = pBuffer.getBankData();
for (int y = 0; y < pHeight; y++) {
for (int x = 0; x < pWidth; x++) {
int offset = (x + y * pWidth);
// ARGB format
- int alpha = data[pChannels - 1][offset] & 0xff;
+ int alpha = pBuffer.getElem(pChannels - 1, offset) & 0xff;
if (alpha != 0) {
double normalizedAlpha = alpha / 255.0;
for (int i = 0; i < pChannels - 1; i++) {
- data[i][offset] = decompose(data[i][offset] & 0xff, normalizedAlpha);
+ pBuffer.setElem(i, offset, decompose(pBuffer.getElem(i, offset) & 0xff, normalizedAlpha));
}
}
else {
for (int i = 0; i < pChannels - 1; i++) {
- data[i][offset] = 0;
+ pBuffer.setElem(i, offset, 0);
}
}
}
}
}
else {
- byte[] data = pBuffer.getData();
-
for (int y = 0; y < pHeight; y++) {
for (int x = 0; x < pWidth; x++) {
int offset = (x + y * pWidth) * pChannels;
// ABGR format
- int alpha = data[offset] & 0xff;
+ int alpha = pBuffer.getElem(offset) & 0xff;
if (alpha != 0) {
double normalizedAlpha = alpha / 255.0;
for (int i = 1; i < pChannels; i++) {
- data[offset + i] = decompose(data[offset + i] & 0xff, normalizedAlpha);
+ pBuffer.setElem(offset + i, decompose(pBuffer.getElem(offset + i) & 0xff, normalizedAlpha));
}
}
else {
for (int i = 1; i < pChannels; i++) {
- data[offset + i] = 0;
+ pBuffer.setElem(offset + i, 0);
}
}
}
@@ -697,7 +714,7 @@ public class PSDImageReader extends ImageReaderBase {
private void readHeader() throws IOException {
assertInput();
if (mHeader == null) {
- mHeader = new PSDHeader(mImageInput);
+ mHeader = new PSDHeader(imageInput);
mMetadata = new PSDMetadata();
mMetadata.mHeader = mHeader;
@@ -714,17 +731,17 @@ public class PSDImageReader extends ImageReaderBase {
around as a black box for use when saving the file.
*/
if (mHeader.mMode == PSD.COLOR_MODE_INDEXED) {
- mMetadata.mColorData = new PSDColorData(mImageInput);
+ mMetadata.mColorData = new PSDColorData(imageInput);
}
else {
// TODO: We need to store the duotone spec if we decide to create a writer...
// Skip color mode data for other modes
- long length = mImageInput.readUnsignedInt();
- mImageInput.skipBytes(length);
+ long length = imageInput.readUnsignedInt();
+ imageInput.skipBytes(length);
}
// Don't need the header again
- mImageInput.flushBefore(mImageInput.getStreamPosition());
+ imageInput.flushBefore(imageInput.getStreamPosition());
}
}
@@ -732,40 +749,40 @@ public class PSDImageReader extends ImageReaderBase {
// TODO: Obey ignoreMetadata
private void readImageResources(final boolean pParseData) throws IOException {
// TODO: Avoid unnecessary stream repositioning
- long pos = mImageInput.getFlushedPosition();
- mImageInput.seek(pos);
+ long pos = imageInput.getFlushedPosition();
+ imageInput.seek(pos);
- long length = mImageInput.readUnsignedInt();
+ long length = imageInput.readUnsignedInt();
if (pParseData && length > 0) {
if (mMetadata.mImageResources == null) {
mMetadata.mImageResources = new ArrayList();
- long expectedEnd = mImageInput.getStreamPosition() + length;
+ long expectedEnd = imageInput.getStreamPosition() + length;
- while (mImageInput.getStreamPosition() < expectedEnd) {
+ while (imageInput.getStreamPosition() < expectedEnd) {
// TODO: Have PSDImageResources defer actual parsing? (Just store stream offsets)
- PSDImageResource resource = PSDImageResource.read(mImageInput);
+ PSDImageResource resource = PSDImageResource.read(imageInput);
mMetadata.mImageResources.add(resource);
}
- if (mImageInput.getStreamPosition() != expectedEnd) {
+ if (imageInput.getStreamPosition() != expectedEnd) {
throw new IIOException("Corrupt PSD document"); // ..or maybe just a bug in the reader.. ;-)
}
}
}
- mImageInput.seek(pos + length + 4);
+ imageInput.seek(pos + length + 4);
}
// TODO: Flags or list of interesting resources to parse
// TODO: Obey ignoreMetadata
private void readLayerAndMaskInfo(final boolean pParseData) throws IOException {
// TODO: Make sure we are positioned correctly
- long length = mImageInput.readUnsignedInt();
+ long length = imageInput.readUnsignedInt();
if (pParseData && length > 0) {
- long pos = mImageInput.getStreamPosition();
+ long pos = imageInput.getStreamPosition();
- long layerInfoLength = mImageInput.readUnsignedInt();
+ long layerInfoLength = imageInput.readUnsignedInt();
/*
"Layer count. If it is a negative number, its absolute value is the number of
@@ -773,19 +790,19 @@ public class PSDImageReader extends ImageReaderBase {
merged result."
*/
// TODO: Figure out what the last part of that sentence means in practice...
- int layers = mImageInput.readShort();
+ int layers = imageInput.readShort();
PSDLayerInfo[] layerInfos = new PSDLayerInfo[Math.abs(layers)];
for (int i = 0; i < layerInfos.length; i++) {
- layerInfos[i] = new PSDLayerInfo(mImageInput);
+ layerInfos[i] = new PSDLayerInfo(imageInput);
}
mMetadata.mLayerInfo = Arrays.asList(layerInfos);
// TODO: Clean-up
- mImageInput.mark();
+ imageInput.mark();
ImageTypeSpecifier raw = getRawImageTypeInternal(0);
ImageTypeSpecifier imageType = getImageTypes(0).next();
- mImageInput.reset();
+ imageInput.reset();
for (PSDLayerInfo layerInfo : layerInfos) {
// TODO: If not explicitly needed, skip layers...
@@ -797,30 +814,30 @@ public class PSDImageReader extends ImageReaderBase {
// }
}
- long read = mImageInput.getStreamPosition() - pos;
+ long read = imageInput.getStreamPosition() - pos;
long diff = layerInfoLength - (read - 4); // - 4 for the layerInfoLength field itself
// System.out.println("diff: " + diff);
- mImageInput.skipBytes(diff);
+ imageInput.skipBytes(diff);
// TODO: Global LayerMaskInfo (18 bytes or more..?)
// 4 (length), 2 (colorSpace), 8 (4 * 2 byte color components), 2 (opacity %), 1 (kind), variable (pad)
- long layerMaskInfoLength = mImageInput.readUnsignedInt();
+ long layerMaskInfoLength = imageInput.readUnsignedInt();
// System.out.println("GlobalLayerMaskInfo length: " + layerMaskInfoLength);
if (layerMaskInfoLength > 0) {
- mMetadata.mGlobalLayerMask = new PSDGlobalLayerMask(mImageInput);
+ mMetadata.mGlobalLayerMask = new PSDGlobalLayerMask(imageInput);
// System.out.println("mGlobalLayerMask: " + mGlobalLayerMask);
}
- read = mImageInput.getStreamPosition() - pos;
+ read = imageInput.getStreamPosition() - pos;
long toSkip = length - read;
// System.out.println("toSkip: " + toSkip);
- mImageInput.skipBytes(toSkip);
+ imageInput.skipBytes(toSkip);
}
else {
// Skip entire layer and mask section
- mImageInput.skipBytes(length);
+ imageInput.skipBytes(length);
}
}
@@ -853,13 +870,13 @@ public class PSDImageReader extends ImageReaderBase {
final int interleavedBands = banded ? 1 : raster.getNumBands();
for (PSDChannelInfo channelInfo : pLayerInfo.mChannelInfo) {
- int compression = mImageInput.readUnsignedShort();
+ int compression = imageInput.readUnsignedShort();
// Skip layer if we can't read it
// channelId == -2 means "user supplied layer mask", whatever that is...
if (width <= 0 || height <= 0 || channelInfo.mChannelId == -2 ||
(compression != PSD.COMPRESSION_NONE && compression != PSD.COMPRESSION_RLE)) {
- mImageInput.skipBytes(channelInfo.mLength - 2);
+ imageInput.skipBytes(channelInfo.mLength - 2);
}
else {
// 0 = red, 1 = green, etc
@@ -881,7 +898,7 @@ public class PSDImageReader extends ImageReaderBase {
// each count stored as a two*byte value.
byteCounts = new int[pLayerInfo.mBottom - pLayerInfo.mTop];
for (int i = 0; i < byteCounts.length; i++) {
- byteCounts[i] = mImageInput.readUnsignedShort();
+ byteCounts[i] = imageInput.readUnsignedShort();
}
break;
@@ -897,24 +914,25 @@ public class PSDImageReader extends ImageReaderBase {
switch (mHeader.mBits) {
case 1:
byte[] row1 = ((DataBufferByte) rowRaster.getDataBuffer()).getData();
- DataBufferByte buffer1 = (DataBufferByte) raster.getDataBuffer();
- byte[] data1 = banded ? buffer1.getData(c) : buffer1.getData();
+// DataBufferByte buffer1 = (DataBufferByte) raster.getDataBuffer();
+// byte[] data1 = banded ? buffer1.getData(c) : buffer1.getData();
- read1bitChannel(c, imageType.getNumBands(), data1, interleavedBands, bandOffset, sourceCM, row1, area, area, xsub, ysub, width, height, byteCounts, compression == PSD.COMPRESSION_RLE);
+ read1bitChannel(c, imageType.getNumBands(), raster.getDataBuffer(), interleavedBands, bandOffset, sourceCM, row1, area, area, xsub, ysub, width, height, byteCounts, compression == PSD.COMPRESSION_RLE);
break;
case 8:
byte[] row8 = ((DataBufferByte) rowRaster.getDataBuffer()).getData();
- DataBufferByte buffer8 = (DataBufferByte) raster.getDataBuffer();
- byte[] data8 = banded ? buffer8.getData(c) : buffer8.getData();
+// DataBufferByte buffer8 = (DataBufferByte) raster.getDataBuffer();
+// byte[] data8 = banded ? buffer8.getData(c) : buffer8.getData();
- read8bitChannel(c, imageType.getNumBands(), data8, interleavedBands, bandOffset, sourceCM, row8, area, area, xsub, ysub, width, height, byteCounts, 0, compression == PSD.COMPRESSION_RLE);
+// read8bitChannel(c, imageType.getNumBands(), data8, interleavedBands, bandOffset, sourceCM, row8, area, area, xsub, ysub, width, height, byteCounts, 0, compression == PSD.COMPRESSION_RLE);
+ read8bitChannel(c, imageType.getNumBands(), raster.getDataBuffer(), interleavedBands, bandOffset, sourceCM, row8, area, area, xsub, ysub, width, height, byteCounts, 0, compression == PSD.COMPRESSION_RLE);
break;
case 16:
short[] row16 = ((DataBufferUShort) rowRaster.getDataBuffer()).getData();
- DataBufferUShort buffer16 = (DataBufferUShort) raster.getDataBuffer();
- short[] data16 = banded ? buffer16.getData(c) : buffer16.getData();
+// DataBufferUShort buffer16 = (DataBufferUShort) raster.getDataBuffer();
+// short[] data16 = banded ? buffer16.getData(c) : buffer16.getData();
- read16bitChannel(c, imageType.getNumBands(), data16, interleavedBands, bandOffset, sourceCM, row16, area, area, xsub, ysub, width, height, byteCounts, 0, compression == PSD.COMPRESSION_RLE);
+ read16bitChannel(c, imageType.getNumBands(), raster.getDataBuffer(), interleavedBands, bandOffset, sourceCM, row16, area, area, xsub, ysub, width, height, byteCounts, 0, compression == PSD.COMPRESSION_RLE);
break;
default:
throw new IIOException(String.format("Unknown PSD bit depth: %s", mHeader.mBits));
@@ -995,7 +1013,7 @@ public class PSDImageReader extends ImageReaderBase {
readLayerAndMaskInfo(true);
// TODO: Need to make sure compression is set in metadata, even without reading the image data!
- mMetadata.mCompression = mImageInput.readShort();
+ mMetadata.mCompression = imageInput.readShort();
// mMetadata.mHeader = mHeader;
// mMetadata.mColorData = mColorData;
diff --git a/imageio/imageio-psd/src/main/java/com/twelvemonkeys/imageio/plugins/psd/PSDImageResource.java b/imageio/imageio-psd/src/main/java/com/twelvemonkeys/imageio/plugins/psd/PSDImageResource.java
index 7aa60dc4..fed3d818 100644
--- a/imageio/imageio-psd/src/main/java/com/twelvemonkeys/imageio/plugins/psd/PSDImageResource.java
+++ b/imageio/imageio-psd/src/main/java/com/twelvemonkeys/imageio/plugins/psd/PSDImageResource.java
@@ -43,7 +43,7 @@ import java.lang.reflect.Field;
* @author last modified by $Author: haraldk$
* @version $Id: PSDImageResource.java,v 1.0 Apr 29, 2008 5:49:06 PM haraldk Exp$
*/
-class PSDImageResource {
+public class PSDImageResource {
// TODO: Refactor image resources to separate package
// TODO: Change constructor to store stream offset and length only (+ possibly the name), defer reading
diff --git a/imageio/imageio-psd/src/main/java/com/twelvemonkeys/imageio/plugins/psd/YCbCrColorSpace.java b/imageio/imageio-psd/src/main/java/com/twelvemonkeys/imageio/plugins/psd/YCbCrColorSpace.java
deleted file mode 100755
index d0d020f1..00000000
--- a/imageio/imageio-psd/src/main/java/com/twelvemonkeys/imageio/plugins/psd/YCbCrColorSpace.java
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * Copyright (c) 2008, Harald Kuhr
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * * Neither the name "TwelveMonkeys" nor the
- * names of its contributors may be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-package com.twelvemonkeys.imageio.plugins.psd;
-
-import java.awt.color.ColorSpace;
-
-/**
- * YCbCrColorSpace
- *
- * @author Harald Kuhr
- * @author last modified by $Author: haraldk$
- * @version $Id: YCbCrColorSpace.java,v 1.0 Jun 28, 2008 3:30:50 PM haraldk Exp$
- */
-// TODO: Move to com.twlevemonkeys.image?
-// TODO: Read an ICC YCbCr profile from classpath resource? Is there such a thing?
-final class YCbCrColorSpace extends ColorSpace {
-
- static final ColorSpace INSTANCE = new CMYKColorSpace();
- final ColorSpace sRGB = getInstance(CS_sRGB);
-
- YCbCrColorSpace() {
- super(ColorSpace.TYPE_YCbCr, 3);
- }
-
- public static ColorSpace getInstance() {
- return INSTANCE;
- }
-
- // http://www.w3.org/Graphics/JPEG/jfif.txt
- /*
- Conversion to and from RGB
-
- Y, Cb, and Cr are converted from R, G, and B as defined in CCIR Recommendation 601
- but are normalized so as to occupy the full 256 levels of a 8-bit binary encoding. More
- precisely:
-
- Y = 256 * E'y
- Cb = 256 * [ E'Cb ] + 128
- Cr = 256 * [ E'Cr ] + 128
-
- where the E'y, E'Cb and E'Cb are defined as in CCIR 601. Since values of E'y have a
- range of 0 to 1.0 and those for E'Cb and E'Cr have a range of -0.5 to +0.5, Y, Cb, and Cr
- must be clamped to 255 when they are maximum value.
-
- RGB to YCbCr Conversion
-
- YCbCr (256 levels) can be computed directly from 8-bit RGB as follows:
-
- Y = 0.299 R + 0.587 G + 0.114 B
- Cb = - 0.1687 R - 0.3313 G + 0.5 B + 128
- Cr = 0.5 R - 0.4187 G - 0.0813 B + 128
-
- NOTE - Not all image file formats store image samples in the order R0, G0,
- B0, ... Rn, Gn, Bn. Be sure to verify the sample order before converting an
- RGB file to JFIF.
-
- YCbCr to RGB Conversion
-
- RGB can be computed directly from YCbCr (256 levels) as follows:
-
- R = Y + 1.402 (Cr-128)
- G = Y - 0.34414 (Cb-128) - 0.71414 (Cr-128)
- B = Y + 1.772 (Cb-128)
- */
- public float[] toRGB(float[] colorvalue) {
-// R = Y + 1.402 (Cr-128)
-// G = Y - 0.34414 (Cb-128) - 0.71414 (Cr-128)
-// B = Y + 1.772 (Cb-128)
- return new float[] {
- colorvalue[0] + 1.402f * (colorvalue[2] - .5f),
- colorvalue[0] - 0.34414f * (colorvalue[1] - .5f) - 0.71414f * (colorvalue[2] - .5f),
- colorvalue[0] + 1.772f * (colorvalue[1] - .5f),
- };
- // TODO: Convert via CIEXYZ space using sRGB space, as suggested in docs
- // return sRGB.fromCIEXYZ(toCIEXYZ(colorvalue));
- }
-
- public float[] fromRGB(float[] rgbvalue) {
-// Y = 0.299 R + 0.587 G + 0.114 B
-// Cb = - 0.1687 R - 0.3313 G + 0.5 B + 128
-// Cr = 0.5 R - 0.4187 G - 0.0813 B + 128
- return new float[] {
- 0.299f * rgbvalue[0] + 0.587f * rgbvalue[1] + 0.114f * rgbvalue[2],
- -0.1687f * rgbvalue[0] - 0.3313f * rgbvalue[1] + 0.5f * rgbvalue[2] + .5f,
- 0.5f * rgbvalue[0] - 0.4187f * rgbvalue[1] - 0.0813f * rgbvalue[2] + .5f
- };
- }
-
- public float[] toCIEXYZ(float[] colorvalue) {
- throw new UnsupportedOperationException("Method toCIEXYZ not implemented"); // TODO: Implement
- }
-
- public float[] fromCIEXYZ(float[] colorvalue) {
- throw new UnsupportedOperationException("Method fromCIEXYZ not implemented"); // TODO: Implement
- }
-}
diff --git a/imageio/imageio-psd/todo.txt b/imageio/imageio-psd/todo.txt
index c7d6d53c..7d731b62 100755
--- a/imageio/imageio-psd/todo.txt
+++ b/imageio/imageio-psd/todo.txt
@@ -1,6 +1,7 @@
-Implement source subsampling and region of interest
-Separate package for the resources (seems to be a lot)?
-Possibility to read only some resources? readResources(int[] resourceKeys)?
- - Probably faster when we only need the color space
-Support for Photoshop specific TIFF tags (extension for TIFFImageReader)?
-PSDImageWriter?
\ No newline at end of file
+- Implement source subsampling and region of interest
+- Separate package for the resources (seems to be a lot)?
+ - Move to metadata package, or implement metadata interface, as this is (similar|equivalent) to TIFF/JPEG APP13 segment tag?
+- Possibility to read only some resources? readResources(int[] resourceKeys)?
+ - Probably faster when we only need the color space
+- Support for Photoshop specific TIFF tags (extension for TIFFImageReader)?
+- PSDImageWriter?
diff --git a/imageio/imageio-thumbsdb/src/main/java/com/twelvemonkeys/imageio/plugins/thumbsdb/ThumbsDBImageReader.java b/imageio/imageio-thumbsdb/src/main/java/com/twelvemonkeys/imageio/plugins/thumbsdb/ThumbsDBImageReader.java
index 56b80623..67249499 100644
--- a/imageio/imageio-thumbsdb/src/main/java/com/twelvemonkeys/imageio/plugins/thumbsdb/ThumbsDBImageReader.java
+++ b/imageio/imageio-thumbsdb/src/main/java/com/twelvemonkeys/imageio/plugins/thumbsdb/ThumbsDBImageReader.java
@@ -209,8 +209,8 @@ public class ThumbsDBImageReader extends ImageReaderBase {
@Override
public void setInput(Object pInput, boolean pSeekForwardOnly, boolean pIgnoreMetadata) {
super.setInput(pInput, pSeekForwardOnly, pIgnoreMetadata);
- if (mImageInput != null) {
- mImageInput.setByteOrder(ByteOrder.LITTLE_ENDIAN);
+ if (imageInput != null) {
+ imageInput.setByteOrder(ByteOrder.LITTLE_ENDIAN);
}
}
@@ -263,7 +263,7 @@ public class ThumbsDBImageReader extends ImageReaderBase {
private void init() throws IOException {
assertInput();
if (mRoot == null) {
- mRoot = new CompoundDocument(mImageInput).getRootEntry();
+ mRoot = new CompoundDocument(imageInput).getRootEntry();
SortedSet children = mRoot.getChildEntries();
mThumbnails = new BufferedImage[children.size() - 1];