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