/*
 * Copyright (c) 1999, 2014, Oracle and/or its affiliates. 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.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package javax.imageio;

import java.awt.Dimension;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import java.awt.image.RenderedImage;
import 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 javax.imageio.event.IIOWriteWarningListener;
import javax.imageio.event.IIOWriteProgressListener;
import javax.imageio.metadata.IIOMetadata;
import javax.imageio.stream.ImageOutputStream;
import 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} objects are normally instantiated by
 * the service provider class for the specific format.  Service
 * provider classes are registered with the {@code IIORegistry},
 * which uses them for format recognition and presentation of
 * available format readers and writers.
 *
 * @see ImageReader
 * @see ImageWriteParam
 * @see javax.imageio.spi.IIORegistry
 * @see javax.imageio.spi.ImageWriterSpi
 *
 */
public abstract class ImageWriter implements ImageTranscoder {

    /**
     * The {@code ImageWriterSpi} that instantiated this object,
     * or {@code null} if its identity is not known or none
     * exists.  By default it is initialized to {@code null}.
     */
    protected ImageWriterSpi originatingProvider = null;

    /**
     * The {@code ImageOutputStream} or other {@code Object}
     * set by {@code setOutput} and retrieved by
     * {@code getOutput}.  By default it is initialized to
     * {@code null}.
     */
    protected Object output = null;

    /**
     * An array of {@code Locale}s that may be used to localize
     * warning messages and compression setting values, or
     * {@code null} if localization is not supported.  By default
     * it is initialized to {@code null}.
     */
    protected Locale[] availableLocales = null;

    /**
     * The current {@code Locale} to be used for localization, or
     * {@code null} if none has been set.  By default it is
     * initialized to {@code null}.
     */
    protected Locale locale = null;

    /**
     * A {@code List} of currently registered
     * {@code IIOWriteWarningListener}s, initialized by default to
     * {@code null}, which is synonymous with an empty
     * {@code List}.
     */
    protected List<IIOWriteWarningListener> warningListeners = null;

    /**
     * A {@code List} of {@code Locale}s, one for each
     * element of {@code warningListeners}, initialized by default
     * {@code null}, which is synonymous with an empty
     * {@code List}.
     */
    protected List<Locale> warningLocales = null;

    /**
     * A {@code List} of currently registered
     * {@code IIOWriteProgressListener}s, initialized by default
     * {@code null}, which is synonymous with an empty
     * {@code List}.
     */
    protected List<IIOWriteProgressListener> progressListeners = null;

    /**
     * If {@code true}, the current write operation should be
     * aborted.
     */
    private boolean abortFlag = false;

    /**
     * Constructs an {@code ImageWriter} and sets its
     * {@code originatingProvider} instance variable to the
     * supplied value.
     *
     * <p> Subclasses that make use of extensions should provide a
     * constructor with signature {@code (ImageWriterSpi, Object)}
     * in order to retrieve the extension object.  If
     * the extension object is unsuitable, an
     * {@code IllegalArgumentException} should be thrown.
     *
     * @param originatingProvider the {@code ImageWriterSpi} that
     * is constructing this object, or {@code null}.
     */
    protected ImageWriter(ImageWriterSpi originatingProvider) {
        this.originatingProvider = originatingProvider;
    }

    /**
     * Returns the {@code ImageWriterSpi} object that created
     * this {@code ImageWriter}, or {@code null} if this
     * object was not created through the {@code IIORegistry}.
     *
     * <p> The default implementation returns the value of the
     * {@code originatingProvider} instance variable.
     *
     * @return an {@code ImageWriterSpi}, or {@code null}.
     *
     * @see ImageWriterSpi
     */
    public ImageWriterSpi getOriginatingProvider() {
        return originatingProvider;
    }

    /**
     * Sets the destination to the given
     * {@code ImageOutputStream} or other {@code Object}.
     * 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} is
     * {@code null}, any currently set output will be removed.
     *
     * <p> If {@code output} is an
     * {@code ImageOutputStream}, calls to the
     * {@code write}, {@code writeToSequence}, and
     * {@code prepareWriteEmpty}/{@code endWriteEmpty}
     * methods will preserve the existing contents of the stream.
     * Other write methods, such as {@code writeInsert},
     * {@code replaceStreamMetadata},
     * {@code replaceImageMetadata}, {@code replacePixels},
     * {@code prepareInsertEmpty}/{@code endInsertEmpty},
     * and {@code endWriteSequence}, 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} other than an
     * {@code ImageOutputStream} 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} method; most writers
     * will return a single-element array containing only
     * {@code ImageOutputStream.class} to indicate that they
     * accept only an {@code ImageOutputStream}.
     *
     * <p> The default implementation sets the {@code output}
     * instance variable to the value of {@code output} after
     * checking {@code output} against the set of classes
     * advertised by the originating provider, if there is one.
     *
     * @param output the {@code ImageOutputStream} or other
     * {@code Object} to use for future writing.
     *
     * @throws IllegalArgumentException if {@code output} is
     * not an instance of one of the classes returned by the
     * originating service provider's {@code getOutputTypes}
     * 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} or other
     * {@code Object} set by the most recent call to the
     * {@code setOutput} method.  If no destination has been
     * set, {@code null} is returned.
     *
     * <p> The default implementation returns the value of the
     * {@code output} instance variable.
     *
     * @return the {@code Object} that was specified using
     * {@code setOutput}, or {@code null}.
     *
     * @see #setOutput
     */
    public Object getOutput() {
        return output;
    }

    // Localization

