History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/javax/imageio/ImageWriter.java (1 of 18352 files). Show all

Unified · Split

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