diff options
author | Thomas Fitzsimmons <fitzsim@redhat.com> | 2005-10-02 05:29:54 +0000 |
---|---|---|
committer | Thomas Fitzsimmons <fitzsim@redhat.com> | 2005-10-02 05:29:54 +0000 |
commit | 08510d2cd68b43ccbfa7b04a237cc7b76cf157f1 (patch) | |
tree | 5839b2169dd9bbfa3d30217e13b46b665a30acd7 /javax/imageio | |
parent | 2e01606db66ab085f9c909df5eb51fc8b6b83642 (diff) | |
download | classpath-08510d2cd68b43ccbfa7b04a237cc7b76cf157f1.tar.gz |
2005-10-02 Thomas Fitzsimmons <fitzsim@redhat.com>
* javax/imageio/IIOException.java: Document.
* javax/imageio/IIOImage.java: Document.
* javax/imageio/IIOParam.java: Complete and document.
* javax/imageio/IIOParamController.java: Document.
* javax/imageio/ImageIO.java: Complete and document.
* javax/imageio/ImageReader.java: Complete and document.
* javax/imageio/ImageTranscoder.java: Document.
* javax/imageio/ImageTypeSpecifier.java: Complete and document.
* javax/imageio/ImageWriter.java: Complete and document.
* javax/imageio/package.html: Write.
Diffstat (limited to 'javax/imageio')
-rw-r--r-- | javax/imageio/IIOException.java | 3 | ||||
-rw-r--r-- | javax/imageio/IIOImage.java | 137 | ||||
-rw-r--r-- | javax/imageio/IIOParam.java | 364 | ||||
-rw-r--r-- | javax/imageio/IIOParamController.java | 13 | ||||
-rw-r--r-- | javax/imageio/ImageIO.java | 568 | ||||
-rw-r--r-- | javax/imageio/ImageReadParam.java | 2 | ||||
-rw-r--r-- | javax/imageio/ImageReader.java | 1389 | ||||
-rw-r--r-- | javax/imageio/ImageTranscoder.java | 48 | ||||
-rw-r--r-- | javax/imageio/ImageTypeSpecifier.java | 467 | ||||
-rw-r--r-- | javax/imageio/ImageWriteParam.java | 3 | ||||
-rw-r--r-- | javax/imageio/ImageWriter.java | 892 | ||||
-rw-r--r-- | javax/imageio/package.html | 45 |
12 files changed, 3859 insertions, 72 deletions
diff --git a/javax/imageio/IIOException.java b/javax/imageio/IIOException.java index 8f8dd0344..b281db1b0 100644 --- a/javax/imageio/IIOException.java +++ b/javax/imageio/IIOException.java @@ -39,8 +39,9 @@ package javax.imageio; import java.io.IOException; - /** + * A runtime exception to indicate image reading and writing failures. + * * @author Michael Koch (konqueror@gmx.de) */ public class IIOException extends IOException diff --git a/javax/imageio/IIOImage.java b/javax/imageio/IIOImage.java index 651c9baaa..0d9874762 100644 --- a/javax/imageio/IIOImage.java +++ b/javax/imageio/IIOImage.java @@ -45,13 +45,53 @@ import java.util.List; import javax.imageio.metadata.IIOMetadata; +/** + * IIOImage is a container class for components of an image file that + * stores image data, image metadata and thumbnails. + * + * The image data can be either a RenderedImage or a Raster but not + * both. Image readers that produce IIOImages will always produce + * BufferedImages from the RenderedImage field. Image writers that + * accept IIOImages will always accept RenderedImages and may + * optionally accept Rasters. + * + * @author Thomas Fitzsimmons (fitzsim@redhat.com) + */ public class IIOImage { + /** + * Image data as a RenderedImage. null if this IIOImage uses the + * Raster representation. + */ protected RenderedImage image; + + /** + * Image metadata. + */ protected IIOMetadata metadata; + + /** + * Image data as a Raster. null if this IIOImage uses the + * RenderedImage representation. + */ protected Raster raster; + + /** + * A list of BufferedImage thumbnails of this image. + */ + // for 1.5 these lists are List<? extends BufferedImage> protected List thumbnails; - + + /** + * Construct an IIOImage containing raster image data, thumbnails + * and metadata. + * + * @param raster image data + * @param thumbnails a list of BufferedImage thumbnails or null + * @param metadata image metadata or null + * + * @exception IllegalArgumentException if raster is null + */ public IIOImage (Raster raster, List thumbnails, IIOMetadata metadata) { if (raster == null) @@ -62,6 +102,16 @@ public class IIOImage this.metadata = metadata; } + /** + * Construct an IIOImage containing rendered image data, thumbnails + * and metadata. + * + * @param image rendered image data + * @param thumbnails a list of BufferedImage thumbnails or null + * @param metadata image metadata or null + * + * @exception IllegalArgumentException if image is null + */ public IIOImage (RenderedImage image, List thumbnails, IIOMetadata metadata) { if (image == null) @@ -72,46 +122,111 @@ public class IIOImage this.metadata = metadata; } + /** + * Retrieve the image metadata or null if there is no metadata + * associated with this IIOImage. + * + * @return image metadata or null + */ public IIOMetadata getMetadata() { return metadata; } + /** + * Retrieve the number of thumbnails in this IIOImage. + * + * @return the number of thumbnails + */ public int getNumThumbnails() { - return thumbnails.size(); + return thumbnails == null ? 0 : thumbnails.size(); } + /** + * Retrieve the raster image data stored in this IIOImage or null if + * this image stores data using the RenderedImage representation. + * + * @return the raster image data or null + */ public Raster getRaster() { return raster; } + /** + * Retrieve the rendered image data stored in this IIOImage or null + * if this image stores data using the Raster representation. + * + * @return the rendered image data or null + */ public RenderedImage getRenderedImage() { return image; } + /** + * Retrieve the thumbnail stored at the specified index in the + * thumbnails list. + * + * @param index the index of the thumbnail to retrieve + * + * @return the buffered image thumbnail + * + * @exception IndexOutOfBoundsException if index is out-of-bounds + * @exception ClassCastException if the object returned from the + * thumbnails list is not a BufferedImage + */ public BufferedImage getThumbnail (int index) { + // This throws a ClassCastException if the returned object is not + // a BufferedImage or an IndexOutOfBoundsException if index is + // out-of-bounds. return (BufferedImage) thumbnails.get (index); } + /** + * Retrieve the list of thumbnails or null if there are no + * thumbnails associated with this IIOImage. The returned reference + * can be used to update the thumbnails list. + * + * @return a list of thumbnails or null + */ public List getThumbnails() { return thumbnails; } + /** + * Check whether this IIOImage stores its image data as a Raster or + * as a RenderedImage. + * + * @return true if this IIOImage uses the Raster representation, + * false if it uses the RenderedImage representation. + */ public boolean hasRaster() { return raster != null; } + /** + * Set this IIOImage's metadata. + * + * @param metadata the image metadata + */ public void setMetadata (IIOMetadata metadata) { this.metadata = metadata; } + /** + * Set the raster data for this image. This disposes of any + * existing rendered image data stored in this IIOImage. + * + * @param raster the image raster data + * + * @exception IllegalArgumentException if raster is null + */ public void setRaster (Raster raster) { if (raster == null) @@ -121,6 +236,14 @@ public class IIOImage this.raster = raster; } + /** + * Set the rendered image data for this image. This disposes of any + * existing raster data stored in this IIOImage. + * + * @param image the rendered image data + * + * @exception IllegalArgumentException if image is null + */ public void setRenderedImage (RenderedImage image) { if (image == null) @@ -130,9 +253,15 @@ public class IIOImage this.raster = null; } + /** + * Set the list of thumbnails for this IIOImage to a new list of + * BufferedImages or to null. Any existing thumbnails list is + * disposed. + * + * @param thumbnails a new list of thumbnails or null + */ public void setThumbnails (List thumbnails) { this.thumbnails = thumbnails; } - -} // class IIOParam +} diff --git a/javax/imageio/IIOParam.java b/javax/imageio/IIOParam.java index 01f616605..f6460b4e7 100644 --- a/javax/imageio/IIOParam.java +++ b/javax/imageio/IIOParam.java @@ -42,97 +42,317 @@ import java.awt.Point; import java.awt.Rectangle; /** + * An IIOParam stores parameters used when encoding or decoding image + * streams. ImageReadParam and ImageWriteParam extend this abstract + * base class. + * + * IIOParams allow control over how source pixels converted into + * destination pixels. This conversion can take place between a + * stream and in-memory image data, when an image reader is doing the + * conversion, or a writer can be doing the conversion from an + * in-memory source to a stream destination. + * + * An image reader can be restricted to only read from a given region; + * likewise a writer can be restricted to only write output to a given + * region. + * + * For image readers and writers, IIOParam supports image pixelation + * -- where the input image is approximated by the output image using + * larger-sized pixel blocks. For example: FIXME + * + * IIOParams can control how pixels are combined into larger blocks + * using sub-sampling matrices. For example: FIXME + * + * They can also control which source bands are read and written; this + * example reads the RGBA (red, green, blue, transparency) data from a + * PNG image and outputs just the red and transparency bands: FIXME + * + * @author Thomas Fitzsimmons (fitzsim@redhat.com) * @author Michael Koch (konqueror@gmx.de) */ public abstract class IIOParam { - protected IIOParamController controller; - protected IIOParamController defaultController; + /** + * The controller called by this IIOParam to retrieve parameters. + */ + protected IIOParamController controller = null; + + /** + * The default controller called by this IIOParam to retrieve + * parameters. + */ + protected IIOParamController defaultController = null; + + /** + * The offset in the destination where the upper-left + * decoded/encoded pixel should be located. + */ protected Point destinationOffset = new Point(0, 0); - protected ImageTypeSpecifier destinationType; - protected int[] sourceBands; - protected Rectangle sourceRegion; - protected int sourceXSubsampling; - protected int sourceYSubsampling; - protected int subsamplingXOffset; - protected int subsamplingYOffset; /** - * Initializes an <code>IIOParam</code> object. + * Sets the output colour type when writing or the destination image + * type when reading. + */ + protected ImageTypeSpecifier destinationType = null; + + /** + * An array indicating which source bands will be used or null. + */ + protected int[] sourceBands = null; + + /** + * The source pixel region or null. + */ + protected Rectangle sourceRegion = null; + + /** + * Sample every sourceXSubsampling'th pixel in the source image when + * pixelating the destination image in the horizontal direction. + */ + protected int sourceXSubsampling = 1; + + /** + * Sample every sourceYSubsampling'th pixel in the source image when + * pixelating the destination image in the vertical direction. + */ + protected int sourceYSubsampling = 1; + + /** + * Start sampling at this horizontal offset within the source region + * when pixelating the destination image in the horizontal + * direction. + */ + protected int subsamplingXOffset = 0; + + /** + * Start sampling at this vertical offset within the source region + * when pixelating the destination image in the vertical direction. + */ + protected int subsamplingYOffset = 0; + + /** + * Indicates whether or not the controller has been explicitly set + * to null. + */ + private boolean no_controller = false; + + /** + * Constructs an IIOParam object. */ protected IIOParam() { - // Do nothing here. } + /** + * Activates the parameter controller by calling its activate method + * and passing it this IIOParam. A true return value indicates that + * this IIOParam's values are ready for the next read or write + * operation. A return value of false means that this IIOParam's + * values have not been affected because the controller operations + * were cancelled. + * + * @return true if parameters were successfully set, false if + * parameters were not changed + */ public boolean activateController() { if (controller == null) - return false; - - return controller.activate(this); + { + if (defaultController == null || no_controller) + return false; + else + return defaultController.activate (this); + } + else + return controller.activate(this); } - + + /** + * Retrieve the currently set controller if one has been set, or the + * default controller, or null if the controller has been explicitly + * set to null. + * + * @return the currently used controller or null + */ public IIOParamController getController() { - return controller; + return controller == null ? + (no_controller ? null : defaultController) : controller; } + /** + * Retrieve the default controller regardless of whether or not a + * non-default controller has been set. The default controller may + * be null. + * + * @return the default controller or null + */ public IIOParamController getDefaultController() { return defaultController; } + /** + * Retrieve the offset in the destination where the upper-left + * decoded/encoded pixel should be located. (0, 0) by default. + * + * @return the destination offset + */ public Point getDestinationOffset() { return destinationOffset; } + /** + * Retrieve the currently set image-type specifier or null if none + * has been set. + * + * @return the current image-type specifier or null + */ public ImageTypeSpecifier getDestinationType() { return destinationType; } + /** + * Retrieve the current source band values or null if source band + * values have not been set. + * + * The returned array is a copy of this IIOParam's source band + * array. + * + * @return the current set of source band values or null + */ public int[] getSourceBands() { - return sourceBands; + if (sourceBands == null) + return null; + + int[] sourceBandsCopy = new int[sourceBands.length]; + System.arraycopy (sourceBands, 0, sourceBandsCopy, 0, sourceBands.length); + return sourceBandsCopy; } + /** + * Retrieve the source rectangle from which pixels should be read or + * null if no source region has been set. + * + * @return the current source region or null + */ public Rectangle getSourceRegion() { return sourceRegion; } + /** + * Retrieve the number of pixel columns to advance before taking a + * pixel sample. + * + * @return the horizontal sub-sampling interval + */ public int getSourceXSubsampling() { return sourceXSubsampling; } + /** + * Retrieve the number of pixel rows to advance before taking a + * pixel sample. + * + * @return the vertical sub-sampling interval + */ public int getSourceYSubsampling() { return sourceYSubsampling; } + /** + * Retrieve the number of pixel columns to advance before taking any + * pixel samples. + * + * @return the horizontal sub-sampling offset + */ public int getSubsamplingXOffset() { return subsamplingXOffset; } - + + /** + * Retrieve the number of pixel rows to advance before taking any + * pixel samples. + * + * @return the vertical sub-sampling offset + */ public int getSubsamplingYOffset() { return subsamplingYOffset; } + /** + * Check if a non-null controller is currently available. + * + * @return true if getController returns a non-null value, false if + * getController returns null + */ public boolean hasController() { return getController() != null; } + /** + * Sets the controller for this IIOParam. This is the controller + * that will be activated when activateController is called. The + * argument controller overrides this IIOParam's default controller. + * If the argument is null then no controller will be set, not even + * the default one. To reset the default controller call + * setController(getDefaultController()). + * + * @param controller the controller to set or null + */ public void setController(IIOParamController controller) { - this.controller = controller; + if (controller == defaultController) + { + this.controller = null; + no_controller = false; + } + else + { + no_controller = (controller == null); + this.controller = controller; + } } + /** + * Set the destination image type. + * + * If this value is set on an image reader then its read method will + * return a new BufferedImage of the specified destination type. In + * this case any destination image set using setDestination() is + * ignored. + * + * If this is set on an image writer then the destination type + * affects only the colour model of the destination image. The + * destination type's SampleModel is ignored. The destination + * type's ColorModel will override the source image's colour model. + * + * @param destinationType the sample and colour models of the + * destination image + */ + public void setDestinationType (ImageTypeSpecifier destinationType) + { + this.destinationType = destinationType; + } + + /** + * Specify the destination pixel offset. Image writers are only + * affected by this setting when ImageWriter.replacePixels is called + * in which case the offset is into the region of pixels being + * changed. + * + * @param destinationOffset the offset where pixel writing should + * begin + */ public void setDestinationOffset(Point destinationOffset) { if (destinationOffset == null) @@ -141,11 +361,43 @@ public abstract class IIOParam this.destinationOffset = destinationOffset; } + /** + * Set the indices of the source bands to be used. Duplicate + * indices are not allowed. A value of null means use all source + * bands. The argument array is copied and stored, so subsequent + * updates to it will not be reflected in this IIOParam. + * + * @param sourceBands the array of source bands to use + */ public void setSourceBands(int[] sourceBands) { - this.sourceBands = sourceBands; + int[] sourceBandsCopy = new int[sourceBands.length]; + System.arraycopy (sourceBands, 0, sourceBandsCopy, 0, sourceBands.length); + this.sourceBands = sourceBandsCopy; } + /** + * Set the source region from which to read. The number of pixels + * sampled from the source region depends on the source sub-sampling + * settings. If the combination of this sourceRegion and the + * current sub-sampling settings would result in no pixels being + * sampled then an IllegalStateException will be thrown. + * + * The source region is specified in the source image coordinate + * system which has point (0, 0) at the top-left and increases down + * and to the right. The argument source region is clipped to the + * image boundaries at read-time. + * + * A null argument sets the source region to null meaning that the + * whole image should be read. + * + * @param sourceRegion the rectangular source region + * + * @exception IllegalArgumentException if sourceRegion has width or + * height <= 0 or x or y < 0 + * @exception IllegalStateException if the given sourceRegion and + * the current sampling settings would produce zero samples + */ public void setSourceRegion(Rectangle sourceRegion) { if (sourceRegion != null @@ -154,15 +406,83 @@ public abstract class IIOParam || sourceRegion.width <= 0 || sourceRegion.height <= 0)) throw new IllegalArgumentException("illegal source region"); - - // FIXME: Throw IllegalStateException. + + if (sourceRegion != null) + { + int num_rows = + (sourceRegion.height - subsamplingYOffset + sourceYSubsampling - 1) + / sourceYSubsampling; + + int num_columns = + (sourceRegion.width - subsamplingXOffset + sourceXSubsampling - 1) + / sourceXSubsampling; + + if (num_rows <= 0 || num_columns <= 0) + throw new IllegalStateException("zero pixels in source region"); + } this.sourceRegion = sourceRegion; } + /** + * Set the source sampling intervals and offsets. Every + * sourceXSubsampling'th pixel horizontally and + * sourceYSubsampling'th pixel vertically will be sampled. Sampling + * will being a the subsamplingXOffset'th column and the + * subsamplingYOffset'th row. + * + * Horizontally, the number of sampled pixels will be: + * + * floor((width - subsamplingXOffset + sourceXSubsampling - 1) / sourceXSubsampling) + * + * Vertically: + * + * floor((height - subsamplingYOffset + sourceYSubsampling - 1) / sourceYSubsampling) + * + * If the current source region setting is such that the given + * sub-sampling arguments would produce zero pixel samples, an + * IllegalStateException is thrown. + * + * The offset parameters can be used to make source regions overlap + * when tiling across an image. This can eliminate seams and + * better-tile images whose width or height is not a multiple of the + * sampling interval. + * + * @param sourceXSubsampling the horizontal sampling interval + * @param sourceYSubsampling the vertical sampling interval + * @param subsamplingXOffset the horizontal offset of the initial + * sample + * @param subsamplingYOffset the vertical offset of the initial + * sample + * + * @exception IllegalArgumentException if either subsamplingXOffset + * or subsamplingYOffset is < 0 + * @exception IllegalStateException if the current source region + * combined with the given sub-sampling parameters would produce + * zero pixel samples + */ public void setSourceSubsampling(int sourceXSubsampling, int sourceYSubsampling, int subsamplingXOffset, int subsamplingYOffset) { + if (subsamplingXOffset < 0 || subsamplingYOffset < 0) + throw new IllegalArgumentException("subsampling offset < 0"); + + if (sourceRegion != null) + { + int num_rows = + (sourceRegion.height - subsamplingYOffset + sourceYSubsampling - 1) + / sourceYSubsampling; + + int num_columns = + (sourceRegion.width - subsamplingXOffset + sourceXSubsampling - 1) + / sourceXSubsampling; + + if (num_rows <= 0 || num_columns <= 0) + throw new IllegalStateException("subsampling parameters would" + + " produce zero pixel samples" + + " in source region"); + } + this.sourceXSubsampling = sourceXSubsampling; this.sourceYSubsampling = sourceYSubsampling; this.subsamplingXOffset = subsamplingXOffset; diff --git a/javax/imageio/IIOParamController.java b/javax/imageio/IIOParamController.java index 125520e73..0ee54df40 100644 --- a/javax/imageio/IIOParamController.java +++ b/javax/imageio/IIOParamController.java @@ -39,12 +39,23 @@ exception statement from your version. */ package javax.imageio; /** + * An interface to set image parameters. An IIOParamController may be + * a GUI component, a database reader, command-line parser or any + * other means of getting parameter settings. For exampe, a dialog + * box could implement IIOParamController to allow a user to adjust + * JPEG compression levels. + * + * The activate method should always behave modally; it should only + * return when the action has been either cancelled or completed. + * * @author Michael Koch (konqueror@gmx.de) */ public interface IIOParamController { /** - * Activates the controller. + * Activates the controller. A return value of false should mean + * that no changes were made to param. A return value of true + * should mean that the image is ready to be read or written. * * @param param the <code>IIOParam</code> to be modified * diff --git a/javax/imageio/ImageIO.java b/javax/imageio/ImageIO.java index 95c7c3251..6fc3365c9 100644 --- a/javax/imageio/ImageIO.java +++ b/javax/imageio/ImageIO.java @@ -60,12 +60,18 @@ import javax.imageio.stream.ImageOutputStream; import javax.imageio.stream.MemoryCacheImageInputStream; import javax.imageio.stream.MemoryCacheImageOutputStream; +/** + * An uninstantiable class that provides static methods for locating + * and using image readers and writers. + */ public final class ImageIO { /** - * This class isn't intended to be instantiated. + * Construct an ImageIO. Private since ImageIO is not instantiable. */ - private ImageIO() {} + private ImageIO() + { + } private static final class ReaderFormatFilter implements ServiceRegistry.Filter { @@ -117,13 +123,13 @@ public final class ImageIO } } - private static final class ReaderSuffixFilter implements ServiceRegistry.Filter + private static final class ReaderObjectFilter implements ServiceRegistry.Filter { - private String fileSuffix; + private Object object; - public ReaderSuffixFilter(String fileSuffix) + public ReaderObjectFilter(Object object) { - this.fileSuffix = fileSuffix; + this.object = object; } public boolean filter(Object provider) @@ -131,17 +137,15 @@ public final class ImageIO if (provider instanceof ImageReaderSpi) { ImageReaderSpi spi = (ImageReaderSpi) provider; - String[] suffixes = spi.getFileSuffixes(); - for (int i = suffixes.length - 1; i >= 0; --i) - if (fileSuffix.equals(suffixes[i])) - return true; + if (spi.canDecodeInput(object)) + return true; } return false; } } - + private static final class WriterFormatFilter implements ServiceRegistry.Filter { private String formatName; @@ -217,6 +221,66 @@ public final class ImageIO } } + private static final class WriterObjectFilter implements ServiceRegistry.Filter + { + private ImageTypeSpecifier type; + private String formatName; + + public WriterObjectFilter(ImageTypeSpecifier type, + String formatName) + { + this.type = type; + this.formatName = formatName; + } + + public boolean filter(Object provider) + { + if (provider instanceof ImageWriterSpi) + { + ImageWriterSpi spi = (ImageWriterSpi) provider; + + if (spi.canEncodeImage(type)) + { + String[] formatNames = spi.getFormatNames(); + for (int i = formatNames.length - 1; i >= 0; --i) + if (formatName.equals(formatNames[i])) + return true; + } + } + + return false; + } + } + + private static final class TranscoderFilter implements ServiceRegistry.Filter + { + private ImageReader reader; + private ImageWriter writer; + + public WriterObjectFilter(ImageReader reader, + ImageWriter writer) + { + this.reader = reader; + this.writer = writer; + } + + public boolean filter(Object provider) + { + if (provider instanceof ImageTranscoderSpi) + { + ImageTranscoderSpi spi = (ImageTranscoderSpi) provider; + + if (spi.getReaderServiceProviderName().equals + (reader.getOriginatingProvider().getClass().getName()) + && spi.getWriterServiceProviderName().equals + (writer.getOriginatingProvider().getClass().getName())) + return true; + } + + return false; + } + } + private static final class ImageReaderIterator implements Iterator { Iterator it; @@ -318,11 +382,26 @@ public final class ImageIO } } + /** + * Retrieve the current cache directory. + * + * @return the current cache directory or null if none is set. + */ public static File getCacheDirectory() { return cacheDirectory; } + /** + * Retrieve an iterator over all registered readers for the given + * format. + * + * @param formatName an infomal format name (e.g. "jpeg" or "bmp") + * + * @return an iterator over a collection of image readers + * + * @exception IllegalArgumentException if formatName is null + */ public static Iterator getImageReadersByFormatName(String formatName) { if (formatName == null) @@ -333,6 +412,17 @@ public final class ImageIO formatName); } + /** + * Retrieve an iterator over all registered readers for the given + * MIME type. + * + * @param MIMEType a MIME specification for an image type + * (e.g. "image/jpeg" or "image/x-bmp") + * + * @return an iterator over a collection of image readers + * + * @exception IllegalArgumentException if MIMEType is null + */ public static Iterator getImageReadersByMIMEType(String MIMEType) { if (MIMEType == null) @@ -343,6 +433,16 @@ public final class ImageIO MIMEType); } + /** + * Retrieve an iterator over all registered readers for the given + * file suffix. + * + * @param fileSuffix an image file suffix (e.g. "jpg" or "bmp") + * + * @return an iterator over a collection of image readers + * + * @exception IllegalArgumentException if fileSuffix is null + */ public static Iterator getImageReadersBySuffix(String fileSuffix) { if (fileSuffix == null) @@ -353,6 +453,16 @@ public final class ImageIO fileSuffix); } + /** + * Retrieve an iterator over all registered writers for the given + * format. + * + * @param formatName an infomal format name (e.g. "jpeg" or "bmp") + * + * @return an iterator over a collection of image writers + * + * @exception IllegalArgumentException if formatName is null + */ public static Iterator getImageWritersByFormatName(String formatName) { if (formatName == null) @@ -363,6 +473,17 @@ public final class ImageIO formatName); } + /** + * Retrieve an iterator over all registered writers for the given + * MIME type. + * + * @param MIMEType a MIME specification for an image type + * (e.g. "image/jpeg" or "image/x-bmp") + * + * @return an iterator over a collection of image writers + * + * @exception IllegalArgumentException if MIMEType is null + */ public static Iterator getImageWritersByMIMEType(String MIMEType) { if (MIMEType == null) @@ -373,6 +494,16 @@ public final class ImageIO MIMEType); } + /** + * Retrieve an iterator over all registered writers for the given + * file suffix. + * + * @param fileSuffix an image file suffix (e.g. "jpg" or "bmp") + * + * @return an iterator over a collection of image writers + * + * @exception IllegalArgumentException if fileSuffix is null + */ public static Iterator getImageWritersBySuffix(String fileSuffix) { if (fileSuffix == null) @@ -383,6 +514,12 @@ public final class ImageIO fileSuffix); } + /** + * Retrieve all the informal format names supported by the + * collection of registered image readers. + * + * @return an array of format names + */ public static String[] getReaderFormatNames() { try @@ -408,6 +545,12 @@ public final class ImageIO } } + /** + * Retrieve all the MIME types supported by the collection of + * registered image readers. + * + * @return an array of MIME types + */ public static String[] getReaderMIMETypes() { try @@ -438,11 +581,23 @@ public final class ImageIO return IIORegistry.getDefaultInstance(); } + /** + * Check whether or not an on-disk cache is used for image input and + * output streams. + * + * @return true if an on-disk cache is available, false otherwise + */ public static boolean getUseCache() { return useCache; } + /** + * Retrieve all the informal format names supported by the + * collection of registered image writers. + * + * @return an array of format names + */ public static String[] getWriterFormatNames() { try @@ -468,6 +623,12 @@ public final class ImageIO } } + /** + * Retrieve all the MIME types supported by the collection of + * registered image writers. + * + * @return an array of MIME types + */ public static String[] getWriterMIMETypes() { try @@ -502,8 +663,20 @@ public final class ImageIO IIORegistry.getDefaultInstance().registerApplicationClasspathSpis(); } + /** + * Set the directory to be used for caching image data. A null + * argument means to use the default system temporary directory. + * This cache directory is only used if getUseCache returns true. + * + * @param cacheDirectory the directory where image data should be + * cached + * + * @exception IllegalArgumentException if cacheDirectory is not a + * directory + */ public static void setCacheDirectory(File cacheDirectory) { + // FIXME: add SecurityManager call if (cacheDirectory != null) { if (!cacheDirectory.isDirectory()) @@ -515,37 +688,98 @@ public final class ImageIO ImageIO.cacheDirectory = cacheDirectory; } + /** + * Control whether or not an on-disk cache is used. This cache is + * used to store input or output data from an image data stream when + * data in the stream needs to be re-processed. + * + * If useCache is false the cache will be stored in memory. Doing + * so eliminates file creation and deletion overhead. The default + * is to use an on-disk cache. + * + * @param useCache true to use an on-disk cache, false otherwise + */ public static void setUseCache(boolean useCache) { ImageIO.useCache = useCache; } - /* - * "Standard" simplified entry points. + /** + * Write an image to a file using a registered writer that supports + * the given format, overwriting the file if it already exists. + * + * @param im the image data to write + * @param formatName an informal description of the output format + * @param output the file to which the image will be written + * + * @return false if no registered writer supports the given format, + * true otherwise + * + * @exception IllegalArgumentException if any argument is null + * @exception IOException if a writing error occurs */ - public static boolean write(RenderedImage im, String formatName, File output) throws IOException { + if (im == null || formatName == null || output == null) + throw new IllegalArgumentException ("null argument"); + return write(im, formatName, new FileOutputStream(output)); } + /** + * Write an image to an output stream using a registered writer that + * supports the given format. + * + * @param im the image data to write + * @param formatName an informal description of the output format + * @param output the output stream to which the image will be + * written + * + * @return false if no registered writer supports the given format, + * true otherwise + * + * @exception IllegalArgumentException if any argument is null + * @exception IOException if a writing error occurs + */ public static boolean write(RenderedImage im, String formatName, OutputStream output) throws IOException { + if (im == null || formatName == null || output == null) + throw new IllegalArgumentException ("null argument"); + return write(im, formatName, new MemoryCacheImageOutputStream(output)); } - - + + /** + * Write an image to an ImageOutputStream using a registered writer + * that supports the given format. Image data is written starting + * at the ImageOutputStream's current stream pointer, overwriting + * any existing data. + * + * @param im the image data to write + * @param formatName an informal description of the output format + * @param output the image output stream to which the image will be + * written + * + * @return false if no registered writer supports the given format, + * true otherwise + * + * @exception IllegalArgumentException if any argument is null + * @exception IOException if a writing error occurs + */ public static boolean write(RenderedImage im, String formatName, ImageOutputStream output) throws IOException { + if (im == null || formatName == null || output == null) + throw new IllegalArgumentException ("null argument"); + Iterator writers = getImageWritersByFormatName(formatName); IIOImage img = new IIOImage(im, null, null); while (writers.hasNext()) @@ -567,9 +801,27 @@ public final class ImageIO return false; } + /** + * Create a buffered image from an image input stream. An image + * reader that supports the given image data is automatically + * selected from the collection of registered readers. If no + * registered reader can handle the input format, null is returned. + * + * @param stream the image input stream from which to read image + * data + * + * @return a new buffered image created from the given image data, + * or null + * + * @exception IllegalArgumentException if stream is null + * @exception IOException if a reading error occurs + */ public static BufferedImage read(ImageInputStream stream) throws IOException { + if (stream == null) + throw new IllegalArgumentException("null argument"); + Iterator providers = getRegistry().getServiceProviders(ImageReaderSpi.class, true); while (providers.hasNext()) { @@ -583,23 +835,305 @@ public final class ImageIO } return null; } - + + /** + * Create a buffered image from a URL. An image reader that + * supports the given image data is automatically selected from the + * collection of registered readers. If no registered reader can + * handle the input format, null is returned. + * + * The image data will be cached in the current cache directory if + * caching is enabled. + * + * This method does not locate readers that read data directly from + * a URL. To locate such readers manually, use IIORegistry and + * ImageReaderSpi. + * + * @param input the URL from which to retrieve the image file + * + * @return a new buffered image created from the given image URL, or + * null + * + * @exception IllegalArgumentException if input is null + * @exception IOException if a reading error occurs + */ public static BufferedImage read(URL input) throws IOException { + if (input == null) + throw new IllegalArgumentException("null argument"); + return read(input.openStream()); } + /** + * Create a buffered image from an input stream. An image reader + * that supports the given image data is automatically selected from + * the collection of registered readers. If no registered reader + * can handle the input format, null is returned. + * + * The image data will be cached in the current cache directory if + * caching is enabled. + * + * This method does not locate readers that read data directly from + * an input stream. To locate such readers manually, use + * IIORegistry and ImageReaderSpi. + * + * @param input the input stream from which to read the image data + * + * @return a new buffered image created from the given input stream, + * or null + * + * @exception IllegalArgumentException if input is null + * @exception IOException if a reading error occurs + */ public static BufferedImage read(InputStream input) throws IOException { + if (input == null) + throw new IllegalArgumentException("null argument"); + return read(new MemoryCacheImageInputStream(input)); } + /** + * Create a buffered image from a file. An image reader that + * supports the given image data is automatically selected from the + * collection of registered readers. If no registered reader can + * handle the input format, null is returned. + * + * The image data will be cached in the current cache directory if + * caching is enabled. + * + * This method does not locate readers that read data directly from + * a file. To locate such readers manually, use IIORegistry and + * ImageReaderSpi. + * + * @param input the file from which to read image data + * + * @return a new buffered image created from the given image file, + * or null + * + * @exception IllegalArgumentException if input is null + * @exception IOException if a reading error occurs + */ public static BufferedImage read(File input) throws IOException { + if (input == null) + throw new IllegalArgumentException("null argument"); + return read(new FileInputStream(input)); } + /** + * Create an image input stream from the given object. The + * collection of ImageInputStreamSpis registered with the + * IIORegistry is searched for an image input stream that can take + * input from the given object. null is returned if no such SPI is + * registered. + * + * The image data will be cached in the current cache directory if + * caching is enabled. + * + * @param input an object from which to read image data + * + * @return an ImageInputStream that can read data from input, or + * null + * + * @exception IllegalArgumentException if input is null + * @exception IOException if caching is required but not enabled + */ + public static ImageInputStream createImageInputStream (Object input) + throws IOException + { + if (input == null) + throw new IllegalArgumentException ("null argument"); + + Iterator spis = getRegistry().getServiceProviders + (ImageInputStreamSpi.class, true); + + ImageInputStreamSpi foundSpi = null; + + while(spis.hasNext()) + { + ImageInputStreamSpi spi = (ImageInputStreamSpi) spis.next(); + + if (input instanceof spi.getInputClass()) + { + foundSpi = spi; + break; + } + } + + if (foundSpi == false) + return null; + else + return foundSpi.createInputStreamInstance (input, + getUseCache(), + getCacheDirectory()); + } + + /** + * Create an image output stream from the given object. The + * collection of ImageOutputStreamSpis registered with the + * IIORegistry is searched for an image output stream that can send + * output to the given object. null is returned if no such SPI is + * registered. + * + * The image data will be cached in the current cache directory if + * caching is enabled. + * + * @param input an object to which to write image data + * + * @return an ImageOutputStream that can send data to output, or + * null + * + * @exception IllegalArgumentException if output is null + * @exception IOException if caching is required but not enabled + */ + public static ImageOutputStream createImageOutputStream (Object output) + throws IOException + { + if (output == null) + throw new IllegalArgumentException ("null argument"); + + Iterator spis = getRegistry().getServiceProviders + (ImageOutputStreamSpi.class, true); + + ImageOutputStreamSpi foundSpi = null; + + while(spis.hasNext()) + { + ImageOutputStreamSpi spi = (ImageOutputStreamSpi) spis.next(); + + if (input instanceof spi.getOutputClass()) + { + foundSpi = spi; + break; + } + } + + if (foundSpi == false) + return null; + else + return foundSpi.createOutputStreamInstance (input, + getUseCache(), + getCacheDirectory()); + } + + /** + * Retrieve an image reader corresponding to an image writer, or + * null if writer is not registered or if no corresponding reader is + * registered. + * + * @param writer a registered image writer + * + * @return an image reader corresponding to writer, or null + * + * @exception IllegalArgumentException if writer is null + */ + public static ImageReader getImageReader (ImageWriter writer) + { + if (writer == null) + throw new IllegalArgumentException ("null argument"); + + ImageWriterSpi spi = (ImageWriterSpi) getRegistry() + .getServiceProviderByClass(writer.getClass()); + + String[] readerSpiNames = spi.getImageReaderSpiNames(); + + return readerSpiNames == null ? null : readerSpiNames[0]; + } + + /** + * Retrieve an iterator over the collection of registered image + * readers that support reading data from the given object. + * + * @param input the object for which to retrieve image readers + * + * @return an iterator over a collection of image readers + */ + public static Iterator getImageReaders (Object input) + { + if (input == null) + throw new IllegalArgumentException ("null argument"); + + return getRegistry().getServiceProviders (ImageReaderSpi.class, + new ReaderObjectFilter(object), + true); + } + + /** + * Retrieve an iterator over the collection of registered image + * writers that support writing images of the given type and in the + * given format. + * + * @param type the output image's colour and sample models + * @param formatName the output image format + * + * @return an iterator over a collection of image writers + */ + public static Iterator getImageWriters (ImageTypeSpecifier type, + String formatName) + { + if (type == null || formatName == null) + throw new IllegalArgumentException ("null argument"); + + return getRegistry().getServiceProviders (ImageWriterSpi.class, + new WriterObjectFilter(object), + true); + } + + /** + * Retrieve an image writer corresponding to an image reader, or + * null if reader is not registered or if no corresponding writer is + * registered. This method is useful for preserving metadata + * without needing to understand its format, since the returned + * writer will be able to write, unchanged, the metadata passed to + * it by the reader. + * + * @param reader a registered image reader + * + * @return an image writer corresponding to reader, or null + * + * @exception IllegalArgumentException if reader is null + */ + public static ImageWriter getImageWriter (ImageReader reader) + { + if (reader == null) + throw new IllegalArgumentException ("null argument"); + + ImageReaderSpi spi = (ImageReaderSpi) getRegistry() + .getServiceProviderByClass(reader.getClass()); + + String[] writerSpiNames = spi.getImageWriterSpiNames(); + + return writerSpiNames == null ? null : writerSpiNames[0]; + } + + /** + * Retrieve an iterator over a collection of image transcoders that + * support transcoding from the given image reader's metadata format + * to the given writer's metadata format. + * + * @param reader an image reader + * @param writer an image writer + * + * @return an iterator over a collection of image transcoders + * + * @exception IllegalArgumentException if either reader or writer is + * null + */ + public static Iterator getImageTranscoders (ImageReader reader, + ImageWriter writer) + { + if (reader == null || writer == null) + throw new IllegalArgumentException ("null argument"); + + return getRegistry().getServiceProviders (ImageTranscoderSpi.class, + new ImageTranscoderSpi (reader, + writer), + true); + } } diff --git a/javax/imageio/ImageReadParam.java b/javax/imageio/ImageReadParam.java index 889fe6cc9..b2680f6b1 100644 --- a/javax/imageio/ImageReadParam.java +++ b/javax/imageio/ImageReadParam.java @@ -42,6 +42,8 @@ import java.awt.Dimension; import java.awt.image.BufferedImage; /** + * DOCUMENT ME + * * @author Michel Koch (konqueror@gmx.de) */ public class ImageReadParam extends IIOParam diff --git a/javax/imageio/ImageReader.java b/javax/imageio/ImageReader.java index fdf692bd2..5c45d61e0 100644 --- a/javax/imageio/ImageReader.java +++ b/javax/imageio/ImageReader.java @@ -38,13 +38,17 @@ exception statement from your version. */ package javax.imageio; +import java.awt.Point; +import java.awt.Rectangle; import java.awt.image.BufferedImage; import java.awt.image.Raster; +import java.awt.image.RenderedImage; import java.io.IOException; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Locale; +import java.util.Set; import javax.imageio.event.IIOReadProgressListener; import javax.imageio.event.IIOReadUpdateListener; @@ -53,45 +57,144 @@ import javax.imageio.metadata.IIOMetadata; import javax.imageio.spi.ImageReaderSpi; import javax.imageio.stream.ImageInputStream; +/** + * A class for decoding images within the ImageIO framework. + * + * An ImageReader for a given format is instantiated by an + * ImageReaderSpi for that format. ImageReaderSpis are registered + * with the IIORegistry. + * + * The ImageReader API supports reading animated images that may have + * multiple frames; to support such images many methods take an index + * parameter. + * + * Images may also be read in multiple passes, where each successive + * pass increases the level of detail in the destination image. + */ public abstract class ImageReader { private boolean aborted; - - protected Locale[] availableLocales; - protected boolean ignoreMetadata; - protected Object input; - protected Locale locale; - protected int minIndex; - protected ImageReaderSpi originatingProvider; - protected List progressListeners = new ArrayList(); - protected boolean seekForwardOnly; - protected List updateListeners = new ArrayList(); - protected List warningListeners = new ArrayList(); - protected List warningLocales = new ArrayList(); + /** + * All locales available for localization of warning messages, or + * null if localization is not supported. + */ + protected Locale[] availableLocales = null; + + /** + * true if the input source does not require metadata to be read, + * false otherwise. + */ + protected boolean ignoreMetadata = false; + + /** + * An ImageInputStream from which image data is read. + */ + protected Object input = null; + + /** + * The current locale used to localize warning messages, or null if + * no locale has been set. + */ + protected Locale locale = null; + + /** + * The minimum index at which data can be read. Constantly 0 if + * seekForwardOnly is false, always increasing if seekForwardOnly is + * true. + */ + protected int minIndex = 0; + + /** + * The image reader SPI that instantiated this reader. + */ + protected ImageReaderSpi originatingProvider = null; + + /** + * A list of installed progress listeners. Initially null, meaning + * no installed listeners. + */ + protected List progressListeners = null; + + /** + * true if this reader should only read data further ahead in the + * stream than its current location. false if it can read backwards + * in the stream. If this is true then caching can be avoided. + */ + protected boolean seekForwardOnly = false; + + /** + * A list of installed update listeners. Initially null, meaning no + * installed listeners. + */ + protected List updateListeners = null; + + /** + * A list of installed warning listeners. Initially null, meaning + * no installed listeners. + */ + protected List warningListeners = null; + + /** + * A list of warning locales corresponding with the list of + * installed warning listeners. Initially null, meaning no locales. + */ + protected List warningLocales = null; + + /** + * Construct an image reader. + * + * @param originatingProvider the provider that is constructing this + * image reader, or null + */ protected ImageReader(ImageReaderSpi originatingProvider) { this.originatingProvider = originatingProvider; } + /** + * Request that reading be aborted. The unread contents of the + * image will be undefined. + * + * Readers should clear the abort flag before starting a read + * operation, then poll it periodically during the read operation. + */ public void abort() { aborted = true; } + /** + * Check if the abort flag is set. + * + * @return true if the current read operation should be aborted, + * false otherwise + */ protected boolean abortRequested() { return aborted; } + /** + * Install a read progress listener. This method will return + * immediately if listener is null. + * + * @param listener a read progress listener or null + */ public void addIIOReadProgressListener(IIOReadProgressListener listener) { if (listener == null) return; - + progressListeners.add(listener); } + /** + * Install a read update listener. This method will return + * immediately if listener is null. + * + * @param listener a read update listener + */ public void addIIOReadUpdateListener(IIOReadUpdateListener listener) { if (listener == null) @@ -100,6 +203,15 @@ public abstract class ImageReader updateListeners.add(listener); } + /** + * Install a read warning listener. This method will return + * immediately if listener is null. Warning messages sent to this + * listener will be localized using the current locale. If the + * current locale is null then this reader will select a sensible + * default. + * + * @param listener a read warning listener + */ public void addIIOReadWarningListener(IIOReadWarningListener listener) { if (listener == null) @@ -108,27 +220,67 @@ public abstract class ImageReader warningListeners.add(listener); } + /** + * Check if this reader can handle raster data. Determines whether + * or not readRaster and readTileRaster throw + * UnsupportedOperationException. + * + * @return true if this reader supports raster data, false if not + */ public boolean canReadRaster() { return false; } + /** + * Clear the abort flag. + */ protected void clearAbortRequest() { aborted = false; } - + + /** + * Releases any resources allocated to this object. Subsequent + * calls to methods on this object will produce undefined results. + * + * The default implementation does nothing; subclasses should use + * this method ensure that native resources are released. + */ public void dispose() { // The default implementation does nothing. } - + + /** + * Returns the aspect ratio of this image, the ration of its width + * to its height. The aspect ratio is useful when resizing an image + * while keeping its proportions constant. + * + * @param imageIndex the frame index + * + * @return the image's aspect ratio + * + * @exception IllegalStateException if input is null + * @exception IndexOutOfBoundsException if the frame index is + * out-of-bounds + * @exception IOException if a read error occurs + */ public float getAspectRatio(int imageIndex) throws IOException { + if (input == null) + throw new IllegalStateException("input is null"); + return (float) (getWidth(imageIndex) / getHeight(imageIndex)); } + /** + * Retrieve the available locales. Return null if no locales are + * available or a clone of availableLocales. + * + * @return an array of locales or null + */ public Locale[] getAvailableLocales() { if (availableLocales == null) @@ -137,26 +289,107 @@ public abstract class ImageReader return (Locale[]) availableLocales.clone(); } + /** + * Retrieve the default read parameters for this reader's image + * format. + * + * The default implementation returns new ImageReadParam(). + * + * @return image reading parameters + */ public ImageReadParam getDefaultReadParam() { return new ImageReadParam(); } + /** + * Retrieve the format of the input source. + * + * @return the input source format name + * + * @exception IOException if a read error occurs + */ public String getFormatName() throws IOException { return originatingProvider.getFormatNames()[0]; } + /** + * Get the height of the input image in pixels. If the input image + * is resizable then a default height is returned. + * + * @param imageIndex the frame index + * + * @return the height of the input image + * + * @exception IllegalStateException if input has not been set + * @exception IndexOutOfBoundsException if the frame index is + * out-of-bounds + * @exception IOException if a read error occurs + */ public abstract int getHeight(int imageIndex) throws IOException; + /** + * Get the metadata associated with this image. If the reader is + * set to ignore metadata or does not support reading metadata, or + * if no metadata is available then null is returned. + * + * @param imageIndex the frame index + * + * @return a metadata object, or null + * + * @exception IllegalStateException if input has not been set + * @exception IndexOutOfBoundsException if the frame index is + * out-of-bounds + * @exception IOException if a read error occurs + */ public abstract IIOMetadata getImageMetadata(int imageIndex) throws IOException; + /** + * Get an iterator over the collection of image types into which + * this reader can decode image data. This method is guaranteed to + * return at least one valid image type specifier. + * + * The elements of the iterator should be ordered; the first element + * should be the most appropriate image type for this decoder, + * followed by the second-most appropriate, and so on. + * + * @param imageIndex the frame index + * + * @return an iterator over a collection of image type specifiers + * + * @exception IllegalStateException if input has not been set + * @exception IndexOutOfBoundsException if the frame index is + * out-of-bounds + * @exception IOException if a read error occurs + */ public abstract Iterator getImageTypes(int imageIndex) throws IOException; + /** + * Set the input source to the given object, specify whether this + * reader should be allowed to read input from the data stream more + * than once, and specify whether this reader should ignore metadata + * in the input stream. The input source must be set before many + * methods can be called on this reader. (see all ImageReader + * methods that throw IllegalStateException). If input is null then + * the current input source will be removed. + * + * Unless this reader has direct access with imaging hardware, input + * should be an ImageInputStream. + * + * @param input the input source object + * @param seekForwardOnly true if this reader should be allowed to + * read input from the data stream more than once, false otherwise + * @param ignoreMetadata true if this reader should ignore metadata + * associated with the input source, false otherwise + * + * @exception IllegalArgumentException if input is not a valid input + * source for this reader and is not an ImageInputStream + */ public void setInput(Object input, boolean seekForwardOnly, boolean ignoreMetadata) @@ -183,110 +416,351 @@ public abstract class ImageReader this.minIndex = 0; } + /** + * Set the input source to the given object and specify whether this + * reader should be allowed to read input from the data stream more + * than once. The input source must be set before many methods can + * be called on this reader. (see all ImageReader methods that throw + * IllegalStateException). If input is null then the current input + * source will be removed. + * + * @param input the input source object + * @param seekForwardOnly true if this reader should be allowed to + * read input from the data stream more than once, false otherwise + * + * @exception IllegalArgumentException if input is not a valid input + * source for this reader and is not an ImageInputStream + */ public void setInput(Object in, boolean seekForwardOnly) { setInput(in, seekForwardOnly, false); } - public void setInput(Object in) + /** + * Set the input source to the given object. The input source must + * be set before many methods can be called on this reader. (see all + * ImageReader methods that throw IllegalStateException). If input + * is null then the current input source will be removed. + * + * @param input the input source object + * + * @exception IllegalArgumentException if input is not a valid input + * source for this reader and is not an ImageInputStream + */ + public void setInput(Object input) { - setInput(in, false, false); + setInput(input, false, false); } + /** + * Get this reader's image input source. null is returned if the + * image source has not been set. + * + * @return an image input source object, or null + */ public Object getInput() { return input; } + /** + * Get this reader's locale. null is returned if the locale has not + * been set. + * + * @return this reader's locale, or null + */ public Locale getLocale() { return locale; } + /** + * Return the number of images available from the image input + * source, not including thumbnails. This method will return 1 + * unless this reader is reading an animated image. + * + * Certain multi-image formats do not encode the total number of + * images. When reading images in those formats it may be necessary + * to repeatedly call read, incrementing the image index at each + * call, until an IndexOutOfBoundsException is thrown. + * + * The allowSearch parameter determines whether all images must be + * available at all times. When allowSearch is false, getNumImages + * will return -1 if the total number of images is unknown. + * Otherwise this method returns the number of images. + * + * @param allowSearch true if all images should be available at + * once, false otherwise + * + * @return -1 if allowSearch is false and the total number of images + * is currently unknown, or the number of images + * + * @exception IllegalStateException if input has not been set, or if + * seekForwardOnly is true + * @exception IOException if a read error occurs + */ public abstract int getNumImages(boolean allowSearch) throws IOException; + /** + * Get the number of thumbnails associated with an image. + * + * @param imageIndex the frame index + * + * @return the number of thumbnails associated with this image + */ public int getNumThumbnails(int imageIndex) throws IOException { return 0; } + /** + * Get the ImageReaderSpi that created this reader or null. + * + * @return an ImageReaderSpi, or null + */ public ImageReaderSpi getOriginatingProvider() { return originatingProvider; } + /** + * Get the metadata associated with the image being read. If the + * reader is set to ignore metadata or does not support reading + * metadata, or if no metadata is available then null is returned. + * This method returns metadata associated with the entirety of the + * image data, whereas getImageMetadata(int) returns metadata + * associated with a frame within a multi-image data stream. + * + * @return metadata associated with the image being read, or null + * + * @exception IOException if a read error occurs + */ public abstract IIOMetadata getStreamMetadata() throws IOException; + /** + * Get the height of a thumbnail image. + * + * @param imageIndex the frame index + * @param thumbnailIndex the thumbnail index + * + * @return the height of the thumbnail image + * + * @exception UnsupportedOperationException if this reader does not + * support thumbnails + * @exception IllegalStateException if input is null + * @exception IndexOutOfBoundsException if either index is + * out-of-bounds + * @exception IOException if a read error occurs + */ public int getThumbnailHeight(int imageIndex, int thumbnailIndex) throws IOException { return readThumbnail(imageIndex, thumbnailIndex).getHeight(); } + /** + * Get the width of a thumbnail image. + * + * @param imageIndex the frame index + * @param thumbnailIndex the thumbnail index + * + * @return the width of the thumbnail image + * + * @exception UnsupportedOperationException if this reader does not + * support thumbnails + * @exception IllegalStateException if input is null + * @exception IndexOutOfBoundsException if either index is + * out-of-bounds + * @exception IOException if a read error occurs + */ public int getThumbnailWidth(int imageIndex, int thumbnailIndex) throws IOException { return readThumbnail(imageIndex, thumbnailIndex).getWidth(); } + /** + * Get the X coordinate in pixels of the top-left corner of the + * first tile in this image. + * + * @param imageIndex the frame index + * + * @return the X coordinate of this image's first tile + * + * @exception IllegalStateException if input is needed but the input + * source is not set + * @exception IndexOutOfBoundsException if the frame index is + * out-of-bounds + * @exception IOException if a read error occurs + */ public int getTileGridXOffset(int imageIndex) throws IOException { return 0; } + /** + * Get the Y coordinate in pixels of the top-left corner of the + * first tile in this image. + * + * @param imageIndex the frame index + * + * @return the Y coordinate of this image's first tile + * + * @exception IllegalStateException if input is needed but the input + * source is not set + * @exception IndexOutOfBoundsException if the frame index is + * out-of-bounds + * @exception IOException if a read error occurs + */ public int getTileGridYOffset(int imageIndex) throws IOException { return 0; } + /** + * Get the height of an image tile. + * + * @param imageIndex the frame index + * + * @return the tile height for the given image + * + * @exception IllegalStateException if input is null + * @exception IndexOutOfBoundsException if the frame index is + * out-of-bounds + * @exception IOException if a read error occurs + */ public int getTileHeight(int imageIndex) throws IOException { return getHeight(imageIndex); } + /** + * Get the width of an image tile. + * + * @param imageIndex the frame index + * + * @return the tile width for the given image + * + * @exception IllegalStateException if input is null + * @exception IndexOutOfBoundsException if the frame index is + * out-of-bounds + * @exception IOException if a read error occurs + */ public int getTileWidth(int imageIndex) throws IOException { return getWidth(imageIndex); } + /** + * Get the width of the input image in pixels. If the input image + * is resizable then a default width is returned. + * + * @param imageIndex the image's index + * + * @return the width of the input image + * + * @exception IllegalStateException if input has not been set + * @exception IndexOutOfBoundsException if the frame index is + * out-of-bounds + * @exception IOException if a read error occurs + */ public abstract int getWidth(int imageIndex) throws IOException; + /** + * Check whether or not the given image has thumbnails associated + * with it. + * + * @return true if the given image has thumbnails, false otherwise + * + * @exception IllegalStateException if input is null + * @exception IndexOutOfBoundsException if the frame index is + * out-of-bounds + * @exception IOException if a read error occurs + */ public boolean hasThumbnails(int imageIndex) throws IOException { return getNumThumbnails(imageIndex) > 0; } + /** + * Check if this image reader ignores metadata. This method simply + * returns the value of ignoreMetadata. + * + * @return true if metadata is being ignored, false otherwise + */ public boolean isIgnoringMetadata() { return ignoreMetadata; } + /** + * Check if the given image is sub-divided into equal-sized + * non-overlapping pixel rectangles. + * + * A reader may expose tiling in the underlying format, hide it, or + * simulate tiling even if the underlying format is not tiled. + * + * @return true if the given image is tiled, false otherwise + * + * @exception IllegalStateException if input is null + * @exception IndexOutOfBoundsException if the frame index is + * out-of-bounds + * @exception IOException if a read error occurs + */ public boolean isImageTiled(int imageIndex) throws IOException { return false; } + /** + * Check if all pixels in this image are readily accessible. This + * method should return false for compressed formats. The return + * value is a hint as to the efficiency of certain image reader + * operations. + * + * @param imageIndex the frame index + * + * @return true if random pixel access is fast, false otherwise + * + * @exception IllegalStateException if input is null and it is + * needed to determine the return value + * @exception IndexOutOfBoundsException if the frame index is + * out-of-bounds but the frame data must be accessed to determine + * the return value + * @exception IOException if a read error occurs + */ public boolean isRandomAccessEasy(int imageIndex) throws IOException { return false; } + /** + * Check if this image reader may only seek forward within the input + * stream. + * + * @return true if this reader may only seek forward, false + * otherwise + */ public boolean isSeekForwardOnly() { return seekForwardOnly; } + /** + * Notifies all installed read progress listeners that image loading + * has completed by calling their imageComplete methods. + */ protected void processImageComplete() { Iterator it = progressListeners.iterator(); @@ -298,6 +772,14 @@ public abstract class ImageReader } } + /** + * Notifies all installed read progress listeners that a certain + * percentage of the image has been loaded, by calling their + * imageProgress methods. + * + * @param percentageDone the percentage of image data that has been + * loaded + */ protected void processImageProgress(float percentageDone) { Iterator it = progressListeners.iterator(); @@ -309,6 +791,14 @@ public abstract class ImageReader } } + /** + * Notifies all installed read progress listeners, by calling their + * imageStarted methods, that image loading has started on the given + * image. + * + * @param imageIndex the frame index of the image that has started + * loading + */ protected void processImageStarted(int imageIndex) { Iterator it = progressListeners.iterator(); @@ -320,6 +810,21 @@ public abstract class ImageReader } } + /** + * Notifies all installed read update listeners, by calling their + * imageUpdate methods, that the set of samples has changed. + * + * @param image the buffered image that is being updated + * @param minX the X coordinate of the top-left pixel in this pass + * @param minY the Y coordinate of the top-left pixel in this pass + * @param width the total width of the rectangle covered by this + * pass, including skipped pixels + * @param height the total height of the rectangle covered by this + * pass, including skipped pixels + * @param periodX the horizontal sample interval + * @param periodY the vertical sample interval + * @param bands the affected bands in the destination + */ protected void processImageUpdate(BufferedImage image, int minX, int minY, int width, int height, int periodX, int periodY, int[] bands) @@ -334,6 +839,13 @@ public abstract class ImageReader } } + /** + * Notifies all installed update progress listeners, by calling + * their passComplete methods, that a progressive pass has + * completed. + * + * @param image the image that has being updated + */ protected void processPassComplete(BufferedImage image) { Iterator it = updateListeners.iterator(); @@ -345,6 +857,24 @@ public abstract class ImageReader } } + /** + * Notifies all installed read update listeners, by calling their + * passStarted methods, that a new pass has begun. + * + * @param image the buffered image that is being updated + * @param pass the current pass number + * @param minPass the pass at which decoding will begin + * @param maxPass the pass at which decoding will end + * @param minX the X coordinate of the top-left pixel in this pass + * @param minY the Y coordinate of the top-left pixel in this pass + * @param width the total width of the rectangle covered by this + * pass, including skipped pixels + * @param height the total height of the rectangle covered by this + * pass, including skipped pixels + * @param periodX the horizontal sample interval + * @param periodY the vertical sample interval + * @param bands the affected bands in the destination + */ protected void processPassStarted(BufferedImage image, int pass, int minPass, int maxPass, int minX, int minY, int periodX, int periodY, int[] bands) @@ -359,6 +889,10 @@ public abstract class ImageReader } } + /** + * Notifies all installed read progress listeners that image loading + * has been aborted by calling their readAborted methods. + */ protected void processReadAborted() { Iterator it = progressListeners.iterator(); @@ -370,6 +904,11 @@ public abstract class ImageReader } } + /** + * Notifies all installed read progress listeners, by calling their + * sequenceComplete methods, that a sequence of images has completed + * loading. + */ protected void processSequenceComplete() { Iterator it = progressListeners.iterator(); @@ -381,6 +920,13 @@ public abstract class ImageReader } } + /** + * Notifies all installed read progress listeners, by calling their + * sequenceStarted methods, a sequence of images has started + * loading. + * + * @param minIndex the index of the first image in the sequence + */ protected void processSequenceStarted(int minIndex) { Iterator it = progressListeners.iterator(); @@ -392,6 +938,11 @@ public abstract class ImageReader } } + /** + * Notifies all installed read progress listeners, by calling their + * thumbnailComplete methods, that a thumbnail has completed + * loading. + */ protected void processThumbnailComplete() { Iterator it = progressListeners.iterator(); @@ -403,6 +954,13 @@ public abstract class ImageReader } } + /** + * Notifies all installed update progress listeners, by calling + * their thumbnailPassComplete methods, that a progressive pass has + * completed on a thumbnail. + * + * @param thumbnail the thumbnail that has being updated + */ protected void processThumbnailPassComplete(BufferedImage thumbnail) { Iterator it = updateListeners.iterator(); @@ -414,6 +972,24 @@ public abstract class ImageReader } } + /** + * Notifies all installed read update listeners, by calling their + * thumbnailPassStarted methods, that a new pass has begun. + * + * @param thumbnail the thumbnail that is being updated + * @param pass the current pass number + * @param minPass the pass at which decoding will begin + * @param maxPass the pass at which decoding will end + * @param minX the X coordinate of the top-left pixel in this pass + * @param minY the Y coordinate of the top-left pixel in this pass + * @param width the total width of the rectangle covered by this + * pass, including skipped pixels + * @param height the total height of the rectangle covered by this + * pass, including skipped pixels + * @param periodX the horizontal sample interval + * @param periodY the vertical sample interval + * @param bands the affected bands in the destination + */ protected void processThumbnailPassStarted(BufferedImage thumbnail, int pass, int minPass, int maxPass, int minX, int minY, int periodX, int periodY, @@ -429,6 +1005,14 @@ public abstract class ImageReader } } + /** + * Notifies all installed read progress listeners that a certain + * percentage of a thumbnail has been loaded, by calling their + * thumbnailProgress methods. + * + * @param percentageDone the percentage of thumbnail data that has + * been loaded + */ protected void processThumbnailProgress(float percentageDone) { Iterator it = progressListeners.iterator(); @@ -440,6 +1024,16 @@ public abstract class ImageReader } } + /** + * Notifies all installed read progress listeners, by calling their + * imageStarted methods, that thumbnail loading has started on the + * given thumbnail of the given image. + * + * @param imageIndex the frame index of the image one of who's + * thumbnails has started loading + * @param thumbnailIndex the index of the thumbnail that has started + * loading + */ protected void processThumbnailStarted(int imageIndex, int thumbnailIndex) { Iterator it = progressListeners.iterator(); @@ -451,6 +1045,21 @@ public abstract class ImageReader } } + /** + * Notifies all installed read update listeners, by calling their + * thumbnailUpdate methods, that the set of samples has changed. + * + * @param image the buffered image that is being updated + * @param minX the X coordinate of the top-left pixel in this pass + * @param minY the Y coordinate of the top-left pixel in this pass + * @param width the total width of the rectangle covered by this + * pass, including skipped pixels + * @param height the total height of the rectangle covered by this + * pass, including skipped pixels + * @param periodX the horizontal sample interval + * @param periodY the vertical sample interval + * @param bands the affected bands in the destination + */ protected void processThumbnailUpdate(BufferedImage image, int minX, int minY, int width, int height, int periodX, int periodY, int[] bands) @@ -465,8 +1074,19 @@ public abstract class ImageReader } } + /** + * Notifies all installed warning listeners, by calling their + * warningOccurred methods, that a warning message has been raised. + * + * @param warning the warning message + * + * @throw IllegalArgumentException if warning is null + */ protected void processWarningOccurred(String warning) { + if (warning == null) + throw new IllegalArgumentException ("null argument"); + Iterator it = warningListeners.iterator(); while (it.hasNext()) @@ -476,41 +1096,111 @@ public abstract class ImageReader } } + /** + * Read the given frame into a buffered image using the given read + * parameters. Listeners will be notified of image loading progress + * and warnings. + * + * @param imageIndex the index of the frame to read + * @param param the image read parameters to use when reading + * + * @return a buffered image + * + * @exception IllegalStateException if input is null + * @exception IndexOutOfBoundsException if the frame index is + * out-of-bounds + * @exception IOException if a read error occurs + */ public abstract BufferedImage read(int imageIndex, ImageReadParam param) throws IOException; + /** + * Check if this reader supports reading thumbnails. + * + * @return true if this reader supports reading thumbnails, false + * otherwise + */ public boolean readerSupportsThumbnails() { return false; } + /** + * Read raw raster data. The image type specifier in param is + * ignored but all other parameters are used. Offset parameters are + * translated into the raster's coordinate space. This method may + * be implemented by image readers that want to provide direct + * access to raw image data. + * + * @param imageIndex the frame index + * @param param the image read parameters + * + * @return a raster containing the read image data + * + * @exception UnsupportedOperationException if this reader doesn't + * support rasters + * @exception IllegalStateException if input is null + * @exception IndexOutOfBoundsException if the frame index is + * out-of-bounds + * @exception IOException if a read error occurs + */ public Raster readRaster(int imageIndex, ImageReadParam param) throws IOException { throw new UnsupportedOperationException(); } + /** + * Read a thumbnail. + * + * @param imageIndex the frame index + * @param thumbnailIndex the thumbnail index + * + * @return a buffered image of the thumbnail + * + * @exception UnsupportedOperationException if this reader doesn't + * support thumbnails + * @exception IllegalStateException if input is null + * @exception IndexOutOfBoundsException if either the frame index or + * the thumbnail index is out-of-bounds + * @exception IOException if a read error occurs + * + */ public BufferedImage readThumbnail(int imageIndex, int thumbnailIndex) throws IOException { throw new UnsupportedOperationException(); } + /** + * Uninstall all read progress listeners. + */ public void removeAllIIOReadProgressListeners() { - progressListeners.clear(); + progressListeners = null; } + /** + * Uninstall all read update listeners. + */ public void removeAllIIOReadUpdateListeners() { - updateListeners.clear(); + updateListeners = null; } + /** + * Uninstall all read warning listeners. + */ public void removeAllIIOReadWarningListeners() { - warningListeners.clear(); + warningListeners = null; } - + + /** + * Uninstall the given read progress listener. + * + * @param listener the listener to remove + */ public void removeIIOReadProgressListener(IIOReadProgressListener listener) { if (listener == null) @@ -519,6 +1209,11 @@ public abstract class ImageReader progressListeners.remove(listener); } + /** + * Uninstall the given read update listener. + * + * @param listener the listener to remove + */ public void removeIIOReadUpdateListener(IIOReadUpdateListener listener) { if (listener == null) @@ -527,6 +1222,11 @@ public abstract class ImageReader updateListeners.remove(listener); } + /** + * Uninstall the given read warning listener. + * + * @param listener the listener to remove + */ public void removeIIOReadWarningListener(IIOReadWarningListener listener) { if (listener == null) @@ -534,7 +1234,12 @@ public abstract class ImageReader warningListeners.remove(listener); } - + + /** + * Set the current locale or use the default locale. + * + * @param locale the locale to set, or null + */ public void setLocale(Locale locale) { if (locale != null) @@ -553,4 +1258,644 @@ public abstract class ImageReader this.locale = locale; } + + /** + * Check that the given read parameters have valid source and + * destination band settings. If the param.getSourceBands() returns + * null, the array is assumed to include all band indices, 0 to + * numSrcBands - 1; likewise if param.getDestinationBands() returns + * null, it is assumed to be an array containing indices 0 to + * numDstBands - 1. A failure will cause this method to throw + * IllegalArgumentException. + * + * @param param the image parameters to check + * @param numSrcBands the number of input source bands + * @param numDstBands the number of ouput destination bands + * + * @exception IllegalArgumentException if either the given source or + * destination band indices are invalid + */ + protected static void checkReadParamBandSettings(ImageReadParam param, + int numSrcBands, + int numDstBands) + { + int[] srcBands = param.getSourceBands(); + int[] dstBands = param.getDestinationBands(); + boolean lengthsDiffer = false; + boolean srcOOB = false; + boolean dstOOB = false; + + if (srcBands == null) + { + if (dstBands == null) + { + if (numSrcBands != numDstBands) + lengthsDiffer = true; + } + else + { + if (numSrcBands != dstBands.length) + lengthsDiffer = true; + + for (int i = 0; i < dstBands.length; i++) + if (dstBands[i] > numSrcBands - 1) + { + dstOOB = true; + break; + } + } + } + else + { + if (dstBands == null) + { + if (srcBands.length != numDstBands) + lengthsDiffer = true; + + for (int i = 0; i < srcBands.length; i++) + if (srcBands[i] > numDstBands - 1) + { + srcOOB = true; + break; + } + } + else + { + if (srcBands.length != dstBands.length) + lengthsDiffer = true; + + for (int i = 0; i < srcBands.length; i++) + if (srcBands[i] > numDstBands - 1) + { + srcOOB = true; + break; + } + + for (int i = 0; i < dstBands.length; i++) + if (dstBands[i] > numSrcBands - 1) + { + dstOOB = true; + break; + } + } + } + + if (lengthsDiffer) + throw new IllegalArgumentException ("array lengths differ"); + + if (srcOOB) + throw new IllegalArgumentException ("source band index" + + " out-of-bounds"); + + if (dstOOB) + throw new IllegalArgumentException ("destination band index" + + " out-of-bounds"); + } + + /** + * Calcluate the source and destination regions that will be read + * from and written to, given image parameters and/or a destination + * buffered image. The source region will be clipped if any of its + * bounds are outside the destination region. Clipping will account + * for subsampling and destination offsets. Likewise, the + * destination region is clipped to the given destination image, if + * it is not null, using the given image parameters, if they are not + * null. IllegalArgumentException is thrown if either region will + * contain 0 pixels after clipping. + * + * @param image read parameters, or null + * @param srcWidth the width of the source image + * @param srcHeight the height of the source image + * @param image the destination image, or null + * @param srcRegion a rectangle whose values will be set to the + * clipped source region + * @param destRegion a rectangle whose values will be set to the + * clipped destination region + * + * @exception IllegalArgumentException if either srcRegion or + * destRegion is null + * @exception IllegalArgumentException if either of the calculated + * regions is empty + */ + protected static void computeRegions (ImageReadParam param, + int srcWidth, + int srcHeight, + BufferedImage image, + Rectangle srcRegion, + Rectangle destRegion) + { + if (srcRegion == null || destRegion == null) + throw new IllegalArgumentException ("null region"); + + if (srcWidth == 0 || srcHeight == 0) + throw new IllegalArgumentException ("zero-sized region"); + + srcRegion = getSourceRegion(param, srcWidth, srcHeight); + if (image != null) + destRegion = new Rectangle (0, 0, image.getWidth(), image.getHeight()); + else + destRegion = new Rectangle (0, 0, srcWidth, srcHeight); + + if (param != null) + { + Point offset = param.getDestinationOffset(); + + if (offset.x < 0) + { + srcRegion.x -= offset.x; + srcRegion.width += offset.x; + } + if (offset.y < 0) + { + srcRegion.y -= offset.y; + srcRegion.height += offset.y; + } + + srcRegion.width = srcRegion.width > destRegion.width + ? destRegion.width : srcRegion.width; + srcRegion.height = srcRegion.height > destRegion.height + ? destRegion.height : srcRegion.height; + + if (offset.x >= 0) + { + destRegion.x += offset.x; + destRegion.width -= offset.x; + } + if (offset.y >= 0) + { + destRegion.y += offset.y; + destRegion.height -= offset.y; + } + } + + if (srcRegion.isEmpty() || destRegion.isEmpty()) + throw new IllegalArgumentException ("zero-sized region"); + } + + /** + * Return a suitable destination buffered image. If + * param.getDestination() is non-null, then it is returned, + * otherwise a buffered image is created using + * param.getDestinationType() if it is non-null and also in the + * given imageTypes collection, or the first element of imageTypes + * otherwise. + * + * @param param image read parameters from which a destination image + * or image type is retrieved, or null + * @param imageTypes a collection of legal image types + * @param width the width of the source image + * @param height the height of the source image + * + * @return a suitable destination buffered image + * + * @exception IIOException if param.getDestinationType() does not + * return an image type in imageTypes + * @exception IllegalArgumentException if imageTypes is null or + * empty, or if a non-ImageTypeSpecifier object is retrieved from + * imageTypes + * @exception IllegalArgumentException if the resulting destination + * region is empty + * @exception IllegalArgumentException if the product of width and + * height is greater than Integer.MAX_VALUE + */ + protected static BufferedImage getDestination (ImageReadParam param, + Iterator imageTypes, + int width, + int height) + throws IOException + { + if (imageTypes == null || !imageTypes.hasNext()) + throw new IllegalArgumentException ("imageTypes null or empty"); + + if (width < 0 || height < 0) + throw new IllegalArgumentException ("negative dimension"); + + // test for overflow + if (width * height < Math.min (width, height)) + throw new IllegalArgumentException ("width * height > Integer.MAX_VALUE"); + + BufferedImage dest = null; + ImageTypeSpecifier destType = null; + + if (param != null) + { + dest = param.getDestination (); + if (dest == null) + { + ImageTypeSpecifier type = param.getDestinationType(); + if (type != null) + { + Iterator it = imageTypes; + + while (it.hasNext()) + { + Object o = it.next (); + if (! (o instanceof ImageTypeSpecifier)) + throw new IllegalArgumentException ("non-ImageTypeSpecifier object"); + + ImageTypeSpecifier t = (ImageTypeSpecifier) o; + if (t.equals (type)) + { + dest = t.createBufferedImage (width, height); + break; + } + if (destType == null) + throw new IIOException ("invalid destination type"); + + } + } + } + } + if (dest == null) + { + Rectangle srcRegion = new Rectangle (); + Rectangle destRegion = new Rectangle (); + + computeRegions (param, width, height, null, srcRegion, destRegion); + + if (destRegion.isEmpty()) + throw new IllegalArgumentException ("destination region empty"); + + if (destType == null) + { + Object o = imageTypes.next(); + if (! (o instanceof ImageTypeSpecifier)) + throw new IllegalArgumentException ("non-ImageTypeSpecifier" + + " object"); + + dest = ((ImageTypeSpecifier) o).createBufferedImage + (destRegion.width, destRegion.height); + } + else + dest = destType.createBufferedImage + (destRegion.width, destRegion.height); + } + return dest; + } + + /** + * Get the metadata associated with this image. If the reader is + * set to ignore metadata or does not support reading metadata, or + * if no metadata is available then null is returned. + * + * This more specific version of getImageMetadata(int) can be used + * to restrict metadata retrieval to specific formats and node + * names, which can limit the amount of data that needs to be + * processed. + * + * @param imageIndex the frame index + * @param formatName the format of metadata requested + * @param nodeNames a set of Strings specifiying node names to be + * retrieved + * + * @return a metadata object, or null + * + * @exception IllegalStateException if input has not been set + * @exception IndexOutOfBoundsException if the frame index is + * out-of-bounds + * @exception IllegalArgumentException if formatName is null + * @exception IllegalArgumentException if nodeNames is null + * @exception IOException if a read error occurs + */ + public IIOMetadata getImageMetadata (int imageIndex, + String formatName, + Set nodeNames) + throws IOException + { + if (formatName == null || nodeNames == null) + throw new IllegalArgumentException ("null argument"); + + return getImageMetadata (imageIndex); + } + + /** + * Get the index at which the next image will be read. If + * seekForwardOnly is true then the returned value will increase + * monotonically each time an image frame is read. If + * seekForwardOnly is false then the returned value will always be + * 0. + * + * @return the current frame index + */ + public int getMinIndex() + { + return minIndex; + } + + /** + * Get the image type specifier that most closely represents the + * internal data representation used by this reader. This value + * should be included in the return value of getImageTypes. + * + * @param imageIndex the frame index + * + * @return an image type specifier + * + * @exception IllegalStateException if input has not been set + * @exception IndexOutOfBoundsException if the frame index is + * out-of-bounds + * @exception IOException if a read error occurs + */ + public ImageTypeSpecifier getRawImageType (int imageIndex) + throws IOException + { + return (ImageTypeSpecifier) getImageTypes(imageIndex).next(); + } + + /** + * Calculate a source region based on the given source image + * dimensions and parameters. Subsampling offsets and a source + * region are taken from the given image read parameters and used to + * clip the given image dimensions, returning a new rectangular + * region as a result. + * + * @param param image parameters, or null + * @param srcWidth the width of the source image + * @param srcHeight the height of the source image + * + * @return a clipped rectangle + */ + protected static Rectangle getSourceRegion (ImageReadParam param, + int srcWidth, + int srcHeight) + { + Rectangle clippedRegion = new Rectangle (0, 0, srcWidth, srcHeight); + + if (param != null) + { + Rectangle srcRegion = param.getSourceRegion(); + + if (srcRegion != null) + { + clippedRegion.x = srcRegion.x > clippedRegion.x + ? srcRegion.x : clippedRegion.x; + clippedRegion.y = srcRegion.y > clippedRegion.y + ? srcRegion.y : clippedRegion.y; + clippedRegion.width = srcRegion.width > clippedRegion.width + ? srcRegion.width : clippedRegion.width; + clippedRegion.height = srcRegion.height > clippedRegion.height + ? srcRegion.height : clippedRegion.height; + } + + int xOffset = param.getSubsamplingXOffset(); + + clippedRegion.x += xOffset; + clippedRegion.width -= xOffset; + + int yOffset = param.getSubsamplingYOffset(); + + clippedRegion.y += yOffset; + clippedRegion.height -= yOffset; + } + return clippedRegion; + } + + /** + * Get the metadata associated with the image being read. If the + * reader is set to ignore metadata or does not support reading + * metadata, or if no metadata is available then null is returned. + * This method returns metadata associated with the entirety of the + * image data, whereas getStreamMetadata() returns metadata + * associated with a frame within a multi-image data stream. + * + * This more specific version of getStreamMetadata() can be used to + * restrict metadata retrieval to specific formats and node names, + * which can limit the amount of data that needs to be processed. + * + * @param formatName the format of metadata requested + * @param nodeNames a set of Strings specifiying node names to be + * retrieved + * + * @return metadata associated with the image being read, or null + * + * @exception IllegalArgumentException if formatName is null + * @exception IllegalArgumentException if nodeNames is null + * @exception IOException if a read error occurs + */ + public IIOMetadata getStreamMetadata (String formatName, + Set nodeNames) + throws IOException + { + if (formatName == null || nodeNames == null) + throw new IllegalArgumentException ("null argument"); + + return getStreamMetadata(); + } + + /** + * Read the given frame all at once, using default image read + * parameters, and return a buffered image. + * + * The returned image will be formatted according to the + * currently-preferred image type specifier. + * + * Installed read progress listeners, update progress listeners and + * warning listeners will be notified of read progress, changes in + * sample sets and warnings respectively. + * + * @param the index of the image frame to read + * + * @return a buffered image + * + * @exception IllegalStateException if input has not been set + * @exception IndexOutOfBoundsException if the frame index is + * out-of-bounds + * @exception IOException if a read error occurs + */ + public BufferedImage read (int imageIndex) + throws IOException + { + return read (imageIndex, null); + } + + /** + * Read the given frame all at once, using the given image read + * parameters, and return an IIOImage. The IIOImage will contain a + * buffered image as returned by getDestination. + * + * Installed read progress listeners, update progress listeners and + * warning listeners will be notified of read progress, changes in + * sample sets and warnings respectively. + * + * The source and destination band settings are checked with a call + * to checkReadParamBandSettings. + * + * @param the index of the image frame to read + * @param the image read parameters + * + * @return an IIOImage + * + * @exception IllegalStateException if input has not been set + * @exception IndexOutOfBoundsException if the frame index is + * out-of-bounds + * @exception IllegalArgumentException if param.getSourceBands() and + * param.getDestinationBands() are incompatible + * @exception IllegalArgumentException if either the source or + * destination image regions are empty + * @exception IOException if a read error occurs + */ + public IIOImage readAll (int imageIndex, + ImageReadParam param) + throws IOException + { + checkReadParamBandSettings (param, + param.getSourceBands().length, + param.getDestinationBands().length); + + List l = new ArrayList (); + + for (int i = 0; i < getNumThumbnails (imageIndex); i++) + l.add (readThumbnail(imageIndex, i)); + + return new IIOImage (getDestination(param, getImageTypes(imageIndex), + getWidth(imageIndex), + getHeight(imageIndex)), + l, + getImageMetadata (imageIndex)); + } + + /** + * Read all image frames all at once, using the given image read + * parameters iterator, and return an iterator over a collection of + * IIOImages. Each IIOImage in the collection will contain a + * buffered image as returned by getDestination. + * + * Installed read progress listeners, update progress listeners and + * warning listeners will be notified of read progress, changes in + * sample sets and warnings respectively. + * + * Each set of source and destination band settings are checked with + * a call to checkReadParamBandSettings. + * + * @param an iterator over the image read parameters + * + * @return an IIOImage + * + * @exception IllegalStateException if input has not been set + * @exception IllegalArgumentException if a non-ImageReadParam is + * found in params + * @exception IllegalArgumentException if param.getSourceBands() and + * param.getDestinationBands() are incompatible + * @exception IllegalArgumentException if either the source or + * destination image regions are empty + * @exception IOException if a read error occurs + */ + public Iterator readAll (Iterator params) + throws IOException + { + List l = new ArrayList (); + int index = 0; + + while (params.hasNext()) + { + if (params != null && ! (params instanceof ImageReadParam)) + throw new IllegalArgumentException ("non-ImageReadParam found"); + + l.add (readAll(index++, (ImageReadParam) params.next ())); + } + + return l.iterator(); + } + + /** + * Read a rendered image. This is a more general counterpart to + * read (int, ImageReadParam). All image data may not be read + * before this method returns and so listeners will not necessarily + * be notified. + * + * @param the index of the image frame to read + * @param the image read parameters + * + * @return a rendered image + * + * @exception IllegalStateException if input is null + * @exception IndexOutOfBoundsException if the frame index is + * out-of-bounds + * @exception IllegalArgumentException if param.getSourceBands() and + * param.getDestinationBands() are incompatible + * @exception IllegalArgumentException if either the source or + * destination image regions are empty + * @exception IOException if a read error occurs + */ + public RenderedImage readAsRenderedImage (int imageIndex, + ImageReadParam param) + throws IOException + { + return read (imageIndex, param); + } + + /** + * Read the given tile into a buffered image. If the tile + * coordinates are out-of-bounds an exception is thrown. If the + * image is not tiled then the coordinates 0, 0 are expected and the + * entire image will be read. + * + * @param imageIndex the frame index + * @param tileX the horizontal tile coordinate + * @param tileY the vertical tile coordinate + * + * @return the contents of the tile as a buffered image + * + * @exception IllegalStateException if input is null + * @exception IndexOutOfBoundsException if the frame index is + * out-of-bounds + * @exception IllegalArgumentException if the tile coordinates are + * out-of-bounds + * @exception IOException if a read error occurs + */ + public BufferedImage readTile (int imageIndex, int tileX, int tileY) + throws IOException + { + if (tileX != 0 || tileY != 0) + throw new IllegalArgumentException ("tileX not 0 or tileY not 0"); + + return read (imageIndex); + } + + /** + * Read the given tile into a raster containing the raw image data. + * If the tile coordinates are out-of-bounds an exception is thrown. + * If the image is not tiled then the coordinates 0, 0 are expected + * and the entire image will be read. + * + * @param imageIndex the frame index + * @param tileX the horizontal tile coordinate + * @param tileY the vertical tile coordinate + * + * @return the contents of the tile as a raster + * + * @exception UnsupportedOperationException if rasters are not + * supported + * @exception IllegalStateException if input is null + * @exception IndexOutOfBoundsException if the frame index is + * out-of-bounds + * @exception IllegalArgumentException if the tile coordinates are + * out-of-bounds + * @exception IOException if a read error occurs + */ + public Raster readTileRaster (int imageIndex, int tileX, int tileY) + throws IOException + { + if (!canReadRaster()) + throw new UnsupportedOperationException ("cannot read rasters"); + + if (tileX != 0 || tileY != 0) + throw new IllegalArgumentException ("tileX not 0 or tileY not 0"); + + return readRaster (imageIndex, null); + } + + /** + * Reset this reader's internal state. + */ + public void reset () + { + setInput (null, false); + setLocale (null); + removeAllIIOReadUpdateListeners (); + removeAllIIOReadWarningListeners (); + removeAllIIOReadProgressListeners (); + clearAbortRequest (); + } } + diff --git a/javax/imageio/ImageTranscoder.java b/javax/imageio/ImageTranscoder.java index ccc993162..1f9195f58 100644 --- a/javax/imageio/ImageTranscoder.java +++ b/javax/imageio/ImageTranscoder.java @@ -41,14 +41,62 @@ package javax.imageio; import javax.imageio.metadata.IIOMetadata; /** + * An ImageTranscoder translates IIOMetadata objects provided by an + * ImageReader into corresponding IIOMetadata objects that can be + * understood by a given ImageWriter. + * + * Usually an ImageWriter will implement ImageTranscoder directly in + * which case the conversion methods will return IIOMetadata objects + * appropriate for this ImageWriter. + * + * Independent transcoders are also allowed; they must have knowledge + * of both the source IIOMetadata provided by the reader and the + * returned IIOMetadata expected by the writer. + * * @author Michael Koch (konqueror@gmx.de) */ public interface ImageTranscoder { + /** + * Converts IIOMetadata from an input reader format, returning an + * IIOMetadata suitable for use by an image writer. + * + * The ImageTypeSpecifier specifies the destination image type. + * + * An optional ImageWriteParam argument is available in case the + * image writing parameters affect the metadata conversion. + * + * @param inData the metadata coming from an image reader + * @param imageType the output image type of the writer + * @param param the image writing parameters or null + * + * @return the converted metadata that should be used by the image + * writer, or null if this ImageTranscoder has no knowledge of the + * input metadata + * + * @exception IllegalArgumentException if either inData or imageType + * is null + */ IIOMetadata convertImageMetadata(IIOMetadata inData, ImageTypeSpecifier imageType, ImageWriteParam param); + /** + * Converts IIOMetadata from an input stream format, returning an + * IIOMetadata suitable for use by an image writer. + * + * An optional ImageWriteParam argument is available in case the + * image writing parameters affect the metadata conversion. + * + * @param inData the metadata coming from an input image stream + * @param param the image writing parameters or null + * + * @return the converted metadata that should be used by the image + * writer, or null if this ImageTranscoder has no knowledge of the + * input metadata + * + * @exception IllegalArgumentException if inData is null + */ IIOMetadata convertStreamMetadata(IIOMetadata inData, ImageWriteParam param); } diff --git a/javax/imageio/ImageTypeSpecifier.java b/javax/imageio/ImageTypeSpecifier.java index 0751e3767..55650595f 100644 --- a/javax/imageio/ImageTypeSpecifier.java +++ b/javax/imageio/ImageTypeSpecifier.java @@ -38,15 +38,47 @@ exception statement from your version. */ package javax.imageio; +import java.awt.Transparency; +import java.awt.color.ColorSpace; +import java.awt.image.DataBuffer; +import java.awt.image.BandedSampleModel; +import java.awt.image.BufferedImage; import java.awt.image.ColorModel; +import java.awt.image.ComponentColorModel; +import java.awt.image.DirectColorModel; +import java.awt.image.IndexColorModel; +import java.awt.image.MultiPixelPackedSampleModel; +import java.awt.image.PixelInterleavedSampleModel; import java.awt.image.RenderedImage; import java.awt.image.SampleModel; +/** + * ImageTypeSpecifier store the color and sample models associated + * with an IIOImage. + */ public class ImageTypeSpecifier { + /** + * The image's color model. + */ protected ColorModel colorModel; + + /** + * The image's sample model. + */ protected SampleModel sampleModel; + /** + * Construct an image type specifier with the given models. + * + * @param colorModel the color model + * @param sampleModel the sample model + * + * @exception IllegalArgumentException if either model argument is + * null + * @exception IllegalArgumentException if the models are + * incompatible with one another + */ public ImageTypeSpecifier(ColorModel colorModel, SampleModel sampleModel) { if (colorModel == null) @@ -63,6 +95,14 @@ public class ImageTypeSpecifier this.sampleModel = sampleModel; } + /** + * Construct an image type specifier that describes the given + * rendered image. + * + * @param image a rendered image + * + * @exception IllegalArgumentException if image is null + */ public ImageTypeSpecifier(RenderedImage image) { if (image == null) @@ -72,21 +112,448 @@ public class ImageTypeSpecifier this.sampleModel = image.getSampleModel(); } + /** + * Create an image type specifier for a banded image using a + * component color model and a banded sample model. + * + * @param colorSpace the color space + * @param bankIndices the bank indices at which each band will be + * stored + * @param bandOffsets the starting band offset for each band within + * its bank + * @param dataType the data type, a DataBuffer constant + * @param hasAlpha true if this image type specifier should have an + * alpha component, false otherwise + * @param isAlphaPremultiplied true if other color components should + * be premultiplied by the alpha component, false otherwise + * + * @return a banded image type specifier + * + * @exception IllegalArgumentException if any of colorSpace, + * bankIndices or bankOffsets is null + * @exception IllegalArgumentException if bankIndices and + * bankOffsets differ in length + * @excpetion IllegalArgumentException if the number of color space + * components, including the alpha component if requested, is + * different from bandOffsets.length + * @exception if dataType is not a valid DataBuffer constant + */ + public static ImageTypeSpecifier createBanded (ColorSpace colorSpace, + int[] bankIndices, + int[] bankOffsets, + int dataType, + boolean hasAlpha, + boolean isAlphaPremultiplied) + { + if (colorSpace == null || bankIndices == null || bankOffsets == null) + throw new IllegalArgumentException ("null argument"); + + if (bankIndices.length != bankOffsets.length) + throw new IllegalArgumentException ("array lengths differ"); + + if (bankOffsets.length != (colorSpace.getNumComponents() + (hasAlpha ? 1 : 0))) + throw new IllegalArgumentException ("invalid bankOffsets length"); + + return new ImageTypeSpecifier (new ComponentColorModel (colorSpace, + hasAlpha, + isAlphaPremultiplied, + hasAlpha ? Transparency.TRANSLUCENT : Transparency.OPAQUE, + dataType), + new BandedSampleModel (dataType, 1, 1, 1, + bankIndices, + bankOffsets)); + } + + /** + * Create a buffered image with the given dimensions using that has + * the characteristics specified by this image type specifier. + * + * @param the width of the buffered image, in pixels + * @param the height of the buffered image, in pixels + * + * @return a buffered image + * + * @exception IllegalArgumentException if either width or height is + * less than or equal to zero + * @exception IllegalArgumentException if width * height is greater + * than Integer.MAX_VALUE or if the storage required is greater than + * Integer.MAX_VALUE + */ + public BufferedImage createBufferedImage (int width, int height) + { + if (width <= 0 || height <= 0) + throw new IllegalArgumentException ("dimension <= 0"); + + // test for overflow + if (width * height < Math.min (width, height)) + throw new IllegalArgumentException ("width * height > Integer.MAX_VALUE"); + + if (width * height * sampleModel.getNumBands() < Math.min (width, height)) + throw new IllegalArgumentException ("storage required >" + + " Integer.MAX_VALUE"); + + // FIXME: this is probably wrong: + return new BufferedImage (width, height, BufferedImage.TYPE_INT_RGB); + } + + /** + * Create an image type specifier that describes the given buffered + * image type. + * + * @param bufferedImageType the buffered image type to represent + * with the returned image type specifier + * + * @return a new image type specifier + * + * @exception IllegalArgumentException if bufferedImageType is not a + * BufferedImage constant or is BufferedImage.TYPE_CUSTOM + */ + public static ImageTypeSpecifier createFromBufferedImageType (int bufferedImageType) + { + if (bufferedImageType <= BufferedImage.TYPE_CUSTOM + || bufferedImageType > BufferedImage.TYPE_BYTE_INDEXED) + throw new IllegalArgumentException ("invalid buffered image type"); + + return new ImageTypeSpecifier (new BufferedImage (1, 1, bufferedImageType)); + } + + /** + * Create an image type specifier that describes the given rendered + * image's type. + * + * @param image the rendered image + * + * @return a new image type specifier + * + * @exception IllegalArgumentException if image is null + */ + public static ImageTypeSpecifier createFromRenderedImage (RenderedImage image) + { + if (image == null) + throw new IllegalArgumentException ("image null"); + + return new ImageTypeSpecifier (image); + } + + /** + * Create a grayscale image type specifier, given the number of + * bits, data type and whether or not the data is signed. + * + * @param bits the number of bits used to specify a greyscale value + * @param dataType a DataBuffer type constant + * @param isSigned true if this type specifier should support + * negative values, false otherwise + * + * @return a greyscal image type specifier + * + * @exception IllegalArgumentException if bits is not 1, 2, 4, 8 or 16 + * @exception IllegalArgumentException if dataType is not + * DataBuffer.TYPE_BYTE, DataBuffer.TYPE_SHORT or + * DataBuffer.TYPE_USHORT + * @exception if bits is larger than the number of bits in the given + * data type + */ + public static ImageTypeSpecifier createGrayScale (int bits, int dataType, boolean isSigned) + { + return createGrayScale (bits, dataType, isSigned, false); + } + + /** + * Create a grayscale image type specifier, given the number of + * bits, data type and whether or not the data is signed. + * + * @param bits the number of bits used to specify a greyscale value + * @param dataType a DataBuffer type constant + * @param isSigned true if this type specifier should support + * negative values, false otherwise + * + * @return a greyscal image type specifier + * + * @exception IllegalArgumentException if bits is not 1, 2, 4, 8 or + * 16 + * @exception IllegalArgumentException if dataType is not + * DataBuffer.TYPE_BYTE, DataBuffer.TYPE_SHORT or + * DataBuffer.TYPE_USHORT + * @exception if bits is larger than the number of bits in the given + * data type + */ + public static ImageTypeSpecifier createGrayScale (int bits, int dataType, + boolean isSigned, + boolean isAlphaPremultiplied) + { + if (bits != 1 && bits != 2 && bits != 4 && bits != 8 && bits != 16) + throw new IllegalArgumentException ("invalid bit size"); + + if (dataType != DataBuffer.TYPE_BYTE && dataType != DataBuffer.TYPE_SHORT + && dataType != DataBuffer.TYPE_USHORT) + throw new IllegalArgumentException ("invalid data type"); + + if (dataType == DataBuffer.TYPE_BYTE && bits > 8) + throw new IllegalArgumentException ("number of bits too large for data type"); + + // FIXME: this is probably wrong: + return new ImageTypeSpecifier (new DirectColorModel (bits, 0xff, 0x0, + 0x0, 0xff), + new MultiPixelPackedSampleModel (dataType, + 1, 1, + bits)); + } + + /** + * Return an image type specifier for an image that uses an indexed + * colour model where each colour value has the specified number of + * bits and type and where the colour tables are those given. + * + * @param redLUT the red index values + * @param greenLUT the green index values + * @param blueLUT the blue index values + * @param alphaLUT the alpha index values + * @param bits the number of bits per index value + * @param dataType the type of each index value + * + * @return an indexed image type specifier + * + * @exception IllegalArgumentException if any of the colour arrays, + * not including alphaLUT, is null + * @exception IllegalArgumentException if bits is not 1, 2, 4, 8 or + * 16 + * @exception IllegalArgumentException if dataType is not + * DataBuffer.TYPE_BYTE, DataBuffer.TYPE_SHORT or + * DataBuffer.TYPE_USHORT + * @exception if bits is larger than the number of bits in the given + * data type + */ + public static ImageTypeSpecifier createIndex (byte[] redLUT, + byte[] greenLUT, + byte[] blueLUT, + byte[] alphaLUT, + int bits, + int dataType) + { + if (redLUT == null || greenLUT == null || blueLUT == null) + throw new IllegalArgumentException ("null colour table"); + + if (bits != 1 && bits != 2 && bits != 4 && bits != 8 && bits != 16) + throw new IllegalArgumentException ("invalid bit size"); + + if (dataType != DataBuffer.TYPE_BYTE && dataType != DataBuffer.TYPE_SHORT + && dataType != DataBuffer.TYPE_USHORT) + throw new IllegalArgumentException ("invalid data type"); + + if (dataType == DataBuffer.TYPE_BYTE && bits > 8) + throw new IllegalArgumentException ("number of bits too large for data type"); + + // FIXME: this is probably wrong: + return new ImageTypeSpecifier (new IndexColorModel (bits, redLUT.length, + redLUT, greenLUT, blueLUT, + alphaLUT), + new MultiPixelPackedSampleModel (dataType, + 1, 1, + bits)); + } + + /** + * Create an image type specifier that uses a component colour model + * and a pixel interleaved sample model. Each pixel component will + * be stored in a separate value of the given data type. + * + * @param colorSpace the colour space used by the colour model + * @param bandOffsets the starting band offset for each band within + * its bank + * @param dataType the type of each pixel value + * @param hasAlpha true if an alpha channel should be specified, + * false otherwise + * @param isAlphaPremultiplied true if other colour channels should + * be premultiplied by the alpha value, false otherwise + * + * @return an interleaved image type specifier + * + * @exception IllegalArgumentException if either colorSpace or + * bandOffsets is null + * @excpetion IllegalArgumentException if the number of color space + * components, including the alpha component if requested, is + * different from bandOffsets.length + * @exception if dataType is not a valid DataBuffer constant + */ + public static ImageTypeSpecifier createInterleaved (ColorSpace colorSpace, + int[] bandOffsets, + int dataType, + boolean hasAlpha, + boolean isAlphaPremultiplied) + { + if (colorSpace == null || bandOffsets == null) + throw new IllegalArgumentException ("null argument"); + + if (bandOffsets.length != (colorSpace.getNumComponents() + (hasAlpha ? 1 : 0))) + throw new IllegalArgumentException ("invalid bankOffsets length"); + + return new ImageTypeSpecifier (new ComponentColorModel (colorSpace, + hasAlpha, + isAlphaPremultiplied, + hasAlpha ? Transparency.TRANSLUCENT : Transparency.OPAQUE, + dataType), + new PixelInterleavedSampleModel (dataType, 1, 1, 1, 1, + bandOffsets)); + } + + /** + * Create an image type specifier using a direct color model and a + * packed sample model. All pixel components will be packed into + * one value of the given data type. + * + * @param colorSpace the color space to use in the color model + * @param redMask the bitmask for the red bits + * @param greenMask the bitmask for the green bits + * @param blueMask the bitmask for the blue bits + * @param alphaMask the bitmask for the alpha bits + * @param transferType the data type used to store pixel values + * @param isAlphaPremultiplied true if other colour channels should + * be premultiplied by the alpha value, false otherwise + * + * @return a packed image type specifier + * + * @exception IllegalArgumentException if colorSpace is null + * @exception IllegalArgumentException if colorSpace does not have + * type ColorSpace.TYPE_RGB + * @exception IllegalArgumentException if all masks are 0 + * @exception IllegalArgumentException if dataType is not + * DataBuffer.TYPE_BYTE, DataBuffer.TYPE_SHORT or + * DataBuffer.TYPE_INT + */ + public static ImageTypeSpecifier createPacked (ColorSpace colorSpace, + int redMask, + int greenMask, + int blueMask, + int alphaMask, + int transferType, + boolean isAlphaPremultiplied) + { + if (colorSpace == null) + throw new IllegalArgumentException ("null color space"); + + if (colorSpace.getType() != ColorSpace.TYPE_RGB) + throw new IllegalArgumentException ("invalid color space type"); + + if (redMask == 0 && greenMask == 0 && blueMask == 0 && alphaMask == 0) + throw new IllegalArgumentException ("no non-zero mask"); + + if (transferType != DataBuffer.TYPE_BYTE && transferType != DataBuffer.TYPE_USHORT + && transferType != DataBuffer.TYPE_INT) + throw new IllegalArgumentException ("invalid data type"); + + // Assume DataBuffer.TYPE_BYTE. + int numBits = 8; + + if (transferType == DataBuffer.TYPE_SHORT) + numBits = 16; + else if (transferType == DataBuffer.TYPE_INT) + numBits = 32; + + return new ImageTypeSpecifier (new DirectColorModel (colorSpace, + numBits, + redMask, + greenMask, + blueMask, + alphaMask, + isAlphaPremultiplied, + transferType), + new MultiPixelPackedSampleModel (transferType, + 1, 1, numBits)); + } + + /** + * Get the number of bits per sample in the given band. + * + * @param band the band from which to get the number of bits + * + * @return the number of bits in the given band + * + * @exception IllegalArgumentException if band is out-of-bounds + */ + public int getBitsPerBand (int band) + { + if (band < 0 || band > sampleModel.getNumBands()) + throw new IllegalArgumentException ("band out-of-bounds"); + + return sampleModel.getSampleSize (band); + } + + /** + * Get the buffered image constant specified by this image type + * specifier. + * + * @return a buffered image constant + */ + public int getBufferedImageType () + { + // FIXME: + return BufferedImage.TYPE_INT_RGB; + } + + /** + * Create a sample model that is compatible with the one specified + * by this image type specifier, with the given dimensions. + * + * @param width the width of the returned sample model + * @param height the height of the returned sample model + * + * @return a sample model compatible with the one in this image type + * specifier, with the given dimensions + * + * @exception IllegalArgumentException if either width or height is + * less than or equal to 0 + * @exception IllegalArgumentException if width * height is greater + * than Intere.MAX_VALUE + */ + public SampleModel getSampleModel (int width, int height) + { + if (width <= 0 || height <= 0) + throw new IllegalArgumentException ("invalid dimension"); + + // test for overflow + if (width * height < Math.min (width, height)) + throw new IllegalArgumentException ("width * height > Integer.MAX_VALUE"); + + return sampleModel.createCompatibleSampleModel (width, height); + } + + /** + * Get the color model specified by this image type specifier. + * + * @return the color model + */ public ColorModel getColorModel() { return colorModel; } + /** + * Get the number of bands specified by this image type specifier's + * sample model. + * + * @return the number of bands in the sample model + */ public int getNumBands() { return sampleModel.getNumBands(); } + /** + * Get the number of components specified by this image type + * specifier's color model. + * + * @return the number of color components per pixel + */ public int getNumComponents() { return colorModel.getNumComponents(); } + /** + * Get the sample model specified by this image type specifier. + * + * @return the sample model + */ public SampleModel getSampleModel() { return sampleModel; diff --git a/javax/imageio/ImageWriteParam.java b/javax/imageio/ImageWriteParam.java index 08f4885a8..84b257e04 100644 --- a/javax/imageio/ImageWriteParam.java +++ b/javax/imageio/ImageWriteParam.java @@ -41,6 +41,9 @@ package javax.imageio; import java.awt.Dimension; import java.util.Locale; +/** + * DOCUMENT ME + */ public class ImageWriteParam extends IIOParam { public static final int MODE_DISABLED = 0; diff --git a/javax/imageio/ImageWriter.java b/javax/imageio/ImageWriter.java index 7479c3074..2938e1464 100644 --- a/javax/imageio/ImageWriter.java +++ b/javax/imageio/ImageWriter.java @@ -39,6 +39,9 @@ exception statement from your version. */ package javax.imageio; import java.awt.Dimension; +import java.awt.Rectangle; +import java.awt.image.Raster; +import java.awt.image.RenderedImage; import java.io.IOException; import java.util.ArrayList; import java.util.Iterator; @@ -51,40 +54,117 @@ import javax.imageio.metadata.IIOMetadata; import javax.imageio.spi.ImageWriterSpi; +/** + * A class for encoding images within the ImageIO framework. + * + * An ImageWriter for a given format is instantiated by an + * ImageWriterSpi for that format. ImageWriterSpis are registered + * with the IIORegistry. + * + * The ImageWriter API supports writing animated images that may have + * multiple frames; to support such images many methods take an index + * parameter. + * + * Images may also be written in multiple passes, where each + * successive pass increases the level of detail in the destination + * image. + */ public abstract class ImageWriter implements ImageTranscoder { private boolean aborted; + /** + * All locales available for localization of warning messages, or + * null if localization is not supported. + */ protected Locale[] availableLocales; + + /** + * The current locale used to localize warning messages, or null if + * no locale has been set. + */ protected Locale locale; + + /** + * The image writer SPI that instantiated this writer. + */ protected ImageWriterSpi originatingProvider; + + /** + * An ImageInputStream to which image data is written. + */ protected Object output; + + /** + * A list of installed progress listeners. Initially null, meaning + * no installed listeners. + */ protected List progressListeners = new ArrayList(); + + /** + * A list of installed warning listeners. Initially null, meaning + * no installed listeners. + */ protected List warningListeners = new ArrayList(); + + /** + * A list of warning locales corresponding with the list of + * installed warning listeners. Initially null, meaning no locales. + */ protected List warningLocales = new ArrayList(); + /** + * Construct an image writer. + * + * @param originatingProvider the provider that is constructing this + * image writer, or null + */ protected ImageWriter(ImageWriterSpi originatingProvider) { this.originatingProvider = originatingProvider; } + /** + * Throw an IllegalStateException if output is null. + * + * @exception IllegalStateException if output is null + */ private void checkOutputSet() { if (output == null) throw new IllegalStateException("no output set"); } + /** + * Request that writing be aborted. The unwritten portions of the + * destination image will be undefined. + * + * Writers should clear the abort flag before starting a write + * operation, then poll it periodically during the write operation. + */ public void abort() { aborted = true; } + /** + * Check if the abort flag is set. + * + * @return true if the current write operation should be aborted, + * false otherwise + */ protected boolean abortRequested() { return aborted; } + /** + * Install a write progress listener. This method will return + * immediately if listener is null. + * + * @param listener a write progress listener or null + */ public void addIIOWriteProgressListener(IIOWriteProgressListener listener) { if (listener == null) @@ -93,6 +173,15 @@ public abstract class ImageWriter progressListeners.add(listener); } + /** + * Install a write warning listener. This method will return + * immediately if listener is null. Warning messages sent to this + * listener will be localized using the current locale. If the + * current locale is null then this writer will select a sensible + * default. + * + * @param listener a write warning listener + */ public void addIIOWriteWarningListener (IIOWriteWarningListener listener) { if (listener == null) @@ -101,6 +190,23 @@ public abstract class ImageWriter warningListeners.add(listener); } + /** + * Check whether a new empty image can be inserted at the given + * frame index. Pixel values may be filled in later using the + * replacePixels methods. Indices greater than the insertion index + * will be incremented. If imageIndex is -1, the image will be + * appended at the end of the current image list. + * + * @param imageIndex the frame index + * + * @return true if an empty image can be inserted at imageIndex, + * false otherwise + * + * @exception IllegalStateException if output is null + * @exception IndexOutOfBoundsException if imageIndex is less than + * -1 or greater than the last index in the current image list + * @exception IOException if a write error occurs + */ public boolean canInsertEmpty(int imageIndex) throws IOException { @@ -108,6 +214,22 @@ public abstract class ImageWriter return false; } + /** + * Check whether an image can be inserted at the given frame index. + * Indices greater than the insertion index will be incremented. If + * imageIndex is -1, the image will be appended at the end of the + * current image list. + * + * @param imageIndex the frame index + * + * @return true if an image can be inserted at imageIndex, false + * otherwise + * + * @exception IllegalStateException if output is null + * @exception IndexOutOfBoundsException if imageIndex is less than + * -1 or greater than the last index in the current image list + * @exception IOException if a write error occurs + */ public boolean canInsertImage(int imageIndex) throws IOException { @@ -115,6 +237,20 @@ public abstract class ImageWriter return false; } + /** + * Check whether an image can be removed from the given frame index. + * Indices greater than the removal index will be decremented. + * + * @param imageIndex the frame index + * + * @return true if an image can be removed from imageIndex, false + * otherwise + * + * @exception IllegalStateException if output is null + * @exception IndexOutOfBoundsException if imageIndex is less than 0 + * or greater than the last index in the current image list + * @exception IOException if a write error occurs + */ public boolean canRemoveImage(int imageIndex) throws IOException { @@ -122,6 +258,20 @@ public abstract class ImageWriter return false; } + /** + * Check whether the metadata associated the image at the given + * frame index can be replaced. + * + * @param imageIndex the frame index + * + * @return true if the metadata associated with the image at + * imageIndex can be replaced, false otherwise + * + * @exception IllegalStateException if output is null + * @exception IndexOutOfBoundsException if imageIndex is less than 0 + * or greater than the last index in the current image list + * @exception IOException if a write error occurs + */ public boolean canReplaceImageMetadata(int imageIndex) throws IOException { @@ -129,6 +279,20 @@ public abstract class ImageWriter return false; } + /** + * Check whether the pixels within the image at the given index can + * be replaced. + * + * @param imageIndex the frame index + * + * @return true if the pixels in the image at imageIndex can be + * replaced, false otherwise + * + * @exception IllegalStateException if output is null + * @exception IndexOutOfBoundsException if imageIndex is less than 0 + * or greater than the last index in the current image list + * @exception IOException if a write error occurs + */ public boolean canReplacePixels(int imageIndex) throws IOException { @@ -136,6 +300,16 @@ public abstract class ImageWriter return false; } + /** + * Check whether the metadata associated the entire image stream can + * be replaced. + * + * @return true if the stream metadata can be replaced, false + * otherwise + * + * @exception IllegalStateException if output is null + * @exception IOException if a write error occurs + */ public boolean canReplaceStreamMetadata() throws IOException { @@ -143,6 +317,18 @@ public abstract class ImageWriter return false; } + /** + * Check whether an entire empty image, including empty metadata and + * empty thumbnails, can be written to the output stream, leaving + * pixel values to be filled in later using the replacePixels + * methods. + * + * @return true if an entire empty image can be written before its + * contents are filled in, false otherwise + * + * @exception IllegalStateException if output is null + * @exception IOException if a write error occurs + */ public boolean canWriteEmpty() throws IOException { @@ -150,68 +336,217 @@ public abstract class ImageWriter return false; } + /** + * Check if IIOImages containing raster data are supported. + * + * @return true if raster IIOImages are supported, false otherwise + */ public boolean canWriteRasters() { return false; } + /** + * Check if an image can be appended at the end of the current list + * of images even if prior images have already been written. + * + * @return true if sequences of images can be written, false + * otherwise + */ public boolean canWriteSequence() { return false; } + /** + * Clear the abort flag. + */ protected void clearAbortRequest() { aborted = false; } - + + /** + * Convert IIOMetadata from an input reader format, returning an + * IIOMetadata suitable for use by an image writer. + * + * The ImageTypeSpecifier specifies the destination image type. + * + * An optional ImageWriteParam argument is available in case the + * image writing parameters affect the metadata conversion. + * + * @param inData the metadata coming from an image reader + * @param imageType the output image type of the writer + * @param param the image writing parameters or null + * + * @return the converted metadata that should be used by the image + * writer, or null if this ImageTranscoder has no knowledge of the + * input metadata + * + * @exception IllegalArgumentException if either inData or imageType + * is null + */ public abstract IIOMetadata convertImageMetadata (IIOMetadata inData, ImageTypeSpecifier imageType, ImageWriteParam param); + /** + * Convert IIOMetadata from an input stream format, returning an + * IIOMetadata suitable for use by an image writer. + * + * An optional ImageWriteParam argument is available in case the + * image writing parameters affect the metadata conversion. + * + * @param inData the metadata coming from an input image stream + * @param param the image writing parameters or null + * + * @return the converted metadata that should be used by the image + * writer, or null if this ImageTranscoder has no knowledge of the + * input metadata + * + * @exception IllegalArgumentException if inData is null + */ public abstract IIOMetadata convertStreamMetadata (IIOMetadata inData, ImageWriteParam param); + /** + * Releases any resources allocated to this object. Subsequent + * calls to methods on this object will produce undefined results. + * + * The default implementation does nothing; subclasses should use + * this method ensure that native resources are released. + */ public void dispose() { // The default implementation is empty. Subclasses have to overwrite it. } + /** + * Retrieve the available locales. Return null if no locales are + * available or a clone of availableLocales. + * + * @return an array of locales or null + */ public Locale[] getAvailableLocales() { return availableLocales; } + /** + * Get a metadata object appropriate for encoding an image specified + * by the given image type specifier and optional image write + * parameters. + * + * @param imageType an image type specifier + * @param param image writing parameters, or null + * + * @return a metadata object appropriate for encoding an image of + * the given type with the given parameters + */ public abstract IIOMetadata getDefaultImageMetadata (ImageTypeSpecifier imageType, ImageWriteParam param); + /** + * Get a metadata object appropriate for encoding the default image + * type handled by this writer, optionally considering image write + * parameters. + * + * @param param image writing parameters, or null + * + * @return a metadata object appropriate for encoding an image of + * the default type with the given parameters + */ public abstract IIOMetadata getDefaultStreamMetadata (ImageWriteParam param); + /** + * Retrieve the default write parameters for this writer's image + * format. + * + * The default implementation returns new ImageWriteParam(). + * + * @return image writing parameters + */ public ImageWriteParam getDefaultWriteParam() { return new ImageWriteParam(getLocale()); } + /** + * Get this writer's locale. null is returned if the locale has not + * been set. + * + * @return this writer's locale, or null + */ public Locale getLocale() { return locale; } - public int getNumThumbnailsSupported (ImageTypeSpecifier imageType, ImageWriteParam param, - IIOMetadata streamMetadata, IIOMetadata imageMetadata) + /** + * Get the number of thumbnails supported by this image writer, + * based on the given image type, image writing parameters, and + * stream and image metadata. The image writing parameters are + * optional, in case they affect the number of thumbnails supported. + * + * @param imageType an image type specifier, or null + * @param param image writing parameters, or null + * @param streamMetadata the metadata associated with this stream, + * or null + * @param imageMetadata the metadata associated with this image, or + * null + * + * @return the number of thumbnails that this writer supports + * writing or -1 if the given information is insufficient + */ + public int getNumThumbnailsSupported (ImageTypeSpecifier imageType, + ImageWriteParam param, + IIOMetadata streamMetadata, + IIOMetadata imageMetadata) { return 0; } + /** + * Get the ImageWriterSpi that created this writer or null. + * + * @return an ImageWriterSpi, or null + */ public ImageWriterSpi getOriginatingProvider() { return originatingProvider; } + /** + * Get this reader's image output destination. null is returned if + * the image destination has not been set. + * + * @return an image output destination object, or null + */ public Object getOutput() { return output; } + /** + * Get the preferred sizes for thumbnails based on the given image + * type, image writing parameters, and stream and image metadata. + * The preferred sizes are returned in pairs of dimension values; + * the first value in the array is a dimension object representing + * the minimum thumbnail size, the second value is a dimension + * object representing a maximum thumbnail size. The writer can + * select a size within the range given by each pair, or it can + * ignore these size hints. + * + * @param imageType an image type specifier, or null + * @param param image writing parameters, or null + * @param streamMetadata the metadata associated with this stream, + * or null + * @param imageMetadata the metadata associated with this image, or + * null + * + * @return an array of dimension pairs whose length is a multiple of + * 2, or null if there is no preferred size (any size is allowed) or + * if the size is unknown (insufficient information was provided) + */ public Dimension[] getPreferredThumbnailSizes (ImageTypeSpecifier imageType, ImageWriteParam param, IIOMetadata streamMetadata, @@ -220,6 +555,10 @@ public abstract class ImageWriter return null; } + /** + * Notifies all installed write progress listeners that image + * loading has completed by calling their imageComplete methods. + */ protected void processImageComplete() { Iterator it = progressListeners.iterator(); @@ -231,6 +570,14 @@ public abstract class ImageWriter } } + /** + * Notifies all installed write progress listeners that a certain + * percentage of the image has been loaded, by calling their + * imageProgress methods. + * + * @param percentageDone the percentage of image data that has been + * loaded + */ protected void processImageProgress(float percentageDone) { Iterator it = progressListeners.iterator(); @@ -242,6 +589,14 @@ public abstract class ImageWriter } } + /** + * Notifies all installed write progress listeners, by calling their + * imageStarted methods, that image loading has started on the given + * image. + * + * @param imageIndex the frame index of the image that has started + * loading + */ protected void processImageStarted(int imageIndex) { Iterator it = progressListeners.iterator(); @@ -253,6 +608,11 @@ public abstract class ImageWriter } } + /** + * Notifies all installed write progress listeners, by calling their + * thumbnailComplete methods, that a thumbnail has completed + * loading. + */ protected void processThumbnailComplete() { Iterator it = progressListeners.iterator(); @@ -264,6 +624,14 @@ public abstract class ImageWriter } } + /** + * Notifies all installed write progress listeners that a certain + * percentage of a thumbnail has been loaded, by calling their + * thumbnailProgress methods. + * + * @param percentageDone the percentage of thumbnail data that has + * been loaded + */ protected void processThumbnailProgress(float percentageDone) { Iterator it = progressListeners.iterator(); @@ -275,6 +643,16 @@ public abstract class ImageWriter } } + /** + * Notifies all installed write progress listeners, by calling their + * imageStarted methods, that thumbnail loading has started on the + * given thumbnail of the given image. + * + * @param imageIndex the frame index of the image one of who's + * thumbnails has started loading + * @param thumbnailIndex the index of the thumbnail that has started + * loading + */ protected void processThumbnailStarted(int imageIndex, int thumbnailIndex) { Iterator it = progressListeners.iterator(); @@ -286,6 +664,16 @@ public abstract class ImageWriter } } + /** + * Notifies all installed warning listeners, by calling their + * warningOccurred methods, that a warning message has been raised. + * + * @param imageIndex the index of the image that was being written + * when the warning was raised + * @param warning the warning message + * + * @throw IllegalArgumentException if warning is null + */ protected void processWarningOccurred(int imageIndex, String warning) { Iterator it = warningListeners.iterator(); @@ -297,6 +685,10 @@ public abstract class ImageWriter } } + /** + * Notifies all installed write progress listeners that image + * loading has been aborted by calling their writeAborted methods. + */ protected void processWriteAborted() { Iterator it = progressListeners.iterator(); @@ -308,16 +700,27 @@ public abstract class ImageWriter } } + /** + * Uninstall all write progress listeners. + */ public void removeAllIIOWriteProgressListeners() { progressListeners.clear(); } + /** + * Uninstall all write warning listeners. + */ public void removeAllIIOWriteWarningListeners() { progressListeners.clear(); } + /** + * Uninstall the given write progress listener. + * + * @param listener the listener to remove + */ public void removeIIOWriteProgressListener (IIOWriteProgressListener listener) { if (listener == null) @@ -326,6 +729,11 @@ public abstract class ImageWriter progressListeners.remove(listener); } + /** + * Uninstall the given write warning listener. + * + * @param listener the listener to remove + */ public void removeIIOWriteWarningListener (IIOWriteWarningListener listener) { if (listener == null) @@ -334,6 +742,9 @@ public abstract class ImageWriter warningListeners.remove(listener); } + /** + * Reset this writer's internal state. + */ public void reset() { setOutput(null); @@ -343,6 +754,11 @@ public abstract class ImageWriter clearAbortRequest(); } + /** + * Set the current locale or use the default locale. + * + * @param locale the locale to set, or null + */ public void setLocale(Locale locale) { if (locale != null) @@ -362,6 +778,18 @@ public abstract class ImageWriter this.locale = locale; } + /** + * Set the output destination of the given object. The output + * destination must be set before many methods can be called on this + * writer. (see all ImageWriter methods that throw + * IllegalStateException). If input is null then the current input + * source will be removed. + * + * @param input the output destination object + * + * @exception IllegalArgumentException if input is not a valid input + * source for this writer and is not an ImageInputStream + */ public void setOutput(Object output) { if (output != null) @@ -385,6 +813,464 @@ public abstract class ImageWriter this.output = output; } + /** + * Write an image stream, including thumbnails and metadata to the + * output stream. The output must have been set prior to this + * method being called. Metadata associated with the stream may be + * supplied, or it can be left null. IIOImage may contain raster + * data if this writer supports rasters, or it will contain a + * rendered image. Thumbnails are resized if need be. Image + * writing parameters may be specified to affect writing, or may be + * left null. + * + * @param streamMetadata metadata associated with this stream, or + * null + * @param image an IIOImage containing image data, metadata and + * thumbnails to be written + * @param param image writing parameters, or null + * + * @exception IllegalStateException if output is null + * @exception UnsupportedOperationException if image contains raster + * data but this writer does not support rasters + * @exception IllegalArgumentException if image is null + * @exception IOException if a write error occurs + */ public abstract void write (IIOMetadata streamMetadata, IIOImage image, ImageWriteParam param) throws IOException; + + /** + * Complete inserting an empty image in the output stream. + * + * @exception IllegalStateException if output is null + * @exception UnsupportedOperationException if inserting empty + * images is not supported + * @exception IllegalArgumentException if a call to + * prepareInsertEmpty was not called previous to this method being + * called (a sequence of prepareInsertEmpty calls must be terminated + * by a call to endInsertEmpty) + * @exception IllegalArgumentException if prepareWriteEmpty was + * called before this method being called (without a terminating + * call to endWriteEmpty) + * @exception IllegalArgumentException if prepareReplacePixels was + * called before this method being called (without a terminating + * call to endReplacePixels) + * @exception IOException if a write error occurs + */ + public void endInsertEmpty () + throws IOException + { + if (!canInsertEmpty(0)) + throw new UnsupportedOperationException(); + } + + /** + * Complete replacing pixels in an image in the output stream. + * + * @exception IllegalStateException if output is null + * @exception UnsupportedOperationException if replacing pixels is + * not supported by this writer + * @exception IllegalArgumentException if prepareReplacePixels was + * not called before this method being called + * @exception IOException if a write error occurs + */ + public void endReplacePixels () + throws IOException + { + if (!canReplacePixels(0)) + throw new UnsupportedOperationException(); + } + + /** + * Complete writing an empty image to the image output stream. + * + * @exception IllegalStateException if output is null + * @exception UnsupportedOperationException if writing empty images + * is not supported + * @exception IllegalArgumentException if a call to + * prepareWriteEmpty was not called previous to this method being + * called (a sequence of prepareWriteEmpty calls must be terminated + * by a call to endWriteEmpty) + * @exception IllegalArgumentException if prepareInsertEmpty was + * called before this method being called (without a terminating + * call to endInsertEmpty) + * @exception IllegalArgumentException if prepareReplacePixels was + * called before this method being called (without a terminating + * call to endReplacePixels) + * @exception IOException if a write error occurs + */ + public void endWriteEmpty () + throws IOException + { + if (!canWriteEmpty()) + throw new UnsupportedOperationException(); + } + + /** + * Complete writing a sequence of images to the output stream. This + * method may patch header data and write out footer data. + * + * @exception IllegalStateException if output is null + * @exception IllegalStateException if prepareWriteSequence has not + * been called + * @exception UnsupportedOperationException if writing a sequence of + * images is not supported + * @exception IOException if a write error occurs + */ + public void endWriteSequence () + throws IOException + { + checkOutputSet(); + if (!canWriteSequence()) + throw new UnsupportedOperationException(); + } + + /** + * Start inserting an empty image in the image output stream. All + * indices after the specified index are incremented. An index of + * -1 implies that the empty image should be appended to the end of + * the current image list. + * + * The insertion that this method call starts is not complete until + * endInsertEmpty is called. prepareInsertEmpty cannot be called + * again until endInsertEmpty is called and calls to + * prepareWriteEmpty and prepareInsertEmpty may not be intersperced. + * + * @param imageIndex the image index + * @param imageType the image type specifier + * @param width the image width + * @param height the image height + * @param imageMetadata the image metadata, or null + * @param thumbnails a list of thumbnails, or null + * @param param image write parameters, or null + * + * @exception IllegalStateException if output is null + * @exception UnsupportedOperationException if inserting empty + * images is not supported + * @exception IndexOutOfBoundsException if imageIndex is less than + * -1 or greater than the last index in the current image list + * @exception IllegalStateException if a previous call to + * prepareInsertEmpty was made (without a terminating call to + * endInsertEmpty) + * @exception IllegalStateException if a previous call to + * prepareWriteEmpty was made (without a terminating call to + * endWriteEmpty) + * @exception IllegalArgumentException if imageType is null or + * thumbnails contain non-BufferedImage objects + * @exception IllegalArgumentException if either width or height is + * less than 1 + * @exception IOException if a write error occurs + */ + public void prepareInsertEmpty (int imageIndex, ImageTypeSpecifier imageType, + int width, int height, + IIOMetadata imageMetadata, + List thumbnails, + ImageWriteParam param) + throws IOException + { + if (!canInsertEmpty(imageIndex)) + throw new UnsupportedOperationException(); + } + + /** + * Start the replacement of pixels within an image in the output + * stream. Output pixels will be clipped to lie within region. + * + * @param imageIndex the index of the image in which pixels are + * being replaced + * @param region the rectangle to which to limit pixel replacement + * + * @exception IllegalStateException if output is null + * @exception UnsupportedOperationException if replacing pixels is + * not supported + * @exception IndexOutOfBoundsException if imageIndex is less than 0 + * or greater than the last index in the current image list + * @exception IllegalStateException if a previous call to + * prepareReplacePixels was made (without a terminating call to + * endReplacePixels) + * @exception IllegalArgumentException if either region.width or + * region.height is less than 1, or if region is null + * @exception IOException if a write error occurs + */ + public void prepareReplacePixels (int imageIndex, Rectangle region) + throws IOException + { + if (canReplacePixels(imageIndex)) + throw new UnsupportedOperationException(); + } + + /** + * Start writing an empty image to the end of the image output + * stream. + * + * The writing that this method call starts is not complete until + * endWriteEmpty is called. prepareWritetEmpty cannot be called + * again until endWriteEmpty is called and calls to + * prepareWriteEmpty and prepareInsertEmpty may not be intersperced. + * + * @param streamMetadata metadata associated with the stream, or null + * @param imageType the image type specifier + * @param width the image width + * @param height the image height + * @param imageMetadata the image metadata, or null + * @param thumbnails a list of thumbnails, or null + * @param param image write parameters, or null + * + * @exception IllegalStateException if output is null + * @exception UnsupportedOperationException if writing empty images + * is not supported + * @exception IndexOutOfBoundsException if imageIndex is less than + * -1 or greater than the last index in the current image list + * @exception IllegalStateException if a previous call to + * prepareInsertEmpty was made (without a terminating call to + * endInsertEmpty) + * @exception IllegalStateException if a previous call to + * prepareWriteEmpty was made (without a terminating call to + * endWriteEmpty) + * @exception IllegalArgumentException if imageType is null or + * thumbnails contain non-BufferedImage objects + * @exception IllegalArgumentException if either width or height is + * less than 1 + * @exception IOException if a write error occurs + */ + public void prepareWriteEmpty (IIOMetadata streamMetadata, + ImageTypeSpecifier imageType, + int width, int height, + IIOMetadata imageMetadata, + List thumbnails, + ImageWriteParam param) + throws IOException + { + if (!canWriteEmpty()) + throw new UnsupportedOperationException(); + } + + /** + * Start the writing of a sequence of images. + * + * @param streamMetadata the stream metadata, or null + * + * @exception IllegalStateException if output is null + * @exception UnsupportedOperationException if writing sequences of + * images is not supported + * @exception IOException if a write error occurs + */ + public void prepareWriteSequence (IIOMetadata streamMetadata) + throws IOException + { + checkOutputSet(); + if (!canWriteSequence()) + throw new UnsupportedOperationException(); + } + + /** + * Remove the image at the specified index from the output stream. + * + * @param imageIndex the frame index from which to remove the image + * + * @exception IllegalStateException if output is null + * @exception UnsupportedOperationException if removing this image + * is not supported + * @exception IndexOutOfBoundsException if imageIndex is less than 0 + * or greater than the last index in the current image list + * @exception IOException if a write error occurs + */ + public void removeImage (int imageIndex) + throws IOException + { + if (!canRemoveImage(imageIndex)) + throw new UnsupportedOperationException(); + } + + /** + * Replace the metadata associated with the image at the given + * index. + * + * @param imageIndex the index of the image whose metadata should be + * replaced + * @param imageMetadata the metadata, or null + * + * @exception IllegalStateException if output is null + * @exception UnsupportedOperationException if replacing this + * image's metadata is not supported + * @exception IndexOutOfBoundsException if imageIndex is less than 0 + * or greater than the last index in the current image list + * @exception IOException if a write error occurs + */ + public void replaceImageMetadata (int imageIndex, IIOMetadata imageMetadata) + throws IOException + { + if (!canReplaceImageMetadata(imageIndex)) + throw new UnsupportedOperationException(); + } + + /** + * Replace a region of an image in the output stream with a portion + * of the given rendered image. The image data must be of the same + * type as that in the output stream. The destination region is + * given by the image writing parameters and the source region is + * the one given to prepareReplacePixels. + * + * @param image the rendered image with which to overwrite the image + * region in the stream + * @param param the image writing parameters + * + * @exception IllegalStateException if output is null + * @exception UnsupportedOperationException if replacing pixels is + * not supported + * @exception IllegalStateException if prepareReplacePixels was not + * called before this method was called + * @exception IllegalArgumentException if image is null or if param + * is null or if the overlap of the source and destination regions + * contains no pixels or if the image types differ and no conversion + * is possible + * @exception IOException if a write error occurs + */ + public void replacePixels (RenderedImage image, + ImageWriteParam param) + throws IOException + { + if (!canReplacePixels(0)) + throw new UnsupportedOperationException(); + } + + /** + * Replace a region of an image in the output stream with a portion + * of the given raster data. The image data must be of the same + * type as that in the output stream. The destination region is + * given by the image writing parameters and the source region is + * the one given to prepareReplacePixels. + * + * @param raster the raster data with which to overwrite the image + * region in the stream + * @param param the image writing parameters + * + * @exception IllegalStateException if output is null + * @exception UnsupportedOperationException if replacing pixels is + * not supported + * @exception IllegalStateException if prepareReplacePixels was not + * called before this method was called + * @exception UnsupportedOperationException if raster data is not + * supported + * @exception IllegalArgumentException if raster is null or if param + * is null or if the overlap of the source and destination regions + * contains no pixels or if the image types differ and no conversion + * is possible + * @exception IOException if a write error occurs + */ + public void replacePixels (Raster raster, ImageWriteParam param) + throws IOException + { + if (!canReplacePixels(0)) + throw new UnsupportedOperationException(); + } + + /** + * Replace the metadata associated with this image stream. + * + * @param streamMetadata the stream metadata, or null + * + * @exception IllegalStateException if output is null + * @exception UnsupportedOperationException if replacing the stream + * metadata is not supported + * @exception IOException if a write error occurs + */ + public void replaceStreamMetadata (IIOMetadata streamMetadata) + throws IOException + { + if (!canReplaceStreamMetadata()) + throw new UnsupportedOperationException(); + } + + /** + * Write a rendered image to the output stream. + * + * @param image a rendered image containing image data to be written + * + * @exception IllegalStateException if output is null + * @exception IllegalArgumentException if image is null + * @exception IOException if a write error occurs + */ + public void write (RenderedImage image) + throws IOException + { + checkOutputSet(); + write (null, new IIOImage(image, null, null), null); + } + + /** + * Write a image data, metadata and thumbnails to the output stream. + * + * @param image image data, metadata and thumbnails to be written + * + * @exception IllegalStateException if output is null + * @exception UnsupportedOperationException if image contains raster + * data but this writer does not support rasters + * @exception IllegalArgumentException if image is null + * @exception IOException if a write error occurs + */ + public void write (IIOImage image) + throws IOException + { + checkOutputSet(); + write (null, image, null); + } + + /** + * Insert an image into the output stream. Indices greater than the + * specified index are incremented accordingly. Specifying an index + * of -1 causes the image to be appended at the end of the current + * image list. + * + * @param imageIndex the frame index at which to insert the image + * @param image the image data, metadata and thumbnails to be + * inserted + * @param the image write parameters, or null + * + * @exception IllegalStateException if output is null + * @exception UnsupportedOperationException if image insertion is + * not supported + * @exception IllegalArgumentException if image is null + * @exception IndexOutOfBoundsException if imageIndex is less than + * -1 or greater than the last index in the current image list + * @exception UnsupportedOperationException if image contains raster + * data but this writer does not support rasters + * @exception IOException if a write error occurs + */ + public void writeInsert (int imageIndex, IIOImage image, ImageWriteParam param) + throws IOException + { + if (!canInsertImage(imageIndex)) + throw new UnsupportedOperationException(); + } + + /** + * Write a sequence of images, including thumbnails and metadata, to + * the output stream. The output must have been set prior to this + * method being called. Metadata associated with the stream may be + * supplied, or it can be left null. IIOImage may contain raster + * data if this writer supports rasters, or it will contain a + * rendered image. Thumbnails are resized if need be. Image + * writing parameters may be specified to affect writing, or may be + * left null. + * + * @param streamMetadata metadata associated with this stream, or + * null + * @param image an IIOImage containing image data, metadata and + * thumbnails to be written + * @param param image writing parameters, or null + * + * @exception IllegalStateException if output is null + * @exception UnsupportedOperationException if writing sequences of + * images is not supported + * @exception IllegalArgumentException if image is null + * @exception UnsupportedOperationException if image contains raster + * data but this writer does not support rasters + * @exception IOException if a write error occurs + */ + public void writeToSequence (IIOImage image, ImageWriteParam param) + throws IOException + { + if (!canWriteSequence()) + throw new UnsupportedOperationException(); + } } diff --git a/javax/imageio/package.html b/javax/imageio/package.html index ce36a7b44..f6a604de8 100644 --- a/javax/imageio/package.html +++ b/javax/imageio/package.html @@ -40,7 +40,48 @@ exception statement from your version. --> <head><title>GNU Classpath - javax.imageio</title></head> <body> -<p></p> - +<p> +This package provides image input/output APIs. +</p> +<p> +The standard class library provides other ways of loading images (@see +java.awt.Toolkit, @see java.awt.Component)) but the ImageIO package is +more powerful. +</p> +<p> +The static ImageIO class supports reading and writing images in many +different formats along with most other basic image I/O operations. +</p> +<p> +Other classes provide finer control of image-related operations; +reading is controlled by ImageReader, ImageReadParam and +ImageTypeSpecifyer, writing by ImageWriter and ImageWriteParam. +ImageTranscoder allows fine-grained control over how images are +converted between formats and IIOException reports errors. IIOImage +describes an image file in detail including metadata and thumbnails. +</p> +<h2>Supported Formats</h2> +<p> +The default GNU Classpath ImageIO backend uses ImageMagick and so +supports the following formats: +<table> +<tr> +<th></th> <th>Read</th> <th>Write</th> +</tr> +<tr><td>JPEG</td><td>yes</td><td>yes</td></tr> +<tr><td>PNG</td><td>yes</td><td>yes</td></tr> +<tr><td>BMP</td><td>yes</td><td>yes</td></tr> +<tr><td>WBMP</td><td>yes</td><td>yes</td></tr> +<tr><td>GIF</td><td>yes</td><td>yes</td></tr> +<tr><td>TIFF</td><td>yes</td><td>yes</td></tr> +<tr><td>XPM</td><td>yes</td><td>yes</td></tr> +<tr><td>TGA</td><td>yes</td><td>yes</td></tr> +<tr><td>PDF</td><td>yes</td><td>no</td></tr> +<tr><td>SVG</td><td>yes</td><td>no</td></tr> +<table> +</p> +<p> +@since 1.4 +</p> </body> </html> |