    /**
     * Returns an array of {@code Locale}s that may be used to
     * localize warning listeners and compression settings.  A return
     * value of {@code null} indicates that localization is not
     * supported.
     *
     * <p> The default implementation returns a clone of the
     * {@code availableLocales} instance variable if it is
     * non-{@code null}, or else returns {@code null}.
     *
     * @return an array of {@code Locale}s that may be used as
     * arguments to {@code setLocale}, or {@code null}.
     */
    public Locale[] getAvailableLocales() {
        return (availableLocales == null) ?
            null : availableLocales.clone();
    }

    /**
     * Sets the current {@code Locale} of this
     * {@code ImageWriter} to the given value.  A value of
     * {@code null} removes any previous setting, and indicates
     * that the writer should localize as it sees fit.
     *
     * <p> The default implementation checks {@code locale}
     * against the values returned by
     * {@code getAvailableLocales}, and sets the
     * {@code locale} instance variable if it is found.  If
     * {@code locale} is {@code null}, the instance variable
     * is set to {@code null} without any checking.
     *
     * @param locale the desired {@code Locale}, or
     * {@code null}.
     *
     * @throws IllegalArgumentException if {@code locale} is
     * non-{@code null} but is not one of the values returned by
     * {@code getAvailableLocales}.
     *
     * @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}, or
     * {@code null} if none has been set.
     *
     * <p> The default implementation returns the value of the
     * {@code locale} instance variable.
     *
     * @return the current {@code Locale}, or {@code null}.
     *
     * @see #setLocale
     */
    public Locale getLocale() {
        return locale;
    }

    // Write params

    /**
     * Returns a new {@code ImageWriteParam} object of the
     * appropriate type for this file format containing default
     * values, that is, those values that would be used
     * if no {@code ImageWriteParam} 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} object that does not allow tiling,
     * progressive encoding, or compression, and that will be
     * localized for the current {@code Locale} (<i>i.e.</i>,
     * what you would get by calling
     * {@code new ImageWriteParam(getLocale())}.
     *
     * <p> Individual plug-ins may return an instance of
     * {@code ImageWriteParam} with additional optional features
     * enabled, or they may return an instance of a plug-in specific
     * subclass of {@code ImageWriteParam}.
     *
     * @return a new {@code ImageWriteParam} object containing
     * default values.
     */
    public ImageWriteParam getDefaultWriteParam() {
        return new ImageWriteParam(getLocale());
    }

    // Metadata

    /**
     * Returns an {@code IIOMetadata} 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} method, an
     * {@code IIOMetadataController} object, or via plug-in
     * specific interfaces, and the resulting data supplied to one of
     * the {@code write} methods that take a stream metadata
     * parameter.
     *
     * <p> An optional {@code ImageWriteParam} may be supplied
     * for cases where it may affect the structure of the stream
     * metadata.
     *
     * <p> If the supplied {@code ImageWriteParam} 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}.
     *
     * @param param an {@code ImageWriteParam} that will be used to
     * encode the image, or {@code null}.
     *
     * @return an {@code IIOMetadata} object.
     */
    public abstract IIOMetadata
        getDefaultStreamMetadata(ImageWriteParam param);

    /**
     * Returns an {@code IIOMetadata} 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}
     * method, an {@code IIOMetadataController} object, or via
     * plug-in specific interfaces, and the resulting data supplied to
     * one of the {@code write} methods that take a stream
     * metadata parameter.
     *
     * <p> An optional {@code ImageWriteParam} may be supplied
     * for cases where it may affect the structure of the image
     * metadata.
     *
     * <p> If the supplied {@code ImageWriteParam} 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} indicating the
     * format of the image to be written later.
     * @param param an {@code ImageWriteParam} that will be used to
     * encode the image, or {@code null}.
     *
     * @return an {@code IIOMetadata} 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 supported 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} indicates that
     * insufficient information is available.
     *
     * <p> An {@code ImageWriteParam} may optionally be supplied
     * for cases where it may affect thumbnail handling.
     *
     * <p> If the supplied {@code ImageWriteParam} 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} indicating
     * the type of image to be written, or {@code null}.
     * @param param the {@code ImageWriteParam} that will be used for
     * writing, or {@code null}.
     * @param streamMetadata an {@code IIOMetadata} object that will
     * be used for writing, or {@code null}.
     * @param imageMetadata an {@code IIOMetadata} object that will
     * be used for writing, or {@code null}.
     *
     * @return the number of thumbnails that may be written given the
     * supplied parameters, or {@code -1} if insufficient
     * information is available.
     */
    public int getNumThumbnailsSupported(ImageTypeSpecifier imageType,
                                         ImageWriteParam param,
                                         IIOMetadata streamMetadata,
                                         IIOMetadata imageMetadata) {
        return 0;
    }

    /**
     * Returns an array of {@code Dimension}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}
     * indicates that the size is arbitrary or unknown.
     *
     * <p> An {@code ImageWriteParam} may optionally be supplied
     * for cases where it may affect thumbnail handling.
     *
     * <p> If the supplied {@code ImageWriteParam} 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}.
     *
     * @param imageType an {@code ImageTypeSpecifier} indicating the
     * type of image to be written, or {@code null}.
     * @param param the {@code ImageWriteParam} that will be used for
     * writing, or {@code null}.
     * @param streamMetadata an {@code IIOMetadata} object that will
     * be used for writing, or {@code null}.
     * @param imageMetadata an {@code IIOMetadata} object that will
     * be used for writing, or {@code null}.
     *
     * @return an array of {@code Dimension}s with an even length
     * of at least two, or {@code null}.
     */
    public Dimension[] getPreferredThumbnailSizes(ImageTypeSpecifier imageType,
                                                  ImageWriteParam param,
                                                  IIOMetadata streamMetadata,
                                                  IIOMetadata imageMetadata) {
        return null;
    }

