mirror of
https://github.com/haraldk/TwelveMonkeys.git
synced 2025-10-04 11:26:44 -04:00
It all works
This commit is contained in:
25
imageio/imageio-core/license.txt
Executable file
25
imageio/imageio-core/license.txt
Executable file
@@ -0,0 +1,25 @@
|
||||
Copyright (c) 2009, 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.
|
16
imageio/imageio-core/pom.xml
Normal file
16
imageio/imageio-core/pom.xml
Normal file
@@ -0,0 +1,16 @@
|
||||
<?xml version="1.0"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>com.twelvemonkeys.imageio</groupId>
|
||||
<artifactId>twelvemonkeys-imageio-core</artifactId>
|
||||
<version>2.3-SNAPSHOT</version>
|
||||
<name>TwelveMonkeys ImageIO Core</name>
|
||||
|
||||
<parent>
|
||||
<artifactId>twelvemonkeys-imageio</artifactId>
|
||||
<groupId>com.twelvemonkeys</groupId>
|
||||
<version>2.3-SNAPSHOT</version>
|
||||
</parent>
|
||||
</project>
|
@@ -0,0 +1,478 @@
|
||||
/*
|
||||
* 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.*;
|
||||
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.awt.image.IndexColorModel;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* Abstract base class for image readers.
|
||||
*
|
||||
* @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 pProvider the {@code ImageReaderSpi} that is invoking this constructor, or {@code null}.
|
||||
*/
|
||||
protected ImageReaderBase(final ImageReaderSpi pProvider) {
|
||||
super(pProvider);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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(final Object pInput, final boolean pSeekForwardOnly, final 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();
|
||||
|
||||
/**
|
||||
* Default implementation that always returns {@code null}.
|
||||
*
|
||||
* @param pImageIndex ignored, unless overridden
|
||||
* @return {@code null}, unless overridden
|
||||
* @throws IOException never, unless overridden.
|
||||
*/
|
||||
public IIOMetadata getImageMetadata(int pImageIndex) throws IOException {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Default implementation that always returns {@code null}.
|
||||
*
|
||||
* @return {@code null}, unless overridden
|
||||
* @throws IOException never, unless overridden.
|
||||
*/
|
||||
public IIOMetadata getStreamMetadata() throws IOException {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Default implementation that always returns {@code 1}.
|
||||
*
|
||||
* @param pAllowSearch ignored, unless overridden
|
||||
* @return {@code 1}, unless overridden
|
||||
* @throws IOException never, unless overridden
|
||||
*/
|
||||
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 {@code minIndex <= pIndex < numImages}
|
||||
*/
|
||||
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");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@code BufferedImage} to which decoded pixel
|
||||
* data should be written.
|
||||
* <p/>
|
||||
* As {@link javax.imageio.ImageReader#getDestination} but tests if the explicit destination
|
||||
* image (if set) is valid according to the {@code ImageTypeSpecifier}s given in {@code pTypes}
|
||||
*
|
||||
*
|
||||
* @param pParam an {@code ImageReadParam} to be used to get
|
||||
* the destination image or image type, or {@code null}.
|
||||
* @param pTypes an {@code Iterator} of
|
||||
* {@code ImageTypeSpecifier}s indicating the legal image
|
||||
* types, with the default first.
|
||||
* @param pWidth the true width of the image or tile begin decoded.
|
||||
* @param pHeight the true width of the image or tile being decoded.
|
||||
*
|
||||
* @return the {@code BufferedImage} to which decoded pixel
|
||||
* data should be written.
|
||||
*
|
||||
* @exception IIOException if the {@code ImageTypeSpecifier} or {@code BufferedImage}
|
||||
* specified by {@code pParam} does not match any of the legal
|
||||
* ones from {@code pTypes}.
|
||||
* @throws IllegalArgumentException if {@code pTypes}
|
||||
* is {@code null} or empty, or if an object not of type
|
||||
* {@code ImageTypeSpecifier} is retrieved from it.
|
||||
* Or, if the resulting image would have a width or height less than 1,
|
||||
* or if the product of {@code pWidth} and {@code pHeight} is greater than
|
||||
* {@code Integer.MAX_VALUE}.
|
||||
*/
|
||||
public static BufferedImage getDestination(final ImageReadParam pParam, final Iterator<ImageTypeSpecifier> pTypes,
|
||||
final int pWidth, final int pHeight) throws IIOException {
|
||||
BufferedImage image = ImageReader.getDestination(pParam, pTypes, pWidth, pHeight);
|
||||
|
||||
if (pParam != null) {
|
||||
BufferedImage dest = pParam.getDestination();
|
||||
if (dest != null) {
|
||||
boolean found = false;
|
||||
|
||||
// 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();
|
||||
int imageType = specifier.getBufferedImageType();
|
||||
|
||||
if (imageType != 0 && imageType == dest.getType()) {
|
||||
// Known types equal, perfect match
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
else {
|
||||
// If types are different, or TYPE_CUSTOM, test if
|
||||
// - transferType is ok
|
||||
// - bands are ok
|
||||
// TODO: Test if color model is ok?
|
||||
if (specifier.getSampleModel().getTransferType() == dest.getSampleModel().getTransferType() &&
|
||||
specifier.getNumBands() <= dest.getSampleModel().getNumBands()) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
throw new IIOException(String.format("Illegal explicit destination image %s", dest));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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]));
|
||||
if (image == null) {
|
||||
System.err.println("Supported formats: " + Arrays.toString(ImageIO.getReaderFormatNames()));
|
||||
System.exit(1);
|
||||
}
|
||||
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;
|
||||
|
||||
final Paint mCheckeredBG;
|
||||
final Color mDefaultBG;
|
||||
|
||||
public ImageLabel(final BufferedImage pImage) {
|
||||
super(new BufferedImageIcon(pImage));
|
||||
setOpaque(false);
|
||||
setCursor(Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR));
|
||||
|
||||
mCheckeredBG = createTexture();
|
||||
|
||||
// For indexed color, default to the color of the transparent pixel, if any
|
||||
mDefaultBG = getDefaultBackground(pImage);
|
||||
|
||||
mBackground = mDefaultBG != null ? mDefaultBG : mCheckeredBG;
|
||||
|
||||
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("Checkered", mCheckeredBG), 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...", mDefaultBG != null ? mDefaultBG : 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 static Color getDefaultBackground(BufferedImage pImage) {
|
||||
if (pImage.getColorModel() instanceof IndexColorModel) {
|
||||
IndexColorModel cm = (IndexColorModel) pImage.getColorModel();
|
||||
int transparent = cm.getTransparentPixel();
|
||||
if (transparent >= 0) {
|
||||
return new Color(cm.getRGB(transparent), false);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,164 @@
|
||||
/*
|
||||
* 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.ImageWriter;
|
||||
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;
|
||||
|
||||
/**
|
||||
* Abstract base class for image writers.
|
||||
*
|
||||
* @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 ImageWriter {
|
||||
|
||||
/**
|
||||
* For convenience. Only set if the output is an {@code ImageInputStream}.
|
||||
* @see #setOutput(Object)
|
||||
*/
|
||||
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(final 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 ignored.
|
||||
* @return {@code null}.
|
||||
*/
|
||||
public IIOMetadata getDefaultStreamMetadata(final ImageWriteParam pParam) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code null}
|
||||
*
|
||||
* @param pInData ignored.
|
||||
* @param pParam ignored.
|
||||
* @return {@code null}.
|
||||
*/
|
||||
public IIOMetadata convertStreamMetadata(final IIOMetadata pInData, final ImageWriteParam pParam) {
|
||||
return null;
|
||||
}
|
||||
|
||||
protected static Rectangle getSourceRegion(final ImageWriteParam pParam, final int pWidth, final 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 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(final BufferedImage pImage, final 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 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(final Image pImage, final ImageWriteParam pParam) {
|
||||
return IIOUtil.fakeSubsampling(pImage, pParam);
|
||||
}
|
||||
}
|
@@ -0,0 +1,93 @@
|
||||
package com.twelvemonkeys.imageio.spi;
|
||||
|
||||
import com.twelvemonkeys.lang.Validate;
|
||||
|
||||
/**
|
||||
* Provides provider info, like vendor name and version,
|
||||
* for {@link javax.imageio.spi.ImageReaderWriterSpi} subclasses based on information in the manifest.
|
||||
*
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @author last modified by $Author: haraldk$
|
||||
* @version $Id: ProviderInfo.java,v 1.0 Oct 31, 2009 3:49:39 PM haraldk Exp$
|
||||
*
|
||||
* @see <a href="http://java.sun.com/j2se/1.5.0/docs/guide/jar/jar.html#JAR%20Manifest">JAR Manifest</a>
|
||||
*/
|
||||
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;
|
||||
|
||||
/**
|
||||
* Creates a provider information instance based on the given package.
|
||||
*
|
||||
* @param pPackage the package to get provider information from.
|
||||
* This should typically be the package containing the Spi class.
|
||||
*
|
||||
* @throws IllegalArgumentException if {@code pPackage == null}
|
||||
*/
|
||||
public ProviderInfo(final Package pPackage) {
|
||||
Validate.notNull(pPackage, "package");
|
||||
|
||||
String title = pPackage.getImplementationTitle();
|
||||
mTitle = title != null ? title : pPackage.getName();
|
||||
|
||||
String vendor = pPackage.getImplementationVendor();
|
||||
mVendorName = vendor != null ? vendor : fakeVendor(pPackage);
|
||||
|
||||
String version = pPackage.getImplementationVersion();
|
||||
mVersion = version != null ? version : fakeVersion(pPackage);
|
||||
}
|
||||
|
||||
private static String fakeVendor(final Package pPackage) {
|
||||
String name = pPackage.getName();
|
||||
return name.startsWith("com.twelvemonkeys") ? "TwelveMonkeys" : name;
|
||||
}
|
||||
|
||||
private String fakeVersion(Package pPackage) {
|
||||
String name = pPackage.getName();
|
||||
return name.startsWith("com.twelvemonkeys") ? "DEV" : "Unspecified";
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the implementation title, as specified in the manifest entry
|
||||
* {@code Implementation-Title} for the package.
|
||||
* If the title is unavailable, the package name or some default name
|
||||
* for known packages are used.
|
||||
*
|
||||
* @return the implementation title
|
||||
*/
|
||||
final String getImplementationTitle() {
|
||||
return mTitle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the vendor name, as specified in the manifest entry
|
||||
* {@code Implementation-Vendor} for the package.
|
||||
* If the vendor name is unavailable, the package name or some default name
|
||||
* for known packages are used.
|
||||
*
|
||||
* @return the vendor name.
|
||||
*/
|
||||
public final String getVendorName() {
|
||||
return mVendorName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the version/build number string, as specified in the manifest entry
|
||||
* {@code Implementation-Version} for the package.
|
||||
* If the version is unavailable, some arbitrary (non-{@code null}) value is used.
|
||||
*
|
||||
* @return the vendor name.
|
||||
*/
|
||||
public final String getVersion() {
|
||||
return mVersion;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return mTitle + ", " + mVersion + " by " + mVendorName;
|
||||
}
|
||||
}
|
@@ -0,0 +1,185 @@
|
||||
package com.twelvemonkeys.imageio.stream;
|
||||
|
||||
import com.twelvemonkeys.lang.Validate;
|
||||
|
||||
import javax.imageio.stream.ImageInputStream;
|
||||
import javax.imageio.stream.ImageInputStreamImpl;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* A buffered {@code ImageInputStream}.
|
||||
* Experimental - seems to be effective for {@link javax.imageio.stream.FileImageInputStream}
|
||||
* and {@link javax.imageio.stream.FileCacheImageInputStream} when doing a lot of single-byte reads
|
||||
* (or short byte-array reads) on OS X at least.
|
||||
* Code that uses the {@code readFully} methods are not affected by the issue.
|
||||
*
|
||||
* @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?
|
||||
// TODO: Test on other platforms, might be just an OS X issue
|
||||
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) throws IOException {
|
||||
this(pStream, DEFAULT_BUFFER_SIZE);
|
||||
}
|
||||
|
||||
private BufferedImageInputStream(final ImageInputStream pStream, final int pBufferSize) throws IOException {
|
||||
Validate.notNull(pStream, "stream");
|
||||
|
||||
mStream = pStream;
|
||||
streamPos = pStream.getStreamPosition();
|
||||
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;
|
||||
|
||||
if (!isBufferValid()) {
|
||||
// Bypass cache if cache is empty for reads longer than buffer
|
||||
if (pLength >= mBuffer.length) {
|
||||
return readDirect(pBuffer, pOffset, pLength);
|
||||
}
|
||||
else {
|
||||
fillBuffer();
|
||||
}
|
||||
}
|
||||
|
||||
return readBuffered(pBuffer, pOffset, pLength);
|
||||
}
|
||||
|
||||
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));
|
||||
|
||||
if (read > 0) {
|
||||
streamPos += read;
|
||||
}
|
||||
|
||||
mBufferStart = mStream.getStreamPosition();
|
||||
mBufferLength = 0;
|
||||
|
||||
return read;
|
||||
}
|
||||
|
||||
|
||||
private int readBuffered(final byte[] pBuffer, final int pOffset, final int pLength) {
|
||||
if (mBufferLength <= 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Read as much as possible from buffer
|
||||
int length = Math.min(mBufferLength - mBufferPos, pLength);
|
||||
|
||||
if (length > 0) {
|
||||
System.arraycopy(mBuffer, mBufferPos, pBuffer, pOffset, length);
|
||||
mBufferPos += length;
|
||||
}
|
||||
|
||||
streamPos += length;
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
@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();
|
||||
}
|
||||
|
||||
@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;
|
||||
}
|
||||
}
|
@@ -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;
|
||||
}
|
||||
}
|
@@ -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";
|
||||
}
|
||||
|
||||
}
|
@@ -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())));
|
||||
}
|
||||
catch (URISyntaxException ignore) {
|
||||
// This should never happen, but if it does, we'll fall back to using the stream
|
||||
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";
|
||||
}
|
||||
}
|
@@ -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;
|
||||
}
|
||||
}
|
@@ -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;
|
||||
}
|
||||
}
|
149
imageio/imageio-core/src/main/java/com/twelvemonkeys/imageio/util/IIOUtil.java
Executable file
149
imageio/imageio-core/src/main/java/com/twelvemonkeys/imageio/util/IIOUtil.java
Executable file
@@ -0,0 +1,149 @@
|
||||
package com.twelvemonkeys.imageio.util;
|
||||
|
||||
import com.twelvemonkeys.image.ImageUtil;
|
||||
import com.twelvemonkeys.imageio.spi.ProviderInfo;
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link ProviderInfo} instance for the given service provider.
|
||||
*
|
||||
* @param pProviderClass the provider class to get info for.
|
||||
* @return the newly created {@link ProviderInfo}.
|
||||
*/
|
||||
public static ProviderInfo getProviderInfo(final Class<? extends IIOServiceProvider> pProviderClass) {
|
||||
return new ProviderInfo(pProviderClass.getPackage());
|
||||
}
|
||||
|
||||
/**
|
||||
* THIS METHOD WILL ME MOVED/RENAMED, DO NOT USE.
|
||||
*
|
||||
* @param pRegistry the registry to unregister from
|
||||
* @param pProvider the provider to unregister
|
||||
* @param pCategory the category to unregister from
|
||||
*
|
||||
* @deprecated
|
||||
*/
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
@@ -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!");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -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) {
|
||||
}
|
||||
}
|
@@ -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;
|
||||
}
|
||||
}
|
@@ -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;
|
||||
}
|
||||
}
|
@@ -0,0 +1,97 @@
|
||||
package com.twelvemonkeys.imageio.spi;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import java.net.URL;
|
||||
|
||||
/**
|
||||
* ProviderInfoTestCase
|
||||
*
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @author last modified by $Author: haraldk$
|
||||
* @version $Id: ProviderInfoTestCase.java,v 1.0 Oct 31, 2009 3:51:22 PM haraldk Exp$
|
||||
*/
|
||||
public class ProviderInfoTestCase extends TestCase {
|
||||
public void testCreateNorma() {
|
||||
new ProviderInfo(Package.getPackage("java.util"));
|
||||
}
|
||||
|
||||
public void testCreateNullPackage() {
|
||||
try {
|
||||
new ProviderInfo(null);
|
||||
fail("IllegalArgumentException expected for null package");
|
||||
}
|
||||
catch (IllegalArgumentException expected) {
|
||||
assertTrue(expected.getMessage().toLowerCase().contains("package"));
|
||||
}
|
||||
}
|
||||
|
||||
public void testGetVendorUnknownNonJARPackage() {
|
||||
ProviderInfo info = new ProviderInfo(mockNonJARPackage("org.foo"));
|
||||
|
||||
String vendor = info.getVendorName();
|
||||
assertNotNull(vendor);
|
||||
assertEquals("org.foo", vendor);
|
||||
|
||||
String version = info.getVersion();
|
||||
assertNotNull(version);
|
||||
assertEquals("Unspecified", version);
|
||||
}
|
||||
|
||||
public void testGetVendorNonJARTMPackage() {
|
||||
ProviderInfo info = new ProviderInfo(mockNonJARPackage("com.twelvemonkeys"));
|
||||
|
||||
String vendor = info.getVendorName();
|
||||
assertNotNull(vendor);
|
||||
assertEquals("TwelveMonkeys", vendor);
|
||||
|
||||
String version = info.getVersion();
|
||||
assertNotNull(version);
|
||||
assertEquals("DEV", version);
|
||||
}
|
||||
|
||||
public void testGetVendorKnownJARPackage() {
|
||||
ProviderInfo info = new ProviderInfo(mockJARPackage("com.acme", "1.7u4-BETA-b39", "Acme"));
|
||||
|
||||
String vendor = info.getVendorName();
|
||||
assertNotNull(vendor);
|
||||
assertEquals("Acme", vendor);
|
||||
|
||||
String version = info.getVersion();
|
||||
assertNotNull(version);
|
||||
assertEquals("1.7u4-BETA-b39", version);
|
||||
}
|
||||
|
||||
private Package mockNonJARPackage(final String pName) {
|
||||
return new MockClassLoader().mockPackage(
|
||||
pName,
|
||||
null, null, null,
|
||||
null, null, null,
|
||||
null
|
||||
);
|
||||
}
|
||||
|
||||
private Package mockJARPackage(final String pName, final String pImplVersion, final String pImplVendor) {
|
||||
return new MockClassLoader().mockPackage(
|
||||
pName,
|
||||
"The almighty specification", "1.0", "Acme Inc",
|
||||
"The buggy implementation", pImplVersion, pImplVendor,
|
||||
null
|
||||
);
|
||||
}
|
||||
|
||||
private static class MockClassLoader extends ClassLoader {
|
||||
protected MockClassLoader() {
|
||||
super(null);
|
||||
}
|
||||
|
||||
public Package mockPackage(String name, String specTitle, String specVersion, String specVendor, String implTitle, String implVersion, String implVendor, URL sealBase) throws IllegalArgumentException {
|
||||
return definePackage(name, specTitle, specVersion, specVendor, implTitle, implVersion, implVendor, sealBase);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Package getPackage(String name) {
|
||||
return null; // Allow re-createing packages
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,145 @@
|
||||
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() throws IOException {
|
||||
new BufferedImageInputStream(new ByteArrayImageInputStream(new byte[0]));
|
||||
}
|
||||
|
||||
public void testCreateNull() throws IOException {
|
||||
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));
|
||||
}
|
||||
|
||||
public void testBufferPositionCorrect() throws IOException {
|
||||
// Fill bytes
|
||||
byte[] bytes = new byte[1024];
|
||||
mRandom.nextBytes(bytes);
|
||||
|
||||
ByteArrayImageInputStream input = new ByteArrayImageInputStream(bytes);
|
||||
|
||||
input.readByte();
|
||||
input.readByte();
|
||||
input.skipBytes(124);
|
||||
input.readByte();
|
||||
input.readByte();
|
||||
|
||||
// Sanity check
|
||||
assertEquals(128, input.getStreamPosition());
|
||||
|
||||
BufferedImageInputStream stream = new BufferedImageInputStream(input);
|
||||
|
||||
assertEquals(input.getStreamPosition(), stream.getStreamPosition());
|
||||
|
||||
stream.skipBytes(128);
|
||||
|
||||
//assertTrue(256 <= input.getStreamPosition());
|
||||
assertEquals(256, stream.getStreamPosition());
|
||||
|
||||
stream.seek(1020);
|
||||
assertEquals(1020, stream.getStreamPosition());
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
}
|
@@ -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));
|
||||
}
|
||||
}
|
||||
}
|
@@ -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());
|
||||
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@@ -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();
|
||||
}
|
||||
|
||||
}
|
@@ -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));
|
||||
}
|
||||
}
|
BIN
imageio/imageio-core/src/test/resources/Thumbs-camera.db
Executable file
BIN
imageio/imageio-core/src/test/resources/Thumbs-camera.db
Executable file
Binary file not shown.
8
imageio/imageio-core/todo.txt
Executable file
8
imageio/imageio-core/todo.txt
Executable file
@@ -0,0 +1,8 @@
|
||||
- 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?
|
||||
- WBMP?
|
||||
- XBM?
|
||||
DONE:
|
||||
- Split up into separate plugins (modules), to allow easier configuration
|
Reference in New Issue
Block a user