Home » openjdk-7 » javax » imageio » [javadoc | source]

    1   /*
    2    * Copyright (c) 1999, 2006, Oracle and/or its affiliates. All rights reserved.
    3    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    4    *
    5    * This code is free software; you can redistribute it and/or modify it
    6    * under the terms of the GNU General Public License version 2 only, as
    7    * published by the Free Software Foundation.  Oracle designates this
    8    * particular file as subject to the "Classpath" exception as provided
    9    * by Oracle in the LICENSE file that accompanied this code.
   10    *
   11    * This code is distributed in the hope that it will be useful, but WITHOUT
   12    * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   13    * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   14    * version 2 for more details (a copy is included in the LICENSE file that
   15    * accompanied this code).
   16    *
   17    * You should have received a copy of the GNU General Public License version
   18    * 2 along with this work; if not, write to the Free Software Foundation,
   19    * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   20    *
   21    * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   22    * or visit www.oracle.com if you need additional information or have any
   23    * questions.
   24    */
   25   
   26   package javax.imageio;
   27   
   28   import java.awt.Dimension;
   29   import java.awt.Rectangle;
   30   import java.awt.image.BufferedImage;
   31   import java.awt.image.RenderedImage;
   32   import java.awt.image.Raster;
   33   import java.io.IOException;
   34   import java.util.ArrayList;
   35   import java.util.List;
   36   import java.util.Locale;
   37   import java.util.MissingResourceException;
   38   import java.util.ResourceBundle;
   39   import javax.imageio.event.IIOWriteWarningListener;
   40   import javax.imageio.event.IIOWriteProgressListener;
   41   import javax.imageio.metadata.IIOMetadata;
   42   import javax.imageio.stream.ImageOutputStream;
   43   import javax.imageio.spi.ImageWriterSpi;
   44   
   45   /**
   46    * An abstract superclass for encoding and writing images.  This class
   47    * must be subclassed by classes that write out images in the context
   48    * of the Java Image I/O framework.
   49    *
   50    * <p> <code>ImageWriter</code> objects are normally instantiated by
   51    * the service provider class for the specific format.  Service
   52    * provider classes are registered with the <code>IIORegistry</code>,
   53    * which uses them for format recognition and presentation of
   54    * available format readers and writers.
   55    *
   56    * <p>
   57    *
   58    * @see ImageReader
   59    * @see ImageWriteParam
   60    * @see javax.imageio.spi.IIORegistry
   61    * @see javax.imageio.spi.ImageWriterSpi
   62    *
   63    */
   64   public abstract class ImageWriter implements ImageTranscoder {
   65   
   66       /**
   67        * The <code>ImageWriterSpi</code> that instantiated this object,
   68        * or <code>null</code> if its identity is not known or none
   69        * exists.  By default it is initialized to <code>null</code>.
   70        */
   71       protected ImageWriterSpi originatingProvider = null;
   72   
   73       /**
   74        * The <code>ImageOutputStream</code> or other <code>Object</code>
   75        * set by <code>setOutput</code> and retrieved by
   76        * <code>getOutput</code>.  By default it is initialized to
   77        * <code>null</code>.
   78        */
   79       protected Object output = null;
   80   
   81       /**
   82        * An array of <code>Locale</code>s that may be used to localize
   83        * warning messages and compression setting values, or
   84        * <code>null</code> if localization is not supported.  By default
   85        * it is initialized to <code>null</code>.
   86        */
   87       protected Locale[] availableLocales = null;
   88   
   89       /**
   90        * The current <code>Locale</code> to be used for localization, or
   91        * <code>null</code> if none has been set.  By default it is
   92        * initialized to <code>null</code>.
   93        */
   94       protected Locale locale = null;
   95   
   96       /**
   97        * A <code>List</code> of currently registered
   98        * <code>IIOWriteWarningListener</code>s, initialized by default to
   99        * <code>null</code>, which is synonymous with an empty
  100        * <code>List</code>.
  101        */
  102       protected List<IIOWriteWarningListener> warningListeners = null;
  103   
  104       /**
  105        * A <code>List</code> of <code>Locale</code>s, one for each
  106        * element of <code>warningListeners</code>, initialized by default
  107        * <code>null</code>, which is synonymous with an empty
  108        * <code>List</code>.
  109        */
  110       protected List<Locale> warningLocales = null;
  111   
  112       /**
  113        * A <code>List</code> of currently registered
  114        * <code>IIOWriteProgressListener</code>s, initialized by default
  115        * <code>null</code>, which is synonymous with an empty
  116        * <code>List</code>.
  117        */
  118       protected List<IIOWriteProgressListener> progressListeners = null;
  119   
  120       /**
  121        * If <code>true</code>, the current write operation should be
  122        * aborted.
  123        */
  124       private boolean abortFlag = false;
  125   
  126       /**
  127        * Constructs an <code>ImageWriter</code> and sets its
  128        * <code>originatingProvider</code> instance variable to the
  129        * supplied value.
  130        *
  131        * <p> Subclasses that make use of extensions should provide a
  132        * constructor with signature <code>(ImageWriterSpi,
  133        * Object)</code> in order to retrieve the extension object.  If
  134        * the extension object is unsuitable, an
  135        * <code>IllegalArgumentException</code> should be thrown.
  136        *
  137        * @param originatingProvider the <code>ImageWriterSpi</code> that
  138        * is constructing this object, or <code>null</code>.
  139        */
  140       protected ImageWriter(ImageWriterSpi originatingProvider) {
  141           this.originatingProvider = originatingProvider;
  142       }
  143   
  144       /**
  145        * Returns the <code>ImageWriterSpi</code> object that created
  146        * this <code>ImageWriter</code>, or <code>null</code> if this
  147        * object was not created through the <code>IIORegistry</code>.
  148        *
  149        * <p> The default implementation returns the value of the
  150        * <code>originatingProvider</code> instance variable.
  151        *
  152        * @return an <code>ImageWriterSpi</code>, or <code>null</code>.
  153        *
  154        * @see ImageWriterSpi
  155        */
  156       public ImageWriterSpi getOriginatingProvider() {
  157           return originatingProvider;
  158       }
  159   
  160       /**
  161        * Sets the destination to the given
  162        * <code>ImageOutputStream</code> or other <code>Object</code>.
  163        * The destination is assumed to be ready to accept data, and will
  164        * not be closed at the end of each write. This allows distributed
  165        * imaging applications to transmit a series of images over a
  166        * single network connection.  If <code>output</code> is
  167        * <code>null</code>, any currently set output will be removed.
  168        *
  169        * <p> If <code>output</code> is an
  170        * <code>ImageOutputStream</code>, calls to the
  171        * <code>write</code>, <code>writeToSequence</code>, and
  172        * <code>prepareWriteEmpty</code>/<code>endWriteEmpty</code>
  173        * methods will preserve the existing contents of the stream.
  174        * Other write methods, such as <code>writeInsert</code>,
  175        * <code>replaceStreamMetadata</code>,
  176        * <code>replaceImageMetadata</code>, <code>replacePixels</code>,
  177        * <code>prepareInsertEmpty</code>/<code>endInsertEmpty</code>,
  178        * and <code>endWriteSequence</code>, require the full contents
  179        * of the stream to be readable and writable, and may alter any
  180        * portion of the stream.
  181        *
  182        * <p> Use of a general <code>Object</code> other than an
  183        * <code>ImageOutputStream</code> is intended for writers that
  184        * interact directly with an output device or imaging protocol.
  185        * The set of legal classes is advertised by the writer's service
  186        * provider's <code>getOutputTypes</code> method; most writers
  187        * will return a single-element array containing only
  188        * <code>ImageOutputStream.class</code> to indicate that they
  189        * accept only an <code>ImageOutputStream</code>.
  190        *
  191        * <p> The default implementation sets the <code>output</code>
  192        * instance variable to the value of <code>output</code> after
  193        * checking <code>output</code> against the set of classes
  194        * advertised by the originating provider, if there is one.
  195        *
  196        * @param output the <code>ImageOutputStream</code> or other
  197        * <code>Object</code> to use for future writing.
  198        *
  199        * @exception IllegalArgumentException if <code>output</code> is
  200        * not an instance of one of the classes returned by the
  201        * originating service provider's <code>getOutputTypes</code>
  202        * method.
  203        *
  204        * @see #getOutput
  205        */
  206       public void setOutput(Object output) {
  207           if (output != null) {
  208               ImageWriterSpi provider = getOriginatingProvider();
  209               if (provider != null) {
  210                   Class[] classes = provider.getOutputTypes();
  211                   boolean found = false;
  212                   for (int i = 0; i < classes.length; i++) {
  213                       if (classes[i].isInstance(output)) {
  214                           found = true;
  215                           break;
  216                       }
  217                   }
  218                   if (!found) {
  219                       throw new IllegalArgumentException("Illegal output type!");
  220                   }
  221               }
  222           }
  223   
  224           this.output = output;
  225       }
  226   
  227       /**
  228        * Returns the <code>ImageOutputStream</code> or other
  229        * <code>Object</code> set by the most recent call to the
  230        * <code>setOutput</code> method.  If no destination has been
  231        * set, <code>null</code> is returned.
  232        *
  233        * <p> The default implementation returns the value of the
  234        * <code>output</code> instance variable.
  235        *
  236        * @return the <code>Object</code> that was specified using
  237        * <code>setOutput</code>, or <code>null</code>.
  238        *
  239        * @see #setOutput
  240        */
  241       public Object getOutput() {
  242           return output;
  243       }
  244   
  245       // Localization
  246   
  247       /**
  248        * Returns an array of <code>Locale</code>s that may be used to
  249        * localize warning listeners and compression settings.  A return
  250        * value of <code>null</code> indicates that localization is not
  251        * supported.
  252        *
  253        * <p> The default implementation returns a clone of the
  254        * <code>availableLocales</code> instance variable if it is
  255        * non-<code>null</code>, or else returns <code>null</code>.
  256        *
  257        * @return an array of <code>Locale</code>s that may be used as
  258        * arguments to <code>setLocale</code>, or <code>null</code>.
  259        */
  260       public Locale[] getAvailableLocales() {
  261           return (availableLocales == null) ?
  262               null : (Locale[])availableLocales.clone();
  263       }
  264   
  265       /**
  266        * Sets the current <code>Locale</code> of this
  267        * <code>ImageWriter</code> to the given value.  A value of
  268        * <code>null</code> removes any previous setting, and indicates
  269        * that the writer should localize as it sees fit.
  270        *
  271        * <p> The default implementation checks <code>locale</code>
  272        * against the values returned by
  273        * <code>getAvailableLocales</code>, and sets the
  274        * <code>locale</code> instance variable if it is found.  If
  275        * <code>locale</code> is <code>null</code>, the instance variable
  276        * is set to <code>null</code> without any checking.
  277        *
  278        * @param locale the desired <code>Locale</code>, or
  279        * <code>null</code>.
  280        *
  281        * @exception IllegalArgumentException if <code>locale</code> is
  282        * non-<code>null</code> but is not one of the values returned by
  283        * <code>getAvailableLocales</code>.
  284        *
  285        * @see #getLocale
  286        */
  287       public void setLocale(Locale locale) {
  288           if (locale != null) {
  289               Locale[] locales = getAvailableLocales();
  290               boolean found = false;
  291               if (locales != null) {
  292                   for (int i = 0; i < locales.length; i++) {
  293                       if (locale.equals(locales[i])) {
  294                           found = true;
  295                           break;
  296                       }
  297                   }
  298               }
  299               if (!found) {
  300                   throw new IllegalArgumentException("Invalid locale!");
  301               }
  302           }
  303           this.locale = locale;
  304       }
  305   
  306       /**
  307        * Returns the currently set <code>Locale</code>, or
  308        * <code>null</code> if none has been set.
  309        *
  310        * <p> The default implementation returns the value of the
  311        * <code>locale</code> instance variable.
  312        *
  313        * @return the current <code>Locale</code>, or <code>null</code>.
  314        *
  315        * @see #setLocale
  316        */
  317       public Locale getLocale() {
  318           return locale;
  319       }
  320   
  321       // Write params
  322   
  323       /**
  324        * Returns a new <code>ImageWriteParam</code> object of the
  325        * appropriate type for this file format containing default
  326        * values, that is, those values that would be used
  327        * if no <code>ImageWriteParam</code> object were specified.  This
  328        * is useful as a starting point for tweaking just a few parameters
  329        * and otherwise leaving the default settings alone.
  330        *
  331        * <p> The default implementation constructs and returns a new
  332        * <code>ImageWriteParam</code> object that does not allow tiling,
  333        * progressive encoding, or compression, and that will be
  334        * localized for the current <code>Locale</code> (<i>i.e.</i>,
  335        * what you would get by calling <code>new
  336        * ImageWriteParam(getLocale())</code>.
  337        *
  338        * <p> Individual plug-ins may return an instance of
  339        * <code>ImageWriteParam</code> with additional optional features
  340        * enabled, or they may return an instance of a plug-in specific
  341        * subclass of <code>ImageWriteParam</code>.
  342        *
  343        * @return a new <code>ImageWriteParam</code> object containing
  344        * default values.
  345        */
  346       public ImageWriteParam getDefaultWriteParam() {
  347           return new ImageWriteParam(getLocale());
  348       }
  349   
  350       // Metadata
  351   
  352       /**
  353        * Returns an <code>IIOMetadata</code> object containing default
  354        * values for encoding a stream of images.  The contents of the
  355        * object may be manipulated using either the XML tree structure
  356        * returned by the <code>IIOMetadata.getAsTree</code> method, an
  357        * <code>IIOMetadataController</code> object, or via plug-in
  358        * specific interfaces, and the resulting data supplied to one of
  359        * the <code>write</code> methods that take a stream metadata
  360        * parameter.
  361        *
  362        * <p> An optional <code>ImageWriteParam</code> may be supplied
  363        * for cases where it may affect the structure of the stream
  364        * metadata.
  365        *
  366        * <p> If the supplied <code>ImageWriteParam</code> contains
  367        * optional setting values not supported by this writer (<i>e.g.</i>
  368        * progressive encoding or any format-specific settings), they
  369        * will be ignored.
  370        *
  371        * <p> Writers that do not make use of stream metadata
  372        * (<i>e.g.</i>, writers for single-image formats) should return
  373        * <code>null</code>.
  374        *
  375        * @param param an <code>ImageWriteParam</code> that will be used to
  376        * encode the image, or <code>null</code>.
  377        *
  378        * @return an <code>IIOMetadata</code> object.
  379        */
  380       public abstract IIOMetadata
  381           getDefaultStreamMetadata(ImageWriteParam param);
  382   
  383       /**
  384        * Returns an <code>IIOMetadata</code> object containing default
  385        * values for encoding an image of the given type.  The contents
  386        * of the object may be manipulated using either the XML tree
  387        * structure returned by the <code>IIOMetadata.getAsTree</code>
  388        * method, an <code>IIOMetadataController</code> object, or via
  389        * plug-in specific interfaces, and the resulting data supplied to
  390        * one of the <code>write</code> methods that take a stream
  391        * metadata parameter.
  392        *
  393        * <p> An optional <code>ImageWriteParam</code> may be supplied
  394        * for cases where it may affect the structure of the image
  395        * metadata.
  396        *
  397        * <p> If the supplied <code>ImageWriteParam</code> contains
  398        * optional setting values not supported by this writer (<i>e.g.</i>
  399        * progressive encoding or any format-specific settings), they
  400        * will be ignored.
  401        *
  402        * @param imageType an <code>ImageTypeSpecifier</code> indicating the
  403        * format of the image to be written later.
  404        * @param param an <code>ImageWriteParam</code> that will be used to
  405        * encode the image, or <code>null</code>.
  406        *
  407        * @return an <code>IIOMetadata</code> object.
  408        */
  409       public abstract IIOMetadata
  410           getDefaultImageMetadata(ImageTypeSpecifier imageType,
  411                                   ImageWriteParam param);
  412   
  413       // comment inherited
  414       public abstract IIOMetadata convertStreamMetadata(IIOMetadata inData,
  415                                                         ImageWriteParam param);
  416   
  417       // comment inherited
  418       public abstract IIOMetadata
  419           convertImageMetadata(IIOMetadata inData,
  420                                ImageTypeSpecifier imageType,
  421                                ImageWriteParam param);
  422   
  423       // Thumbnails
  424   
  425       /**
  426        * Returns the number of thumbnails suported by the format being
  427        * written, given the image type and any additional write
  428        * parameters and metadata objects that will be used during
  429        * encoding.  A return value of <code>-1</code> indicates that
  430        * insufficient information is available.
  431        *
  432        * <p> An <code>ImageWriteParam</code> may optionally be supplied
  433        * for cases where it may affect thumbnail handling.
  434        *
  435        * <p> If the supplied <code>ImageWriteParam</code> contains
  436        * optional setting values not supported by this writer (<i>e.g.</i>
  437        * progressive encoding or any format-specific settings), they
  438        * will be ignored.
  439        *
  440        * <p> The default implementation returns 0.
  441        *
  442        * @param imageType an <code>ImageTypeSpecifier</code> indicating
  443        * the type of image to be written, or <code>null</code>.
  444        * @param param the <code>ImageWriteParam</code> that will be used for
  445        * writing, or <code>null</code>.
  446        * @param streamMetadata an <code>IIOMetadata</code> object that will
  447        * be used for writing, or <code>null</code>.
  448        * @param imageMetadata an <code>IIOMetadata</code> object that will
  449        * be used for writing, or <code>null</code>.
  450        *
  451        * @return the number of thumbnails that may be written given the
  452        * supplied parameters, or <code>-1</code> if insufficient
  453        * information is available.
  454        */
  455       public int getNumThumbnailsSupported(ImageTypeSpecifier imageType,
  456                                            ImageWriteParam param,
  457                                            IIOMetadata streamMetadata,
  458                                            IIOMetadata imageMetadata) {
  459           return 0;
  460       }
  461   
  462       /**
  463        * Returns an array of <code>Dimension</code>s indicating the
  464        * legal size ranges for thumbnail images as they will be encoded
  465        * in the output file or stream.  This information is merely
  466        * advisory; the writer will resize any supplied thumbnails as
  467        * necessary.
  468        *
  469        * <p> The information is returned as a set of pairs; the first
  470        * element of a pair contains an (inclusive) minimum width and
  471        * height, and the second element contains an (inclusive) maximum
  472        * width and height.  Together, each pair defines a valid range of
  473        * sizes.  To specify a fixed size, the same width and height will
  474        * appear for both elements.  A return value of <code>null</code>
  475        * indicates that the size is arbitrary or unknown.
  476        *
  477        * <p> An <code>ImageWriteParam</code> may optionally be supplied
  478        * for cases where it may affect thumbnail handling.
  479        *
  480        * <p> If the supplied <code>ImageWriteParam</code> contains
  481        * optional setting values not supported by this writer (<i>e.g.</i>
  482        * progressive encoding or any format-specific settings), they
  483        * will be ignored.
  484        *
  485        * <p> The default implementation returns <code>null</code>.
  486        *
  487        * @param imageType an <code>ImageTypeSpecifier</code> indicating the
  488        * type of image to be written, or <code>null</code>.
  489        * @param param the <code>ImageWriteParam</code> that will be used for
  490        * writing, or <code>null</code>.
  491        * @param streamMetadata an <code>IIOMetadata</code> object that will
  492        * be used for writing, or <code>null</code>.
  493        * @param imageMetadata an <code>IIOMetadata</code> object that will
  494        * be used for writing, or <code>null</code>.
  495        *
  496        * @return an array of <code>Dimension</code>s with an even length
  497        * of at least two, or <code>null</code>.
  498        */
  499       public Dimension[] getPreferredThumbnailSizes(ImageTypeSpecifier imageType,
  500                                                     ImageWriteParam param,
  501                                                     IIOMetadata streamMetadata,
  502                                                     IIOMetadata imageMetadata) {
  503           return null;
  504       }
  505   
  506       /**
  507        * Returns <code>true</code> if the methods that take an
  508        * <code>IIOImage</code> parameter are capable of dealing with a
  509        * <code>Raster</code> (as opposed to <code>RenderedImage</code>)
  510        * source image.  If this method returns <code>false</code>, then
  511        * those methods will throw an
  512        * <code>UnsupportedOperationException</code> if supplied with an
  513        * <code>IIOImage</code> containing a <code>Raster</code>.
  514        *
  515        * <p> The default implementation returns <code>false</code>.
  516        *
  517        * @return <code>true</code> if <code>Raster</code> sources are
  518        * supported.
  519        */
  520       public boolean canWriteRasters() {
  521           return false;
  522       }
  523   
  524       /**
  525        * Appends a complete image stream containing a single image and
  526        * associated stream and image metadata and thumbnails to the
  527        * output.  Any necessary header information is included.  If the
  528        * output is an <code>ImageOutputStream</code>, its existing
  529        * contents prior to the current seek position are not affected,
  530        * and need not be readable or writable.
  531        *
  532        * <p> The output must have been set beforehand using the
  533        * <code>setOutput</code> method.
  534        *
  535        * <p> Stream metadata may optionally be supplied; if it is
  536        * <code>null</code>, default stream metadata will be used.
  537        *
  538        * <p> If <code>canWriteRasters</code> returns <code>true</code>,
  539        * the <code>IIOImage</code> may contain a <code>Raster</code>
  540        * source.  Otherwise, it must contain a
  541        * <code>RenderedImage</code> source.
  542        *
  543        * <p> The supplied thumbnails will be resized if needed, and any
  544        * thumbnails in excess of the supported number will be ignored.
  545        * If the format requires additional thumbnails that are not
  546        * provided, the writer should generate them internally.
  547        *
  548        * <p>  An <code>ImageWriteParam</code> may
  549        * optionally be supplied to control the writing process.  If
  550        * <code>param</code> is <code>null</code>, a default write param
  551        * will be used.
  552        *
  553        * <p> If the supplied <code>ImageWriteParam</code> contains
  554        * optional setting values not supported by this writer (<i>e.g.</i>
  555        * progressive encoding or any format-specific settings), they
  556        * will be ignored.
  557        *
  558        * @param streamMetadata an <code>IIOMetadata</code> object representing
  559        * stream metadata, or <code>null</code> to use default values.
  560        * @param image an <code>IIOImage</code> object containing an
  561        * image, thumbnails, and metadata to be written.
  562        * @param param an <code>ImageWriteParam</code>, or
  563        * <code>null</code> to use a default
  564        * <code>ImageWriteParam</code>.
  565        *
  566        * @exception IllegalStateException if the output has not
  567        * been set.
  568        * @exception UnsupportedOperationException if <code>image</code>
  569        * contains a <code>Raster</code> and <code>canWriteRasters</code>
  570        * returns <code>false</code>.
  571        * @exception IllegalArgumentException if <code>image</code> is
  572        * <code>null</code>.
  573        * @exception IOException if an error occurs during writing.
  574        */
  575       public abstract void write(IIOMetadata streamMetadata,
  576                                  IIOImage image,
  577                                  ImageWriteParam param) throws IOException;
  578   
  579       /**
  580        * Appends a complete image stream containing a single image with
  581        * default metadata and thumbnails to the output.  This method is
  582        * a shorthand for <code>write(null, image, null)</code>.
  583        *
  584        * @param image an <code>IIOImage</code> object containing an
  585        * image, thumbnails, and metadata to be written.
  586        *
  587        * @exception IllegalStateException if the output has not
  588        * been set.
  589        * @exception IllegalArgumentException if <code>image</code> is
  590        * <code>null</code>.
  591        * @exception UnsupportedOperationException if <code>image</code>
  592        * contains a <code>Raster</code> and <code>canWriteRasters</code>
  593        * returns <code>false</code>.
  594        * @exception IOException if an error occurs during writing.
  595        */
  596       public void write(IIOImage image) throws IOException {
  597           write(null, image, null);
  598       }
  599   
  600       /**
  601        * Appends a complete image stream consisting of a single image
  602        * with default metadata and thumbnails to the output.  This
  603        * method is a shorthand for <code>write(null, new IIOImage(image,
  604        * null, null), null)</code>.
  605        *
  606        * @param image a <code>RenderedImage</code> to be written.
  607        *
  608        * @exception IllegalStateException if the output has not
  609        * been set.
  610        * @exception IllegalArgumentException if <code>image</code> is
  611        * <code>null</code>.
  612        * @exception IOException if an error occurs during writing.
  613        */
  614       public void write(RenderedImage image) throws IOException {
  615           write(null, new IIOImage(image, null, null), null);
  616       }
  617   
  618       // Check that the output has been set, then throw an
  619       // UnsupportedOperationException.
  620       private void unsupported() {
  621           if (getOutput() == null) {
  622               throw new IllegalStateException("getOutput() == null!");
  623           }
  624           throw new UnsupportedOperationException("Unsupported write variant!");
  625       }
  626   
  627       // Sequence writes
  628   
  629       /**
  630        * Returns <code>true</code> if the writer is able to append an
  631        * image to an image stream that already contains header
  632        * information and possibly prior images.
  633        *
  634        * <p> If <code>canWriteSequence</code> returns <code>false</code>,
  635        * <code>writeToSequence</code> and <code>endWriteSequence</code>
  636        * will throw an <code>UnsupportedOperationException</code>.
  637        *
  638        * <p> The default implementation returns <code>false</code>.
  639        *
  640        * @return <code>true</code> if images may be appended sequentially.
  641        */
  642       public boolean canWriteSequence() {
  643           return false;
  644       }
  645   
  646       /**
  647        * Prepares a stream to accept a series of subsequent
  648        * <code>writeToSequence</code> calls, using the provided stream
  649        * metadata object.  The metadata will be written to the stream if
  650        * it should precede the image data.  If the argument is <code>null</code>,
  651        * default stream metadata is used.
  652        *
  653        * <p> If the output is an <code>ImageOutputStream</code>, the existing
  654        * contents of the output prior to the current seek position are
  655        * flushed, and need not be readable or writable.  If the format
  656        * requires that <code>endWriteSequence</code> be able to rewind to
  657        * patch up the header information, such as for a sequence of images
  658        * in a single TIFF file, then the metadata written by this method
  659        * must remain in a writable portion of the stream.  Other formats
  660        * may flush the stream after this method and after each image.
  661        *
  662        * <p> If <code>canWriteSequence</code> returns <code>false</code>,
  663        * this method will throw an
  664        * <code>UnsupportedOperationException</code>.
  665        *
  666        * <p> The output must have been set beforehand using either
  667        * the <code>setOutput</code> method.
  668        *
  669        * <p> The default implementation throws an
  670        * <code>IllegalStateException</code> if the output is
  671        * <code>null</code>, and otherwise throws an
  672        * <code>UnsupportedOperationException</code>.
  673        *
  674        * @param streamMetadata A stream metadata object, or <code>null</code>.
  675        *
  676        * @exception IllegalStateException if the output has not
  677        * been set.
  678        * @exception UnsupportedOperationException if
  679        * <code>canWriteSequence</code> returns <code>false</code>.
  680        * @exception IOException if an error occurs writing the stream
  681        * metadata.
  682        */
  683       public void prepareWriteSequence(IIOMetadata streamMetadata)
  684           throws IOException {
  685           unsupported();
  686       }
  687   
  688       /**
  689        * Appends a single image and possibly associated metadata and
  690        * thumbnails, to the output.  If the output is an
  691        * <code>ImageOutputStream</code>, the existing contents of the
  692        * output prior to the current seek position may be flushed, and
  693        * need not be readable or writable, unless the plug-in needs to
  694        * be able to patch up the header information when
  695        * <code>endWriteSequence</code> is called (<italic>e.g.</italic> TIFF).
  696        *
  697        * <p> If <code>canWriteSequence</code> returns <code>false</code>,
  698        * this method will throw an
  699        * <code>UnsupportedOperationException</code>.
  700        *
  701        * <p> The output must have been set beforehand using
  702        * the <code>setOutput</code> method.
  703        *
  704        * <p> <code>prepareWriteSequence</code> must have been called
  705        * beforehand, or an <code>IllegalStateException</code> is thrown.
  706        *
  707        * <p> If <code>canWriteRasters</code> returns <code>true</code>,
  708        * the <code>IIOImage</code> may contain a <code>Raster</code>
  709        * source.  Otherwise, it must contain a
  710        * <code>RenderedImage</code> source.
  711        *
  712        * <p> The supplied thumbnails will be resized if needed, and any
  713        * thumbnails in excess of the supported number will be ignored.
  714        * If the format requires additional thumbnails that are not
  715        * provided, the writer will generate them internally.
  716        *
  717        * <p> An <code>ImageWriteParam</code> may optionally be supplied
  718        * to control the writing process.  If <code>param</code> is
  719        * <code>null</code>, a default write param will be used.
  720        *
  721        * <p> If the supplied <code>ImageWriteParam</code> contains
  722        * optional setting values not supported by this writer (<i>e.g.</i>
  723        * progressive encoding or any format-specific settings), they
  724        * will be ignored.
  725        *
  726        * <p> The default implementation throws an
  727        * <code>IllegalStateException</code> if the output is
  728        * <code>null</code>, and otherwise throws an
  729        * <code>UnsupportedOperationException</code>.
  730        *
  731        * @param image an <code>IIOImage</code> object containing an
  732        * image, thumbnails, and metadata to be written.
  733        * @param param an <code>ImageWriteParam</code>, or
  734        * <code>null</code> to use a default
  735        * <code>ImageWriteParam</code>.
  736        *
  737        * @exception IllegalStateException if the output has not
  738        * been set, or <code>prepareWriteSequence</code> has not been called.
  739        * @exception UnsupportedOperationException if
  740        * <code>canWriteSequence</code> returns <code>false</code>.
  741        * @exception IllegalArgumentException if <code>image</code> is
  742        * <code>null</code>.
  743        * @exception UnsupportedOperationException if <code>image</code>
  744        * contains a <code>Raster</code> and <code>canWriteRasters</code>
  745        * returns <code>false</code>.
  746        * @exception IOException if an error occurs during writing.
  747        */
  748       public void writeToSequence(IIOImage image, ImageWriteParam param)
  749           throws IOException {
  750           unsupported();
  751       }
  752   
  753       /**
  754        * Completes the writing of a sequence of images begun with
  755        * <code>prepareWriteSequence</code>.  Any stream metadata that
  756        * should come at the end of the sequence of images is written out,
  757        * and any header information at the beginning of the sequence is
  758        * patched up if necessary.  If the output is an
  759        * <code>ImageOutputStream</code>, data through the stream metadata
  760        * at the end of the sequence are flushed and need not be readable
  761        * or writable.
  762        *
  763        * <p> If <code>canWriteSequence</code> returns <code>false</code>,
  764        * this method will throw an
  765        * <code>UnsupportedOperationException</code>.
  766        *
  767        * <p> The default implementation throws an
  768        * <code>IllegalStateException</code> if the output is
  769        * <code>null</code>, and otherwise throws an
  770        * <code>UnsupportedOperationException</code>.
  771        *
  772        * @exception IllegalStateException if the output has not
  773        * been set, or <code>prepareWriteSequence</code> has not been called.
  774        * @exception UnsupportedOperationException if
  775        * <code>canWriteSequence</code> returns <code>false</code>.
  776        * @exception IOException if an error occurs during writing.
  777        */
  778       public void endWriteSequence() throws IOException {
  779           unsupported();
  780       }
  781   
  782       // Metadata replacement
  783   
  784       /**
  785        * Returns <code>true</code> if it is possible to replace the
  786        * stream metadata already present in the output.
  787        *
  788        * <p> The default implementation throws an
  789        * <code>IllegalStateException</code> if the output is
  790        * <code>null</code>, and otherwise returns <code>false</code>.
  791        *
  792        * @return <code>true</code> if replacement of stream metadata is
  793        * allowed.
  794        *
  795        * @exception IllegalStateException if the output has not
  796        * been set.
  797        * @exception IOException if an I/O error occurs during the query.
  798        */
  799       public boolean canReplaceStreamMetadata() throws IOException {
  800           if (getOutput() == null) {
  801               throw new IllegalStateException("getOutput() == null!");
  802           }
  803           return false;
  804       }
  805   
  806       /**
  807        * Replaces the stream metadata in the output with new
  808        * information.  If the output is an
  809        * <code>ImageOutputStream</code>, the prior contents of the
  810        * stream are examined and possibly edited to make room for the
  811        * new data.  All of the prior contents of the output must be
  812        * available for reading and writing.
  813        *
  814        * <p> If <code>canReplaceStreamMetadata</code> returns
  815        * <code>false</code>, an
  816        * <code>UnsupportedOperationException</code> will be thrown.
  817        *
  818        * <p> The default implementation throws an
  819        * <code>IllegalStateException</code> if the output is
  820        * <code>null</code>, and otherwise throws an
  821        * <code>UnsupportedOperationException</code>.
  822        *
  823        * @param streamMetadata an <code>IIOMetadata</code> object representing
  824        * stream metadata, or <code>null</code> to use default values.
  825        *
  826        * @exception IllegalStateException if the output has not
  827        * been set.
  828        * @exception UnsupportedOperationException if the
  829        * <code>canReplaceStreamMetadata</code> returns
  830        * <code>false</code>.  modes do not include
  831        * @exception IOException if an error occurs during writing.
  832        */
  833       public void replaceStreamMetadata(IIOMetadata streamMetadata)
  834           throws IOException {
  835           unsupported();
  836       }
  837   
  838       /**
  839        * Returns <code>true</code> if it is possible to replace the
  840        * image metadata associated with an existing image with index
  841        * <code>imageIndex</code>.  If this method returns
  842        * <code>false</code>, a call to
  843        * <code>replaceImageMetadata(imageIndex)</code> will throw an
  844        * <code>UnsupportedOperationException</code>.
  845        *
  846        * <p> A writer that does not support any image metadata
  847        * replacement may return <code>false</code> without performing
  848        * bounds checking on the index.
  849        *
  850        * <p> The default implementation throws an
  851        * <code>IllegalStateException</code> if the output is
  852        * <code>null</code>, and otherwise returns <code>false</code>
  853        * without checking the value of <code>imageIndex</code>.
  854        *
  855        * @param imageIndex the index of the image whose metadata is to
  856        * be replaced.
  857        *
  858        * @return <code>true</code> if the image metadata of the given
  859        * image can be replaced.
  860        *
  861        * @exception IllegalStateException if the output has not
  862        * been set.
  863        * @exception IndexOutOfBoundsException if the writer supports
  864        * image metadata replacement in general, but
  865        * <code>imageIndex</code> is less than 0 or greater than the
  866        * largest available index.
  867        * @exception IOException if an I/O error occurs during the query.
  868        */
  869       public boolean canReplaceImageMetadata(int imageIndex)
  870           throws IOException {
  871           if (getOutput() == null) {
  872               throw new IllegalStateException("getOutput() == null!");
  873           }
  874           return false;
  875       }
  876   
  877       /**
  878        * Replaces the image metadata associated with an existing image.
  879        *
  880        * <p> If <code>canReplaceImageMetadata(imageIndex)</code> returns
  881        * <code>false</code>, an
  882        * <code>UnsupportedOperationException</code> will be thrown.
  883        *
  884        * <p> The default implementation throws an
  885        * <code>IllegalStateException</code> if the output is
  886        * <code>null</code>, and otherwise throws an
  887        * <code>UnsupportedOperationException</code>.
  888        *
  889        * @param imageIndex the index of the image whose metadata is to
  890        * be replaced.
  891        * @param imageMetadata an <code>IIOMetadata</code> object
  892        * representing image metadata, or <code>null</code>.
  893        *
  894        * @exception IllegalStateException if the output has not been
  895        * set.
  896        * @exception UnsupportedOperationException if
  897        * <code>canReplaceImageMetadata</code> returns
  898        * <code>false</code>.
  899        * @exception IndexOutOfBoundsException if <code>imageIndex</code>
  900        * is less than 0 or greater than the largest available index.
  901        * @exception IOException if an error occurs during writing.
  902        */
  903       public void replaceImageMetadata(int imageIndex,
  904                                        IIOMetadata imageMetadata)
  905           throws IOException {
  906           unsupported();
  907       }
  908   
  909       // Image insertion
  910   
  911       /**
  912        * Returns <code>true</code> if the writer supports the insertion
  913        * of a new image at the given index.  Existing images with
  914        * indices greater than or equal to the insertion index will have
  915        * their indices increased by 1.  A value for
  916        * <code>imageIndex</code> of <code>-1</code> may be used to
  917        * signify an index one larger than the current largest index.
  918        *
  919        * <p> A writer that does not support any image insertion may
  920        * return <code>false</code> without performing bounds checking on
  921        * the index.
  922        *
  923        * <p> The default implementation throws an
  924        * <code>IllegalStateException</code> if the output is
  925        * <code>null</code>, and otherwise returns <code>false</code>
  926        * withour checking the value of <code>imageIndex</code>.
  927        *
  928        * @param imageIndex the index at which the image is to be
  929        * inserted.
  930        *
  931        * @return <code>true</code> if an image may be inserted at the
  932        * given index.
  933        *
  934        * @exception IllegalStateException if the output has not
  935        * been set.
  936        * @exception IndexOutOfBoundsException if the writer supports
  937        * image insertion in general, but <code>imageIndex</code> is less
  938        * than -1 or greater than the largest available index.
  939        * @exception IOException if an I/O error occurs during the query.
  940        */
  941       public boolean canInsertImage(int imageIndex) throws IOException {
  942           if (getOutput() == null) {
  943               throw new IllegalStateException("getOutput() == null!");
  944           }
  945           return false;
  946       }
  947   
  948       /**
  949        * Inserts a new image into an existing image stream.  Existing
  950        * images with an index greater than <code>imageIndex</code> are
  951        * preserved, and their indices are each increased by 1.  A value
  952        * for <code>imageIndex</code> of -1 may be used to signify an
  953        * index one larger than the previous largest index; that is, it
  954        * will cause the image to be logically appended to the end of the
  955        * sequence.  If the output is an <code>ImageOutputStream</code>,
  956        * the entirety of the stream must be both readable and writeable.
  957        *
  958        * <p> If <code>canInsertImage(imageIndex)</code> returns
  959        * <code>false</code>, an
  960        * <code>UnsupportedOperationException</code> will be thrown.
  961        *
  962        * <p> An <code>ImageWriteParam</code> may optionally be supplied
  963        * to control the writing process.  If <code>param</code> is
  964        * <code>null</code>, a default write param will be used.
  965        *
  966        * <p> If the supplied <code>ImageWriteParam</code> contains
  967        * optional setting values not supported by this writer (<i>e.g.</i>
  968        * progressive encoding or any format-specific settings), they
  969        * will be ignored.
  970        *
  971        * <p> The default implementation throws an
  972        * <code>IllegalStateException</code> if the output is
  973        * <code>null</code>, and otherwise throws an
  974        * <code>UnsupportedOperationException</code>.
  975        *
  976        * @param imageIndex the index at which to write the image.
  977        * @param image an <code>IIOImage</code> object containing an
  978        * image, thumbnails, and metadata to be written.
  979        * @param param an <code>ImageWriteParam</code>, or
  980        * <code>null</code> to use a default
  981        * <code>ImageWriteParam</code>.
  982        *
  983        * @exception IllegalStateException if the output has not
  984        * been set.
  985        * @exception UnsupportedOperationException if
  986        * <code>canInsertImage(imageIndex)</code> returns <code>false</code>.
  987        * @exception IllegalArgumentException if <code>image</code> is
  988        * <code>null</code>.
  989        * @exception IndexOutOfBoundsException if <code>imageIndex</code>
  990        * is less than -1 or greater than the largest available index.
  991        * @exception UnsupportedOperationException if <code>image</code>
  992        * contains a <code>Raster</code> and <code>canWriteRasters</code>
  993        * returns <code>false</code>.
  994        * @exception IOException if an error occurs during writing.
  995        */
  996       public void writeInsert(int imageIndex,
  997                               IIOImage image,
  998                               ImageWriteParam param) throws IOException {
  999           unsupported();
 1000       }
 1001   
 1002       // Image removal
 1003   
 1004       /**
 1005        * Returns <code>true</code> if the writer supports the removal
 1006        * of an existing image at the given index.  Existing images with
 1007        * indices greater than the insertion index will have
 1008        * their indices decreased by 1.
 1009        *
 1010        * <p> A writer that does not support any image removal may
 1011        * return <code>false</code> without performing bounds checking on
 1012        * the index.
 1013        *
 1014        * <p> The default implementation throws an
 1015        * <code>IllegalStateException</code> if the output is
 1016        * <code>null</code>, and otherwise returns <code>false</code>
 1017        * without checking the value of <code>imageIndex</code>.
 1018        *
 1019        * @param imageIndex the index of the image to be removed.
 1020        *
 1021        * @return <code>true</code> if it is possible to remove the given
 1022        * image.
 1023        *
 1024        * @exception IllegalStateException if the output has not
 1025        * been set.
 1026        * @exception IndexOutOfBoundsException if the writer supports
 1027        * image removal in general, but <code>imageIndex</code> is less
 1028        * than 0 or greater than the largest available index.
 1029        * @exception IOException if an I/O error occurs during the
 1030        * query.
 1031        */
 1032       public boolean canRemoveImage(int imageIndex) throws IOException {
 1033           if (getOutput() == null) {
 1034               throw new IllegalStateException("getOutput() == null!");
 1035           }
 1036           return false;
 1037       }
 1038   
 1039       /**
 1040        * Removes an image from the stream.
 1041        *
 1042        * <p> If <code>canRemoveImage(imageIndex)</code> returns false,
 1043        * an <code>UnsupportedOperationException</code>will be thrown.
 1044        *
 1045        * <p> The removal may or may not cause a reduction in the actual
 1046        * file size.
 1047        *
 1048        * <p> The default implementation throws an
 1049        * <code>IllegalStateException</code> if the output is
 1050        * <code>null</code>, and otherwise throws an
 1051        * <code>UnsupportedOperationException</code>.
 1052        *
 1053        * @param imageIndex the index of the image to be removed.
 1054        *
 1055        * @exception IllegalStateException if the output has not
 1056        * been set.
 1057        * @exception UnsupportedOperationException if
 1058        * <code>canRemoveImage(imageIndex)</code> returns <code>false</code>.
 1059        * @exception IndexOutOfBoundsException if <code>imageIndex</code>
 1060        * is less than 0 or greater than the largest available index.
 1061        * @exception IOException if an I/O error occurs during the
 1062        * removal.
 1063        */
 1064       public void removeImage(int imageIndex) throws IOException {
 1065           unsupported();
 1066       }
 1067   
 1068       // Empty images
 1069   
 1070       /**
 1071        * Returns <code>true</code> if the writer supports the writing of
 1072        * a complete image stream consisting of a single image with
 1073        * undefined pixel values and associated metadata and thumbnails
 1074        * to the output.  The pixel values may be defined by future
 1075        * calls to the <code>replacePixels</code> methods.  If the output
 1076        * is an <code>ImageOutputStream</code>, its existing contents
 1077        * prior to the current seek position are not affected, and need
 1078        * not be readable or writable.
 1079        *
 1080        * <p> The default implementation throws an
 1081        * <code>IllegalStateException</code> if the output is
 1082        * <code>null</code>, and otherwise returns <code>false</code>.
 1083        *
 1084        * @return <code>true</code> if the writing of complete image
 1085        * stream with contents to be defined later is supported.
 1086        *
 1087        * @exception IllegalStateException if the output has not been
 1088        * set.
 1089        * @exception IOException if an I/O error occurs during the
 1090        * query.
 1091        */
 1092       public boolean canWriteEmpty() throws IOException {
 1093           if (getOutput() == null) {
 1094               throw new IllegalStateException("getOutput() == null!");
 1095           }
 1096           return false;
 1097       }
 1098   
 1099       /**
 1100        * Begins the writing of a complete image stream, consisting of a
 1101        * single image with undefined pixel values and associated
 1102        * metadata and thumbnails, to the output.  The pixel values will
 1103        * be defined by future calls to the <code>replacePixels</code>
 1104        * methods.  If the output is an <code>ImageOutputStream</code>,
 1105        * its existing contents prior to the current seek position are
 1106        * not affected, and need not be readable or writable.
 1107        *
 1108        * <p> The writing is not complete until a call to
 1109        * <code>endWriteEmpty</code> occurs.  Calls to
 1110        * <code>prepareReplacePixels</code>, <code>replacePixels</code>,
 1111        * and <code>endReplacePixels</code> may occur between calls to
 1112        * <code>prepareWriteEmpty</code> and <code>endWriteEmpty</code>.
 1113        * However, calls to <code>prepareWriteEmpty</code> cannot be
 1114        * nested, and calls to <code>prepareWriteEmpty</code> and
 1115        * <code>prepareInsertEmpty</code> may not be interspersed.
 1116        *
 1117        * <p> If <code>canWriteEmpty</code> returns <code>false</code>,
 1118        * an <code>UnsupportedOperationException</code> will be thrown.
 1119        *
 1120        * <p> An <code>ImageWriteParam</code> may optionally be supplied
 1121        * to control the writing process.  If <code>param</code> is
 1122        * <code>null</code>, a default write param will be used.
 1123        *
 1124        * <p> If the supplied <code>ImageWriteParam</code> contains
 1125        * optional setting values not supported by this writer (<i>e.g.</i>
 1126        * progressive encoding or any format-specific settings), they
 1127        * will be ignored.
 1128        *
 1129        * <p> The default implementation throws an
 1130        * <code>IllegalStateException</code> if the output is
 1131        * <code>null</code>, and otherwise throws an
 1132        * <code>UnsupportedOperationException</code>.
 1133        *
 1134        * @param streamMetadata an <code>IIOMetadata</code> object representing
 1135        * stream metadata, or <code>null</code> to use default values.
 1136        * @param imageType an <code>ImageTypeSpecifier</code> describing
 1137        * the layout of the image.
 1138        * @param width the width of the image.
 1139        * @param height the height of the image.
 1140        * @param imageMetadata an <code>IIOMetadata</code> object
 1141        * representing image metadata, or <code>null</code>.
 1142        * @param thumbnails a <code>List</code> of
 1143        * <code>BufferedImage</code> thumbnails for this image, or
 1144        * <code>null</code>.
 1145        * @param param an <code>ImageWriteParam</code>, or
 1146        * <code>null</code> to use a default
 1147        * <code>ImageWriteParam</code>.
 1148        *
 1149        * @exception IllegalStateException if the output has not
 1150        * been set.
 1151        * @exception UnsupportedOperationException if
 1152        * <code>canWriteEmpty</code> returns <code>false</code>.
 1153        * @exception IllegalStateException if a previous call to
 1154        * <code>prepareWriteEmpty</code> has been made without a
 1155        * corresponding call to <code>endWriteEmpty</code>.
 1156        * @exception IllegalStateException if a previous call to
 1157        * <code>prepareInsertEmpty</code> has been made without a
 1158        * corresponding call to <code>endInsertEmpty</code>.
 1159        * @exception IllegalArgumentException if <code>imageType</code>
 1160        * is <code>null</code> or <code>thumbnails</code> contains
 1161        * <code>null</code> references or objects other than
 1162        * <code>BufferedImage</code>s.
 1163        * @exception IllegalArgumentException if width or height are less
 1164        * than 1.
 1165        * @exception IOException if an I/O error occurs during writing.
 1166        */
 1167       public void prepareWriteEmpty(IIOMetadata streamMetadata,
 1168                                     ImageTypeSpecifier imageType,
 1169                                     int width, int height,
 1170                                     IIOMetadata imageMetadata,
 1171                                     List<? extends BufferedImage> thumbnails,
 1172                                     ImageWriteParam param) throws IOException {
 1173           unsupported();
 1174       }
 1175   
 1176       /**
 1177        * Completes the writing of a new image that was begun with a
 1178        * prior call to <code>prepareWriteEmpty</code>.
 1179        *
 1180        * <p> If <code>canWriteEmpty()</code> returns <code>false</code>,
 1181        * an <code>UnsupportedOperationException</code> will be thrown.
 1182        *
 1183        * <p> The default implementation throws an
 1184        * <code>IllegalStateException</code> if the output is
 1185        * <code>null</code>, and otherwise throws an
 1186        * <code>UnsupportedOperationException</code>.
 1187        *
 1188        * @exception IllegalStateException if the output has not
 1189        * been set.
 1190        * @exception UnsupportedOperationException if
 1191        * <code>canWriteEmpty(imageIndex)</code> returns
 1192        * <code>false</code>.
 1193        * @exception IllegalStateException if a previous call to
 1194        * <code>prepareWriteEmpty</code> without a corresponding call to
 1195        * <code>endWriteEmpty</code> has not been made.
 1196        * @exception IllegalStateException if a previous call to
 1197        * <code>prepareInsertEmpty</code> without a corresponding call to
 1198        * <code>endInsertEmpty</code> has been made.
 1199        * @exception IllegalStateException if a call to
 1200        * <code>prepareReiplacePixels</code> has been made without a
 1201        * matching call to <code>endReplacePixels</code>.
 1202        * @exception IOException if an I/O error occurs during writing.
 1203        */
 1204       public void endWriteEmpty() throws IOException {
 1205           if (getOutput() == null) {
 1206               throw new IllegalStateException("getOutput() == null!");
 1207           }
 1208           throw new IllegalStateException("No call to prepareWriteEmpty!");
 1209       }
 1210   
 1211       /**
 1212        * Returns <code>true</code> if the writer supports the insertion
 1213        * of a new, empty image at the given index.  The pixel values of
 1214        * the image are undefined, and may be specified in pieces using
 1215        * the <code>replacePixels</code> methods.  Existing images with
 1216        * indices greater than or equal to the insertion index will have
 1217        * their indices increased by 1.  A value for
 1218        * <code>imageIndex</code> of <code>-1</code> may be used to
 1219        * signify an index one larger than the current largest index.
 1220        *
 1221        * <p> A writer that does not support insertion of empty images
 1222        * may return <code>false</code> without performing bounds
 1223        * checking on the index.
 1224        *
 1225        * <p> The default implementation throws an
 1226        * <code>IllegalStateException</code> if the output is
 1227        * <code>null</code>, and otherwise returns <code>false</code>
 1228        * without checking the value of <code>imageIndex</code>.
 1229        *
 1230        * @param imageIndex the index at which the image is to be
 1231        * inserted.
 1232        *
 1233        * @return <code>true</code> if an empty image may be inserted at
 1234        * the given index.
 1235        *
 1236        * @exception IllegalStateException if the output has not been
 1237        * set.
 1238        * @exception IndexOutOfBoundsException if the writer supports
 1239        * empty image insertion in general, but <code>imageIndex</code>
 1240        * is less than -1 or greater than the largest available index.
 1241        * @exception IOException if an I/O error occurs during the
 1242        * query.
 1243        */
 1244       public boolean canInsertEmpty(int imageIndex) throws IOException {
 1245           if (getOutput() == null) {
 1246               throw new IllegalStateException("getOutput() == null!");
 1247           }
 1248           return false;
 1249       }
 1250   
 1251       /**
 1252        * Begins the insertion of a new image with undefined pixel values
 1253        * into an existing image stream.  Existing images with an index
 1254        * greater than <code>imageIndex</code> are preserved, and their
 1255        * indices are each increased by 1.  A value for
 1256        * <code>imageIndex</code> of -1 may be used to signify an index
 1257        * one larger than the previous largest index; that is, it will
 1258        * cause the image to be logically appended to the end of the
 1259        * sequence.  If the output is an <code>ImageOutputStream</code>,
 1260        * the entirety of the stream must be both readable and writeable.
 1261        *
 1262        * <p> The image contents may be
 1263        * supplied later using the <code>replacePixels</code> method.
 1264        * The insertion is not complete until a call to
 1265        * <code>endInsertEmpty</code> occurs.  Calls to
 1266        * <code>prepareReplacePixels</code>, <code>replacePixels</code>,
 1267        * and <code>endReplacePixels</code> may occur between calls to
 1268        * <code>prepareInsertEmpty</code> and
 1269        * <code>endInsertEmpty</code>.  However, calls to
 1270        * <code>prepareInsertEmpty</code> cannot be nested, and calls to
 1271        * <code>prepareWriteEmpty</code> and
 1272        * <code>prepareInsertEmpty</code> may not be interspersed.
 1273        *
 1274        * <p> If <code>canInsertEmpty(imageIndex)</code> returns
 1275        * <code>false</code>, an
 1276        * <code>UnsupportedOperationException</code> will be thrown.
 1277        *
 1278        * <p> An <code>ImageWriteParam</code> may optionally be supplied
 1279        * to control the writing process.  If <code>param</code> is
 1280        * <code>null</code>, a default write param will be used.
 1281        *
 1282        * <p> If the supplied <code>ImageWriteParam</code> contains
 1283        * optional setting values not supported by this writer (<i>e.g.</i>
 1284        * progressive encoding or any format-specific settings), they
 1285        * will be ignored.
 1286        *
 1287        * <p> The default implementation throws an
 1288        * <code>IllegalStateException</code> if the output is
 1289        * <code>null</code>, and otherwise throws an
 1290        * <code>UnsupportedOperationException</code>.
 1291        *
 1292        * @param imageIndex the index at which to write the image.
 1293        * @param imageType an <code>ImageTypeSpecifier</code> describing
 1294        * the layout of the image.
 1295        * @param width the width of the image.
 1296        * @param height the height of the image.
 1297        * @param imageMetadata an <code>IIOMetadata</code> object
 1298        * representing image metadata, or <code>null</code>.
 1299        * @param thumbnails a <code>List</code> of
 1300        * <code>BufferedImage</code> thumbnails for this image, or
 1301        * <code>null</code>.
 1302        * @param param an <code>ImageWriteParam</code>, or
 1303        * <code>null</code> to use a default
 1304        * <code>ImageWriteParam</code>.
 1305        *
 1306        * @exception IllegalStateException if the output has not
 1307        * been set.
 1308        * @exception UnsupportedOperationException if
 1309        * <code>canInsertEmpty(imageIndex)</code> returns
 1310        * <code>false</code>.
 1311        * @exception IndexOutOfBoundsException if <code>imageIndex</code>
 1312        * is less than -1 or greater than the largest available index.
 1313        * @exception IllegalStateException if a previous call to
 1314        * <code>prepareInsertEmpty</code> has been made without a
 1315        * corresponding call to <code>endInsertEmpty</code>.
 1316        * @exception IllegalStateException if a previous call to
 1317        * <code>prepareWriteEmpty</code> has been made without a
 1318        * corresponding call to <code>endWriteEmpty</code>.
 1319        * @exception IllegalArgumentException if <code>imageType</code>
 1320        * is <code>null</code> or <code>thumbnails</code> contains
 1321        * <code>null</code> references or objects other than
 1322        * <code>BufferedImage</code>s.
 1323        * @exception IllegalArgumentException if width or height are less
 1324        * than 1.
 1325        * @exception IOException if an I/O error occurs during writing.
 1326        */
 1327       public void prepareInsertEmpty(int imageIndex,
 1328                                      ImageTypeSpecifier imageType,
 1329                                      int width, int height,
 1330                                      IIOMetadata imageMetadata,
 1331                                      List<? extends BufferedImage> thumbnails,
 1332                                      ImageWriteParam param) throws IOException {
 1333           unsupported();
 1334       }
 1335   
 1336       /**
 1337        * Completes the insertion of a new image that was begun with a
 1338        * prior call to <code>prepareInsertEmpty</code>.
 1339        *
 1340        * <p> The default implementation throws an
 1341        * <code>IllegalStateException</code> if the output is
 1342        * <code>null</code>, and otherwise throws an
 1343        * <code>UnsupportedOperationException</code>.
 1344        *
 1345        * @exception IllegalStateException if the output has not
 1346        * been set.
 1347        * @exception UnsupportedOperationException if
 1348        * <code>canInsertEmpty(imageIndex)</code> returns
 1349        * <code>false</code>.
 1350        * @exception IllegalStateException if a previous call to
 1351        * <code>prepareInsertEmpty</code> without a corresponding call to
 1352        * <code>endInsertEmpty</code> has not been made.
 1353        * @exception IllegalStateException if a previous call to
 1354        * <code>prepareWriteEmpty</code> without a corresponding call to
 1355        * <code>endWriteEmpty</code> has been made.
 1356        * @exception IllegalStateException if a call to
 1357        * <code>prepareReplacePixels</code> has been made without a
 1358        * matching call to <code>endReplacePixels</code>.
 1359        * @exception IOException if an I/O error occurs during writing.
 1360        */
 1361       public void endInsertEmpty() throws IOException {
 1362           unsupported();
 1363       }
 1364   
 1365       // Pixel replacement
 1366   
 1367       /**
 1368        * Returns <code>true</code> if the writer allows pixels of the
 1369        * given image to be replaced using the <code>replacePixels</code>
 1370        * methods.
 1371        *
 1372        * <p> A writer that does not support any pixel replacement may
 1373        * return <code>false</code> without performing bounds checking on
 1374        * the index.
 1375        *
 1376        * <p> The default implementation throws an
 1377        * <code>IllegalStateException</code> if the output is
 1378        * <code>null</code>, and otherwise returns <code>false</code>
 1379        * without checking the value of <code>imageIndex</code>.
 1380        *
 1381        * @param imageIndex the index of the image whose pixels are to be
 1382        * replaced.
 1383        *
 1384        * @return <code>true</code> if the pixels of the given
 1385        * image can be replaced.
 1386        *
 1387        * @exception IllegalStateException if the output has not been
 1388        * set.
 1389        * @exception IndexOutOfBoundsException if the writer supports
 1390        * pixel replacement in general, but <code>imageIndex</code> is
 1391        * less than 0 or greater than the largest available index.
 1392        * @exception IOException if an I/O error occurs during the query.
 1393        */
 1394       public boolean canReplacePixels(int imageIndex) throws IOException {
 1395           if (getOutput() == null) {
 1396               throw new IllegalStateException("getOutput() == null!");
 1397           }
 1398           return false;
 1399       }
 1400   
 1401       /**
 1402        * Prepares the writer to handle a series of calls to the
 1403        * <code>replacePixels</code> methods.  The affected pixel area
 1404        * will be clipped against the supplied
 1405        *
 1406        * <p> If <code>canReplacePixels</code> returns
 1407        * <code>false</code>, and
 1408        * <code>UnsupportedOperationException</code> will be thrown.
 1409        *
 1410        * <p> The default implementation throws an
 1411        * <code>IllegalStateException</code> if the output is
 1412        * <code>null</code>, and otherwise throws an
 1413        * <code>UnsupportedOperationException</code>.
 1414        *
 1415        * @param imageIndex the index of the image whose pixels are to be
 1416        * replaced.
 1417        * @param region a <code>Rectangle</code> that will be used to clip
 1418        * future pixel regions.
 1419        *
 1420        * @exception IllegalStateException if the output has not
 1421        * been set.
 1422        * @exception UnsupportedOperationException if
 1423        * <code>canReplacePixels(imageIndex)</code> returns
 1424        * <code>false</code>.
 1425        * @exception IndexOutOfBoundsException if <code>imageIndex</code>
 1426        * is less than 0 or greater than the largest available index.
 1427        * @exception IllegalStateException if there is a previous call to
 1428        * <code>prepareReplacePixels</code> without a matching call to
 1429        * <code>endReplacePixels</code> (<i>i.e.</i>, nesting is not
 1430        * allowed).
 1431        * @exception IllegalArgumentException if <code>region</code> is
 1432        * <code>null</code> or has a width or height less than 1.
 1433        * @exception IOException if an I/O error occurs during the
 1434        * preparation.
 1435        */
 1436       public void prepareReplacePixels(int imageIndex,
 1437                                        Rectangle region)  throws IOException {
 1438           unsupported();
 1439       }
 1440   
 1441       /**
 1442        * Replaces a portion of an image already present in the output
 1443        * with a portion of the given image.  The image data must match,
 1444        * or be convertible to, the image layout of the existing image.
 1445        *
 1446        * <p> The destination region is specified in the
 1447        * <code>param</code> argument, and will be clipped to the image
 1448        * boundaries and the region supplied to
 1449        * <code>prepareReplacePixels</code>.  At least one pixel of the
 1450        * source must not be clipped, or an exception is thrown.
 1451        *
 1452        * <p> An <code>ImageWriteParam</code> may optionally be supplied
 1453        * to control the writing process.  If <code>param</code> is
 1454        * <code>null</code>, a default write param will be used.
 1455        *
 1456        * <p> If the supplied <code>ImageWriteParam</code> contains
 1457        * optional setting values not supported by this writer (<i>e.g.</i>
 1458        * progressive encoding or any format-specific settings), they
 1459        * will be ignored.
 1460        *
 1461        * <p> This method may only be called after a call to
 1462        * <code>prepareReplacePixels</code>, or else an
 1463        * <code>IllegalStateException</code> will be thrown.
 1464        *
 1465        * <p> The default implementation throws an
 1466        * <code>IllegalStateException</code> if the output is
 1467        * <code>null</code>, and otherwise throws an
 1468        * <code>UnsupportedOperationException</code>.
 1469        *
 1470        * @param image a <code>RenderedImage</code> containing source
 1471        * pixels.
 1472        * @param param an <code>ImageWriteParam</code>, or
 1473        * <code>null</code> to use a default
 1474        * <code>ImageWriteParam</code>.
 1475        *
 1476        * @exception IllegalStateException if the output has not
 1477        * been set.
 1478        * @exception UnsupportedOperationException if
 1479        * <code>canReplacePixels(imageIndex)</code> returns
 1480        * <code>false</code>.
 1481        * @exception IllegalStateException if there is no previous call to
 1482        * <code>prepareReplacePixels</code> without a matching call to
 1483        * <code>endReplacePixels</code>.
 1484        * @exception IllegalArgumentException if any of the following are true:
 1485        * <ul>
 1486        * <li> <code>image</code> is <code>null</code>.
 1487        * <li> <code>param</code> is <code>null</code>.
 1488        * <li> the intersected region does not contain at least one pixel.
 1489        * <li> the layout of <code>image</code> does not match, or this
 1490        * writer cannot convert it to, the existing image layout.
 1491        * </ul>
 1492        * @exception IOException if an I/O error occurs during writing.
 1493        */
 1494       public void replacePixels(RenderedImage image, ImageWriteParam param)
 1495           throws IOException {
 1496           unsupported();
 1497       }
 1498   
 1499       /**
 1500        * Replaces a portion of an image already present in the output
 1501        * with a portion of the given <code>Raster</code>.  The image
 1502        * data must match, or be convertible to, the image layout of the
 1503        * existing image.
 1504        *
 1505        * <p> An <code>ImageWriteParam</code> may optionally be supplied
 1506        * to control the writing process.  If <code>param</code> is
 1507        * <code>null</code>, a default write param will be used.
 1508        *
 1509        * <p> The destination region is specified in the
 1510        * <code>param</code> argument, and will be clipped to the image
 1511        * boundaries and the region supplied to
 1512        * <code>prepareReplacePixels</code>.  At least one pixel of the
 1513        * source must not be clipped, or an exception is thrown.
 1514        *
 1515        * <p> If the supplied <code>ImageWriteParam</code> contains
 1516        * optional setting values not supported by this writer (<i>e.g.</i>
 1517        * progressive encoding or any format-specific settings), they
 1518        * will be ignored.
 1519        *
 1520        * <p> This method may only be called after a call to
 1521        * <code>prepareReplacePixels</code>, or else an
 1522        * <code>IllegalStateException</code> will be thrown.
 1523        *
 1524        * <p> The default implementation throws an
 1525        * <code>IllegalStateException</code> if the output is
 1526        * <code>null</code>, and otherwise throws an
 1527        * <code>UnsupportedOperationException</code>.
 1528        *
 1529        * @param raster a <code>Raster</code> containing source
 1530        * pixels.
 1531        * @param param an <code>ImageWriteParam</code>, or
 1532        * <code>null</code> to use a default
 1533        * <code>ImageWriteParam</code>.
 1534        *
 1535        * @exception IllegalStateException if the output has not
 1536        * been set.
 1537        * @exception UnsupportedOperationException if
 1538        * <code>canReplacePixels(imageIndex)</code> returns
 1539        * <code>false</code>.
 1540        * @exception IllegalStateException if there is no previous call to
 1541        * <code>prepareReplacePixels</code> without a matching call to
 1542        * <code>endReplacePixels</code>.
 1543        * @exception UnsupportedOperationException if
 1544        * <code>canWriteRasters</code> returns <code>false</code>.
 1545        * @exception IllegalArgumentException if any of the following are true:
 1546        * <ul>
 1547        * <li> <code>raster</code> is <code>null</code>.
 1548        * <li> <code>param</code> is <code>null</code>.
 1549        * <li> the intersected region does not contain at least one pixel.
 1550        * <li> the layout of <code>raster</code> does not match, or this
 1551        * writer cannot convert it to, the existing image layout.
 1552        * </ul>
 1553        * @exception IOException if an I/O error occurs during writing.
 1554        */
 1555       public void replacePixels(Raster raster, ImageWriteParam param)
 1556           throws IOException {
 1557           unsupported();
 1558       }
 1559   
 1560       /**
 1561        * Terminates a sequence of calls to <code>replacePixels</code>.
 1562        *
 1563        * <p> If <code>canReplacePixels</code> returns
 1564        * <code>false</code>, and
 1565        * <code>UnsupportedOperationException</code> will be thrown.
 1566        *
 1567        * <p> The default implementation throws an
 1568        * <code>IllegalStateException</code> if the output is
 1569        * <code>null</code>, and otherwise throws an
 1570        * <code>UnsupportedOperationException</code>.
 1571        *
 1572        * @exception IllegalStateException if the output has not
 1573        * been set.
 1574        * @exception UnsupportedOperationException if
 1575        * <code>canReplacePixels(imageIndex)</code> returns
 1576        * <code>false</code>.
 1577        * @exception IllegalStateException if there is no previous call
 1578        * to <code>prepareReplacePixels</code> without a matching call to
 1579        * <code>endReplacePixels</code>.
 1580        * @exception IOException if an I/O error occurs during writing.
 1581        */
 1582       public void endReplacePixels() throws IOException {
 1583           unsupported();
 1584       }
 1585   
 1586       // Abort
 1587   
 1588       /**
 1589        * Requests that any current write operation be aborted.  The
 1590        * contents of the output following the abort will be undefined.
 1591        *
 1592        * <p> Writers should call <code>clearAbortRequest</code> at the
 1593        * beginning of each write operation, and poll the value of
 1594        * <code>abortRequested</code> regularly during the write.
 1595        */
 1596       public synchronized void abort() {
 1597           this.abortFlag = true;
 1598       }
 1599   
 1600       /**
 1601        * Returns <code>true</code> if a request to abort the current
 1602        * write operation has been made since the writer was instantiated or
 1603        * <code>clearAbortRequest</code> was called.
 1604        *
 1605        * @return <code>true</code> if the current write operation should
 1606        * be aborted.
 1607        *
 1608        * @see #abort
 1609        * @see #clearAbortRequest
 1610        */
 1611       protected synchronized boolean abortRequested() {
 1612           return this.abortFlag;
 1613       }
 1614   
 1615       /**
 1616        * Clears any previous abort request.  After this method has been
 1617        * called, <code>abortRequested</code> will return
 1618        * <code>false</code>.
 1619        *
 1620        * @see #abort
 1621        * @see #abortRequested
 1622        */
 1623       protected synchronized void clearAbortRequest() {
 1624           this.abortFlag = false;
 1625       }
 1626   
 1627       // Listeners
 1628   
 1629       /**
 1630        * Adds an <code>IIOWriteWarningListener</code> to the list of
 1631        * registered warning listeners.  If <code>listener</code> is
 1632        * <code>null</code>, no exception will be thrown and no action
 1633        * will be taken.  Messages sent to the given listener will be
 1634        * localized, if possible, to match the current
 1635        * <code>Locale</code>.  If no <code>Locale</code> has been set,
 1636        * warning messages may be localized as the writer sees fit.
 1637        *
 1638        * @param listener an <code>IIOWriteWarningListener</code> to be
 1639        * registered.
 1640        *
 1641        * @see #removeIIOWriteWarningListener
 1642        */
 1643       public void addIIOWriteWarningListener(IIOWriteWarningListener listener) {
 1644           if (listener == null) {
 1645               return;
 1646           }
 1647           warningListeners = ImageReader.addToList(warningListeners, listener);
 1648           warningLocales = ImageReader.addToList(warningLocales, getLocale());
 1649       }
 1650   
 1651       /**
 1652        * Removes an <code>IIOWriteWarningListener</code> from the list
 1653        * of registered warning listeners.  If the listener was not
 1654        * previously registered, or if <code>listener</code> is
 1655        * <code>null</code>, no exception will be thrown and no action
 1656        * will be taken.
 1657        *
 1658        * @param listener an <code>IIOWriteWarningListener</code> to be
 1659        * deregistered.
 1660        *
 1661        * @see #addIIOWriteWarningListener
 1662        */
 1663       public
 1664           void removeIIOWriteWarningListener(IIOWriteWarningListener listener) {
 1665           if (listener == null || warningListeners == null) {
 1666               return;
 1667           }
 1668           int index = warningListeners.indexOf(listener);
 1669           if (index != -1) {
 1670               warningListeners.remove(index);
 1671               warningLocales.remove(index);
 1672               if (warningListeners.size() == 0) {
 1673                   warningListeners = null;
 1674                   warningLocales = null;
 1675               }
 1676           }
 1677       }
 1678   
 1679       /**
 1680        * Removes all currently registered
 1681        * <code>IIOWriteWarningListener</code> objects.
 1682        *
 1683        * <p> The default implementation sets the
 1684        * <code>warningListeners</code> and <code>warningLocales</code>
 1685        * instance variables to <code>null</code>.
 1686        */
 1687       public void removeAllIIOWriteWarningListeners() {
 1688           this.warningListeners = null;
 1689           this.warningLocales = null;
 1690       }
 1691   
 1692       /**
 1693        * Adds an <code>IIOWriteProgressListener</code> to the list of
 1694        * registered progress listeners.  If <code>listener</code> is
 1695        * <code>null</code>, no exception will be thrown and no action
 1696        * will be taken.
 1697        *
 1698        * @param listener an <code>IIOWriteProgressListener</code> to be
 1699        * registered.
 1700        *
 1701        * @see #removeIIOWriteProgressListener
 1702        */
 1703       public void
 1704           addIIOWriteProgressListener(IIOWriteProgressListener listener) {
 1705           if (listener == null) {
 1706               return;
 1707           }
 1708           progressListeners = ImageReader.addToList(progressListeners, listener);
 1709       }
 1710   
 1711       /**
 1712        * Removes an <code>IIOWriteProgressListener</code> from the list
 1713        * of registered progress listeners.  If the listener was not
 1714        * previously registered, or if <code>listener</code> is
 1715        * <code>null</code>, no exception will be thrown and no action
 1716        * will be taken.
 1717        *
 1718        * @param listener an <code>IIOWriteProgressListener</code> to be
 1719        * deregistered.
 1720        *
 1721        * @see #addIIOWriteProgressListener
 1722        */
 1723       public void
 1724           removeIIOWriteProgressListener(IIOWriteProgressListener listener) {
 1725           if (listener == null || progressListeners == null) {
 1726               return;
 1727           }
 1728           progressListeners =
 1729               ImageReader.removeFromList(progressListeners, listener);
 1730       }
 1731   
 1732       /**
 1733        * Removes all currently registered
 1734        * <code>IIOWriteProgressListener</code> objects.
 1735        *
 1736        * <p> The default implementation sets the
 1737        * <code>progressListeners</code> instance variable to
 1738        * <code>null</code>.
 1739        */
 1740       public void removeAllIIOWriteProgressListeners() {
 1741           this.progressListeners = null;
 1742       }
 1743   
 1744       /**
 1745        * Broadcasts the start of an image write to all registered
 1746        * <code>IIOWriteProgressListener</code>s by calling their
 1747        * <code>imageStarted</code> method.  Subclasses may use this
 1748        * method as a convenience.
 1749        *
 1750        * @param imageIndex the index of the image about to be written.
 1751        */
 1752       protected void processImageStarted(int imageIndex) {
 1753           if (progressListeners == null) {
 1754               return;
 1755           }
 1756           int numListeners = progressListeners.size();
 1757           for (int i = 0; i < numListeners; i++) {
 1758               IIOWriteProgressListener listener =
 1759                   (IIOWriteProgressListener)progressListeners.get(i);
 1760               listener.imageStarted(this, imageIndex);
 1761           }
 1762       }
 1763   
 1764       /**
 1765        * Broadcasts the current percentage of image completion to all
 1766        * registered <code>IIOWriteProgressListener</code>s by calling
 1767        * their <code>imageProgress</code> method.  Subclasses may use
 1768        * this method as a convenience.
 1769        *
 1770        * @param percentageDone the current percentage of completion,
 1771        * as a <code>float</code>.
 1772        */
 1773       protected void processImageProgress(float percentageDone) {
 1774           if (progressListeners == null) {
 1775               return;
 1776           }
 1777           int numListeners = progressListeners.size();
 1778           for (int i = 0; i < numListeners; i++) {
 1779               IIOWriteProgressListener listener =
 1780                   (IIOWriteProgressListener)progressListeners.get(i);
 1781               listener.imageProgress(this, percentageDone);
 1782           }
 1783       }
 1784   
 1785       /**
 1786        * Broadcasts the completion of an image write to all registered
 1787        * <code>IIOWriteProgressListener</code>s by calling their
 1788        * <code>imageComplete</code> method.  Subclasses may use this
 1789        * method as a convenience.
 1790        */
 1791       protected void processImageComplete() {
 1792           if (progressListeners == null) {
 1793               return;
 1794           }
 1795           int numListeners = progressListeners.size();
 1796           for (int i = 0; i < numListeners; i++) {
 1797               IIOWriteProgressListener listener =
 1798                   (IIOWriteProgressListener)progressListeners.get(i);
 1799               listener.imageComplete(this);
 1800           }
 1801       }
 1802   
 1803       /**
 1804        * Broadcasts the start of a thumbnail write to all registered
 1805        * <code>IIOWriteProgressListener</code>s by calling their
 1806        * <code>thumbnailStarted</code> method.  Subclasses may use this
 1807        * method as a convenience.
 1808        *
 1809        * @param imageIndex the index of the image associated with the
 1810        * thumbnail.
 1811        * @param thumbnailIndex the index of the thumbnail.
 1812        */
 1813       protected void processThumbnailStarted(int imageIndex,
 1814                                              int thumbnailIndex) {
 1815           if (progressListeners == null) {
 1816               return;
 1817           }
 1818           int numListeners = progressListeners.size();
 1819           for (int i = 0; i < numListeners; i++) {
 1820               IIOWriteProgressListener listener =
 1821                   (IIOWriteProgressListener)progressListeners.get(i);
 1822               listener.thumbnailStarted(this, imageIndex, thumbnailIndex);
 1823           }
 1824       }
 1825   
 1826       /**
 1827        * Broadcasts the current percentage of thumbnail completion to
 1828        * all registered <code>IIOWriteProgressListener</code>s by calling
 1829        * their <code>thumbnailProgress</code> method.  Subclasses may
 1830        * use this method as a convenience.
 1831        *
 1832        * @param percentageDone the current percentage of completion,
 1833        * as a <code>float</code>.
 1834        */
 1835       protected void processThumbnailProgress(float percentageDone) {
 1836           if (progressListeners == null) {
 1837               return;
 1838           }
 1839           int numListeners = progressListeners.size();
 1840           for (int i = 0; i < numListeners; i++) {
 1841               IIOWriteProgressListener listener =
 1842                   (IIOWriteProgressListener)progressListeners.get(i);
 1843               listener.thumbnailProgress(this, percentageDone);
 1844           }
 1845       }
 1846   
 1847       /**
 1848        * Broadcasts the completion of a thumbnail write to all registered
 1849        * <code>IIOWriteProgressListener</code>s by calling their
 1850        * <code>thumbnailComplete</code> method.  Subclasses may use this
 1851        * method as a convenience.
 1852        */
 1853       protected void processThumbnailComplete() {
 1854           if (progressListeners == null) {
 1855               return;
 1856           }
 1857           int numListeners = progressListeners.size();
 1858           for (int i = 0; i < numListeners; i++) {
 1859               IIOWriteProgressListener listener =
 1860                   (IIOWriteProgressListener)progressListeners.get(i);
 1861               listener.thumbnailComplete(this);
 1862           }
 1863       }
 1864   
 1865       /**
 1866        * Broadcasts that the write has been aborted to all registered
 1867        * <code>IIOWriteProgressListener</code>s by calling their
 1868        * <code>writeAborted</code> method.  Subclasses may use this
 1869        * method as a convenience.
 1870        */
 1871       protected void processWriteAborted() {
 1872           if (progressListeners == null) {
 1873               return;
 1874           }
 1875           int numListeners = progressListeners.size();
 1876           for (int i = 0; i < numListeners; i++) {
 1877               IIOWriteProgressListener listener =
 1878                   (IIOWriteProgressListener)progressListeners.get(i);
 1879               listener.writeAborted(this);
 1880           }
 1881       }
 1882   
 1883       /**
 1884        * Broadcasts a warning message to all registered
 1885        * <code>IIOWriteWarningListener</code>s by calling their
 1886        * <code>warningOccurred</code> method.  Subclasses may use this
 1887        * method as a convenience.
 1888        *
 1889        * @param imageIndex the index of the image on which the warning
 1890        * occurred.
 1891        * @param warning the warning message.
 1892        *
 1893        * @exception IllegalArgumentException if <code>warning</code>
 1894        * is <code>null</code>.
 1895        */
 1896       protected void processWarningOccurred(int imageIndex,
 1897                                             String warning) {
 1898           if (warningListeners == null) {
 1899               return;
 1900           }
 1901           if (warning == null) {
 1902               throw new IllegalArgumentException("warning == null!");
 1903           }
 1904           int numListeners = warningListeners.size();
 1905           for (int i = 0; i < numListeners; i++) {
 1906               IIOWriteWarningListener listener =
 1907                   (IIOWriteWarningListener)warningListeners.get(i);
 1908   
 1909               listener.warningOccurred(this, imageIndex, warning);
 1910           }
 1911       }
 1912   
 1913       /**
 1914        * Broadcasts a localized warning message to all registered
 1915        * <code>IIOWriteWarningListener</code>s by calling their
 1916        * <code>warningOccurred</code> method with a string taken
 1917        * from a <code>ResourceBundle</code>.  Subclasses may use this
 1918        * method as a convenience.
 1919        *
 1920        * @param imageIndex the index of the image on which the warning
 1921        * occurred.
 1922        * @param baseName the base name of a set of
 1923        * <code>ResourceBundle</code>s containing localized warning
 1924        * messages.
 1925        * @param keyword the keyword used to index the warning message
 1926        * within the set of <code>ResourceBundle</code>s.
 1927        *
 1928        * @exception IllegalArgumentException if <code>baseName</code>
 1929        * is <code>null</code>.
 1930        * @exception IllegalArgumentException if <code>keyword</code>
 1931        * is <code>null</code>.
 1932        * @exception IllegalArgumentException if no appropriate
 1933        * <code>ResourceBundle</code> may be located.
 1934        * @exception IllegalArgumentException if the named resource is
 1935        * not found in the located <code>ResourceBundle</code>.
 1936        * @exception IllegalArgumentException if the object retrieved
 1937        * from the <code>ResourceBundle</code> is not a
 1938        * <code>String</code>.
 1939        */
 1940       protected void processWarningOccurred(int imageIndex,
 1941                                             String baseName,
 1942                                             String keyword) {
 1943           if (warningListeners == null) {
 1944               return;
 1945           }
 1946           if (baseName == null) {
 1947               throw new IllegalArgumentException("baseName == null!");
 1948           }
 1949           if (keyword == null) {
 1950               throw new IllegalArgumentException("keyword == null!");
 1951           }
 1952           int numListeners = warningListeners.size();
 1953           for (int i = 0; i < numListeners; i++) {
 1954               IIOWriteWarningListener listener =
 1955                   (IIOWriteWarningListener)warningListeners.get(i);
 1956               Locale locale = (Locale)warningLocales.get(i);
 1957               if (locale == null) {
 1958                   locale = Locale.getDefault();
 1959               }
 1960   
 1961               /**
 1962                * If an applet supplies an implementation of ImageWriter and
 1963                * resource bundles, then the resource bundle will need to be
 1964                * accessed via the applet class loader. So first try the context
 1965                * class loader to locate the resource bundle.
 1966                * If that throws MissingResourceException, then try the
 1967                * system class loader.
 1968                */
 1969               ClassLoader loader = (ClassLoader)
 1970                   java.security.AccessController.doPrivileged(
 1971                      new java.security.PrivilegedAction() {
 1972                         public Object run() {
 1973                           return Thread.currentThread().getContextClassLoader();
 1974                         }
 1975                   });
 1976   
 1977               ResourceBundle bundle = null;
 1978               try {
 1979                   bundle = ResourceBundle.getBundle(baseName, locale, loader);
 1980               } catch (MissingResourceException mre) {
 1981                   try {
 1982                       bundle = ResourceBundle.getBundle(baseName, locale);
 1983                   } catch (MissingResourceException mre1) {
 1984                       throw new IllegalArgumentException("Bundle not found!");
 1985                   }
 1986               }
 1987   
 1988               String warning = null;
 1989               try {
 1990                   warning = bundle.getString(keyword);
 1991               } catch (ClassCastException cce) {
 1992                   throw new IllegalArgumentException("Resource is not a String!");
 1993               } catch (MissingResourceException mre) {
 1994                   throw new IllegalArgumentException("Resource is missing!");
 1995               }
 1996   
 1997               listener.warningOccurred(this, imageIndex, warning);
 1998           }
 1999       }
 2000   
 2001       // State management
 2002   
 2003       /**
 2004        * Restores the <code>ImageWriter</code> to its initial state.
 2005        *
 2006        * <p> The default implementation calls
 2007        * <code>setOutput(null)</code>, <code>setLocale(null)</code>,
 2008        * <code>removeAllIIOWriteWarningListeners()</code>,
 2009        * <code>removeAllIIOWriteProgressListeners()</code>, and
 2010        * <code>clearAbortRequest</code>.
 2011        */
 2012       public void reset() {
 2013           setOutput(null);
 2014           setLocale(null);
 2015           removeAllIIOWriteWarningListeners();
 2016           removeAllIIOWriteProgressListeners();
 2017           clearAbortRequest();
 2018       }
 2019   
 2020       /**
 2021        * Allows any resources held by this object to be released.  The
 2022        * result of calling any other method (other than
 2023        * <code>finalize</code>) subsequent to a call to this method
 2024        * is undefined.
 2025        *
 2026        * <p>It is important for applications to call this method when they
 2027        * know they will no longer be using this <code>ImageWriter</code>.
 2028        * Otherwise, the writer may continue to hold on to resources
 2029        * indefinitely.
 2030        *
 2031        * <p>The default implementation of this method in the superclass does
 2032        * nothing.  Subclass implementations should ensure that all resources,
 2033        * especially native resources, are released.
 2034        */
 2035       public void dispose() {
 2036       }
 2037   }

Home » openjdk-7 » javax » imageio » [javadoc | source]