    /**
     * Returns {@code true} if the methods that take an
     * {@code IIOImage} parameter are capable of dealing with a
     * {@code Raster} (as opposed to {@code RenderedImage})
     * source image.  If this method returns {@code false}, then
     * those methods will throw an
     * {@code UnsupportedOperationException} if supplied with an
     * {@code IIOImage} containing a {@code Raster}.
     *
     * <p> The default implementation returns {@code false}.
     *
     * @return {@code true} if {@code Raster} 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}, 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} method.
     *
     * <p> Stream metadata may optionally be supplied; if it is
     * {@code null}, default stream metadata will be used.
     *
     * <p> If {@code canWriteRasters} returns {@code true},
     * the {@code IIOImage} may contain a {@code Raster}
     * source.  Otherwise, it must contain a
     * {@code RenderedImage} 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} may
     * optionally be supplied to control the writing process.  If
     * {@code param} is {@code null}, a default write param
     * will be used.
     *
     * <p> If the supplied {@code ImageWriteParam} 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} object representing
     * stream metadata, or {@code null} to use default values.
     * @param image an {@code IIOImage} object containing an
     * image, thumbnails, and metadata to be written.
     * @param param an {@code ImageWriteParam}, or
     * {@code null} to use a default
     * {@code ImageWriteParam}.
     *
     * @throws IllegalStateException if the output has not
     * been set.
     * @throws UnsupportedOperationException if {@code image}
     * contains a {@code Raster} and {@code canWriteRasters}
     * returns {@code false}.
     * @throws IllegalArgumentException if {@code image} is
     * {@code null}.
     * @throws 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)}.
     *
     * @param image an {@code IIOImage} object containing an
     * image, thumbnails, and metadata to be written.
     *
     * @throws IllegalStateException if the output has not
     * been set.
     * @throws IllegalArgumentException if {@code image} is
     * {@code null}.
     * @throws UnsupportedOperationException if {@code image}
     * contains a {@code Raster} and {@code canWriteRasters}
     * returns {@code false}.
     * @throws 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)}.
     *
     * @param image a {@code RenderedImage} to be written.
     *
     * @throws IllegalStateException if the output has not
     * been set.
     * @throws IllegalArgumentException if {@code image} is
     * {@code null}.
     * @throws 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} 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} returns {@code false},
     * {@code writeToSequence} and {@code endWriteSequence}
     * will throw an {@code UnsupportedOperationException}.
     *
     * <p> The default implementation returns {@code false}.
     *
     * @return {@code true} if images may be appended sequentially.
     */
    public boolean canWriteSequence() {
        return false;
    }

    /**
     * Prepares a stream to accept a series of subsequent
     * {@code writeToSequence} 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},
     * default stream metadata is used.
     *
     * <p> If the output is an {@code ImageOutputStream}, 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} 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} returns {@code false},
     * this method will throw an
     * {@code UnsupportedOperationException}.
     *
     * <p> The output must have been set beforehand using either
     * the {@code setOutput} method.
     *
     * <p> The default implementation throws an
     * {@code IllegalStateException} if the output is
     * {@code null}, and otherwise throws an
     * {@code UnsupportedOperationException}.
     *
     * @param streamMetadata A stream metadata object, or {@code null}.
     *
     * @throws IllegalStateException if the output has not
     * been set.
     * @throws UnsupportedOperationException if
     * {@code canWriteSequence} returns {@code false}.
     * @throws 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}, 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} is called (<i>e.g.</i> TIFF).
     *
     * <p> If {@code canWriteSequence} returns {@code false},
     * this method will throw an
     * {@code UnsupportedOperationException}.
     *
     * <p> The output must have been set beforehand using
     * the {@code setOutput} method.
     *
     * <p> {@code prepareWriteSequence} must have been called
     * beforehand, or an {@code IllegalStateException} is thrown.
     *
     * <p> If {@code canWriteRasters} returns {@code true},
     * the {@code IIOImage} may contain a {@code Raster}
     * source.  Otherwise, it must contain a
     * {@code RenderedImage} 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} may optionally be supplied
     * to control the writing process.  If {@code param} is
     * {@code null}, a default write param will be used.
     *
     * <p> If the supplied {@code ImageWriteParam} 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} if the output is
     * {@code null}, and otherwise throws an
     * {@code UnsupportedOperationException}.
     *
     * @param image an {@code IIOImage} object containing an
     * image, thumbnails, and metadata to be written.
     * @param param an {@code ImageWriteParam}, or
     * {@code null} to use a default
     * {@code ImageWriteParam}.
     *
     * @throws IllegalStateException if the output has not
     * been set, or {@code prepareWriteSequence} has not been called.
     * @throws UnsupportedOperationException if
     * {@code canWriteSequence} returns {@code false}.
     * @throws IllegalArgumentException if {@code image} is
     * {@code null}.
     * @throws UnsupportedOperationException if {@code image}
     * contains a {@code Raster} and {@code canWriteRasters}
     * returns {@code false}.
     * @throws 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}.  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}, data through the stream metadata
     * at the end of the sequence are flushed and need not be readable
     * or writable.
     *
     * <p> If {@code canWriteSequence} returns {@code false},
     * this method will throw an
     * {@code UnsupportedOperationException}.
     *
     * <p> The default implementation throws an
     * {@code IllegalStateException} if the output is
     * {@code null}, and otherwise throws an
     * {@code UnsupportedOperationException}.
     *
     * @throws IllegalStateException if the output has not
     * been set, or {@code prepareWriteSequence} has not been called.
     * @throws UnsupportedOperationException if
     * {@code canWriteSequence} returns {@code false}.
     * @throws IOException if an error occurs during writing.
     */
    public void endWriteSequence() throws IOException {
        unsupported();
    }

