/*
* Copyright 1999-2006 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package ae.javax.imageio;
import ae.java.awt.Dimension;
import ae.java.awt.Rectangle;
import ae.java.awt.image.BufferedImage;
import ae.java.awt.image.RenderedImage;
import ae.java.awt.image.Raster;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
import ae.javax.imageio.event.IIOWriteWarningListener;
import ae.javax.imageio.event.IIOWriteProgressListener;
import ae.javax.imageio.metadata.IIOMetadata;
import ae.javax.imageio.stream.ImageOutputStream;
import ae.javax.imageio.spi.ImageWriterSpi;
/**
* An abstract superclass for encoding and writing images. This class
* must be subclassed by classes that write out images in the context
* of the Java Image I/O framework.
*
* <p> <code>ImageWriter</code> objects are normally instantiated by
* the service provider class for the specific format. Service
* provider classes are registered with the <code>IIORegistry</code>,
* which uses them for format recognition and presentation of
* available format readers and writers.
*
* <p>
*
* @see ImageReader
* @see ImageWriteParam
* @see ae.javax.imageio.spi.IIORegistry
* @see ae.javax.imageio.spi.ImageWriterSpi
*
*/
public abstract class ImageWriter implements ImageTranscoder {
/**
* The <code>ImageWriterSpi</code> that instantiated this object,
* or <code>null</code> if its identity is not known or none
* exists. By default it is initialized to <code>null</code>.
*/
protected ImageWriterSpi originatingProvider = null;
/**
* The <code>ImageOutputStream</code> or other <code>Object</code>
* set by <code>setOutput</code> and retrieved by
* <code>getOutput</code>. By default it is initialized to
* <code>null</code>.
*/
protected Object output = null;
/**
* An array of <code>Locale</code>s that may be used to localize
* warning messages and compression setting values, or
* <code>null</code> if localization is not supported. By default
* it is initialized to <code>null</code>.
*/
protected Locale[] availableLocales = null;
/**
* The current <code>Locale</code> to be used for localization, or
* <code>null</code> if none has been set. By default it is
* initialized to <code>null</code>.
*/
protected Locale locale = null;
/**
* A <code>List</code> of currently registered
* <code>IIOWriteWarningListener</code>s, initialized by default to
* <code>null</code>, which is synonymous with an empty
* <code>List</code>.
*/
protected List<IIOWriteWarningListener> warningListeners = null;
/**
* A <code>List</code> of <code>Locale</code>s, one for each
* element of <code>warningListeners</code>, initialized by default
* <code>null</code>, which is synonymous with an empty
* <code>List</code>.
*/
protected List<Locale> warningLocales = null;
/**
* A <code>List</code> of currently registered
* <code>IIOWriteProgressListener</code>s, initialized by default
* <code>null</code>, which is synonymous with an empty
* <code>List</code>.
*/
protected List<IIOWriteProgressListener> progressListeners = null;
/**
* If <code>true</code>, the current write operation should be
* aborted.
*/
private boolean abortFlag = false;
/**
* Constructs an <code>ImageWriter</code> and sets its
* <code>originatingProvider</code> instance variable to the
* supplied value.
*
* <p> Subclasses that make use of extensions should provide a
* constructor with signature <code>(ImageWriterSpi,
* Object)</code> in order to retrieve the extension object. If
* the extension object is unsuitable, an
* <code>IllegalArgumentException</code> should be thrown.
*
* @param originatingProvider the <code>ImageWriterSpi</code> that
* is constructing this object, or <code>null</code>.
*/
protected ImageWriter(ImageWriterSpi originatingProvider) {
this.originatingProvider = originatingProvider;
}
/**
* Returns the <code>ImageWriterSpi</code> object that created
* this <code>ImageWriter</code>, or <code>null</code> if this
* object was not created through the <code>IIORegistry</code>.
*
* <p> The default implementation returns the value of the
* <code>originatingProvider</code> instance variable.
*
* @return an <code>ImageWriterSpi</code>, or <code>null</code>.
*
* @see ImageWriterSpi
*/
public ImageWriterSpi getOriginatingProvider() {
return originatingProvider;
}
/**
* Sets the destination to the given
* <code>ImageOutputStream</code> or other <code>Object</code>.
* The destination is assumed to be ready to accept data, and will
* not be closed at the end of each write. This allows distributed
* imaging applications to transmit a series of images over a
* single network connection. If <code>output</code> is
* <code>null</code>, any currently set output will be removed.
*
* <p> If <code>output</code> is an
* <code>ImageOutputStream</code>, calls to the
* <code>write</code>, <code>writeToSequence</code>, and
* <code>prepareWriteEmpty</code>/<code>endWriteEmpty</code>
* methods will preserve the existing contents of the stream.
* Other write methods, such as <code>writeInsert</code>,
* <code>replaceStreamMetadata</code>,
* <code>replaceImageMetadata</code>, <code>replacePixels</code>,
* <code>prepareInsertEmpty</code>/<code>endInsertEmpty</code>,
* and <code>endWriteSequence</code>, require the full contents
* of the stream to be readable and writable, and may alter any
* portion of the stream.
*
* <p> Use of a general <code>Object</code> other than an
* <code>ImageOutputStream</code> is intended for writers that
* interact directly with an output device or imaging protocol.
* The set of legal classes is advertised by the writer's service
* provider's <code>getOutputTypes</code> method; most writers
* will return a single-element array containing only
* <code>ImageOutputStream.class</code> to indicate that they
* accept only an <code>ImageOutputStream</code>.
*
* <p> The default implementation sets the <code>output</code>
* instance variable to the value of <code>output</code> after
* checking <code>output</code> against the set of classes
* advertised by the originating provider, if there is one.
*
* @param output the <code>ImageOutputStream</code> or other
* <code>Object</code> to use for future writing.
*
* @exception IllegalArgumentException if <code>output</code> is
* not an instance of one of the classes returned by the
* originating service provider's <code>getOutputTypes</code>
* method.
*
* @see #getOutput
*/
public void setOutput(Object output) {
if (output != null) {
ImageWriterSpi provider = getOriginatingProvider();
if (provider != null) {
Class[] classes = provider.getOutputTypes();
boolean found = false;
for (int i = 0; i < classes.length; i++) {
if (classes[i].isInstance(output)) {
found = true;
break;
}
}
if (!found) {
throw new IllegalArgumentException("Illegal output type!");
}
}
}
this.output = output;
}
/**
* Returns the <code>ImageOutputStream</code> or other
* <code>Object</code> set by the most recent call to the
* <code>setOutput</code> method. If no destination has been
* set, <code>null</code> is returned.
*
* <p> The default implementation returns the value of the
* <code>output</code> instance variable.
*
* @return the <code>Object</code> that was specified using
* <code>setOutput</code>, or <code>null</code>.
*
* @see #setOutput
*/
public Object getOutput() {
return output;
}
// Localization
/**
* Returns an array of <code>Locale</code>s that may be used to
* localize warning listeners and compression settings. A return
* value of <code>null</code> indicates that localization is not
* supported.
*
* <p> The default implementation returns a clone of the
* <code>availableLocales</code> instance variable if it is
* non-<code>null</code>, or else returns <code>null</code>.
*
* @return an array of <code>Locale</code>s that may be used as
* arguments to <code>setLocale</code>, or <code>null</code>.
*/
public Locale[] getAvailableLocales() {
return (availableLocales == null) ?
null : (Locale[])availableLocales.clone();
}
/**
* Sets the current <code>Locale</code> of this
* <code>ImageWriter</code> to the given value. A value of
* <code>null</code> removes any previous setting, and indicates
* that the writer should localize as it sees fit.
*
* <p> The default implementation checks <code>locale</code>
* against the values returned by
* <code>getAvailableLocales</code>, and sets the
* <code>locale</code> instance variable if it is found. If
* <code>locale</code> is <code>null</code>, the instance variable
* is set to <code>null</code> without any checking.
*
* @param locale the desired <code>Locale</code>, or
* <code>null</code>.
*
* @exception IllegalArgumentException if <code>locale</code> is
* non-<code>null</code> but is not one of the values returned by
* <code>getAvailableLocales</code>.
*
* @see #getLocale
*/
public void setLocale(Locale locale) {
if (locale != null) {
Locale[] locales = getAvailableLocales();
boolean found = false;
if (locales != null) {
for (int i = 0; i < locales.length; i++) {
if (locale.equals(locales[i])) {
found = true;
break;
}
}
}
if (!found) {
throw new IllegalArgumentException("Invalid locale!");
}
}
this.locale = locale;
}
/**
* Returns the currently set <code>Locale</code>, or
* <code>null</code> if none has been set.
*
* <p> The default implementation returns the value of the
* <code>locale</code> instance variable.
*
* @return the current <code>Locale</code>, or <code>null</code>.
*
* @see #setLocale
*/
public Locale getLocale() {
return locale;
}
// Write params
/**
* Returns a new <code>ImageWriteParam</code> object of the
* appropriate type for this file format containing default
* values, that is, those values that would be used
* if no <code>ImageWriteParam</code> object were specified. This
* is useful as a starting point for tweaking just a few parameters
* and otherwise leaving the default settings alone.
*
* <p> The default implementation constructs and returns a new
* <code>ImageWriteParam</code> object that does not allow tiling,
* progressive encoding, or compression, and that will be
* localized for the current <code>Locale</code> (<i>i.e.</i>,
* what you would get by calling <code>new
* ImageWriteParam(getLocale())</code>.
*
* <p> Individual plug-ins may return an instance of
* <code>ImageWriteParam</code> with additional optional features
* enabled, or they may return an instance of a plug-in specific
* subclass of <code>ImageWriteParam</code>.
*
* @return a new <code>ImageWriteParam</code> object containing
* default values.
*/
public ImageWriteParam getDefaultWriteParam() {
return new ImageWriteParam(getLocale());
}
// Metadata
/**
* Returns an <code>IIOMetadata</code> object containing default
* values for encoding a stream of images. The contents of the
* object may be manipulated using either the XML tree structure
* returned by the <code>IIOMetadata.getAsTree</code> method, an
* <code>IIOMetadataController</code> object, or via plug-in
* specific interfaces, and the resulting data supplied to one of
* the <code>write</code> methods that take a stream metadata
* parameter.
*
* <p> An optional <code>ImageWriteParam</code> may be supplied
* for cases where it may affect the structure of the stream
* metadata.
*
* <p> If the supplied <code>ImageWriteParam</code> contains
* optional setting values not supported by this writer (<i>e.g.</i>
* progressive encoding or any format-specific settings), they
* will be ignored.
*
* <p> Writers that do not make use of stream metadata
* (<i>e.g.</i>, writers for single-image formats) should return
* <code>null</code>.
*
* @param param an <code>ImageWriteParam</code> that will be used to
* encode the image, or <code>null</code>.
*
* @return an <code>IIOMetadata</code> object.
*/
public abstract IIOMetadata
getDefaultStreamMetadata(ImageWriteParam param);
/**
* Returns an <code>IIOMetadata</code> object containing default
* values for encoding an image of the given type. The contents
* of the object may be manipulated using either the XML tree
* structure returned by the <code>IIOMetadata.getAsTree</code>
* method, an <code>IIOMetadataController</code> object, or via
* plug-in specific interfaces, and the resulting data supplied to
* one of the <code>write</code> methods that take a stream
* metadata parameter.
*
* <p> An optional <code>ImageWriteParam</code> may be supplied
* for cases where it may affect the structure of the image
* metadata.
*
* <p> If the supplied <code>ImageWriteParam</code> contains
* optional setting values not supported by this writer (<i>e.g.</i>
* progressive encoding or any format-specific settings), they
* will be ignored.
*
* @param imageType an <code>ImageTypeSpecifier</code> indicating the
* format of the image to be written later.
* @param param an <code>ImageWriteParam</code> that will be used to
* encode the image, or <code>null</code>.
*
* @return an <code>IIOMetadata</code> object.
*/
public abstract IIOMetadata
getDefaultImageMetadata(ImageTypeSpecifier imageType,
ImageWriteParam param);
// comment inherited
public abstract IIOMetadata convertStreamMetadata(IIOMetadata inData,
ImageWriteParam param);
// comment inherited
public abstract IIOMetadata
convertImageMetadata(IIOMetadata inData,
ImageTypeSpecifier imageType,
ImageWriteParam param);
// Thumbnails
/**
* Returns the number of thumbnails suported by the format being
* written, given the image type and any additional write
* parameters and metadata objects that will be used during
* encoding. A return value of <code>-1</code> indicates that
* insufficient information is available.
*
* <p> An <code>ImageWriteParam</code> may optionally be supplied
* for cases where it may affect thumbnail handling.
*
* <p> If the supplied <code>ImageWriteParam</code> contains
* optional setting values not supported by this writer (<i>e.g.</i>
* progressive encoding or any format-specific settings), they
* will be ignored.
*
* <p> The default implementation returns 0.
*
* @param imageType an <code>ImageTypeSpecifier</code> indicating
* the type of image to be written, or <code>null</code>.
* @param param the <code>ImageWriteParam</code> that will be used for
* writing, or <code>null</code>.
* @param streamMetadata an <code>IIOMetadata</code> object that will
* be used for writing, or <code>null</code>.
* @param imageMetadata an <code>IIOMetadata</code> object that will
* be used for writing, or <code>null</code>.
*
* @return the number of thumbnails that may be written given the
* supplied parameters, or <code>-1</code> if insufficient
* information is available.
*/
public int getNumThumbnailsSupported(ImageTypeSpecifier imageType,
ImageWriteParam param,
IIOMetadata streamMetadata,
IIOMetadata imageMetadata) {
return 0;
}
/**
* Returns an array of <code>Dimension</code>s indicating the
* legal size ranges for thumbnail images as they will be encoded
* in the output file or stream. This information is merely
* advisory; the writer will resize any supplied thumbnails as
* necessary.
*
* <p> The information is returned as a set of pairs; the first
* element of a pair contains an (inclusive) minimum width and
* height, and the second element contains an (inclusive) maximum
* width and height. Together, each pair defines a valid range of
* sizes. To specify a fixed size, the same width and height will
* appear for both elements. A return value of <code>null</code>
* indicates that the size is arbitrary or unknown.
*
* <p> An <code>ImageWriteParam</code> may optionally be supplied
* for cases where it may affect thumbnail handling.
*
* <p> If the supplied <code>ImageWriteParam</code> contains
* optional setting values not supported by this writer (<i>e.g.</i>
* progressive encoding or any format-specific settings), they
* will be ignored.
*
* <p> The default implementation returns <code>null</code>.
*
* @param imageType an <code>ImageTypeSpecifier</code> indicating the
* type of image to be written, or <code>null</code>.
* @param param the <code>ImageWriteParam</code> that will be used for
* writing, or <code>null</code>.
* @param streamMetadata an <code>IIOMetadata</code> object that will
* be used for writing, or <code>null</code>.
* @param imageMetadata an <code>IIOMetadata</code> object that will
* be used for writing, or <code>null</code>.
*
* @return an array of <code>Dimension</code>s with an even length
* of at least two, or <code>null</code>.
*/
public Dimension[] getPreferredThumbnailSizes(ImageTypeSpecifier imageType,
ImageWriteParam param,
IIOMetadata streamMetadata,
IIOMetadata imageMetadata) {
return null;
}
/**
* Returns <code>true</code> if the methods that take an
* <code>IIOImage</code> parameter are capable of dealing with a
* <code>Raster</code> (as opposed to <code>RenderedImage</code>)
* source image. If this method returns <code>false</code>, then
* those methods will throw an
* <code>UnsupportedOperationException</code> if supplied with an
* <code>IIOImage</code> containing a <code>Raster</code>.
*
* <p> The default implementation returns <code>false</code>.
*
* @return <code>true</code> if <code>Raster</code> sources are
* supported.
*/
public boolean canWriteRasters() {
return false;
}
/**
* Appends a complete image stream containing a single image and
* associated stream and image metadata and thumbnails to the
* output. Any necessary header information is included. If the
* output is an <code>ImageOutputStream</code>, its existing
* contents prior to the current seek position are not affected,
* and need not be readable or writable.
*
* <p> The output must have been set beforehand using the
* <code>setOutput</code> method.
*
* <p> Stream metadata may optionally be supplied; if it is
* <code>null</code>, default stream metadata will be used.
*
* <p> If <code>canWriteRasters</code> returns <code>true</code>,
* the <code>IIOImage</code> may contain a <code>Raster</code>
* source. Otherwise, it must contain a
* <code>RenderedImage</code> source.
*
* <p> The supplied thumbnails will be resized if needed, and any
* thumbnails in excess of the supported number will be ignored.
* If the format requires additional thumbnails that are not
* provided, the writer should generate them internally.
*
* <p> An <code>ImageWriteParam</code> may
* optionally be supplied to control the writing process. If
* <code>param</code> is <code>null</code>, a default write param
* will be used.
*
* <p> If the supplied <code>ImageWriteParam</code> contains
* optional setting values not supported by this writer (<i>e.g.</i>
* progressive encoding or any format-specific settings), they
* will be ignored.
*
* @param streamMetadata an <code>IIOMetadata</code> object representing
* stream metadata, or <code>null</code> to use default values.
* @param image an <code>IIOImage</code> object containing an
* image, thumbnails, and metadata to be written.
* @param param an <code>ImageWriteParam</code>, or
* <code>null</code> to use a default
* <code>ImageWriteParam</code>.
*
* @exception IllegalStateException if the output has not
* been set.
* @exception UnsupportedOperationException if <code>image</code>
* contains a <code>Raster</code> and <code>canWriteRasters</code>
* returns <code>false</code>.
* @exception IllegalArgumentException if <code>image</code> is
* <code>null</code>.
* @exception IOException if an error occurs during writing.
*/
public abstract void write(IIOMetadata streamMetadata,
IIOImage image,
ImageWriteParam param) throws IOException;
/**
* Appends a complete image stream containing a single image with
* default metadata and thumbnails to the output. This method is
* a shorthand for <code>write(null, image, null)</code>.
*
* @param image an <code>IIOImage</code> object containing an
* image, thumbnails, and metadata to be written.
*
* @exception IllegalStateException if the output has not
* been set.
* @exception IllegalArgumentException if <code>image</code> is
* <code>null</code>.
* @exception UnsupportedOperationException if <code>image</code>
* contains a <code>Raster</code> and <code>canWriteRasters</code>
* returns <code>false</code>.
* @exception IOException if an error occurs during writing.
*/
public void write(IIOImage image) throws IOException {
write(null, image, null);
}
/**
* Appends a complete image stream consisting of a single image
* with default metadata and thumbnails to the output. This
* method is a shorthand for <code>write(null, new IIOImage(image,
* null, null), null)</code>.
*
* @param image a <code>RenderedImage</code> to be written.
*
* @exception IllegalStateException if the output has not
* been set.
* @exception IllegalArgumentException if <code>image</code> is
* <code>null</code>.
* @exception IOException if an error occurs during writing.
*/
public void write(RenderedImage image) throws IOException {
write(null, new IIOImage(image, null, null), null);
}
// Check that the output has been set, then throw an
// UnsupportedOperationException.
private void unsupported() {
if (getOutput() == null) {
throw new IllegalStateException("getOutput() == null!");
}
throw new UnsupportedOperationException("Unsupported write variant!");
}
// Sequence writes
/**
* Returns <code>true</code> if the writer is able to append an
* image to an image stream that already contains header
* information and possibly prior images.
*
* <p> If <code>canWriteSequence</code> returns <code>false</code>,
* <code>writeToSequence</code> and <code>endWriteSequence</code>
* will throw an <code>UnsupportedOperationException</code>.
*
* <p> The default implementation returns <code>false</code>.
*
* @return <code>true</code> if images may be appended sequentially.
*/
public boolean canWriteSequence() {
return false;
}
/**
* Prepares a stream to accept a series of subsequent
* <code>writeToSequence</code> calls, using the provided stream
* metadata object. The metadata will be written to the stream if
* it should precede the image data. If the argument is <code>null</code>,
* default stream metadata is used.
*
* <p> If the output is an <code>ImageOutputStream</code>, the existing
* contents of the output prior to the current seek position are
* flushed, and need not be readable or writable. If the format
* requires that <code>endWriteSequence</code> be able to rewind to
* patch up the header information, such as for a sequence of images
* in a single TIFF file, then the metadata written by this method
* must remain in a writable portion of the stream. Other formats
* may flush the stream after this method and after each image.
*
* <p> If <code>canWriteSequence</code> returns <code>false</code>,
* this method will throw an
* <code>UnsupportedOperationException</code>.
*
* <p> The output must have been set beforehand using either
* the <code>setOutput</code> method.
*
* <p> The default implementation throws an
* <code>IllegalStateException</code> if the output is
* <code>null</code>, and otherwise throws an
* <code>UnsupportedOperationException</code>.
*
* @param streamMetadata A stream metadata object, or <code>null</code>.
*
* @exception IllegalStateException if the output has not
* been set.
* @exception UnsupportedOperationException if
* <code>canWriteSequence</code> returns <code>false</code>.
* @exception IOException if an error occurs writing the stream
* metadata.
*/
public void prepareWriteSequence(IIOMetadata streamMetadata)
throws IOException {
unsupported();
}
/**
* Appends a single image and possibly associated metadata and
* thumbnails, to the output. If the output is an
* <code>ImageOutputStream</code>, the existing contents of the
* output prior to the current seek position may be flushed, and
* need not be readable or writable, unless the plug-in needs to
* be able to patch up the header information when
* <code>endWriteSequence</code> is called (<italic>e.g.</italic> TIFF).
*
* <p> If <code>canWriteSequence</code> returns <code>false</code>,
* this method will throw an
* <code>UnsupportedOperationException</code>.
*
* <p> The output must have been set beforehand using
* the <code>setOutput</code> method.
*
* <p> <code>prepareWriteSequence</code> must have been called
* beforehand, or an <code>IllegalStateException</code> is thrown.
*
* <p> If <code>canWriteRasters</code> returns <code>true</code>,
* the <code>IIOImage</code> may contain a <code>Raster</code>
* source. Otherwise, it must contain a
* <code>RenderedImage</code> source.
*
* <p> The supplied thumbnails will be resized if needed, and any
* thumbnails in excess of the supported number will be ignored.
* If the format requires additional thumbnails that are not
* provided, the writer will generate them internally.
*
* <p> An <code>ImageWriteParam</code> may optionally be supplied
* to control the writing process. If <code>param</code> is
* <code>null</code>, a default write param will be used.
*
* <p> If the supplied <code>ImageWriteParam</code> contains
* optional setting values not supported by this writer (<i>e.g.</i>
* progressive encoding or any format-specific settings), they
* will be ignored.
*
* <p> The default implementation throws an
* <code>IllegalStateException</code> if the output is
* <code>null</code>, and otherwise throws an
* <code>UnsupportedOperationException</code>.
*
* @param image an <code>IIOImage</code> object containing an
* image, thumbnails, and metadata to be written.
* @param param an <code>ImageWriteParam</code>, or
* <code>null</code> to use a default
* <code>ImageWriteParam</code>.
*
* @exception IllegalStateException if the output has not
* been set, or <code>prepareWriteSequence</code> has not been called.
* @exception UnsupportedOperationException if
* <code>canWriteSequence</code> returns <code>false</code>.
* @exception IllegalArgumentException if <code>image</code> is
* <code>null</code>.
* @exception UnsupportedOperationException if <code>image</code>
* contains a <code>Raster</code> and <code>canWriteRasters</code>
* returns <code>false</code>.
* @exception IOException if an error occurs during writing.
*/
public void writeToSequence(IIOImage image, ImageWriteParam param)
throws IOException {
unsupported();
}
/**
* Completes the writing of a sequence of images begun with
* <code>prepareWriteSequence</code>. Any stream metadata that
* should come at the end of the sequence of images is written out,
* and any header information at the beginning of the sequence is
* patched up if necessary. If the output is an
* <code>ImageOutputStream</code>, data through the stream metadata
* at the end of the sequence are flushed and need not be readable
* or writable.
*
* <p> If <code>canWriteSequence</code> returns <code>false</code>,
* this method will throw an
* <code>UnsupportedOperationException</code>.
*
* <p> The default implementation throws an
* <code>IllegalStateException</code> if the output is
* <code>null</code>, and otherwise throws an
* <code>UnsupportedOperationException</code>.
*
* @exception IllegalStateException if the output has not
* been set, or <code>prepareWriteSequence</code> has not been called.
* @exception UnsupportedOperationException if
* <code>canWriteSequence</code> returns <code>false</code>.
* @exception IOException if an error occurs during writing.
*/
public void endWriteSequence() throws IOException {
unsupported();
}
// Metadata replacement
/**
* Returns <code>true</code> if it is possible to replace the
* stream metadata already present in the output.
*
* <p> The default implementation throws an
* <code>IllegalStateException</code> if the output is
* <code>null</code>, and otherwise returns <code>false</code>.
*
* @return <code>true</code> if replacement of stream metadata is
* allowed.
*
* @exception IllegalStateException if the output has not
* been set.
* @exception IOException if an I/O error occurs during the query.
*/
public boolean canReplaceStreamMetadata() throws IOException {
if (getOutput() == null) {
throw new IllegalStateException("getOutput() == null!");
}
return false;
}
/**
* Replaces the stream metadata in the output with new
* information. If the output is an
* <code>ImageOutputStream</code>, the prior contents of the
* stream are examined and possibly edited to make room for the
* new data. All of the prior contents of the output must be
* available for reading and writing.
*
* <p> If <code>canReplaceStreamMetadata</code> returns
* <code>false</code>, an
* <code>UnsupportedOperationException</code> will be thrown.
*
* <p> The default implementation throws an
* <code>IllegalStateException</code> if the output is
* <code>null</code>, and otherwise throws an
* <code>UnsupportedOperationException</code>.
*
* @param streamMetadata an <code>IIOMetadata</code> object representing
* stream metadata, or <code>null</code> to use default values.
*
* @exception IllegalStateException if the output has not
* been set.
* @exception UnsupportedOperationException if the
* <code>canReplaceStreamMetadata</code> returns
* <code>false</code>. modes do not include
* @exception IOException if an error occurs during writing.
*/
public void replaceStreamMetadata(IIOMetadata streamMetadata)
throws IOException {
unsupported();
}
/**
* Returns <code>true</code> if it is possible to replace the
* image metadata associated with an existing image with index
* <code>imageIndex</code>. If this method returns
* <code>false</code>, a call to
* <code>replaceImageMetadata(imageIndex)</code> will throw an
* <code>UnsupportedOperationException</code>.
*
* <p> A writer that does not support any image metadata
* replacement may return <code>false</code> without performing
* bounds checking on the index.
*
* <p> The default implementation throws an
* <code>IllegalStateException</code> if the output is
* <code>null</code>, and otherwise returns <code>false</code>
* without checking the value of <code>imageIndex</code>.
*
* @param imageIndex the index of the image whose metadata is to
* be replaced.
*
* @return <code>true</code> if the image metadata of the given
* image can be replaced.
*
* @exception IllegalStateException if the output has not
* been set.
* @exception IndexOutOfBoundsException if the writer supports
* image metadata replacement in general, but
* <code>imageIndex</code> is less than 0 or greater than the
* largest available index.
* @exception IOException if an I/O error occurs during the query.
*/
public boolean canReplaceImageMetadata(int imageIndex)
throws IOException {
if (getOutput() == null) {
throw new IllegalStateException("getOutput() == null!");
}
return false;
}
/**
* Replaces the image metadata associated with an existing image.
*
* <p> If <code>canReplaceImageMetadata(imageIndex)</code> returns
* <code>false</code>, an
* <code>UnsupportedOperationException</code> will be thrown.
*
* <p> The default implementation throws an
* <code>IllegalStateException</code> if the output is
* <code>null</code>, and otherwise throws an
* <code>UnsupportedOperationException</code>.
*
* @param imageIndex the index of the image whose metadata is to
* be replaced.
* @param imageMetadata an <code>IIOMetadata</code> object
* representing image metadata, or <code>null</code>.
*
* @exception IllegalStateException if the output has not been
* set.
* @exception UnsupportedOperationException if
* <code>canReplaceImageMetadata</code> returns
* <code>false</code>.
* @exception IndexOutOfBoundsException if <code>imageIndex</code>
* is less than 0 or greater than the largest available index.
* @exception IOException if an error occurs during writing.
*/
public void replaceImageMetadata(int imageIndex,
IIOMetadata imageMetadata)
throws IOException {
unsupported();
}
// Image insertion
/**
* Returns <code>true</code> if the writer supports the insertion
* of a new image at the given index. Existing images with
* indices greater than or equal to the insertion index will have
* their indices increased by 1. A value for
* <code>imageIndex</code> of <code>-1</code> may be used to
* signify an index one larger than the current largest index.
*
* <p> A writer that does not support any image insertion may
* return <code>false</code> without performing bounds checking on
* the index.
*
* <p> The default implementation throws an
* <code>IllegalStateException</code> if the output is
* <code>null</code>, and otherwise returns <code>false</code>
* withour checking the value of <code>imageIndex</code>.
*
* @param imageIndex the index at which the image is to be
* inserted.
*
* @return <code>true</code> if an image may be inserted at the
* given index.
*
* @exception IllegalStateException if the output has not
* been set.
* @exception IndexOutOfBoundsException if the writer supports
* image insertion in general, but <code>imageIndex</code> is less
* than -1 or greater than the largest available index.
* @exception IOException if an I/O error occurs during the query.
*/
public boolean canInsertImage(int imageIndex) throws IOException {
if (getOutput() == null) {
throw new IllegalStateException("getOutput() == null!");
}
return false;
}
/**
* Inserts a new image into an existing image stream. Existing
* images with an index greater than <code>imageIndex</code> are
* preserved, and their indices are each increased by 1. A value
* for <code>imageIndex</code> of -1 may be used to signify an
* index one larger than the previous largest index; that is, it
* will cause the image to be logically appended to the end of the
* sequence. If the output is an <code>ImageOutputStream</code>,
* the entirety of the stream must be both readable and writeable.
*
* <p> If <code>canInsertImage(imageIndex)</code> returns
* <code>false</code>, an
* <code>UnsupportedOperationException</code> will be thrown.
*
* <p> An <code>ImageWriteParam</code> may optionally be supplied
* to control the writing process. If <code>param</code> is
* <code>null</code>, a default write param will be used.
*
* <p> If the supplied <code>ImageWriteParam</code> contains
* optional setting values not supported by this writer (<i>e.g.</i>
* progressive encoding or any format-specific settings), they
* will be ignored.
*
* <p> The default implementation throws an
* <code>IllegalStateException</code> if the output is
* <code>null</code>, and otherwise throws an
* <code>UnsupportedOperationException</code>.
*
* @param imageIndex the index at which to write the image.
* @param image an <code>IIOImage</code> object containing an
* image, thumbnails, and metadata to be written.
* @param param an <code>ImageWriteParam</code>, or
* <code>null</code> to use a default
* <code>ImageWriteParam</code>.
*
* @exception IllegalStateException if the output has not
* been set.
* @exception UnsupportedOperationException if
* <code>canInsertImage(imageIndex)</code> returns <code>false</code>.
* @exception IllegalArgumentException if <code>image</code> is
* <code>null</code>.
* @exception IndexOutOfBoundsException if <code>imageIndex</code>
* is less than -1 or greater than the largest available index.
* @exception UnsupportedOperationException if <code>image</code>
* contains a <code>Raster</code> and <code>canWriteRasters</code>
* returns <code>false</code>.
* @exception IOException if an error occurs during writing.
*/
public void writeInsert(int imageIndex,
IIOImage image,
ImageWriteParam param) throws IOException {
unsupported();
}
// Image removal
/**
* Returns <code>true</code> if the writer supports the removal
* of an existing image at the given index. Existing images with
* indices greater than the insertion index will have
* their indices decreased by 1.
*
* <p> A writer that does not support any image removal may
* return <code>false</code> without performing bounds checking on
* the index.
*
* <p> The default implementation throws an
* <code>IllegalStateException</code> if the output is
* <code>null</code>, and otherwise returns <code>false</code>
* without checking the value of <code>imageIndex</code>.
*
* @param imageIndex the index of the image to be removed.
*
* @return <code>true</code> if it is possible to remove the given
* image.
*
* @exception IllegalStateException if the output has not
* been set.
* @exception IndexOutOfBoundsException if the writer supports
* image removal in general, but <code>imageIndex</code> is less
* than 0 or greater than the largest available index.
* @exception IOException if an I/O error occurs during the
* query.
*/
public boolean canRemoveImage(int imageIndex) throws IOException {
if (getOutput() == null) {
throw new IllegalStateException("getOutput() == null!");
}
return false;
}
/**
* Removes an image from the stream.
*
* <p> If <code>canRemoveImage(imageIndex)</code> returns false,
* an <code>UnsupportedOperationException</code>will be thrown.
*
* <p> The removal may or may not cause a reduction in the actual
* file size.
*
* <p> The default implementation throws an
* <code>IllegalStateException</code> if the output is
* <code>null</code>, and otherwise throws an
* <code>UnsupportedOperationException</code>.
*
* @param imageIndex the index of the image to be removed.
*
* @exception IllegalStateException if the output has not
* been set.
* @exception UnsupportedOperationException if
* <code>canRemoveImage(imageIndex)</code> returns <code>false</code>.
* @exception IndexOutOfBoundsException if <code>imageIndex</code>
* is less than 0 or greater than the largest available index.
* @exception IOException if an I/O error occurs during the
* removal.
*/
public void removeImage(int imageIndex) throws IOException {
unsupported();
}
// Empty images
/**
* Returns <code>true</code> if the writer supports the writing of
* a complete image stream consisting of a single image with
* undefined pixel values and associated metadata and thumbnails
* to the output. The pixel values may be defined by future
* calls to the <code>replacePixels</code> methods. If the output
* is an <code>ImageOutputStream</code>, its existing contents
* prior to the current seek position are not affected, and need
* not be readable or writable.
*
* <p> The default implementation throws an
* <code>IllegalStateException</code> if the output is
* <code>null</code>, and otherwise returns <code>false</code>.
*
* @return <code>true</code> if the writing of complete image
* stream with contents to be defined later is supported.
*
* @exception IllegalStateException if the output has not been
* set.
* @exception IOException if an I/O error occurs during the
* query.
*/
public boolean canWriteEmpty() throws IOException {
if (getOutput() == null) {
throw new IllegalStateException("getOutput() == null!");
}
return false;
}
/**
* Begins the writing of a complete image stream, consisting of a
* single image with undefined pixel values and associated
* metadata and thumbnails, to the output. The pixel values will
* be defined by future calls to the <code>replacePixels</code>
* methods. If the output is an <code>ImageOutputStream</code>,
* its existing contents prior to the current seek position are
* not affected, and need not be readable or writable.
*
* <p> The writing is not complete until a call to
* <code>endWriteEmpty</code> occurs. Calls to
* <code>prepareReplacePixels</code>, <code>replacePixels</code>,
* and <code>endReplacePixels</code> may occur between calls to
* <code>prepareWriteEmpty</code> and <code>endWriteEmpty</code>.
* However, calls to <code>prepareWriteEmpty</code> cannot be
* nested, and calls to <code>prepareWriteEmpty</code> and
* <code>prepareInsertEmpty</code> may not be interspersed.
*
* <p> If <code>canWriteEmpty</code> returns <code>false</code>,
* an <code>UnsupportedOperationException</code> will be thrown.
*
* <p> An <code>ImageWriteParam</code> may optionally be supplied
* to control the writing process. If <code>param</code> is
* <code>null</code>, a default write param will be used.
*
* <p> If the supplied <code>ImageWriteParam</code> contains
* optional setting values not supported by this writer (<i>e.g.</i>
* progressive encoding or any format-specific settings), they
* will be ignored.
*
* <p> The default implementation throws an
* <code>IllegalStateException</code> if the output is
* <code>null</code>, and otherwise throws an
* <code>UnsupportedOperationException</code>.
*
* @param streamMetadata an <code>IIOMetadata</code> object representing
* stream metadata, or <code>null</code> to use default values.
* @param imageType an <code>ImageTypeSpecifier</code> describing
* the layout of the image.
* @param width the width of the image.
* @param height the height of the image.
* @param imageMetadata an <code>IIOMetadata</code> object
* representing image metadata, or <code>null</code>.
* @param thumbnails a <code>List</code> of
* <code>BufferedImage</code> thumbnails for this image, or
* <code>null</code>.
* @param param an <code>ImageWriteParam</code>, or
* <code>null</code> to use a default
* <code>ImageWriteParam</code>.
*
* @exception IllegalStateException if the output has not
* been set.
* @exception UnsupportedOperationException if
* <code>canWriteEmpty</code> returns <code>false</code>.
* @exception IllegalStateException if a previous call to
* <code>prepareWriteEmpty</code> has been made without a
* corresponding call to <code>endWriteEmpty</code>.
* @exception IllegalStateException if a previous call to
* <code>prepareInsertEmpty</code> has been made without a
* corresponding call to <code>endInsertEmpty</code>.
* @exception IllegalArgumentException if <code>imageType</code>
* is <code>null</code> or <code>thumbnails</code> contains
* <code>null</code> references or objects other than
* <code>BufferedImage</code>s.
* @exception IllegalArgumentException if width or height are less
* than 1.
* @exception IOException if an I/O error occurs during writing.
*/
public void prepareWriteEmpty(IIOMetadata streamMetadata,
ImageTypeSpecifier imageType,
int width, int height,
IIOMetadata imageMetadata,
List<? extends BufferedImage> thumbnails,
ImageWriteParam param) throws IOException {
unsupported();
}
/**
* Completes the writing of a new image that was begun with a
* prior call to <code>prepareWriteEmpty</code>.
*
* <p> If <code>canWriteEmpty()</code> returns <code>false</code>,
* an <code>UnsupportedOperationException</code> will be thrown.
*
* <p> The default implementation throws an
* <code>IllegalStateException</code> if the output is
* <code>null</code>, and otherwise throws an
* <code>UnsupportedOperationException</code>.
*
* @exception IllegalStateException if the output has not
* been set.
* @exception UnsupportedOperationException if
* <code>canWriteEmpty(imageIndex)</code> returns
* <code>false</code>.
* @exception IllegalStateException if a previous call to
* <code>prepareWriteEmpty</code> without a corresponding call to
* <code>endWriteEmpty</code> has not been made.
* @exception IllegalStateException if a previous call to
* <code>prepareInsertEmpty</code> without a corresponding call to
* <code>endInsertEmpty</code> has been made.
* @exception IllegalStateException if a call to
* <code>prepareReiplacePixels</code> has been made without a
* matching call to <code>endReplacePixels</code>.
* @exception IOException if an I/O error occurs during writing.
*/
public void endWriteEmpty() throws IOException {
if (getOutput() == null) {
throw new IllegalStateException("getOutput() == null!");
}
throw new IllegalStateException("No call to prepareWriteEmpty!");
}
/**
* Returns <code>true</code> if the writer supports the insertion
* of a new, empty image at the given index. The pixel values of
* the image are undefined, and may be specified in pieces using
* the <code>replacePixels</code> methods. Existing images with
* indices greater than or equal to the insertion index will have
* their indices increased by 1. A value for
* <code>imageIndex</code> of <code>-1</code> may be used to
* signify an index one larger than the current largest index.
*
* <p> A writer that does not support insertion of empty images
* may return <code>false</code> without performing bounds
* checking on the index.
*
* <p> The default implementation throws an
* <code>IllegalStateException</code> if the output is
* <code>null</code>, and otherwise returns <code>false</code>
* without checking the value of <code>imageIndex</code>.
*
* @param imageIndex the index at which the image is to be
* inserted.
*
* @return <code>true</code> if an empty image may be inserted at
* the given index.
*
* @exception IllegalStateException if the output has not been
* set.
* @exception IndexOutOfBoundsException if the writer supports
* empty image insertion in general, but <code>imageIndex</code>
* is less than -1 or greater than the largest available index.
* @exception IOException if an I/O error occurs during the
* query.
*/
public boolean canInsertEmpty(int imageIndex) throws IOException {
if (getOutput() == null) {
throw new IllegalStateException("getOutput() == null!");
}
return false;
}
/**
* Begins the insertion of a new image with undefined pixel values
* into an existing image stream. Existing images with an index
* greater than <code>imageIndex</code> are preserved, and their
* indices are each increased by 1. A value for
* <code>imageIndex</code> of -1 may be used to signify an index
* one larger than the previous largest index; that is, it will
* cause the image to be logically appended to the end of the
* sequence. If the output is an <code>ImageOutputStream</code>,
* the entirety of the stream must be both readable and writeable.
*
* <p> The image contents may be
* supplied later using the <code>replacePixels</code> method.
* The insertion is not complete until a call to
* <code>endInsertEmpty</code> occurs. Calls to
* <code>prepareReplacePixels</code>, <code>replacePixels</code>,
* and <code>endReplacePixels</code> may occur between calls to
* <code>prepareInsertEmpty</code> and
* <code>endInsertEmpty</code>. However, calls to
* <code>prepareInsertEmpty</code> cannot be nested, and calls to
* <code>prepareWriteEmpty</code> and
* <code>prepareInsertEmpty</code> may not be interspersed.
*
* <p> If <code>canInsertEmpty(imageIndex)</code> returns
* <code>false</code>, an
* <code>UnsupportedOperationException</code> will be thrown.
*
* <p> An <code>ImageWriteParam</code> may optionally be supplied
* to control the writing process. If <code>param</code> is
* <code>null</code>, a default write param will be used.
*
* <p> If the supplied <code>ImageWriteParam</code> contains
* optional setting values not supported by this writer (<i>e.g.</i>
* progressive encoding or any format-specific settings), they
* will be ignored.
*
* <p> The default implementation throws an
* <code>IllegalStateException</code> if the output is
* <code>null</code>, and otherwise throws an
* <code>UnsupportedOperationException</code>.
*
* @param imageIndex the index at which to write the image.
* @param imageType an <code>ImageTypeSpecifier</code> describing
* the layout of the image.
* @param width the width of the image.
* @param height the height of the image.
* @param imageMetadata an <code>IIOMetadata</code> object
* representing image metadata, or <code>null</code>.
* @param thumbnails a <code>List</code> of
* <code>BufferedImage</code> thumbnails for this image, or
* <code>null</code>.
* @param param an <code>ImageWriteParam</code>, or
* <code>null</code> to use a default
* <code>ImageWriteParam</code>.
*
* @exception IllegalStateException if the output has not
* been set.
* @exception UnsupportedOperationException if
* <code>canInsertEmpty(imageIndex)</code> returns
* <code>false</code>.
* @exception IndexOutOfBoundsException if <code>imageIndex</code>
* is less than -1 or greater than the largest available index.
* @exception IllegalStateException if a previous call to
* <code>prepareInsertEmpty</code> has been made without a
* corresponding call to <code>endInsertEmpty</code>.
* @exception IllegalStateException if a previous call to
* <code>prepareWriteEmpty</code> has been made without a
* corresponding call to <code>endWriteEmpty</code>.
* @exception IllegalArgumentException if <code>imageType</code>
* is <code>null</code> or <code>thumbnails</code> contains
* <code>null</code> references or objects other than
* <code>BufferedImage</code>s.
* @exception IllegalArgumentException if width or height are less
* than 1.
* @exception IOException if an I/O error occurs during writing.
*/
public void prepareInsertEmpty(int imageIndex,
ImageTypeSpecifier imageType,
int width, int height,
IIOMetadata imageMetadata,
List<? extends BufferedImage> thumbnails,
ImageWriteParam param) throws IOException {
unsupported();
}
/**
* Completes the insertion of a new image that was begun with a
* prior call to <code>prepareInsertEmpty</code>.
*
* <p> The default implementation throws an
* <code>IllegalStateException</code> if the output is
* <code>null</code>, and otherwise throws an
* <code>UnsupportedOperationException</code>.
*
* @exception IllegalStateException if the output has not
* been set.
* @exception UnsupportedOperationException if
* <code>canInsertEmpty(imageIndex)</code> returns
* <code>false</code>.
* @exception IllegalStateException if a previous call to
* <code>prepareInsertEmpty</code> without a corresponding call to
* <code>endInsertEmpty</code> has not been made.
* @exception IllegalStateException if a previous call to
* <code>prepareWriteEmpty</code> without a corresponding call to
* <code>endWriteEmpty</code> has been made.
* @exception IllegalStateException if a call to
* <code>prepareReplacePixels</code> has been made without a
* matching call to <code>endReplacePixels</code>.
* @exception IOException if an I/O error occurs during writing.
*/
public void endInsertEmpty() throws IOException {
unsupported();
}
// Pixel replacement
/**
* Returns <code>true</code> if the writer allows pixels of the
* given image to be replaced using the <code>replacePixels</code>
* methods.
*
* <p> A writer that does not support any pixel replacement may
* return <code>false</code> without performing bounds checking on
* the index.
*
* <p> The default implementation throws an
* <code>IllegalStateException</code> if the output is
* <code>null</code>, and otherwise returns <code>false</code>
* without checking the value of <code>imageIndex</code>.
*
* @param imageIndex the index of the image whose pixels are to be
* replaced.
*
* @return <code>true</code> if the pixels of the given
* image can be replaced.
*
* @exception IllegalStateException if the output has not been
* set.
* @exception IndexOutOfBoundsException if the writer supports
* pixel replacement in general, but <code>imageIndex</code> is
* less than 0 or greater than the largest available index.
* @exception IOException if an I/O error occurs during the query.
*/
public boolean canReplacePixels(int imageIndex) throws IOException {
if (getOutput() == null) {
throw new IllegalStateException("getOutput() == null!");
}
return false;
}
/**
* Prepares the writer to handle a series of calls to the
* <code>replacePixels</code> methods. The affected pixel area
* will be clipped against the supplied
*
* <p> If <code>canReplacePixels</code> returns
* <code>false</code>, and
* <code>UnsupportedOperationException</code> will be thrown.
*
* <p> The default implementation throws an
* <code>IllegalStateException</code> if the output is
* <code>null</code>, and otherwise throws an
* <code>UnsupportedOperationException</code>.
*
* @param imageIndex the index of the image whose pixels are to be
* replaced.
* @param region a <code>Rectangle</code> that will be used to clip
* future pixel regions.
*
* @exception IllegalStateException if the output has not
* been set.
* @exception UnsupportedOperationException if
* <code>canReplacePixels(imageIndex)</code> returns
* <code>false</code>.
* @exception IndexOutOfBoundsException if <code>imageIndex</code>
* is less than 0 or greater than the largest available index.
* @exception IllegalStateException if there is a previous call to
* <code>prepareReplacePixels</code> without a matching call to
* <code>endReplacePixels</code> (<i>i.e.</i>, nesting is not
* allowed).
* @exception IllegalArgumentException if <code>region</code> is
* <code>null</code> or has a width or height less than 1.
* @exception IOException if an I/O error occurs during the
* preparation.
*/
public void prepareReplacePixels(int imageIndex,
Rectangle region) throws IOException {
unsupported();
}
/**
* Replaces a portion of an image already present in the output
* with a portion of the given image. The image data must match,
* or be convertible to, the image layout of the existing image.
*
* <p> The destination region is specified in the
* <code>param</code> argument, and will be clipped to the image
* boundaries and the region supplied to
* <code>prepareReplacePixels</code>. At least one pixel of the
* source must not be clipped, or an exception is thrown.
*
* <p> An <code>ImageWriteParam</code> may optionally be supplied
* to control the writing process. If <code>param</code> is
* <code>null</code>, a default write param will be used.
*
* <p> If the supplied <code>ImageWriteParam</code> contains
* optional setting values not supported by this writer (<i>e.g.</i>
* progressive encoding or any format-specific settings), they
* will be ignored.
*
* <p> This method may only be called after a call to
* <code>prepareReplacePixels</code>, or else an
* <code>IllegalStateException</code> will be thrown.
*
* <p> The default implementation throws an
* <code>IllegalStateException</code> if the output is
* <code>null</code>, and otherwise throws an
* <code>UnsupportedOperationException</code>.
*
* @param image a <code>RenderedImage</code> containing source
* pixels.
* @param param an <code>ImageWriteParam</code>, or
* <code>null</code> to use a default
* <code>ImageWriteParam</code>.
*
* @exception IllegalStateException if the output has not
* been set.
* @exception UnsupportedOperationException if
* <code>canReplacePixels(imageIndex)</code> returns
* <code>false</code>.
* @exception IllegalStateException if there is no previous call to
* <code>prepareReplacePixels</code> without a matching call to
* <code>endReplacePixels</code>.
* @exception IllegalArgumentException if any of the following are true:
* <ul>
* <li> <code>image</code> is <code>null</code>.
* <li> <code>param</code> is <code>null</code>.
* <li> the intersected region does not contain at least one pixel.
* <li> the layout of <code>image</code> does not match, or this
* writer cannot convert it to, the existing image layout.
* </ul>
* @exception IOException if an I/O error occurs during writing.
*/
public void replacePixels(RenderedImage image, ImageWriteParam param)
throws IOException {
unsupported();
}
/**
* Replaces a portion of an image already present in the output
* with a portion of the given <code>Raster</code>. The image
* data must match, or be convertible to, the image layout of the
* existing image.
*
* <p> An <code>ImageWriteParam</code> may optionally be supplied
* to control the writing process. If <code>param</code> is
* <code>null</code>, a default write param will be used.
*
* <p> The destination region is specified in the
* <code>param</code> argument, and will be clipped to the image
* boundaries and the region supplied to
* <code>prepareReplacePixels</code>. At least one pixel of the
* source must not be clipped, or an exception is thrown.
*
* <p> If the supplied <code>ImageWriteParam</code> contains
* optional setting values not supported by this writer (<i>e.g.</i>
* progressive encoding or any format-specific settings), they
* will be ignored.
*
* <p> This method may only be called after a call to
* <code>prepareReplacePixels</code>, or else an
* <code>IllegalStateException</code> will be thrown.
*
* <p> The default implementation throws an
* <code>IllegalStateException</code> if the output is
* <code>null</code>, and otherwise throws an
* <code>UnsupportedOperationException</code>.
*
* @param raster a <code>Raster</code> containing source
* pixels.
* @param param an <code>ImageWriteParam</code>, or
* <code>null</code> to use a default
* <code>ImageWriteParam</code>.
*
* @exception IllegalStateException if the output has not
* been set.
* @exception UnsupportedOperationException if
* <code>canReplacePixels(imageIndex)</code> returns
* <code>false</code>.
* @exception IllegalStateException if there is no previous call to
* <code>prepareReplacePixels</code> without a matching call to
* <code>endReplacePixels</code>.
* @exception UnsupportedOperationException if
* <code>canWriteRasters</code> returns <code>false</code>.
* @exception IllegalArgumentException if any of the following are true:
* <ul>
* <li> <code>raster</code> is <code>null</code>.
* <li> <code>param</code> is <code>null</code>.
* <li> the intersected region does not contain at least one pixel.
* <li> the layout of <code>raster</code> does not match, or this
* writer cannot convert it to, the existing image layout.
* </ul>
* @exception IOException if an I/O error occurs during writing.
*/
public void replacePixels(Raster raster, ImageWriteParam param)
throws IOException {
unsupported();
}
/**
* Terminates a sequence of calls to <code>replacePixels</code>.
*
* <p> If <code>canReplacePixels</code> returns
* <code>false</code>, and
* <code>UnsupportedOperationException</code> will be thrown.
*
* <p> The default implementation throws an
* <code>IllegalStateException</code> if the output is
* <code>null</code>, and otherwise throws an
* <code>UnsupportedOperationException</code>.
*
* @exception IllegalStateException if the output has not
* been set.
* @exception UnsupportedOperationException if
* <code>canReplacePixels(imageIndex)</code> returns
* <code>false</code>.
* @exception IllegalStateException if there is no previous call
* to <code>prepareReplacePixels</code> without a matching call to
* <code>endReplacePixels</code>.
* @exception IOException if an I/O error occurs during writing.
*/
public void endReplacePixels() throws IOException {
unsupported();
}
// Abort
/**
* Requests that any current write operation be aborted. The
* contents of the output following the abort will be undefined.
*
* <p> Writers should call <code>clearAbortRequest</code> at the
* beginning of each write operation, and poll the value of
* <code>abortRequested</code> regularly during the write.
*/
public synchronized void abort() {
this.abortFlag = true;
}
/**
* Returns <code>true</code> if a request to abort the current
* write operation has been made since the writer was instantiated or
* <code>clearAbortRequest</code> was called.
*
* @return <code>true</code> if the current write operation should
* be aborted.
*
* @see #abort
* @see #clearAbortRequest
*/
protected synchronized boolean abortRequested() {
return this.abortFlag;
}
/**
* Clears any previous abort request. After this method has been
* called, <code>abortRequested</code> will return
* <code>false</code>.
*
* @see #abort
* @see #abortRequested
*/
protected synchronized void clearAbortRequest() {
this.abortFlag = false;
}
// Listeners
/**
* Adds an <code>IIOWriteWarningListener</code> to the list of
* registered warning listeners. If <code>listener</code> is
* <code>null</code>, no exception will be thrown and no action
* will be taken. Messages sent to the given listener will be
* localized, if possible, to match the current
* <code>Locale</code>. If no <code>Locale</code> has been set,
* warning messages may be localized as the writer sees fit.
*
* @param listener an <code>IIOWriteWarningListener</code> to be
* registered.
*
* @see #removeIIOWriteWarningListener
*/
public void addIIOWriteWarningListener(IIOWriteWarningListener listener) {
if (listener == null) {
return;
}
warningListeners = ImageReader.addToList(warningListeners, listener);
warningLocales = ImageReader.addToList(warningLocales, getLocale());
}
/**
* Removes an <code>IIOWriteWarningListener</code> from the list
* of registered warning listeners. If the listener was not
* previously registered, or if <code>listener</code> is
* <code>null</code>, no exception will be thrown and no action
* will be taken.
*
* @param listener an <code>IIOWriteWarningListener</code> to be
* deregistered.
*
* @see #addIIOWriteWarningListener
*/
public
void removeIIOWriteWarningListener(IIOWriteWarningListener listener) {
if (listener == null || warningListeners == null) {
return;
}
int index = warningListeners.indexOf(listener);
if (index != -1) {
warningListeners.remove(index);
warningLocales.remove(index);
if (warningListeners.size() == 0) {
warningListeners = null;
warningLocales = null;
}
}
}
/**
* Removes all currently registered
* <code>IIOWriteWarningListener</code> objects.
*
* <p> The default implementation sets the
* <code>warningListeners</code> and <code>warningLocales</code>
* instance variables to <code>null</code>.
*/
public void removeAllIIOWriteWarningListeners() {
this.warningListeners = null;
this.warningLocales = null;
}
/**
* Adds an <code>IIOWriteProgressListener</code> to the list of
* registered progress listeners. If <code>listener</code> is
* <code>null</code>, no exception will be thrown and no action
* will be taken.
*
* @param listener an <code>IIOWriteProgressListener</code> to be
* registered.
*
* @see #removeIIOWriteProgressListener
*/
public void
addIIOWriteProgressListener(IIOWriteProgressListener listener) {
if (listener == null) {
return;
}
progressListeners = ImageReader.addToList(progressListeners, listener);
}
/**
* Removes an <code>IIOWriteProgressListener</code> from the list
* of registered progress listeners. If the listener was not
* previously registered, or if <code>listener</code> is
* <code>null</code>, no exception will be thrown and no action
* will be taken.
*
* @param listener an <code>IIOWriteProgressListener</code> to be
* deregistered.
*
* @see #addIIOWriteProgressListener
*/
public void
removeIIOWriteProgressListener(IIOWriteProgressListener listener) {
if (listener == null || progressListeners == null) {
return;
}
progressListeners =
ImageReader.removeFromList(progressListeners, listener);
}
/**
* Removes all currently registered
* <code>IIOWriteProgressListener</code> objects.
*
* <p> The default implementation sets the
* <code>progressListeners</code> instance variable to
* <code>null</code>.
*/
public void removeAllIIOWriteProgressListeners() {
this.progressListeners = null;
}
/**
* Broadcasts the start of an image write to all registered
* <code>IIOWriteProgressListener</code>s by calling their
* <code>imageStarted</code> method. Subclasses may use this
* method as a convenience.
*
* @param imageIndex the index of the image about to be written.
*/
protected void processImageStarted(int imageIndex) {
if (progressListeners == null) {
return;
}
int numListeners = progressListeners.size();
for (int i = 0; i < numListeners; i++) {
IIOWriteProgressListener listener =
(IIOWriteProgressListener)progressListeners.get(i);
listener.imageStarted(this, imageIndex);
}
}
/**
* Broadcasts the current percentage of image completion to all
* registered <code>IIOWriteProgressListener</code>s by calling
* their <code>imageProgress</code> method. Subclasses may use
* this method as a convenience.
*
* @param percentageDone the current percentage of completion,
* as a <code>float</code>.
*/
protected void processImageProgress(float percentageDone) {
if (progressListeners == null) {
return;
}
int numListeners = progressListeners.size();
for (int i = 0; i < numListeners; i++) {
IIOWriteProgressListener listener =
(IIOWriteProgressListener)progressListeners.get(i);
listener.imageProgress(this, percentageDone);
}
}
/**
* Broadcasts the completion of an image write to all registered
* <code>IIOWriteProgressListener</code>s by calling their
* <code>imageComplete</code> method. Subclasses may use this
* method as a convenience.
*/
protected void processImageComplete() {
if (progressListeners == null) {
return;
}
int numListeners = progressListeners.size();
for (int i = 0; i < numListeners; i++) {
IIOWriteProgressListener listener =
(IIOWriteProgressListener)progressListeners.get(i);
listener.imageComplete(this);
}
}
/**
* Broadcasts the start of a thumbnail write to all registered
* <code>IIOWriteProgressListener</code>s by calling their
* <code>thumbnailStarted</code> method. Subclasses may use this
* method as a convenience.
*
* @param imageIndex the index of the image associated with the
* thumbnail.
* @param thumbnailIndex the index of the thumbnail.
*/
protected void processThumbnailStarted(int imageIndex,
int thumbnailIndex) {
if (progressListeners == null) {
return;
}
int numListeners = progressListeners.size();
for (int i = 0; i < numListeners; i++) {
IIOWriteProgressListener listener =
(IIOWriteProgressListener)progressListeners.get(i);
listener.thumbnailStarted(this, imageIndex, thumbnailIndex);
}
}
/**
* Broadcasts the current percentage of thumbnail completion to
* all registered <code>IIOWriteProgressListener</code>s by calling
* their <code>thumbnailProgress</code> method. Subclasses may
* use this method as a convenience.
*
* @param percentageDone the current percentage of completion,
* as a <code>float</code>.
*/
protected void processThumbnailProgress(float percentageDone) {
if (progressListeners == null) {
return;
}
int numListeners = progressListeners.size();
for (int i = 0; i < numListeners; i++) {
IIOWriteProgressListener listener =
(IIOWriteProgressListener)progressListeners.get(i);
listener.thumbnailProgress(this, percentageDone);
}
}
/**
* Broadcasts the completion of a thumbnail write to all registered
* <code>IIOWriteProgressListener</code>s by calling their
* <code>thumbnailComplete</code> method. Subclasses may use this
* method as a convenience.
*/
protected void processThumbnailComplete() {
if (progressListeners == null) {
return;
}
int numListeners = progressListeners.size();
for (int i = 0; i < numListeners; i++) {
IIOWriteProgressListener listener =
(IIOWriteProgressListener)progressListeners.get(i);
listener.thumbnailComplete(this);
}
}
/**
* Broadcasts that the write has been aborted to all registered
* <code>IIOWriteProgressListener</code>s by calling their
* <code>writeAborted</code> method. Subclasses may use this
* method as a convenience.
*/
protected void processWriteAborted() {
if (progressListeners == null) {
return;
}
int numListeners = progressListeners.size();
for (int i = 0; i < numListeners; i++) {
IIOWriteProgressListener listener =
(IIOWriteProgressListener)progressListeners.get(i);
listener.writeAborted(this);
}
}
/**
* Broadcasts a warning message to all registered
* <code>IIOWriteWarningListener</code>s by calling their
* <code>warningOccurred</code> method. Subclasses may use this
* method as a convenience.
*
* @param imageIndex the index of the image on which the warning
* occurred.
* @param warning the warning message.
*
* @exception IllegalArgumentException if <code>warning</code>
* is <code>null</code>.
*/
protected void processWarningOccurred(int imageIndex,
String warning) {
if (warningListeners == null) {
return;
}
if (warning == null) {
throw new IllegalArgumentException("warning == null!");
}
int numListeners = warningListeners.size();
for (int i = 0; i < numListeners; i++) {
IIOWriteWarningListener listener =
(IIOWriteWarningListener)warningListeners.get(i);
listener.warningOccurred(this, imageIndex, warning);
}
}
/**
* Broadcasts a localized warning message to all registered
* <code>IIOWriteWarningListener</code>s by calling their
* <code>warningOccurred</code> method with a string taken
* from a <code>ResourceBundle</code>. Subclasses may use this
* method as a convenience.
*
* @param imageIndex the index of the image on which the warning
* occurred.
* @param baseName the base name of a set of
* <code>ResourceBundle</code>s containing localized warning
* messages.
* @param keyword the keyword used to index the warning message
* within the set of <code>ResourceBundle</code>s.
*
* @exception IllegalArgumentException if <code>baseName</code>
* is <code>null</code>.
* @exception IllegalArgumentException if <code>keyword</code>
* is <code>null</code>.
* @exception IllegalArgumentException if no appropriate
* <code>ResourceBundle</code> may be located.
* @exception IllegalArgumentException if the named resource is
* not found in the located <code>ResourceBundle</code>.
* @exception IllegalArgumentException if the object retrieved
* from the <code>ResourceBundle</code> is not a
* <code>String</code>.
*/
protected void processWarningOccurred(int imageIndex,
String baseName,
String keyword) {
if (warningListeners == null) {
return;
}
if (baseName == null) {
throw new IllegalArgumentException("baseName == null!");
}
if (keyword == null) {
throw new IllegalArgumentException("keyword == null!");
}
int numListeners = warningListeners.size();
for (int i = 0; i < numListeners; i++) {
IIOWriteWarningListener listener =
(IIOWriteWarningListener)warningListeners.get(i);
Locale locale = (Locale)warningLocales.get(i);
if (locale == null) {
locale = Locale.getDefault();
}
/**
* If an applet supplies an implementation of ImageWriter and
* resource bundles, then the resource bundle will need to be
* accessed via the applet class loader. So first try the context
* class loader to locate the resource bundle.
* If that throws MissingResourceException, then try the
* system class loader.
*/
ClassLoader loader = (ClassLoader)
java.security.AccessController.doPrivileged(
new java.security.PrivilegedAction() {
public Object run() {
return Thread.currentThread().getContextClassLoader();
}
});
ResourceBundle bundle = null;
try {
bundle = ResourceBundle.getBundle(baseName, locale, loader);
} catch (MissingResourceException mre) {
try {
bundle = ResourceBundle.getBundle(baseName, locale);
} catch (MissingResourceException mre1) {
throw new IllegalArgumentException("Bundle not found!");
}
}
String warning = null;
try {
warning = bundle.getString(keyword);
} catch (ClassCastException cce) {
throw new IllegalArgumentException("Resource is not a String!");
} catch (MissingResourceException mre) {
throw new IllegalArgumentException("Resource is missing!");
}
listener.warningOccurred(this, imageIndex, warning);
}
}
// State management
/**
* Restores the <code>ImageWriter</code> to its initial state.
*
* <p> The default implementation calls
* <code>setOutput(null)</code>, <code>setLocale(null)</code>,
* <code>removeAllIIOWriteWarningListeners()</code>,
* <code>removeAllIIOWriteProgressListeners()</code>, and
* <code>clearAbortRequest</code>.
*/
public void reset() {
setOutput(null);
setLocale(null);
removeAllIIOWriteWarningListeners();
removeAllIIOWriteProgressListeners();
clearAbortRequest();
}
/**
* Allows any resources held by this object to be released. The
* result of calling any other method (other than
* <code>finalize</code>) subsequent to a call to this method
* is undefined.
*
* <p>It is important for applications to call this method when they
* know they will no longer be using this <code>ImageWriter</code>.
* Otherwise, the writer may continue to hold on to resources
* indefinitely.
*
* <p>The default implementation of this method in the superclass does
* nothing. Subclass implementations should ensure that all resources,
* especially native resources, are released.
*/
public void dispose() {
}
}