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 }