    // Metadata replacement

    /**
     * Returns {@code true} if it is possible to replace the
     * stream metadata already present in the output.
     *
     * <p> The default implementation throws an
     * {@code IllegalStateException} if the output is
     * {@code null}, and otherwise returns {@code false}.
     *
     * @return {@code true} if replacement of stream metadata is
     * allowed.
     *
     * @throws IllegalStateException if the output has not
     * been set.
     * @throws 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}, 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} returns
     * {@code false}, an
     * {@code UnsupportedOperationException} will be thrown.
     *
     * <p> The default implementation throws an
     * {@code IllegalStateException} if the output is
     * {@code null}, and otherwise throws an
     * {@code UnsupportedOperationException}.
     *
     * @param streamMetadata an {@code IIOMetadata} object representing
     * stream metadata, or {@code null} to use default values.
     *
     * @throws IllegalStateException if the output has not
     * been set.
     * @throws UnsupportedOperationException if the
     * {@code canReplaceStreamMetadata} returns
     * {@code false}.  modes do not include
     * @throws IOException if an error occurs during writing.
     */
    public void replaceStreamMetadata(IIOMetadata streamMetadata)
        throws IOException {
        unsupported();
    }

    /**
     * Returns {@code true} if it is possible to replace the
     * image metadata associated with an existing image with index
     * {@code imageIndex}.  If this method returns
     * {@code false}, a call to
     * {@code replaceImageMetadata(imageIndex)} will throw an
     * {@code UnsupportedOperationException}.
     *
     * <p> A writer that does not support any image metadata
     * replacement may return {@code false} without performing
     * bounds checking on the index.
     *
     * <p> The default implementation throws an
     * {@code IllegalStateException} if the output is
     * {@code null}, and otherwise returns {@code false}
     * without checking the value of {@code imageIndex}.
     *
     * @param imageIndex the index of the image whose metadata is to
     * be replaced.
     *
     * @return {@code true} if the image metadata of the given
     * image can be replaced.
     *
     * @throws IllegalStateException if the output has not
     * been set.
     * @throws IndexOutOfBoundsException if the writer supports
     * image metadata replacement in general, but
     * {@code imageIndex} is less than 0 or greater than the
     * largest available index.
     * @throws 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)} returns
     * {@code false}, an
     * {@code UnsupportedOperationException} will be thrown.
     *
     * <p> The default implementation throws an
     * {@code IllegalStateException} if the output is
     * {@code null}, and otherwise throws an
     * {@code UnsupportedOperationException}.
     *
     * @param imageIndex the index of the image whose metadata is to
     * be replaced.
     * @param imageMetadata an {@code IIOMetadata} object
     * representing image metadata, or {@code null}.
     *
     * @throws IllegalStateException if the output has not been
     * set.
     * @throws UnsupportedOperationException if
     * {@code canReplaceImageMetadata} returns
     * {@code false}.
     * @throws IndexOutOfBoundsException if {@code imageIndex}
     * is less than 0 or greater than the largest available index.
     * @throws IOException if an error occurs during writing.
     */
    public void replaceImageMetadata(int imageIndex,
                                     IIOMetadata imageMetadata)
        throws IOException {
        unsupported();
    }

    // Image insertion

    /**
     * Returns {@code true} 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} of {@code -1} 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} without performing bounds checking on
     * the index.
     *
     * <p> The default implementation throws an
     * {@code IllegalStateException} if the output is
     * {@code null}, and otherwise returns {@code false}
     * without checking the value of {@code imageIndex}.
     *
     * @param imageIndex the index at which the image is to be
     * inserted.
     *
     * @return {@code true} if an image may be inserted at the
     * given index.
     *
     * @throws IllegalStateException if the output has not
     * been set.
     * @throws IndexOutOfBoundsException if the writer supports
     * image insertion in general, but {@code imageIndex} is less
     * than -1 or greater than the largest available index.
     * @throws 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} are
     * preserved, and their indices are each increased by 1.  A value
     * for {@code imageIndex} 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},
     * the entirety of the stream must be both readable and writeable.
     *
     * <p> If {@code canInsertImage(imageIndex)} returns
     * {@code false}, an
     * {@code UnsupportedOperationException} will be thrown.
     *
     * <p> An {@code ImageWriteParam} may optionally be supplied
     * to control the writing process.  If {@code param} is
     * {@code null}, a default write param will be used.
     *
     * <p> If the supplied {@code ImageWriteParam} 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} if the output is
     * {@code null}, and otherwise throws an
     * {@code UnsupportedOperationException}.
     *
     * @param imageIndex the index at which to write the image.
     * @param image an {@code IIOImage} object containing an
     * image, thumbnails, and metadata to be written.
     * @param param an {@code ImageWriteParam}, or
     * {@code null} to use a default
     * {@code ImageWriteParam}.
     *
     * @throws IllegalStateException if the output has not
     * been set.
     * @throws UnsupportedOperationException if
     * {@code canInsertImage(imageIndex)} returns {@code false}.
     * @throws IllegalArgumentException if {@code image} is
     * {@code null}.
     * @throws IndexOutOfBoundsException if {@code imageIndex}
     * is less than -1 or greater than the largest available index.
     * @throws UnsupportedOperationException if {@code image}
     * contains a {@code Raster} and {@code canWriteRasters}
     * returns {@code false}.
     * @throws IOException if an error occurs during writing.
     */
    public void writeInsert(int imageIndex,
                            IIOImage image,
                            ImageWriteParam param) throws IOException {
        unsupported();
    }

