mirror of
https://github.com/haraldk/TwelveMonkeys.git
synced 2026-04-30 00:00:01 -04:00
Adding the twelvemonkeys-imageio sub-project
This commit is contained in:
+381
@@ -0,0 +1,381 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import com.twelvemonkeys.image.BufferedImageIcon;
|
||||
import com.twelvemonkeys.imageio.util.IIOUtil;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.imageio.ImageReadParam;
|
||||
import javax.imageio.ImageReader;
|
||||
import javax.imageio.metadata.IIOMetadata;
|
||||
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.image.BufferedImage;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
|
||||
/**
|
||||
* ImageReaderBase
|
||||
*
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @author last modified by $Author: haraldk$
|
||||
* @version $Id: ImageReaderBase.java,v 1.0 Sep 20, 2007 5:28:37 PM haraldk Exp$
|
||||
*/
|
||||
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;
|
||||
|
||||
/**
|
||||
* Constructs an {@code ImageReader} and sets its
|
||||
* {@code originatingProvider} field to the supplied value.
|
||||
* <p/>
|
||||
* <p> Subclasses that make use of extensions should provide a
|
||||
* constructor with signature {@code (ImageReaderSpi,
|
||||
* Object)} in order to retrieve the extension object. If
|
||||
* the extension object is unsuitable, an
|
||||
* {@code IllegalArgumentException} should be thrown.
|
||||
*
|
||||
* @param pOriginatingProvider the {@code ImageReaderSpi} that is
|
||||
* invoking this constructor, or {@code null}.
|
||||
*/
|
||||
protected ImageReaderBase(final ImageReaderSpi pOriginatingProvider) {
|
||||
super(pOriginatingProvider);
|
||||
}
|
||||
|
||||
/**
|
||||
* Overrides {@code setInput}, to allow easy access to the input, in case
|
||||
* it is an {@code ImageInputStream}.
|
||||
*
|
||||
* @param pInput the {@code ImageInputStream} or other
|
||||
* {@code Object} to use for future decoding.
|
||||
* @param pSeekForwardOnly if {@code true}, images and metadata
|
||||
* may only be read in ascending order from this input source.
|
||||
* @param pIgnoreMetadata if {@code true}, metadata
|
||||
* may be ignored during reads.
|
||||
*
|
||||
* @exception IllegalArgumentException if {@code input} is
|
||||
* not an instance of one of the classes returned by the
|
||||
* originating service provider's {@code getInputTypes}
|
||||
* method, or is not an {@code ImageInputStream}.
|
||||
*
|
||||
* @see ImageInputStream
|
||||
*/
|
||||
@Override
|
||||
public void setInput(Object pInput, boolean pSeekForwardOnly, boolean pIgnoreMetadata) {
|
||||
resetMembers();
|
||||
super.setInput(pInput, pSeekForwardOnly, pIgnoreMetadata);
|
||||
if (pInput instanceof ImageInputStream) {
|
||||
mImageInput = (ImageInputStream) pInput;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
resetMembers();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
resetMembers();
|
||||
super.reset();
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets all member variables. This method is by default invoked from:
|
||||
* <ul>
|
||||
* <li>{@link #setInput(Object, boolean, boolean)}</li>
|
||||
* <li>{@link #dispose()}</li>
|
||||
* <li>{@link #reset()}</li>
|
||||
* </ul>
|
||||
*
|
||||
*/
|
||||
protected abstract void resetMembers();
|
||||
|
||||
/**
|
||||
* Defaul implementation that always return {@code null}.
|
||||
*
|
||||
* @param pImageIndex ignored, unless overriden
|
||||
* @return {@code null}, unless overriden
|
||||
* @throws IOException never, unless overriden.
|
||||
*/
|
||||
public IIOMetadata getImageMetadata(int pImageIndex) throws IOException {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Defaul implementation that always return {@code null}.
|
||||
*
|
||||
* @return {@code null}, unless overriden
|
||||
* @throws IOException never, unless overriden.
|
||||
*/
|
||||
public IIOMetadata getStreamMetadata() throws IOException {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Default implementation that always returns {@code 1}.
|
||||
*
|
||||
* @param pAllowSearch ignored, unless overriden
|
||||
* @return {@code 1}, unless overriden
|
||||
* @throws IOException never, unless overriden
|
||||
*/
|
||||
public int getNumImages(boolean pAllowSearch) throws IOException {
|
||||
assertInput();
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method to make sure image index is within bounds.
|
||||
*
|
||||
* @param pIndex the image index
|
||||
*
|
||||
* @throws java.io.IOException if an error occurs during reading
|
||||
* @throws IndexOutOfBoundsException if not
|
||||
* <tt>minIndex <= pIndex < numImages</tt>
|
||||
*/
|
||||
protected void checkBounds(int pIndex) throws IOException {
|
||||
assertInput();
|
||||
if (pIndex < getMinIndex()) {
|
||||
throw new IndexOutOfBoundsException("index < minIndex");
|
||||
}
|
||||
else if (getNumImages(false) != -1 && pIndex >= getNumImages(false)) {
|
||||
throw new IndexOutOfBoundsException("index >= numImages (" + pIndex + " >= " + getNumImages(false) + ")");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes sure input is set.
|
||||
*
|
||||
* @throws IllegalStateException if {@code getInput() == null}.
|
||||
*/
|
||||
protected void assertInput() {
|
||||
if (getInput() == null) {
|
||||
throw new IllegalStateException("getInput() == null");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method for getting the area of interest (AOI) of an image.
|
||||
* The AOI is defined by the {@link javax.imageio.IIOParam#setSourceRegion(java.awt.Rectangle)}
|
||||
* method.
|
||||
* <p/>
|
||||
* Note: If it is possible for the reader to read the AOI directly, such a
|
||||
* method should be used instead, for efficiency.
|
||||
*
|
||||
* @param pImage the image to get AOI from
|
||||
* @param pParam the param optionally specifying the AOI
|
||||
*
|
||||
* @return a {@code BufferedImage} containing the area of interest (source
|
||||
* region), or the original image, if no source region was set, or
|
||||
* {@code pParam} was {@code null}
|
||||
*/
|
||||
protected static BufferedImage fakeAOI(BufferedImage pImage, ImageReadParam pParam) {
|
||||
return IIOUtil.fakeAOI(pImage, getSourceRegion(pParam, pImage.getWidth(), pImage.getHeight()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method for getting the subsampled image.
|
||||
* The subsampling is defined by the
|
||||
* {@link javax.imageio.IIOParam#setSourceSubsampling(int, int, int, int)}
|
||||
* method.
|
||||
* <p/>
|
||||
* NOTE: This method does not take the subsampling offsets into
|
||||
* consideration.
|
||||
* <p/>
|
||||
* Note: If it is possible for the reader to subsample directly, such a
|
||||
* method should be used instead, for efficiency.
|
||||
*
|
||||
* @param pImage the image to subsample
|
||||
* @param pParam the param optionally specifying subsampling
|
||||
*
|
||||
* @return an {@code Image} containing the subsampled image, or the
|
||||
* original image, if no subsampling was specified, or
|
||||
* {@code pParam} was {@code null}
|
||||
*/
|
||||
protected static Image fakeSubsampling(Image pImage, ImageReadParam pParam) {
|
||||
return IIOUtil.fakeSubsampling(pImage, pParam);
|
||||
}
|
||||
|
||||
public static void main(String[] pArgs) throws IOException {
|
||||
BufferedImage image = ImageIO.read(new File(pArgs[0]));
|
||||
showIt(image, pArgs[0]);
|
||||
}
|
||||
|
||||
protected static void showIt(final BufferedImage pImage, final String pTitle) {
|
||||
try {
|
||||
SwingUtilities.invokeAndWait(new Runnable() {
|
||||
public void run() {
|
||||
JFrame frame = new JFrame(pTitle);
|
||||
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||
frame.setLocationByPlatform(true);
|
||||
JPanel pane = new JPanel(new BorderLayout());
|
||||
JScrollPane scroll = new JScrollPane(new ImageLabel(pImage));
|
||||
scroll.setBorder(null);
|
||||
pane.add(scroll);
|
||||
frame.setContentPane(pane);
|
||||
frame.pack();
|
||||
frame.setVisible(true);
|
||||
}
|
||||
});
|
||||
}
|
||||
catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
catch (InvocationTargetException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private static class ImageLabel extends JLabel {
|
||||
Paint mBackground;
|
||||
|
||||
public ImageLabel(BufferedImage pImage) {
|
||||
super(new BufferedImageIcon(pImage));
|
||||
setOpaque(false);
|
||||
setCursor(Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR));
|
||||
|
||||
mBackground = createTexture();
|
||||
|
||||
JPopupMenu popup = createBackgroundPopup();
|
||||
|
||||
setComponentPopupMenu(popup);
|
||||
addMouseListener(new MouseAdapter() {
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent e) {
|
||||
if (e.isPopupTrigger()) {
|
||||
getComponentPopupMenu().show(ImageLabel.this, e.getX(), e.getY());
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private JPopupMenu createBackgroundPopup() {
|
||||
JPopupMenu popup = new JPopupMenu();
|
||||
ButtonGroup group = new ButtonGroup();
|
||||
addCheckBoxItem(new ChangeBackgroundAction("Default", mBackground), popup, group);
|
||||
popup.addSeparator();
|
||||
addCheckBoxItem(new ChangeBackgroundAction("White", Color.WHITE), popup, group);
|
||||
addCheckBoxItem(new ChangeBackgroundAction("Light", Color.LIGHT_GRAY), popup, group);
|
||||
addCheckBoxItem(new ChangeBackgroundAction("Gray", Color.GRAY), popup, group);
|
||||
addCheckBoxItem(new ChangeBackgroundAction("Dark", Color.DARK_GRAY), popup, group);
|
||||
addCheckBoxItem(new ChangeBackgroundAction("Black", Color.BLACK), popup, group);
|
||||
popup.addSeparator();
|
||||
addCheckBoxItem(new ChooseBackgroundAction("Choose...", Color.BLUE), popup, group);
|
||||
return popup;
|
||||
}
|
||||
|
||||
private void addCheckBoxItem(final Action pAction, final JPopupMenu pPopup, final ButtonGroup pGroup) {
|
||||
JCheckBoxMenuItem item = new JCheckBoxMenuItem(pAction);
|
||||
pGroup.add(item);
|
||||
pPopup.add(item);
|
||||
}
|
||||
|
||||
private Paint createTexture() {
|
||||
GraphicsConfiguration graphicsConfiguration = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration();
|
||||
BufferedImage pattern = graphicsConfiguration.createCompatibleImage(20, 20);
|
||||
Graphics2D g = pattern.createGraphics();
|
||||
try {
|
||||
g.setColor(Color.LIGHT_GRAY);
|
||||
g.fillRect(0, 0, pattern.getWidth(), pattern.getHeight());
|
||||
g.setColor(Color.GRAY);
|
||||
g.fillRect(0, 0, pattern.getWidth() / 2, pattern.getHeight() / 2);
|
||||
g.fillRect(pattern.getWidth() / 2, pattern.getHeight() / 2, pattern.getWidth() / 2, pattern.getHeight() / 2);
|
||||
}
|
||||
finally {
|
||||
g.dispose();
|
||||
}
|
||||
|
||||
return new TexturePaint(pattern, new Rectangle(pattern.getWidth(), pattern.getHeight()));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void paintComponent(Graphics g) {
|
||||
Graphics2D gr = (Graphics2D) g;
|
||||
gr.setPaint(mBackground);
|
||||
gr.fillRect(0, 0, getWidth(), getHeight());
|
||||
super.paintComponent(g);
|
||||
}
|
||||
|
||||
private class ChangeBackgroundAction extends AbstractAction {
|
||||
protected Paint mPaint;
|
||||
|
||||
public ChangeBackgroundAction(final String pName, final Paint pPaint) {
|
||||
super(pName);
|
||||
mPaint = pPaint;
|
||||
}
|
||||
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
mBackground = mPaint;
|
||||
repaint();
|
||||
}
|
||||
}
|
||||
|
||||
private class ChooseBackgroundAction extends ChangeBackgroundAction {
|
||||
public ChooseBackgroundAction(final String pName, final Color pColor) {
|
||||
super(pName, pColor);
|
||||
putValue(Action.SMALL_ICON, new Icon() {
|
||||
public void paintIcon(Component c, Graphics pGraphics, int x, int y) {
|
||||
Graphics g = pGraphics.create();
|
||||
g.setColor((Color) mPaint);
|
||||
g.fillRect(x, y, 16, 16);
|
||||
g.dispose();
|
||||
}
|
||||
|
||||
public int getIconWidth() {
|
||||
return 16;
|
||||
}
|
||||
|
||||
public int getIconHeight() {
|
||||
return 16;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
Color selected = JColorChooser.showDialog(ImageLabel.this, "Choose background", (Color) mPaint);
|
||||
if (selected != null) {
|
||||
mPaint = selected;
|
||||
super.actionPerformed(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+158
@@ -0,0 +1,158 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import com.twelvemonkeys.imageio.util.IIOUtil;
|
||||
|
||||
import javax.imageio.ImageWriteParam;
|
||||
import javax.imageio.metadata.IIOMetadata;
|
||||
import javax.imageio.spi.ImageWriterSpi;
|
||||
import javax.imageio.stream.ImageOutputStream;
|
||||
import java.awt.*;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* ImageWriterBase
|
||||
*
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @author last modified by $Author: haraldk$
|
||||
* @version $Id: ImageWriterBase.java,v 1.0 Sep 24, 2007 12:22:28 AM haraldk Exp$
|
||||
*/
|
||||
public abstract class ImageWriterBase extends javax.imageio.ImageWriter {
|
||||
protected ImageOutputStream mImageOutput;
|
||||
|
||||
/**
|
||||
* Constructs an {@code ImageWriter} and sets its
|
||||
* {@code originatingProvider} instance variable to the
|
||||
* supplied value.
|
||||
* <p/>
|
||||
* <p> Subclasses that make use of extensions should provide a
|
||||
* constructor with signature {@code (ImageWriterSpi,
|
||||
* Object)} in order to retrieve the extension object. If
|
||||
* the extension object is unsuitable, an
|
||||
* {@code IllegalArgumentException} should be thrown.
|
||||
*
|
||||
* @param pProvider the {@code ImageWriterSpi} that
|
||||
* is constructing this object, or {@code null}.
|
||||
*/
|
||||
protected ImageWriterBase(final ImageWriterSpi pProvider) {
|
||||
super(pProvider);
|
||||
}
|
||||
|
||||
public String getFormatName() throws IOException {
|
||||
return getOriginatingProvider().getFormatNames()[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOutput(Object pOutput) {
|
||||
super.setOutput(pOutput);
|
||||
if (pOutput instanceof ImageOutputStream) {
|
||||
mImageOutput = (ImageOutputStream) pOutput;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes sure output is set.
|
||||
*
|
||||
* @throws IllegalStateException if {@code getOutput() == null}.
|
||||
*/
|
||||
protected void assertOutput() {
|
||||
if (getOutput() == null) {
|
||||
throw new IllegalStateException("getOutput() == null");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code null}
|
||||
*
|
||||
* @param pParam igonred.
|
||||
* @return {@code null}.
|
||||
*/
|
||||
public IIOMetadata getDefaultStreamMetadata(javax.imageio.ImageWriteParam pParam) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code null}
|
||||
*
|
||||
* @param pInData ignored.
|
||||
* @param pParam igonred.
|
||||
* @return {@code null}.
|
||||
*/
|
||||
public IIOMetadata convertStreamMetadata(IIOMetadata pInData, ImageWriteParam pParam) {
|
||||
return null;
|
||||
}
|
||||
|
||||
protected static Rectangle getSourceRegion(ImageWriteParam pParam, int pWidth, int pHeight) {
|
||||
return IIOUtil.getSourceRegion(pParam, pWidth, pHeight);
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method for getting the area of interest (AOI) of an image.
|
||||
* The AOI is defined by the {@link IIOParam#setSourceRegion(java.awt.Rectangle)}
|
||||
* method.
|
||||
* <p/>
|
||||
* Note: If it is possible for the reader to read the AOI directly, such a
|
||||
* method should be used instead, for efficiency.
|
||||
*
|
||||
* @param pImage the image to get AOI from
|
||||
* @param pParam the param optionally specifying the AOI
|
||||
*
|
||||
* @return a {@code BufferedImage} containing the area of interest (source
|
||||
* region), or the original image, if no source region was set, or
|
||||
* {@code pParam} was {@code null}
|
||||
*/
|
||||
protected static BufferedImage fakeAOI(BufferedImage pImage, ImageWriteParam pParam) {
|
||||
return IIOUtil.fakeAOI(pImage, getSourceRegion(pParam, pImage.getWidth(), pImage.getHeight()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method for getting the subsampled image.
|
||||
* The subsampling is defined by the
|
||||
* {@link IIOParam#setSourceSubsampling(int, int, int, int)}
|
||||
* method.
|
||||
* <p/>
|
||||
* NOTE: This method does not take the subsampling offsets into
|
||||
* consideration.
|
||||
* <p/>
|
||||
* Note: If it is possible for the reader to subsample directly, such a
|
||||
* method should be used instead, for efficiency.
|
||||
*
|
||||
* @param pImage the image to subsample
|
||||
* @param pParam the param optionally specifying subsampling
|
||||
*
|
||||
* @return an {@code Image} containing the subsampled image, or the
|
||||
* original image, if no subsampling was specified, or
|
||||
* {@code pParam} was {@code null}
|
||||
*/
|
||||
protected static Image fakeSubsampling(Image pImage, ImageWriteParam pParam) {
|
||||
return IIOUtil.fakeSubsampling(pImage, pParam);
|
||||
}
|
||||
}
|
||||
+171
@@ -0,0 +1,171 @@
|
||||
package com.twelvemonkeys.imageio.stream;
|
||||
|
||||
import com.twelvemonkeys.lang.Validate;
|
||||
|
||||
import javax.imageio.stream.ImageInputStream;
|
||||
import javax.imageio.stream.ImageInputStreamImpl;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* BufferedFileImageInputStream
|
||||
* Experimental - seems to be effective for FileImageInputStream and FileCacheImageInputStream.
|
||||
*
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @author last modified by $Author: haraldk$
|
||||
* @version $Id: BufferedFileImageInputStream.java,v 1.0 May 15, 2008 4:36:49 PM haraldk Exp$
|
||||
*/
|
||||
// TODO: Create a provider for this (wrapping the FileIIS and FileCacheIIS classes), and disable the Sun built-in spis?
|
||||
public final class BufferedImageInputStream extends ImageInputStreamImpl implements ImageInputStream {
|
||||
|
||||
static final int DEFAULT_BUFFER_SIZE = 8192;
|
||||
|
||||
private ImageInputStream mStream;
|
||||
|
||||
private byte[] mBuffer;
|
||||
private long mBufferStart = 0;
|
||||
private int mBufferPos = 0;
|
||||
private int mBufferLength = 0;
|
||||
|
||||
public BufferedImageInputStream(final ImageInputStream pStream) {
|
||||
this(pStream, DEFAULT_BUFFER_SIZE);
|
||||
}
|
||||
|
||||
private BufferedImageInputStream(final ImageInputStream pStream, final int pBufferSize) {
|
||||
Validate.notNull(pStream, "stream");
|
||||
|
||||
mStream = pStream;
|
||||
mBuffer = new byte[pBufferSize];
|
||||
}
|
||||
|
||||
private void fillBuffer() throws IOException {
|
||||
mBufferStart = streamPos;
|
||||
mBufferLength = mStream.read(mBuffer, 0, mBuffer.length);
|
||||
mBufferPos = 0;
|
||||
}
|
||||
|
||||
private boolean isBufferValid() throws IOException {
|
||||
return mBufferPos < mBufferLength && mBufferStart == mStream.getStreamPosition() - mBufferLength;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read() throws IOException {
|
||||
if (!isBufferValid()) {
|
||||
fillBuffer();
|
||||
}
|
||||
if (mBufferLength <= 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
bitOffset = 0;
|
||||
streamPos++;
|
||||
|
||||
return mBuffer[mBufferPos++] & 0xff;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read(final byte[] pBuffer, final int pOffset, final int pLength) throws IOException {
|
||||
bitOffset = 0;
|
||||
|
||||
boolean bypassBuffer = false;
|
||||
|
||||
if (!isBufferValid()) {
|
||||
// Bypass cache if cache is empty for reads longer than buffer
|
||||
if (pLength >= mBuffer.length) {
|
||||
bypassBuffer = true;
|
||||
}
|
||||
else {
|
||||
fillBuffer();
|
||||
}
|
||||
}
|
||||
|
||||
if (!bypassBuffer && mBufferLength <= 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Read as much as possible from buffer
|
||||
int length = bypassBuffer ? 0 : Math.min(mBufferLength - mBufferPos, pLength);
|
||||
|
||||
if (length > 0) {
|
||||
System.arraycopy(mBuffer, mBufferPos, pBuffer, pOffset, length);
|
||||
mBufferPos += length;
|
||||
}
|
||||
|
||||
// Read rest directly from stream, if longer than buffer
|
||||
if (pLength - length >= mBuffer.length) {
|
||||
int read = mStream.read(pBuffer, pOffset + length, pLength - length);
|
||||
|
||||
if (read > 0) {
|
||||
length += read;
|
||||
}
|
||||
}
|
||||
|
||||
streamPos += length;
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void seek(long pPosition) throws IOException {
|
||||
// TODO: Could probably be optimized to not invalidate buffer if new pos is within current buffer
|
||||
mStream.seek(pPosition);
|
||||
mBufferLength = 0; // Will invalidate buffer
|
||||
streamPos = mStream.getStreamPosition();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flushBefore(long pos) throws IOException {
|
||||
mStream.flushBefore(pos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getFlushedPosition() {
|
||||
return mStream.getFlushedPosition();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCached() {
|
||||
return mStream.isCached();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCachedMemory() {
|
||||
return mStream.isCachedMemory();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCachedFile() {
|
||||
return mStream.isCachedFile();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
if (mStream != null) {
|
||||
mStream.close();
|
||||
mStream = null;
|
||||
mBuffer = null;
|
||||
}
|
||||
super.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void finalize() throws Throwable {
|
||||
super.finalize();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long length() {
|
||||
// WTF?! This method is allowed to throw IOException in the interface...
|
||||
try {
|
||||
return mStream.length();
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw unchecked(e, RuntimeException.class);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked", "UnusedDeclaration"})
|
||||
private <T extends Throwable> T unchecked(IOException pExcption, Class<T> pClass) {
|
||||
// Ugly hack to fool the compiler..
|
||||
return (T) pExcption;
|
||||
}
|
||||
}
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
package com.twelvemonkeys.imageio.stream;
|
||||
|
||||
import com.twelvemonkeys.lang.Validate;
|
||||
|
||||
import javax.imageio.stream.ImageInputStreamImpl;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Experimental
|
||||
*
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @author last modified by $Author: haraldk$
|
||||
* @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;
|
||||
|
||||
public ByteArrayImageInputStream(final byte[] pData) {
|
||||
Validate.notNull(pData, "data");
|
||||
mData = pData;
|
||||
}
|
||||
|
||||
public int read() throws IOException {
|
||||
if (streamPos >= mData.length) {
|
||||
return -1;
|
||||
}
|
||||
bitOffset = 0;
|
||||
return mData[((int) streamPos++)] & 0xff;
|
||||
}
|
||||
|
||||
public int read(byte[] pBuffer, int pOffset, int pLength) throws IOException {
|
||||
if (streamPos >= mData.length) {
|
||||
return -1;
|
||||
}
|
||||
int length = (int) Math.min(mData.length - streamPos, pLength);
|
||||
bitOffset = 0;
|
||||
System.arraycopy(mData, (int) streamPos, pBuffer, pOffset, length);
|
||||
streamPos += length;
|
||||
return length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long length() {
|
||||
return mData.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCached() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCachedMemory() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
package com.twelvemonkeys.imageio.stream;
|
||||
|
||||
import javax.imageio.spi.ImageInputStreamSpi;
|
||||
import javax.imageio.stream.ImageInputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* ByteArrayImageInputStreamSpi
|
||||
* Experimental
|
||||
*
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @author last modified by $Author: haraldk$
|
||||
* @version $Id: ByteArrayImageInputStreamSpi.java,v 1.0 May 15, 2008 2:12:12 PM haraldk Exp$
|
||||
*/
|
||||
public class ByteArrayImageInputStreamSpi extends ImageInputStreamSpi {
|
||||
|
||||
public ByteArrayImageInputStreamSpi() {
|
||||
super("TwelveMonkeys", "1.0 BETA", byte[].class);
|
||||
}
|
||||
|
||||
public ImageInputStream createInputStreamInstance(Object pInput, boolean pUseCache, File pCacheDir) throws IOException {
|
||||
if (pInput instanceof byte[]) {
|
||||
return new ByteArrayImageInputStream((byte[]) pInput);
|
||||
}
|
||||
else {
|
||||
throw new IllegalArgumentException("Expected input of type byte[]: " + pInput);
|
||||
}
|
||||
}
|
||||
|
||||
public String getDescription(Locale pLocale) {
|
||||
return "Service provider that instantiates an ImageInputStream from a byte array";
|
||||
}
|
||||
|
||||
}
|
||||
+84
@@ -0,0 +1,84 @@
|
||||
package com.twelvemonkeys.imageio.stream;
|
||||
|
||||
import javax.imageio.spi.ImageInputStreamSpi;
|
||||
import javax.imageio.stream.FileCacheImageInputStream;
|
||||
import javax.imageio.stream.FileImageInputStream;
|
||||
import javax.imageio.stream.ImageInputStream;
|
||||
import javax.imageio.stream.MemoryCacheImageInputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URL;
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* URLImageInputStreamSpi
|
||||
* Experimental
|
||||
*
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @author last modified by $Author: haraldk$
|
||||
* @version $Id: URLImageInputStreamSpi.java,v 1.0 May 15, 2008 2:14:59 PM haraldk Exp$
|
||||
*/
|
||||
// TODO: URI instead of URL?
|
||||
public class URLImageInputStreamSpi extends ImageInputStreamSpi {
|
||||
public URLImageInputStreamSpi() {
|
||||
super("TwelveMonkeys", "1.0 BETA", URL.class);
|
||||
}
|
||||
|
||||
// TODO: Create a URI or URLImageInputStream class, with a getUR[I|L] method, to allow for multiple file formats
|
||||
// The good thing with that is that it does not clash with the built-in Sun-stuff or other people's hacks
|
||||
// The bad thing is that most people don't expect there to be an UR[I|L]ImageInputStreamSpi..
|
||||
public ImageInputStream createInputStreamInstance(final Object pInput, final boolean pUseCache, final File pCacheDir) throws IOException {
|
||||
if (pInput instanceof URL) {
|
||||
URL url = (URL) pInput;
|
||||
|
||||
// Special case for file protocol, a lot faster than FileCacheImageInputStream
|
||||
if ("file".equals(url.getProtocol())) {
|
||||
try {
|
||||
return new BufferedImageInputStream(new FileImageInputStream(new File(url.toURI())));
|
||||
// return new FileImageInputStream(new File(url.toURI()));
|
||||
}
|
||||
catch (URISyntaxException ignore) {
|
||||
ignore.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
// Otherwise revert to cached
|
||||
final InputStream stream = url.openStream();
|
||||
if (pUseCache) {
|
||||
return new BufferedImageInputStream(new FileCacheImageInputStream(stream, pCacheDir) {
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
try {
|
||||
super.close();
|
||||
}
|
||||
finally {
|
||||
stream.close(); // NOTE: If this line throws IOE, it will shadow the original..
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
return new MemoryCacheImageInputStream(stream) {
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
try {
|
||||
super.close();
|
||||
}
|
||||
finally {
|
||||
stream.close(); // NOTE: If this line throws IOE, it will shadow the original..
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
else {
|
||||
throw new IllegalArgumentException("Expected input of type URL: " + pInput);
|
||||
}
|
||||
}
|
||||
|
||||
public String getDescription(final Locale pLocale) {
|
||||
return "Service provider that instantiates an ImageInputStream from a URL";
|
||||
}
|
||||
}
|
||||
Executable
+177
@@ -0,0 +1,177 @@
|
||||
/*
|
||||
* 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.util;
|
||||
|
||||
import javax.imageio.stream.ImageInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
/**
|
||||
* IIOInputStreamAdapter
|
||||
* <p/>
|
||||
* Note: You should always wrap this stream in a {@code BufferedInputStream}.
|
||||
* If not, performance may degrade significantly.
|
||||
*
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @author last modified by $Author: haraldk$
|
||||
* @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;
|
||||
|
||||
// TODO: Enforce stream boundaries!
|
||||
// TODO: Stream start position....
|
||||
|
||||
/**
|
||||
* Creates an {@code InputStream} that reads from the given {@code ImageInputStream}.
|
||||
* The input stream will read from the current stream position, until the end of the
|
||||
* underlying stream.
|
||||
*
|
||||
* @param pInput the {@code ImageInputStream} to read from.
|
||||
*/
|
||||
public IIOInputStreamAdapter(final ImageInputStream pInput) {
|
||||
this(pInput, -1, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an {@code InputStream} that reads from the given {@code ImageInputStream}.
|
||||
* The input stream will read from the current stream position, until at most
|
||||
* {@code pLength} bytes has been read.
|
||||
*
|
||||
* @param pInput the {@code ImageInputStream} to read from.
|
||||
* @param pLength the length of the stream
|
||||
*/
|
||||
public IIOInputStreamAdapter(final ImageInputStream pInput, final long pLength) {
|
||||
this(pInput, pLength, true);
|
||||
}
|
||||
|
||||
private IIOInputStreamAdapter(ImageInputStream pInput, long pLength, boolean pHasLength) {
|
||||
if (pInput == null) {
|
||||
throw new IllegalArgumentException("stream == null");
|
||||
}
|
||||
if (pHasLength && pLength < 0) {
|
||||
throw new IllegalArgumentException("length < 0");
|
||||
}
|
||||
|
||||
mInput = pInput;
|
||||
mHasLength = pHasLength;
|
||||
mLeft = pLength;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Marks this stream as closed.
|
||||
* This implementation does <em>not</em> close the underlying stream.
|
||||
*/
|
||||
public void close() throws IOException {
|
||||
if (mHasLength) {
|
||||
mInput.seek(mInput.getStreamPosition() + mLeft);
|
||||
}
|
||||
|
||||
mLeft = 0;
|
||||
mInput = null;
|
||||
}
|
||||
|
||||
public int available() throws IOException {
|
||||
if (mHasLength) {
|
||||
return mLeft > 0 ? (int) Math.min(Integer.MAX_VALUE, mLeft) : 0;
|
||||
}
|
||||
return 0; // We don't really know, so we say 0 to be safe.
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean markSupported() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public void mark(int pReadLimit) {
|
||||
try {
|
||||
mMarkPosition = mInput.getStreamPosition();
|
||||
}
|
||||
catch (IOException e) {
|
||||
// Let's hope this never happens, because it's not possible to reset then...
|
||||
throw new IllegalStateException("Could not read stream position: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
public void reset() throws IOException {
|
||||
long diff = mInput.getStreamPosition() - mMarkPosition;
|
||||
mInput.seek(mMarkPosition);
|
||||
mLeft += diff;
|
||||
}
|
||||
|
||||
public int read() throws IOException {
|
||||
if (mHasLength && mLeft-- <= 0) {
|
||||
mLeft = 0;
|
||||
return -1;
|
||||
}
|
||||
return mInput.read();
|
||||
}
|
||||
|
||||
public final int read(byte[] pBytes) throws IOException {
|
||||
return read(pBytes, 0, pBytes.length);
|
||||
}
|
||||
|
||||
public int read(final byte[] pBytes, final int pOffset, final int pLength) throws IOException {
|
||||
if (mHasLength && mLeft <= 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
int read = mInput.read(pBytes, pOffset, (int) findMaxLen(pLength));
|
||||
if (mHasLength) {
|
||||
mLeft = read < 0 ? 0 : mLeft - read;
|
||||
}
|
||||
return read;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the maximum number of bytes we can read or skip, from this stream.
|
||||
* The number will be in the range {@code [0 ... bytes left]}.
|
||||
*
|
||||
* @param pLength the requested length
|
||||
* @return the maximum number of bytes to read
|
||||
*/
|
||||
private long findMaxLen(long pLength) {
|
||||
if (mHasLength && mLeft < pLength) {
|
||||
return Math.max(mLeft, 0);
|
||||
}
|
||||
else {
|
||||
return Math.max(pLength, 0);
|
||||
}
|
||||
}
|
||||
|
||||
public long skip(long pLength) throws IOException {
|
||||
long skipped = mInput.skipBytes(findMaxLen(pLength)); // Skips 0 or more, never -1
|
||||
mLeft -= skipped;
|
||||
return skipped;
|
||||
}
|
||||
}
|
||||
Executable
+73
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* 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.util;
|
||||
|
||||
import javax.imageio.stream.ImageOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
|
||||
/**
|
||||
* IIOOutputStreamAdapter
|
||||
*
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @author last modified by $Author: haraldk$
|
||||
* @version $Id: IIOOutputStreamAdapter.java,v 1.0 Sep 26, 2007 11:50:38 AM haraldk Exp$
|
||||
*/
|
||||
class IIOOutputStreamAdapter extends OutputStream {
|
||||
private ImageOutputStream mOutput;
|
||||
|
||||
public IIOOutputStreamAdapter(final ImageOutputStream pOutput) {
|
||||
mOutput = pOutput;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(final byte[] pBytes) throws IOException {
|
||||
mOutput.write(pBytes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(final byte[] pBytes, final int pOffset, final int pLength) throws IOException {
|
||||
mOutput.write(pBytes, pOffset, pLength);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(final int pByte) throws IOException {
|
||||
mOutput.write(pByte);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flush() throws IOException {
|
||||
mOutput.flush();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
mOutput = null;
|
||||
}
|
||||
}
|
||||
+131
@@ -0,0 +1,131 @@
|
||||
package com.twelvemonkeys.imageio.util;
|
||||
|
||||
import com.twelvemonkeys.image.ImageUtil;
|
||||
|
||||
import javax.imageio.IIOParam;
|
||||
import javax.imageio.spi.IIOServiceProvider;
|
||||
import javax.imageio.spi.ServiceRegistry;
|
||||
import javax.imageio.stream.ImageInputStream;
|
||||
import javax.imageio.stream.ImageOutputStream;
|
||||
import java.awt.*;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
/**
|
||||
* IIOUtil
|
||||
*
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @author last modified by $Author: haraldk$
|
||||
* @version $Id: IIOUtil.java,v 1.0 May 8, 2008 3:04:54 PM haraldk Exp$
|
||||
*/
|
||||
public final class IIOUtil {
|
||||
private IIOUtil() {}
|
||||
|
||||
/**
|
||||
* Creates an {@code InputStream} adapter that reads from an underlying {@code ImageInputStream}.
|
||||
* The input stream will read until the end of {@code pStream}.
|
||||
*
|
||||
* @param pStream the stream to read from.
|
||||
* @return an {@code InputStream} reading from {@code pStream}.
|
||||
*/
|
||||
public static InputStream createStreamAdapter(final ImageInputStream pStream) {
|
||||
// TODO: Include stream start pos?
|
||||
// TODO: Skip buffering for known in-memory implementations?
|
||||
return new BufferedInputStream(new IIOInputStreamAdapter(pStream));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an {@code InputStream} adapter that reads from an underlying {@code ImageInputStream}.
|
||||
* The input stream will read until the end of {@code pStream}, or at most {@code pLength} bytes has been read.
|
||||
*
|
||||
* @param pStream the stream to read from.
|
||||
* @param pLength the maximum number of bytes that can be read from {@code pStream}.
|
||||
* @return an {@code InputStream} reading from {@code pStream}.
|
||||
*/
|
||||
public static InputStream createStreamAdapter(final ImageInputStream pStream, final long pLength) {
|
||||
// TODO: Include stream start pos?
|
||||
// TODO: Skip buffering for known in-memory implementations?
|
||||
return new BufferedInputStream(new IIOInputStreamAdapter(pStream, pLength));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an {@code OutputStream} adapter that writes to an underlying {@code ImageOutputStream}.
|
||||
*
|
||||
* @param pStream the stream to write to.
|
||||
* @return an {@code OutputSteam} writing to {@code pStream}.
|
||||
*/
|
||||
public static OutputStream createStreamAdapter(final ImageOutputStream pStream) {
|
||||
return new BufferedOutputStream(new IIOOutputStreamAdapter(pStream));
|
||||
}
|
||||
|
||||
/*
|
||||
* THIS METHOD WILL ME MOVED/RENAMED, DO NOT USE.
|
||||
*/
|
||||
public static <T> void deregisterProvider(final ServiceRegistry pRegistry, final IIOServiceProvider pProvider, final Class<T> pCategory) {
|
||||
// http://www.ibm.com/developerworks/java/library/j-jtp04298.html
|
||||
// TODO: Consider placing this method in a ImageReaderSpiBase class or similar
|
||||
pRegistry.deregisterServiceProvider(pCategory.cast(pProvider), pCategory);
|
||||
}
|
||||
|
||||
public static Image fakeSubsampling(final Image pImage, final IIOParam pParam) {
|
||||
if (pImage == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (pParam != null) {
|
||||
int x = pParam.getSourceXSubsampling();
|
||||
int y = pParam.getSourceYSubsampling();
|
||||
|
||||
// 1 is default
|
||||
if (x > 1 || y > 1) {
|
||||
int w = (ImageUtil.getWidth(pImage) + x - 1) / x;
|
||||
int h = (ImageUtil.getHeight(pImage) + y - 1) / y;
|
||||
|
||||
// Fake subsampling by scaling fast
|
||||
return pImage.getScaledInstance(w, h, Image.SCALE_FAST);
|
||||
}
|
||||
}
|
||||
|
||||
return pImage;
|
||||
}
|
||||
|
||||
public static Rectangle getSourceRegion(final IIOParam pParam, final int pSrcWidth, final int pSrcHeight) {
|
||||
Rectangle sourceRegion = new Rectangle(pSrcWidth, pSrcHeight);
|
||||
|
||||
// If param is present, calculate region
|
||||
if (pParam != null) {
|
||||
// Get intersection with source region
|
||||
Rectangle region = pParam.getSourceRegion();
|
||||
if (region != null) {
|
||||
sourceRegion = sourceRegion.intersection(region);
|
||||
}
|
||||
|
||||
// Scale according to subsampling offsets
|
||||
int subsampleXOffset = pParam.getSubsamplingXOffset();
|
||||
int subsampleYOffset = pParam.getSubsamplingYOffset();
|
||||
sourceRegion.x += subsampleXOffset;
|
||||
sourceRegion.y += subsampleYOffset;
|
||||
sourceRegion.width -= subsampleXOffset;
|
||||
sourceRegion.height -= subsampleYOffset;
|
||||
}
|
||||
|
||||
return sourceRegion;
|
||||
}
|
||||
|
||||
public static BufferedImage fakeAOI(final BufferedImage pImage, final Rectangle pSourceRegion) {
|
||||
if (pImage == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (pSourceRegion != null) {
|
||||
if (pSourceRegion.x != 0 || pSourceRegion.y != 0 || pSourceRegion.width != pImage.getWidth() || pSourceRegion.height != pImage.getHeight()) {
|
||||
return pImage.getSubimage(pSourceRegion.x, pSourceRegion.y, pSourceRegion.width, pSourceRegion.height);
|
||||
}
|
||||
}
|
||||
|
||||
return pImage;
|
||||
}
|
||||
}
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
package com.twelvemonkeys.imageio.util;
|
||||
|
||||
import javax.imageio.ImageTypeSpecifier;
|
||||
import java.awt.image.IndexColorModel;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.WritableRaster;
|
||||
import java.util.Hashtable;
|
||||
|
||||
/**
|
||||
* IndexedImageTypeSpecifier
|
||||
*
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @author last modified by $Author: haraldk$
|
||||
* @version $Id: IndexedImageTypeSpecifier.java,v 1.0 May 19, 2008 11:04:28 AM haraldk Exp$
|
||||
*/
|
||||
public class IndexedImageTypeSpecifier extends ImageTypeSpecifier {
|
||||
IndexedImageTypeSpecifier(IndexColorModel pColorModel) {
|
||||
// For some reason, we need a sample model
|
||||
super(pColorModel, pColorModel.createCompatibleSampleModel(1, 1));
|
||||
}
|
||||
|
||||
public static ImageTypeSpecifier createFromIndexColorModel(final IndexColorModel pColorModel) {
|
||||
return new IndexedImageTypeSpecifier(pColorModel);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final BufferedImage createBufferedImage(int pWidth, int pHeight) {
|
||||
try {
|
||||
// This is a fix for the super-method, that first creates a sample model, and then
|
||||
// creates a raster from it, using Raster.createWritableRaster. The problem with
|
||||
// that approach, is that it always creates a TYPE_CUSTOM BufferedImage for indexed images.
|
||||
WritableRaster raster = colorModel.createCompatibleWritableRaster(pWidth, pHeight);
|
||||
return new BufferedImage(colorModel, raster, colorModel.isAlphaPremultiplied(), new Hashtable());
|
||||
}
|
||||
catch (NegativeArraySizeException e) {
|
||||
// Exception most likely thrown from a DataBuffer constructor
|
||||
throw new IllegalArgumentException("Array size > Integer.MAX_VALUE!");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Executable
+94
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* 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.util;
|
||||
|
||||
import javax.imageio.ImageReader;
|
||||
import javax.imageio.ImageWriter;
|
||||
import javax.imageio.event.IIOReadProgressListener;
|
||||
import javax.imageio.event.IIOWriteProgressListener;
|
||||
|
||||
/**
|
||||
* ProgressListenerBase
|
||||
* <p/>
|
||||
*
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @version $Id: ProgressListenerBase.java,v 1.0 26.aug.2005 14:29:42 haku Exp$
|
||||
*/
|
||||
public abstract class ProgressListenerBase implements IIOReadProgressListener, IIOWriteProgressListener {
|
||||
protected ProgressListenerBase() {
|
||||
}
|
||||
|
||||
public void imageComplete(ImageReader pSource) {
|
||||
}
|
||||
|
||||
public void imageProgress(ImageReader pSource, float pPercentageDone) {
|
||||
}
|
||||
|
||||
public void imageStarted(ImageReader pSource, int pImageIndex) {
|
||||
}
|
||||
|
||||
public void readAborted(ImageReader pSource) {
|
||||
}
|
||||
|
||||
public void sequenceComplete(ImageReader pSource) {
|
||||
}
|
||||
|
||||
public void sequenceStarted(ImageReader pSource, int pMinIndex) {
|
||||
}
|
||||
|
||||
public void thumbnailComplete(ImageReader pSource) {
|
||||
}
|
||||
|
||||
public void thumbnailProgress(ImageReader pSource, float pPercentageDone) {
|
||||
}
|
||||
|
||||
public void thumbnailStarted(ImageReader pSource, int pImageIndex, int pThumbnailIndex) {
|
||||
}
|
||||
|
||||
public void imageComplete(ImageWriter pSource) {
|
||||
}
|
||||
|
||||
public void imageProgress(ImageWriter pSource, float pPercentageDone) {
|
||||
}
|
||||
|
||||
public void imageStarted(ImageWriter pSource, int pImageIndex) {
|
||||
}
|
||||
|
||||
public void thumbnailComplete(ImageWriter pSource) {
|
||||
}
|
||||
|
||||
public void thumbnailProgress(ImageWriter pSource, float pPercentageDone) {
|
||||
}
|
||||
|
||||
public void thumbnailStarted(ImageWriter pSource, int pImageIndex, int pThumbnailIndex) {
|
||||
}
|
||||
|
||||
public void writeAborted(ImageWriter pSource) {
|
||||
}
|
||||
}
|
||||
Executable
+98
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
* 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.util;
|
||||
|
||||
import com.twelvemonkeys.io.FileUtil;
|
||||
import com.twelvemonkeys.lang.StringUtil;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.swing.filechooser.FileFilter;
|
||||
import java.io.File;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* ReaderFileSuffixFilter
|
||||
* <p/>
|
||||
*
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @author last modified by $Author: haku$
|
||||
* @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<String, Boolean> mKnownSuffixes = new HashMap<String, Boolean>(32);
|
||||
|
||||
public ReaderFileSuffixFilter() {
|
||||
this("Images (all supported input formats)");
|
||||
}
|
||||
|
||||
public ReaderFileSuffixFilter(String pDescription) {
|
||||
mDescription = pDescription;
|
||||
}
|
||||
|
||||
public boolean accept(File pFile) {
|
||||
// Directories are always supported
|
||||
if (pFile.isDirectory()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// See if we have an ImageReader for this suffix
|
||||
String suffix = FileUtil.getExtension(pFile);
|
||||
|
||||
return !StringUtil.isEmpty(suffix) && hasReaderForSuffix(suffix);
|
||||
}
|
||||
|
||||
private boolean hasReaderForSuffix(String pSuffix) {
|
||||
if (mKnownSuffixes.get(pSuffix) == Boolean.TRUE) {
|
||||
return true;
|
||||
}
|
||||
|
||||
try {
|
||||
// Cahce lookup
|
||||
Iterator iterator = ImageIO.getImageReadersBySuffix(pSuffix);
|
||||
if (iterator.hasNext()) {
|
||||
mKnownSuffixes.put(pSuffix, Boolean.TRUE);
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
mKnownSuffixes.put(pSuffix, Boolean.FALSE);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
catch (IllegalArgumentException iae) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return mDescription;
|
||||
}
|
||||
}
|
||||
Executable
+98
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
* 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.util;
|
||||
|
||||
import com.twelvemonkeys.io.FileUtil;
|
||||
import com.twelvemonkeys.lang.StringUtil;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.swing.filechooser.FileFilter;
|
||||
import java.io.File;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* WriterFileSuffixFilter
|
||||
* <p/>
|
||||
*
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @author last modified by $Author: haku$
|
||||
* @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 Map<String, Boolean>mKnownSuffixes = new HashMap<String, Boolean>(32);
|
||||
|
||||
public WriterFileSuffixFilter() {
|
||||
this("Images (all supported output formats)");
|
||||
}
|
||||
|
||||
public WriterFileSuffixFilter(String pDescription) {
|
||||
mDescription = pDescription;
|
||||
}
|
||||
|
||||
public boolean accept(File pFile) {
|
||||
// Directories are always supported
|
||||
if (pFile.isDirectory()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Test if we have an ImageWriter for this suffix
|
||||
String suffix = FileUtil.getExtension(pFile);
|
||||
return !StringUtil.isEmpty(suffix) && hasWriterForSuffix(suffix);
|
||||
|
||||
}
|
||||
|
||||
private boolean hasWriterForSuffix(String pSuffix) {
|
||||
if (mKnownSuffixes.get(pSuffix) == Boolean.TRUE) {
|
||||
return true;
|
||||
}
|
||||
|
||||
try {
|
||||
// Cahce lookup
|
||||
Iterator iterator = ImageIO.getImageWritersBySuffix(pSuffix);
|
||||
if (iterator.hasNext()) {
|
||||
mKnownSuffixes.put(pSuffix, Boolean.TRUE);
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
mKnownSuffixes.put(pSuffix, Boolean.FALSE);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
catch (IllegalArgumentException iae) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return mDescription;
|
||||
}
|
||||
}
|
||||
+116
@@ -0,0 +1,116 @@
|
||||
package com.twelvemonkeys.imageio.stream;
|
||||
|
||||
import com.twelvemonkeys.io.ole2.CompoundDocument;
|
||||
import com.twelvemonkeys.io.ole2.Entry;
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import javax.imageio.stream.ImageInputStream;
|
||||
import javax.imageio.stream.MemoryCacheImageInputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteOrder;
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* BufferedImageInputStreamTestCase
|
||||
*
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @author last modified by $Author: haraldk$
|
||||
* @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();
|
||||
|
||||
public void testCreate() {
|
||||
new BufferedImageInputStream(new ByteArrayImageInputStream(new byte[0]));
|
||||
}
|
||||
|
||||
public void testCreateNull() {
|
||||
try {
|
||||
new BufferedImageInputStream(null);
|
||||
fail("Expected IllegalArgumentException");
|
||||
}
|
||||
catch (IllegalArgumentException expected) {
|
||||
assertNotNull("Null exception message", expected.getMessage());
|
||||
String message = expected.getMessage().toLowerCase();
|
||||
assertTrue("Exception message does not contain parameter name", message.contains("stream"));
|
||||
assertTrue("Exception message does not contain null", message.contains("null"));
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Write other tests
|
||||
|
||||
// TODO: Create test that exposes read += -1 (eof) bug
|
||||
|
||||
public void testArrayIndexOutOfBoundsBufferedReadBug() throws IOException {
|
||||
// TODO: Create a more straight forward way to prove correctness, for now this is good enough to avoid regression
|
||||
ImageInputStream input = new BufferedImageInputStream(new MemoryCacheImageInputStream(getClass().getResourceAsStream("/Thumbs-camera.db")));
|
||||
input.setByteOrder(ByteOrder.LITTLE_ENDIAN);
|
||||
Entry root = new CompoundDocument(input).getRootEntry();
|
||||
|
||||
Entry child = root.getChildEntry("Catalog");
|
||||
|
||||
assertNotNull("Input stream can never be null", child.getInputStream());
|
||||
}
|
||||
|
||||
public void testReadResetReadDirectBufferBug() throws IOException {
|
||||
// Make sure we use the exact size of the buffer
|
||||
final int size = BufferedImageInputStream.DEFAULT_BUFFER_SIZE;
|
||||
|
||||
// Fill bytes
|
||||
byte[] bytes = new byte[size * 2];
|
||||
mRandom.nextBytes(bytes);
|
||||
|
||||
// Create wrapper stream
|
||||
BufferedImageInputStream stream = new BufferedImageInputStream(new ByteArrayImageInputStream(bytes));
|
||||
|
||||
// Read to fill the buffer, then reset
|
||||
stream.readLong();
|
||||
stream.seek(0);
|
||||
|
||||
// Read fully and compare
|
||||
byte[] result = new byte[size];
|
||||
stream.readFully(result);
|
||||
assertTrue(rangeEquals(bytes, 0, result, 0, size));
|
||||
|
||||
stream.readFully(result);
|
||||
assertTrue(rangeEquals(bytes, size, result, 0, size));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test two arrays for range equality. That is, they contain the same elements for some specified range.
|
||||
*
|
||||
* @param pFirst one array to test for equality
|
||||
* @param pFirstOffset the offset into the first array to start testing for equality
|
||||
* @param pSecond the other array to test for equality
|
||||
* @param pSecondOffset the offset into the second array to start testing for equality
|
||||
* @param pLength the length of the range to check for equality
|
||||
*
|
||||
* @return {@code true} if both arrays are non-{@code null}
|
||||
* and have at least {@code offset + pLength} elements
|
||||
* and all elements in the range from the first array is equal to the elements from the second array,
|
||||
* or if {@code pFirst == pSecond} (including both arrays being {@code null})
|
||||
* and {@code pFirstOffset == pSecondOffset}.
|
||||
* Otherwise {@code false}.
|
||||
*/
|
||||
static boolean rangeEquals(byte[] pFirst, int pFirstOffset, byte[] pSecond, int pSecondOffset, int pLength) {
|
||||
if (pFirst == pSecond && pFirstOffset == pSecondOffset) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (pFirst == null || pSecond == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (pFirst.length < pFirstOffset + pLength || pSecond.length < pSecondOffset + pLength) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < pLength; i++) {
|
||||
if (pFirst[pFirstOffset + i] != pSecond[pSecondOffset + i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
+102
@@ -0,0 +1,102 @@
|
||||
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;
|
||||
|
||||
/**
|
||||
* ByteArrayImageInputStreamTestCase
|
||||
*
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @author last modified by $Author: haraldk$
|
||||
* @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();
|
||||
|
||||
public void testCreate() {
|
||||
ByteArrayImageInputStream stream = new ByteArrayImageInputStream(new byte[0]);
|
||||
assertEquals("Data length should be same as stream length", 0, stream.length());
|
||||
}
|
||||
|
||||
public void testCreateNull() {
|
||||
try {
|
||||
new ByteArrayImageInputStream(null);
|
||||
fail("Expected IllegalArgumentException");
|
||||
}
|
||||
catch (IllegalArgumentException expected) {
|
||||
assertNotNull("Null exception message", expected.getMessage());
|
||||
String message = expected.getMessage().toLowerCase();
|
||||
assertTrue("Exception message does not contain parameter name", message.contains("data"));
|
||||
assertTrue("Exception message does not contain null", message.contains("null"));
|
||||
}
|
||||
}
|
||||
|
||||
public void testRead() throws IOException {
|
||||
byte[] data = new byte[1024 * 1024];
|
||||
mRandom.nextBytes(data);
|
||||
|
||||
ByteArrayImageInputStream stream = new ByteArrayImageInputStream(data);
|
||||
|
||||
assertEquals("Data length should be same as stream length", data.length, stream.length());
|
||||
|
||||
for (byte b : data) {
|
||||
assertEquals("Wrong data read", b & 0xff, stream.read());
|
||||
}
|
||||
}
|
||||
|
||||
public void testReadArray() throws IOException {
|
||||
byte[] data = new byte[1024 * 1024];
|
||||
mRandom.nextBytes(data);
|
||||
|
||||
ByteArrayImageInputStream stream = new ByteArrayImageInputStream(data);
|
||||
|
||||
assertEquals("Data length should be same as stream length", data.length, stream.length());
|
||||
|
||||
byte[] result = new byte[1024];
|
||||
|
||||
for (int i = 0; i < data.length / result.length; i++) {
|
||||
stream.readFully(result);
|
||||
assertTrue("Wrong data read: " + i, rangeEquals(data, i * result.length, result, 0, result.length));
|
||||
}
|
||||
}
|
||||
|
||||
public void testReadSkip() throws IOException {
|
||||
byte[] data = new byte[1024 * 14];
|
||||
mRandom.nextBytes(data);
|
||||
|
||||
ByteArrayImageInputStream stream = new ByteArrayImageInputStream(data);
|
||||
|
||||
assertEquals("Data length should be same as stream length", data.length, stream.length());
|
||||
|
||||
byte[] result = new byte[7];
|
||||
|
||||
for (int i = 0; i < data.length / result.length; i += 2) {
|
||||
stream.readFully(result);
|
||||
stream.skipBytes(result.length);
|
||||
assertTrue("Wrong data read: " + i, rangeEquals(data, i * result.length, result, 0, result.length));
|
||||
}
|
||||
}
|
||||
|
||||
public void testReadSeek() throws IOException {
|
||||
byte[] data = new byte[1024 * 18];
|
||||
mRandom.nextBytes(data);
|
||||
|
||||
ByteArrayImageInputStream stream = new ByteArrayImageInputStream(data);
|
||||
|
||||
assertEquals("Data length should be same as stream length", data.length, stream.length());
|
||||
|
||||
byte[] result = new byte[9];
|
||||
|
||||
for (int i = 0; i < data.length / result.length; i++) {
|
||||
// Read backwards
|
||||
long newPos = stream.length() - result.length - i * result.length;
|
||||
stream.seek(newPos);
|
||||
assertEquals("Wrong stream position", newPos, stream.getStreamPosition());
|
||||
stream.readFully(result);
|
||||
assertTrue("Wrong data read: " + i, rangeEquals(data, (int) newPos, result, 0, result.length));
|
||||
}
|
||||
}
|
||||
}
|
||||
+140
@@ -0,0 +1,140 @@
|
||||
/*
|
||||
* 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.util;
|
||||
|
||||
import com.twelvemonkeys.io.InputStreamAbstractTestCase;
|
||||
|
||||
import javax.imageio.stream.MemoryCacheImageInputStream;
|
||||
import java.io.InputStream;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* IIOInputStreamAdapter
|
||||
*
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @author last modified by $Author: haraldk$
|
||||
* @version $Id: IIOInputStreamAdapter.java,v 1.0 Apr 11, 2008 1:04:42 PM haraldk Exp$
|
||||
*/
|
||||
public class IIOInputStreamAdapterTestCase extends InputStreamAbstractTestCase {
|
||||
public IIOInputStreamAdapterTestCase(String name) {
|
||||
super(name);
|
||||
}
|
||||
|
||||
protected InputStream makeInputStream(byte[] pBytes) {
|
||||
return new IIOInputStreamAdapter(new MemoryCacheImageInputStream(new ByteArrayInputStream(pBytes)), pBytes.length);
|
||||
}
|
||||
|
||||
public void testReadSubstreamOpenEnd() throws IOException {
|
||||
byte[] bytes = new byte[20];
|
||||
|
||||
MemoryCacheImageInputStream input = new MemoryCacheImageInputStream(new ByteArrayInputStream(bytes));
|
||||
|
||||
input.seek(10);
|
||||
assertEquals(10, input.getStreamPosition());
|
||||
|
||||
IIOInputStreamAdapter stream = new IIOInputStreamAdapter(input);
|
||||
for (int i = 0; i < 10; i++) {
|
||||
assertTrue("Unexpected end of stream", -1 != stream.read());
|
||||
}
|
||||
|
||||
assertEquals("Read value after end of stream", -1, stream.read());
|
||||
assertEquals("Read value after end of stream", -1, stream.read());
|
||||
|
||||
// Make sure underlying stream is positioned at end of substream after close
|
||||
stream.close();
|
||||
assertEquals(20, input.getStreamPosition());
|
||||
|
||||
input.close();
|
||||
}
|
||||
|
||||
public void testReadSubstream() throws IOException {
|
||||
byte[] bytes = new byte[20];
|
||||
|
||||
MemoryCacheImageInputStream input = new MemoryCacheImageInputStream(new ByteArrayInputStream(bytes));
|
||||
IIOInputStreamAdapter stream = new IIOInputStreamAdapter(input, 9);
|
||||
for (int i = 0; i < 9; i++) {
|
||||
assertTrue("Unexpected end of stream", -1 != stream.read());
|
||||
}
|
||||
|
||||
assertEquals("Read value after end of stream", -1, stream.read());
|
||||
assertEquals("Read value after end of stream", -1, stream.read());
|
||||
|
||||
// Make sure we don't read outside stream boundaries
|
||||
assertTrue(input.getStreamPosition() <= 9);
|
||||
|
||||
input.close();
|
||||
}
|
||||
|
||||
public void testReadSubstreamRepositionOnClose() throws IOException {
|
||||
byte[] bytes = new byte[20];
|
||||
|
||||
MemoryCacheImageInputStream input = new MemoryCacheImageInputStream(new ByteArrayInputStream(bytes));
|
||||
IIOInputStreamAdapter stream = new IIOInputStreamAdapter(input, 10);
|
||||
for (int i = 0; i < 7; i++) {
|
||||
assertTrue("Unexpected end of stream", -1 != stream.read());
|
||||
}
|
||||
|
||||
// Make sure we don't read outside stream boundaries
|
||||
assertTrue(input.getStreamPosition() <= 7);
|
||||
|
||||
// Make sure underlying stream is positioned at end of substream after close
|
||||
stream.close();
|
||||
assertEquals(10, input.getStreamPosition());
|
||||
|
||||
input.close();
|
||||
}
|
||||
|
||||
public void testSeekBeforeStreamNoEnd() throws IOException {
|
||||
byte[] bytes = new byte[20];
|
||||
|
||||
MemoryCacheImageInputStream input = new MemoryCacheImageInputStream(new ByteArrayInputStream(bytes));
|
||||
|
||||
input.seek(10);
|
||||
assertEquals(10, input.getStreamPosition());
|
||||
|
||||
IIOInputStreamAdapter stream = new IIOInputStreamAdapter(input);
|
||||
assertEquals("Should not skip backwards", 0, stream.skip(-5));
|
||||
assertEquals(10, input.getStreamPosition());
|
||||
}
|
||||
|
||||
public void testSeekBeforeStream() throws IOException {
|
||||
byte[] bytes = new byte[20];
|
||||
|
||||
MemoryCacheImageInputStream input = new MemoryCacheImageInputStream(new ByteArrayInputStream(bytes));
|
||||
|
||||
input.seek(10);
|
||||
assertEquals(10, input.getStreamPosition());
|
||||
|
||||
IIOInputStreamAdapter stream = new IIOInputStreamAdapter(input, 9);
|
||||
assertEquals("Should not skip backwards", 0, stream.skip(-5));
|
||||
assertEquals(10, input.getStreamPosition());
|
||||
|
||||
}
|
||||
}
|
||||
+1373
File diff suppressed because it is too large
Load Diff
+322
@@ -0,0 +1,322 @@
|
||||
/*
|
||||
* 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.util;
|
||||
|
||||
import org.jmock.Mock;
|
||||
import org.jmock.cglib.MockObjectTestCase;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.imageio.ImageWriteParam;
|
||||
import javax.imageio.ImageWriter;
|
||||
import javax.imageio.event.IIOWriteProgressListener;
|
||||
import java.awt.image.RenderedImage;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* ImageReaderAbstractTestCase class description.
|
||||
*
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @author last modified by $Author: haku $
|
||||
* @version $Id: ImageReaderAbstractTestCase.java,v 1.0 18.nov.2004 17:38:33 haku Exp $
|
||||
*/
|
||||
public abstract class ImageWriterAbstractTestCase extends MockObjectTestCase {
|
||||
|
||||
protected abstract ImageWriter createImageWriter();
|
||||
|
||||
protected abstract RenderedImage getTestData();
|
||||
|
||||
public void testSetOutput() throws IOException {
|
||||
// Should just pass with no exceptions
|
||||
ImageWriter writer = createImageWriter();
|
||||
assertNotNull(writer);
|
||||
writer.setOutput(ImageIO.createImageOutputStream(new ByteArrayOutputStream()));
|
||||
}
|
||||
|
||||
public void testSetOutputNull() {
|
||||
// Should just pass with no exceptions
|
||||
ImageWriter writer = createImageWriter();
|
||||
assertNotNull(writer);
|
||||
writer.setOutput(null);
|
||||
}
|
||||
|
||||
public void testWrite() throws IOException {
|
||||
ImageWriter writer = createImageWriter();
|
||||
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
||||
writer.setOutput(ImageIO.createImageOutputStream(buffer));
|
||||
try {
|
||||
writer.write(getTestData());
|
||||
}
|
||||
catch (IOException e) {
|
||||
fail(e.getMessage());
|
||||
}
|
||||
assertTrue("No image data written", buffer.size() > 0);
|
||||
}
|
||||
|
||||
public void testWrite2() {
|
||||
// Note: There's a difference between new ImageOutputStreamImpl and
|
||||
// ImageIO.createImageOutputStream... Make sure writers handle both
|
||||
// cases
|
||||
ImageWriter writer = createImageWriter();
|
||||
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
||||
try {
|
||||
writer.setOutput(ImageIO.createImageOutputStream(buffer));
|
||||
writer.write(getTestData());
|
||||
}
|
||||
catch (IOException e) {
|
||||
fail(e.getMessage());
|
||||
}
|
||||
|
||||
assertTrue("No image data written", buffer.size() > 0);
|
||||
}
|
||||
|
||||
public void testWriteNull() throws IOException {
|
||||
ImageWriter writer = createImageWriter();
|
||||
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
||||
writer.setOutput(ImageIO.createImageOutputStream(buffer));
|
||||
try {
|
||||
writer.write((RenderedImage) null);
|
||||
}
|
||||
catch(IllegalArgumentException ignore) {
|
||||
}
|
||||
catch (IOException e) {
|
||||
fail(e.getMessage());
|
||||
}
|
||||
assertTrue("Image data written", buffer.size() == 0);
|
||||
}
|
||||
|
||||
public void testWriteNoOutput() {
|
||||
ImageWriter writer = createImageWriter();
|
||||
try {
|
||||
writer.write(getTestData());
|
||||
}
|
||||
catch (IllegalStateException ignore) {
|
||||
}
|
||||
catch (IOException e) {
|
||||
fail(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public void testGetDefaultWriteParam() {
|
||||
ImageWriter writer = createImageWriter();
|
||||
ImageWriteParam param = writer.getDefaultWriteParam();
|
||||
assertNotNull("Default ImageWriteParam is null", param);
|
||||
}
|
||||
|
||||
// TODO: Test writing with params
|
||||
// TODO: Source region and subsampling at least
|
||||
|
||||
public void testAddIIOWriteProgressListener() {
|
||||
ImageWriter writer = createImageWriter();
|
||||
Mock mockListener = new Mock(IIOWriteProgressListener.class);
|
||||
writer.addIIOWriteProgressListener((IIOWriteProgressListener) mockListener.proxy());
|
||||
}
|
||||
|
||||
public void testAddIIOWriteProgressListenerNull() {
|
||||
ImageWriter writer = createImageWriter();
|
||||
writer.addIIOWriteProgressListener(null);
|
||||
}
|
||||
|
||||
public void testAddIIOWriteProgressListenerCallbacks() throws IOException {
|
||||
ImageWriter writer = createImageWriter();
|
||||
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
||||
writer.setOutput(ImageIO.createImageOutputStream(buffer));
|
||||
|
||||
Mock mockListener = new Mock(IIOWriteProgressListener.class);
|
||||
String started = "Started";
|
||||
mockListener.expects(once()).method("imageStarted").withAnyArguments().id(started);
|
||||
mockListener.stubs().method("imageProgress").withAnyArguments().after(started);
|
||||
mockListener.expects(once()).method("imageComplete").withAnyArguments().after(started);
|
||||
|
||||
writer.addIIOWriteProgressListener((IIOWriteProgressListener) mockListener.proxy());
|
||||
|
||||
try {
|
||||
writer.write(getTestData());
|
||||
}
|
||||
catch (IOException e) {
|
||||
fail("Could not write image");
|
||||
}
|
||||
|
||||
// At least imageStarted and imageComplete, plus any number of imageProgress
|
||||
mockListener.verify();
|
||||
}
|
||||
|
||||
public void testMultipleAddIIOWriteProgressListenerCallbacks() throws IOException {
|
||||
ImageWriter writer = createImageWriter();
|
||||
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
||||
writer.setOutput(ImageIO.createImageOutputStream(buffer));
|
||||
|
||||
Mock mockListener = new Mock(IIOWriteProgressListener.class);
|
||||
String started = "Started";
|
||||
mockListener.expects(once()).method("imageStarted").withAnyArguments().id(started);
|
||||
mockListener.stubs().method("imageProgress").withAnyArguments().after(started);
|
||||
mockListener.expects(once()).method("imageComplete").withAnyArguments().after(started);
|
||||
|
||||
Mock mockListenerToo = new Mock(IIOWriteProgressListener.class);
|
||||
String startedToo = "Started Two";
|
||||
mockListenerToo.expects(once()).method("imageStarted").withAnyArguments().id(startedToo);
|
||||
mockListenerToo.stubs().method("imageProgress").withAnyArguments().after(startedToo);
|
||||
mockListenerToo.expects(once()).method("imageComplete").withAnyArguments().after(startedToo);
|
||||
|
||||
Mock mockListenerThree = new Mock(IIOWriteProgressListener.class);
|
||||
String startedThree = "Started Three";
|
||||
mockListenerThree.expects(once()).method("imageStarted").withAnyArguments().id(startedThree);
|
||||
mockListenerThree.stubs().method("imageProgress").withAnyArguments().after(startedThree);
|
||||
mockListenerThree.expects(once()).method("imageComplete").withAnyArguments().after(startedThree);
|
||||
|
||||
|
||||
writer.addIIOWriteProgressListener((IIOWriteProgressListener) mockListener.proxy());
|
||||
writer.addIIOWriteProgressListener((IIOWriteProgressListener) mockListenerToo.proxy());
|
||||
writer.addIIOWriteProgressListener((IIOWriteProgressListener) mockListenerThree.proxy());
|
||||
|
||||
try {
|
||||
writer.write(getTestData());
|
||||
}
|
||||
catch (IOException e) {
|
||||
fail("Could not write image");
|
||||
}
|
||||
|
||||
// At least imageStarted and imageComplete, plus any number of imageProgress
|
||||
mockListener.verify();
|
||||
mockListenerToo.verify();
|
||||
mockListenerThree.verify();
|
||||
}
|
||||
|
||||
|
||||
public void testRemoveIIOWriteProgressListenerNull() {
|
||||
ImageWriter writer = createImageWriter();
|
||||
writer.removeIIOWriteProgressListener(null);
|
||||
}
|
||||
|
||||
public void testRemoveIIOWriteProgressListenerNone() {
|
||||
ImageWriter writer = createImageWriter();
|
||||
Mock mockListener = new Mock(IIOWriteProgressListener.class);
|
||||
writer.removeIIOWriteProgressListener((IIOWriteProgressListener) mockListener.proxy());
|
||||
}
|
||||
|
||||
public void testRemoveIIOWriteProgressListener() throws IOException {
|
||||
ImageWriter writer = createImageWriter();
|
||||
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
||||
writer.setOutput(ImageIO.createImageOutputStream(buffer));
|
||||
|
||||
Mock mockListener = new Mock(IIOWriteProgressListener.class);
|
||||
IIOWriteProgressListener listener = (IIOWriteProgressListener) mockListener.proxy();
|
||||
writer.addIIOWriteProgressListener(listener);
|
||||
writer.removeIIOWriteProgressListener(listener);
|
||||
|
||||
try {
|
||||
writer.write(getTestData());
|
||||
}
|
||||
catch (IOException e) {
|
||||
fail("Could not write image");
|
||||
}
|
||||
|
||||
// Should not have called any methods...
|
||||
mockListener.verify();
|
||||
}
|
||||
|
||||
public void testRemoveIIOWriteProgressListenerMultiple() throws IOException {
|
||||
ImageWriter writer = createImageWriter();
|
||||
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
||||
writer.setOutput(ImageIO.createImageOutputStream(buffer));
|
||||
|
||||
|
||||
Mock mockListener = new Mock(IIOWriteProgressListener.class);
|
||||
writer.addIIOWriteProgressListener((IIOWriteProgressListener) mockListener.proxy());
|
||||
|
||||
Mock mockListenerToo = new Mock(IIOWriteProgressListener.class);
|
||||
mockListenerToo.stubs().method("imageStarted").withAnyArguments();
|
||||
mockListenerToo.stubs().method("imageProgress").withAnyArguments();
|
||||
mockListenerToo.stubs().method("imageComplete").withAnyArguments();
|
||||
writer.addIIOWriteProgressListener((IIOWriteProgressListener) mockListenerToo.proxy());
|
||||
|
||||
writer.removeIIOWriteProgressListener((IIOWriteProgressListener) mockListener.proxy());
|
||||
|
||||
try {
|
||||
writer.write(getTestData());
|
||||
}
|
||||
catch (IOException e) {
|
||||
fail("Could not write image");
|
||||
}
|
||||
|
||||
// Should not have called any methods...
|
||||
mockListener.verify();
|
||||
mockListenerToo.verify();
|
||||
}
|
||||
|
||||
|
||||
public void testRemoveAllIIOWriteProgressListeners() throws IOException {
|
||||
ImageWriter writer = createImageWriter();
|
||||
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
||||
writer.setOutput(ImageIO.createImageOutputStream(buffer));
|
||||
|
||||
|
||||
Mock mockListener = new Mock(IIOWriteProgressListener.class);
|
||||
writer.addIIOWriteProgressListener((IIOWriteProgressListener) mockListener.proxy());
|
||||
|
||||
writer.removeAllIIOWriteProgressListeners();
|
||||
|
||||
try {
|
||||
writer.write(getTestData());
|
||||
}
|
||||
catch (IOException e) {
|
||||
fail("Could not write image");
|
||||
}
|
||||
|
||||
// Should not have called any methods...
|
||||
mockListener.verify();
|
||||
}
|
||||
|
||||
public void testRemoveAllIIOWriteProgressListenersMultiple() throws IOException {
|
||||
ImageWriter writer = createImageWriter();
|
||||
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
||||
writer.setOutput(ImageIO.createImageOutputStream(buffer));
|
||||
|
||||
|
||||
Mock mockListener = new Mock(IIOWriteProgressListener.class);
|
||||
writer.addIIOWriteProgressListener((IIOWriteProgressListener) mockListener.proxy());
|
||||
|
||||
Mock mockListenerToo = new Mock(IIOWriteProgressListener.class);
|
||||
writer.addIIOWriteProgressListener((IIOWriteProgressListener) mockListenerToo.proxy());
|
||||
|
||||
writer.removeAllIIOWriteProgressListeners();
|
||||
|
||||
try {
|
||||
writer.write(getTestData());
|
||||
}
|
||||
catch (IOException e) {
|
||||
fail("Could not write image");
|
||||
}
|
||||
|
||||
// Should not have called any methods...
|
||||
mockListener.verify();
|
||||
mockListenerToo.verify();
|
||||
}
|
||||
|
||||
}
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
package com.twelvemonkeys.imageio.util;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import java.awt.image.DataBuffer;
|
||||
import java.awt.image.IndexColorModel;
|
||||
|
||||
/**
|
||||
* IndexedImageTypeSpecifierTestCase
|
||||
*
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @author last modified by $Author: haraldk$
|
||||
* @version $Id: IndexedImageTypeSpecifierTestCase.java,v 1.0 Jun 9, 2008 2:42:03 PM haraldk Exp$
|
||||
*/
|
||||
public class IndexedImageTypeSpecifierTestCase extends TestCase {
|
||||
public void testEquals() {
|
||||
IndexColorModel cm = new IndexColorModel(1, 2, new int[]{0xffffff, 0x00}, 0, false, -1, DataBuffer.TYPE_BYTE);
|
||||
|
||||
IndexedImageTypeSpecifier spec = new IndexedImageTypeSpecifier(cm);
|
||||
IndexedImageTypeSpecifier other = new IndexedImageTypeSpecifier(cm);
|
||||
|
||||
assertEquals(spec, other);
|
||||
assertEquals(other, spec);
|
||||
|
||||
assertTrue(spec.equals(other));
|
||||
assertTrue(other.equals(spec));
|
||||
}
|
||||
}
|
||||
Binary file not shown.
Reference in New Issue
Block a user