/* * 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. * * @exception 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}. * * @exception 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}. * * @exception IllegalStateException if the output has not * been set. * @exception UnsupportedOperationException if {@code image} * contains a {@code Raster} and {@code canWriteRasters} * returns {@code false}. * @exception IllegalArgumentException if {@code image} is * {@code null}. * @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)}. * * @param image an {@code IIOImage} object containing an * image, thumbnails, and metadata to be written. * * @exception IllegalStateException if the output has not * been set. * @exception IllegalArgumentException if {@code image} is * {@code null}. * @exception UnsupportedOperationException if {@code image} * contains a {@code Raster} and {@code canWriteRasters} * returns {@code false}. * @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)}. * * @param image a {@code RenderedImage} to be written. * * @exception IllegalStateException if the output has not * been set. * @exception IllegalArgumentException if {@code image} is * {@code null}. * @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} 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}. * * @exception IllegalStateException if the output has not * been set. * @exception UnsupportedOperationException if * {@code canWriteSequence} returns {@code false}. * @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}, 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}. * * @exception IllegalStateException if the output has not * been set, or {@code prepareWriteSequence} has not been called. * @exception UnsupportedOperationException if * {@code canWriteSequence} returns {@code false}. * @exception IllegalArgumentException if {@code image} is * {@code null}. * @exception UnsupportedOperationException if {@code image} * contains a {@code Raster} and {@code canWriteRasters} * returns {@code false}. * @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}. 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}. * * @exception IllegalStateException if the output has not * been set, or {@code prepareWriteSequence} has not been called. * @exception UnsupportedOperationException if * {@code canWriteSequence} returns {@code false}. * @exception 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. * * @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}, 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. * * @exception IllegalStateException if the output has not * been set. * @exception UnsupportedOperationException if the * {@code canReplaceStreamMetadata} returns * {@code false}. modes do not include * @exception 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. * * @exception IllegalStateException if the output has not * been set. * @exception IndexOutOfBoundsException if the writer supports * image metadata replacement in general, but * {@code imageIndex} 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)} 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}. * * @exception IllegalStateException if the output has not been * set. * @exception UnsupportedOperationException if * {@code canReplaceImageMetadata} returns * {@code false}. * @exception IndexOutOfBoundsException if {@code imageIndex} * 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} 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. * * @exception IllegalStateException if the output has not * been set. * @exception IndexOutOfBoundsException if the writer supports * image insertion in general, but {@code imageIndex} 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} 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}. * * @exception IllegalStateException if the output has not * been set. * @exception UnsupportedOperationException if * {@code canInsertImage(imageIndex)} returns {@code false}. * @exception IllegalArgumentException if {@code image} is * {@code null}. * @exception IndexOutOfBoundsException if {@code imageIndex} * is less than -1 or greater than the largest available index. * @exception UnsupportedOperationException if {@code image} * contains a {@code Raster} and {@code canWriteRasters} * returns {@code false}. * @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} 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. * * @exception IllegalStateException if the output has not * been set. * @exception IndexOutOfBoundsException if the writer supports * image removal in general, but {@code imageIndex} 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)} 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. * * @exception IllegalStateException if the output has not * been set. * @exception UnsupportedOperationException if * {@code canRemoveImage(imageIndex)} returns {@code false}. * @exception IndexOutOfBoundsException if {@code imageIndex} * 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} 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. * * @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} * 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}. * * @exception IllegalStateException if the output has not * been set. * @exception UnsupportedOperationException if * {@code canWriteEmpty} returns {@code false}. * @exception IllegalStateException if a previous call to * {@code prepareWriteEmpty} has been made without a * corresponding call to {@code endWriteEmpty}. * @exception IllegalStateException if a previous call to * {@code prepareInsertEmpty} has been made without a * corresponding call to {@code endInsertEmpty}. * @exception IllegalArgumentException if {@code imageType} * is {@code null} or {@code thumbnails} contains * {@code null} references or objects other than * {@code BufferedImage}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}. * * <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}. * * @exception IllegalStateException if the output has not * been set. * @exception UnsupportedOperationException if * {@code canWriteEmpty(imageIndex)} returns * {@code false}. * @exception IllegalStateException if a previous call to * {@code prepareWriteEmpty} without a corresponding call to * {@code endWriteEmpty} has not been made. * @exception IllegalStateException if a previous call to * {@code prepareInsertEmpty} without a corresponding call to * {@code endInsertEmpty} has been made. * @exception IllegalStateException if a call to * {@code prepareReiplacePixels} has been made without a * matching call to {@code endReplacePixels}. * @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} 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. * * @exception IllegalStateException if the output has not been * set. * @exception IndexOutOfBoundsException if the writer supports * empty image insertion in general, but {@code imageIndex} * 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} 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}. * * @exception IllegalStateException if the output has not * been set. * @exception UnsupportedOperationException if * {@code canInsertEmpty(imageIndex)} returns * {@code false}. * @exception IndexOutOfBoundsException if {@code imageIndex} * is less than -1 or greater than the largest available index. * @exception IllegalStateException if a previous call to * {@code prepareInsertEmpty} has been made without a * corresponding call to {@code endInsertEmpty}. * @exception IllegalStateException if a previous call to * {@code prepareWriteEmpty} has been made without a * corresponding call to {@code endWriteEmpty}. * @exception IllegalArgumentException if {@code imageType} * is {@code null} or {@code thumbnails} contains * {@code null} references or objects other than * {@code BufferedImage}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}. * * <p> The default implementation throws an * {@code IllegalStateException} if the output is * {@code null}, and otherwise throws an * {@code UnsupportedOperationException}. * * @exception IllegalStateException if the output has not * been set. * @exception UnsupportedOperationException if * {@code canInsertEmpty(imageIndex)} returns * {@code false}. * @exception IllegalStateException if a previous call to * {@code prepareInsertEmpty} without a corresponding call to * {@code endInsertEmpty} has not been made. * @exception IllegalStateException if a previous call to * {@code prepareWriteEmpty} without a corresponding call to * {@code endWriteEmpty} has been made. * @exception IllegalStateException if a call to * {@code prepareReplacePixels} has been made without a * matching call to {@code endReplacePixels}. * @exception 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. * * @exception IllegalStateException if the output has not been * set. * @exception IndexOutOfBoundsException if the writer supports * pixel replacement in general, but {@code imageIndex} 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} 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. * * @exception IllegalStateException if the output has not * been set. * @exception UnsupportedOperationException if * {@code canReplacePixels(imageIndex)} returns * {@code false}. * @exception IndexOutOfBoundsException if {@code imageIndex} * is less than 0 or greater than the largest available index. * @exception 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). * @exception IllegalArgumentException if {@code region} is * {@code null} 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} 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}. * * @exception IllegalStateException if the output has not * been set. * @exception UnsupportedOperationException if * {@code canReplacePixels(imageIndex)} returns * {@code false}. * @exception IllegalStateException if there is no previous call to * {@code prepareReplacePixels} without a matching call to * {@code endReplacePixels}. * @exception 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> * @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}. 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}. * * @exception IllegalStateException if the output has not * been set. * @exception UnsupportedOperationException if * {@code canReplacePixels(imageIndex)} returns * {@code false}. * @exception IllegalStateException if there is no previous call to * {@code prepareReplacePixels} without a matching call to * {@code endReplacePixels}. * @exception UnsupportedOperationException if * {@code canWriteRasters} returns {@code false}. * @exception 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> * @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}. * * <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}. * * @exception IllegalStateException if the output has not * been set. * @exception UnsupportedOperationException if * {@code canReplacePixels(imageIndex)} returns * {@code false}. * @exception IllegalStateException if there is no previous call * to {@code prepareReplacePixels} without a matching call to * {@code endReplacePixels}. * @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} 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. * * @exception 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. * * @exception IllegalArgumentException if {@code baseName} * is {@code null}. * @exception IllegalArgumentException if {@code keyword} * is {@code null}. * @exception IllegalArgumentException if no appropriate * {@code ResourceBundle} may be located. * @exception IllegalArgumentException if the named resource is * not found in the located {@code ResourceBundle}. * @exception 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() { } }