    // Image removal

    /**
     * Returns {@code true} 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} without performing bounds checking on
     * the index.
     *
     * <p> The default implementation throws an
     * {@code IllegalStateException} if the output is
     * {@code null}, and otherwise returns {@code false}
     * without checking the value of {@code imageIndex}.
     *
     * @param imageIndex the index of the image to be removed.
     *
     * @return {@code true} if it is possible to remove the given
     * image.
     *
     * @throws IllegalStateException if the output has not
     * been set.
     * @throws IndexOutOfBoundsException if the writer supports
     * image removal in general, but {@code imageIndex} is less
     * than 0 or greater than the largest available index.
     * @throws 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)} returns false,
     * an {@code UnsupportedOperationException} 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} if the output is
     * {@code null}, and otherwise throws an
     * {@code UnsupportedOperationException}.
     *
     * @param imageIndex the index of the image to be removed.
     *
     * @throws IllegalStateException if the output has not
     * been set.
     * @throws UnsupportedOperationException if
     * {@code canRemoveImage(imageIndex)} returns {@code false}.
     * @throws IndexOutOfBoundsException if {@code imageIndex}
     * is less than 0 or greater than the largest available index.
     * @throws IOException if an I/O error occurs during the
     * removal.
     */
    public void removeImage(int imageIndex) throws IOException {
        unsupported();
    }

    // Empty images

    /**
     * Returns {@code true} 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} methods.  If the output
     * is an {@code ImageOutputStream}, 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} if the output is
     * {@code null}, and otherwise returns {@code false}.
     *
     * @return {@code true} if the writing of complete image
     * stream with contents to be defined later is supported.
     *
     * @throws IllegalStateException if the output has not been
     * set.
     * @throws 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}
     * methods.  If the output is an {@code ImageOutputStream},
     * 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} occurs.  Calls to
     * {@code prepareReplacePixels}, {@code replacePixels},
     * and {@code endReplacePixels} may occur between calls to
     * {@code prepareWriteEmpty} and {@code endWriteEmpty}.
     * However, calls to {@code prepareWriteEmpty} cannot be
     * nested, and calls to {@code prepareWriteEmpty} and
     * {@code prepareInsertEmpty} may not be interspersed.
     *
     * <p> If {@code canWriteEmpty} returns {@code false},
     * an {@code UnsupportedOperationException} will be thrown.
     *
     * <p> An {@code ImageWriteParam} may optionally be supplied
     * to control the writing process.  If {@code param} is
     * {@code null}, a default write param will be used.
     *
     * <p> If the supplied {@code ImageWriteParam} 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} if the output is
     * {@code null}, and otherwise throws an
     * {@code UnsupportedOperationException}.
     *
     * @param streamMetadata an {@code IIOMetadata} object representing
     * stream metadata, or {@code null} to use default values.
     * @param imageType an {@code ImageTypeSpecifier} 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} object
     * representing image metadata, or {@code null}.
     * @param thumbnails a {@code List} of
     * {@code BufferedImage} thumbnails for this image, or
     * {@code null}.
     * @param param an {@code ImageWriteParam}, or
     * {@code null} to use a default
     * {@code ImageWriteParam}.
     *
     * @throws IllegalStateException if the output has not
     * been set.
     * @throws UnsupportedOperationException if
     * {@code canWriteEmpty} returns {@code false}.
     * @throws IllegalStateException if a previous call to
     * {@code prepareWriteEmpty} has been made without a
     * corresponding call to {@code endWriteEmpty}.
     * @throws IllegalStateException if a previous call to
     * {@code prepareInsertEmpty} has been made without a
     * corresponding call to {@code endInsertEmpty}.
     * @throws IllegalArgumentException if {@code imageType}
     * is {@code null} or {@code thumbnails} contains
     * {@code null} references or objects other than
     * {@code BufferedImage}s.
     * @throws IllegalArgumentException if width or height are less
     * than 1.
     * @throws 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}.
     *
     * <p> If {@code canWriteEmpty()} returns {@code false},
     * an {@code UnsupportedOperationException} will be thrown.
     *
     * <p> The default implementation throws an
     * {@code IllegalStateException} if the output is
     * {@code null}, and otherwise throws an
     * {@code UnsupportedOperationException}.
     *
     * @throws IllegalStateException if the output has not
     * been set.
     * @throws UnsupportedOperationException if
     * {@code canWriteEmpty(imageIndex)} returns
     * {@code false}.
     * @throws IllegalStateException if a previous call to
     * {@code prepareWriteEmpty} without a corresponding call to
     * {@code endWriteEmpty} has not been made.
     * @throws IllegalStateException if a previous call to
     * {@code prepareInsertEmpty} without a corresponding call to
     * {@code endInsertEmpty} has been made.
     * @throws IllegalStateException if a call to
     * {@code prepareReiplacePixels} has been made without a
     * matching call to {@code endReplacePixels}.
     * @throws 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} 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} 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} of {@code -1} 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} without performing bounds
     * checking on the index.
     *
     * <p> The default implementation throws an
     * {@code IllegalStateException} if the output is
     * {@code null}, and otherwise returns {@code false}
     * without checking the value of {@code imageIndex}.
     *
     * @param imageIndex the index at which the image is to be
     * inserted.
     *
     * @return {@code true} if an empty image may be inserted at
     * the given index.
     *
     * @throws IllegalStateException if the output has not been
     * set.
     * @throws IndexOutOfBoundsException if the writer supports
     * empty image insertion in general, but {@code imageIndex}
     * is less than -1 or greater than the largest available index.
     * @throws 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} are preserved, and their
     * indices are each increased by 1.  A value for
     * {@code imageIndex} 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},
     * the entirety of the stream must be both readable and writeable.
     *
     * <p> The image contents may be
     * supplied later using the {@code replacePixels} method.
     * The insertion is not complete until a call to
     * {@code endInsertEmpty} occurs.  Calls to
     * {@code prepareReplacePixels}, {@code replacePixels},
     * and {@code endReplacePixels} may occur between calls to
     * {@code prepareInsertEmpty} and
     * {@code endInsertEmpty}.  However, calls to
     * {@code prepareInsertEmpty} cannot be nested, and calls to
     * {@code prepareWriteEmpty} and
     * {@code prepareInsertEmpty} may not be interspersed.
     *
     * <p> If {@code canInsertEmpty(imageIndex)} returns
     * {@code false}, an
     * {@code UnsupportedOperationException} will be thrown.
     *
     * <p> An {@code ImageWriteParam} may optionally be supplied
     * to control the writing process.  If {@code param} is
     * {@code null}, a default write param will be used.
     *
     * <p> If the supplied {@code ImageWriteParam} 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} if the output is
     * {@code null}, and otherwise throws an
     * {@code UnsupportedOperationException}.
     *
     * @param imageIndex the index at which to write the image.
     * @param imageType an {@code ImageTypeSpecifier} 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} object
     * representing image metadata, or {@code null}.
     * @param thumbnails a {@code List} of
     * {@code BufferedImage} thumbnails for this image, or
     * {@code null}.
     * @param param an {@code ImageWriteParam}, or
     * {@code null} to use a default
     * {@code ImageWriteParam}.
     *
     * @throws IllegalStateException if the output has not
     * been set.
     * @throws UnsupportedOperationException if
     * {@code canInsertEmpty(imageIndex)} returns
     * {@code false}.
     * @throws IndexOutOfBoundsException if {@code imageIndex}
     * is less than -1 or greater than the largest available index.
     * @throws IllegalStateException if a previous call to
     * {@code prepareInsertEmpty} has been made without a
     * corresponding call to {@code endInsertEmpty}.
     * @throws IllegalStateException if a previous call to
     * {@code prepareWriteEmpty} has been made without a
     * corresponding call to {@code endWriteEmpty}.
     * @throws IllegalArgumentException if {@code imageType}
     * is {@code null} or {@code thumbnails} contains
     * {@code null} references or objects other than
     * {@code BufferedImage}s.
     * @throws IllegalArgumentException if width or height are less
     * than 1.
     * @throws 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}.
     *
     * <p> The default implementation throws an
     * {@code IllegalStateException} if the output is
     * {@code null}, and otherwise throws an
     * {@code UnsupportedOperationException}.
     *
     * @throws IllegalStateException if the output has not
     * been set.
     * @throws UnsupportedOperationException if
     * {@code canInsertEmpty(imageIndex)} returns
     * {@code false}.
     * @throws IllegalStateException if a previous call to
     * {@code prepareInsertEmpty} without a corresponding call to
     * {@code endInsertEmpty} has not been made.
     * @throws IllegalStateException if a previous call to
     * {@code prepareWriteEmpty} without a corresponding call to
     * {@code endWriteEmpty} has been made.
     * @throws IllegalStateException if a call to
     * {@code prepareReplacePixels} has been made without a
     * matching call to {@code endReplacePixels}.
     * @throws IOException if an I/O error occurs during writing.
     */
    public void endInsertEmpty() throws IOException {
        unsupported();
    }

