1 /*
2 * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
3 * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
4 *
5 *
6 *
7 *
8 *
9 *
10 *
11 *
12 *
13 *
14 *
15 *
16 *
17 *
18 *
19 *
20 *
21 *
22 *
23 *
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 supported 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 (<i>e.g.</i> 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 * without 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 }
2038