1 /* ImageWriter.java -- Encodes raster images. 2 Copyright (C) 2004, 2005 Free Software Foundation, Inc. 3 4 This file is part of GNU Classpath. 5 6 GNU Classpath is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation; either version 2, or (at your option) 9 any later version. 10 11 GNU Classpath is distributed in the hope that it will be useful, but 12 WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with GNU Classpath; see the file COPYING. If not, write to the 18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 19 02110-1301 USA. 20 21 Linking this library statically or dynamically with other modules is 22 making a combined work based on this library. Thus, the terms and 23 conditions of the GNU General Public License cover the whole 24 combination. 25 26 As a special exception, the copyright holders of this library give you 27 permission to link this library with independent modules to produce an 28 executable, regardless of the license terms of these independent 29 modules, and to copy and distribute the resulting executable under 30 terms of your choice, provided that you also meet, for each linked 31 independent module, the terms and conditions of the license of that 32 module. An independent module is a module which is not derived from 33 or based on this library. If you modify this library, you may extend 34 this exception to your version of the library, but you are not 35 obligated to do so. If you do not wish to do so, delete this 36 exception statement from your version. */ 37 38 39 package javax.imageio; 40 41 import java.awt.Dimension; 42 import java.awt.Rectangle; 43 import java.awt.image.BufferedImage; 44 import java.awt.image.Raster; 45 import java.awt.image.RenderedImage; 46 import java.io.IOException; 47 import java.util.ArrayList; 48 import java.util.Iterator; 49 import java.util.List; 50 import java.util.Locale; 51 import java.util.ResourceBundle; 52 import java.util.MissingResourceException; 53 54 import javax.imageio.event.IIOWriteProgressListener; 55 import javax.imageio.event.IIOWriteWarningListener; 56 import javax.imageio.metadata.IIOMetadata; 57 58 import javax.imageio.spi.ImageWriterSpi; 59 60 /** 61 * A class for encoding images within the ImageIO framework. 62 * 63 * An ImageWriter for a given format is instantiated by an 64 * ImageWriterSpi for that format. ImageWriterSpis are registered 65 * with the IIORegistry. 66 * 67 * The ImageWriter API supports writing animated images that may have 68 * multiple frames; to support such images many methods take an index 69 * parameter. 70 * 71 * Images may also be written in multiple passes, where each 72 * successive pass increases the level of detail in the destination 73 * image. 74 */ 75 public abstract class ImageWriter 76 implements ImageTranscoder 77 { 78 private boolean aborted; 79 80 /** 81 * All locales available for localization of warning messages, or 82 * null if localization is not supported. 83 */ 84 protected Locale[] availableLocales = null; 85 86 /** 87 * The current locale used to localize warning messages, or null if 88 * no locale has been set. 89 */ 90 protected Locale locale = null; 91 92 /** 93 * The image writer SPI that instantiated this writer. 94 */ 95 protected ImageWriterSpi originatingProvider = null; 96 97 /** 98 * An ImageInputStream to which image data is written. 99 */ 100 protected Object output = null; 101 102 /** 103 * A list of installed progress listeners. Initially null, meaning 104 * no installed listeners. 105 */ 106 protected List<IIOWriteProgressListener> progressListeners = null; 107 108 /** 109 * A list of installed warning listeners. Initially null, meaning 110 * no installed listeners. 111 */ 112 protected List<IIOWriteWarningListener> warningListeners = null; 113 114 /** 115 * A list of warning locales corresponding with the list of 116 * installed warning listeners. Initially null, meaning no locales. 117 */ 118 protected List<Locale> warningLocales = null; 119 120 /** 121 * Construct an image writer. 122 * 123 * @param originatingProvider the provider that is constructing this 124 * image writer, or null 125 */ ImageWriter(ImageWriterSpi originatingProvider)126 protected ImageWriter(ImageWriterSpi originatingProvider) 127 { 128 this.originatingProvider = originatingProvider; 129 } 130 131 /** 132 * Throw an IllegalStateException if output is null. 133 * 134 * @exception IllegalStateException if output is null 135 */ checkOutputSet()136 private void checkOutputSet() 137 { 138 if (output == null) 139 throw new IllegalStateException("no output set"); 140 } 141 142 /** 143 * Request that writing be aborted. The unwritten portions of the 144 * destination image will be undefined. 145 * 146 * Writers should clear the abort flag before starting a write 147 * operation, then poll it periodically during the write operation. 148 */ abort()149 public void abort() 150 { 151 aborted = true; 152 } 153 154 /** 155 * Check if the abort flag is set. 156 * 157 * @return true if the current write operation should be aborted, 158 * false otherwise 159 */ abortRequested()160 protected boolean abortRequested() 161 { 162 return aborted; 163 } 164 165 /** 166 * Install a write progress listener. This method will return 167 * immediately if listener is null. 168 * 169 * @param listener a write progress listener or null 170 */ addIIOWriteProgressListener(IIOWriteProgressListener listener)171 public void addIIOWriteProgressListener(IIOWriteProgressListener listener) 172 { 173 if (listener == null) 174 return; 175 if (progressListeners == null) 176 progressListeners = new ArrayList (); 177 progressListeners.add(listener); 178 } 179 180 /** 181 * Install a write warning listener. This method will return 182 * immediately if listener is null. Warning messages sent to this 183 * listener will be localized using the current locale. If the 184 * current locale is null then this writer will select a sensible 185 * default. 186 * 187 * @param listener a write warning listener 188 */ addIIOWriteWarningListener(IIOWriteWarningListener listener)189 public void addIIOWriteWarningListener (IIOWriteWarningListener listener) 190 { 191 if (listener == null) 192 return; 193 if (warningListeners == null) 194 warningListeners = new ArrayList (); 195 warningListeners.add(listener); 196 } 197 198 /** 199 * Check whether a new empty image can be inserted at the given 200 * frame index. Pixel values may be filled in later using the 201 * replacePixels methods. Indices greater than the insertion index 202 * will be incremented. If imageIndex is -1, the image will be 203 * appended at the end of the current image list. 204 * 205 * @param imageIndex the frame index 206 * 207 * @return true if an empty image can be inserted at imageIndex, 208 * false otherwise 209 * 210 * @exception IllegalStateException if output is null 211 * @exception IndexOutOfBoundsException if imageIndex is less than 212 * -1 or greater than the last index in the current image list 213 * @exception IOException if a write error occurs 214 */ canInsertEmpty(int imageIndex)215 public boolean canInsertEmpty(int imageIndex) 216 throws IOException 217 { 218 checkOutputSet(); 219 return false; 220 } 221 222 /** 223 * Check whether an image can be inserted at the given frame index. 224 * Indices greater than the insertion index will be incremented. If 225 * imageIndex is -1, the image will be appended at the end of the 226 * current image list. 227 * 228 * @param imageIndex the frame index 229 * 230 * @return true if an image can be inserted at imageIndex, false 231 * otherwise 232 * 233 * @exception IllegalStateException if output is null 234 * @exception IndexOutOfBoundsException if imageIndex is less than 235 * -1 or greater than the last index in the current image list 236 * @exception IOException if a write error occurs 237 */ canInsertImage(int imageIndex)238 public boolean canInsertImage(int imageIndex) 239 throws IOException 240 { 241 checkOutputSet(); 242 return false; 243 } 244 245 /** 246 * Check whether an image can be removed from the given frame index. 247 * Indices greater than the removal index will be decremented. 248 * 249 * @param imageIndex the frame index 250 * 251 * @return true if an image can be removed from imageIndex, false 252 * otherwise 253 * 254 * @exception IllegalStateException if output is null 255 * @exception IndexOutOfBoundsException if imageIndex is less than 0 256 * or greater than the last index in the current image list 257 * @exception IOException if a write error occurs 258 */ canRemoveImage(int imageIndex)259 public boolean canRemoveImage(int imageIndex) 260 throws IOException 261 { 262 checkOutputSet(); 263 return false; 264 } 265 266 /** 267 * Check whether the metadata associated the image at the given 268 * frame index can be replaced. 269 * 270 * @param imageIndex the frame index 271 * 272 * @return true if the metadata associated with the image at 273 * imageIndex can be replaced, false otherwise 274 * 275 * @exception IllegalStateException if output is null 276 * @exception IndexOutOfBoundsException if imageIndex is less than 0 277 * or greater than the last index in the current image list 278 * @exception IOException if a write error occurs 279 */ canReplaceImageMetadata(int imageIndex)280 public boolean canReplaceImageMetadata(int imageIndex) 281 throws IOException 282 { 283 checkOutputSet(); 284 return false; 285 } 286 287 /** 288 * Check whether the pixels within the image at the given index can 289 * be replaced. 290 * 291 * @param imageIndex the frame index 292 * 293 * @return true if the pixels in the image at imageIndex can be 294 * replaced, false otherwise 295 * 296 * @exception IllegalStateException if output is null 297 * @exception IndexOutOfBoundsException if imageIndex is less than 0 298 * or greater than the last index in the current image list 299 * @exception IOException if a write error occurs 300 */ canReplacePixels(int imageIndex)301 public boolean canReplacePixels(int imageIndex) 302 throws IOException 303 { 304 checkOutputSet(); 305 return false; 306 } 307 308 /** 309 * Check whether the metadata associated the entire image stream can 310 * be replaced. 311 * 312 * @return true if the stream metadata can be replaced, false 313 * otherwise 314 * 315 * @exception IllegalStateException if output is null 316 * @exception IOException if a write error occurs 317 */ canReplaceStreamMetadata()318 public boolean canReplaceStreamMetadata() 319 throws IOException 320 { 321 checkOutputSet(); 322 return false; 323 } 324 325 /** 326 * Check whether an entire empty image, including empty metadata and 327 * empty thumbnails, can be written to the output stream, leaving 328 * pixel values to be filled in later using the replacePixels 329 * methods. 330 * 331 * @return true if an entire empty image can be written before its 332 * contents are filled in, false otherwise 333 * 334 * @exception IllegalStateException if output is null 335 * @exception IOException if a write error occurs 336 */ canWriteEmpty()337 public boolean canWriteEmpty() 338 throws IOException 339 { 340 checkOutputSet(); 341 return false; 342 } 343 344 /** 345 * Check if IIOImages containing raster data are supported. 346 * 347 * @return true if raster IIOImages are supported, false otherwise 348 */ canWriteRasters()349 public boolean canWriteRasters() 350 { 351 return false; 352 } 353 354 /** 355 * Check if an image can be appended at the end of the current list 356 * of images even if prior images have already been written. 357 * 358 * @return true if sequences of images can be written, false 359 * otherwise 360 */ canWriteSequence()361 public boolean canWriteSequence() 362 { 363 return false; 364 } 365 366 /** 367 * Clear the abort flag. 368 */ clearAbortRequest()369 protected void clearAbortRequest() 370 { 371 aborted = false; 372 } 373 374 /** 375 * Convert IIOMetadata from an input reader format, returning an 376 * IIOMetadata suitable for use by an image writer. 377 * 378 * The ImageTypeSpecifier specifies the destination image type. 379 * 380 * An optional ImageWriteParam argument is available in case the 381 * image writing parameters affect the metadata conversion. 382 * 383 * @param inData the metadata coming from an image reader 384 * @param imageType the output image type of the writer 385 * @param param the image writing parameters or null 386 * 387 * @return the converted metadata that should be used by the image 388 * writer, or null if this ImageTranscoder has no knowledge of the 389 * input metadata 390 * 391 * @exception IllegalArgumentException if either inData or imageType 392 * is null 393 */ convertImageMetadata(IIOMetadata inData, ImageTypeSpecifier imageType, ImageWriteParam param)394 public abstract IIOMetadata convertImageMetadata (IIOMetadata inData, 395 ImageTypeSpecifier imageType, 396 ImageWriteParam param); 397 398 /** 399 * Convert IIOMetadata from an input stream format, returning an 400 * IIOMetadata suitable for use by an image writer. 401 * 402 * An optional ImageWriteParam argument is available in case the 403 * image writing parameters affect the metadata conversion. 404 * 405 * @param inData the metadata coming from an input image stream 406 * @param param the image writing parameters or null 407 * 408 * @return the converted metadata that should be used by the image 409 * writer, or null if this ImageTranscoder has no knowledge of the 410 * input metadata 411 * 412 * @exception IllegalArgumentException if inData is null 413 */ convertStreamMetadata(IIOMetadata inData, ImageWriteParam param)414 public abstract IIOMetadata convertStreamMetadata (IIOMetadata inData, 415 ImageWriteParam param); 416 417 /** 418 * Releases any resources allocated to this object. Subsequent 419 * calls to methods on this object will produce undefined results. 420 * 421 * The default implementation does nothing; subclasses should use 422 * this method ensure that native resources are released. 423 */ dispose()424 public void dispose() 425 { 426 // The default implementation is empty. Subclasses have to overwrite it. 427 } 428 429 /** 430 * Retrieve the available locales. Return null if no locales are 431 * available or a clone of availableLocales. 432 * 433 * @return an array of locales or null 434 */ getAvailableLocales()435 public Locale[] getAvailableLocales() 436 { 437 return availableLocales; 438 } 439 440 /** 441 * Get a metadata object appropriate for encoding an image specified 442 * by the given image type specifier and optional image write 443 * parameters. 444 * 445 * @param imageType an image type specifier 446 * @param param image writing parameters, or null 447 * 448 * @return a metadata object appropriate for encoding an image of 449 * the given type with the given parameters 450 */ getDefaultImageMetadata(ImageTypeSpecifier imageType, ImageWriteParam param)451 public abstract IIOMetadata getDefaultImageMetadata (ImageTypeSpecifier imageType, ImageWriteParam param); 452 453 /** 454 * Get a metadata object appropriate for encoding the default image 455 * type handled by this writer, optionally considering image write 456 * parameters. 457 * 458 * @param param image writing parameters, or null 459 * 460 * @return a metadata object appropriate for encoding an image of 461 * the default type with the given parameters 462 */ getDefaultStreamMetadata(ImageWriteParam param)463 public abstract IIOMetadata getDefaultStreamMetadata (ImageWriteParam param); 464 465 /** 466 * Retrieve the default write parameters for this writer's image 467 * format. 468 * 469 * The default implementation returns new ImageWriteParam(). 470 * 471 * @return image writing parameters 472 */ getDefaultWriteParam()473 public ImageWriteParam getDefaultWriteParam() 474 { 475 return new ImageWriteParam(getLocale()); 476 } 477 478 /** 479 * Get this writer's locale. null is returned if the locale has not 480 * been set. 481 * 482 * @return this writer's locale, or null 483 */ getLocale()484 public Locale getLocale() 485 { 486 return locale; 487 } 488 489 /** 490 * Get the number of thumbnails supported by this image writer, 491 * based on the given image type, image writing parameters, and 492 * stream and image metadata. The image writing parameters are 493 * optional, in case they affect the number of thumbnails supported. 494 * 495 * @param imageType an image type specifier, or null 496 * @param param image writing parameters, or null 497 * @param streamMetadata the metadata associated with this stream, 498 * or null 499 * @param imageMetadata the metadata associated with this image, or 500 * null 501 * 502 * @return the number of thumbnails that this writer supports 503 * writing or -1 if the given information is insufficient 504 */ getNumThumbnailsSupported(ImageTypeSpecifier imageType, ImageWriteParam param, IIOMetadata streamMetadata, IIOMetadata imageMetadata)505 public int getNumThumbnailsSupported (ImageTypeSpecifier imageType, 506 ImageWriteParam param, 507 IIOMetadata streamMetadata, 508 IIOMetadata imageMetadata) 509 { 510 return 0; 511 } 512 513 /** 514 * Get the ImageWriterSpi that created this writer or null. 515 * 516 * @return an ImageWriterSpi, or null 517 */ getOriginatingProvider()518 public ImageWriterSpi getOriginatingProvider() 519 { 520 return originatingProvider; 521 } 522 523 /** 524 * Get this reader's image output destination. null is returned if 525 * the image destination has not been set. 526 * 527 * @return an image output destination object, or null 528 */ getOutput()529 public Object getOutput() 530 { 531 return output; 532 } 533 534 /** 535 * Get the preferred sizes for thumbnails based on the given image 536 * type, image writing parameters, and stream and image metadata. 537 * The preferred sizes are returned in pairs of dimension values; 538 * the first value in the array is a dimension object representing 539 * the minimum thumbnail size, the second value is a dimension 540 * object representing a maximum thumbnail size. The writer can 541 * select a size within the range given by each pair, or it can 542 * ignore these size hints. 543 * 544 * @param imageType an image type specifier, or null 545 * @param param image writing parameters, or null 546 * @param streamMetadata the metadata associated with this stream, 547 * or null 548 * @param imageMetadata the metadata associated with this image, or 549 * null 550 * 551 * @return an array of dimension pairs whose length is a multiple of 552 * 2, or null if there is no preferred size (any size is allowed) or 553 * if the size is unknown (insufficient information was provided) 554 */ getPreferredThumbnailSizes(ImageTypeSpecifier imageType, ImageWriteParam param, IIOMetadata streamMetadata, IIOMetadata imageMetadata)555 public Dimension[] getPreferredThumbnailSizes (ImageTypeSpecifier imageType, 556 ImageWriteParam param, 557 IIOMetadata streamMetadata, 558 IIOMetadata imageMetadata) 559 { 560 return null; 561 } 562 563 /** 564 * Notifies all installed write progress listeners that image 565 * loading has completed by calling their imageComplete methods. 566 */ processImageComplete()567 protected void processImageComplete() 568 { 569 if (progressListeners != null) 570 { 571 Iterator it = progressListeners.iterator(); 572 573 while (it.hasNext()) 574 { 575 IIOWriteProgressListener listener = 576 (IIOWriteProgressListener) it.next(); 577 listener.imageComplete(this); 578 } 579 } 580 } 581 582 /** 583 * Notifies all installed write progress listeners that a certain 584 * percentage of the image has been loaded, by calling their 585 * imageProgress methods. 586 * 587 * @param percentageDone the percentage of image data that has been 588 * loaded 589 */ processImageProgress(float percentageDone)590 protected void processImageProgress(float percentageDone) 591 { 592 if (progressListeners != null) 593 { 594 Iterator it = progressListeners.iterator(); 595 596 while (it.hasNext()) 597 { 598 IIOWriteProgressListener listener = 599 (IIOWriteProgressListener) it.next(); 600 listener.imageProgress(this, percentageDone); 601 } 602 } 603 } 604 605 /** 606 * Notifies all installed write progress listeners, by calling their 607 * imageStarted methods, that image loading has started on the given 608 * image. 609 * 610 * @param imageIndex the frame index of the image that has started 611 * loading 612 */ processImageStarted(int imageIndex)613 protected void processImageStarted(int imageIndex) 614 { 615 if (progressListeners != null) 616 { 617 Iterator it = progressListeners.iterator(); 618 619 while (it.hasNext()) 620 { 621 IIOWriteProgressListener listener = 622 (IIOWriteProgressListener) it.next(); 623 listener.imageStarted(this, imageIndex); 624 } 625 } 626 } 627 628 /** 629 * Notifies all installed write progress listeners, by calling their 630 * thumbnailComplete methods, that a thumbnail has completed 631 * loading. 632 */ processThumbnailComplete()633 protected void processThumbnailComplete() 634 { 635 if (progressListeners != null) 636 { 637 Iterator it = progressListeners.iterator(); 638 639 while (it.hasNext()) 640 { 641 IIOWriteProgressListener listener = 642 (IIOWriteProgressListener) it.next(); 643 listener.thumbnailComplete(this); 644 } 645 } 646 } 647 648 /** 649 * Notifies all installed write progress listeners that a certain 650 * percentage of a thumbnail has been loaded, by calling their 651 * thumbnailProgress methods. 652 * 653 * @param percentageDone the percentage of thumbnail data that has 654 * been loaded 655 */ processThumbnailProgress(float percentageDone)656 protected void processThumbnailProgress(float percentageDone) 657 { 658 if (progressListeners != null) 659 { 660 Iterator it = progressListeners.iterator(); 661 662 while (it.hasNext()) 663 { 664 IIOWriteProgressListener listener = 665 (IIOWriteProgressListener) it.next(); 666 listener.thumbnailProgress(this, percentageDone); 667 } 668 } 669 } 670 671 /** 672 * Notifies all installed write progress listeners, by calling their 673 * imageStarted methods, that thumbnail loading has started on the 674 * given thumbnail of the given image. 675 * 676 * @param imageIndex the frame index of the image one of who's 677 * thumbnails has started loading 678 * @param thumbnailIndex the index of the thumbnail that has started 679 * loading 680 */ processThumbnailStarted(int imageIndex, int thumbnailIndex)681 protected void processThumbnailStarted(int imageIndex, int thumbnailIndex) 682 { 683 if (progressListeners != null) 684 { 685 Iterator it = progressListeners.iterator(); 686 687 while (it.hasNext()) 688 { 689 IIOWriteProgressListener listener = 690 (IIOWriteProgressListener) it.next(); 691 listener.thumbnailStarted(this, imageIndex, thumbnailIndex); 692 } 693 } 694 } 695 696 /** 697 * Notifies all installed warning listeners, by calling their 698 * warningOccurred methods, that a warning message has been raised. 699 * 700 * @param imageIndex the index of the image that was being written 701 * when the warning was raised 702 * @param warning the warning message 703 * 704 * @exception IllegalArgumentException if warning is null 705 */ processWarningOccurred(int imageIndex, String warning)706 protected void processWarningOccurred(int imageIndex, String warning) 707 { 708 if (warningListeners != null) 709 { 710 Iterator it = warningListeners.iterator(); 711 712 while (it.hasNext()) 713 { 714 IIOWriteWarningListener listener = 715 (IIOWriteWarningListener) it.next(); 716 listener.warningOccurred(this, imageIndex, warning); 717 } 718 } 719 } 720 721 /** 722 * Notify all installed warning listeners, by calling their 723 * warningOccurred methods, that a warning message has been raised. 724 * The warning message is retrieved from a resource bundle, using 725 * the given basename and keyword. 726 * 727 * @param imageIndex the index of the image that was being written 728 * when the warning was raised 729 * @param baseName the basename of the resource from which to 730 * retrieve the warning message 731 * @param keyword the keyword used to retrieve the warning from the 732 * resource bundle 733 * 734 * @exception IllegalArgumentException if either baseName or keyword 735 * is null 736 * @exception IllegalArgumentException if no resource bundle is 737 * found using baseName 738 * @exception IllegalArgumentException if the given keyword produces 739 * no results from the resource bundle 740 * @exception IllegalArgumentException if the retrieved object is 741 * not a String 742 */ processWarningOccurred(int imageIndex, String baseName, String keyword)743 protected void processWarningOccurred(int imageIndex, 744 String baseName, 745 String keyword) 746 { 747 if (baseName == null || keyword == null) 748 throw new IllegalArgumentException ("null argument"); 749 750 ResourceBundle b = null; 751 752 try 753 { 754 b = ResourceBundle.getBundle(baseName, getLocale()); 755 } 756 catch (MissingResourceException e) 757 { 758 throw new IllegalArgumentException ("no resource bundle found"); 759 } 760 761 Object str = null; 762 763 try 764 { 765 str = b.getObject(keyword); 766 } 767 catch (MissingResourceException e) 768 { 769 throw new IllegalArgumentException ("no results found for keyword"); 770 } 771 772 if (! (str instanceof String)) 773 throw new IllegalArgumentException ("retrieved object not a String"); 774 775 String warning = (String) str; 776 777 if (warningListeners != null) 778 { 779 Iterator it = warningListeners.iterator(); 780 781 while (it.hasNext()) 782 { 783 IIOWriteWarningListener listener = 784 (IIOWriteWarningListener) it.next(); 785 listener.warningOccurred(this, imageIndex, warning); 786 } 787 } 788 } 789 790 /** 791 * Notifies all installed write progress listeners that image 792 * loading has been aborted by calling their writeAborted methods. 793 */ processWriteAborted()794 protected void processWriteAborted() 795 { 796 if (progressListeners != null) 797 { 798 Iterator it = progressListeners.iterator(); 799 800 while (it.hasNext()) 801 { 802 IIOWriteProgressListener listener = 803 (IIOWriteProgressListener) it.next(); 804 listener.writeAborted(this); 805 } 806 } 807 } 808 809 /** 810 * Uninstall all write progress listeners. 811 */ removeAllIIOWriteProgressListeners()812 public void removeAllIIOWriteProgressListeners() 813 { 814 if (progressListeners != null) 815 { 816 progressListeners.clear(); 817 } 818 } 819 820 /** 821 * Uninstall all write warning listeners. 822 */ removeAllIIOWriteWarningListeners()823 public void removeAllIIOWriteWarningListeners() 824 { 825 if (progressListeners != null) 826 { 827 progressListeners.clear(); 828 } 829 } 830 831 /** 832 * Uninstall the given write progress listener. 833 * 834 * @param listener the listener to remove 835 */ removeIIOWriteProgressListener(IIOWriteProgressListener listener)836 public void removeIIOWriteProgressListener (IIOWriteProgressListener listener) 837 { 838 if (listener == null) 839 return; 840 if (progressListeners != null) 841 { 842 progressListeners.remove(listener); 843 } 844 } 845 /** 846 * Uninstall the given write warning listener. 847 * 848 * @param listener the listener to remove 849 */ removeIIOWriteWarningListener(IIOWriteWarningListener listener)850 public void removeIIOWriteWarningListener (IIOWriteWarningListener listener) 851 { 852 if (listener == null) 853 return; 854 if (warningListeners != null) 855 { 856 warningListeners.remove(listener); 857 } 858 } 859 /** 860 * Reset this writer's internal state. 861 */ reset()862 public void reset() 863 { 864 setOutput(null); 865 setLocale(null); 866 removeAllIIOWriteWarningListeners(); 867 removeAllIIOWriteProgressListeners(); 868 clearAbortRequest(); 869 } 870 871 /** 872 * Set the current locale or use the default locale. 873 * 874 * @param locale the locale to set, or null 875 */ setLocale(Locale locale)876 public void setLocale(Locale locale) 877 { 878 if (locale != null) 879 { 880 // Check if its a valid locale. 881 boolean found = false; 882 883 if (availableLocales != null) 884 for (int i = availableLocales.length - 1; i >= 0; --i) 885 if (availableLocales[i].equals(locale)) 886 found = true; 887 888 if (! found) 889 throw new IllegalArgumentException("looale not available"); 890 } 891 892 this.locale = locale; 893 } 894 895 /** 896 * Set the output destination of the given object. The output 897 * destination must be set before many methods can be called on this 898 * writer. (see all ImageWriter methods that throw 899 * IllegalStateException). If input is null then the current input 900 * source will be removed. 901 * 902 * @param output the output destination object 903 * 904 * @exception IllegalArgumentException if input is not a valid input 905 * source for this writer and is not an ImageInputStream 906 */ setOutput(Object output)907 public void setOutput(Object output) 908 { 909 if (output != null) 910 { 911 // Check if its a valid output object. 912 boolean found = false; 913 Class[] types = null; 914 915 if (originatingProvider != null) 916 types = originatingProvider.getOutputTypes(); 917 918 if (types != null) 919 for (int i = types.length - 1; i >= 0; --i) 920 if (types[i].isInstance(output)) 921 found = true; 922 923 if (! found) 924 throw new IllegalArgumentException("output type not available"); 925 } 926 927 this.output = output; 928 } 929 930 /** 931 * Write an image stream, including thumbnails and metadata to the 932 * output stream. The output must have been set prior to this 933 * method being called. Metadata associated with the stream may be 934 * supplied, or it can be left null. IIOImage may contain raster 935 * data if this writer supports rasters, or it will contain a 936 * rendered image. Thumbnails are resized if need be. Image 937 * writing parameters may be specified to affect writing, or may be 938 * left null. 939 * 940 * @param streamMetadata metadata associated with this stream, or 941 * null 942 * @param image an IIOImage containing image data, metadata and 943 * thumbnails to be written 944 * @param param image writing parameters, or null 945 * 946 * @exception IllegalStateException if output is null 947 * @exception UnsupportedOperationException if image contains raster 948 * data but this writer does not support rasters 949 * @exception IllegalArgumentException if image is null 950 * @exception IOException if a write error occurs 951 */ write(IIOMetadata streamMetadata, IIOImage image, ImageWriteParam param)952 public abstract void write (IIOMetadata streamMetadata, IIOImage image, ImageWriteParam param) 953 throws IOException; 954 955 /** 956 * Complete inserting an empty image in the output stream. 957 * 958 * @exception IllegalStateException if output is null 959 * @exception UnsupportedOperationException if inserting empty 960 * images is not supported 961 * @exception IllegalArgumentException if a call to 962 * prepareInsertEmpty was not called previous to this method being 963 * called (a sequence of prepareInsertEmpty calls must be terminated 964 * by a call to endInsertEmpty) 965 * @exception IllegalArgumentException if prepareWriteEmpty was 966 * called before this method being called (without a terminating 967 * call to endWriteEmpty) 968 * @exception IllegalArgumentException if prepareReplacePixels was 969 * called before this method being called (without a terminating 970 * call to endReplacePixels) 971 * @exception IOException if a write error occurs 972 */ endInsertEmpty()973 public void endInsertEmpty () 974 throws IOException 975 { 976 if (!canInsertEmpty(0)) 977 throw new UnsupportedOperationException(); 978 } 979 980 /** 981 * Complete replacing pixels in an image in the output stream. 982 * 983 * @exception IllegalStateException if output is null 984 * @exception UnsupportedOperationException if replacing pixels is 985 * not supported by this writer 986 * @exception IllegalArgumentException if prepareReplacePixels was 987 * not called before this method being called 988 * @exception IOException if a write error occurs 989 */ endReplacePixels()990 public void endReplacePixels () 991 throws IOException 992 { 993 if (!canReplacePixels(0)) 994 throw new UnsupportedOperationException(); 995 } 996 997 /** 998 * Complete writing an empty image to the image output stream. 999 * 1000 * @exception IllegalStateException if output is null 1001 * @exception UnsupportedOperationException if writing empty images 1002 * is not supported 1003 * @exception IllegalArgumentException if a call to 1004 * prepareWriteEmpty was not called previous to this method being 1005 * called (a sequence of prepareWriteEmpty calls must be terminated 1006 * by a call to endWriteEmpty) 1007 * @exception IllegalArgumentException if prepareInsertEmpty was 1008 * called before this method being called (without a terminating 1009 * call to endInsertEmpty) 1010 * @exception IllegalArgumentException if prepareReplacePixels was 1011 * called before this method being called (without a terminating 1012 * call to endReplacePixels) 1013 * @exception IOException if a write error occurs 1014 */ endWriteEmpty()1015 public void endWriteEmpty () 1016 throws IOException 1017 { 1018 if (!canWriteEmpty()) 1019 throw new UnsupportedOperationException(); 1020 } 1021 1022 /** 1023 * Complete writing a sequence of images to the output stream. This 1024 * method may patch header data and write out footer data. 1025 * 1026 * @exception IllegalStateException if output is null 1027 * @exception IllegalStateException if prepareWriteSequence has not 1028 * been called 1029 * @exception UnsupportedOperationException if writing a sequence of 1030 * images is not supported 1031 * @exception IOException if a write error occurs 1032 */ endWriteSequence()1033 public void endWriteSequence () 1034 throws IOException 1035 { 1036 checkOutputSet(); 1037 if (!canWriteSequence()) 1038 throw new UnsupportedOperationException(); 1039 } 1040 1041 /** 1042 * Start inserting an empty image in the image output stream. All 1043 * indices after the specified index are incremented. An index of 1044 * -1 implies that the empty image should be appended to the end of 1045 * the current image list. 1046 * 1047 * The insertion that this method call starts is not complete until 1048 * endInsertEmpty is called. prepareInsertEmpty cannot be called 1049 * again until endInsertEmpty is called and calls to 1050 * prepareWriteEmpty and prepareInsertEmpty may not be intersperced. 1051 * 1052 * @param imageIndex the image index 1053 * @param imageType the image type specifier 1054 * @param width the image width 1055 * @param height the image height 1056 * @param imageMetadata the image metadata, or null 1057 * @param thumbnails a list of thumbnails, or null 1058 * @param param image write parameters, or null 1059 * 1060 * @exception IllegalStateException if output is null 1061 * @exception UnsupportedOperationException if inserting empty 1062 * images is not supported 1063 * @exception IndexOutOfBoundsException if imageIndex is less than 1064 * -1 or greater than the last index in the current image list 1065 * @exception IllegalStateException if a previous call to 1066 * prepareInsertEmpty was made (without a terminating call to 1067 * endInsertEmpty) 1068 * @exception IllegalStateException if a previous call to 1069 * prepareWriteEmpty was made (without a terminating call to 1070 * endWriteEmpty) 1071 * @exception IllegalArgumentException if imageType is null or 1072 * thumbnails contain non-BufferedImage objects 1073 * @exception IllegalArgumentException if either width or height is 1074 * less than 1 1075 * @exception IOException if a write error occurs 1076 */ prepareInsertEmpty(int imageIndex, ImageTypeSpecifier imageType, int width, int height, IIOMetadata imageMetadata, List<? extends BufferedImage> thumbnails, ImageWriteParam param)1077 public void prepareInsertEmpty (int imageIndex, ImageTypeSpecifier imageType, 1078 int width, int height, 1079 IIOMetadata imageMetadata, 1080 List<? extends BufferedImage> thumbnails, 1081 ImageWriteParam param) 1082 throws IOException 1083 { 1084 if (!canInsertEmpty(imageIndex)) 1085 throw new UnsupportedOperationException(); 1086 } 1087 1088 /** 1089 * Start the replacement of pixels within an image in the output 1090 * stream. Output pixels will be clipped to lie within region. 1091 * 1092 * @param imageIndex the index of the image in which pixels are 1093 * being replaced 1094 * @param region the rectangle to which to limit pixel replacement 1095 * 1096 * @exception IllegalStateException if output is null 1097 * @exception UnsupportedOperationException if replacing pixels is 1098 * not supported 1099 * @exception IndexOutOfBoundsException if imageIndex is less than 0 1100 * or greater than the last index in the current image list 1101 * @exception IllegalStateException if a previous call to 1102 * prepareReplacePixels was made (without a terminating call to 1103 * endReplacePixels) 1104 * @exception IllegalArgumentException if either region.width or 1105 * region.height is less than 1, or if region is null 1106 * @exception IOException if a write error occurs 1107 */ prepareReplacePixels(int imageIndex, Rectangle region)1108 public void prepareReplacePixels (int imageIndex, Rectangle region) 1109 throws IOException 1110 { 1111 if (canReplacePixels(imageIndex)) 1112 throw new UnsupportedOperationException(); 1113 } 1114 1115 /** 1116 * Start writing an empty image to the end of the image output 1117 * stream. 1118 * 1119 * The writing that this method call starts is not complete until 1120 * endWriteEmpty is called. prepareWritetEmpty cannot be called 1121 * again until endWriteEmpty is called and calls to 1122 * prepareWriteEmpty and prepareInsertEmpty may not be intersperced. 1123 * 1124 * @param streamMetadata metadata associated with the stream, or null 1125 * @param imageType the image type specifier 1126 * @param width the image width 1127 * @param height the image height 1128 * @param imageMetadata the image metadata, or null 1129 * @param thumbnails a list of thumbnails, or null 1130 * @param param image write parameters, or null 1131 * 1132 * @exception IllegalStateException if output is null 1133 * @exception UnsupportedOperationException if writing empty images 1134 * is not supported 1135 * @exception IndexOutOfBoundsException if imageIndex is less than 1136 * -1 or greater than the last index in the current image list 1137 * @exception IllegalStateException if a previous call to 1138 * prepareInsertEmpty was made (without a terminating call to 1139 * endInsertEmpty) 1140 * @exception IllegalStateException if a previous call to 1141 * prepareWriteEmpty was made (without a terminating call to 1142 * endWriteEmpty) 1143 * @exception IllegalArgumentException if imageType is null or 1144 * thumbnails contain non-BufferedImage objects 1145 * @exception IllegalArgumentException if either width or height is 1146 * less than 1 1147 * @exception IOException if a write error occurs 1148 */ prepareWriteEmpty(IIOMetadata streamMetadata, ImageTypeSpecifier imageType, int width, int height, IIOMetadata imageMetadata, List<? extends BufferedImage> thumbnails, ImageWriteParam param)1149 public void prepareWriteEmpty (IIOMetadata streamMetadata, 1150 ImageTypeSpecifier imageType, 1151 int width, int height, 1152 IIOMetadata imageMetadata, 1153 List<? extends BufferedImage> thumbnails, 1154 ImageWriteParam param) 1155 throws IOException 1156 { 1157 if (!canWriteEmpty()) 1158 throw new UnsupportedOperationException(); 1159 } 1160 1161 /** 1162 * Start the writing of a sequence of images. 1163 * 1164 * @param streamMetadata the stream metadata, or null 1165 * 1166 * @exception IllegalStateException if output is null 1167 * @exception UnsupportedOperationException if writing sequences of 1168 * images is not supported 1169 * @exception IOException if a write error occurs 1170 */ prepareWriteSequence(IIOMetadata streamMetadata)1171 public void prepareWriteSequence (IIOMetadata streamMetadata) 1172 throws IOException 1173 { 1174 checkOutputSet(); 1175 if (!canWriteSequence()) 1176 throw new UnsupportedOperationException(); 1177 } 1178 1179 /** 1180 * Remove the image at the specified index from the output stream. 1181 * 1182 * @param imageIndex the frame index from which to remove the image 1183 * 1184 * @exception IllegalStateException if output is null 1185 * @exception UnsupportedOperationException if removing this image 1186 * is not supported 1187 * @exception IndexOutOfBoundsException if imageIndex is less than 0 1188 * or greater than the last index in the current image list 1189 * @exception IOException if a write error occurs 1190 */ removeImage(int imageIndex)1191 public void removeImage (int imageIndex) 1192 throws IOException 1193 { 1194 if (!canRemoveImage(imageIndex)) 1195 throw new UnsupportedOperationException(); 1196 } 1197 1198 /** 1199 * Replace the metadata associated with the image at the given 1200 * index. 1201 * 1202 * @param imageIndex the index of the image whose metadata should be 1203 * replaced 1204 * @param imageMetadata the metadata, or null 1205 * 1206 * @exception IllegalStateException if output is null 1207 * @exception UnsupportedOperationException if replacing this 1208 * image's metadata is not supported 1209 * @exception IndexOutOfBoundsException if imageIndex is less than 0 1210 * or greater than the last index in the current image list 1211 * @exception IOException if a write error occurs 1212 */ replaceImageMetadata(int imageIndex, IIOMetadata imageMetadata)1213 public void replaceImageMetadata (int imageIndex, IIOMetadata imageMetadata) 1214 throws IOException 1215 { 1216 if (!canReplaceImageMetadata(imageIndex)) 1217 throw new UnsupportedOperationException(); 1218 } 1219 1220 /** 1221 * Replace a region of an image in the output stream with a portion 1222 * of the given rendered image. The image data must be of the same 1223 * type as that in the output stream. The destination region is 1224 * given by the image writing parameters and the source region is 1225 * the one given to prepareReplacePixels. 1226 * 1227 * @param image the rendered image with which to overwrite the image 1228 * region in the stream 1229 * @param param the image writing parameters 1230 * 1231 * @exception IllegalStateException if output is null 1232 * @exception UnsupportedOperationException if replacing pixels is 1233 * not supported 1234 * @exception IllegalStateException if prepareReplacePixels was not 1235 * called before this method was called 1236 * @exception IllegalArgumentException if image is null or if param 1237 * is null or if the overlap of the source and destination regions 1238 * contains no pixels or if the image types differ and no conversion 1239 * is possible 1240 * @exception IOException if a write error occurs 1241 */ replacePixels(RenderedImage image, ImageWriteParam param)1242 public void replacePixels (RenderedImage image, 1243 ImageWriteParam param) 1244 throws IOException 1245 { 1246 if (!canReplacePixels(0)) 1247 throw new UnsupportedOperationException(); 1248 } 1249 1250 /** 1251 * Replace a region of an image in the output stream with a portion 1252 * of the given raster data. The image data must be of the same 1253 * type as that in the output stream. The destination region is 1254 * given by the image writing parameters and the source region is 1255 * the one given to prepareReplacePixels. 1256 * 1257 * @param raster the raster data with which to overwrite the image 1258 * region in the stream 1259 * @param param the image writing parameters 1260 * 1261 * @exception IllegalStateException if output is null 1262 * @exception UnsupportedOperationException if replacing pixels is 1263 * not supported 1264 * @exception IllegalStateException if prepareReplacePixels was not 1265 * called before this method was called 1266 * @exception UnsupportedOperationException if raster data is not 1267 * supported 1268 * @exception IllegalArgumentException if raster is null or if param 1269 * is null or if the overlap of the source and destination regions 1270 * contains no pixels or if the image types differ and no conversion 1271 * is possible 1272 * @exception IOException if a write error occurs 1273 */ replacePixels(Raster raster, ImageWriteParam param)1274 public void replacePixels (Raster raster, ImageWriteParam param) 1275 throws IOException 1276 { 1277 if (!canReplacePixels(0)) 1278 throw new UnsupportedOperationException(); 1279 } 1280 1281 /** 1282 * Replace the metadata associated with this image stream. 1283 * 1284 * @param streamMetadata the stream metadata, or null 1285 * 1286 * @exception IllegalStateException if output is null 1287 * @exception UnsupportedOperationException if replacing the stream 1288 * metadata is not supported 1289 * @exception IOException if a write error occurs 1290 */ replaceStreamMetadata(IIOMetadata streamMetadata)1291 public void replaceStreamMetadata (IIOMetadata streamMetadata) 1292 throws IOException 1293 { 1294 if (!canReplaceStreamMetadata()) 1295 throw new UnsupportedOperationException(); 1296 } 1297 1298 /** 1299 * Write a rendered image to the output stream. 1300 * 1301 * @param image a rendered image containing image data to be written 1302 * 1303 * @exception IllegalStateException if output is null 1304 * @exception IllegalArgumentException if image is null 1305 * @exception IOException if a write error occurs 1306 */ write(RenderedImage image)1307 public void write (RenderedImage image) 1308 throws IOException 1309 { 1310 checkOutputSet(); 1311 write (null, new IIOImage(image, null, null), null); 1312 } 1313 1314 /** 1315 * Write a image data, metadata and thumbnails to the output stream. 1316 * 1317 * @param image image data, metadata and thumbnails to be written 1318 * 1319 * @exception IllegalStateException if output is null 1320 * @exception UnsupportedOperationException if image contains raster 1321 * data but this writer does not support rasters 1322 * @exception IllegalArgumentException if image is null 1323 * @exception IOException if a write error occurs 1324 */ write(IIOImage image)1325 public void write (IIOImage image) 1326 throws IOException 1327 { 1328 checkOutputSet(); 1329 write (null, image, null); 1330 } 1331 1332 /** 1333 * Insert an image into the output stream. Indices greater than the 1334 * specified index are incremented accordingly. Specifying an index 1335 * of -1 causes the image to be appended at the end of the current 1336 * image list. 1337 * 1338 * @param imageIndex the frame index at which to insert the image 1339 * @param image the image data, metadata and thumbnails to be 1340 * inserted 1341 * @param param image write parameters, or null 1342 * 1343 * @exception IllegalStateException if output is null 1344 * @exception UnsupportedOperationException if image insertion is 1345 * not supported 1346 * @exception IllegalArgumentException if image is null 1347 * @exception IndexOutOfBoundsException if imageIndex is less than 1348 * -1 or greater than the last index in the current image list 1349 * @exception UnsupportedOperationException if image contains raster 1350 * data but this writer does not support rasters 1351 * @exception IOException if a write error occurs 1352 */ writeInsert(int imageIndex, IIOImage image, ImageWriteParam param)1353 public void writeInsert (int imageIndex, IIOImage image, ImageWriteParam param) 1354 throws IOException 1355 { 1356 if (!canInsertImage(imageIndex)) 1357 throw new UnsupportedOperationException(); 1358 } 1359 1360 /** 1361 * Write a sequence of images, including thumbnails and metadata, to 1362 * the output stream. The output must have been set prior to this 1363 * method being called. Metadata associated with the stream may be 1364 * supplied, or it can be left null. IIOImage may contain raster 1365 * data if this writer supports rasters, or it will contain a 1366 * rendered image. Thumbnails are resized if need be. Image 1367 * writing parameters may be specified to affect writing, or may be 1368 * left null. 1369 * 1370 * @param streamMetadata metadata associated with this stream, or 1371 * null 1372 * @param image an IIOImage containing image data, metadata and 1373 * thumbnails to be written 1374 * @param param image writing parameters, or null 1375 * 1376 * @exception IllegalStateException if output is null 1377 * @exception UnsupportedOperationException if writing sequences of 1378 * images is not supported 1379 * @exception IllegalArgumentException if image is null 1380 * @exception UnsupportedOperationException if image contains raster 1381 * data but this writer does not support rasters 1382 * @exception IOException if a write error occurs 1383 */ writeToSequence(IIOImage image, ImageWriteParam param)1384 public void writeToSequence (IIOImage image, ImageWriteParam param) 1385 throws IOException 1386 { 1387 if (!canWriteSequence()) 1388 throw new UnsupportedOperationException(); 1389 } 1390 } 1391