    // Pixel replacement

    /**
     * Returns {@code true} if the writer allows pixels of the
     * given image to be replaced using the {@code replacePixels}
     * methods.
     *
     * <p> A writer that does not support any pixel replacement may
     * return {@code false} without performing bounds checking on
     * the index.
     *
     * <p> The default implementation throws an
     * {@code IllegalStateException} if the output is
     * {@code null}, and otherwise returns {@code false}
     * without checking the value of {@code imageIndex}.
     *
     * @param imageIndex the index of the image whose pixels are to be
     * replaced.
     *
     * @return {@code true} if the pixels of the given
     * image can be replaced.
     *
     * @throws IllegalStateException if the output has not been
     * set.
     * @throws IndexOutOfBoundsException if the writer supports
     * pixel replacement in general, but {@code imageIndex} is
     * less than 0 or greater than the largest available index.
     * @throws 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} methods.  The affected pixel area
     * will be clipped against the supplied
     *
     * <p> If {@code canReplacePixels} returns
     * {@code false}, and
     * {@code UnsupportedOperationException} will be thrown.
     *
     * <p> The default implementation throws an
     * {@code IllegalStateException} if the output is
     * {@code null}, and otherwise throws an
     * {@code UnsupportedOperationException}.
     *
     * @param imageIndex the index of the image whose pixels are to be
     * replaced.
     * @param region a {@code Rectangle} that will be used to clip
     * future pixel regions.
     *
     * @throws IllegalStateException if the output has not
     * been set.
     * @throws UnsupportedOperationException if
     * {@code canReplacePixels(imageIndex)} returns
     * {@code false}.
     * @throws IndexOutOfBoundsException if {@code imageIndex}
     * is less than 0 or greater than the largest available index.
     * @throws IllegalStateException if there is a previous call to
     * {@code prepareReplacePixels} without a matching call to
     * {@code endReplacePixels} (<i>i.e.</i>, nesting is not
     * allowed).
     * @throws IllegalArgumentException if {@code region} is
     * {@code null} or has a width or height less than 1.
     * @throws 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} argument, and will be clipped to the image
     * boundaries and the region supplied to
     * {@code prepareReplacePixels}.  At least one pixel of the
     * source must not be clipped, or an exception is thrown.
     *
     * <p> An {@code ImageWriteParam} may optionally be supplied
     * to control the writing process.  If {@code param} is
     * {@code null}, a default write param will be used.
     *
     * <p> If the supplied {@code ImageWriteParam} 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}, or else an
     * {@code IllegalStateException} will be thrown.
     *
     * <p> The default implementation throws an
     * {@code IllegalStateException} if the output is
     * {@code null}, and otherwise throws an
     * {@code UnsupportedOperationException}.
     *
     * @param image a {@code RenderedImage} containing source
     * pixels.
     * @param param an {@code ImageWriteParam}, or
     * {@code null} to use a default
     * {@code ImageWriteParam}.
     *
     * @throws IllegalStateException if the output has not
     * been set.
     * @throws UnsupportedOperationException if
     * {@code canReplacePixels(imageIndex)} returns
     * {@code false}.
     * @throws IllegalStateException if there is no previous call to
     * {@code prepareReplacePixels} without a matching call to
     * {@code endReplacePixels}.
     * @throws IllegalArgumentException if any of the following are true:
     * <ul>
     * <li> {@code image} is {@code null}.
     * <li> the intersected region does not contain at least one pixel.
     * <li> the layout of {@code image} does not match, or this
     * writer cannot convert it to, the existing image layout.
     * </ul>
     * @throws 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}.  The image
     * data must match, or be convertible to, the image layout of the
     * existing image.
     *
     * <p> An {@code ImageWriteParam} may optionally be supplied
     * to control the writing process.  If {@code param} is
     * {@code null}, a default write param will be used.
     *
     * <p> The destination region is specified in the
     * {@code param} argument, and will be clipped to the image
     * boundaries and the region supplied to
     * {@code prepareReplacePixels}.  At least one pixel of the
     * source must not be clipped, or an exception is thrown.
     *
     * <p> If the supplied {@code ImageWriteParam} 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}, or else an
     * {@code IllegalStateException} will be thrown.
     *
     * <p> The default implementation throws an
     * {@code IllegalStateException} if the output is
     * {@code null}, and otherwise throws an
     * {@code UnsupportedOperationException}.
     *
     * @param raster a {@code Raster} containing source
     * pixels.
     * @param param an {@code ImageWriteParam}, or
     * {@code null} to use a default
     * {@code ImageWriteParam}.
     *
     * @throws IllegalStateException if the output has not
     * been set.
     * @throws UnsupportedOperationException if
     * {@code canReplacePixels(imageIndex)} returns
     * {@code false}.
     * @throws IllegalStateException if there is no previous call to
     * {@code prepareReplacePixels} without a matching call to
     * {@code endReplacePixels}.
     * @throws UnsupportedOperationException if
     * {@code canWriteRasters} returns {@code false}.
     * @throws IllegalArgumentException if any of the following are true:
     * <ul>
     * <li> {@code raster} is {@code null}.
     * <li> the intersected region does not contain at least one pixel.
     * <li> the layout of {@code raster} does not match, or this
     * writer cannot convert it to, the existing image layout.
     * </ul>
     * @throws 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}.
     *
     * <p> If {@code canReplacePixels} returns
     * {@code false}, and
     * {@code UnsupportedOperationException} will be thrown.
     *
     * <p> The default implementation throws an
     * {@code IllegalStateException} if the output is
     * {@code null}, and otherwise throws an
     * {@code UnsupportedOperationException}.
     *
     * @throws IllegalStateException if the output has not
     * been set.
     * @throws UnsupportedOperationException if
     * {@code canReplacePixels(imageIndex)} returns
     * {@code false}.
     * @throws IllegalStateException if there is no previous call
     * to {@code prepareReplacePixels} without a matching call to
     * {@code endReplacePixels}.
     * @throws 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} at the
     * beginning of each write operation, and poll the value of
     * {@code abortRequested} regularly during the write.
     */
    public synchronized void abort() {
        this.abortFlag = true;
    }

