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