diff options
author | upstream source tree <ports@midipix.org> | 2015-03-15 20:14:05 -0400 |
---|---|---|
committer | upstream source tree <ports@midipix.org> | 2015-03-15 20:14:05 -0400 |
commit | 554fd8c5195424bdbcabf5de30fdc183aba391bd (patch) | |
tree | 976dc5ab7fddf506dadce60ae936f43f58787092 /libjava/classpath/javax/imageio | |
download | cbb-gcc-4.6.4-554fd8c5195424bdbcabf5de30fdc183aba391bd.tar.bz2 cbb-gcc-4.6.4-554fd8c5195424bdbcabf5de30fdc183aba391bd.tar.xz |
obtained gcc-4.6.4.tar.bz2 from upstream website;upstream
verified gcc-4.6.4.tar.bz2.sig;
imported gcc-4.6.4 source tree from verified upstream tarball.
downloading a git-generated archive based on the 'upstream' tag
should provide you with a source tree that is binary identical
to the one extracted from the above tarball.
if you have obtained the source via the command 'git clone',
however, do note that line-endings of files in your working
directory might differ from line-endings of the respective
files in the upstream repository.
Diffstat (limited to 'libjava/classpath/javax/imageio')
53 files changed, 15980 insertions, 0 deletions
diff --git a/libjava/classpath/javax/imageio/IIOException.java b/libjava/classpath/javax/imageio/IIOException.java new file mode 100644 index 000000000..b281db1b0 --- /dev/null +++ b/libjava/classpath/javax/imageio/IIOException.java @@ -0,0 +1,70 @@ +/* IIOException.java -- + Copyright (C) 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +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 +{ + /** + * Create an exception with a descriptive error message. + * + * @param message The descriptive error message. + */ + public IIOException(String message) + { + super(message); + } + + /** + * Create an exception with a descriptive error message. + * + * @param message The descriptive error message. + * @param cause The cause for this exception. + */ + public IIOException(String message, Throwable cause) + { + super(message); + initCause(cause); + } +} diff --git a/libjava/classpath/javax/imageio/IIOImage.java b/libjava/classpath/javax/imageio/IIOImage.java new file mode 100644 index 000000000..a368e5a84 --- /dev/null +++ b/libjava/classpath/javax/imageio/IIOImage.java @@ -0,0 +1,268 @@ +/* IIOImage.java -- + Copyright (C) 2003 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.imageio; + +import java.awt.image.BufferedImage; +import java.awt.image.Raster; +import java.awt.image.RenderedImage; +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. + */ + protected List<? extends BufferedImage> 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<? extends BufferedImage> thumbnails, + IIOMetadata metadata) + { + if (raster == null) + throw new IllegalArgumentException ("raster may not be null"); + + this.raster = raster; + this.thumbnails = thumbnails; + 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<? extends BufferedImage> thumbnails, + IIOMetadata metadata) + { + if (image == null) + throw new IllegalArgumentException ("image may not be null"); + + this.image = image; + this.thumbnails = thumbnails; + 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 == 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<? extends BufferedImage> 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) + throw new IllegalArgumentException ("raster may not be null"); + + this.image = null; + 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) + throw new IllegalArgumentException ("image may not be null"); + + this.image = image; + 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<? extends BufferedImage> thumbnails) + { + this.thumbnails = thumbnails; + } +} diff --git a/libjava/classpath/javax/imageio/IIOParam.java b/libjava/classpath/javax/imageio/IIOParam.java new file mode 100644 index 000000000..3e7854747 --- /dev/null +++ b/libjava/classpath/javax/imageio/IIOParam.java @@ -0,0 +1,491 @@ +/* IIOParam.java -- + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.imageio; + +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 +{ + /** + * 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); + + /** + * 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() + { + } + + /** + * 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) + { + 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 == 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() + { + 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) + { + 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) + throw new IllegalArgumentException("destinationOffset is null"); + + 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) + { + 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 + && (sourceRegion.x < 0 + || sourceRegion.y < 0 + || sourceRegion.width <= 0 + || sourceRegion.height <= 0)) + throw new IllegalArgumentException("illegal source region"); + + 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; + this.subsamplingYOffset = subsamplingYOffset; + } +} diff --git a/libjava/classpath/javax/imageio/IIOParamController.java b/libjava/classpath/javax/imageio/IIOParamController.java new file mode 100644 index 000000000..e77f8542f --- /dev/null +++ b/libjava/classpath/javax/imageio/IIOParamController.java @@ -0,0 +1,69 @@ +/* IIOParamController.java -- + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +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. 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 + * + * @return true if the <code>IIOParam</code> has been modified, + * false otherwise + * + * @exception IllegalArgumentException if param is null or is not an instance + * of the correct class + */ + boolean activate(IIOParam param); +} diff --git a/libjava/classpath/javax/imageio/ImageIO.java b/libjava/classpath/javax/imageio/ImageIO.java new file mode 100644 index 000000000..9abb1c818 --- /dev/null +++ b/libjava/classpath/javax/imageio/ImageIO.java @@ -0,0 +1,1241 @@ +/* ImageIO.java -- + Copyright (C) 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.imageio; + +import java.awt.image.BufferedImage; +import java.awt.image.RenderedImage; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.URL; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; + +import javax.imageio.spi.IIORegistry; +import javax.imageio.spi.ImageInputStreamSpi; +import javax.imageio.spi.ImageOutputStreamSpi; +import javax.imageio.spi.ImageReaderSpi; +import javax.imageio.spi.ImageTranscoderSpi; +import javax.imageio.spi.ImageWriterSpi; +import javax.imageio.spi.ServiceRegistry; +import javax.imageio.stream.ImageInputStream; +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 +{ + /** + * Construct an ImageIO. Private since ImageIO is not instantiable. + */ + private ImageIO() + { + } + + private static final class ReaderFormatFilter implements ServiceRegistry.Filter + { + private String formatName; + + public ReaderFormatFilter(String formatName) + { + this.formatName = formatName; + } + + public boolean filter (Object provider) + { + if (provider instanceof ImageReaderSpi) + { + ImageReaderSpi spi = (ImageReaderSpi) provider; + 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 ReaderMIMETypeFilter implements ServiceRegistry.Filter + { + private String MIMEType; + + public ReaderMIMETypeFilter(String MIMEType) + { + this.MIMEType = MIMEType; + } + + public boolean filter(Object provider) + { + if (provider instanceof ImageReaderSpi) + { + ImageReaderSpi spi = (ImageReaderSpi) provider; + String[] mimetypes = spi.getMIMETypes(); + + for (int i = mimetypes.length - 1; i >= 0; --i) + if (MIMEType.equals(mimetypes[i])) + return true; + } + + return false; + } + } + + private static final class ReaderObjectFilter implements ServiceRegistry.Filter + { + private Object object; + + public ReaderObjectFilter(Object object) + { + this.object = object; + } + + public boolean filter(Object provider) + { + if (provider instanceof ImageReaderSpi) + { + ImageReaderSpi spi = (ImageReaderSpi) provider; + + try + { + if (spi.canDecodeInput(object)) + return true; + } + catch (IOException e) + { + // Return false in this case + } + } + return false; + } + } + + private static final class ReaderSuffixFilter implements ServiceRegistry.Filter + { + private String fileSuffix; + + public ReaderSuffixFilter(String fileSuffix) + { + this.fileSuffix = fileSuffix; + } + + public boolean filter(Object provider) + { + 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; + } + + return false; + } + } + + private static final class WriterFormatFilter implements ServiceRegistry.Filter + { + private String formatName; + + public WriterFormatFilter(String formatName) + { + this.formatName = formatName; + } + + public boolean filter(Object provider) + { + if (provider instanceof ImageWriterSpi) + { + ImageWriterSpi spi = (ImageWriterSpi) provider; + 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 WriterMIMETypeFilter implements ServiceRegistry.Filter + { + private String MIMEType; + + public WriterMIMETypeFilter(String MIMEType) + { + this.MIMEType = MIMEType; + } + + public boolean filter(Object provider) + { + if (provider instanceof ImageWriterSpi) + { + ImageWriterSpi spi = (ImageWriterSpi) provider; + String[] mimetypes = spi.getMIMETypes(); + + for (int i = mimetypes.length - 1; i >= 0; --i) + if (MIMEType.equals(mimetypes[i])) + return true; + } + + return false; + } + } + + private static final class WriterSuffixFilter implements ServiceRegistry.Filter + { + private String fileSuffix; + + public WriterSuffixFilter(String fileSuffix) + { + this.fileSuffix = fileSuffix; + } + + public boolean filter(Object provider) + { + if (provider instanceof ImageWriterSpi) + { + ImageWriterSpi spi = (ImageWriterSpi) provider; + String[] suffixes = spi.getFileSuffixes(); + + for (int i = suffixes.length - 1; i >= 0; --i) + if (fileSuffix.equals(suffixes[i])) + return true; + } + + return false; + } + } + + 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 TranscoderFilter(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<ImageReader> + { + Iterator<ImageReaderSpi> it; + Object readerExtension; + + public ImageReaderIterator(Iterator<ImageReaderSpi> it, + Object readerExtension) + { + this.it = it; + this.readerExtension = readerExtension; + } + + public ImageReaderIterator(Iterator<ImageReaderSpi> it) + { + this.it = it; + } + + public boolean hasNext() + { + return it.hasNext(); + } + + public ImageReader next() + { + try + { + ImageReaderSpi spi = it.next(); + return (readerExtension == null + ? spi.createReaderInstance() + : spi.createReaderInstance(readerExtension)); + } + catch (IOException e) + { + return null; + } + } + + public void remove() + { + throw new UnsupportedOperationException(); + } + } + + private static final class ImageWriterIterator + implements Iterator<ImageWriter> + { + Iterator<ImageWriterSpi> it; + Object writerExtension; + + public ImageWriterIterator(Iterator<ImageWriterSpi> it, + Object writerExtension) + { + this.it = it; + this.writerExtension = writerExtension; + } + + public ImageWriterIterator(Iterator<ImageWriterSpi> it) + { + this.it = it; + } + + public boolean hasNext() + { + return it.hasNext(); + } + + public ImageWriter next() + { + try + { + ImageWriterSpi spi = it.next(); + return (writerExtension == null + ? spi.createWriterInstance() + : spi.createWriterInstance(writerExtension)); + } + catch (IOException e) + { + return null; + } + } + + public void remove() + { + throw new UnsupportedOperationException(); + } + } + + private static File cacheDirectory; + private static boolean useCache = true; + + private static Iterator<ImageReader> getReadersByFilter(Class<ImageReaderSpi> type, + ServiceRegistry.Filter filter, + Object readerExtension) + { + try + { + Iterator<ImageReaderSpi> it + = getRegistry().getServiceProviders(type, filter, true); + return new ImageReaderIterator(it, readerExtension); + } + catch (IllegalArgumentException e) + { + return Collections.EMPTY_SET.iterator(); + } + } + + private static Iterator<ImageWriter> getWritersByFilter(Class<ImageWriterSpi> type, + ServiceRegistry.Filter filter, + Object writerExtension) + { + try + { + Iterator<ImageWriterSpi> it + = getRegistry().getServiceProviders(type, filter, true); + return new ImageWriterIterator(it, writerExtension); + } + catch (IllegalArgumentException e) + { + return Collections.EMPTY_SET.iterator(); + } + } + + /** + * 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<ImageReader> getImageReadersByFormatName(String formatName) + { + if (formatName == null) + throw new IllegalArgumentException("formatName may not be null"); + + return getReadersByFilter(ImageReaderSpi.class, + new ReaderFormatFilter(formatName), + 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<ImageReader> getImageReadersByMIMEType(String MIMEType) + { + if (MIMEType == null) + throw new IllegalArgumentException("MIMEType may not be null"); + + return getReadersByFilter(ImageReaderSpi.class, + new ReaderMIMETypeFilter(MIMEType), + 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<ImageReader> getImageReadersBySuffix(String fileSuffix) + { + if (fileSuffix == null) + throw new IllegalArgumentException("formatName may not be null"); + + return getReadersByFilter(ImageReaderSpi.class, + new ReaderSuffixFilter(fileSuffix), + 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<ImageWriter> getImageWritersByFormatName(String formatName) + { + if (formatName == null) + throw new IllegalArgumentException("formatName may not be null"); + + return getWritersByFilter(ImageWriterSpi.class, + new WriterFormatFilter(formatName), + 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<ImageWriter> getImageWritersByMIMEType(String MIMEType) + { + if (MIMEType == null) + throw new IllegalArgumentException("MIMEType may not be null"); + + return getWritersByFilter(ImageWriterSpi.class, + new WriterMIMETypeFilter(MIMEType), + 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<ImageWriter> getImageWritersBySuffix(String fileSuffix) + { + if (fileSuffix == null) + throw new IllegalArgumentException("fileSuffix may not be null"); + + return getWritersByFilter(ImageWriterSpi.class, + new WriterSuffixFilter(fileSuffix), + 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 + { + Iterator it = + getRegistry().getServiceProviders(ImageReaderSpi.class, true); + ArrayList result = new ArrayList(); + + while (it.hasNext()) + { + ImageReaderSpi spi = (ImageReaderSpi) it.next(); + String[] names = spi.getFormatNames(); + + for (int i = names.length - 1; i >= 0; --i) + result.add(names[i]); + } + + return (String[]) result.toArray(new String[result.size()]); + } + catch (IllegalArgumentException e) + { + return new String[0]; + } + } + + /** + * Retrieve all the MIME types supported by the collection of + * registered image readers. + * + * @return an array of MIME types + */ + public static String[] getReaderMIMETypes() + { + try + { + Iterator it = + getRegistry().getServiceProviders(ImageReaderSpi.class, true); + ArrayList result = new ArrayList(); + + while (it.hasNext()) + { + ImageReaderSpi spi = (ImageReaderSpi) it.next(); + String[] names = spi.getMIMETypes(); + + for (int i = names.length - 1; i >= 0; --i) + result.add(names[i]); + } + + return (String[]) result.toArray(new String[result.size()]); + } + catch (IllegalArgumentException e) + { + return new String[0]; + } + } + + private static IIORegistry getRegistry() + { + 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 + { + Iterator it = + getRegistry().getServiceProviders(ImageWriterSpi.class, true); + ArrayList result = new ArrayList(); + + while (it.hasNext()) + { + ImageWriterSpi spi = (ImageWriterSpi) it.next(); + String[] names = spi.getFormatNames(); + + for (int i = names.length - 1; i >= 0; --i) + result.add(names[i]); + } + + return (String[]) result.toArray(new String[result.size()]); + } + catch (IllegalArgumentException e) + { + return new String[0]; + } + } + + /** + * Retrieve all the MIME types supported by the collection of + * registered image writers. + * + * @return an array of MIME types + */ + public static String[] getWriterMIMETypes() + { + try + { + Iterator it = + getRegistry().getServiceProviders(ImageWriterSpi.class, true); + ArrayList result = new ArrayList(); + + while (it.hasNext()) + { + ImageWriterSpi spi = (ImageWriterSpi) it.next(); + String[] names = spi.getMIMETypes(); + + for (int i = names.length - 1; i >= 0; --i) + result.add(names[i]); + } + + return (String[]) result.toArray(new String[result.size()]); + } + catch (IllegalArgumentException e) + { + return new String[0]; + } + } + + /** + * Rescans the application classpath for ImageIO service providers + * and registers them. + */ + public static void scanForPlugins() + { + 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()) + throw new IllegalArgumentException("cacheDirectory must be a directory"); + + cacheDirectory.canWrite(); + } + + 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; + } + + /** + * 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()) + { + ImageWriter w = (ImageWriter) writers.next(); + try + { + w.setOutput(output); + } + catch (IllegalArgumentException e) + { + continue; + } + + w.write(null, img, null); + w.dispose(); + output.close(); + return true; + } + 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()) + { + ImageReaderSpi spi = (ImageReaderSpi) providers.next(); + if (spi.canDecodeInput(stream)) + { + ImageReader reader = spi.createReaderInstance(); + reader.setInput(stream); + return reader.read(0, null); + } + } + 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.getClass().equals(spi.getInputClass())) + { + foundSpi = spi; + break; + } + } + + return foundSpi == null ? null : + 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 output 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 (output.getClass().equals(spi.getOutputClass())) + { + foundSpi = spi; + break; + } + } + + return foundSpi == null ? null : + foundSpi.createOutputStreamInstance (output, + 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 = writer.getOriginatingProvider(); + + String[] readerSpiNames = spi.getImageReaderSpiNames(); + + ImageReader r = null; + + if (readerSpiNames != null) + { + try + { + Class readerClass = Class.forName (readerSpiNames[0]); + r = (ImageReader) readerClass.newInstance (); + } + catch (Exception e) + { + return null; + } + } + return r; + } + + /** + * 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<ImageReader> getImageReaders (Object input) + { + if (input == null) + throw new IllegalArgumentException ("null argument"); + + Iterator<ImageReaderSpi> spiIterator + = getRegistry().getServiceProviders (ImageReaderSpi.class, + new ReaderObjectFilter(input), + true); + return new ImageReaderIterator(spiIterator); + } + + /** + * 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<ImageWriter> getImageWriters (ImageTypeSpecifier type, + String formatName) + { + if (type == null || formatName == null) + throw new IllegalArgumentException ("null argument"); + + final Iterator<ImageWriterSpi> spiIterator + = getRegistry().getServiceProviders (ImageWriterSpi.class, + new WriterObjectFilter(type, + formatName), + true); + return new ImageWriterIterator(spiIterator); + } + + /** + * 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 = reader.getOriginatingProvider(); + + String[] writerSpiNames = spi.getImageWriterSpiNames(); + + ImageWriter w = null; + + if (writerSpiNames != null) + { + try + { + Class writerClass = Class.forName (writerSpiNames[0]); + w = (ImageWriter) writerClass.newInstance (); + } + catch (Exception e) + { + return null; + } + } + return w; + } + + /** + * 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<ImageTranscoder> getImageTranscoders (ImageReader reader, + ImageWriter writer) + { + if (reader == null || writer == null) + throw new IllegalArgumentException ("null argument"); + + final Iterator<ImageTranscoderSpi> spiIterator + = getRegistry().getServiceProviders (ImageTranscoderSpi.class, + new TranscoderFilter (reader, + writer), + true); + return new Iterator<ImageTranscoder>() + { + public boolean hasNext() + { + return spiIterator.hasNext(); + } + + public ImageTranscoder next() + { + return spiIterator.next().createTranscoderInstance(); + } + + public void remove() + { + throw new UnsupportedOperationException(); + } + }; + } +} diff --git a/libjava/classpath/javax/imageio/ImageReadParam.java b/libjava/classpath/javax/imageio/ImageReadParam.java new file mode 100644 index 000000000..8a31253e8 --- /dev/null +++ b/libjava/classpath/javax/imageio/ImageReadParam.java @@ -0,0 +1,128 @@ +/* ImageReadParam.java -- + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.imageio; + +import java.awt.Dimension; +import java.awt.image.BufferedImage; + +/** + * DOCUMENT ME + * + * @author Michel Koch (konqueror@gmx.de) + */ +public class ImageReadParam extends IIOParam +{ + protected boolean canSetSourceRenderSize; + protected BufferedImage destination; + protected int[] destinationBands; + protected int minProgressivePass; + protected int numProgressivePasses = Integer.MAX_VALUE; + protected Dimension sourceRenderSize; + + public ImageReadParam() + { + } + + public boolean canSetSourceRenderSize() + { + return canSetSourceRenderSize; + } + + public BufferedImage getDestination() + { + return destination; + } + + public int[] getDestinationBands() + { + return destinationBands; + } + + public int getSourceMaxProgressivePass() + { + if (getSourceNumProgressivePasses() == Integer.MAX_VALUE) + return Integer.MAX_VALUE; + + return getSourceMinProgressivePass() + getSourceNumProgressivePasses() - 1; + } + + public int getSourceMinProgressivePass() + { + return minProgressivePass; + } + + public int getSourceNumProgressivePasses() + { + return numProgressivePasses; + } + + public Dimension getSourceRenderSize() + { + return sourceRenderSize; + } + + public void setDestination(BufferedImage destination) + { + this.destination = destination; + } + + public void setDestinationBands(int[] destinationBands) + { + this.destinationBands = destinationBands; + } + + public void setSourceProgressivePasses(int minPass, int numPasses) + { + this.minProgressivePass = minPass; + this.numProgressivePasses = numPasses; + } + + public void setSourceRenderSize(Dimension size) + throws UnsupportedOperationException + { + if (! canSetSourceRenderSize()) + throw new UnsupportedOperationException + ("setting source render size not supported"); + + if (size.width <= 0 || size.height <= 0) + throw new IllegalArgumentException("negative dimension not allowed"); + + sourceRenderSize = size; + } +} diff --git a/libjava/classpath/javax/imageio/ImageReader.java b/libjava/classpath/javax/imageio/ImageReader.java new file mode 100644 index 000000000..14e935994 --- /dev/null +++ b/libjava/classpath/javax/imageio/ImageReader.java @@ -0,0 +1,2035 @@ +/* ImageReader.java -- Decodes raster images. + Copyright (C) 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +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.ResourceBundle; +import java.util.MissingResourceException; +import java.util.Set; + +import javax.imageio.event.IIOReadProgressListener; +import javax.imageio.event.IIOReadUpdateListener; +import javax.imageio.event.IIOReadWarningListener; +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; + + /** + * 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<IIOReadProgressListener> 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<IIOReadUpdateListener> updateListeners = null; + + /** + * A list of installed warning listeners. Initially null, meaning + * no installed listeners. + */ + protected List<IIOReadWarningListener> warningListeners = null; + + /** + * A list of warning locales corresponding with the list of + * installed warning listeners. Initially null, meaning no locales. + */ + protected List<Locale> 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; + if (progressListeners == null) + progressListeners = new ArrayList (); + 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) + return; + if (updateListeners == null) + updateListeners = new ArrayList (); + 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) + return; + if (warningListeners == null) + warningListeners = new ArrayList (); + 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) + return null; + + 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<ImageTypeSpecifier> 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) + { + Class[] okClasses = originatingProvider.getInputTypes(); + if (okClasses == null) + { + if (!(input instanceof ImageInputStream)) + throw new IllegalArgumentException(); + } + else + { + boolean classOk = false; + for (int i = 0; i < okClasses.length; ++i) + if (okClasses[i].isInstance(input)) + classOk = true; + if (!classOk) + throw new IllegalArgumentException(); + } + + this.input = input; + this.seekForwardOnly = seekForwardOnly; + this.ignoreMetadata = ignoreMetadata; + 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 in 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); + } + + /** + * 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(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() + { + if (progressListeners != null) + { + Iterator it = progressListeners.iterator(); + + while (it.hasNext()) + { + IIOReadProgressListener listener = + (IIOReadProgressListener) it.next(); + listener.imageComplete (this); + } + } + } + + /** + * 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) + { + if (progressListeners != null) + { + Iterator it = progressListeners.iterator(); + + while (it.hasNext()) + { + IIOReadProgressListener listener = + (IIOReadProgressListener) it.next(); + listener.imageProgress(this, percentageDone); + } + } + } + /** + * 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) + { + if (progressListeners != null) + { + Iterator it = progressListeners.iterator(); + + while (it.hasNext()) + { + IIOReadProgressListener listener = + (IIOReadProgressListener) it.next(); + listener.imageStarted(this, imageIndex); + } + } + } + + /** + * 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) + { + if (updateListeners != null) + { + Iterator it = updateListeners.iterator(); + + while (it.hasNext()) + { + IIOReadUpdateListener listener = (IIOReadUpdateListener) it.next(); + listener.imageUpdate(this, image, minX, minY, width, height, + periodX, periodY, bands); + } + } + } + + /** + * 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) + { + if (updateListeners != null) + { + Iterator it = updateListeners.iterator(); + + while (it.hasNext()) + { + IIOReadUpdateListener listener = (IIOReadUpdateListener) it.next(); + listener.passComplete(this, image); + } + } + } + + /** + * 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) + { + if (updateListeners != null) + { + Iterator it = updateListeners.iterator(); + + while (it.hasNext()) + { + IIOReadUpdateListener listener = (IIOReadUpdateListener) it.next(); + listener.passStarted(this, image, pass, minPass, maxPass, minX, + minY, periodX, periodY, bands); + } + } + } + + /** + * Notifies all installed read progress listeners that image loading + * has been aborted by calling their readAborted methods. + */ + protected void processReadAborted() + { + if (progressListeners != null) + { + Iterator it = progressListeners.iterator(); + + while (it.hasNext()) + { + IIOReadProgressListener listener = + (IIOReadProgressListener) it.next(); + listener.readAborted(this); + } + } + } + /** + * Notifies all installed read progress listeners, by calling their + * sequenceComplete methods, that a sequence of images has completed + * loading. + */ + protected void processSequenceComplete() + { + if (progressListeners != null) + { + Iterator it = progressListeners.iterator(); + + while (it.hasNext()) + { + IIOReadProgressListener listener = + (IIOReadProgressListener) it.next(); + listener.sequenceComplete(this); + } + } + } + + /** + * 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) + { + + if (progressListeners != null) + { + Iterator it = progressListeners.iterator(); + + while (it.hasNext()) + { + IIOReadProgressListener listener = + (IIOReadProgressListener) it.next(); + listener.sequenceStarted(this, minIndex); + } + } + } + + /** + * Notifies all installed read progress listeners, by calling their + * thumbnailComplete methods, that a thumbnail has completed + * loading. + */ + protected void processThumbnailComplete() + { + if (progressListeners != null) + { + Iterator it = progressListeners.iterator(); + + while (it.hasNext()) + { + IIOReadProgressListener listener = + (IIOReadProgressListener) it.next(); + listener.thumbnailComplete(this); + } + } + } + + /** + * 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) + { + if (updateListeners != null) + { + Iterator it = updateListeners.iterator(); + + while (it.hasNext()) + { + IIOReadUpdateListener listener = (IIOReadUpdateListener) it.next(); + listener.thumbnailPassComplete(this, thumbnail); + } + } + } + + /** + * 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, + int[] bands) + { + if (updateListeners != null) + { + Iterator it = updateListeners.iterator(); + + while (it.hasNext()) + { + IIOReadUpdateListener listener = (IIOReadUpdateListener) it.next(); + listener.thumbnailPassStarted(this, thumbnail, pass, minPass, + maxPass, minX, minY, periodX, + periodY, bands); + } + } + } + + /** + * 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) + { + if (progressListeners != null) + { + Iterator it = progressListeners.iterator(); + + while (it.hasNext()) + { + IIOReadProgressListener listener = + (IIOReadProgressListener) it.next(); + listener.thumbnailProgress(this, percentageDone); + } + } + } + + /** + * 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) + { + if (progressListeners != null) + { + Iterator it = progressListeners.iterator(); + + while (it.hasNext()) + { + IIOReadProgressListener listener = + (IIOReadProgressListener) it.next(); + listener.thumbnailStarted(this, imageIndex, thumbnailIndex); + } + } + } + + /** + * 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) + { + if (updateListeners != null) + { + Iterator it = updateListeners.iterator(); + + while (it.hasNext()) + { + IIOReadUpdateListener listener = (IIOReadUpdateListener) it.next(); + listener.thumbnailUpdate(this, image, minX, minY, width, height, + periodX, periodY, bands); + } + } + } + + /** + * Notifies all installed warning listeners, by calling their + * warningOccurred methods, that a warning message has been raised. + * + * @param warning the warning message + * + * @exception IllegalArgumentException if warning is null + */ + protected void processWarningOccurred(String warning) + { + if (warning == null) + throw new IllegalArgumentException ("null argument"); + if (warningListeners != null) + { + Iterator it = warningListeners.iterator(); + + while (it.hasNext()) + { + IIOReadWarningListener listener = + (IIOReadWarningListener) it.next(); + listener.warningOccurred(this, warning); + } + } + } + + /** + * Notify all installed warning listeners, by calling their + * warningOccurred methods, that a warning message has been raised. + * The warning message is retrieved from a resource bundle, using + * the given basename and keyword. + * + * @param baseName the basename of the resource from which to + * retrieve the warning message + * @param keyword the keyword used to retrieve the warning from the + * resource bundle + * + * @exception IllegalArgumentException if either baseName or keyword + * is null + * @exception IllegalArgumentException if no resource bundle is + * found using baseName + * @exception IllegalArgumentException if the given keyword produces + * no results from the resource bundle + * @exception IllegalArgumentException if the retrieved object is + * not a String + */ + protected void processWarningOccurred(String baseName, + String keyword) + { + if (baseName == null || keyword == null) + throw new IllegalArgumentException ("null argument"); + + ResourceBundle b = null; + + try + { + b = ResourceBundle.getBundle(baseName, getLocale()); + } + catch (MissingResourceException e) + { + throw new IllegalArgumentException ("no resource bundle found"); + } + + Object str = null; + + try + { + str = b.getObject(keyword); + } + catch (MissingResourceException e) + { + throw new IllegalArgumentException ("no results found for keyword"); + } + + if (! (str instanceof String)) + throw new IllegalArgumentException ("retrieved object not a String"); + + String warning = (String) str; + + if (warningListeners != null) + { + Iterator it = warningListeners.iterator(); + + while (it.hasNext()) + { + IIOReadWarningListener listener = + (IIOReadWarningListener) it.next(); + listener.warningOccurred(this, warning); + } + } + } + + /** + * 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 = null; + } + + /** + * Uninstall all read update listeners. + */ + public void removeAllIIOReadUpdateListeners() + { + updateListeners = null; + } + + /** + * Uninstall all read warning listeners. + */ + public void removeAllIIOReadWarningListeners() + { + warningListeners = null; + } + + /** + * Uninstall the given read progress listener. + * + * @param listener the listener to remove + */ + public void removeIIOReadProgressListener(IIOReadProgressListener listener) + { + if (listener == null) + return; + if (progressListeners != null) + { + progressListeners.remove(listener); + } + } + + /** + * Uninstall the given read update listener. + * + * @param listener the listener to remove + */ + public void removeIIOReadUpdateListener(IIOReadUpdateListener listener) + { + if (listener == null) + return; + + if (updateListeners != null) + { + updateListeners.remove(listener); + } + } + + /** + * Uninstall the given read warning listener. + * + * @param listener the listener to remove + */ + public void removeIIOReadWarningListener(IIOReadWarningListener listener) + { + if (listener == null) + return; + if (warningListeners != null) + { + 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) + { + // Check if its a valid locale. + boolean found = false; + + if (availableLocales != null) + for (int i = availableLocales.length - 1; i >= 0; --i) + if (availableLocales[i].equals(locale)) + found = true; + + if (! found) + throw new IllegalArgumentException("looale not available"); + } + + 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 param 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<ImageTypeSpecifier> imageTypes, + int width, + int height) + throws IIOException + { + 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<String> 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 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<String> 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 imageIndex 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 imageIndex the index of the image frame to read + * @param 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 params 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<IIOImage> readAll (Iterator<? extends ImageReadParam> 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 imageIndex the index of the image frame to read + * @param 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/libjava/classpath/javax/imageio/ImageTranscoder.java b/libjava/classpath/javax/imageio/ImageTranscoder.java new file mode 100644 index 000000000..352bb18b7 --- /dev/null +++ b/libjava/classpath/javax/imageio/ImageTranscoder.java @@ -0,0 +1,102 @@ +/* ImageTranscoder.java -- Image metadata transcoder. + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +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/libjava/classpath/javax/imageio/ImageTypeSpecifier.java b/libjava/classpath/javax/imageio/ImageTypeSpecifier.java new file mode 100644 index 000000000..da229610a --- /dev/null +++ b/libjava/classpath/javax/imageio/ImageTypeSpecifier.java @@ -0,0 +1,561 @@ +/* ImageTypeSpecifier.java -- + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +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) + throw new IllegalArgumentException("colorModel may not be null"); + + if (sampleModel == null) + throw new IllegalArgumentException("sampleModel may not be null"); + + if (!colorModel.isCompatibleSampleModel(sampleModel)) + throw new IllegalArgumentException + ("sample Model not compatible with colorModel"); + + this.colorModel = colorModel; + 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) + throw new IllegalArgumentException("image may not be null"); + + this.colorModel = image.getColorModel(); + 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 bankOffsets 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 width width of the buffered image, in pixels + * @param height 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 createIndexed (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/libjava/classpath/javax/imageio/ImageWriteParam.java b/libjava/classpath/javax/imageio/ImageWriteParam.java new file mode 100644 index 000000000..1c400e1ea --- /dev/null +++ b/libjava/classpath/javax/imageio/ImageWriteParam.java @@ -0,0 +1,495 @@ +/* ImageWriteParam.java -- + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.imageio; + +import java.awt.Dimension; +import java.util.Locale; + +/** + * DOCUMENT ME + */ +public class ImageWriteParam extends IIOParam +{ + + /** + * Can be passed to setTilingMode, setProgressiveMode and + * setCompressionMode to disable feature. + */ + public static final int MODE_DISABLED = 0; + + /** + * Can be passed to setTilingMode, setProgressiveMode and + * setCompressionMode to enable feature. + */ + public static final int MODE_DEFAULT = 1; + + /** + * Can be passed to setTilingMode, setCompressionMode to disable feature. + */ + public static final int MODE_EXPLICIT = 2; + + /** + * Can be passed to setTilingMode, setProgressiveMode and + * setCompressionMode to enable feature. + */ + public static final int MODE_COPY_FROM_METADATA = 3; + + /** + * True if tiling grid offset parameters can be set. + */ + protected boolean canOffsetTiles; + + /** + * True if this writer can write images using compression. + */ + protected boolean canWriteCompressed; + + /** + * True if images can be written as a progressive sequence + * of increasing quality. + */ + protected boolean canWriteProgressive; + + /** + * True if tile width and height parameters can be set. + */ + protected boolean canWriteTiles; + + /** + * Controls compression settings, which must be set to one of the four + * MODE_* values. + */ + protected int compressionMode = MODE_COPY_FROM_METADATA; + + /** + * Contains the current compression quality setting. + */ + protected float compressionQuality; + + /** + * Contains the name of the current compression type. + */ + protected String compressionType; + + /** + * Array of the names of the available compression types. + */ + protected String[] compressionTypes; + + /** + * Localizes compression type names and quality descriptions, + * or null to use default Locale. + */ + protected Locale locale; + + /** + * Preferred tile size range pairs. + */ + protected Dimension[] preferredTileSizes; + + /** + * The mode controlling progressive encoding, which must + * be set to one of the four MODE_* values, except + * MODE_EXPLICIT. + */ + protected int progressiveMode = MODE_COPY_FROM_METADATA; + + /** + * The amount by which the tile grid origin should be offset + * horizontally from the image origin if tiling has been set. + */ + protected int tileGridXOffset; + + /** + * The amount by which the tile grid origin should be offset + * vertically from the image origin if tiling has been set. + */ + protected int tileGridYOffset; + + /** + * The height of each tile if tiling has been set. + */ + protected int tileHeight; + + /** + * The width of each tile if tiling has been set. + */ + protected int tileWidth; + + /** + * The mode controlling tiling settings, which must be + * set to one of the four MODE_* values. + */ + protected int tilingMode; + + /** + * True if the tiling parameters have been specified. + */ + protected boolean tilingSet; + + /** + * Creates an empty <code>ImageWriteParam</code> object. + * The subclass is responsible to initialize all fields. + */ + protected ImageWriteParam() + { + // Do nothing here. + } + + /** + * Creates an <code>ImageWriteParam</code> object with the given locale. + * + * @param locale the locale to use for user visible strings + */ + public ImageWriteParam(Locale locale) + { + this.locale = locale; + } + + public float getBitRate(float quality) + { + checkNotExplicitCompression(); + checkCompressionTypesSet(); + + return -1.0f; + } + + private void checkSupportsCompression() + { + if (! canWriteCompressed()) + throw new UnsupportedOperationException("compression not supported"); + } + + private void checkNotExplicitCompression() + { + if (getCompressionMode() != MODE_EXPLICIT) + throw new IllegalStateException("compression mode is not MODE_EXPLICIT"); + } + + private void checkCompressionTypesSet() + { + if (getCompressionType() == null + && getCompressionTypes() != null) + throw new IllegalStateException("no compression type set"); + } + + private void checkSupportsProgressiveEncoding() + { + if (! canWriteProgressive()) + throw new UnsupportedOperationException + ("progressive output not supported"); + } + + private void checkSupportsTiling() + { + if (! canWriteTiles()) + throw new UnsupportedOperationException("tiling not supported"); + } + + private void checkNotExplicitTiling() + { + if (getTilingMode() != MODE_EXPLICIT) + throw new IllegalStateException("tiling mode not MODE_EXPLICIT"); + } + + private void checkTilingInitialized() + { + if (! tilingSet) + throw new IllegalStateException("tiling parameters not set"); + } + + private void checkMode(int mode) + { + if (mode < MODE_DISABLED || mode > MODE_COPY_FROM_METADATA) + throw new IllegalArgumentException("mode not supported"); + } + + public boolean canOffsetTiles() + { + return canOffsetTiles; + } + + public boolean canWriteCompressed() + { + return canWriteCompressed; + } + + public boolean canWriteProgressive() + { + return canWriteProgressive; + } + + public boolean canWriteTiles() + { + return canWriteTiles; + } + + public int getCompressionMode() + { + checkSupportsCompression(); + + return compressionMode; + } + + public float getCompressionQuality() + { + checkNotExplicitCompression(); + checkCompressionTypesSet(); + + return compressionQuality; + } + + public String[] getCompressionQualityDescriptions() + { + checkNotExplicitCompression(); + checkCompressionTypesSet(); + + return null; + } + + public float[] getCompressionQualityValues() + { + checkNotExplicitCompression(); + checkCompressionTypesSet(); + + return null; + } + + public String getCompressionType() + { + checkNotExplicitCompression(); + + return compressionType; + } + + public String[] getCompressionTypes() + { + checkSupportsCompression(); + + return compressionTypes != null ? (String[]) compressionTypes.clone() : null; + } + + public Locale getLocale() + { + return locale; + } + + public String getLocalizedCompressionTypeName() + { + checkNotExplicitCompression(); + checkCompressionTypesSet(); + + return getCompressionType(); + } + + public Dimension[] getPreferredTileSizes() + { + checkSupportsTiling(); + + return preferredTileSizes; + } + + public int getProgressiveMode() + { + checkSupportsProgressiveEncoding(); + + return progressiveMode; + } + + public int getTileGridXOffset() + { + checkNotExplicitTiling(); + checkTilingInitialized(); + + return tileGridXOffset; + } + + public int getTileGridYOffset() + { + checkNotExplicitTiling(); + checkTilingInitialized(); + + return tileGridYOffset; + } + + public int getTileHeight() + { + checkNotExplicitTiling(); + checkTilingInitialized(); + + return tileHeight; + } + + public int getTileWidth() + { + checkNotExplicitTiling(); + checkTilingInitialized(); + + return tileWidth; + } + + public int getTilingMode() + { + checkSupportsTiling(); + + return tilingMode; + } + + public boolean isCompressionLossless() + { + checkNotExplicitCompression(); + checkCompressionTypesSet(); + + return true; + } + + public void setCompressionMode(int mode) + { + checkSupportsCompression(); + checkMode(mode); + + compressionMode = mode; + + if (mode == MODE_EXPLICIT) + unsetCompression(); + } + + public void setCompressionQuality(float quality) + { + checkNotExplicitCompression(); + checkCompressionTypesSet(); + + if (quality < 0.0f || quality > 1.0f) + throw new IllegalArgumentException("quality out of range"); + + compressionQuality = quality; + } + + public void setCompressionType(String compressionType) + { + checkNotExplicitCompression(); + + String[] types = getCompressionTypes(); + + if (types == null) + throw new UnsupportedOperationException("no settable compression types"); + + if (compressionType == null) + this.compressionType = null; + + for (int i = types.length - 1; i >= 0; --i) + if (types[i].equals(compressionType)) + { + this.compressionType = compressionType; + return; + } + + throw new IllegalArgumentException("unknown compression type"); + } + + public void setProgressiveMode(int mode) + { + checkSupportsProgressiveEncoding(); + checkMode(mode); + + progressiveMode = mode; + } + + public void setTiling(int tileWidth, int tileHeight, + int tileGridXOffset, int tileGridYOffset) + { + checkNotExplicitTiling(); + + if (! canOffsetTiles + && tileGridXOffset != 0 + && tileGridYOffset != 0) + throw new UnsupportedOperationException("tile offsets not supported"); + + if (tileWidth < 0 || tileHeight < 0) + throw new IllegalArgumentException("negative tile dimension"); + + if (preferredTileSizes != null) + { + boolean found = false; + + for (int i = 0; i < preferredTileSizes.length; i += 2) + { + if (tileWidth >= preferredTileSizes[i].width + && tileWidth <= preferredTileSizes[i + 1].width + && tileHeight >= preferredTileSizes[i].height + && tileHeight <= preferredTileSizes[i + 1].height) + found = true; + } + + if (! found) + throw new IllegalArgumentException("illegal tile size"); + } + + this.tilingSet = true; + this.tileWidth = tileWidth; + this.tileHeight = tileHeight; + this.tileGridXOffset = tileGridXOffset; + this.tileGridYOffset = tileGridYOffset; + } + + public void setTilingMode(int mode) + { + checkSupportsTiling(); + checkMode(mode); + tilingMode = mode; + } + + public void unsetCompression() + { + checkNotExplicitCompression(); + + compressionType = null; + compressionQuality = 1.0F; + } + + public void unsetTiling() + { + checkNotExplicitTiling(); + + tileWidth = 0; + tileHeight = 0; + tileGridXOffset = 0; + tileGridYOffset = 0; + } +} diff --git a/libjava/classpath/javax/imageio/ImageWriter.java b/libjava/classpath/javax/imageio/ImageWriter.java new file mode 100644 index 000000000..7a7f45e6f --- /dev/null +++ b/libjava/classpath/javax/imageio/ImageWriter.java @@ -0,0 +1,1390 @@ +/* ImageWriter.java -- Encodes raster images. + Copyright (C) 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.imageio; + +import java.awt.Dimension; +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.ResourceBundle; +import java.util.MissingResourceException; + +import javax.imageio.event.IIOWriteProgressListener; +import javax.imageio.event.IIOWriteWarningListener; +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 = null; + + /** + * The current locale used to localize warning messages, or null if + * no locale has been set. + */ + protected Locale locale = null; + + /** + * The image writer SPI that instantiated this writer. + */ + protected ImageWriterSpi originatingProvider = null; + + /** + * An ImageInputStream to which image data is written. + */ + protected Object output = null; + + /** + * A list of installed progress listeners. Initially null, meaning + * no installed listeners. + */ + protected List<IIOWriteProgressListener> progressListeners = null; + + /** + * A list of installed warning listeners. Initially null, meaning + * no installed listeners. + */ + protected List<IIOWriteWarningListener> warningListeners = null; + + /** + * A list of warning locales corresponding with the list of + * installed warning listeners. Initially null, meaning no locales. + */ + protected List<Locale> warningLocales = null; + + /** + * 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) + return; + if (progressListeners == null) + progressListeners = new ArrayList (); + 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) + return; + if (warningListeners == null) + warningListeners = new ArrayList (); + 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 + { + checkOutputSet(); + 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 + { + checkOutputSet(); + 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 + { + checkOutputSet(); + 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 + { + checkOutputSet(); + 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 + { + checkOutputSet(); + 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 + { + checkOutputSet(); + 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 + { + checkOutputSet(); + 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; + } + + /** + * 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, + IIOMetadata imageMetadata) + { + return null; + } + + /** + * Notifies all installed write progress listeners that image + * loading has completed by calling their imageComplete methods. + */ + protected void processImageComplete() + { + if (progressListeners != null) + { + Iterator it = progressListeners.iterator(); + + while (it.hasNext()) + { + IIOWriteProgressListener listener = + (IIOWriteProgressListener) it.next(); + listener.imageComplete(this); + } + } + } + + /** + * 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) + { + if (progressListeners != null) + { + Iterator it = progressListeners.iterator(); + + while (it.hasNext()) + { + IIOWriteProgressListener listener = + (IIOWriteProgressListener) it.next(); + listener.imageProgress(this, percentageDone); + } + } + } + + /** + * 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) + { + if (progressListeners != null) + { + Iterator it = progressListeners.iterator(); + + while (it.hasNext()) + { + IIOWriteProgressListener listener = + (IIOWriteProgressListener) it.next(); + listener.imageStarted(this, imageIndex); + } + } + } + + /** + * Notifies all installed write progress listeners, by calling their + * thumbnailComplete methods, that a thumbnail has completed + * loading. + */ + protected void processThumbnailComplete() + { + if (progressListeners != null) + { + Iterator it = progressListeners.iterator(); + + while (it.hasNext()) + { + IIOWriteProgressListener listener = + (IIOWriteProgressListener) it.next(); + listener.thumbnailComplete(this); + } + } + } + + /** + * 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) + { + if (progressListeners != null) + { + Iterator it = progressListeners.iterator(); + + while (it.hasNext()) + { + IIOWriteProgressListener listener = + (IIOWriteProgressListener) it.next(); + listener.thumbnailProgress(this, percentageDone); + } + } + } + + /** + * 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) + { + if (progressListeners != null) + { + Iterator it = progressListeners.iterator(); + + while (it.hasNext()) + { + IIOWriteProgressListener listener = + (IIOWriteProgressListener) it.next(); + listener.thumbnailStarted(this, imageIndex, thumbnailIndex); + } + } + } + + /** + * 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 + * + * @exception IllegalArgumentException if warning is null + */ + protected void processWarningOccurred(int imageIndex, String warning) + { + if (warningListeners != null) + { + Iterator it = warningListeners.iterator(); + + while (it.hasNext()) + { + IIOWriteWarningListener listener = + (IIOWriteWarningListener) it.next(); + listener.warningOccurred(this, imageIndex, warning); + } + } + } + + /** + * Notify all installed warning listeners, by calling their + * warningOccurred methods, that a warning message has been raised. + * The warning message is retrieved from a resource bundle, using + * the given basename and keyword. + * + * @param imageIndex the index of the image that was being written + * when the warning was raised + * @param baseName the basename of the resource from which to + * retrieve the warning message + * @param keyword the keyword used to retrieve the warning from the + * resource bundle + * + * @exception IllegalArgumentException if either baseName or keyword + * is null + * @exception IllegalArgumentException if no resource bundle is + * found using baseName + * @exception IllegalArgumentException if the given keyword produces + * no results from the resource bundle + * @exception IllegalArgumentException if the retrieved object is + * not a String + */ + protected void processWarningOccurred(int imageIndex, + String baseName, + String keyword) + { + if (baseName == null || keyword == null) + throw new IllegalArgumentException ("null argument"); + + ResourceBundle b = null; + + try + { + b = ResourceBundle.getBundle(baseName, getLocale()); + } + catch (MissingResourceException e) + { + throw new IllegalArgumentException ("no resource bundle found"); + } + + Object str = null; + + try + { + str = b.getObject(keyword); + } + catch (MissingResourceException e) + { + throw new IllegalArgumentException ("no results found for keyword"); + } + + if (! (str instanceof String)) + throw new IllegalArgumentException ("retrieved object not a String"); + + String warning = (String) str; + + if (warningListeners != null) + { + Iterator it = warningListeners.iterator(); + + while (it.hasNext()) + { + IIOWriteWarningListener listener = + (IIOWriteWarningListener) it.next(); + listener.warningOccurred(this, imageIndex, warning); + } + } + } + + /** + * Notifies all installed write progress listeners that image + * loading has been aborted by calling their writeAborted methods. + */ + protected void processWriteAborted() + { + if (progressListeners != null) + { + Iterator it = progressListeners.iterator(); + + while (it.hasNext()) + { + IIOWriteProgressListener listener = + (IIOWriteProgressListener) it.next(); + listener.writeAborted(this); + } + } + } + + /** + * Uninstall all write progress listeners. + */ + public void removeAllIIOWriteProgressListeners() + { + if (progressListeners != null) + { + progressListeners.clear(); + } + } + + /** + * Uninstall all write warning listeners. + */ + public void removeAllIIOWriteWarningListeners() + { + if (progressListeners != null) + { + progressListeners.clear(); + } + } + + /** + * Uninstall the given write progress listener. + * + * @param listener the listener to remove + */ + public void removeIIOWriteProgressListener (IIOWriteProgressListener listener) + { + if (listener == null) + return; + if (progressListeners != null) + { + progressListeners.remove(listener); + } + } + /** + * Uninstall the given write warning listener. + * + * @param listener the listener to remove + */ + public void removeIIOWriteWarningListener (IIOWriteWarningListener listener) + { + if (listener == null) + return; + if (warningListeners != null) + { + warningListeners.remove(listener); + } + } + /** + * Reset this writer's internal state. + */ + public void reset() + { + setOutput(null); + setLocale(null); + removeAllIIOWriteWarningListeners(); + removeAllIIOWriteProgressListeners(); + 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) + { + // Check if its a valid locale. + boolean found = false; + + if (availableLocales != null) + for (int i = availableLocales.length - 1; i >= 0; --i) + if (availableLocales[i].equals(locale)) + found = true; + + if (! found) + throw new IllegalArgumentException("looale not available"); + } + + 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 output 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) + { + // Check if its a valid output object. + boolean found = false; + Class[] types = null; + + if (originatingProvider != null) + types = originatingProvider.getOutputTypes(); + + if (types != null) + for (int i = types.length - 1; i >= 0; --i) + if (types[i].isInstance(output)) + found = true; + + if (! found) + throw new IllegalArgumentException("output type not available"); + } + + 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<? extends BufferedImage> 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<? extends BufferedImage> 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 param 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/libjava/classpath/javax/imageio/event/IIOReadProgressListener.java b/libjava/classpath/javax/imageio/event/IIOReadProgressListener.java new file mode 100644 index 000000000..0eea61017 --- /dev/null +++ b/libjava/classpath/javax/imageio/event/IIOReadProgressListener.java @@ -0,0 +1,117 @@ +/* IIOReadProgressListener.java -- + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.imageio.event; + +import java.util.EventListener; + +import javax.imageio.ImageReader; + +public interface IIOReadProgressListener extends EventListener +{ + /** + * Reports that the current image read operation has completed. + * + * @param source the <code>ImageReader</code> object calling this method + */ + void imageComplete(ImageReader source); + + /** + * Reports the approximate percentage of completions of this image read + * operation. + * + * @param source the <code>ImageReader</code> object calling this method + * @param percentageDone the approximate percentage of encoding completed + */ + void imageProgress(ImageReader source, float percentageDone); + + /** + * Reports that the current image read operation has started. + * + * @param source the <code>ImageReader</code> object calling this method + * @param imageIndex the index of the image to read + */ + void imageStarted(ImageReader source, int imageIndex); + + /** + * Reports that a read operation has been aborted. + * + * @param source the <code>ImageReader</code> object calling this method + */ + void readAborted(ImageReader source); + + /** + * Reports that a sequence of read operationshas completed. + * + * @param source the <code>ImageReader</code> object calling this method + */ + void sequenceComplete(ImageReader source); + + /** + * Reports that a sequence of read operations is beginning. + * + * @param source the <code>ImageReader</code> object calling this method + * @param minIndex the index of the first image to be read + */ + void sequenceStarted(ImageReader source, int minIndex); + + /** + * Reports that a thumbnail read operation has completed. + * + * @param source the <code>ImageReader</code> object calling this method + */ + void thumbnailComplete(ImageReader source); + + /** + * Reports the approximate percentage of completion of a thumbnail read + * operation. + * + * @param source the <code>ImageReader</code> object calling this method + * @param percentageDone the approximate percentage of encoding completed + */ + void thumbnailProgress(ImageReader source, float percentageDone); + + /** + * Reports that a thumbnail read operation is beginning. + * + * @param source the <code>ImageReader</code> object calling this method + * @param imageIndex the index of the image being read + * @param thumbnailIndex the index of the thumbnail being read + */ + void thumbnailStarted(ImageReader source, int imageIndex, int thumbnailIndex); +} diff --git a/libjava/classpath/javax/imageio/event/IIOReadUpdateListener.java b/libjava/classpath/javax/imageio/event/IIOReadUpdateListener.java new file mode 100644 index 000000000..a20a99ebc --- /dev/null +++ b/libjava/classpath/javax/imageio/event/IIOReadUpdateListener.java @@ -0,0 +1,133 @@ +/* IIOReadUpdateListener.java -- + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.imageio.event; + +import java.awt.image.BufferedImage; +import java.util.EventListener; + +import javax.imageio.ImageReader; + +public interface IIOReadUpdateListener extends EventListener +{ + /** + * Reports that a given region of the image has been updated. + * + * @param source the <code>ImageReader</code> object calling this method + * @param image the BufferedImage being updated + * @param minX the X coordinate of the leftmost updated column of pixels + * @param minY the Y coordinate of the uppermost updated row of pixels + * @param width the number of updated pixels horizontally + * @param height the number of updated pixels vertically + * @param periodX the horizontal spacing between updated pixels; a value of 1 means no gaps + * @param periodY the vertical spacing between updated pixels; a value of 1 means no gaps + * @param bands an array of <code>int</code>s indicating which bands are being updated + */ + void imageUpdate(ImageReader source, BufferedImage image, int minX, + int minY, int width, int height, int periodX, int periodY, + int[] bands); + + /** + * Reports that the current read operation has completed a progressive pass. + * + * @param source the <code>ImageReader</code> object calling this method + * @param image the BufferedImage being updated + */ + void passComplete(ImageReader source, BufferedImage image); + + /** + * Reports that the current read operation is about to begin a progressive pass. + * + * @param source the <code>ImageReader</code> object calling this method + * @param image the BufferedImage being updated + * @param pass the numer of the pass that is about to begin, starting with 0 + * @param minPass the index of the first pass that will be decoded + * @param maxPass the index of the last pass that will be decoded + * @param minX the X coordinate of the leftmost updated column of pixels + * @param minY the Y coordinate of the uppermost updated row of pixels + * @param periodX the horizontal spacing between updated pixels; a value of 1 means no gaps + * @param periodY the vertical spacing between updated pixels; a value of 1 means no gaps + * @param bands an array of <code>int</code>s indicating which bands are being updated + */ + void passStarted(ImageReader source, BufferedImage image, int pass, + int minPass, int maxPass, int minX, int minY, int periodX, + int periodY, int[] bands); + + /** + * Reports that the current thumbnail read operation has completed a progressive pass. + * + * @param source the <code>ImageReader</code> object calling this method + * @param image the BufferedImage being updated + */ + void thumbnailPassComplete(ImageReader source, BufferedImage image); + + /** + * Reports that the current thumbnail read operation is about to begin a progressive pass. + * + * @param source the <code>ImageReader</code> object calling this method + * @param image the BufferedImage being updated + * @param pass the numer of the pass that is about to begin, starting with 0 + * @param minPass the index of the first pass that will be decoded + * @param maxPass the index of the last pass that will be decoded + * @param minX the X coordinate of the leftmost updated column of pixels + * @param minY the Y coordinate of the uppermost updated row of pixels + * @param periodX the horizontal spacing between updated pixels; a value of 1 means no gaps + * @param periodY the vertical spacing between updated pixels; a value of 1 means no gaps + * @param bands an array of <code>int</code>s indicating which bands are being updated + */ + void thumbnailPassStarted(ImageReader source, BufferedImage image, int pass, + int minPass, int maxPass, int minX, int minY, + int periodX, int periodY, int[] bands); + + /** + * Reports that a given region of a thumbnail image has been updated. + * + * @param source the <code>ImageReader</code> object calling this method + * @param image the BufferedImage being updated + * @param minX the X coordinate of the leftmost updated column of pixels + * @param minY the Y coordinate of the uppermost updated row of pixels + * @param width the number of updated pixels horizontally + * @param height the number of updated pixels vertically + * @param periodX the horizontal spacing between updated pixels; a value of 1 means no gaps + * @param periodY the vertical spacing between updated pixels; a value of 1 means no gaps + * @param bands an array of <code>int</code>s indicating which bands are being updated + */ + void thumbnailUpdate(ImageReader source, BufferedImage image, int minX, + int minY, int width, int height, int periodX, + int periodY, int[] bands); +} diff --git a/libjava/classpath/javax/imageio/event/IIOReadWarningListener.java b/libjava/classpath/javax/imageio/event/IIOReadWarningListener.java new file mode 100644 index 000000000..e89735035 --- /dev/null +++ b/libjava/classpath/javax/imageio/event/IIOReadWarningListener.java @@ -0,0 +1,55 @@ +/* IIOReadProgressListener.java -- + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.imageio.event; + +import java.util.EventListener; + +import javax.imageio.ImageReader; + +public interface IIOReadWarningListener extends EventListener +{ + /** + * Reports the occurrence of a non-fatal error in decoding. + * Decoding will continue after this method is called. + * + * @param source the <code>ImageReader</code> object calling this method + * @param warning the warning + */ + void warningOccurred(ImageReader source, String warning); +} diff --git a/libjava/classpath/javax/imageio/event/IIOWriteProgressListener.java b/libjava/classpath/javax/imageio/event/IIOWriteProgressListener.java new file mode 100644 index 000000000..d75976205 --- /dev/null +++ b/libjava/classpath/javax/imageio/event/IIOWriteProgressListener.java @@ -0,0 +1,102 @@ +/* IIOWriteProgressListener.java -- + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.imageio.event; + +import java.util.EventListener; + +import javax.imageio.ImageWriter; + +public interface IIOWriteProgressListener extends EventListener +{ + /** + * Reports that an image write operation has completed. + * + * @param source the <code>ImageWriter</code> object calling this method + */ + void imageComplete(ImageWriter source); + + /** + * Reports the approximate percentage of completion of an image write + * operation. + * + * @param source the <code>ImageWriter</code> object calling this method + * @param percentageDone the approximate percentage of decoding completed + */ + void imageProgress(ImageWriter source, float percentageDone); + + /** + * Reports that a thumbnail write operation has started. + * + * @param source the <code>ImageWriter</code> object calling this method + * @param imageIndex the index of the image being written + */ + void imageStarted(ImageWriter source, int imageIndex); + + /** + * Reports that a thumbnail write operation has completed. + * + * @param source the <code>ImageWriter</code> object calling this method + */ + void thumbnailComplete(ImageWriter source); + + /** + * Reports the approximate percentage of completion of a thumbnail write + * operation. + * + * @param source the <code>ImageWriter</code> object calling this method + * @param percentageDone the approximate percentage of decoding completed + */ + void thumbnailProgress(ImageWriter source, float percentageDone); + + /** + * Reports that a thumbnail write operation is beginning. + * + * @param source the <code>ImageWriter</code> object calling this method + * @param imageIndex the index of the image being written + * @param thumnailIndex the index of the thumbnail being written + */ + void thumbnailStarted(ImageWriter source, int imageIndex, int thumnailIndex); + + /** + * Reports that an image write operation is aborted. + * + * @param source the <code>ImageWriter</code> object calling this method + */ + void writeAborted(ImageWriter source); +} diff --git a/libjava/classpath/javax/imageio/event/IIOWriteWarningListener.java b/libjava/classpath/javax/imageio/event/IIOWriteWarningListener.java new file mode 100644 index 000000000..3c4e3bd99 --- /dev/null +++ b/libjava/classpath/javax/imageio/event/IIOWriteWarningListener.java @@ -0,0 +1,60 @@ +/* IIOWriteWarningListener.java -- + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.imageio.event; + +import java.util.EventListener; + +import javax.imageio.ImageWriter; + +/** + * @author Michael Koch (konqueror@gmx.de) + */ +public interface IIOWriteWarningListener extends EventListener +{ + /** + * Reports the occurrence of a non-fatal error in encoding. + * Encoding will continue after this method is called. + * + * @param source the <code>ImageWriter</code> object calling this method + * @param imageIndex the index of the image generating this warning, + * starting with 0 + * @param warning the warning + */ + void warningOccurred(ImageWriter source, int imageIndex, String warning); +} diff --git a/libjava/classpath/javax/imageio/event/package.html b/libjava/classpath/javax/imageio/event/package.html new file mode 100644 index 000000000..69171d276 --- /dev/null +++ b/libjava/classpath/javax/imageio/event/package.html @@ -0,0 +1,46 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> +<!-- package.html - describes classes in javax.imageio.event package. + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. --> + +<html> +<head><title>GNU Classpath - javax.imageio.event</title></head> + +<body> +<p></p> + +</body> +</html> diff --git a/libjava/classpath/javax/imageio/metadata/IIOInvalidTreeException.java b/libjava/classpath/javax/imageio/metadata/IIOInvalidTreeException.java new file mode 100644 index 000000000..b79b8cf96 --- /dev/null +++ b/libjava/classpath/javax/imageio/metadata/IIOInvalidTreeException.java @@ -0,0 +1,68 @@ +/* IIOInvalidTreeException.java -- + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.imageio.metadata; + +import javax.imageio.IIOException; + +import org.w3c.dom.Node; + +public class IIOInvalidTreeException extends IIOException +{ + private static final long serialVersionUID = -1314083172544132777L; + + protected Node offendingNode; + + public IIOInvalidTreeException(String message, Node offendingNode) + { + super(message); + this.offendingNode = offendingNode; + } + + public IIOInvalidTreeException(String message, Throwable cause, + Node offendingNode) + { + super(message, cause); + this.offendingNode = offendingNode; + } + + public Node getOffendingNode() + { + return offendingNode; + } +} diff --git a/libjava/classpath/javax/imageio/metadata/IIOMetadata.java b/libjava/classpath/javax/imageio/metadata/IIOMetadata.java new file mode 100644 index 000000000..b898b9942 --- /dev/null +++ b/libjava/classpath/javax/imageio/metadata/IIOMetadata.java @@ -0,0 +1,323 @@ +/* IIOMetadata.java -- + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.imageio.metadata; + +import org.w3c.dom.Node; + +/** + * Represents metadata that describe an image or an image stream. + * Each ImageIO plugin will represent image data using an opaque + * object but all such objects should expose their internal + * information as a tree of IIOMetadataNodes. + * + * There are three formats of metadata that a plugin can support: + * + * <ul> + * <li>a "native" format</li> + * <li>a custom format</li> + * <li>a standard plugin-neutral format</li> + * </ul> + * + * If a plugin supports more than one format of metadata, the other + * formats can be retrieved by calling getMetadataFormatNames. + * + * The native format is used to transfer metadata from one image to + * another image of the same type, losslessly. + * + * The custom format describes the image metadata and exposes a tree + * of IIOMetadataNodes but its internal representation is specific to + * this plugin. + * + * The plugin-neutral format uses a generic tree structure as its + * internal representation. + * + * ImageTranscoders may be used to convert metadata understood by one + * plugin to metadata understood by another, however the conversion + * may be lossy. + * + * @author Michael Koch (konqueror@gmx.de) + * @author Thomas Fitzsimmons (fitzsim@redhat.com) + */ +public abstract class IIOMetadata +{ + protected IIOMetadataController controller; + protected IIOMetadataController defaultController; + protected String[] extraMetadataFormatClassNames; + protected String[] extraMetadataFormatNames; + protected String nativeMetadataFormatClassName; + protected String nativeMetadataFormatName; + protected boolean standardFormatSupported; + + /** + * Construct an IIOMetadata object. + */ + protected IIOMetadata() + { + // Do nothing here. + } + + /** + * Construct an IIOMetadata object. + * + * @param standardMetadataFormatSupported + * @param nativeMetadataFormatName + * @param nativeMetadataFormatClassName + * @param extraMetadataFormatNames + * @param extraMetadataFormatClassNames + * + * @throws IllegalArgumentException if extraMetadataFormatNames has length of + * zero or extraMetadataFormatNames and extraMetadataFormatClassNames are + * neither both null, not have the same length + */ + protected IIOMetadata(boolean standardMetadataFormatSupported, + String nativeMetadataFormatName, + String nativeMetadataFormatClassName, + String[] extraMetadataFormatNames, + String[] extraMetadataFormatClassNames) + { + if (extraMetadataFormatNames != null + && extraMetadataFormatNames.length == 0) + throw new IllegalArgumentException + ("extraMetadataFormatNames may not be empty"); + + if (((extraMetadataFormatNames == null) + && (extraMetadataFormatClassNames != null)) + || ((extraMetadataFormatNames != null) + && (extraMetadataFormatClassNames == null)) + || ((extraMetadataFormatNames != null) + && (extraMetadataFormatClassNames != null) + && (extraMetadataFormatNames.length != + extraMetadataFormatClassNames.length))) + throw new IllegalArgumentException + ("extraMetadataFormatNames and extraMetadataFormatClassNames " + + "have different lengths"); + + this.standardFormatSupported = standardMetadataFormatSupported; + this.nativeMetadataFormatName = nativeMetadataFormatName; + this.nativeMetadataFormatClassName = nativeMetadataFormatClassName; + this.extraMetadataFormatNames = extraMetadataFormatNames; + this.extraMetadataFormatClassNames = extraMetadataFormatClassNames; + } + + public boolean activateController() + { + if (! hasController()) + return false; + + return getDefaultController().activate(this); + } + + public IIOMetadataController getController() + { + return controller; + } + + public IIOMetadataController getDefaultController() + { + return defaultController; + } + + public String[] getExtraMetadataFormatNames() + { + return (String[]) extraMetadataFormatNames.clone(); + } + + public IIOMetadataFormat getMetadataFormat(String formatName) + { + if (formatName == null) + throw new IllegalArgumentException("formatName may not be null"); + + String formatClassName = null; + + if (isStandardMetadataFormatSupported() + && formatName.equals(nativeMetadataFormatName)) + formatClassName = nativeMetadataFormatClassName; + else + { + String[] extraFormatNames = getExtraMetadataFormatNames(); + + for (int i = extraFormatNames.length - 1; i >= 0; --i) + if (extraFormatNames[i].equals(formatName)) + { + formatClassName = extraFormatNames[i]; + break; + } + } + + if (formatClassName == null) + throw new IllegalArgumentException("unknown format"); + + IIOMetadataFormat format; + + try + { + format = (IIOMetadataFormat) Class.forName(formatClassName) + .newInstance(); + } + catch (Exception e) + { + IllegalStateException ise = new IllegalStateException(); + ise.initCause(e); + throw ise; + } + + return format; + } + + public String[] getMetadataFormatNames() + { + String[] formatNames = getExtraMetadataFormatNames(); + + if (isStandardMetadataFormatSupported()) + { + // Combine native metadata format name and extra metadata format names + // into one String array. + String[] tmp = new String[formatNames.length + 1]; + tmp[0] = getNativeMetadataFormatName(); + + for (int i = 1; i < tmp.length; ++i) + tmp[i] = formatNames[i - 1]; + + formatNames = tmp; + } + + return formatNames; + } + + public String getNativeMetadataFormatName() + { + return nativeMetadataFormatName; + } + + public boolean hasController() + { + return getController() != null; + } + + public abstract boolean isReadOnly(); + + public boolean isStandardMetadataFormatSupported() + { + return standardFormatSupported; + } + + public abstract void reset(); + + public void setController(IIOMetadataController controller) + { + this.controller = controller; + } + + public abstract Node getAsTree (String formatName); + + protected IIOMetadataNode getStandardChromaNode () + { + return null; + } + + protected IIOMetadataNode getStandardCompressionNode () + { + return null; + } + + protected IIOMetadataNode getStandardDataNode () + { + return null; + } + + protected IIOMetadataNode getStandardDimensionNode () + { + return null; + } + + protected IIOMetadataNode getStandardDocumentNode () + { + return null; + } + + protected IIOMetadataNode getStandardTextNode () + { + return null; + } + + protected IIOMetadataNode getStandardTileNode () + { + return null; + } + + protected IIOMetadataNode getStandardTransparencyNode () + { + return null; + } + + private void appendChild (IIOMetadataNode node, + IIOMetadataNode child) + { + if (child != null) + node.appendChild(child); + } + + protected final IIOMetadataNode getStandardTree () + { + IIOMetadataNode node = new IIOMetadataNode(); + + appendChild (node, getStandardChromaNode()); + appendChild (node, getStandardCompressionNode()); + appendChild (node, getStandardDataNode()); + appendChild (node, getStandardDimensionNode()); + appendChild (node, getStandardDocumentNode()); + appendChild (node, getStandardTextNode()); + appendChild (node, getStandardTileNode()); + appendChild (node, getStandardTransparencyNode()); + + return node; + } + + public abstract void mergeTree (String formatName, + Node root) + throws IIOInvalidTreeException; + + public void setFromTree (String formatName, Node root) + throws IIOInvalidTreeException + { + reset(); + + mergeTree (formatName, root); + } +} diff --git a/libjava/classpath/javax/imageio/metadata/IIOMetadataController.java b/libjava/classpath/javax/imageio/metadata/IIOMetadataController.java new file mode 100644 index 000000000..86e544386 --- /dev/null +++ b/libjava/classpath/javax/imageio/metadata/IIOMetadataController.java @@ -0,0 +1,47 @@ +/* IIOMetadataController.java -- + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.imageio.metadata; + +/** + * @author Michael Koch (konqueror@gmx.de) + */ +public interface IIOMetadataController +{ + boolean activate(IIOMetadata metadata); +} diff --git a/libjava/classpath/javax/imageio/metadata/IIOMetadataFormat.java b/libjava/classpath/javax/imageio/metadata/IIOMetadataFormat.java new file mode 100644 index 000000000..15f2ceb0b --- /dev/null +++ b/libjava/classpath/javax/imageio/metadata/IIOMetadataFormat.java @@ -0,0 +1,124 @@ +/* IIOMetadataFormat.java -- + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.imageio.metadata; + +import java.util.Locale; + +import javax.imageio.ImageTypeSpecifier; + +/** + * @author Michael Koch (konqueror@gmx.de) + */ +public interface IIOMetadataFormat +{ + int CHILD_POLICY_ALL = 1; + int CHILD_POLICY_CHOICE = 3; + int CHILD_POLICY_EMPTY = 0; + int CHILD_POLICY_MAX = 5; + int CHILD_POLICY_REPEAT = 5; + int CHILD_POLICY_SEQUENCE = 4; + int CHILD_POLICY_SOME = 2; + int DATATYPE_BOOLEAN = 1; + int DATATYPE_DOUBLE = 4; + int DATATYPE_FLOAT = 3; + int DATATYPE_INTEGER = 2; + int DATATYPE_STRING = 0; + int VALUE_ARBITRARY = 1; + int VALUE_ENUMERATION = 16; + int VALUE_LIST = 32; + int VALUE_NONE = 0; + int VALUE_RANGE = 2; + int VALUE_RANGE_MAX_INCLUSIVE = 10; + int VALUE_RANGE_MAX_INCLUSIVE_MASK = 8; + int VALUE_RANGE_MIN_INCLUSIVE = 6; + int VALUE_RANGE_MIN_INCLUSIVE_MASK = 4; + int VALUE_RANGE_MIN_MAX_INCLUSIVE = 14; + + boolean canNodeAppear (String elementName, ImageTypeSpecifier imageType); + + int getAttributeDataType (String elementName, String attrName); + + String getAttributeDefaultValue (String elementName, String attrName); + + String getAttributeDescription (String elementName, String attrName, Locale locale); + + String[] getAttributeEnumerations (String elementName, String attrName); + + int getAttributeListMaxLength (String elementName, String attrName); + + int getAttributeListMinLength (String elementName, String attrName); + + String getAttributeMaxValue (String elementName, String attrName); + + String getAttributeMinValue (String elementName, String attrName); + + String[] getAttributeNames (String elementName); + + int getAttributeValueType (String elementName, String attrName); + + String[] getChildNames (String elementName); + + int getChildPolicy (String elementName); + + String getElementDescription (String elementName, Locale locale); + + int getElementMaxChildren (String elementName); + + int getElementMinChildren (String elementName); + + int getObjectArrayMaxLength (String elementName); + + int getObjectArrayMinLength (String elementName); + + Class<?> getObjectClass (String elementName); + + Object getObjectDefaultValue (String elementName); + + Object[] getObjectEnumerations (String elementName); + + Comparable<?> getObjectMaxValue (String elementName); + + Comparable<?> getObjectMinValue (String elementName); + + int getObjectValueType (String elementName); + + String getRootName(); + + boolean isAttributeRequired (String elementName, String attrName); +} diff --git a/libjava/classpath/javax/imageio/metadata/IIOMetadataFormatImpl.java b/libjava/classpath/javax/imageio/metadata/IIOMetadataFormatImpl.java new file mode 100644 index 000000000..efea723f9 --- /dev/null +++ b/libjava/classpath/javax/imageio/metadata/IIOMetadataFormatImpl.java @@ -0,0 +1,881 @@ +/* IIOMetadataFormatImpl.java -- + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.imageio.metadata; + +import org.w3c.dom.Attr; +import org.w3c.dom.Element; +import org.w3c.dom.NamedNodeMap; +import org.w3c.dom.NodeList; +import org.w3c.dom.TypeInfo; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; +import java.util.List; +import java.util.Locale; +import java.util.ResourceBundle; +import java.util.MissingResourceException; +import javax.imageio.ImageTypeSpecifier; + +public abstract class IIOMetadataFormatImpl implements IIOMetadataFormat +{ + /** + * The standard metadata format name constant set to + * "javax_imageio_1.0". + */ + public static final String standardMetadataFormatName = "javax_imageio_1.0"; + + private String rootName; + + // These maps assume that each element name is unique. + + private Map nodes = new HashMap(); + + // A mapping from element name to child policy. + private Map childPolicies = new HashMap(); + + // A mapping from element name to the permissible number of + // children. Values in this map are length-two integer arrays; the + // first index is the minimum bound, the second index is the maximum + // bound. + private Map childRanges = new HashMap(); + + private String resourceBaseName; + + // Package-private so that it may be used in IIOMetadataNode. + static class IIOMetadataNodeAttr extends IIOMetadataNode + implements Attr + { + protected Element owner; + protected String name; + protected int dataType; + protected boolean required; + protected String defaultValue; + + public IIOMetadataNodeAttr (Element owner, + String name, + String defaultValue) + { + this (owner, name, IIOMetadataFormat.DATATYPE_STRING, + true, defaultValue); + } + + public IIOMetadataNodeAttr (Element owner, + String name, + int dataType, + boolean required, + String defaultValue) + { + this.owner = owner; + this.name = name; + this.dataType = dataType; + this.required = required; + this.defaultValue = defaultValue; + } + + public String getName () + { + return name; + } + + public Element getOwnerElement () + { + return owner; + } + + public int getDataType () + { + return dataType; + } + + public TypeInfo getSchemaTypeInfo () + { + return null; + } + + public boolean getSpecified () + { + return false; + } + + public String getValue () + { + return defaultValue; + } + + public boolean isId() + { + return false; + } + + public void setValue (String value) + { + } + + // new methods + + public boolean isRequired () + { + return required; + } + } + + private class IIOMetadataNodeAttrEnumerated extends IIOMetadataNodeAttr + { + protected List enumeratedValues; + + public IIOMetadataNodeAttrEnumerated (Element owner, + String name, + int dataType, + boolean required, + String defaultValue, + List enumeratedValues) + { + super (owner, name, dataType, required, defaultValue); + this.enumeratedValues = new ArrayList (enumeratedValues); + } + + public Object[] getEnumerations () + { + return enumeratedValues.toArray (); + } + } + + private class IIOMetadataNodeAttrBounded extends IIOMetadataNodeAttr + { + protected String minValue; + protected String maxValue; + protected boolean minInclusive; + protected boolean maxInclusive; + + public IIOMetadataNodeAttrBounded (Element owner, + String name, + int dataType, + boolean required, + String defaultValue, + String minValue, + String maxValue, + boolean minInclusive, + boolean maxInclusive) + { + super (owner, name, dataType, required, defaultValue); + this.minValue = minValue; + this.maxValue = maxValue; + this.minInclusive = minInclusive; + this.maxInclusive = maxInclusive; + } + + public String getMinValue () + { + return minValue; + } + + public String getMaxValue () + { + return maxValue; + } + } + + private class IIOMetadataNodeAttrList extends IIOMetadataNodeAttr + { + protected int listMinLength; + protected int listMaxLength; + + public IIOMetadataNodeAttrList (Element owner, + String name, + int dataType, + boolean required, + int listMinLength, + int listMaxLength) + { + super (owner, name, dataType, required, null); + this.listMinLength = listMinLength; + this.listMaxLength = listMaxLength; + } + + public int getListMinLength () + { + return listMinLength; + } + + public int getListMaxLength () + { + return listMaxLength; + } + } + + private class NodeObject + { + protected Element owner; + protected Class classType; + protected boolean required; + protected Object defaultValue; + protected int valueType; + + public NodeObject (Element owner, + Class classType, + boolean required, + Object defaultValue) + { + this.owner = owner; + this.classType = classType; + this.required = required; + this.defaultValue = defaultValue; + valueType = IIOMetadataFormat.VALUE_ARBITRARY; + } + + public int getValueType () + { + return valueType; + } + + public Class getClassType () + { + return classType; + } + + public Element getOwnerElement () + { + return owner; + } + + public Object getDefaultValue () + { + return defaultValue; + } + + public boolean isRequired () + { + return required; + } + } + + private class NodeObjectEnumerated extends NodeObject + { + protected List enumeratedValues; + + public NodeObjectEnumerated (Element owner, + Class classType, + boolean required, + Object defaultValue, + List enumeratedValues) + { + super (owner, classType, false, defaultValue); + this.enumeratedValues = enumeratedValues; + valueType = IIOMetadataFormat.VALUE_ENUMERATION; + } + + public Object[] getEnumerations () + { + return enumeratedValues.toArray(); + } + } + + private class NodeObjectBounded extends NodeObject + { + protected Comparable minValue; + protected Comparable maxValue; + protected boolean minInclusive; + protected boolean maxInclusive; + + public NodeObjectBounded (Element owner, + Class classType, + Object defaultValue, + Comparable minValue, + Comparable maxValue, + boolean minInclusive, + boolean maxInclusive) + { + super (owner, classType, false, defaultValue); + this.minValue = minValue; + this.maxValue = maxValue; + this.minInclusive = minInclusive; + this.maxInclusive = maxInclusive; + if (minInclusive) + { + if (maxInclusive) + valueType = IIOMetadataFormat.VALUE_RANGE_MIN_MAX_INCLUSIVE; + else + valueType = IIOMetadataFormat.VALUE_RANGE_MIN_INCLUSIVE; + } + else + { + if (maxInclusive) + valueType = IIOMetadataFormat.VALUE_RANGE_MAX_INCLUSIVE; + else + valueType = IIOMetadataFormat.VALUE_RANGE; + } + } + + public Comparable getMinValue () + { + return minValue; + } + + public Comparable getMaxValue () + { + return maxValue; + } + } + + private class NodeObjectArray extends NodeObject + { + protected Integer arrayMinLength; + protected Integer arrayMaxLength; + + public NodeObjectArray (Element owner, + Class classType, + int arrayMinLength, + int arrayMaxLength) + { + super (owner, classType, false, null); + this.arrayMinLength = new Integer (arrayMinLength); + this.arrayMaxLength = new Integer (arrayMaxLength); + valueType = IIOMetadataFormat.VALUE_LIST; + } + + public Comparable getArrayMinLength () + { + return arrayMinLength; + } + + public Comparable getArrayMaxLength () + { + return arrayMaxLength; + } + } + + /** + * Construct a blank IIOMetadataFormatImpl with the given root name + * and child policy. + * + * @param rootName the root element name + * @param childPolicy the child policy of the root element + * + * @exception IllegalArgumentException if rootName is null + * @exception IllegalArgumentException if childPolicy is + * CHILD_POLICY_REPEAT or if childPolicy is not a CHILD_POLICY + * constant + */ + public IIOMetadataFormatImpl (String rootName, int childPolicy) + { + if (rootName == null) + throw new IllegalArgumentException ("null argument"); + + if (childPolicy < IIOMetadataFormat.CHILD_POLICY_ALL + || childPolicy > IIOMetadataFormat.CHILD_POLICY_SOME + || childPolicy == IIOMetadataFormat.CHILD_POLICY_REPEAT) + throw new IllegalArgumentException ("wrong child policy"); + + nodes.put (rootName, new IIOMetadataNode (rootName)); + childPolicies.put (rootName, new Integer (childPolicy)); + this.rootName = rootName; + } + + /** + * Construct a blank IIOMetadataFormatImpl with the given root name, + * a child policy of CHILD_POLICY_REPEAT and the given minimum and + * maximum limits on the number of root element children. + * + * @param rootName the root element name + * @param minChildren the minimum number of children that this node + * can have + * @param maxChildren the maximum number of children that this node + * can have + * + * @exception IllegalArgumentException if rootName is null + * @exception IllegalArgumentException if minChildren is less than + * zero or greater than maxChildren + */ + public IIOMetadataFormatImpl (String rootName, + int minChildren, + int maxChildren) + { + if (rootName == null) + throw new IllegalArgumentException ("null argument"); + + if (minChildren < 0 || maxChildren < minChildren) + throw new IllegalArgumentException ("invalid min or max children argument"); + + nodes.put (rootName, new IIOMetadataNode (rootName)); + childPolicies.put (rootName, new Integer (IIOMetadataFormat.CHILD_POLICY_REPEAT)); + childRanges.put (rootName, new int [] { minChildren, maxChildren }); + this.rootName = rootName; + } + + protected void addAttribute (String elementName, + String attrName, + int dataType, + boolean required, + String defaultValue) + { + IIOMetadataNode node = (IIOMetadataNode) nodes.get (elementName); + node.setAttributeNode (new IIOMetadataNodeAttr (node, + attrName, + dataType, + required, + defaultValue)); + } + + protected void addAttribute (String elementName, + String attrName, + int dataType, + boolean required, + String defaultValue, + List<String> enumeratedValues) + { + IIOMetadataNode node = (IIOMetadataNode) nodes.get (elementName); + node.setAttributeNode (new IIOMetadataNodeAttrEnumerated (node, + attrName, + dataType, + required, + defaultValue, + enumeratedValues)); + } + + protected void addAttribute (String elementName, + String attrName, + int dataType, + boolean required, + String defaultValue, + String minValue, + String maxValue, + boolean minInclusive, + boolean maxInclusive) + { + IIOMetadataNode node = (IIOMetadataNode) nodes.get (elementName); + node.setAttributeNode (new IIOMetadataNodeAttrBounded (node, + attrName, + dataType, + required, + defaultValue, + minValue, + maxValue, + minInclusive, + maxInclusive)); + } + + protected void addAttribute (String elementName, + String attrName, + int dataType, + boolean required, + int listMinLength, + int listMaxLength) + { + IIOMetadataNode node = (IIOMetadataNode) nodes.get (elementName); + node.setAttributeNode (new IIOMetadataNodeAttrList (node, + attrName, + dataType, + required, + listMinLength, + listMaxLength)); + } + + protected void addBooleanAttribute (String elementName, + String attrName, + boolean hasDefaultValue, + boolean defaultValue) + { + IIOMetadataNode node = (IIOMetadataNode) nodes.get (elementName); + + List enumeratedValues = new ArrayList(); + enumeratedValues.add ("TRUE"); + enumeratedValues.add ("FALSE"); + + node.setAttributeNode (new IIOMetadataNodeAttrEnumerated (node, + attrName, + IIOMetadataFormat.DATATYPE_BOOLEAN, + hasDefaultValue, + defaultValue ? "TRUE" : "FALSE", + enumeratedValues)); + } + + protected void addChildElement (String elementName, String parentName) + { + IIOMetadataNode node = (IIOMetadataNode) nodes.get (parentName); + + node.appendChild (new IIOMetadataNode (elementName)); + childPolicies.put (elementName, new Integer (IIOMetadataFormat.CHILD_POLICY_REPEAT)); + } + + protected void addElement (String elementName, String parentName, int childPolicy) + { + IIOMetadataNode node = (IIOMetadataNode) nodes.get (parentName); + + node.appendChild (new IIOMetadataNode (elementName)); + childPolicies.put (elementName, new Integer (childPolicy)); + } + + protected void addElement (String elementName, String parentName, + int minChildren, int maxChildren) + { + addChildElement (elementName, parentName); + childRanges.put (elementName, new int [] { minChildren, maxChildren }); + } + + private void addNodeObject (IIOMetadataNode node, NodeObject o) + { + node.setUserObject (o); + } + + private NodeObject getNodeObject (IIOMetadataNode node) + { + return (NodeObject) node.getUserObject (); + } + + private void removeNodeObject (IIOMetadataNode node) + { + node.setUserObject (null); + } + + protected <T> void addObjectValue (String elementName, Class<T> classType, + boolean required, T defaultValue) + { + IIOMetadataNode node = (IIOMetadataNode) nodes.get (elementName); + addNodeObject (node, new NodeObject (node, + classType, + required, + defaultValue)); + } + + protected <T> void addObjectValue (String elementName, Class<T> classType, + boolean required, T defaultValue, + List<? extends T> enumeratedValues) + { + IIOMetadataNode node = (IIOMetadataNode) nodes.get (elementName); + addNodeObject (node, new NodeObjectEnumerated (node, + classType, + required, + defaultValue, + enumeratedValues)); + } + + protected <T extends Object & Comparable<? super T>> + void addObjectValue (String elementName, Class<T> classType, + T defaultValue, + Comparable<? super T> minValue, + Comparable<? super T> maxValue, + boolean minInclusive, + boolean maxInclusive) + { + IIOMetadataNode node = (IIOMetadataNode) nodes.get (elementName); + addNodeObject (node, new NodeObjectBounded (node, + classType, + defaultValue, + minValue, + maxValue, + minInclusive, + maxInclusive)); + } + + protected void addObjectValue (String elementName, Class<?> classType, + int arrayMinLength, int arrayMaxLength) + { + IIOMetadataNode node = (IIOMetadataNode) nodes.get (elementName); + addNodeObject (node, new NodeObjectArray (node, + classType, + arrayMinLength, + arrayMaxLength)); + } + + public String getRootName () + { + return rootName; + } + + protected String getResourceBaseName () + { + return resourceBaseName; + } + + public static IIOMetadataFormat getStandardFormatInstance () + { + // FIXME: populate this with the standard metadata format + return new IIOMetadataFormatImpl (standardMetadataFormatName, + IIOMetadataFormat.CHILD_POLICY_ALL) + { + public boolean canNodeAppear (String elementName, + ImageTypeSpecifier specifier) + { + return true; + } + }; + } + + public abstract boolean canNodeAppear (String elementName, + ImageTypeSpecifier specifier); + + protected void removeAttribute (String elementName, + String attrName) + { + IIOMetadataNode node = (IIOMetadataNode) nodes.get (elementName); + node.removeAttribute (attrName); + } + + protected void removeElement (String elementName) + { + nodes.remove (elementName); + } + + protected void removeObjectValue (String elementName) + { + IIOMetadataNode node = (IIOMetadataNode) nodes.get (elementName); + removeNodeObject (node); + } + + protected void setResourceBaseName (String resourceBaseName) + { + this.resourceBaseName = resourceBaseName; + } + + public int getAttributeDataType (String elementName, String attrName) + { + IIOMetadataNode node = (IIOMetadataNode) nodes.get (elementName); + IIOMetadataNodeAttr attr = (IIOMetadataNodeAttr) node.getAttributeNode (attrName); + return attr.getDataType (); + } + + public String getAttributeDefaultValue (String elementName, String attrName) + { + IIOMetadataNode node = (IIOMetadataNode) nodes.get (elementName); + IIOMetadataNodeAttr attr = (IIOMetadataNodeAttr) node.getAttributeNode (attrName); + return attr.getValue(); + } + + public String getAttributeDescription (String elementName, String attrName, Locale locale) + { + return getDescription (elementName + "/" + attrName, locale); + } + + public String[] getAttributeEnumerations (String elementName, String attrName) + { + IIOMetadataNode node = (IIOMetadataNode) nodes.get (elementName); + IIOMetadataNodeAttrEnumerated attr = + (IIOMetadataNodeAttrEnumerated) node.getAttributeNode (attrName); + + Object[] attrEnums = attr.getEnumerations(); + + String[] attrNames = new String[attrEnums.length]; + + for (int i = 0; i < attrEnums.length; i++) + { + attrNames[i] = (String) attrEnums[i]; + } + + return attrNames; + } + + public int getAttributeListMaxLength (String elementName, String attrName) + { + IIOMetadataNode node = (IIOMetadataNode) nodes.get (elementName); + IIOMetadataNodeAttrList attr = + (IIOMetadataNodeAttrList) node.getAttributeNode (attrName); + return attr.getListMaxLength(); + } + + public int getAttributeListMinLength (String elementName, String attrName) + { + IIOMetadataNode node = (IIOMetadataNode) nodes.get (elementName); + IIOMetadataNodeAttrList attr = + (IIOMetadataNodeAttrList) node.getAttributeNode (attrName); + return attr.getListMinLength(); + } + + public String getAttributeMaxValue (String elementName, String attrName) + { + IIOMetadataNode node = (IIOMetadataNode) nodes.get (elementName); + IIOMetadataNodeAttrBounded attr = + (IIOMetadataNodeAttrBounded) node.getAttributeNode (attrName); + return attr.getMaxValue(); + } + + public String getAttributeMinValue (String elementName, String attrName) + { + IIOMetadataNode node = (IIOMetadataNode) nodes.get (elementName); + IIOMetadataNodeAttrBounded attr = + (IIOMetadataNodeAttrBounded) node.getAttributeNode (attrName); + return attr.getMinValue(); + } + + public String[] getAttributeNames (String elementName) + { + IIOMetadataNode node = (IIOMetadataNode) nodes.get (elementName); + + NamedNodeMap attrNodes = node.getAttributes(); + + String[] attrNames = new String[attrNodes.getLength()]; + + for (int i = 0; i < attrNodes.getLength(); i++) + { + attrNames[i] = attrNodes.item (i).getLocalName(); + } + + return attrNames; + } + + public int getAttributeValueType (String elementName, String attrName) + { + IIOMetadataNode node = (IIOMetadataNode) nodes.get (elementName); + IIOMetadataNodeAttr attr = (IIOMetadataNodeAttr) node.getAttributeNode (attrName); + return attr.getDataType(); + } + + public String[] getChildNames (String elementName) + { + IIOMetadataNode node = (IIOMetadataNode) nodes.get (elementName); + + NodeList childNodes = node.getChildNodes(); + + String[] childNames = new String[childNodes.getLength()]; + + for (int i = 0; i < childNodes.getLength(); i++) + { + childNames[i] = childNodes.item (i).getLocalName(); + } + + return childNames; + } + + public int getChildPolicy (String elementName) + { + return ((Integer) childPolicies.get (elementName)).intValue(); + } + + private String getDescription (String resourceName, Locale locale) + { + if (resourceBaseName == null) + return null; + + Locale l = locale; + + if (l == null) + l = Locale.getDefault(); + + ResourceBundle bundle = ResourceBundle.getBundle (resourceBaseName, locale); + + String desc = null; + + if (bundle == null) + { + try + { + desc = bundle.getString (resourceName); + } + catch (MissingResourceException e) + { + desc = null; + } + } + + return desc; + } + + public String getElementDescription (String elementName, Locale locale) + { + return getDescription (elementName, locale); + } + + public int getElementMaxChildren (String elementName) + { + return ((int[]) childRanges.get (elementName))[1]; + } + + public int getElementMinChildren (String elementName) + { + return ((int[]) childRanges.get (elementName))[0]; + } + + public int getObjectArrayMaxLength (String elementName) + { + IIOMetadataNode node = (IIOMetadataNode) nodes.get (elementName); + return ((Integer) ((NodeObjectArray) getNodeObject (node)).getArrayMaxLength ()).intValue(); + } + + public int getObjectArrayMinLength (String elementName) + { + IIOMetadataNode node = (IIOMetadataNode) nodes.get (elementName); + return ((Integer) ((NodeObjectArray) getNodeObject (node)).getArrayMinLength ()).intValue(); + } + + public Class<?> getObjectClass (String elementName) + { + IIOMetadataNode node = (IIOMetadataNode) nodes.get (elementName); + return getNodeObject (node).getClassType (); + } + + public Object getObjectDefaultValue (String elementName) + { + IIOMetadataNode node = (IIOMetadataNode) nodes.get (elementName); + return getNodeObject (node).getDefaultValue (); + } + + public Object[] getObjectEnumerations (String elementName) + { + IIOMetadataNode node = (IIOMetadataNode) nodes.get (elementName); + return ((NodeObjectEnumerated) getNodeObject (node)).getEnumerations (); + } + + public Comparable<?> getObjectMaxValue (String elementName) + { + IIOMetadataNode node = (IIOMetadataNode) nodes.get (elementName); + return ((NodeObjectBounded) getNodeObject (node)).getMaxValue (); + } + + public Comparable<?> getObjectMinValue (String elementName) + { + IIOMetadataNode node = (IIOMetadataNode) nodes.get (elementName); + return ((NodeObjectBounded) getNodeObject (node)).getMinValue (); + } + + public int getObjectValueType (String elementName) + { + IIOMetadataNode node = (IIOMetadataNode) nodes.get (elementName); + NodeObject n = getNodeObject (node); + + if (n == null) + return IIOMetadataFormat.VALUE_NONE; + else + return n.getValueType (); + } + + public boolean isAttributeRequired (String elementName, String attrName) + { + IIOMetadataNode node = (IIOMetadataNode) nodes.get (elementName); + return ((IIOMetadataNodeAttr) node.getAttributeNode (attrName)).isRequired(); + } +} diff --git a/libjava/classpath/javax/imageio/metadata/IIOMetadataNode.java b/libjava/classpath/javax/imageio/metadata/IIOMetadataNode.java new file mode 100644 index 000000000..db3de2347 --- /dev/null +++ b/libjava/classpath/javax/imageio/metadata/IIOMetadataNode.java @@ -0,0 +1,709 @@ +/* IIOMetadataNode.java -- + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.imageio.metadata; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; + +import org.w3c.dom.Attr; +import org.w3c.dom.DOMException; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.NamedNodeMap; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.w3c.dom.TypeInfo; +import org.w3c.dom.UserDataHandler; +import javax.imageio.metadata.IIOMetadataFormatImpl.IIOMetadataNodeAttr; + +public class IIOMetadataNode + implements Element, NodeList +{ + private String name; + private HashMap attrs = new HashMap(); + private List children = new ArrayList(); + private IIOMetadataNode parent; + private Object obj; + + /** + * Simple NamedNodeMap class for IIOMetadataNode. + * + * @author jlquinn + */ + private class IIONamedNodeMap implements NamedNodeMap + { + HashMap attrs; + + /** + * @param attrs + * @param node + */ + public IIONamedNodeMap(HashMap attrs) + { + this.attrs = attrs; + } + + /* (non-Javadoc) + * @see org.w3c.dom.NamedNodeMap#getNamedItem(java.lang.String) + */ + public Node getNamedItem(String name) + { + return (Node)attrs.get(name); + } + + /* (non-Javadoc) + * @see org.w3c.dom.NamedNodeMap#setNamedItem(org.w3c.dom.Node) + */ + public Node setNamedItem(Node arg) throws DOMException + { + if (arg instanceof IIOMetadataNodeAttr) + { + IIOMetadataNodeAttr attr = (IIOMetadataNodeAttr) arg; + // The only code that can successfully do this is in this package. + if (attr.owner != null) + throw new DOMException(DOMException.INUSE_ATTRIBUTE_ERR, ""); + return (Node)attrs.put(attr.name, attr); + } + // Anything else gets treated as an invalid op. + throw new DOMException(DOMException.HIERARCHY_REQUEST_ERR, ""); + } + + /* (non-Javadoc) + * @see org.w3c.dom.NamedNodeMap#removeNamedItem(java.lang.String) + */ + public Node removeNamedItem(String name) throws DOMException + { + return (Node)attrs.remove(name); + } + + /* (non-Javadoc) + * @see org.w3c.dom.NamedNodeMap#item(int) + */ + public Node item(int index) + { + return (Node)attrs.values().toArray()[index]; + } + + /* (non-Javadoc) + * @see org.w3c.dom.NamedNodeMap#getLength() + */ + public int getLength() + { + return attrs.size(); + } + + /* (non-Javadoc) + * @see org.w3c.dom.NamedNodeMap#getNamedItemNS(java.lang.String, java.lang.String) + */ + public Node getNamedItemNS(String namespaceURI, String localName) + { + return getNamedItem(localName); + } + + /* (non-Javadoc) + * @see org.w3c.dom.NamedNodeMap#setNamedItemNS(org.w3c.dom.Node) + */ + public Node setNamedItemNS(Node arg) throws DOMException + { + return setNamedItem(arg); + } + + /* (non-Javadoc) + * @see org.w3c.dom.NamedNodeMap#removeNamedItemNS(java.lang.String, java.lang.String) + */ + public Node removeNamedItemNS(String namespaceURI, String localName) + throws DOMException + { + return removeNamedItem(localName); + } + } + + /** + * Simple NodeList implementation for IIOMetadataNode. + * + * @author jlquinn + * + */ + private class IIONodeList implements NodeList + { + List children = new ArrayList(); + + /* (non-Javadoc) + * @see org.w3c.dom.NodeList#item(int) + */ + public Node item(int index) + { + return (index < children.size()) ? (Node)children.get(index) : null; + } + + /* (non-Javadoc) + * @see org.w3c.dom.NodeList#getLength() + */ + public int getLength() + { + return children.size(); + } + } + + public IIOMetadataNode() + { + // Do nothing here. + } + + public IIOMetadataNode(String nodename) + { + name = nodename; + } + + public Object getUserObject() + { + return obj; + } + + public void setUserObject(Object o) + { + obj = o; + } + + public short compareDocumentPosition(Node other) + throws DOMException + { + return Element.DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC; + } + + /* (non-Javadoc) + * @see org.w3c.dom.Element#getAttribute(java.lang.String) + */ + public String getAttribute(String name) + { + Attr anode = (Attr) attrs.get(name); + return anode != null ? anode.getValue() : null; + } + + /* (non-Javadoc) + * @see org.w3c.dom.Element#getAttributeNode(java.lang.String) + */ + public Attr getAttributeNode(String name) + { + String val = getAttribute(name); + if (val != null) + return new IIOMetadataNodeAttr(this, name, val); + return null; + } + + /* (non-Javadoc) + * @see org.w3c.dom.Element#getAttributeNodeNS(java.lang.String, java.lang.String) + */ + public Attr getAttributeNodeNS(String namespaceURI, String localName) + { + return getAttributeNode(localName); + } + + /* (non-Javadoc) + * @see org.w3c.dom.Element#getAttributeNS(java.lang.String, java.lang.String) + */ + public String getAttributeNS(String namespaceURI, String localName) + { + return getAttribute(localName); + } + + public String getBaseURI() + { + return null; + } + + // Recursive function for assembling a node list. + private void getElementsRecurse(IIONodeList list, String name) + { + for (int i=0; i < children.size(); i++) + { + if (((Node)children.get(i)).getNodeName().equals(name)) + list.children.add(children.get(i)); + getElementsRecurse(list, name); + } + } + + /* (non-Javadoc) + * @see org.w3c.dom.Element#getElementsByTagName(java.lang.String) + */ + public NodeList getElementsByTagName(String name) + { + IIONodeList list = new IIONodeList(); + getElementsRecurse(list, name); + return list; + } + + /* (non-Javadoc) + * @see org.w3c.dom.Element#getElementsByTagNameNS(java.lang.String, java.lang.String) + */ + public NodeList getElementsByTagNameNS(String namespaceURI, String localName) + { + IIONodeList list = new IIONodeList(); + getElementsRecurse(list, name); + return list; + } + + /* (non-Javadoc) + * @see org.w3c.dom.Element#getTagName() + */ + public String getTagName() + { + return name; + } + + /* (non-Javadoc) + * @see org.w3c.dom.Element#hasAttribute(java.lang.String) + */ + public boolean hasAttribute(String name) + { + return attrs.containsKey(name); + } + + /* (non-Javadoc) + * @see org.w3c.dom.Element#hasAttributeNS(java.lang.String, java.lang.String) + */ + public boolean hasAttributeNS(String namespaceURI, String localName) + { + return attrs.containsKey(localName); + } + + /* (non-Javadoc) + * @see org.w3c.dom.Element#removeAttribute(java.lang.String) + */ + public void removeAttribute(String name) + { + attrs.remove(name); + } + + /* (non-Javadoc) + * @see org.w3c.dom.Element#removeAttributeNode(org.w3c.dom.Attr) + */ + public Attr removeAttributeNode(Attr oldAttr) + { + return (Attr)attrs.remove(oldAttr.getName()); + } + + /* (non-Javadoc) + * @see org.w3c.dom.Element#removeAttributeNS(java.lang.String, java.lang.String) + */ + public void removeAttributeNS(String namespaceURI, String localName) + { + removeAttribute(localName); + } + + /* (non-Javadoc) + * @see org.w3c.dom.Element#setAttribute(java.lang.String, java.lang.String) + */ + public void setAttribute(String name, String value) + { + Attr attr = getAttributeNode(name); + if (attr != null) + attr.setValue(value); + else + attrs.put(name, new IIOMetadataNodeAttr(this, name, value)); + } + + /* (non-Javadoc) + * @see org.w3c.dom.Element#setAttributeNode(org.w3c.dom.Attr) + */ + public Attr setAttributeNode(Attr newAttr) + { + return (Attr)attrs.put(newAttr.getName(), newAttr); + } + + /* (non-Javadoc) + * @see org.w3c.dom.Element#setAttributeNodeNS(org.w3c.dom.Attr) + */ + public Attr setAttributeNodeNS(Attr newAttr) + { + return (Attr)attrs.put(newAttr.getName(), newAttr); + } + + /* (non-Javadoc) + * @see org.w3c.dom.Element#setAttributeNS(java.lang.String, java.lang.String, java.lang.String) + */ + public void setAttributeNS(String namespaceURI, String qualifiedName, String value) + { + setAttribute(qualifiedName, value); + } + + /* (non-Javadoc) + * @see org.w3c.dom.NodeList#getLength() + */ + public int getLength() + { + return children.size(); + } + + /* (non-Javadoc) + * @see org.w3c.dom.NodeList#item(int) + */ + public Node item(int index) + { + if (index < children.size()) + return (Node)children.get(index); + else + return null; + } + + /* (non-Javadoc) + * @see org.w3c.dom.Node#appendChild(org.w3c.dom.Node) + */ + public Node appendChild(Node newChild) + { + if (newChild == null) + throw new IllegalArgumentException("Child node is null"); + + IIOMetadataNode child = (IIOMetadataNode) newChild; + + children.add(child); + child.parent = this; + return this; + } + + /* (non-Javadoc) + * @see org.w3c.dom.Node#cloneNode(boolean) + */ + public Node cloneNode(boolean deep) + { + IIOMetadataNode newnode = new IIOMetadataNode(name); + newnode.parent = null; + newnode.obj = obj; + if (deep) + { + for (int i=0; i < children.size(); i++) + newnode.children.add(((Node)children.get(i)).cloneNode(deep)); + } + + // clone attrs + for (Iterator it = attrs.values().iterator(); it.hasNext();) + { + IIOMetadataNodeAttr attr = (IIOMetadataNodeAttr)it.next(); + newnode.attrs.put(attr.name, attr.cloneNode(deep)); + attr.owner = newnode; + } + + return newnode; + } + + /* (non-Javadoc) + * @see org.w3c.dom.Node#getAttributes() + */ + public NamedNodeMap getAttributes() + { + return new IIONamedNodeMap(attrs); + } + + /* (non-Javadoc) + * @see org.w3c.dom.Node#getChildNodes() + */ + public NodeList getChildNodes() + { + return this; + } + + public Object getFeature(String feature, String version) + { + return null; + } + + /* (non-Javadoc) + * @see org.w3c.dom.Node#getFirstChild() + */ + public Node getFirstChild() + { + return (children.size() > 0) ? (Node)children.get(0) : null; + } + + /* (non-Javadoc) + * @see org.w3c.dom.Node#getLastChild() + */ + public Node getLastChild() + { + return (children.size() > 0) ? (Node)children.get(children.size() - 1) + : null; + } + + /* (non-Javadoc) + * @see org.w3c.dom.Node#getLocalName() + */ + public String getLocalName() + { + return name; + } + + /* (non-Javadoc) + * @see org.w3c.dom.Node#getNamespaceURI() + */ + public String getNamespaceURI() + { + return null; + } + + /* (non-Javadoc) + * @see org.w3c.dom.Node#getNextSibling() + */ + public Node getNextSibling() + { + // If this op needs to be faster, add links to prev and next nodes. + if (parent == null) return null; + int idx = parent.children.indexOf(this); + return (idx == parent.children.size() - 1) ? null + : (Node)parent.children.get(idx + 1); + } + + /* (non-Javadoc) + * @see org.w3c.dom.Node#getNodeName() + */ + public String getNodeName() + { + return name; + } + + /* (non-Javadoc) + * @see org.w3c.dom.Node#getNodeType() + */ + public short getNodeType() + { + return ELEMENT_NODE; + } + + /* (non-Javadoc) + * @see org.w3c.dom.Node#getNodeValue() + */ + public String getNodeValue() + { + return null; + } + + /* (non-Javadoc) + * @see org.w3c.dom.Node#getOwnerDocument() + */ + public Document getOwnerDocument() + { + // IOMetadataNodes have no owner + return null; + } + + /* (non-Javadoc) + * @see org.w3c.dom.Node#getParentNode() + */ + public Node getParentNode() + { + return parent; + } + + /* (non-Javadoc) + * @see org.w3c.dom.Node#getPrefix() + */ + public String getPrefix() + { + return null; + } + + /* (non-Javadoc) + * @see org.w3c.dom.Node#getPreviousSibling() + */ + public Node getPreviousSibling() + { + // If this op needs to be faster, add links to prev and next nodes. + if (parent == null) return null; + int idx = parent.children.indexOf(this); + return (idx == 0) ? null + : (Node)parent.children.get(idx - 1); + } + + public TypeInfo getSchemaTypeInfo() + { + return null; + } + + public String getTextContent() + throws DOMException + { + return null; + } + + public Object getUserData(String key) + { + return null; + } + + /* (non-Javadoc) + * @see org.w3c.dom.Node#hasAttributes() + */ + public boolean hasAttributes() + { + return !attrs.isEmpty(); + } + + /* (non-Javadoc) + * @see org.w3c.dom.Node#hasChildNodes() + */ + public boolean hasChildNodes() + { + return !children.isEmpty(); + } + + /* (non-Javadoc) + * @see org.w3c.dom.Node#insertBefore(org.w3c.dom.Node, org.w3c.dom.Node) + */ + public Node insertBefore(Node newChild, Node refChild) + { + if (newChild == null) + throw new IllegalArgumentException(); + + int idx = children.indexOf(refChild); + if (idx == -1) + children.add(newChild); + else + children.add(idx, newChild); + ((IIOMetadataNode)newChild).parent = this; + + return newChild; + } + + public boolean isDefaultNamespace(String namespaceURI) + { + return true; + } + + public boolean isEqualNode(Node arg) + { + return true; + } + + public boolean isSameNode(Node other) + { + return this == other; + } + + /* (non-Javadoc) + * @see org.w3c.dom.Node#isSupported(java.lang.String, java.lang.String) + */ + public boolean isSupported(String feature, String version) + { + // No DOM features are supported + return false; + } + + public String lookupNamespaceURI(String prefix) + { + return null; + } + + public String lookupPrefix(String namespaceURI) + { + return null; + } + + /* (non-Javadoc) + * @see org.w3c.dom.Node#normalize() + */ + public void normalize() + { + // No text nodes so no action + } + + /* (non-Javadoc) + * @see org.w3c.dom.Node#removeChild(org.w3c.dom.Node) + */ + public Node removeChild(Node oldChild) + { + if (oldChild == null) + throw new IllegalArgumentException(); + children.remove(oldChild); + ((IIOMetadataNode)oldChild).parent = null; + + return oldChild; + } + + /* (non-Javadoc) + * @see org.w3c.dom.Node#replaceChild(org.w3c.dom.Node, org.w3c.dom.Node) + */ + public Node replaceChild(Node newChild, Node oldChild) + { + if (newChild == null) + throw new IllegalArgumentException(); + children.set(children.indexOf(oldChild), newChild); + ((IIOMetadataNode)oldChild).parent = null; + return oldChild; + } + + public void setIdAttribute(String name, boolean isId) + throws DOMException + { + } + + public void setIdAttributeNode(Attr idAttr, boolean isId) + throws DOMException + { + } + + public void setIdAttributeNS(String namespaceURI, String localName, boolean isId) + throws DOMException + { + } + + /* (non-Javadoc) + * @see org.w3c.dom.Node#setNodeValue(java.lang.String) + */ + public void setNodeValue(String nodeValue) throws DOMException + { + } + + /* (non-Javadoc) + * @see org.w3c.dom.Node#setPrefix(java.lang.String) + */ + public void setPrefix(String prefix) + { + } + + public void setTextContent(String textContent) + throws DOMException + { + } + + public Object setUserData(String key, Object data, UserDataHandler handler) + { + return null; + } +} diff --git a/libjava/classpath/javax/imageio/metadata/package.html b/libjava/classpath/javax/imageio/metadata/package.html new file mode 100644 index 000000000..5bd77c2a5 --- /dev/null +++ b/libjava/classpath/javax/imageio/metadata/package.html @@ -0,0 +1,46 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> +<!-- package.html - describes classes in javax.imageio.metadata package. + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. --> + +<html> +<head><title>GNU Classpath - javax.imageio.metadata</title></head> + +<body> +<p></p> + +</body> +</html> diff --git a/libjava/classpath/javax/imageio/package.html b/libjava/classpath/javax/imageio/package.html new file mode 100644 index 000000000..f6a604de8 --- /dev/null +++ b/libjava/classpath/javax/imageio/package.html @@ -0,0 +1,87 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> +<!-- package.html - describes classes in javax.imageio package. + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. --> + +<html> +<head><title>GNU Classpath - javax.imageio</title></head> + +<body> +<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> diff --git a/libjava/classpath/javax/imageio/plugins/bmp/BMPImageWriteParam.java b/libjava/classpath/javax/imageio/plugins/bmp/BMPImageWriteParam.java new file mode 100644 index 000000000..cc0e0d34c --- /dev/null +++ b/libjava/classpath/javax/imageio/plugins/bmp/BMPImageWriteParam.java @@ -0,0 +1,144 @@ +/* BMPImageWriteParam.java -- + Copyright (C) 2006 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.imageio.plugins.bmp; + +import java.util.Locale; + +import javax.imageio.ImageWriteParam; + +/** + * A class to encode images in the BMP format. + * By default, the data layout is bottom-up, such that the pixels are stored in + * bottom-up order. + * + * The compression scheme can be specified by using setCompressionType() + * appropriate type string. The compression scheme specified will be honored + * if it is compatible with the type of image being written. If the + * compression scheme is not compatible with the type of image being written, + * then an IOException will be thrown by the BMP image writer. If the + * compression type is not set, then getCompressionType() will return null. + * In this case the BMP image writer will select a compression type that + * supports encoding of the given image without loss of the color resolution. + * + * The compression type strings and the image type each supports are: + * Uncompressed RLE: BI_RGB, image type: <= 8-bits/sample. + * 8-bit Run Length Encoding: BI_RLE8, image type: <= 8-bits/sample + * 4-bit Run Length Encoding: BI_RLE4, image type: <= 4-bits/sample + * Packed data: BI_BITFIELDS, image type: 16 or 32 bits/sample + * + * @author Lillian Angel (langel at redhat dot com) + */ +public class BMPImageWriteParam + extends ImageWriteParam +{ + + /** + * This boolean is true if the data will be written in a topdown manner. + */ + private boolean topDown; + + /** + * Compression type strings. + */ + String rgb = "BI_RGB"; + String rle8 = "BI_RLE8"; + String rle4 = "BI_RLE4"; + String bitfields = "BI_BITFIELDS"; + + /** + * Constants to represent image types. + */ + static final int BI_RGB = 0; + static final int BI_RLE8 = 1; + static final int BI_RLE4 = 2; + static final int BI_BITFIELDS = 3; + + /** + * Constructs an <code>BMPImageWriteParam</code> object with default values + * and a <code>null Locale</code>. + */ + public BMPImageWriteParam() + { + this(null); + } + + /** + * Constructs a <code>BMPImageWriteParam</code> set to use a given + * <code>Locale</code> and with default values for all parameters. + * + * @param locale - a <code>Locale</code> to be used to localize compression + * type names and quality descriptions, or <code>null</code>. + */ + public BMPImageWriteParam(Locale locale) + { + super(locale); + topDown = false; + canWriteCompressed = true; + + compressionTypes = new String[4]; + compressionTypes[BI_RGB] = rgb; + compressionTypes[BI_RLE8] = rle8; + compressionTypes[BI_RLE4] = rle4; + compressionTypes[BI_BITFIELDS] = bitfields; + + compressionType = compressionTypes[BI_RGB]; + } + + /** + * If set, the data will be written out in a top-down manner, the first + * scanline being written first. + * + * @param topDown - whether the data are written in top-down order. + */ + public void setTopDown(boolean topDown) + { + this.topDown = topDown; + } + + /** + * Returns the value of the <code>topDown</code> parameter. The default is + * false. + * + * @return whether the data are written in top-down order. + */ + public boolean isTopDown() + { + return topDown; + } +} diff --git a/libjava/classpath/javax/imageio/plugins/jpeg/JPEGHuffmanTable.java b/libjava/classpath/javax/imageio/plugins/jpeg/JPEGHuffmanTable.java new file mode 100644 index 000000000..be718d4fc --- /dev/null +++ b/libjava/classpath/javax/imageio/plugins/jpeg/JPEGHuffmanTable.java @@ -0,0 +1,282 @@ +/* JPEGHuffmanTable.java -- + Copyright (C) 2006 Free Software Foundation, Inc. + + This file is part of GNU Classpath. + + GNU Classpath is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + GNU Classpath is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GNU Classpath; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301 USA. + + Linking this library statically or dynamically with other modules is + making a combined work based on this library. Thus, the terms and + conditions of the GNU General Public License cover the whole + combination. + + As a special exception, the copyright holders of this library give you + permission to link this library with independent modules to produce an + executable, regardless of the license terms of these independent + modules, and to copy and distribute the resulting executable under + terms of your choice, provided that you also meet, for each linked + independent module, the terms and conditions of the license of that + module. An independent module is a module which is not derived from + or based on this library. If you modify this library, you may extend + this exception to your version of the library, but you are not + obligated to do so. If you do not wish to do so, delete this + exception statement from your version. */ + + +package javax.imageio.plugins.jpeg; + +import gnu.java.lang.CPStringBuilder; + +/** + * The JPEGHuffmanTable class represents a Huffman table read from a + * JPEG image file. The standard JPEG AC and DC chrominance and + * luminance values are provided as static fields. + */ +public class JPEGHuffmanTable +{ + /** + * Huffman code lengths. + */ + private short[] lengths; + + /** + * Huffman values. + */ + private short[] values; + + // The private constructors are used for these final fields to avoid + // unnecessary copying. + /** + * The standard JPEG AC chrominance Huffman table. + */ + public static final JPEGHuffmanTable StdACChrominance = + new JPEGHuffmanTable(new short[] { 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, + 4, 4, 0, 1, 2, 0x77 }, + new short[] { 0x00, 0x01, 0x02, 0x03, 0x11, + 0x04, 0x05, 0x21, 0x31, 0x06, + 0x12, 0x41, 0x51, 0x07, 0x61, + 0x71, 0x13, 0x22, 0x32, 0x81, + 0x08, 0x14, 0x42, 0x91, 0xa1, + 0xb1, 0xc1, 0x09, 0x23, 0x33, + 0x52, 0xf0, 0x15, 0x62, 0x72, + 0xd1, 0x0a, 0x16, 0x24, 0x34, + 0xe1, 0x25, 0xf1, 0x17, 0x18, + 0x19, 0x1a, 0x26, 0x27, 0x28, + 0x29, 0x2a, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x3a, 0x43, 0x44, + 0x45, 0x46, 0x47, 0x48, 0x49, + 0x4a, 0x53, 0x54, 0x55, 0x56, + 0x57, 0x58, 0x59, 0x5a, 0x63, + 0x64, 0x65, 0x66, 0x67, 0x68, + 0x69, 0x6a, 0x73, 0x74, 0x75, + 0x76, 0x77, 0x78, 0x79, 0x7a, + 0x82, 0x83, 0x84, 0x85, 0x86, + 0x87, 0x88, 0x89, 0x8a, 0x92, + 0x93, 0x94, 0x95, 0x96, 0x97, + 0x98, 0x99, 0x9a, 0xa2, 0xa3, + 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, + 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, + 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, + 0xba, 0xc2, 0xc3, 0xc4, 0xc5, + 0xc6, 0xc7, 0xc8, 0xc9, 0xca, + 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, + 0xd7, 0xd8, 0xd9, 0xda, 0xe2, + 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, + 0xe8, 0xe9, 0xea, 0xf2, 0xf3, + 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, + 0xf9, 0xfa }, false); + + /** + * The standard JPEG AC luminance Huffman table. + */ + public static final JPEGHuffmanTable StdACLuminance = + new JPEGHuffmanTable(new short[] { 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, + 4, 4, 0, 0, 1, 0x7d }, + new short[] { 0x01, 0x02, 0x03, 0x00, 0x04, + 0x11, 0x05, 0x12, 0x21, 0x31, + 0x41, 0x06, 0x13, 0x51, 0x61, + 0x07, 0x22, 0x71, 0x14, 0x32, + 0x81, 0x91, 0xa1, 0x08, 0x23, + 0x42, 0xb1, 0xc1, 0x15, 0x52, + 0xd1, 0xf0, 0x24, 0x33, 0x62, + 0x72, 0x82, 0x09, 0x0a, 0x16, + 0x17, 0x18, 0x19, 0x1a, 0x25, + 0x26, 0x27, 0x28, 0x29, 0x2a, + 0x34, 0x35, 0x36, 0x37, 0x38, + 0x39, 0x3a, 0x43, 0x44, 0x45, + 0x46, 0x47, 0x48, 0x49, 0x4a, + 0x53, 0x54, 0x55, 0x56, 0x57, + 0x58, 0x59, 0x5a, 0x63, 0x64, + 0x65, 0x66, 0x67, 0x68, 0x69, + 0x6a, 0x73, 0x74, 0x75, 0x76, + 0x77, 0x78, 0x79, 0x7a, 0x83, + 0x84, 0x85, 0x86, 0x87, 0x88, + 0x89, 0x8a, 0x92, 0x93, 0x94, + 0x95, 0x96, 0x97, 0x98, 0x99, + 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, + 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, + 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, + 0xb7, 0xb8, 0xb9, 0xba, 0xc2, + 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, + 0xc8, 0xc9, 0xca, 0xd2, 0xd3, + 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, + 0xd9, 0xda, 0xe1, 0xe2, 0xe3, + 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, + 0xe9, 0xea, 0xf1, 0xf2, 0xf3, + 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, + 0xf9, 0xfa }, false); + + /** + * The standard JPEG DC chrominance Huffman table. + */ + public static final JPEGHuffmanTable StdDCChrominance = + new JPEGHuffmanTable(new short[] { 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 0, 0, 0, 0, 0 }, + new short[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 10, 11 }, false); + + /** + * The standard JPEG DC luminance Huffman table. + */ + public static final JPEGHuffmanTable StdDCLuminance = + new JPEGHuffmanTable(new short[] { 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0 }, + new short[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 10, 11 }, false); + + /** + * Construct and initialize a Huffman table. Copies are created of + * the array arguments. lengths[index] stores the number of Huffman + * values with Huffman codes of length index + 1. The values array + * stores the Huffman values in order of increasing code length. + * + * @param lengths an array of Huffman code lengths + * @param values a sorted array of Huffman values + * @throws IllegalArgumentException if either parameter is null, if + * lengths.length > 16 or values.length > 256, if any value in + * length or values is negative, or if the parameters do not + * describe a valid Huffman table + */ + public JPEGHuffmanTable(short[] lengths, short[] values) + { + // Create copies of the lengths and values arguments. + this(checkLengths(lengths), checkValues(values, lengths), true); + } + + /** + * Private constructor that avoids unnecessary copying and argument + * checking. + * + * @param lengths an array of Huffman code lengths + * @param values a sorted array of Huffman values + * @param copy true if copies should be created of the given arrays + */ + private JPEGHuffmanTable(short[] lengths, short[] values, boolean copy) + { + this.lengths = copy ? (short[]) lengths.clone() : lengths; + this.values = copy ? (short[]) values.clone() : values; + } + + private static short[] checkLengths(short[] lengths) + { + if (lengths == null || lengths.length > 16) + throw new IllegalArgumentException("invalid length array"); + + for (int i = 0; i < lengths.length; i++) + { + if (lengths[i] < 0) + throw new IllegalArgumentException("negative length"); + } + + int sum = 0; + for (int i = 0; i < lengths.length; i++) + { + if (lengths[i] > ((1 << (i + 1)) - 1)) + throw new IllegalArgumentException("invalid number of codes" + + " for code length " + (i + 1)); + sum += lengths[i]; + } + + return lengths; + } + + private static short[] checkValues(short[] values, short[] lengths) + { + if (values == null || values.length > 256) + throw new IllegalArgumentException("invalid values array"); + + for (int i = 0; i < values.length; i++) + { + if (values[i] < 0) + throw new IllegalArgumentException("negative value"); + } + // lengths is known-valid by this point. + int sum = 0; + for (int i = 0; i < lengths.length; i++) + sum += lengths[i]; + + if (values.length != sum) + throw new IllegalArgumentException("invalid number of values" + + " for number of codes"); + + return values; + } + + /** + * Retrieve a copy of the array of Huffman code lengths. If the + * returned array is called lengthcount, there are + * lengthcount[index] codes of length index + 1. + * + * @return a copy of the array of Huffman code lengths + */ + public short[] getLengths() + { + return (short[]) lengths.clone(); + } + + /** + * Retrieve a copy of the array of Huffman values, sorted in order + * of increasing code length. + * + * @return a copy of the array of Huffman values + */ + public short[] getValues() + { + return (short[]) values.clone(); + } + + /** + * Create a string representation of this JPEG Huffman table. + * + * @return a string representation of this JPEG Huffman table. + */ + public String toString() + { + CPStringBuilder buffer = new CPStringBuilder(); + + buffer.append("JPEGHuffmanTable:\nlengths:"); + + for (int i = 0; i < lengths.length; i++) + buffer.append(" " + lengths[i]); + + buffer.append("\nvalues:"); + + for (int i = 0; i < values.length; i++) + buffer.append(" " + values[i]); + + return buffer.toString(); + } +} diff --git a/libjava/classpath/javax/imageio/plugins/jpeg/JPEGImageReadParam.java b/libjava/classpath/javax/imageio/plugins/jpeg/JPEGImageReadParam.java new file mode 100644 index 000000000..b570922f9 --- /dev/null +++ b/libjava/classpath/javax/imageio/plugins/jpeg/JPEGImageReadParam.java @@ -0,0 +1,161 @@ +/* JPEGImageReadParam.java -- + Copyright (C) 2006 Free Software Foundation, Inc. + + This file is part of GNU Classpath. + + GNU Classpath is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + GNU Classpath is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GNU Classpath; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301 USA. + + Linking this library statically or dynamically with other modules is + making a combined work based on this library. Thus, the terms and + conditions of the GNU General Public License cover the whole + combination. + + As a special exception, the copyright holders of this library give you + permission to link this library with independent modules to produce an + executable, regardless of the license terms of these independent + modules, and to copy and distribute the resulting executable under + terms of your choice, provided that you also meet, for each linked + independent module, the terms and conditions of the license of that + module. An independent module is a module which is not derived from + or based on this library. If you modify this library, you may extend + this exception to your version of the library, but you are not + obligated to do so. If you do not wish to do so, delete this + exception statement from your version. */ + + +package javax.imageio.plugins.jpeg; + +import javax.imageio.ImageReadParam; + +/** + * The JPEGImageReadParam class is only used to set JPEG decoding + * tables for streams that do not provide their own tables. If a + * stream does not provide tables and a custom JPEGImageReadParam is + * not provided, then the standard JPEG tables are used from the + * JPEGQTable and JPEGHuffmanTable classes. If a stream does provide + * decoding tables then JPEGImageReadParam will be ignored. + * JPEGImageReadParam cannot be used to retrieve the tables from a + * stream. Instead, use IIOMetadata for this purpose. + * + * A JPEGImageReadParam instance is retrieved from the built-in JPEG + * ImageReader using the getDefaultImageReadParam method. + */ +public class JPEGImageReadParam + extends ImageReadParam +{ + private JPEGQTable[] qTables; + private JPEGHuffmanTable[] DCHuffmanTables; + private JPEGHuffmanTable[] ACHuffmanTables; + + /** + * Construct a JPEGImageReadParam. + */ + public JPEGImageReadParam() + { + super(); + } + + /** + * Check if the decoding tables are set. + * + * @return true if the decoding tables are set, false otherwise + */ + public boolean areTablesSet() + { + // If qTables is not null then all tables are set. + return (qTables != null); + } + + /** + * Set the quantization and Huffman tables that will be used to + * decode the stream. Copies are created of the array arguments. + * The number of Huffman tables must be the same in both Huffman + * table arrays. No argument may be null and no array may be longer + * than four elements. + * + * @param qTables JPEG quantization tables + * @param DCHuffmanTables JPEG DC Huffman tables + * @param ACHuffmanTables JPEG AC Huffman tables + * + * @throws IllegalArgumentException if any argument is null, if any + * of the arrays are longer than four elements, or if the Huffman + * table arrays do not have the same number of elements + */ + public void setDecodeTables(JPEGQTable[] qTables, + JPEGHuffmanTable[] DCHuffmanTables, + JPEGHuffmanTable[] ACHuffmanTables) + { + if (qTables == null || DCHuffmanTables == null || ACHuffmanTables == null) + throw new IllegalArgumentException("null argument"); + + if (qTables.length > 4 || DCHuffmanTables.length > 4 + || ACHuffmanTables.length > 4) + throw new IllegalArgumentException("argument has too many elements"); + + if (DCHuffmanTables.length != ACHuffmanTables.length) + throw new IllegalArgumentException("Huffman table arrays differ in length"); + + // Do a shallow copy. JPEGQTable's data is not directly + // modifyable since JPEGQTable.getTable returns a copy. Therefore + // it is safe to have multiple references to a single JPEGQTable. + // Likewise for JPEGHuffmanTable. + this.qTables = (JPEGQTable[]) qTables.clone(); + this.DCHuffmanTables = (JPEGHuffmanTable[]) DCHuffmanTables.clone(); + this.ACHuffmanTables = (JPEGHuffmanTable[]) ACHuffmanTables.clone(); + } + + /** + * Clear the quantization and Huffman decoding tables. + */ + public void unsetDecodeTables() + { + qTables = null; + DCHuffmanTables = null; + ACHuffmanTables = null; + } + + /** + * Retrieve the quantization tables. + * + * @returns an array of JPEG quantization tables + */ + public JPEGQTable[] getQTables() + { + return qTables == null ? qTables : (JPEGQTable[]) qTables.clone(); + } + + /** + * Retrieve the DC Huffman tables. + * + * @return an array of JPEG DC Huffman tables + */ + public JPEGHuffmanTable[] getDCHuffmanTables() + { + return DCHuffmanTables == null ? DCHuffmanTables + : (JPEGHuffmanTable[]) DCHuffmanTables.clone(); + } + + /** + * Retrieve the AC Huffman tables. + * + * @return an array of JPEG AC Huffman tables + */ + public JPEGHuffmanTable[] getACHuffmanTables() + { + return ACHuffmanTables == null ? ACHuffmanTables + : (JPEGHuffmanTable[]) ACHuffmanTables.clone(); + } +} diff --git a/libjava/classpath/javax/imageio/plugins/jpeg/JPEGImageWriteParam.java b/libjava/classpath/javax/imageio/plugins/jpeg/JPEGImageWriteParam.java new file mode 100644 index 000000000..1e7989e82 --- /dev/null +++ b/libjava/classpath/javax/imageio/plugins/jpeg/JPEGImageWriteParam.java @@ -0,0 +1,293 @@ +/* JPEGImageWriteParam.java -- + Copyright (C) 2006 Free Software Foundation, Inc. + + This file is part of GNU Classpath. + + GNU Classpath is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + GNU Classpath is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GNU Classpath; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301 USA. + + Linking this library statically or dynamically with other modules is + making a combined work based on this library. Thus, the terms and + conditions of the GNU General Public License cover the whole + combination. + + As a special exception, the copyright holders of this library give you + permission to link this library with independent modules to produce an + executable, regardless of the license terms of these independent + modules, and to copy and distribute the resulting executable under + terms of your choice, provided that you also meet, for each linked + independent module, the terms and conditions of the license of that + module. An independent module is a module which is not derived from + or based on this library. If you modify this library, you may extend + this exception to your version of the library, but you are not + obligated to do so. If you do not wish to do so, delete this + exception statement from your version. */ + + +package javax.imageio.plugins.jpeg; + +import java.util.Locale; +import java.util.PropertyResourceBundle; +import java.util.ResourceBundle; +import javax.imageio.ImageWriteParam; + +/** + * The JPEGImageWriteParam class can be used to specify tables and + * settings used in the JPEG encoding process. Encoding tables are + * taken from the metadata associated with the output stream, and + * failing that (if the metadata tables are null) from an instance of + * JPEGImageWriteParam. The default metadata uses the standard JPEG + * tables from the JPEGQTable and JPEGHuffmanTable classes. Non-null + * metadata tables override JPEGImageWriteParam tables. Compression + * settings range from 1.0, best compression, through 0.75, default + * compression, to 0.0, worst compression. + * + * A JPEGImageWriteParam instance is retrieved from the built-in JPEG + * ImageWriter using the getDefaultImageWriteParam method. + */ +public class JPEGImageWriteParam + extends ImageWriteParam +{ + private JPEGQTable[] qTables; + private JPEGHuffmanTable[] DCHuffmanTables; + private JPEGHuffmanTable[] ACHuffmanTables; + private boolean optimize; + private String[] compressionQualityDescriptions; + private float[] compressionQualityValues; + + /** + * Localized messages are stored in separate files. + */ + private ResourceBundle messages; + + /** + * Construct a JPEGImageWriteParam with the following state: tiling + * is not supported, progressive mode is supported, initial + * progressive mode is MODE_DISABLED, compression is supported, one + * compression type named "JPEG" is supported and the default + * compression quality is 0.75f. Compression type names and + * compression quality descriptions are localized to the given + * locale. + * + * @param locale the locale used for message localization + */ + public JPEGImageWriteParam(Locale locale) + { + super(locale); + + // Get localized compression type and compression quality + // description strings for the given locale. + messages = PropertyResourceBundle.getBundle + ("javax/imageio/plugins/jpeg/MessagesBundle", locale); + + // Initialize inherited ImageWriter fields. + canWriteTiles = false; + canWriteProgressive = true; + progressiveMode = MODE_DISABLED; + canWriteCompressed = true; + compressionTypes = new String[] + { + messages.getString("compression.types.jpeg") + }; + compressionType = compressionTypes[0]; + compressionQuality = 0.75f; + } + + /** + * Reset the compression quality to 0.75f. + */ + public void unsetCompression() + { + compressionQuality = 0.75f; + } + + /** + * Check if compression algorithm is lossless. JPEGImageWriteParam + * overrides this ImageWriteParam method to always return false + * since JPEG compression is inherently lossy. + * + * @return false + */ + public boolean isCompressionLossless() + { + return false; + } + + /** + * Retrieve an array of compression quality descriptions. These + * messages are localized using the locale provided upon + * construction. Each compression quality description in the + * returned array corresponds to the compression quality value at + * the same index in the array returned by + * getCompressionQualityValues. + * + * @return an array of strings each of which describes a compression + * quality value + */ + public String[] getCompressionQualityDescriptions() + { + // Make sure exceptions are thrown when this image write param is + // in the wrong state. + super.getCompressionQualityDescriptions(); + + if (compressionQualityDescriptions == null) + { + compressionQualityDescriptions = new String[] + { + messages.getString("compression.minimum"), + messages.getString("compression.default"), + messages.getString("compression.maximum") + }; + } + + return compressionQualityDescriptions; + } + + /** + * Retrieve an array of compression quality values, ordered from + * lowest quality to highest quality. + * + * @return an array of compressions quality values + */ + public float[] getCompressionQualityValues() + { + // Make sure exceptions are thrown when this image write param is + // in the wrong state. + super.getCompressionQualityValues(); + + if (compressionQualityValues == null) + compressionQualityValues = new float[] { 0.05f, 0.75f, 0.95f }; + + return compressionQualityValues; + } + + /** + * Check if the encoding tables are set. + * + * @return true if the encoding tables are set, false otherwise + */ + public boolean areTablesSet() + { + // If qTables is not null then all tables are set. + return (qTables != null); + } + + /** + * Set the quantization and Huffman tables that will be used to + * encode the stream. Copies are created of the array arguments. + * The number of Huffman tables must be the same in both Huffman + * table arrays. No argument may be null and no array may be longer + * than four elements. + * + * @param qTables JPEG quantization tables + * @param DCHuffmanTables JPEG DC Huffman tables + * @param ACHuffmanTables JPEG AC Huffman tables + * + * @throws IllegalArgumentException if any argument is null, if any + * of the arrays are longer than four elements, or if the Huffman + * table arrays do not have the same number of elements + */ + public void setEncodeTables(JPEGQTable[] qTables, + JPEGHuffmanTable[] DCHuffmanTables, + JPEGHuffmanTable[] ACHuffmanTables) + { + if (qTables == null || DCHuffmanTables == null || ACHuffmanTables == null) + throw new IllegalArgumentException("null argument"); + + if (qTables.length > 4 || DCHuffmanTables.length > 4 + || ACHuffmanTables.length > 4) + throw new IllegalArgumentException("argument has too many elements"); + + if (DCHuffmanTables.length != ACHuffmanTables.length) + throw new IllegalArgumentException("Huffman table arrays differ in length"); + + // Do a shallow copy. JPEGQTable's data is not directly + // modifyable since JPEGQTable.getTable returns a copy. Therefore + // it is safe to have multiple references to a single JPEGQTable. + // Likewise for JPEGHuffmanTable. + this.qTables = (JPEGQTable[]) qTables.clone(); + this.DCHuffmanTables = (JPEGHuffmanTable[]) DCHuffmanTables.clone(); + this.ACHuffmanTables = (JPEGHuffmanTable[]) ACHuffmanTables.clone(); + } + + /** + * Clear the quantization and Huffman encoding tables. + */ + public void unsetEncodeTables() + { + qTables = null; + DCHuffmanTables = null; + ACHuffmanTables = null; + } + + /** + * Retrieve the quantization tables. + * + * @returns an array of JPEG quantization tables + */ + public JPEGQTable[] getQTables() + { + return qTables == null ? qTables : (JPEGQTable[]) qTables.clone(); + } + + /** + * Retrieve the DC Huffman tables. + * + * @return an array of JPEG DC Huffman tables + */ + public JPEGHuffmanTable[] getDCHuffmanTables() + { + return DCHuffmanTables == null ? DCHuffmanTables + : (JPEGHuffmanTable[]) DCHuffmanTables.clone(); + } + + /** + * Retrieve the AC Huffman tables. + * + * @return an array of JPEG AC Huffman tables + */ + public JPEGHuffmanTable[] getACHuffmanTables() + { + return ACHuffmanTables == null ? ACHuffmanTables + : (JPEGHuffmanTable[]) ACHuffmanTables.clone(); + } + + /** + * Specify whether or not Huffman tables written to the output + * stream should be optimized. Every image encoded with this flag + * set will contain a Huffman table, and the generated Huffman + * tables will override those specified in the metadata. + * + * @param optimize true to generate optimized Huffman tables, false + * otherwise + */ + public void setOptimizeHuffmanTables(boolean optimize) + { + this.optimize = optimize; + } + + /** + * Check whether or not Huffman tables written to the output stream + * will be optimized. Unless otherwise set using + * setOptimizeHuffmanTables, this returns false. + * + * @return true Huffman tables written to the output stream will be + * optimized, false otherwise + */ + public boolean getOptimizeHuffmanTables() + { + return optimize; + } +} diff --git a/libjava/classpath/javax/imageio/plugins/jpeg/JPEGQTable.java b/libjava/classpath/javax/imageio/plugins/jpeg/JPEGQTable.java new file mode 100644 index 000000000..259d0aa64 --- /dev/null +++ b/libjava/classpath/javax/imageio/plugins/jpeg/JPEGQTable.java @@ -0,0 +1,198 @@ +/* JPEGQTable.java -- + Copyright (C) 2006 Free Software Foundation, Inc. + + This file is part of GNU Classpath. + + GNU Classpath is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + GNU Classpath is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GNU Classpath; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301 USA. + + Linking this library statically or dynamically with other modules is + making a combined work based on this library. Thus, the terms and + conditions of the GNU General Public License cover the whole + combination. + + As a special exception, the copyright holders of this library give you + permission to link this library with independent modules to produce an + executable, regardless of the license terms of these independent + modules, and to copy and distribute the resulting executable under + terms of your choice, provided that you also meet, for each linked + independent module, the terms and conditions of the license of that + module. An independent module is a module which is not derived from + or based on this library. If you modify this library, you may extend + this exception to your version of the library, but you are not + obligated to do so. If you do not wish to do so, delete this + exception statement from your version. */ + + +package javax.imageio.plugins.jpeg; + +import gnu.java.lang.CPStringBuilder; + +/** + * The JPEGQTable class represents a quantization table that can be + * used to encode or decode a JPEG stream. The standard JPEG + * luminance and chrominance quantization tables are provided as + * static fields. Table entries are stored in natural order, not + * zig-zag order. + */ +public class JPEGQTable +{ + /** + * The table entries, stored in natural order. + */ + private int[] table; + + /** + * The standard JPEG luminance quantization table. Values are + * stored in natural order. + */ + public static final JPEGQTable K1Luminance = new JPEGQTable(new int[] + { + 16, 11, 10, 16, 24, 40, 51, 61, + 12, 12, 14, 19, 26, 58, 60, 55, + 14, 13, 16, 24, 40, 57, 69, 56, + 14, 17, 22, 29, 51, 87, 80, 62, + 18, 22, 37, 56, 68, 109, 103, 77, + 24, 35, 55, 64, 81, 104, 113, 92, + 49, 64, 78, 87, 103, 121, 120, 101, + 72, 92, 95, 98, 112, 100, 103, 99 + }, false); + + /** + * The standard JPEG luminance quantization table, scaled by + * one-half. Values are stored in natural order. + */ + public static final JPEGQTable K1Div2Luminance = + K1Luminance.getScaledInstance(0.5f, true); + + /** + * The standard JPEG chrominance quantization table. Values are + * stored in natural order. + */ + public static final JPEGQTable K2Chrominance = new JPEGQTable(new int[] + { + 17, 18, 24, 47, 99, 99, 99, 99, + 18, 21, 26, 66, 99, 99, 99, 99, + 24, 26, 56, 99, 99, 99, 99, 99, + 47, 66, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99 + }, false); + + /** + * The standard JPEG chrominance quantization table, scaled by + * one-half. Values are stored in natural order. + */ + public static final JPEGQTable K2Div2Chrominance = + K2Chrominance.getScaledInstance(0.5f, true); + + /** + * Construct a new JPEG quantization table. A copy is created of + * the table argument. + * + * @param table the 64-element value table, stored in natural order + * + * @throws IllegalArgumentException if the table is null or if + * table's length is not equal to 64. + */ + public JPEGQTable(int[] table) + { + this(checkTable(table), true); + } + + /** + * Private constructor that avoids unnecessary copying and argument + * checking. + * + * @param table the 64-element value table, stored in natural order + * @param copy true if a copy should be created of the given table + */ + private JPEGQTable(int[] table, boolean copy) + { + this.table = copy ? (int[]) table.clone() : table; + } + + private static int[] checkTable(int[] table) + { + if (table == null || table.length != 64) + throw new IllegalArgumentException("invalid JPEG quantization table"); + + return table; + } + + /** + * Retrieve a copy of the quantization values for this table. + * + * @return a copy of the quantization value array + */ + public int[] getTable() + { + return (int[]) table.clone(); + } + + /** + * Retrieve a copy of this JPEG quantization table with every value + * scaled by the given scale factor, and clamped from 1 to 255 + * baseline or from 1 to 32767 otherwise. + * + * @param scaleFactor the factor by which to scale this table + * @param forceBaseline clamp scaled values to a maximum of 255 if + * true, 32767 if false + * + * @return a new scaled JPEG quantization table + */ + public JPEGQTable getScaledInstance(float scaleFactor, + boolean forceBaseline) + { + int[] scaledTable = getTable(); + int max = forceBaseline ? 255 : 32767; + + for (int i = 0; i < scaledTable.length; i++) + { + scaledTable[i] = Math.round (scaleFactor * (float) scaledTable[i]); + if (scaledTable[i] < 1) + scaledTable[i] = 1; + else if (scaledTable[i] > max) + scaledTable[i] = max; + } + + // Do not copy scaledTable. It is already a copy because we used + // getTable to retrieve it. + return new JPEGQTable(scaledTable, false); + } + + /** + * Create a string representing this JPEG quantization table. + */ + public String toString() + { + CPStringBuilder buffer = new CPStringBuilder(); + + buffer.append("JPEGQTable:\n"); + for (int i = 0; i < 8; i++) + { + buffer.append(" "); + for (int j = 0; j < 8; j++) + { + buffer.append(table[i * 8 + j] + " "); + } + buffer.append("\n"); + } + + return buffer.toString(); + } +} diff --git a/libjava/classpath/javax/imageio/spi/IIORegistry.java b/libjava/classpath/javax/imageio/spi/IIORegistry.java new file mode 100644 index 000000000..faa571d60 --- /dev/null +++ b/libjava/classpath/javax/imageio/spi/IIORegistry.java @@ -0,0 +1,119 @@ +/* IIORegistry.java -- + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.imageio.spi; + +import gnu.classpath.ServiceFactory; + +import java.awt.Toolkit; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; + +import gnu.java.awt.ClasspathToolkit; +import gnu.javax.imageio.bmp.BMPImageReaderSpi; +import gnu.javax.imageio.bmp.BMPImageWriterSpi; +import gnu.javax.imageio.gif.GIFImageReaderSpi; +import gnu.javax.imageio.png.PNGImageReaderSpi; + +public final class IIORegistry extends ServiceRegistry +{ + private static final HashSet defaultCategories = new HashSet(); + + private static HashMap instances = new HashMap(); + + static + { + defaultCategories.add(ImageReaderSpi.class); + defaultCategories.add(ImageWriterSpi.class); + defaultCategories.add(ImageTranscoderSpi.class); + defaultCategories.add(ImageInputStreamSpi.class); + defaultCategories.add(ImageOutputStreamSpi.class); + } + + public static synchronized IIORegistry getDefaultInstance() + { + // XXX: This leaks memory if a ThreadGroup isn't available anymore. + ThreadGroup group = Thread.currentThread().getThreadGroup(); + IIORegistry registry = (IIORegistry) instances.get(group); + + if (registry == null) + { + registry = new IIORegistry(); + instances.put(group, registry); + } + + return registry; + } + + private IIORegistry() + { + super(defaultCategories.iterator()); + + // XXX: Register built-in Spis here. + registerServiceProvider(new PNGImageReaderSpi()); // Register PNG decoder. + registerServiceProvider(new GIFImageReaderSpi()); // Register GIF decoder. + registerServiceProvider(new BMPImageReaderSpi()); + registerServiceProvider(new BMPImageWriterSpi()); + + Toolkit toolkit = Toolkit.getDefaultToolkit(); + if (toolkit instanceof ClasspathToolkit) + ((ClasspathToolkit)toolkit).registerImageIOSpis(this); + + registerApplicationClasspathSpis(); + } + + /** + * Registers all available service providers found on the application + * classpath. + */ + public void registerApplicationClasspathSpis() + { + ClassLoader loader = Thread.currentThread().getContextClassLoader(); + Iterator categories = getCategories(); + + while (categories.hasNext()) + { + Class category = (Class) categories.next(); + Iterator providers = ServiceFactory.lookupProviders(category, loader); + + while (providers.hasNext()) + registerServiceProvider((IIOServiceProvider) providers.next()); + } + } +} diff --git a/libjava/classpath/javax/imageio/spi/IIOServiceProvider.java b/libjava/classpath/javax/imageio/spi/IIOServiceProvider.java new file mode 100644 index 000000000..48fa7d414 --- /dev/null +++ b/libjava/classpath/javax/imageio/spi/IIOServiceProvider.java @@ -0,0 +1,163 @@ +/* IIOServiceProvider.java -- General service provider for image I/O. + Copyright (C) 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.imageio.spi; + +import java.util.Locale; + + +/** + * An abstract superclass for service providers that perform image I/O. + * + * @since 1.4 + * + * @author Sascha Brawer (brawer@dandelis.ch) + */ +public abstract class IIOServiceProvider + implements RegisterableService +{ + /** + * The vendor of this service provider, or <code>null</code> if the + * subclass constructor did not set this field. + * + * @see #getVendorName() + */ + protected String vendorName; + + + /** + * The version of this service provider, or <code>null</code> if the + * subclass constructor did not set this field. + * + * @see #getVersion() + */ + protected String version; + + + /** + * Constructs a general <code>IIOServiceProvider</code>, given the + * vendor name and a version string. + * + * @throws IllegalArgumentException if <code>vendorName</code> + * or <code>version</code> is <code>null</code>. + */ + public IIOServiceProvider(String vendorName, String version) + { + if (vendorName == null || version == null) + throw new IllegalArgumentException(); + + this.vendorName = vendorName; + this.version = version; + } + + + /** + * Constructs a general <code>IIOServiceProvider</code> without + * specifying a vendor name and a version string. The subclass + * constructor should set the {@link #vendorName} and {@link + * #version} to non-null values. + */ + public IIOServiceProvider() + { + } + + + /** + * Informs this service provider that it has been registered in a + * {@link ServiceRegistry}. If this provider gets registered as an + * implementor for several service categories, its + * <code>onRegistration</code> method will be called multiple times. + * The default implementation does nothing. + * + * @param registry the registry to which this service provider has + * been added. + * + * @param category the service category for which this provider has + * been registered as an implementor. + */ + public void onRegistration(ServiceRegistry registry, Class<?> category) + { + } + + + /** + * Informs this service provider that it has been de-registered from + * a {@link ServiceRegistry}. If this provider had been registered + * as an implementor for several service categories, its + * <code>onDeregistration</code> method will be called multiple + * times. The default implementation does nothing. + * + * @param registry the registry from which this service provider has + * been removed. + * + * @param category the service category for which this provider has + * been registered as an implementor. + */ + public void onDeregistration(ServiceRegistry registry, Class<?> category) + { + } + + + /** + * Returns the name of the vendor of this service provider. + */ + public String getVendorName() + { + return vendorName; + } + + + /** + * Returns an identifier string for the version of this service + * provider. + */ + public String getVersion() + { + return version; + } + + + /** + * Returns a short description of this service provider that can be + * presented to a human user. + * + * @param locale the locale for which the description string should + * be localized. + */ + public abstract String getDescription(Locale locale); +} diff --git a/libjava/classpath/javax/imageio/spi/ImageInputStreamSpi.java b/libjava/classpath/javax/imageio/spi/ImageInputStreamSpi.java new file mode 100644 index 000000000..2b60868a5 --- /dev/null +++ b/libjava/classpath/javax/imageio/spi/ImageInputStreamSpi.java @@ -0,0 +1,144 @@ +/* ImageInputStreamSpi.java -- Service provider for image input streams. + Copyright (C) 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.imageio.spi; + +import java.io.File; +import java.io.IOException; + +import javax.imageio.stream.ImageInputStream; + +/** + * An abstract superclass for service providers that create + * {@linkplain javax.imageio.stream.ImageInputStream image input + * streams} for a file, URL, byte array or any other source. + * + * @since 1.4 + * + * @author Sascha Brawer (brawer@dandelis.ch) + */ +public abstract class ImageInputStreamSpi + extends IIOServiceProvider +{ + /** + * Indicates which kind of input is processable by the streams + * created by {@link #createInputStreamInstance(Object)}. + */ + protected Class<?> inputClass; + + + /** + * Constructs a service provider for image input streams, given no + * parameters. It is up to the sub-class to set {@link #vendorName}, + * {@link #version} and {@link #inputClass} to non-null values. + */ + protected ImageInputStreamSpi() + { + } + + + /** + * Constructs a service provider for image input streams, given the + * vendor name and a version string. + * + * @throws IllegalArgumentException if <code>vendorName</code> + * or <code>version</code> is <code>null</code>. + */ + public ImageInputStreamSpi(String vendorName, String version, + Class<?> inputClass) + { + super(vendorName, version); + this.inputClass = inputClass; + } + + + /** + * Determines which kind of input is processable by the streams + * created by {@link #createInputStreamInstance(Object)}. + */ + public Class<?> getInputClass() + { + return inputClass; + } + + + /** + * Determines whether <code>ImageInputStreams</code> created + * by this service provider benefit from using a cache file. + * + * <p>The default behavior is to return <code>false</code>. + * + * @return <code>true</code> if the created streams are faster or + * need less memory when a cache file is being used; + * <code>false</code> if no positive effect results from the cache + * file. + */ + public boolean canUseCacheFile() + { + return false; + } + + + /** + * Determines whether <code>ImageInputStreams</code> created + * by this service provider require the use of a cache file. + * + * <p>The default behavior is to return <code>false</code>. + * + * @return <code>true</code> if the created streams can only work + * when a cache file is being used; <code>false</code> if no cache + * file is needed. + */ + public boolean needsCacheFile() + { + return false; + } + + + public abstract ImageInputStream createInputStreamInstance(Object input, + boolean useCache, + File cacheDir) + throws IOException; + + + public ImageInputStream createInputStreamInstance(Object input) + throws IOException + { + return createInputStreamInstance(input, canUseCacheFile(), null); + } +} diff --git a/libjava/classpath/javax/imageio/spi/ImageOutputStreamSpi.java b/libjava/classpath/javax/imageio/spi/ImageOutputStreamSpi.java new file mode 100644 index 000000000..872e7181e --- /dev/null +++ b/libjava/classpath/javax/imageio/spi/ImageOutputStreamSpi.java @@ -0,0 +1,143 @@ +/* ImageOutputStreamSpi.java -- Service provider for image output streams. + Copyright (C) 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.imageio.spi; + +import java.io.File; +import java.io.IOException; + +import javax.imageio.stream.ImageOutputStream; + +/** + * An abstract superclass for service providers that create + * {@linkplain javax.imageio.stream.ImageOutputStream image output + * streams} for a file, URL, byte array or any other target. + * + * @since 1.4 + * + * @author Sascha Brawer (brawer@dandelis.ch) + */ +public abstract class ImageOutputStreamSpi + extends IIOServiceProvider +{ + /** + * Indicates which kind of output is produced by the streams + * created by {@link #createOutputStreamInstance(Object)}. + */ + protected Class<?> outputClass; + + + /** + * Constructs a service provider for image output streams, given no + * parameters. It is up to the sub-class to set {@link #vendorName}, + * {@link #version} and {@link #outputClass} to non-null values. + */ + protected ImageOutputStreamSpi() + { + } + + + /** + * Constructs a service provider for image output streams, given the + * vendor name, a version string and the kind of producable output. + * + * @throws IllegalArgumentException if <code>vendorName</code> + * or <code>version</code> is <code>null</code>. + */ + public ImageOutputStreamSpi(String vendorName, String version, + Class<?> outputClass) + { + super(vendorName, version); + this.outputClass = outputClass; + } + + + /** + * Determines which kind of output is produced by the streams + * created by {@link #createOutputStreamInstance(Object)}. + */ + public Class<?> getOutputClass() + { + return outputClass; + } + + + /** + * Determines whether <code>ImageOutputStreams</code> created + * by this service provider benefit from using a cache file. + * + * <p>The default behavior is to return <code>false</code>. + * + * @return <code>true</code> if the created streams are faster or + * need less memory when a cache file is being used; + * <code>false</code> if no positive effect results from the cache + * file. + */ + public boolean canUseCacheFile() + { + return false; + } + + + /** + * Determines whether <code>ImageOutputStreams</code> created + * by this service provider require the use of a cache file. + * + * <p>The default behavior is to return <code>false</code>. + * + * @return <code>true</code> if the created streams can only work + * when a cache file is being used; <code>false</code> if no cache + * file is needed. + */ + public boolean needsCacheFile() + { + return false; + } + + + public abstract ImageOutputStream createOutputStreamInstance( + Object output, boolean useCache, File cacheDir) + throws IOException; + + + public ImageOutputStream createOutputStreamInstance(Object output) + throws IOException + { + return createOutputStreamInstance(output, canUseCacheFile(), null); + } +} diff --git a/libjava/classpath/javax/imageio/spi/ImageReaderSpi.java b/libjava/classpath/javax/imageio/spi/ImageReaderSpi.java new file mode 100644 index 000000000..3ffa93a0b --- /dev/null +++ b/libjava/classpath/javax/imageio/spi/ImageReaderSpi.java @@ -0,0 +1,121 @@ +/* ImageReaderSpi.java -- + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.imageio.spi; + +import java.io.IOException; + +import javax.imageio.ImageReader; +import javax.imageio.stream.ImageInputStream; + +/** + * @author Michael Koch (konqueror@gmx.de) + */ +public abstract class ImageReaderSpi extends ImageReaderWriterSpi +{ + public static final Class[] STANDARD_INPUT_TYPE = + { ImageInputStream.class }; + + protected Class[] inputTypes; + protected String[] writerSpiNames; + + protected ImageReaderSpi() + { + // Do nothing here. + } + + public ImageReaderSpi(String vendorName, String version, String[] names, + String[] suffixes, String[] MIMETypes, + String readerClassName, Class[] inputTypes, + String[] writerSpiNames, + boolean supportsStandardStreamMetadataFormat, + String nativeStreamMetadataFormatName, + String nativeStreamMetadataFormatClassName, + String[] extraStreamMetadataFormatNames, + String[] extraStreamMetadataFormatClassNames, + boolean supportsStandardImageMetadataFormat, + String nativeImageMetadataFormatName, + String nativeImageMetadataFormatClassName, + String[] extraImageMetadataFormatNames, + String[] extraImageMetadataFormatClassNames) + { + super(vendorName, version, names, suffixes, MIMETypes, readerClassName, + supportsStandardStreamMetadataFormat, nativeStreamMetadataFormatName, + nativeStreamMetadataFormatClassName, extraStreamMetadataFormatNames, + extraStreamMetadataFormatClassNames, supportsStandardImageMetadataFormat, + nativeImageMetadataFormatName, nativeImageMetadataFormatClassName, + extraImageMetadataFormatNames, extraImageMetadataFormatClassNames); + + if (inputTypes == null + || inputTypes.length == 0) + throw new IllegalArgumentException("inputTypes may not be null or empty"); + + this.inputTypes = inputTypes; + this.writerSpiNames = writerSpiNames; + } + + public abstract boolean canDecodeInput(Object source) + throws IOException; + + public ImageReader createReaderInstance() + throws IOException + { + return createReaderInstance(null); + } + + public abstract ImageReader createReaderInstance(Object extension) + throws IOException; + + public String[] getImageWriterSpiNames() + { + return writerSpiNames; + } + + public Class[] getInputTypes() + { + return inputTypes; + } + + public boolean isOwnReader(ImageReader reader) + { + if (reader == null) + throw new IllegalArgumentException("reader may not be null"); + + return pluginClassName.equals(reader.getClass().getName()); + } +} diff --git a/libjava/classpath/javax/imageio/spi/ImageReaderWriterSpi.java b/libjava/classpath/javax/imageio/spi/ImageReaderWriterSpi.java new file mode 100644 index 000000000..40d44e3d0 --- /dev/null +++ b/libjava/classpath/javax/imageio/spi/ImageReaderWriterSpi.java @@ -0,0 +1,511 @@ +/* ImageReaderWriterSpi.java -- Superclass for image reader and writer spis. + Copyright (C) 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.imageio.spi; + +import javax.imageio.metadata.IIOMetadataFormat; +import javax.imageio.metadata.IIOMetadataFormatImpl; + +/** + * An abstract superclass that contains the common parts of {@link + * javax.imageio.spi.ImageReaderSpi} and {@link + * javax.imageio.spi.ImageWriterSpi}. + * + * @since 1.4 + * + * @author Sascha Brawer (brawer@dandelis.ch) + */ +public abstract class ImageReaderWriterSpi + extends IIOServiceProvider +{ + /** + * The human-readable, localized names of the supported image + * formats. This value should be non-<code>null</code> after + * construction. + * + * @see #getFormatNames() + */ + protected String[] names; + + + /** + * The file suffixes of the supported image formats. This value + * should be non-<code>null</code> after construction. + * + * @see #getFileSuffixes() + */ + protected String[] suffixes; + + + /** + * The MIME types of the supported image formats. This value + * should be non-<code>null</code> after construction. + * + * @see #getMIMETypes() + */ + protected String[] MIMETypes; + + + /** + * The fully qualified name of the class that implements the {@link + * javax.imageio.ImageReader} or {@link javax.imageio.ImageWriter} + * interface. This value should be non-<code>null</code> after + * construction. + * + * @see #getPluginClassName() + */ + protected String pluginClassName; + + + /** + * Indicates whether the per-stream {@linkplain + * javax.imageio.metadata.IIOMetadata metadata objects} associated + * with this plug-in support format + * <code>“javax_imageio_1.0”</code> in their + * <code>getAsTree</code> and <code>setAsTree</code> methods. + * + * @see #isStandardStreamMetadataFormatSupported() + */ + protected boolean supportsStandardStreamMetadataFormat; + + + /** + * The name of the format that allows encoding all stream metadata + * without loss, or <code>null</code> if this plug-in does not + * provide a format that preserves all stream metadata. + */ + protected String nativeStreamMetadataFormatName; + + protected String nativeStreamMetadataFormatClassName; + + + /** + * The names of additional formats for encoding stream metadata, + * other than the {@linkplain + * #isStandardStreamMetadataFormatSupported() standard} and the + * {@linkplain #getNativeStreamMetadataFormatName() native} formats, + * or <code>null</code> if this plug-in does not provide any extra + * formats. + */ + protected String[] extraStreamMetadataFormatNames; + + + protected String[] extraStreamMetadataFormatClassNames; + + + /** + * Indicates whether the per-image {@linkplain + * javax.imageio.metadata.IIOMetadata metadata objects} associated + * with this plug-in support format + * <code>“javax_imageio_1.0”</code> in their + * <code>getAsTree</code> and <code>setAsTree</code> methods. + * + * @see #isStandardImageMetadataFormatSupported() + */ + protected boolean supportsStandardImageMetadataFormat; + + + /** + * The name of the format that allows encoding all image metadata + * without loss, or <code>null</code> if this plug-in does not + * provide a format that preserves all image metadata. + */ + protected String nativeImageMetadataFormatName; + + protected String nativeImageMetadataFormatClassName; + + + /** + * The names of additional formats for encoding image metadata, + * other than the {@linkplain + * #isStandardImageMetadataFormatSupported() standard} and the + * {@linkplain #getNativeImageMetadataFormatName() native} formats, + * or <code>null</code> if this plug-in does not provide any extra + * formats. + */ + protected String[] extraImageMetadataFormatNames; + + + protected String[] extraImageMetadataFormatClassNames; + + + /** + * Constructs an <code>ImageReaderWriteSpi</code> instance, without + * specifying a number of parameters. Constructors of concrete + * subclasses must ensure that they set all inherited fields to + * meaningful values. + */ + public ImageReaderWriterSpi() + { + } + + + /** + * Constructs an <code>ImageReaderWriteSpi</code> instance, + * specifying a number of parameters. + * + * @param names the human-readable, localized names of the supported + * image formats, for example <code>[“Tagged Image File + * Format”, “Portable Network + * Graphics”]</code>. + * + * @param suffixes the file suffixes of the supported image formats, + * for example <code>[“tiff”, “tif”, + * “png”]</code>. + * + * @param MIMETypes the MIME types of the supported image formats, + * for example <code>[“image/tiff”, + * “image/png”]</code>. + * + * @param pluginClassName the fully qualified name of the class that + * implements the {@link javax.imageio.ImageReader} or {@link + * javax.imageio.ImageWriter} interface. + * + * @param supportsStandardStreamMetadataFormat whether the + * per-stream {@linkplain javax.imageio.metadata.IIOMetadata + * metadata objects} associated with this plug-in support format + * <code>“javax_imageio_1.0”</code> in their + * <code>getAsTree</code> and <code>setAsTree</code> methods. + * + * @param nativeStreamMetadataFormatName the name of the format that + * allows encoding all stream metadata without loss, or + * <code>null</code> if this plug-in does not provide a format that + * preserves all stream metadata. + * + * @param extraStreamMetadataFormatNames the names of additional + * formats for encoding stream metadata, other than the {@linkplain + * #isStandardStreamMetadataFormatSupported() standard} and the + * {@linkplain #getNativeStreamMetadataFormatName() native} formats, + * or <code>null</code> if this plug-in does not provide any extra + * formats. + * + * @param supportsStandardImageMetadataFormat whether the per-image + * {@linkplain javax.imageio.metadata.IIOMetadata metadata objects} + * associated with this plug-in support format + * <code>“javax_imageio_1.0”</code> in their + * <code>getAsTree</code> and <code>setAsTree</code> methods. + * + * @param nativeImageMetadataFormatName the name of the format that + * allows encoding all image metadata without loss, or + * <code>null</code> if this plug-in does not provide a format that + * preserves all image metadata. + * + * @param extraImageMetadataFormatNames the names of additional + * formats for encoding image metadata, other than the {@linkplain + * #isStandardImageMetadataFormatSupported() standard} and the + * {@linkplain #getNativeImageMetadataFormatName() native} formats, + * or <code>null</code> if this plug-in does not provide any extra + * formats. + * + * @throws IllegalArgumentException if <code>vendorName</code> + * or <code>version</code> is <code>null</code>. + */ + public ImageReaderWriterSpi(String vendorName, String version, + String[] names, String[] suffixes, + String[] MIMETypes, String pluginClassName, + boolean supportsStandardStreamMetadataFormat, + String nativeStreamMetadataFormatName, + String nativeStreamMetadataFormatClassName, + String[] extraStreamMetadataFormatNames, + String[] extraStreamMetadataFormatClassNames, + boolean supportsStandardImageMetadataFormat, + String nativeImageMetadataFormatName, + String nativeImageMetadataFormatClassName, + String[] extraImageMetadataFormatNames, + String[] extraImageMetadataFormatClassNames) + { + /* The inherited constructor will throw IllegalArgumentException + * if one of its arguments is null. + */ + super(vendorName, version); + + if (names == null || names.length == 0 || pluginClassName == null) + throw new IllegalArgumentException(); + + this.names = names; + this.suffixes = suffixes; + this.MIMETypes = MIMETypes; + this.pluginClassName = pluginClassName; + + this.supportsStandardStreamMetadataFormat + = supportsStandardStreamMetadataFormat; + + this.nativeStreamMetadataFormatName + = nativeStreamMetadataFormatName; + + this.nativeStreamMetadataFormatClassName + = nativeStreamMetadataFormatClassName; + + this.extraStreamMetadataFormatNames + = extraStreamMetadataFormatNames; + + this.extraStreamMetadataFormatClassNames + = extraStreamMetadataFormatClassNames; + + this.supportsStandardImageMetadataFormat + = supportsStandardImageMetadataFormat; + + this.nativeImageMetadataFormatName + = nativeImageMetadataFormatName; + + this.nativeImageMetadataFormatClassName + = nativeImageMetadataFormatClassName; + + this.extraImageMetadataFormatNames + = extraImageMetadataFormatNames; + + this.extraImageMetadataFormatClassNames + = extraImageMetadataFormatClassNames; + } + + + /** + * Returns the human-readable, localized names of the supported + * image formats. For example, a plug-in might return an array with + * the elements <code>[“Tagged Image File Format”, + * “Portable Network Graphics”]</code>. + */ + public String[] getFormatNames() + { + return (String[]) names.clone(); + } + + + /** + * Returns the file suffixes of the supported image formats, for + * example <code>[“tiff”, “tif”, + * “png”]</code>. + */ + public String[] getFileSuffixes() + { + return suffixes; + } + + + /** + * Returns the MIME types of the supported image formats, for + * example <code>[“image/tiff”, + * “image/png”]</code>. + * + * @return an array of MIME type strings, or <code>null</code> if + * none of the supported formats has an associated MIME type. + */ + public String[] getMIMETypes() + { + return MIMETypes; + } + + + /** + * Returns the fully qualified name of the class that implements the + * {@link javax.imageio.ImageReader} or {@link + * javax.imageio.ImageWriter} interface. + */ + public String getPluginClassName() + { + return pluginClassName; + } + + + /** + * Returns whether the per-stream {@linkplain + * javax.imageio.metadata.IIOMetadata metadata objects} associated + * with this plug-in support format + * <code>“javax_imageio_1.0”</code> in their + * <code>getAsTree</code> and <code>setAsTree</code> methods. + */ + public boolean isStandardStreamMetadataFormatSupported() + { + return supportsStandardStreamMetadataFormat; + } + + + /** + * Returns the name of the format that allows encoding all stream + * metadata without loss, or <code>null</code> if this plug-in does + * not provide a format that preserves all stream metadata. + * + * @see #getNativeImageMetadataFormatName() + */ + public String getNativeStreamMetadataFormatName() + { + return nativeStreamMetadataFormatName; + } + + + /** + * Returns the names of additional formats for encoding stream + * metadata, other than the {@linkplain + * #isStandardStreamMetadataFormatSupported() standard} and the + * {@linkplain #getNativeStreamMetadataFormatName() native} formats, + * or <code>null</code> if this plug-in does not provide any extra + * formats. + * + * @see #getExtraImageMetadataFormatNames() + */ + public String[] getExtraStreamMetadataFormatNames() + { + return extraStreamMetadataFormatNames; + } + + + /** + * Returns whether the per-image {@linkplain + * javax.imageio.metadata.IIOMetadata metadata objects} associated + * with this plug-in support format + * <code>“javax_imageio_1.0”</code> in their + * <code>getAsTree</code> and <code>setAsTree</code> methods. + */ + public boolean isStandardImageMetadataFormatSupported() + { + return supportsStandardImageMetadataFormat; + } + + + /** + * Returns the name of the format that allows encoding all image + * metadata without loss, or <code>null</code> if this plug-in does + * not provide a format that preserves all image metadata. + * + * @see #getNativeStreamMetadataFormatName() + */ + public String getNativeImageMetadataFormatName() + { + return nativeImageMetadataFormatName; + } + + + /** + * Returns the names of additional formats for encoding image + * metadata, other than the {@linkplain + * #isStandardImageMetadataFormatSupported() standard} and the + * {@linkplain #getNativeImageMetadataFormatName() native} formats, + * or <code>null</code> if this plug-in does not provide any extra + * formats. + * + * @see #getExtraStreamMetadataFormatNames() + */ + public String[] getExtraImageMetadataFormatNames() + { + return extraImageMetadataFormatNames; + } + + /** + * Returns an IIOMetadataFormat object that represents the requested + * stream metadata format or null if the given format is supported + * but no IIOMetadataFormat can be created for it. + * + * @param formatName the requested stream metadata format name + * + * @return an IIOMetadataFormat object or null + * + * @throws IllegalArgumentException if formatName is null or is not + * one of the standard metadata format or this provider's native or + * extra stream metadata formats + */ + public IIOMetadataFormat getStreamMetadataFormat (String formatName) + { + if (formatName == null) + throw new IllegalArgumentException ("null stream metadata format name"); + + if (!formatName.equals (getNativeStreamMetadataFormatName()) + && !formatName.equals (IIOMetadataFormatImpl.standardMetadataFormatName)) + { + String[] extraNames = getExtraStreamMetadataFormatNames (); + boolean foundName = false; + for (int i = 0; i < extraNames.length; i++) + { + if (formatName.equals(extraNames[i])) + { + foundName = true; + break; + } + } + if (!foundName) + throw new IllegalArgumentException ("unsupported stream metadata format name"); + } + + if (formatName.equals (IIOMetadataFormatImpl.standardMetadataFormatName)) + return IIOMetadataFormatImpl.getStandardFormatInstance (); + else + // Default implementation returns null. + return null; + } + + /** + * Returns an IIOMetadataFormat object that represents the requested + * image metadata format or null if the given format is supported + * but no IIOMetadataFormat can be created for it. + * + * @param formatName the requested image metadata format name + * + * @return an IIOMetadataFormat object or null + * + * @throws IllegalArgumentException if formatName is null or is not + * one of the standard metadata format or this provider's native or + * extra image metadata formats + */ + public IIOMetadataFormat getImageMetadataFormat (String formatName) + { + if (formatName == null) + throw new IllegalArgumentException ("null image metadata format name"); + + if (!formatName.equals (getNativeImageMetadataFormatName()) + && !formatName.equals (IIOMetadataFormatImpl.standardMetadataFormatName)) + { + String[] extraNames = getExtraImageMetadataFormatNames (); + boolean foundName = false; + for (int i = 0; i < extraNames.length; i++) + { + if (formatName.equals(extraNames[i])) + { + foundName = true; + break; + } + } + if (!foundName) + throw new IllegalArgumentException ("unsupported image metadata format name"); + } + + if (formatName.equals (IIOMetadataFormatImpl.standardMetadataFormatName)) + return IIOMetadataFormatImpl.getStandardFormatInstance (); + else + // Default implementation returns null. + return null; + } +} diff --git a/libjava/classpath/javax/imageio/spi/ImageTranscoderSpi.java b/libjava/classpath/javax/imageio/spi/ImageTranscoderSpi.java new file mode 100644 index 000000000..1c04ad20c --- /dev/null +++ b/libjava/classpath/javax/imageio/spi/ImageTranscoderSpi.java @@ -0,0 +1,84 @@ +/* ImageTranscoderSpi.java -- Factory for image metadata transcoders. + Copyright (C) 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.imageio.spi; + +import javax.imageio.ImageTranscoder; + + +/** + * An abstract superclass for service providers that create + * {@linkplain javax.imageio.ImageTranscoder image metadata + * transcoders}. + * + * @since 1.4 + * + * @author Sascha Brawer (brawer@dandelis.ch) + */ +public abstract class ImageTranscoderSpi + extends IIOServiceProvider +{ + /** + * Constructs a service provider for image metadata transcoders, + * given no parameters. It is up to the sub-class to set {@link + * #vendorName} and {@link #version} to non-null values. + */ + protected ImageTranscoderSpi() + { + } + + + /** + * Constructs a service provider for image metadata transcoders, + * given the vendor name and a version string. + * + * @throws IllegalArgumentException if <code>vendorName</code> + * or <code>version</code> is <code>null</code>. + */ + public ImageTranscoderSpi(String vendorName, String version) + { + super(vendorName, version); + } + + + public abstract String getReaderServiceProviderName(); + + public abstract String getWriterServiceProviderName(); + + public abstract ImageTranscoder createTranscoderInstance(); +} diff --git a/libjava/classpath/javax/imageio/spi/ImageWriterSpi.java b/libjava/classpath/javax/imageio/spi/ImageWriterSpi.java new file mode 100644 index 000000000..6a07348cf --- /dev/null +++ b/libjava/classpath/javax/imageio/spi/ImageWriterSpi.java @@ -0,0 +1,135 @@ +/* ImageWriterSpi.java -- + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.imageio.spi; + +import java.awt.image.RenderedImage; +import java.io.IOException; + +import javax.imageio.ImageTypeSpecifier; +import javax.imageio.ImageWriter; +import javax.imageio.stream.ImageOutputStream; + +/** + * @author Michael Koch (konqueror@gmx.de) + */ +public abstract class ImageWriterSpi extends ImageReaderWriterSpi +{ + public static final Class[] STANDARD_OUTPUT_TYPE = + { ImageOutputStream.class }; + + protected Class[] outputTypes; + protected String[] readerSpiNames; + + protected ImageWriterSpi() + { + // Do nothing here. + } + + public ImageWriterSpi(String vendorName, String version, String[] names, + String[] suffixes, String[] MIMETypes, + String writerClassName, Class[] outputTypes, + String[] readerSpiNames, + boolean supportsStandardStreamMetadataFormat, + String nativeStreamMetadataFormatName, + String nativeStreamMetadataFormatClassName, + String[] extraStreamMetadataFormatNames, + String[] extraStreamMetadataFormatClassNames, + boolean supportsStandardImageMetadataFormat, + String nativeImageMetadataFormatName, + String nativeImageMetadataFormatClassName, + String[] extraImageMetadataFormatNames, + String[] extraImageMetadataFormatClassNames) + { + super(vendorName, version, names, suffixes, MIMETypes, writerClassName, + supportsStandardStreamMetadataFormat, nativeStreamMetadataFormatName, + nativeStreamMetadataFormatClassName, extraStreamMetadataFormatNames, + extraStreamMetadataFormatClassNames, supportsStandardImageMetadataFormat, + nativeImageMetadataFormatName, nativeImageMetadataFormatClassName, + extraImageMetadataFormatNames, extraImageMetadataFormatClassNames); + + if (writerClassName == null) + throw new IllegalArgumentException("writerClassName is null"); + + if (outputTypes == null + || outputTypes.length == 0) + throw new IllegalArgumentException("outputTypes may not be null or empty"); + + this.outputTypes = outputTypes; + this.readerSpiNames = readerSpiNames; + } + + public abstract boolean canEncodeImage(ImageTypeSpecifier type); + + public boolean canEncodeImage(RenderedImage image) + { + return canEncodeImage (new ImageTypeSpecifier(image)); + } + + public ImageWriter createWriterInstance() + throws IOException + { + return createWriterInstance(null); + } + + public abstract ImageWriter createWriterInstance(Object extension) + throws IOException; + + public String[] getImageReaderSpiNames() + { + return readerSpiNames; + } + + public Class[] getOutputTypes() + { + return outputTypes; + } + + public boolean isFormatLossless() + { + return true; + } + + public boolean isOwnWriter(ImageWriter writer) + { + if (writer == null) + throw new IllegalArgumentException("writer may not be null"); + + return pluginClassName.equals(writer.getClass().getName()); + } +} diff --git a/libjava/classpath/javax/imageio/spi/RegisterableService.java b/libjava/classpath/javax/imageio/spi/RegisterableService.java new file mode 100644 index 000000000..b424e04a3 --- /dev/null +++ b/libjava/classpath/javax/imageio/spi/RegisterableService.java @@ -0,0 +1,82 @@ +/* RegisterableService.java -- An interface for service providers. + Copyright (C) 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.imageio.spi; + + +/** + * An interface which service providers may optionally implement in + * order to get notified when they are added or removed from a {@link + * ServiceRegistry}. + * + * @since 1.4 + * + * @author Sascha Brawer (brawer@dandelis.ch) + */ +public interface RegisterableService +{ + /** + * Informs this service provider that it has been registered in a + * {@link ServiceRegistry}. If this provider gets registered as an + * implementor for several service categories, its + * <code>onRegistration</code> method will be called multiple times. + * + * @param registry the registry to which this service provider has + * been added. + * + * @param category the service category for which this provider has + * been registered as an implementor. + */ + void onRegistration(ServiceRegistry registry, Class<?> category); + + + /** + * Informs this service provider that it has been de-registered from + * a {@link ServiceRegistry}. If this provider had been registered + * as an implementor for several service categories, its + * <code>onDeregistration</code> method will be called multiple + * times. + * + * @param registry the registry from which this service provider has + * been removed. + * + * @param category the service category for which this provider has + * been registered as an implementor. + */ + void onDeregistration(ServiceRegistry registry, Class<?> category); +} diff --git a/libjava/classpath/javax/imageio/spi/ServiceRegistry.java b/libjava/classpath/javax/imageio/spi/ServiceRegistry.java new file mode 100644 index 000000000..d92359688 --- /dev/null +++ b/libjava/classpath/javax/imageio/spi/ServiceRegistry.java @@ -0,0 +1,961 @@ +/* ServiceRegistry.java -- A simple registry for service providers. + Copyright (C) 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.imageio.spi; + +import gnu.classpath.ServiceFactory; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashSet; +import java.util.IdentityHashMap; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.Map; +import java.util.NoSuchElementException; +import java.util.Set; + +/** + * A registry for service providers. + * + * @since 1.4 + * + * @author Michael Koch (konqueror@gmx.de) + * @author Sascha Brawer (brawer@dandelis.ch) + */ +public class ServiceRegistry +{ + // Package-private to avoid a trampoline. + /** + * The service categories of this registry. + * + * <p>Note that we expect that only very few categories will + * typically be used with a registry. The most common case will be + * one, it seems unlikely that any registry would contain more than + * five or six categories. Therefore, we intentionally avoid the + * overhead of a HashMap. + * + * @see #providers + */ + final Class[] categories; + + + /** + * The registered providers for each service category, indexed by + * the same index as the {@link #categories} array. If no provider + * is registered for a category, the array entry will be + * <code>null</code>. + * + * <p>Note that we expect that only very few providers will + * typically be registered for a category. The most common case will + * be one or two. Therefore, we intentionally avoid the overhead of + * a HashMap. + */ + private final LinkedList[] providers; + + + /** + * The ordring constaints for each service category, indexed by the + * same index as the {@link #categories} array. The constraints for + * a service category are stored as a <code>Map<Object, + * Set<Object>></code>, where the Map’s values are + * those providers that need to come after the key. If no + * constraints are imposed on the providers of a category, the array + * entry will be <code>null</code>. If no constraints have been set + * whatsoever, <code>constraints</code> will be <code>null</code>. + * + * <p>Note that we expect that only very few constraints will + * typically be imposed on a category. The most common case will + * be zero. + */ + private IdentityHashMap[] constraints; + + + /** + * Constructs a <code>ServiceRegistry</code> for the specified + * service categories. + * + * @param categories the categories to support + * + * @throws IllegalArgumentException if <code>categories</code> is + * <code>null</code>, or if its {@link Iterator#next()} method + * returns <code>null</code>. + * + * @throws ClassCastException if <code>categories</code> does not + * iterate over instances of {@link java.lang.Class}. + */ + public ServiceRegistry(Iterator<Class<?>> categories) + { + ArrayList cats = new ArrayList(/* expected size */ 10); + + if (categories == null) + throw new IllegalArgumentException(); + + while (categories.hasNext()) + { + Class cat = (Class) categories.next(); + if (cat == null) + throw new IllegalArgumentException(); + cats.add(cat); + } + + int numCats = cats.size(); + this.categories = (Class[]) cats.toArray(new Class[numCats]); + this.providers = new LinkedList[numCats]; + } + + + /** + * Finds service providers that are implementing the specified + * Service Provider Interface. + * + * <p><b>On-demand loading:</b> Loading and initializing service + * providers is delayed as much as possible. The rationale is that + * typical clients will iterate through the set of installed service + * providers until one is found that matches some criteria (like + * supported formats, or quality of service). In such scenarios, it + * might make sense to install only the frequently needed service + * providers on the local machine. More exotic providers can be put + * onto a server; the server will only be contacted when no suitable + * service could be found locally.</p> + * + * <p><b>Security considerations:</b> Any loaded service providers + * are loaded through the specified ClassLoader, or the system + * ClassLoader if <code>classLoader</code> is + * <code>null</code>. When <code>lookupProviders</code> is called, + * the current {@link java.security.AccessControlContext} gets + * recorded. This captured security context will determine the + * permissions when services get loaded via the <code>next()</code> + * method of the returned <code>Iterator</code>.</p> + * + * @param spi the service provider interface which must be + * implemented by any loaded service providers. + * + * @param loader the class loader that will be used to load the + * service providers, or <code>null</code> for the system class + * loader. For using the context class loader, see {@link + * #lookupProviders(Class)}. + * + * @return an iterator over instances of <code>spi</code>. + * + * @throws IllegalArgumentException if <code>spi</code> is + * <code>null</code>. + */ + public static <T> Iterator<T> lookupProviders(Class<T> spi, + ClassLoader loader) + { + return ServiceFactory.lookupProviders(spi, loader); + } + + + /** + * Finds service providers that are implementing the specified + * Service Provider Interface, using the context class loader + * for loading providers. + * + * @param spi the service provider interface which must be + * implemented by any loaded service providers. + * + * @return an iterator over instances of <code>spi</code>. + * + * @throws IllegalArgumentException if <code>spi</code> is + * <code>null</code>. + * + * @see #lookupProviders(Class, ClassLoader) + */ + public static <T> Iterator<T> lookupProviders(Class<T> spi) + { + return ServiceFactory.lookupProviders(spi); + } + + + /** + * Returns an iterator over all service categories. + * + * @return an unmodifiable {@link + * java.util.Iterator}<{@link java.lang.Class}>. + */ + public Iterator<Class<?>> getCategories() + { + return new Iterator() + { + int index = -1; + + public boolean hasNext() + { + return index < categories.length - 1; + } + + public Object next() + { + if (!hasNext()) + throw new NoSuchElementException(); + + return categories[++index]; + } + + public void remove() + { + throw new UnsupportedOperationException(); + } + }; + } + + + /** + * Registers a provider for a service category which is specified by + * the class-internal category ID. + * + * @param provider the service provider to be registered. + * + * @param cat the service category, which is identified by an index + * into the {@link #categories} array. + * + * @return <code>true</code> if <code>provider</code> is the first + * provider that gets registered for the specified service category; + * <code>false</code> if other providers have already been + * registered for the same servide category. + * + * @throws IllegalArgumentException if <code>provider</code> is + * <code>null</code>. + * + * @throws ClassCastException if <code>provider</code> does not + * implement the specified service provider interface. + */ + private synchronized boolean registerServiceProvider(Object provider, + int cat) + { + LinkedList provs; + boolean result; + Class category; + + if (provider == null) + throw new IllegalArgumentException(); + + category = categories[cat]; + if (!category.isInstance(provider)) + throw new ClassCastException(category.getName()); + + provs = providers[cat]; + if (provs == null) + { + result = true; + provs = providers[cat] = new LinkedList(); + } + else + result = false; + + provs.add(provider); + if (provider instanceof RegisterableService) + ((RegisterableService) provider).onRegistration(this, category); + + return result; + } + + + /** + * Registers a provider for the specified service category. + * + * <p>If <code>provider</code> implements the {@link + * RegisterableService} interface, its {@link + * RegisterableService#onRegistration onRegistration} method is + * invoked in order to inform the provider about the addition to + * this registry. + * + * @param provider the service provider to be registered. + * + * @param category the service category under which + * <code>provider</code> shall be registered. + * + * @return <code>true</code> if <code>provider</code> is the first + * provider that gets registered for the specified service category; + * <code>false</code> if other providers have already been + * registered for the same servide category. + * + * @throws IllegalArgumentException if <code>provider</code> is + * <code>null</code>, or if <code>category</code> is not among the + * categories passed to the {@linkplain #ServiceRegistry(Iterator) + * constructor} of this ServiceRegistry. + * + * @throws ClassCastException if <code>provider</code> does not + * implement <code>category</code>. + */ + public synchronized <T> boolean registerServiceProvider(T provider, + Class<T> category) + { + for (int i = 0; i < categories.length; i++) + if (categories[i] == category) + return registerServiceProvider(provider, i); + throw new IllegalArgumentException(); + } + + + /** + * Registers a provider under all service categories it + * implements. + * + * <p>If <code>provider</code> implements the {@link + * RegisterableService} interface, its {@link + * RegisterableService#onRegistration onRegistration} method is + * invoked in order to inform the provider about the addition to + * this registry. If <code>provider</code> implements several + * service categories, <code>onRegistration</code> gets called + * multiple times. + * + * @param provider the service provider to be registered. + * + * @throws IllegalArgumentException if <code>provider</code> is + * <code>null</code>, or if <code>provider</code> does not implement + * any of the service categories passed to the {@linkplain + * #ServiceRegistry(Iterator) constructor} of this ServiceRegistry. + */ + public synchronized void registerServiceProvider(Object provider) + { + boolean ok = false; + + if (provider == null) + throw new IllegalArgumentException(); + + for (int i = 0; i < categories.length; i++) + if (categories[i].isInstance(provider)) + { + ok = true; + registerServiceProvider(provider, i); + } + + if (!ok) + throw new IllegalArgumentException(); + } + + + /** + * Registers a number of providers under all service categories they + * implement. + * + * <p>If a provider implements the {@link RegisterableService} + * interface, its {@link RegisterableService#onRegistration + * onRegistration} method is invoked in order to inform the provider + * about the addition to this registry. If <code>provider</code> + * implements several service categories, + * <code>onRegistration</code> gets called multiple times. + * + * @throws IllegalArgumentException if <code>providers</code> is + * <code>null</code>, if any iterated provider is <code>null</code>, + * or if some iterated provider does not implement any of the + * service categories passed to the {@linkplain + * #ServiceRegistry(Iterator) constructor} of this + * <code>ServiceRegistry</code>. + */ + public synchronized void registerServiceProviders(Iterator<?> providers) + { + if (providers == null) + throw new IllegalArgumentException(); + + while (providers.hasNext()) + registerServiceProvider(providers.next()); + } + + + /** + * De-registers a provider for a service category which is specified + * by the class-internal category ID. + * + * @param provider the service provider to be registered. + * + * @param cat the service category, which is identified by an index + * into the {@link #categories} array. + * + * @return <code>true</code> if <code>provider</code> was previously + * registered for the specified service category; <code>false</code> + * if if the provider had not been registered. + * + * @throws IllegalArgumentException if <code>provider</code> is + * <code>null</code>. + * + * @throws ClassCastException if <code>provider</code> does not + * implement the specified service provider interface. + */ + private synchronized boolean deregisterServiceProvider(Object provider, + int cat) + { + LinkedList provs; + boolean result; + Class category; + + if (provider == null) + throw new IllegalArgumentException(); + + category = categories[cat]; + if (!category.isInstance(provider)) + throw new ClassCastException(category.getName()); + + provs = providers[cat]; + if (provs == null) + return false; + + result = provs.remove(provider); + if (provs.isEmpty()) + providers[cat] = null; + + if (result && (provider instanceof RegisterableService)) + ((RegisterableService) provider).onDeregistration(this, category); + + return result; + } + + + /** + * De-registers a provider for the specified service category. + * + * <p>If <code>provider</code> implements the {@link + * RegisterableService} interface, its {@link + * RegisterableService#onDeregistration onDeregistration} method is + * invoked in order to inform the provider about the removal from + * this registry. + * + * @param provider the service provider to be de-registered. + * + * @param category the service category from which + * <code>provider</code> shall be de-registered. + * + * @return <code>true</code> if <code>provider</code> was previously + * registered for the specified service category; <code>false</code> + * if if the provider had not been registered. + * + * @throws IllegalArgumentException if <code>provider</code> is + * <code>null</code>, or if <code>category</code> is not among the + * categories passed to the {@linkplain #ServiceRegistry(Iterator) + * constructor} of this ServiceRegistry. + * + * @throws ClassCastException if <code>provider</code> does not + * implement <code>category</code>. + */ + public synchronized <T> boolean deregisterServiceProvider(T provider, + Class<T> category) + { + for (int i = 0; i < categories.length; i++) + if (categories[i] == category) + return deregisterServiceProvider(provider, i); + throw new IllegalArgumentException(); + } + + + /** + * De-registers a provider from all service categories it + * implements. + * + * <p>If <code>provider</code> implements the {@link + * RegisterableService} interface, its {@link + * RegisterableService#onDeregistration onDeregistration} method is + * invoked in order to inform the provider about the removal from + * this registry. If <code>provider</code> implements several + * service categories, <code>onDeregistration</code> gets called + * multiple times.</p> + * + * @param provider the service provider to be de-registered. + * + * @throws IllegalArgumentException if <code>provider</code> is + * <code>null</code>, or if <code>provider</code> does not implement + * any of the service categories passed to the {@linkplain + * #ServiceRegistry(Iterator) constructor} of this + * <code>ServiceRegistry</code>. + */ + public synchronized void deregisterServiceProvider(Object provider) + { + boolean ok = false; + + if (provider == null) + throw new IllegalArgumentException(); + + for (int i = 0; i < categories.length; i++) + if (categories[i].isInstance(provider)) + { + ok = true; + deregisterServiceProvider(provider, i); + } + + if (!ok) + throw new IllegalArgumentException(); + } + + + /** + * De-registers all providers which have been registered for the + * specified service category. + * + * <p>If a provider implements the {@link RegisterableService} + * interface, its {@link RegisterableService#onDeregistration + * onDeregistration} method is invoked in order to inform the + * provider about the removal from this registry. If the provider + * implements several service categories, + * <code>onDeregistration</code> gets called multiple times. + * + * @param category the category whose registered providers will be + * de-registered. + * + * @throws IllegalArgumentException if <code>category</code> is not + * among the categories passed to the {@linkplain + * #ServiceRegistry(Iterator) constructor} of this + * <code>ServiceRegistry</code>. + */ + public synchronized void deregisterAll(Class<?> category) + { + boolean ok = false; + + for (int i = 0; i < categories.length; i++) + { + if (categories[i] != category) + continue; + + ok = true; + while (providers[i] != null) + deregisterServiceProvider(providers[i].get(0), i); + } + + if (!ok) + throw new IllegalArgumentException(); + } + + + /** + * De-registers all service providers. + * + * <p>If a provider implements the {@link RegisterableService} + * interface, its {@link RegisterableService#onDeregistration + * onDeregistration} method is invoked in order to inform the + * provider about the removal from this registry. If the provider + * implements several service categories, + * <code>onDeregistration</code> gets called multiple times. + */ + public synchronized void deregisterAll() + { + for (int i = 0; i < categories.length; i++) + while (providers[i] != null) + deregisterServiceProvider(providers[i].get(0), i); + } + + + /** + * Called by the Virtual Machine when it detects that this + * <code>ServiceRegistry</code> has become garbage. De-registers all + * service providers, which will cause those that implement {@link + * RegisterableService} to receive a {@link + * RegisterableService#onDeregistration onDeregistration} + * notification. + */ + public void finalize() + throws Throwable + { + super.finalize(); + deregisterAll(); + } + + + /** + * Determines whether a provider has been registered with this + * registry. + * + * @return <code>true</code> if <code>provider</code> has been + * registered under any service category; <code>false</code> if + * it is not registered. + * + * @throws IllegalArgumentException if <code>provider</code> is + * <code>null</code>. + */ + public synchronized boolean contains(Object provider) + { + if (provider == null) + throw new IllegalArgumentException(); + + // Note that contains is rather unlikely to be ever called, + // so it would be wasteful to keep a special data structure + // (such as a HashSet) for making it a fast operation. + for (int i = 0; i < providers.length; i++) + { + // If provider does not implement categories[i], + // it would not have been possible to register it there. + // In that case, it would be pointless to look there. + if (!categories[i].isInstance(provider)) + continue; + + // But if the list of registered providers contains provider, + // we have found it. + LinkedList p = providers[i]; + if (p != null && p.contains(provider)) + return true; + } + + return false; + } + + + /** + * Returns the index in {@link #categories} occupied by the + * specified service category. + * + * @throws IllegalArgumentException if <code>category</code> is not + * among the categories passed to the {@linkplain + * #ServiceRegistry(Iterator) constructor} of this ServiceRegistry. + */ + private int getCategoryID(Class category) + { + for (int i = 0; i < categories.length; i++) + if (categories[i] == category) + return i; + + throw new IllegalArgumentException(); + } + + + /** + * Retrieves all providers that have been registered for the + * specified service category. + * + * @param category the service category whose providers are + * to be retrieved. + * + * @param useOrdering <code>true</code> in order to retrieve the + * providers in an order imposed by the {@linkplain #setOrdering + * ordering constraints}; <code>false</code> in order to retrieve + * the providers in any order. + * + * @throws IllegalArgumentException if <code>category</code> is not + * among the categories passed to the {@linkplain + * #ServiceRegistry(Iterator) constructor} of this + * <code>ServiceRegistry</code>. + * + * @see #getServiceProviders(Class, Filter, boolean) + */ + public <T> Iterator<T> getServiceProviders(Class<T> category, + boolean useOrdering) + { + return getServiceProviders(category, null, useOrdering); + } + + + /** + * Retrieves all providers that have been registered for the + * specified service category and that satisfy the criteria + * of a custom filter. + * + * @param category the service category whose providers are + * to be retrieved. + * + * @param filter a custom filter, or <code>null</code> to + * retrieve all registered providers for the specified + * category. + * + * @param useOrdering <code>true</code> in order to retrieve the + * providers in an order imposed by the {@linkplain #setOrdering + * ordering constraints}; <code>false</code> in order to retrieve + * the providers in any order. + * + * @throws IllegalArgumentException if <code>category</code> is not + * among the categories passed to the {@linkplain + * #ServiceRegistry(Iterator) constructor} of this + * <code>ServiceRegistry</code>. + */ + public synchronized <T> Iterator<T> getServiceProviders(Class<T> category, + Filter filter, + boolean useOrdering) + { + int catid; + LinkedList provs; + ArrayList result; + + catid = getCategoryID(category); + provs = providers[catid]; + if (provs == null) + return Collections.EMPTY_LIST.iterator(); + + result = new ArrayList(provs.size()); + for (Iterator iter = provs.iterator(); iter.hasNext();) + { + Object provider = iter.next(); + if (filter == null || filter.filter(provider)) + result.add(provider); + } + + // If we are supposed to obey ordering constraints, and + // if any constraints have been imposed on the specified + // service category, sort the result. + if (useOrdering && constraints != null) + { + final Map cons = constraints[catid]; + if (cons != null) + Collections.sort(result, new Comparator() + { + public int compare(Object o1, Object o2) + { + Set s; + + if (o1 == o2) + return 0; + + s = (Set) cons.get(o1); + if (s != null && s.contains(o2)) + return -1; // o1 < o2 + + s = (Set) cons.get(o2); + if (s != null && s.contains(o1)) + return 1; // o1 > o2 + + return 0; // o1 == o2 + } + }); + } + + return result.iterator(); + } + + + /** + * Returns one of the service providers that is a subclass of the + * specified class. + * + * @param providerClass a class to search for. + */ + public synchronized <T> T getServiceProviderByClass(Class<T> providerClass) + { + if (providerClass == null) + throw new IllegalArgumentException(); + + // Note that the method getServiceProviderByClass is rather + // unlikely to be ever called, so it would be wasteful to keep a + // special data structure for making it a fast operation. + for (int cat = 0; cat < categories.length; cat++) + { + if (!categories[cat].isAssignableFrom(providerClass)) + continue; + + LinkedList provs = providers[cat]; + if (provs == null) + continue; + + for (Iterator iter = provs.iterator(); iter.hasNext();) + { + Object provider = iter.next(); + if (providerClass.isInstance(provider)) + return (T) provider; + } + } + + return null; + } + + + /** + * Adds an ordering constraint on service providers. + * + * @param category the service category to which an ordering + * constraint is to be added. + * + * @param firstProvider the provider which is supposed to come before + * <code>second</code>. + * + * @param secondProvider the provider which is supposed to come after + * <code>first</code>. + * + * @throws IllegalArgumentException if <code>first</code> and + * <code>second</code> are referring to the same object, or if one + * of them is <code>null</code>. + * + * @see #unsetOrdering + * @see #getServiceProviders(Class, Filter, boolean) + */ + public synchronized <T> boolean setOrdering(Class<T> category, + T firstProvider, + T secondProvider) + { + return addConstraint(getCategoryID(category), firstProvider, + secondProvider); + } + + + /** + * Removes an ordering constraint on service providers. + * + * @param category the service category from which an ordering + * constraint is to be removed. + * + * @param firstProvider the provider which is supposed to come before + * <code>second</code>. + * + * @param secondProvider the provider which is supposed to come after + * <code>first</code>. + * + * @throws IllegalArgumentException if <code>first</code> and + * <code>second</code> are referring to the same object, or if one + * of them is <code>null</code>. + * + * @see #setOrdering + */ + public synchronized <T> boolean unsetOrdering(Class<T> category, + T firstProvider, + T secondProvider) + { + return removeConstraint(getCategoryID(category), + firstProvider, secondProvider); + } + + + /** + * Adds an ordering constraint on service providers. + * + * @param catid the service category ID, which is the + * category’s index into the {@link #categories} array. + * + * @param first the provider which is supposed to come before + * <code>second</code>. + * + * @param second the provider which is supposed to come after + * <code>first</code>. + * + * @throws IllegalArgumentException if <code>first</code> and + * <code>second</code> are referring to the same object, or if one + * of them is <code>null</code>. + */ + private boolean addConstraint(int catid, Object first, Object second) + { + Set s; + IdentityHashMap cons; + + // Also checks argument validity. + removeConstraint(catid, second, first); + + if (constraints == null) + constraints = new IdentityHashMap[categories.length]; + cons = constraints[catid]; + if (cons == null) + cons = constraints[catid] = new IdentityHashMap(); + + s = (Set) cons.get(first); + if (s == null) + cons.put(first, s = new HashSet()); + return s.add(second); + } + + + /** + * Removes an ordering constraint on service providers. + * + * @param catid the service category ID, which is the + * category’s index into the {@link #categories} array. + * + * @param first the provider which is supposed to come before + * <code>second</code>. + * + * @param second the provider which is supposed to come after + * <code>first</code>. + * + * @throws IllegalArgumentException if <code>first</code> and + * <code>second</code> are referring to the same object, or if one + * of them is <code>null</code>. + */ + private boolean removeConstraint(int catid, Object first, Object second) + { + Collection s; + IdentityHashMap cons; + + if (first == null || second == null || first == second) + throw new IllegalArgumentException(); + + if (constraints == null) + return false; + + cons = constraints[catid]; + if (cons == null) + return false; + + s = (Collection) cons.get(first); + if (s == null) + return false; + + if (!s.remove(second)) + return false; + + // If we removed the last constraint for a service category, + // we can get free some memory. + if (cons.isEmpty()) + { + constraints[catid] = null; + boolean anyConstraints = false; + for (int i = 0; i < constraints.length; i++) + { + if (constraints[i] != null) + { + anyConstraints = true; + break; + } + } + if (!anyConstraints) + constraints = null; + } + + return true; + } + + + /** + * A filter for selecting service providers that match custom + * criteria. + * + * @see ServiceRegistry#getServiceProviders(Class, Filter, + * boolean) + * + * @since 1.4 + * + * @author Michael Koch (konqueror@gmx.de) + * @author Sascha Brawer (brawer@dandelis.ch) + */ + public static interface Filter + { + /** + * Checks whether the specified service provider matches the + * constraints of this Filter. + * + * @param provider the service provider in question. + * + * @return <code>true</code> if <code>provider</code> matches the + * criteria; <code>false</code> if it does not match. + */ + boolean filter(Object provider); + } +} diff --git a/libjava/classpath/javax/imageio/spi/package.html b/libjava/classpath/javax/imageio/spi/package.html new file mode 100644 index 000000000..69fe33f60 --- /dev/null +++ b/libjava/classpath/javax/imageio/spi/package.html @@ -0,0 +1,46 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> +<!-- package.html - describes classes in javax.imageio.spi package. + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. --> + +<html> +<head><title>GNU Classpath - javax.imageio.spi</title></head> + +<body> +<p></p> + +</body> +</html> diff --git a/libjava/classpath/javax/imageio/stream/FileCacheImageInputStream.java b/libjava/classpath/javax/imageio/stream/FileCacheImageInputStream.java new file mode 100644 index 000000000..2717e079d --- /dev/null +++ b/libjava/classpath/javax/imageio/stream/FileCacheImageInputStream.java @@ -0,0 +1,109 @@ +/* FileCacheImageInputStream.java -- + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.imageio.stream; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; + +/** + * @author Michael Koch (konqueror@gmx.de) + */ +public class FileCacheImageInputStream extends ImageInputStreamImpl +{ + private InputStream stream; + private File cacheDir; + + public FileCacheImageInputStream(InputStream stream, File cacheDir) + throws IOException + { + super(); + this.stream = stream; + // FIXME: We do not support caching yet. + this.cacheDir = cacheDir; + } + + public void close() + throws IOException + { + if (stream != null) + { + stream.close(); + stream = null; + } + } + + private void checkStreamClosed() + throws IOException + { + if (stream == null) + throw new IOException("stream closed"); + } + + public boolean isCached() + { + return true; + } + + public boolean isCachedFile() + { + return true; + } + + public boolean isCachedMemory() + { + return false; + } + + public int read() + throws IOException + { + checkStreamClosed(); + setBitOffset(0); + return stream.read(); + } + + public int read(byte[] data, int offset, int len) + throws IOException + { + checkStreamClosed(); + setBitOffset(0); + return stream.read(data, offset, len); + } +} diff --git a/libjava/classpath/javax/imageio/stream/FileCacheImageOutputStream.java b/libjava/classpath/javax/imageio/stream/FileCacheImageOutputStream.java new file mode 100644 index 000000000..1d73a05e5 --- /dev/null +++ b/libjava/classpath/javax/imageio/stream/FileCacheImageOutputStream.java @@ -0,0 +1,178 @@ +/* FileCacheImageOutputStream.java -- + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.imageio.stream; + +import java.io.File; +import java.io.IOException; +import java.io.OutputStream; +import java.io.RandomAccessFile; + +/** + * @author Michael Koch (konqueror@gmx.de) + */ +public class FileCacheImageOutputStream extends ImageOutputStreamImpl +{ + private OutputStream stream; + private File cacheFile; + private RandomAccessFile cache; + private long maxPos; + + public FileCacheImageOutputStream(OutputStream s, File cacheDir) + throws IOException + { + stream = s; + cacheFile = File.createTempFile("imageio", ".tmp", cacheDir); + cache = new RandomAccessFile(cacheFile, "rw"); + maxPos = 0; + } + + public void close() + throws IOException + { + maxPos = cache.length(); + seek(maxPos); + flushBefore(maxPos); + super.close(); + cache.close(); + cacheFile.delete(); + stream.flush(); + stream = null; + } + + public boolean isCached() + { + return true; + } + + public boolean isCachedFile() + { + return true; + } + + public boolean isCachedMemory() + { + return false; + } + + public int read() + throws IOException + { + bitOffset = 0; + int val = cache.read(); + if (val != -1) + streamPos++; + return val; + } + + public int read(byte[] data, int offset, int len) + throws IOException + { + bitOffset = 0; + int num = cache.read(data, offset, len); + if (num != -1) + streamPos += num; + return num; + } + + public void write(byte[] data, int offset, int len) + throws IOException + { + flushBits(); + cache.write(data, offset, len); + streamPos += len; + maxPos = Math.max(streamPos, maxPos); + } + + public void write(int value) + throws IOException + { + flushBits(); + cache.write(value); + streamPos++; + maxPos = Math.max(streamPos, maxPos); + } + + public long length() + { + long l; + try + { + l = cache.length(); + } + catch (IOException ex) + { + l = -1; + } + return l; + } + + public void seek(long pos) + throws IOException + { + checkClosed(); + if (pos < flushedPos) + throw new IndexOutOfBoundsException(); + cache.seek(pos); + streamPos = cache.getFilePointer(); + maxPos = Math.max(streamPos, maxPos); + bitOffset = 0; + } + + public void flushBefore(long pos) + throws IOException + { + long oldPos = flushedPos; + super.flushBefore(pos); + long flushed = flushedPos - oldPos; + if (flushed > 0) + { + int len = 512; + byte[] buf = new byte[len]; + cache.seek(oldPos); + while (flushed > 0) + { + int l = (int) Math.min(flushed, len); + cache.readFully(buf, 0, l); + stream.write(buf, 0, l); + flushed -= l; + } + stream.flush(); + } + } +} diff --git a/libjava/classpath/javax/imageio/stream/FileImageInputStream.java b/libjava/classpath/javax/imageio/stream/FileImageInputStream.java new file mode 100644 index 000000000..abdd997ba --- /dev/null +++ b/libjava/classpath/javax/imageio/stream/FileImageInputStream.java @@ -0,0 +1,108 @@ +/* FileImageInputStream.java -- + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.imageio.stream; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.RandomAccessFile; + +/** + * @author Michael Koch (konqueror@gmx.de) + */ +public class FileImageInputStream extends ImageInputStreamImpl +{ + private RandomAccessFile file; + + public FileImageInputStream(File file) + throws FileNotFoundException, IOException + { + if (file == null) + throw new IllegalArgumentException ("file may not be null"); + + this.file = new RandomAccessFile(file, "r"); + } + + public FileImageInputStream(RandomAccessFile file) + { + if (file == null) + throw new IllegalArgumentException ("file may not be null"); + + this.file = file; + } + + public void close() + throws IOException + { + file.close(); + } + + public long length() + { + try + { + return file.length(); + } + catch (IOException e) + { + return -1L; + } + } + + public int read() + throws IOException + { + setBitOffset(0); + return file.read(); + } + + public int read(byte[] data, int offset, int len) + throws IOException + { + setBitOffset(0); + return file.read(data, offset, len); + } + + public void seek(long position) + throws IOException + { + super.seek(position); + file.seek(position); + } +} diff --git a/libjava/classpath/javax/imageio/stream/FileImageOutputStream.java b/libjava/classpath/javax/imageio/stream/FileImageOutputStream.java new file mode 100644 index 000000000..7d5d8fbe0 --- /dev/null +++ b/libjava/classpath/javax/imageio/stream/FileImageOutputStream.java @@ -0,0 +1,133 @@ +/* FileImageOutputStream.java -- + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.imageio.stream; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.RandomAccessFile; + +/** + * @author Michael Koch (konqueror@gmx.de) + */ +public class FileImageOutputStream extends ImageOutputStreamImpl +{ + private RandomAccessFile file; + + public FileImageOutputStream(File file) + throws FileNotFoundException, IOException + { + if (file == null) + throw new IllegalArgumentException("file may not be null"); + + // Do security check. + file.canRead(); + + this.file = new RandomAccessFile(file, "r"); + } + + public FileImageOutputStream(RandomAccessFile file) + { + if (file == null) + throw new IllegalArgumentException("file may not be null"); + + this.file = file; + } + + public void close() + throws IOException + { + file.close(); + } + + public long length() + { + try + { + return file.length(); + } + catch (IOException e) + { + return -1L; + } + } + + public int read() + throws IOException + { + checkClosed(); + + setBitOffset(0); + return file.read(); + } + + public int read(byte[] data, int offset, int len) + throws IOException + { + checkClosed(); + + setBitOffset(0); + return file.read(data, offset, len); + } + + public void seek(long position) + throws IOException + { + super.seek(position); + file.seek(position); + } + + public void write(byte[] data, int offset, int len) + throws IOException + { + checkClosed(); + + flushBits(); + file.write(data, offset, len); + } + + public void write(int value) + throws IOException + { + checkClosed(); + + // FIXME: Flush pending bits. + file.write(value); + } +} diff --git a/libjava/classpath/javax/imageio/stream/IIOByteBuffer.java b/libjava/classpath/javax/imageio/stream/IIOByteBuffer.java new file mode 100644 index 000000000..f783653a7 --- /dev/null +++ b/libjava/classpath/javax/imageio/stream/IIOByteBuffer.java @@ -0,0 +1,94 @@ +/* IIOByteBuffer.java + Copyright (C) 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.imageio.stream; + +/** + * A data structure for holding a reference to a byte array, an index + * into that array, and a number of bytes, that can be passed to one + * specific variant of the {@link + * javax.imageio.stream.ImageInputStream#readBytes(IIOByteBuffer, int) + * readBytes} method. + * + * @since 1.4 + * + * @author Sascha Brawer (brawer@dandelis.ch) + */ +public class IIOByteBuffer +{ + private byte[] data; + private int offset; + private int length; + + public IIOByteBuffer(byte[] data, int offset, int length) + { + this.data = data; + this.offset = offset; + this.length = length; + } + + public byte[] getData() + { + return data; + } + + public void setData(byte[] data) + { + this.data = data; + } + + public int getOffset() + { + return offset; + } + + public void setOffset(int offset) + { + this.offset = offset; + } + + public int getLength() + { + return length; + } + + public void setLength(int length) + { + this.length = length; + } +} diff --git a/libjava/classpath/javax/imageio/stream/ImageInputStream.java b/libjava/classpath/javax/imageio/stream/ImageInputStream.java new file mode 100644 index 000000000..dd57ca611 --- /dev/null +++ b/libjava/classpath/javax/imageio/stream/ImageInputStream.java @@ -0,0 +1,651 @@ +/* ImageInputStream.java + Copyright (C) 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.imageio.stream; + +import java.io.DataInput; +import java.io.EOFException; +import java.io.IOException; +import java.nio.ByteOrder; + + +/** + * An input stream for use by {@link javax.imageio.ImageReader + * ImageReaders}. + * + * @since 1.4 + * + * @author Sascha Brawer (brawer@dandelis.ch) + */ +public interface ImageInputStream + extends DataInput +{ + void setByteOrder(ByteOrder order); + + ByteOrder getByteOrder(); + + int read() + throws IOException; + + int read(byte[] b) + throws IOException; + + int read(byte[] b, int offset, int length) + throws IOException; + + + /** + * Reads up to a specified number of bytes, and modifies a + * {@link IIOByteBuffer} to hold the read data. + * + * <p>The {@linkplain #getBitOffset() bit offset} is set to zero + * before any data is read. + * + * @param buf an <code>IIOByteBuffer</code> that will hold the read + * data. + * + * @param numBytes the maximum number of bytes to read. + * + * @throws IndexOutOfBoundsException if <code>numBytes</code> is + * negative. + * + * @throws NullPointerException if <code>buf</code> is + * <code>null</code>. + * + * @throws IOException if some general problem happens with + * accessing data. + */ + void readBytes(IIOByteBuffer buf, int numBytes) + throws IOException; + + + /** + * Reads a byte and checks whether or not its value is zero. + * + * <p>The {@linkplain #getBitOffset() bit offset} is set to zero + * before the byte is read. + * + * @throws EOFException if the input stream is at its end. + * + * @throws IOException if some general problem happens with + * accessing data. + * + * @see #readBit() + * @see #readByte() + * @see #readFully(byte[], int, int) + */ + boolean readBoolean() + throws IOException; + + + /** + * Reads a signed byte. + * + * <p>The {@linkplain #getBitOffset() bit offset} is set to zero + * before any data is read. + * + * @throws EOFException if the input stream is at its end. + * + * @throws IOException if some general problem happens with + * accessing data. + * + * @see #readUnsignedByte() + * @see #readFully(byte[], int, int) + */ + byte readByte() + throws IOException; + + + /** + * Reads an unsigned byte. + * + * <p>The {@linkplain #getBitOffset() bit offset} is set to zero + * before any data is read. + * + * @throws EOFException if the input stream is at its end. + * + * @throws IOException if some general problem happens with + * accessing data. + * + * @see #readByte() + * @see #readFully(byte[], int, int) + */ + int readUnsignedByte() + throws IOException; + + + /** + * Reads an signed 16-bit integer. If necessary, the value gets + * converted from the stream’s {@linkplain #getByteOrder() + * current byte order}. + * + * <p>The {@linkplain #getBitOffset() bit offset} is set to zero + * before any data is read. + * + * @throws EOFException if the input stream ends before all two + * bytes were read. + * + * @throws IOException if some general problem happens with + * accessing data. + * + * @see #readUnsignedShort() + * @see #readChar() + * @see #readFully(short[], int, int) + */ + short readShort() + throws IOException; + + + /** + * Reads an unsigned 16-bit integer. If necessary, the value gets + * converted from the stream’s {@linkplain #getByteOrder() + * current byte order}. + * + * <p>The {@linkplain #getBitOffset() bit offset} is set to zero + * before any data is read. + * + * <p>This method does the same as {@link #readChar()}. + * + * @throws EOFException if the input stream ends before all two + * bytes were read. + * + * @throws IOException if some general problem happens with + * accessing data. + * + * @see #readShort() + * @see #readChar() + * @see #readFully(char[], int, int) + */ + int readUnsignedShort() + throws IOException; + + + /** + * Reads an unsigned 16-bit integer. If necessary, the value gets + * converted from the stream’s {@linkplain #getByteOrder() + * current byte order}. + * + * <p>The {@linkplain #getBitOffset() bit offset} is set to zero + * before any data is read. + * + * <p>This method does the same as {@link #readUnsignedShort()}. + * + * @throws EOFException if the input stream ends before all two + * bytes were read. + * + * @throws IOException if some general problem happens with + * accessing data. + * + * @see #readFully(char[], int, int) + */ + char readChar() + throws IOException; + + + /** + * Reads a signed 32-bit integer. If necessary, the value gets + * converted from the stream’s {@linkplain #getByteOrder() + * current byte order}. + * + * <p>The {@linkplain #getBitOffset() bit offset} is set to zero + * before any data is read. + * + * @throws EOFException if the input stream ends before all four + * bytes were read. + * + * @throws IOException if some general problem happens with + * accessing data. + * + * @see #readUnsignedInt() + * @see #readFully(int[], int, int) + */ + int readInt() + throws IOException; + + + /** + * Reads an unsigned 32-bit integer. If necessary, the value gets + * converted from the stream’s {@linkplain #getByteOrder() + * current byte order}. + * + * <p>The {@linkplain #getBitOffset() bit offset} is set to zero + * before any data is read. + * + * @throws EOFException if the input stream ends before all four + * bytes were read. + * + * @throws IOException if some general problem happens with + * accessing data. + * + * @see #readInt() + * @see #readFully(int[], int, int) + */ + long readUnsignedInt() + throws IOException; + + + /** + * Reads a signed 64-bit integer. If necessary, the value gets + * converted from the stream’s {@linkplain #getByteOrder() + * current byte order}. + * + * <p>The {@linkplain #getBitOffset() bit offset} is set to zero + * before any data is read. + * + * @throws EOFException if the input stream ends before all eight + * bytes were read. + * + * @throws IOException if some general problem happens with + * accessing data. + * + * @see #readFully(long[], int, int) + */ + long readLong() + throws IOException; + + + /** + * Reads an IEEE 32-bit single-precision floating point number. If + * necessary, the value gets converted from the stream’s + * {@linkplain #getByteOrder() current byte order}. + * + * <p>The {@linkplain #getBitOffset() bit offset} is set to zero + * before any data is read. + * + * @throws EOFException if the input stream ends before all four + * bytes were read. + * + * @throws IOException if some general problem happens with + * accessing data. + * + * @see #readFully(float[], int, int) + */ + float readFloat() + throws IOException; + + + /** + * Reads an IEEE 64-bit double-precision floating point number. If + * necessary, the value gets converted from the stream’s + * {@linkplain #getByteOrder() current byte order}. + * + * <p>The {@linkplain #getBitOffset() bit offset} is set to zero + * before any data is read. + * + * @throws EOFException if the input stream ends before all eight + * bytes were read. + * + * @throws IOException if some general problem happens with + * accessing data. + * + * @see #readFully(double[], int, int) + */ + double readDouble() + throws IOException; + + String readLine() + throws IOException; + + String readUTF() + throws IOException; + + + /** + * Reads a sequence of signed 8-bit integers into a + * <code>byte[]</code> array. + * + * <p>The {@linkplain #getBitOffset() bit offset} is set to zero + * before any data is read. + * + * @param b an array for storing the read values. + * + * @param offset the index of the first element in <code>b</code> + * that will hold read data. + * + * @param numBytes the number of bytes to read. + * + * @throws IndexOutOfBoundsException if <code>offset</code> or + * <code>numBytes</code> is negative, or if <code>offset + + * numBytes</code> exceeds <code>b.length</code>. + * + * @throws NullPointerException if <code>b</code> is + * <code>null</code>. + * + * @throws EOFException if the input stream ends before all content + * was read. + * + * @throws IOException if some general problem happens with + * accessing data. + * + * @see #readByte() + */ + void readFully(byte[] b, int offset, int numBytes) + throws IOException; + + + /** + * Reads a sequence of signed 8-bit integers into a + * <code>byte[]</code> array. + * + * <p>The {@linkplain #getBitOffset() bit offset} is set to zero + * before any data is read. + * + * @param b an array for storing the read values. + * + * @throws NullPointerException if <code>b</code> is + * <code>null</code>. + * + * @throws EOFException if the input stream ends before all content + * was read. + * + * @throws IOException if some general problem happens with + * accessing data. + * + * @see #readByte() + * @see #readFully(byte[], int, int) + */ + void readFully(byte[] b) + throws IOException; + + + /** + * Reads a sequence of signed 16-bit integers into a + * <code>short[]</code> array. If necessary, values are converted + * from the stream’s {@linkplain #getByteOrder() current byte + * order}. + * + * <p>The {@linkplain #getBitOffset() bit offset} is set to zero + * before any data is read. + * + * @param s an array for storing the read values. + * + * @param offset the index of the first element in <code>s</code> + * that will hold read data. + * + * @param numShorts the number of signed 16-bit integers to read + * (which is one half of the number of bytes). + * + * @throws IndexOutOfBoundsException if <code>offset</code> or + * <code>numShorts</code> is negative, or if <code>offset + + * numShorts</code> exceeds <code>s.length</code>. + * + * @throws NullPointerException if <code>s</code> is + * <code>null</code>. + * + * @throws EOFException if the input stream ends before all content + * was read. + * + * @throws IOException if some general problem happens with + * accessing data. + * + * @see #readShort() + */ + void readFully(short[] s, int offset, int numShorts) + throws IOException; + + + /** + * Reads a sequence of unsigned 16-bit integers into a + * <code>char[]</code> array. If necessary, values are converted + * from the stream’s {@linkplain #getByteOrder() current byte + * order}. + * + * <p>The {@linkplain #getBitOffset() bit offset} is set to zero + * before any data is read. + * + * @param c an array for storing the read values. + * + * @param offset the index of the first element in <code>c</code> + * that will hold read data. + * + * @param numChars the number of unsigned 16-bit integers to read + * (which is one half of the number of bytes). + * + * @throws IndexOutOfBoundsException if <code>offset</code> or + * <code>numChars</code> is negative, or if <code>offset + + * numChars</code> exceeds <code>c.length</code>. + * + * @throws NullPointerException if <code>c</code> is + * <code>null</code>. + * + * @throws EOFException if the input stream ends before all content + * was read. + * + * @throws IOException if some general problem happens with + * accessing data. + * + * @see #readChar() + */ + void readFully(char[] c, int offset, int numChars) + throws IOException; + + + /** + * Reads a sequence of signed 32-bit integers into a + * <code>long[]</code> array. If necessary, values are converted + * from the stream’s {@linkplain #getByteOrder() current byte + * order}. + * + * <p>The {@linkplain #getBitOffset() bit offset} is set to zero + * before any data is read. + * + * @param i an array for storing the read values. + * + * @param offset the index of the first element in <code>i</code> + * that will hold read data. + * + * @param numInts the number of signed 32-bit integers to read + * (which is one fourth of the number of bytes). + * + * @throws IndexOutOfBoundsException if <code>offset</code> or + * <code>numInts</code> is negative, or if <code>offset + + * numInts</code> exceeds <code>i.length</code>. + * + * @throws NullPointerException if <code>i</code> is + * <code>null</code>. + * + * @throws EOFException if the input stream ends before all content + * was read. + * + * @throws IOException if some general problem happens with + * accessing data. + * + * @see #readInt() + */ + void readFully(int[] i, int offset, int numInts) + throws IOException; + + + /** + * Reads a sequence of signed 64-bit integers into a + * <code>long[]</code> array. If necessary, values are converted + * from the stream’s {@linkplain #getByteOrder() current byte + * order}. + * + * <p>The {@linkplain #getBitOffset() bit offset} is set to zero + * before any data is read. + * + * @param l an array for storing the read values. + * + * @param offset the index of the first element in <code>l</code> + * that will hold read data. + * + * @param numLongs the number of signed 64-bit integers to read + * (which is one eight of the number of bytes). + * + * @throws IndexOutOfBoundsException if <code>offset</code> or + * <code>numLongs</code> is negative, or if <code>offset + + * numLongs</code> exceeds <code>l.length</code>. + * + * @throws NullPointerException if <code>l</code> is + * <code>null</code>. + * + * @throws EOFException if the input stream ends before all content + * was read. + * + * @throws IOException if some general problem happens with + * accessing data. + * + * @see #readLong() + */ + void readFully(long[] l, int offset, int numLongs) + throws IOException; + + + /** + * Reads a sequence of IEEE 32-bit single-precision floating point + * numbers into a <code>float[]</code> array. If necessary, values + * are converted from the stream’s {@linkplain + * #getByteOrder() current byte order}. + * + * <p>The {@linkplain #getBitOffset() bit offset} is set to zero + * before any data is read. + * + * @param d an array for storing the read values. + * + * @param offset the index of the first element in <code>d</code> + * that will hold read data. + * + * @param numFloats the number of IEEE 32-bit single-precision + * floating point numbers to read (which is one fourth of the number + * of bytes). + * + * @throws IndexOutOfBoundsException if <code>offset</code> or + * <code>numFloats</code> is negative, or if <code>offset + + * numFloats</code> exceeds <code>f.length</code>. + * + * @throws NullPointerException if <code>f</code> is + * <code>null</code>. + * + * @throws EOFException if the input stream ends before all content + * was read. + * + * @throws IOException if some general problem happens with + * accessing data. + * + * @see #readFloat() + */ + void readFully(float[] f, int offset, int numFloats) + throws IOException; + + + /** + * Reads a sequence of IEEE 64-bit double-precision floating point + * numbers into a <code>double[]</code> array. If necessary, values + * are converted from the stream’s {@linkplain + * #getByteOrder() current byte order}. + * + * <p>The {@linkplain #getBitOffset() bit offset} is set to zero + * before any data is read. + * + * @param d an array for storing the read values. + * + * @param offset the index of the first element in <code>d</code> + * that will hold read data. + * + * @param numDoubles the number of IEEE 64-bit double-precision + * floating point numbers to read (which is one eight of the number + * of bytes). + * + * @throws IndexOutOfBoundsException if <code>offset</code> or + * <code>numDoubles</code> is negative, or if <code>offset + + * numDoubles</code> exceeds <code>d.length</code>. + * + * @throws NullPointerException if <code>d</code> is + * <code>null</code>. + * + * @throws EOFException if the input stream ends before all content + * was read. + * + * @throws IOException if some general problem happens with + * accessing data. + * + * @see #readDouble() + */ + void readFully(double[] d, int offset, int numDoubles) + throws IOException; + + long getStreamPosition() + throws IOException; + + int getBitOffset() + throws IOException; + + void setBitOffset(int bitOffset) + throws IOException; + + int readBit() + throws IOException; + + long readBits(int numBits) + throws IOException; + + long length() + throws IOException; + + int skipBytes(int numBytes) + throws IOException; + + long skipBytes(long numBytes) + throws IOException; + + void seek(long pos) + throws IOException; + + void mark(); + + void reset() + throws IOException; + + void flushBefore(long pos) + throws IOException; + + void flush() + throws IOException; + + long getFlushedPosition(); + + boolean isCached(); + + boolean isCachedMemory(); + + boolean isCachedFile(); + + void close() + throws IOException; +} diff --git a/libjava/classpath/javax/imageio/stream/ImageInputStreamImpl.java b/libjava/classpath/javax/imageio/stream/ImageInputStreamImpl.java new file mode 100644 index 000000000..72fd6de48 --- /dev/null +++ b/libjava/classpath/javax/imageio/stream/ImageInputStreamImpl.java @@ -0,0 +1,542 @@ +/* ImageInputStream.java -- + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.imageio.stream; + +import gnu.java.lang.CPStringBuilder; + +import java.io.DataInputStream; +import java.io.EOFException; +import java.io.IOException; +import java.nio.ByteOrder; +import java.util.Stack; + +/** + * @author Michael Koch (konqueror@gmx.de) + */ +public abstract class ImageInputStreamImpl implements ImageInputStream +{ + private boolean closed; + private Stack markStack = new Stack(); + + byte[] buffer = new byte[8]; + + protected int bitOffset; + protected ByteOrder byteOrder = ByteOrder.BIG_ENDIAN; + protected long flushedPos; + protected long streamPos; + + public ImageInputStreamImpl() + { + // Do nothing here. + } + + protected final void checkClosed() + throws IOException + { + if (closed) + throw new IOException("stream closed"); + } + + public void close() + throws IOException + { + checkClosed(); + closed = true; + } + + protected void finalize() + throws Throwable + { + if (!closed) + close(); + } + + public void flush() + throws IOException + { + flushBefore(getStreamPosition()); + } + + public void flushBefore(long position) + throws IOException + { + if (position < flushedPos) + throw new IndexOutOfBoundsException(); + + if (position > streamPos) + throw new IndexOutOfBoundsException(); + + flushedPos = position; + } + + public int getBitOffset() + throws IOException + { + checkClosed(); + return bitOffset; + } + + public ByteOrder getByteOrder() + { + return byteOrder; + } + + public long getFlushedPosition() + { + return flushedPos; + } + + public long getStreamPosition() + throws IOException + { + checkClosed(); + return streamPos; + } + + public boolean isCached() + { + return false; + } + + public boolean isCachedFile() + { + return false; + } + + public boolean isCachedMemory() + { + return false; + } + + public long length() + { + return -1L; + } + + public void mark() + { + try + { + markStack.push(new Long(getStreamPosition())); + } + catch (IOException e) + { + throw new RuntimeException(e); + } + } + + public abstract int read() + throws IOException; + + public abstract int read(byte[] data, int offset, int len) + throws IOException; + + public int read(byte[] data) + throws IOException + { + return read(data, 0, data.length); + } + + public int readBit() + throws IOException + { + checkClosed(); + + // Calculate new bit offset here as readByte clears it. + int newOffset = (bitOffset + 1) & 0x7; + + // Clears bitOffset. + byte data = readByte(); + + // If newOffset is 0 it means we just read the 8th bit in a byte + // and therefore we want to advance to the next byte. Otherwise + // we want to roll back the stream one byte so that future readBit + // calls read bits from the same current byte. + if (newOffset != 0) + { + seek(getStreamPosition() - 1); + data = (byte) (data >> (8 - newOffset)); + } + + bitOffset = newOffset; + return data & 0x1; + } + + public long readBits(int numBits) + throws IOException + { + checkClosed(); + + if (numBits < 0 || numBits > 64) + throw new IllegalArgumentException(); + + long bits = 0L; + + for (int i = 0; i < numBits; i++) + { + bits <<= 1; + bits |= readBit(); + } + return bits; + } + + public boolean readBoolean() + throws IOException + { + byte data = readByte(); + + return data != 0; + } + + public byte readByte() + throws IOException + { + checkClosed(); + + int data = read(); + + if (data == -1) + throw new EOFException(); + + return (byte) data; + } + + public void readBytes(IIOByteBuffer buffer, int len) + throws IOException + { + readFullyPrivate(buffer.getData(), buffer.getOffset(), len); + + buffer.setLength(len); + } + + public char readChar() + throws IOException + { + return (char) readShort(); + } + + public double readDouble() + throws IOException + { + return Double.longBitsToDouble(readLong()); + } + + public float readFloat() + throws IOException + { + return Float.intBitsToFloat(readInt()); + } + + public void readFully(byte[] data) + throws IOException + { + readFully(data, 0, data.length); + } + + public void readFully(byte[] data, int offset, int len) + throws IOException + { + readFullyPrivate(data, offset, len); + } + + public void readFully(char[] data, int offset, int len) + throws IOException + { + for (int i = 0; i < len; ++i) + data[offset + i] = readChar(); + } + + public void readFully(double[] data, int offset, int len) + throws IOException + { + for (int i = 0; i < len; ++i) + data[offset + i] = readDouble(); + } + + public void readFully(float[] data, int offset, int len) + throws IOException + { + for (int i = 0; i < len; ++i) + data[offset + i] = readFloat(); + } + + public void readFully(int[] data, int offset, int len) + throws IOException + { + for (int i = 0; i < len; ++i) + data[offset + i] = readInt(); + } + + public void readFully(long[] data, int offset, int len) + throws IOException + { + for (int i = 0; i < len; ++i) + data[offset + i] = readLong(); + } + + public void readFully(short[] data, int offset, int len) + throws IOException + { + for (int i = 0; i < len; ++i) + data[offset + i] = readShort(); + } + + public int readInt() + throws IOException + { + readFullyPrivate(buffer, 0, 4); + + if (getByteOrder() == ByteOrder.LITTLE_ENDIAN) + return (int) + (((int) (buffer[0] & 0xff) << 0) + | ((int) (buffer[1] & 0xff) << 8) + | ((int) (buffer[2] & 0xff) << 16) + | ((int) (buffer[3] & 0xff) << 24)); + + return (int) + (((int) (buffer[0] & 0xff) << 24) + + ((int) (buffer[1] & 0xff) << 16) + + ((int) (buffer[2] & 0xff) << 8) + + ((int) (buffer[3] & 0xff) << 0)); + } + + public String readLine() + throws IOException + { + checkClosed(); + + int c = -1; + boolean eol = false; + CPStringBuilder buffer = new CPStringBuilder(); + + c = read(); + if (c == -1) + return null; + + while (!eol) + { + switch(c) + { + case '\r': + // Check for following '\n'. + long oldPosition = getStreamPosition(); + c = read(); + if (c == -1 || c == '\n') + eol = true; + else + { + seek(oldPosition); + eol = true; + } + continue; + + case '\n': + eol = true; + continue; + + default: + buffer.append((char) c); + break; + } + c = read(); + if (c == -1) + eol = true; + } + + return buffer.toString(); + } + + public long readLong() + throws IOException + { + readFullyPrivate(buffer, 0, 8); + + if (getByteOrder() == ByteOrder.LITTLE_ENDIAN) + return (long) + (((long) (buffer[0] & 0xff) << 0) + | ((long) (buffer[1] & 0xff) << 8) + | ((long) (buffer[2] & 0xff) << 16) + | ((long) (buffer[3] & 0xff) << 24) + | ((long) (buffer[4] & 0xff) << 32) + | ((long) (buffer[5] & 0xff) << 40) + | ((long) (buffer[6] & 0xff) << 48) + | ((long) (buffer[7] & 0xff) << 56)); + + return (long) + (((long) (buffer[0] & 0xff) << 56) + | ((long) (buffer[1] & 0xff) << 48) + | ((long) (buffer[2] & 0xff) << 40) + | ((long) (buffer[3] & 0xff) << 32) + | ((long) (buffer[4] & 0xff) << 24) + | ((long) (buffer[5] & 0xff) << 16) + | ((long) (buffer[6] & 0xff) << 8) + | ((long) (buffer[7] & 0xff) << 0)); + } + + public short readShort() + throws IOException + { + readFullyPrivate(buffer, 0, 2); + + if (getByteOrder() == ByteOrder.LITTLE_ENDIAN) + return (short) + (((short) (buffer[0] & 0xff) << 0) + | ((short) (buffer[1] & 0xff) << 8)); + + return (short) + (((short) (buffer[0] & 0xff) << 8) + | ((short) (buffer[1] & 0xff) << 0)); + } + + public int readUnsignedByte() + throws IOException + { + return (int) readByte() & 0xff; + } + + public long readUnsignedInt() + throws IOException + { + return (long) readInt() & 0xffffffffL; + } + + public int readUnsignedShort() + throws IOException + { + return (int) readShort() & 0xffff; + } + + public String readUTF() + throws IOException + { + checkClosed(); + + String data; + ByteOrder old = getByteOrder(); + // Strings are always big endian. + setByteOrder(ByteOrder.BIG_ENDIAN); + + try + { + data = DataInputStream.readUTF(this); + } + finally + { + setByteOrder(old); + } + + return data; + } + + public void reset() + throws IOException + { + checkClosed(); + + long mark = ((Long) markStack.pop()).longValue(); + seek(mark); + } + + public void seek(long position) + throws IOException + { + checkClosed(); + + if (position < getFlushedPosition()) + throw new IndexOutOfBoundsException("position < flushed position"); + + streamPos = position; + bitOffset = 0; + } + + public void setBitOffset (int bitOffset) + throws IOException + { + checkClosed(); + + if (bitOffset < 0 || bitOffset > 7) + throw new IllegalArgumentException("bitOffset not between 0 and 7 inclusive"); + + this.bitOffset = bitOffset; + } + + public void setByteOrder(ByteOrder byteOrder) + { + this.byteOrder = byteOrder; + } + + public int skipBytes(int num) + throws IOException + { + checkClosed(); + + seek(getStreamPosition() + num); + bitOffset = 0; + return num; + } + + public long skipBytes(long num) + throws IOException + { + checkClosed(); + + seek(getStreamPosition() + num); + bitOffset = 0; + return num; + } + + private void readFullyPrivate (byte[] buf, int offset, int len) throws IOException + { + checkClosed(); + + if (len < 0) + throw new IndexOutOfBoundsException("Negative length: " + len); + + while (len > 0) + { + // read will block until some data is available. + int numread = read (buf, offset, len); + if (numread < 0) + throw new EOFException (); + len -= numread; + offset += numread; + } + bitOffset = 0; + } +} diff --git a/libjava/classpath/javax/imageio/stream/ImageOutputStream.java b/libjava/classpath/javax/imageio/stream/ImageOutputStream.java new file mode 100644 index 000000000..4688ad935 --- /dev/null +++ b/libjava/classpath/javax/imageio/stream/ImageOutputStream.java @@ -0,0 +1,269 @@ +/* ImageOutputStream.java + Copyright (C) 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.imageio.stream; + +import java.io.DataOutput; +import java.io.IOException; + + +/** + * An output stream for use by {@link javax.imageio.ImageWriter + * ImageWriters}. + * + * @since 1.4 + * + * @author Sascha Brawer (brawer@dandelis.ch) + */ +public interface ImageOutputStream + extends ImageInputStream, DataOutput +{ + /** + * @param position + * + * @throws IOException if an errror occurs + */ + void flushBefore(long position) throws IOException; + + /** + * Writes an array into the stream. + * + * @param data the data to be written + * + * @throws IOException if an errror occurs + */ + void write(byte[] data) throws IOException; + + /** + * Writes a region of data from an array into the stream. + * + * @param data the data to be written + * @param offset the offset in the array + * @param len the length in the array + * + * @throws IOException if an errror occurs + */ + void write(byte[] data, int offset, int len) throws IOException; + + /** + * Writes an <code>int</code> into the stream. + * + * @param data the data to be written + * + * @throws IOException if an errror occurs + */ + void write(int data) throws IOException; + + /** + * Writes a bit value to the stream. + * + * @throws IOException if an error occurs + */ + void writeBit(int bit) throws IOException; + + /** + * Writes a number of bit values to the stream. + * + * @throws IOException if an errror occurs + */ + void writeBits(long bits, int numBits) throws IOException; + + /** + * Writes a <code>boolean</code> value into the stream. + * + * @param data the data to be written + * + * @throws IOException if an errror occurs + */ + void writeBoolean(boolean data) throws IOException; + + /** + * Writes a <code>byte</code> value into the stream. + * + * @param data the data to be written + * + * @throws IOException if an errror occurs + */ + void writeByte(int data) throws IOException; + + /** + * @param data the data to be written + * + * @throws IOException if an errror occurs + */ + void writeBytes(String data) throws IOException; + + /** + * Writes a character into the stream. + * + * @param data the data to be written + * + * @throws IOException if an errror occurs + */ + void writeChar(int data) throws IOException; + + /** + * Writes characters to the stream. + * + * @param data the data to be written + * @param offset the offset in the array + * @param len the lenth in the array + * + * @throws IOException if an errror occurs + */ + void writeChars(char[] data, int offset, int len) throws IOException; + + /** + * Writes characters from a given <code>String</code> into the stream. + * + * @param data the data to be written + * + * @throws IOException if an errror occurs + */ + void writeChars(String data) throws IOException; + + /** + * Writes a <code>double</code> into the stream. + * + * @param data the data to be written + * + * @throws IOException if an errror occurs + */ + void writeDouble(double data) throws IOException; + + /** + * Writes an array of <code>double</code> into the stream. + * + * @param data the data to be written + * @param offset the offset in the array + * @param len the lenth in the array + * + * @throws IOException if an errror occurs + */ + void writeDoubles(double[] data, int offset, int len) + throws IOException; + + /** + * Writes a <code>float</code> into the stream. + * + * @param data the data to be written + * + * @throws IOException if an errror occurs + */ + void writeFloat(float data) throws IOException; + + /** + * Writes an array of <code>float</code> into the stream. + * + * @param data the data to be written + * @param offset the offset in the array + * @param len the lenth in the array + * + * @throws IOException if an errror occurs + */ + void writeFloats(float[] data, int offset, int len) throws IOException; + + /** + * Writes a <code>int</code> into the stream. + * + * @param data the data to be written + * + * @throws IOException if an errror occurs + */ + void writeInt(int data) throws IOException; + + /** + * Writes an array of <code>int</code> into the stream. + * + * @param data the data to be written + * @param offset the offset in the array + * @param len the lenth in the array + * + * @throws IOException if an errror occurs + */ + void writeInts(int[] data, int offset, int len) throws IOException; + + /** + * Writes a <code>long</code> into the stream. + * + * @param data the data to be written + * + * @throws IOException if an errror occurs + */ + void writeLong(long data) throws IOException; + + /** + * Writes an array of <code>long</code> into the stream. + * + * @param data the data to be written + * @param offset the offset in the array + * @param len the lenth in the array + * + * @throws IOException if an errror occurs + */ + void writeLongs(long[] data, int offset, int len) throws IOException; + + /** + * Writes a <code>short</code> into the stream. + * + * @param data the data to be written + * + * @throws IOException if an errror occurs + */ + void writeShort(int data) throws IOException; + + /** + * Writes an array of <code>short</code> into the stream. + * + * @param data the data to be written + * @param offset the offset in the array + * @param len the lenth in the array + * + * @throws IOException if an errror occurs + */ + void writeShorts(short[] data, int offset, int len) throws IOException; + + /** + * Writes a <code>String</code> into the stream. + * + * @param data the data to be written + * + * @throws IOException if an errror occurs + */ + void writeUTF(String data) throws IOException; +} diff --git a/libjava/classpath/javax/imageio/stream/ImageOutputStreamImpl.java b/libjava/classpath/javax/imageio/stream/ImageOutputStreamImpl.java new file mode 100644 index 000000000..5bf7e4402 --- /dev/null +++ b/libjava/classpath/javax/imageio/stream/ImageOutputStreamImpl.java @@ -0,0 +1,374 @@ +/* ImageOutputStream.java -- + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.imageio.stream; + +import java.io.IOException; +import java.io.UTFDataFormatException; +import java.nio.ByteOrder; + +/** + * @author Michael Koch (konqueror@gmx.de) + */ +public abstract class ImageOutputStreamImpl extends ImageInputStreamImpl + implements ImageOutputStream +{ + public ImageOutputStreamImpl() + { + // Do nothing here. + } + + protected final void flushBits() + throws IOException + { + checkClosed(); + if (bitOffset != 0) + { + int offset = bitOffset; + int partial = read(); + if (partial < 0) + { + partial = 0; + bitOffset = 0; + } + else + { + seek(getStreamPosition() - 1); + partial &= -1 << (8 - offset); + } + write(partial); + } + } + + public void write(byte[] data) + throws IOException + { + write(data, 0, data.length); + } + + public abstract void write(byte[] data, int offset, int len) + throws IOException; + + public abstract void write(int value) + throws IOException; + + public void writeBit(int bit) + throws IOException + { + writeBits(1L & bit, 1); + } + + public void writeBits(long bits, int numBits) + throws IOException + { + checkClosed(); + // Append chunk of bits to any preexisting bits, if any. + if (getStreamPosition() > 0 || bitOffset > 0) + { + int offs = bitOffset; + int partial = read(); + if (partial != -1) + seek(getStreamPosition() - 1); + else + partial = 0; + if (numBits + offs < 8) + { + // Append complete bits to partial byte. + int shift = 8 - (offs + numBits); + int mask = -1 >>> (32 - numBits); + partial &= ~(mask << shift); + partial |= (bits & mask) << shift; + write(partial); + seek(getStreamPosition() - 1); + bitOffset = offs + numBits; + numBits = 0; + } + else + { + // Append bits and decrease numBits accordingly. + int num = 8 - offs; + int mask = -1 >>> (32 - num); + partial &= ~mask; + partial |= (bits >> (numBits - num)) & mask; + write(partial); + numBits -= num; + } + } + + // Write out whole chunks, if any. + if (numBits > 7) + { + int remaining = numBits % 8; + for (int numBytes = numBits / 8; numBytes > 0; numBytes--) + { + int shift = (numBytes - 1) * 8 + remaining; + int value = (int) ((shift == 0) ? bits & 0xff + : (bits >> shift) & 0xff); + write(value); + } + numBits = remaining; + } + + // Write remaing partial bytes. + if (numBits != 0) + { + int partial = read(); + if (partial == -1) + { + seek(getStreamPosition() - 1); + } + else + { + partial = 0; + } + int shift = 8 - numBits; + int mask = -1 >>> (32 - numBits); + partial &= ~(mask << shift); + partial |= (bits & mask) << shift; + write(partial); + seek(getStreamPosition() - 1); + bitOffset = numBits; + } + } + + public void writeBoolean(boolean value) + throws IOException + { + writeByte(value ? 1 : 0); + } + + public void writeByte(int value) + throws IOException + { + write(value & 0xff); + } + + public void writeBytes(String data) + throws IOException + { + // This is bogus, but it is how the method is specified. + // Sun ought to deprecate this method. + int len = data.length(); + for (int i = 0; i < len; ++i) + writeByte(data.charAt(i)); + } + + public void writeChar(int value) + throws IOException + { + writeShort(value); + } + + public void writeChars(char[] data, int offset, int len) + throws IOException + { + for(int i = 0; i < len; ++len) + writeChar(data[offset + i]); + } + + public void writeChars(String data) + throws IOException + { + int len = data.length(); + for (int i = 0; i < len; ++i) + writeChar(data.charAt(i)); + } + + public void writeDouble(double value) + throws IOException + { + writeLong(Double.doubleToLongBits(value)); + } + + public void writeDoubles(double[] data, int offset, int len) + throws IOException + { + for(int i = 0; i < len; ++len) + writeDouble(data[offset + i]); + } + + public void writeFloat(float value) + throws IOException + { + writeInt(Float.floatToIntBits(value)); + } + + public void writeFloats(float[] data, int offset, int len) + throws IOException + { + for(int i = 0; i < len; ++len) + writeFloat(data[offset + i]); + } + + public void writeInt(int value) + throws IOException + { + if (getByteOrder() == ByteOrder.LITTLE_ENDIAN) + { + buffer[0] = ((byte) value); + buffer[1] = ((byte) (value >> 8)); + buffer[2] = ((byte) (value >> 16)); + buffer[3] = ((byte) (value >> 24)); + } + else + { + buffer[0] = ((byte) (value >> 24)); + buffer[1] = ((byte) (value >> 16)); + buffer[2] = ((byte) (value >> 8)); + buffer[3] = ((byte) value); + } + + write(buffer, 0, 4); + } + + public void writeInts(int[] data, int offset, int len) + throws IOException + { + for(int i = 0; i < len; ++len) + writeInt(data[offset + i]); + } + + public void writeLong(long value) + throws IOException + { + if (getByteOrder() == ByteOrder.LITTLE_ENDIAN) + { + buffer[0] = ((byte) value); + buffer[1] = ((byte) (value >> 8)); + buffer[2] = ((byte) (value >> 16)); + buffer[3] = ((byte) (value >> 24)); + buffer[4] = ((byte) (value >> 32)); + buffer[5] = ((byte) (value >> 40)); + buffer[6] = ((byte) (value >> 48)); + buffer[7] = ((byte) (value >> 56)); + } + else + { + buffer[0] = ((byte) (value >> 56)); + buffer[1] = ((byte) (value >> 48)); + buffer[2] = ((byte) (value >> 40)); + buffer[3] = ((byte) (value >> 32)); + buffer[4] = ((byte) (value >> 24)); + buffer[5] = ((byte) (value >> 16)); + buffer[6] = ((byte) (value >> 8)); + buffer[7] = ((byte) value); + } + + write(buffer, 0, 8); + } + + public void writeLongs(long[] data, int offset, int len) + throws IOException + { + for(int i = 0; i < len; ++len) + writeLong(data[offset + i]); + } + + public void writeShort(int value) + throws IOException + { + if (getByteOrder() == ByteOrder.LITTLE_ENDIAN) + { + buffer[0] = ((byte) value); + buffer[1] = ((byte) (value >> 8)); + } + else + { + buffer[0] = ((byte) (value >> 8)); + buffer[1] = ((byte) value); + } + + write(buffer, 0, 2); + } + + public void writeShorts(short[] data, int offset, int len) + throws IOException + { + for(int i = 0; i < len; ++len) + writeShort(data[offset + i]); + } + + public void writeUTF(String value) + throws IOException + { + // NOTE: this code comes directly from DataOutputStream. + int len = value.length(); + int sum = 0; + + for (int i = 0; i < len && sum <= 65535; ++i) + { + char c = value.charAt(i); + if (c >= '\u0001' && c <= '\u007f') + sum += 1; + else if (c == '\u0000' || (c >= '\u0080' && c <= '\u07ff')) + sum += 2; + else + sum += 3; + } + + if (sum > 65535) + throw new UTFDataFormatException (); + + int pos = 0; + byte[] buf = new byte[sum]; + + for (int i = 0; i < len; ++i) + { + char c = value.charAt(i); + if (c >= '\u0001' && c <= '\u007f') + buf[pos++] = (byte) c; + else if (c == '\u0000' || (c >= '\u0080' && c <= '\u07ff')) + { + buf[pos++] = (byte) (0xc0 | (0x1f & (c >> 6))); + buf[pos++] = (byte) (0x80 | (0x3f & c)); + } + else + { + // JSL says the first byte should be or'd with 0xc0, but + // that is a typo. Unicode says 0xe0, and that is what is + // consistent with DataInputStream. + buf[pos++] = (byte) (0xe0 | (0x0f & (c >> 12))); + buf[pos++] = (byte) (0x80 | (0x3f & (c >> 6))); + buf[pos++] = (byte) (0x80 | (0x3f & c)); + } + } + + writeShort (sum); + write(buf, 0, sum); + } +} diff --git a/libjava/classpath/javax/imageio/stream/MemoryCacheImageInputStream.java b/libjava/classpath/javax/imageio/stream/MemoryCacheImageInputStream.java new file mode 100644 index 000000000..e1ad71f58 --- /dev/null +++ b/libjava/classpath/javax/imageio/stream/MemoryCacheImageInputStream.java @@ -0,0 +1,127 @@ +/* MemoryCacheImageInputStream.java -- + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.imageio.stream; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.InputStream; + +/** + * @author Michael Koch (konqueror@gmx.de) + */ +public class MemoryCacheImageInputStream extends ImageInputStreamImpl +{ + private InputStream stream; + private BufferedInputStream buffer; + + private int READLIMIT = 2048; + + public MemoryCacheImageInputStream(InputStream stream) + { + this.stream = stream; + buffer = new BufferedInputStream(stream); + buffer.mark(READLIMIT); + } + + public void close() + throws IOException + { + super.close(); + stream.close(); + } + + public void flushBefore(long position) + throws IOException + { + long prevFlushedPosition = getFlushedPosition(); + super.flushBefore(position); + buffer.reset(); + buffer.skip(getFlushedPosition() - prevFlushedPosition); + buffer.mark(READLIMIT); + } + + public boolean isCached() + { + return true; + } + + public boolean isCachedFile() + { + return false; + } + + public boolean isCachedMemory() + { + return true; + } + + public int read() + throws IOException + { + setBitOffset(0); + int retval = buffer.read(); + + if (retval != -1) + streamPos++; + + return retval; + } + + public int read(byte[] data, int offset, int len) + throws IOException + { + setBitOffset(0); + int retval = buffer.read(data, offset, len); + + if (retval != -1) + { + streamPos += retval; + } + + return retval; + } + + public void seek(long position) + throws IOException + { + super.seek(position); + buffer.reset(); + buffer.skip(position - getFlushedPosition()); + } +} diff --git a/libjava/classpath/javax/imageio/stream/MemoryCacheImageOutputStream.java b/libjava/classpath/javax/imageio/stream/MemoryCacheImageOutputStream.java new file mode 100644 index 000000000..84e836090 --- /dev/null +++ b/libjava/classpath/javax/imageio/stream/MemoryCacheImageOutputStream.java @@ -0,0 +1,114 @@ +/* MemoryCacheImageOutputStream.java -- + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.imageio.stream; + +import gnu.classpath.NotImplementedException; + +import java.io.IOException; +import java.io.OutputStream; + +/** + * @author Michael Koch (konqueror@gmx.de) + */ +public class MemoryCacheImageOutputStream extends ImageOutputStreamImpl +{ + private OutputStream stream; + + public MemoryCacheImageOutputStream(OutputStream stream) + { + this.stream = stream; + } + + public void close() + throws IOException + { + super.close(); + stream.close(); + } + + public void flushBefore(long position) + throws IOException, NotImplementedException + { + // FIXME: Implement me. + throw new Error("not implemented"); + } + + public boolean isCached() + { + return true; + } + + public boolean isCachedFile() + { + return false; + } + + public boolean isCachedMemory() + { + return true; + } + + public int read() + throws IOException, NotImplementedException + { + // FIXME: Implement me. + throw new Error("not implemented"); + } + + public int read (byte[] data, int offset, int len) + throws IOException, NotImplementedException + { + // FIXME: Implement me. + throw new Error("not implemented"); + } + + public void write(byte[] data, int offset, int len) + throws IOException + { + // FIXME: Flush pending bits. + stream.write(data, offset, len); + } + + public void write(int value) + throws IOException + { + // FIXME: Flush pending bits. + stream.write(value); + } +} diff --git a/libjava/classpath/javax/imageio/stream/package.html b/libjava/classpath/javax/imageio/stream/package.html new file mode 100644 index 000000000..63e53ca65 --- /dev/null +++ b/libjava/classpath/javax/imageio/stream/package.html @@ -0,0 +1,46 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> +<!-- package.html - describes classes in javax.imageio.stream package. + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. --> + +<html> +<head><title>GNU Classpath - javax.imageio.stream</title></head> + +<body> +<p></p> + +</body> +</html> |