    /**
     * Returns {@code true} if a request to abort the current
     * write operation has been made since the writer was instantiated or
     * {@code clearAbortRequest} was called.
     *
     * @return {@code true} 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} will return
     * {@code false}.
     *
     * @see #abort
     * @see #abortRequested
     */
    protected synchronized void clearAbortRequest() {
        this.abortFlag = false;
    }

    // Listeners

    /**
     * Adds an {@code IIOWriteWarningListener} to the list of
     * registered warning listeners.  If {@code listener} is
     * {@code null}, 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}.  If no {@code Locale} has been set,
     * warning messages may be localized as the writer sees fit.
     *
     * @param listener an {@code IIOWriteWarningListener} 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} from the list
     * of registered warning listeners.  If the listener was not
     * previously registered, or if {@code listener} is
     * {@code null}, no exception will be thrown and no action
     * will be taken.
     *
     * @param listener an {@code IIOWriteWarningListener} 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} objects.
     *
     * <p> The default implementation sets the
     * {@code warningListeners} and {@code warningLocales}
     * instance variables to {@code null}.
     */
    public void removeAllIIOWriteWarningListeners() {
        this.warningListeners = null;
        this.warningLocales = null;
    }

    /**
     * Adds an {@code IIOWriteProgressListener} to the list of
     * registered progress listeners.  If {@code listener} is
     * {@code null}, no exception will be thrown and no action
     * will be taken.
     *
     * @param listener an {@code IIOWriteProgressListener} to be
     * registered.
     *
     * @see #removeIIOWriteProgressListener
     */
    public void
        addIIOWriteProgressListener(IIOWriteProgressListener listener) {
        if (listener == null) {
            return;
        }
        progressListeners = ImageReader.addToList(progressListeners, listener);
    }

    /**
     * Removes an {@code IIOWriteProgressListener} from the list
     * of registered progress listeners.  If the listener was not
     * previously registered, or if {@code listener} is
     * {@code null}, no exception will be thrown and no action
     * will be taken.
     *
     * @param listener an {@code IIOWriteProgressListener} 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} objects.
     *
     * <p> The default implementation sets the
     * {@code progressListeners} instance variable to
     * {@code null}.
     */
    public void removeAllIIOWriteProgressListeners() {
        this.progressListeners = null;
    }

    /**
     * Broadcasts the start of an image write to all registered
     * {@code IIOWriteProgressListener}s by calling their
     * {@code imageStarted} 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 =
                progressListeners.get(i);
            listener.imageStarted(this, imageIndex);
        }
    }

    /**
     * Broadcasts the current percentage of image completion to all
     * registered {@code IIOWriteProgressListener}s by calling
     * their {@code imageProgress} method.  Subclasses may use
     * this method as a convenience.
     *
     * @param percentageDone the current percentage of completion,
     * as a {@code float}.
     */
    protected void processImageProgress(float percentageDone) {
        if (progressListeners == null) {
            return;
        }
        int numListeners = progressListeners.size();
        for (int i = 0; i < numListeners; i++) {
            IIOWriteProgressListener listener =
                progressListeners.get(i);
            listener.imageProgress(this, percentageDone);
        }
    }

    /**
     * Broadcasts the completion of an image write to all registered
     * {@code IIOWriteProgressListener}s by calling their
     * {@code imageComplete} 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 =
                progressListeners.get(i);
            listener.imageComplete(this);
        }
    }

    /**
     * Broadcasts the start of a thumbnail write to all registered
     * {@code IIOWriteProgressListener}s by calling their
     * {@code thumbnailStarted} 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 =
                progressListeners.get(i);
            listener.thumbnailStarted(this, imageIndex, thumbnailIndex);
        }
    }

    /**
     * Broadcasts the current percentage of thumbnail completion to
     * all registered {@code IIOWriteProgressListener}s by calling
     * their {@code thumbnailProgress} method.  Subclasses may
     * use this method as a convenience.
     *
     * @param percentageDone the current percentage of completion,
     * as a {@code float}.
     */
    protected void processThumbnailProgress(float percentageDone) {
        if (progressListeners == null) {
            return;
        }
        int numListeners = progressListeners.size();
        for (int i = 0; i < numListeners; i++) {
            IIOWriteProgressListener listener =
                progressListeners.get(i);
            listener.thumbnailProgress(this, percentageDone);
        }
    }

    /**
     * Broadcasts the completion of a thumbnail write to all registered
     * {@code IIOWriteProgressListener}s by calling their
     * {@code thumbnailComplete} 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 =
                progressListeners.get(i);
            listener.thumbnailComplete(this);
        }
    }

    /**
     * Broadcasts that the write has been aborted to all registered
     * {@code IIOWriteProgressListener}s by calling their
     * {@code writeAborted} 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 =
                progressListeners.get(i);
            listener.writeAborted(this);
        }
    }

    /**
     * Broadcasts a warning message to all registered
     * {@code IIOWriteWarningListener}s by calling their
     * {@code warningOccurred} 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.
     *
     * @throws IllegalArgumentException if {@code warning}
     * is {@code null}.
     */
    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 =
                warningListeners.get(i);

            listener.warningOccurred(this, imageIndex, warning);
        }
    }

    /**
     * Broadcasts a localized warning message to all registered
     * {@code IIOWriteWarningListener}s by calling their
     * {@code warningOccurred} method with a string taken
     * from a {@code ResourceBundle}.  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}s containing localized warning
     * messages.
     * @param keyword the keyword used to index the warning message
     * within the set of {@code ResourceBundle}s.
     *
     * @throws IllegalArgumentException if {@code baseName}
     * is {@code null}.
     * @throws IllegalArgumentException if {@code keyword}
     * is {@code null}.
     * @throws IllegalArgumentException if no appropriate
     * {@code ResourceBundle} may be located.
     * @throws IllegalArgumentException if the named resource is
     * not found in the located {@code ResourceBundle}.
     * @throws IllegalArgumentException if the object retrieved
     * from the {@code ResourceBundle} is not a
     * {@code String}.
     */
    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 =
                warningListeners.get(i);
            Locale locale = warningLocales.get(i);
            if (locale == null) {
                locale = Locale.getDefault();
            }

            /*
             * Only the plugin knows the messages that are provided, so we
             * can always locate the resource bundles from the same loader
             * as that for the plugin code itself.
             */
            ResourceBundle bundle = null;
            try {
                bundle = ResourceBundle.getBundle(baseName, locale, this.getClass().getModule());
            } catch (MissingResourceException mre) {
                throw new IllegalArgumentException("Bundle not found!", mre);
            }

            String warning = null;
            try {
                warning = bundle.getString(keyword);
            } catch (ClassCastException cce) {
                throw new IllegalArgumentException("Resource is not a String!", cce);
            } catch (MissingResourceException mre) {
                throw new IllegalArgumentException("Resource is missing!", mre);
            }

            listener.warningOccurred(this, imageIndex, warning);
        }
    }

    // State management

    /**
     * Restores the {@code ImageWriter} to its initial state.
     *
     * <p> The default implementation calls
     * {@code setOutput(null)}, {@code setLocale(null)},
     * {@code removeAllIIOWriteWarningListeners()},
     * {@code removeAllIIOWriteProgressListeners()}, and
     * {@code clearAbortRequest}.
     */
    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}) 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}.
     * 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() {
    }
}
