001 /* ImageIO.java -- 002 Copyright (C) 2004, 2005 Free Software Foundation, Inc. 003 004 This file is part of GNU Classpath. 005 006 GNU Classpath is free software; you can redistribute it and/or modify 007 it under the terms of the GNU General Public License as published by 008 the Free Software Foundation; either version 2, or (at your option) 009 any later version. 010 011 GNU Classpath is distributed in the hope that it will be useful, but 012 WITHOUT ANY WARRANTY; without even the implied warranty of 013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 014 General Public License for more details. 015 016 You should have received a copy of the GNU General Public License 017 along with GNU Classpath; see the file COPYING. If not, write to the 018 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 019 02110-1301 USA. 020 021 Linking this library statically or dynamically with other modules is 022 making a combined work based on this library. Thus, the terms and 023 conditions of the GNU General Public License cover the whole 024 combination. 025 026 As a special exception, the copyright holders of this library give you 027 permission to link this library with independent modules to produce an 028 executable, regardless of the license terms of these independent 029 modules, and to copy and distribute the resulting executable under 030 terms of your choice, provided that you also meet, for each linked 031 independent module, the terms and conditions of the license of that 032 module. An independent module is a module which is not derived from 033 or based on this library. If you modify this library, you may extend 034 this exception to your version of the library, but you are not 035 obligated to do so. If you do not wish to do so, delete this 036 exception statement from your version. */ 037 038 039 package javax.imageio; 040 041 import java.awt.image.BufferedImage; 042 import java.awt.image.RenderedImage; 043 import java.io.File; 044 import java.io.FileInputStream; 045 import java.io.FileOutputStream; 046 import java.io.IOException; 047 import java.io.InputStream; 048 import java.io.OutputStream; 049 import java.net.URL; 050 import java.util.ArrayList; 051 import java.util.Collections; 052 import java.util.Iterator; 053 054 import javax.imageio.spi.IIORegistry; 055 import javax.imageio.spi.ImageInputStreamSpi; 056 import javax.imageio.spi.ImageOutputStreamSpi; 057 import javax.imageio.spi.ImageReaderSpi; 058 import javax.imageio.spi.ImageTranscoderSpi; 059 import javax.imageio.spi.ImageWriterSpi; 060 import javax.imageio.spi.ServiceRegistry; 061 import javax.imageio.stream.ImageInputStream; 062 import javax.imageio.stream.ImageOutputStream; 063 import javax.imageio.stream.MemoryCacheImageInputStream; 064 import javax.imageio.stream.MemoryCacheImageOutputStream; 065 066 /** 067 * An uninstantiable class that provides static methods for locating 068 * and using image readers and writers. 069 */ 070 public final class ImageIO 071 { 072 /** 073 * Construct an ImageIO. Private since ImageIO is not instantiable. 074 */ 075 private ImageIO() 076 { 077 } 078 079 private static final class ReaderFormatFilter implements ServiceRegistry.Filter 080 { 081 private String formatName; 082 083 public ReaderFormatFilter(String formatName) 084 { 085 this.formatName = formatName; 086 } 087 088 public boolean filter (Object provider) 089 { 090 if (provider instanceof ImageReaderSpi) 091 { 092 ImageReaderSpi spi = (ImageReaderSpi) provider; 093 String[] formatNames = spi.getFormatNames(); 094 095 for (int i = formatNames.length - 1; i >= 0; --i) 096 if (formatName.equals(formatNames[i])) 097 return true; 098 } 099 100 return false; 101 } 102 } 103 104 private static final class ReaderMIMETypeFilter implements ServiceRegistry.Filter 105 { 106 private String MIMEType; 107 108 public ReaderMIMETypeFilter(String MIMEType) 109 { 110 this.MIMEType = MIMEType; 111 } 112 113 public boolean filter(Object provider) 114 { 115 if (provider instanceof ImageReaderSpi) 116 { 117 ImageReaderSpi spi = (ImageReaderSpi) provider; 118 String[] mimetypes = spi.getMIMETypes(); 119 120 for (int i = mimetypes.length - 1; i >= 0; --i) 121 if (MIMEType.equals(mimetypes[i])) 122 return true; 123 } 124 125 return false; 126 } 127 } 128 129 private static final class ReaderObjectFilter implements ServiceRegistry.Filter 130 { 131 private Object object; 132 133 public ReaderObjectFilter(Object object) 134 { 135 this.object = object; 136 } 137 138 public boolean filter(Object provider) 139 { 140 if (provider instanceof ImageReaderSpi) 141 { 142 ImageReaderSpi spi = (ImageReaderSpi) provider; 143 144 try 145 { 146 if (spi.canDecodeInput(object)) 147 return true; 148 } 149 catch (IOException e) 150 { 151 // Return false in this case 152 } 153 } 154 return false; 155 } 156 } 157 158 private static final class ReaderSuffixFilter implements ServiceRegistry.Filter 159 { 160 private String fileSuffix; 161 162 public ReaderSuffixFilter(String fileSuffix) 163 { 164 this.fileSuffix = fileSuffix; 165 } 166 167 public boolean filter(Object provider) 168 { 169 if (provider instanceof ImageReaderSpi) 170 { 171 ImageReaderSpi spi = (ImageReaderSpi) provider; 172 String[] suffixes = spi.getFileSuffixes(); 173 174 for (int i = suffixes.length - 1; i >= 0; --i) 175 if (fileSuffix.equals(suffixes[i])) 176 return true; 177 } 178 179 return false; 180 } 181 } 182 183 private static final class WriterFormatFilter implements ServiceRegistry.Filter 184 { 185 private String formatName; 186 187 public WriterFormatFilter(String formatName) 188 { 189 this.formatName = formatName; 190 } 191 192 public boolean filter(Object provider) 193 { 194 if (provider instanceof ImageWriterSpi) 195 { 196 ImageWriterSpi spi = (ImageWriterSpi) provider; 197 String[] formatNames = spi.getFormatNames(); 198 199 for (int i = formatNames.length - 1; i >= 0; --i) 200 if (formatName.equals(formatNames[i])) 201 return true; 202 } 203 204 return false; 205 } 206 } 207 208 private static final class WriterMIMETypeFilter implements ServiceRegistry.Filter 209 { 210 private String MIMEType; 211 212 public WriterMIMETypeFilter(String MIMEType) 213 { 214 this.MIMEType = MIMEType; 215 } 216 217 public boolean filter(Object provider) 218 { 219 if (provider instanceof ImageWriterSpi) 220 { 221 ImageWriterSpi spi = (ImageWriterSpi) provider; 222 String[] mimetypes = spi.getMIMETypes(); 223 224 for (int i = mimetypes.length - 1; i >= 0; --i) 225 if (MIMEType.equals(mimetypes[i])) 226 return true; 227 } 228 229 return false; 230 } 231 } 232 233 private static final class WriterSuffixFilter implements ServiceRegistry.Filter 234 { 235 private String fileSuffix; 236 237 public WriterSuffixFilter(String fileSuffix) 238 { 239 this.fileSuffix = fileSuffix; 240 } 241 242 public boolean filter(Object provider) 243 { 244 if (provider instanceof ImageWriterSpi) 245 { 246 ImageWriterSpi spi = (ImageWriterSpi) provider; 247 String[] suffixes = spi.getFileSuffixes(); 248 249 for (int i = suffixes.length - 1; i >= 0; --i) 250 if (fileSuffix.equals(suffixes[i])) 251 return true; 252 } 253 254 return false; 255 } 256 } 257 258 private static final class WriterObjectFilter implements ServiceRegistry.Filter 259 { 260 private ImageTypeSpecifier type; 261 private String formatName; 262 263 public WriterObjectFilter(ImageTypeSpecifier type, 264 String formatName) 265 { 266 this.type = type; 267 this.formatName = formatName; 268 } 269 270 public boolean filter(Object provider) 271 { 272 if (provider instanceof ImageWriterSpi) 273 { 274 ImageWriterSpi spi = (ImageWriterSpi) provider; 275 276 if (spi.canEncodeImage(type)) 277 { 278 String[] formatNames = spi.getFormatNames(); 279 for (int i = formatNames.length - 1; i >= 0; --i) 280 if (formatName.equals(formatNames[i])) 281 return true; 282 } 283 } 284 285 return false; 286 } 287 } 288 289 private static final class TranscoderFilter implements ServiceRegistry.Filter 290 { 291 private ImageReader reader; 292 private ImageWriter writer; 293 294 public TranscoderFilter(ImageReader reader, 295 ImageWriter writer) 296 { 297 this.reader = reader; 298 this.writer = writer; 299 } 300 301 public boolean filter(Object provider) 302 { 303 if (provider instanceof ImageTranscoderSpi) 304 { 305 ImageTranscoderSpi spi = (ImageTranscoderSpi) provider; 306 307 if (spi.getReaderServiceProviderName().equals 308 (reader.getOriginatingProvider().getClass().getName()) 309 && spi.getWriterServiceProviderName().equals 310 (writer.getOriginatingProvider().getClass().getName())) 311 return true; 312 } 313 314 return false; 315 } 316 } 317 318 private static final class ImageReaderIterator 319 implements Iterator<ImageReader> 320 { 321 Iterator<ImageReaderSpi> it; 322 Object readerExtension; 323 324 public ImageReaderIterator(Iterator<ImageReaderSpi> it, 325 Object readerExtension) 326 { 327 this.it = it; 328 this.readerExtension = readerExtension; 329 } 330 331 public ImageReaderIterator(Iterator<ImageReaderSpi> it) 332 { 333 this.it = it; 334 } 335 336 public boolean hasNext() 337 { 338 return it.hasNext(); 339 } 340 341 public ImageReader next() 342 { 343 try 344 { 345 ImageReaderSpi spi = it.next(); 346 return (readerExtension == null 347 ? spi.createReaderInstance() 348 : spi.createReaderInstance(readerExtension)); 349 } 350 catch (IOException e) 351 { 352 return null; 353 } 354 } 355 356 public void remove() 357 { 358 throw new UnsupportedOperationException(); 359 } 360 } 361 362 private static final class ImageWriterIterator 363 implements Iterator<ImageWriter> 364 { 365 Iterator<ImageWriterSpi> it; 366 Object writerExtension; 367 368 public ImageWriterIterator(Iterator<ImageWriterSpi> it, 369 Object writerExtension) 370 { 371 this.it = it; 372 this.writerExtension = writerExtension; 373 } 374 375 public ImageWriterIterator(Iterator<ImageWriterSpi> it) 376 { 377 this.it = it; 378 } 379 380 public boolean hasNext() 381 { 382 return it.hasNext(); 383 } 384 385 public ImageWriter next() 386 { 387 try 388 { 389 ImageWriterSpi spi = it.next(); 390 return (writerExtension == null 391 ? spi.createWriterInstance() 392 : spi.createWriterInstance(writerExtension)); 393 } 394 catch (IOException e) 395 { 396 return null; 397 } 398 } 399 400 public void remove() 401 { 402 throw new UnsupportedOperationException(); 403 } 404 } 405 406 private static File cacheDirectory; 407 private static boolean useCache = true; 408 409 private static Iterator<ImageReader> getReadersByFilter(Class<ImageReaderSpi> type, 410 ServiceRegistry.Filter filter, 411 Object readerExtension) 412 { 413 try 414 { 415 Iterator<ImageReaderSpi> it 416 = getRegistry().getServiceProviders(type, filter, true); 417 return new ImageReaderIterator(it, readerExtension); 418 } 419 catch (IllegalArgumentException e) 420 { 421 return Collections.EMPTY_SET.iterator(); 422 } 423 } 424 425 private static Iterator<ImageWriter> getWritersByFilter(Class<ImageWriterSpi> type, 426 ServiceRegistry.Filter filter, 427 Object writerExtension) 428 { 429 try 430 { 431 Iterator<ImageWriterSpi> it 432 = getRegistry().getServiceProviders(type, filter, true); 433 return new ImageWriterIterator(it, writerExtension); 434 } 435 catch (IllegalArgumentException e) 436 { 437 return Collections.EMPTY_SET.iterator(); 438 } 439 } 440 441 /** 442 * Retrieve the current cache directory. 443 * 444 * @return the current cache directory or null if none is set. 445 */ 446 public static File getCacheDirectory() 447 { 448 return cacheDirectory; 449 } 450 451 /** 452 * Retrieve an iterator over all registered readers for the given 453 * format. 454 * 455 * @param formatName an infomal format name (e.g. "jpeg" or "bmp") 456 * 457 * @return an iterator over a collection of image readers 458 * 459 * @exception IllegalArgumentException if formatName is null 460 */ 461 public static Iterator<ImageReader> getImageReadersByFormatName(String formatName) 462 { 463 if (formatName == null) 464 throw new IllegalArgumentException("formatName may not be null"); 465 466 return getReadersByFilter(ImageReaderSpi.class, 467 new ReaderFormatFilter(formatName), 468 formatName); 469 } 470 471 /** 472 * Retrieve an iterator over all registered readers for the given 473 * MIME type. 474 * 475 * @param MIMEType a MIME specification for an image type 476 * (e.g. "image/jpeg" or "image/x-bmp") 477 * 478 * @return an iterator over a collection of image readers 479 * 480 * @exception IllegalArgumentException if MIMEType is null 481 */ 482 public static Iterator<ImageReader> getImageReadersByMIMEType(String MIMEType) 483 { 484 if (MIMEType == null) 485 throw new IllegalArgumentException("MIMEType may not be null"); 486 487 return getReadersByFilter(ImageReaderSpi.class, 488 new ReaderMIMETypeFilter(MIMEType), 489 MIMEType); 490 } 491 492 /** 493 * Retrieve an iterator over all registered readers for the given 494 * file suffix. 495 * 496 * @param fileSuffix an image file suffix (e.g. "jpg" or "bmp") 497 * 498 * @return an iterator over a collection of image readers 499 * 500 * @exception IllegalArgumentException if fileSuffix is null 501 */ 502 public static Iterator<ImageReader> getImageReadersBySuffix(String fileSuffix) 503 { 504 if (fileSuffix == null) 505 throw new IllegalArgumentException("formatName may not be null"); 506 507 return getReadersByFilter(ImageReaderSpi.class, 508 new ReaderSuffixFilter(fileSuffix), 509 fileSuffix); 510 } 511 512 /** 513 * Retrieve an iterator over all registered writers for the given 514 * format. 515 * 516 * @param formatName an infomal format name (e.g. "jpeg" or "bmp") 517 * 518 * @return an iterator over a collection of image writers 519 * 520 * @exception IllegalArgumentException if formatName is null 521 */ 522 public static Iterator<ImageWriter> getImageWritersByFormatName(String formatName) 523 { 524 if (formatName == null) 525 throw new IllegalArgumentException("formatName may not be null"); 526 527 return getWritersByFilter(ImageWriterSpi.class, 528 new WriterFormatFilter(formatName), 529 formatName); 530 } 531 532 /** 533 * Retrieve an iterator over all registered writers for the given 534 * MIME type. 535 * 536 * @param MIMEType a MIME specification for an image type 537 * (e.g. "image/jpeg" or "image/x-bmp") 538 * 539 * @return an iterator over a collection of image writers 540 * 541 * @exception IllegalArgumentException if MIMEType is null 542 */ 543 public static Iterator<ImageWriter> getImageWritersByMIMEType(String MIMEType) 544 { 545 if (MIMEType == null) 546 throw new IllegalArgumentException("MIMEType may not be null"); 547 548 return getWritersByFilter(ImageWriterSpi.class, 549 new WriterMIMETypeFilter(MIMEType), 550 MIMEType); 551 } 552 553 /** 554 * Retrieve an iterator over all registered writers for the given 555 * file suffix. 556 * 557 * @param fileSuffix an image file suffix (e.g. "jpg" or "bmp") 558 * 559 * @return an iterator over a collection of image writers 560 * 561 * @exception IllegalArgumentException if fileSuffix is null 562 */ 563 public static Iterator<ImageWriter> getImageWritersBySuffix(String fileSuffix) 564 { 565 if (fileSuffix == null) 566 throw new IllegalArgumentException("fileSuffix may not be null"); 567 568 return getWritersByFilter(ImageWriterSpi.class, 569 new WriterSuffixFilter(fileSuffix), 570 fileSuffix); 571 } 572 573 /** 574 * Retrieve all the informal format names supported by the 575 * collection of registered image readers. 576 * 577 * @return an array of format names 578 */ 579 public static String[] getReaderFormatNames() 580 { 581 try 582 { 583 Iterator it = 584 getRegistry().getServiceProviders(ImageReaderSpi.class, true); 585 ArrayList result = new ArrayList(); 586 587 while (it.hasNext()) 588 { 589 ImageReaderSpi spi = (ImageReaderSpi) it.next(); 590 String[] names = spi.getFormatNames(); 591 592 for (int i = names.length - 1; i >= 0; --i) 593 result.add(names[i]); 594 } 595 596 return (String[]) result.toArray(new String[result.size()]); 597 } 598 catch (IllegalArgumentException e) 599 { 600 return new String[0]; 601 } 602 } 603 604 /** 605 * Retrieve all the MIME types supported by the collection of 606 * registered image readers. 607 * 608 * @return an array of MIME types 609 */ 610 public static String[] getReaderMIMETypes() 611 { 612 try 613 { 614 Iterator it = 615 getRegistry().getServiceProviders(ImageReaderSpi.class, true); 616 ArrayList result = new ArrayList(); 617 618 while (it.hasNext()) 619 { 620 ImageReaderSpi spi = (ImageReaderSpi) it.next(); 621 String[] names = spi.getMIMETypes(); 622 623 for (int i = names.length - 1; i >= 0; --i) 624 result.add(names[i]); 625 } 626 627 return (String[]) result.toArray(new String[result.size()]); 628 } 629 catch (IllegalArgumentException e) 630 { 631 return new String[0]; 632 } 633 } 634 635 private static IIORegistry getRegistry() 636 { 637 return IIORegistry.getDefaultInstance(); 638 } 639 640 /** 641 * Check whether or not an on-disk cache is used for image input and 642 * output streams. 643 * 644 * @return true if an on-disk cache is available, false otherwise 645 */ 646 public static boolean getUseCache() 647 { 648 return useCache; 649 } 650 651 /** 652 * Retrieve all the informal format names supported by the 653 * collection of registered image writers. 654 * 655 * @return an array of format names 656 */ 657 public static String[] getWriterFormatNames() 658 { 659 try 660 { 661 Iterator it = 662 getRegistry().getServiceProviders(ImageWriterSpi.class, true); 663 ArrayList result = new ArrayList(); 664 665 while (it.hasNext()) 666 { 667 ImageWriterSpi spi = (ImageWriterSpi) it.next(); 668 String[] names = spi.getFormatNames(); 669 670 for (int i = names.length - 1; i >= 0; --i) 671 result.add(names[i]); 672 } 673 674 return (String[]) result.toArray(new String[result.size()]); 675 } 676 catch (IllegalArgumentException e) 677 { 678 return new String[0]; 679 } 680 } 681 682 /** 683 * Retrieve all the MIME types supported by the collection of 684 * registered image writers. 685 * 686 * @return an array of MIME types 687 */ 688 public static String[] getWriterMIMETypes() 689 { 690 try 691 { 692 Iterator it = 693 getRegistry().getServiceProviders(ImageWriterSpi.class, true); 694 ArrayList result = new ArrayList(); 695 696 while (it.hasNext()) 697 { 698 ImageWriterSpi spi = (ImageWriterSpi) it.next(); 699 String[] names = spi.getMIMETypes(); 700 701 for (int i = names.length - 1; i >= 0; --i) 702 result.add(names[i]); 703 } 704 705 return (String[]) result.toArray(new String[result.size()]); 706 } 707 catch (IllegalArgumentException e) 708 { 709 return new String[0]; 710 } 711 } 712 713 /** 714 * Rescans the application classpath for ImageIO service providers 715 * and registers them. 716 */ 717 public static void scanForPlugins() 718 { 719 IIORegistry.getDefaultInstance().registerApplicationClasspathSpis(); 720 } 721 722 /** 723 * Set the directory to be used for caching image data. A null 724 * argument means to use the default system temporary directory. 725 * This cache directory is only used if getUseCache returns true. 726 * 727 * @param cacheDirectory the directory where image data should be 728 * cached 729 * 730 * @exception IllegalArgumentException if cacheDirectory is not a 731 * directory 732 */ 733 public static void setCacheDirectory(File cacheDirectory) 734 { 735 // FIXME: add SecurityManager call 736 if (cacheDirectory != null) 737 { 738 if (!cacheDirectory.isDirectory()) 739 throw new IllegalArgumentException("cacheDirectory must be a directory"); 740 741 cacheDirectory.canWrite(); 742 } 743 744 ImageIO.cacheDirectory = cacheDirectory; 745 } 746 747 /** 748 * Control whether or not an on-disk cache is used. This cache is 749 * used to store input or output data from an image data stream when 750 * data in the stream needs to be re-processed. 751 * 752 * If useCache is false the cache will be stored in memory. Doing 753 * so eliminates file creation and deletion overhead. The default 754 * is to use an on-disk cache. 755 * 756 * @param useCache true to use an on-disk cache, false otherwise 757 */ 758 public static void setUseCache(boolean useCache) 759 { 760 ImageIO.useCache = useCache; 761 } 762 763 /** 764 * Write an image to a file using a registered writer that supports 765 * the given format, overwriting the file if it already exists. 766 * 767 * @param im the image data to write 768 * @param formatName an informal description of the output format 769 * @param output the file to which the image will be written 770 * 771 * @return false if no registered writer supports the given format, 772 * true otherwise 773 * 774 * @exception IllegalArgumentException if any argument is null 775 * @exception IOException if a writing error occurs 776 */ 777 public static boolean write(RenderedImage im, 778 String formatName, 779 File output) 780 throws IOException 781 { 782 if (im == null || formatName == null || output == null) 783 throw new IllegalArgumentException ("null argument"); 784 785 return write(im, formatName, new FileOutputStream(output)); 786 } 787 788 /** 789 * Write an image to an output stream using a registered writer that 790 * supports the given format. 791 * 792 * @param im the image data to write 793 * @param formatName an informal description of the output format 794 * @param output the output stream to which the image will be 795 * written 796 * 797 * @return false if no registered writer supports the given format, 798 * true otherwise 799 * 800 * @exception IllegalArgumentException if any argument is null 801 * @exception IOException if a writing error occurs 802 */ 803 public static boolean write(RenderedImage im, 804 String formatName, 805 OutputStream output) 806 throws IOException 807 { 808 if (im == null || formatName == null || output == null) 809 throw new IllegalArgumentException ("null argument"); 810 811 return write(im, formatName, new MemoryCacheImageOutputStream(output)); 812 } 813 814 /** 815 * Write an image to an ImageOutputStream using a registered writer 816 * that supports the given format. Image data is written starting 817 * at the ImageOutputStream's current stream pointer, overwriting 818 * any existing data. 819 * 820 * @param im the image data to write 821 * @param formatName an informal description of the output format 822 * @param output the image output stream to which the image will be 823 * written 824 * 825 * @return false if no registered writer supports the given format, 826 * true otherwise 827 * 828 * @exception IllegalArgumentException if any argument is null 829 * @exception IOException if a writing error occurs 830 */ 831 public static boolean write(RenderedImage im, 832 String formatName, 833 ImageOutputStream output) 834 throws IOException 835 { 836 if (im == null || formatName == null || output == null) 837 throw new IllegalArgumentException ("null argument"); 838 839 Iterator writers = getImageWritersByFormatName(formatName); 840 IIOImage img = new IIOImage(im, null, null); 841 while (writers.hasNext()) 842 { 843 ImageWriter w = (ImageWriter) writers.next(); 844 try 845 { 846 w.setOutput(output); 847 } 848 catch (IllegalArgumentException e) 849 { 850 continue; 851 } 852 853 w.write(null, img, null); 854 output.close(); 855 return true; 856 } 857 return false; 858 } 859 860 /** 861 * Create a buffered image from an image input stream. An image 862 * reader that supports the given image data is automatically 863 * selected from the collection of registered readers. If no 864 * registered reader can handle the input format, null is returned. 865 * 866 * @param stream the image input stream from which to read image 867 * data 868 * 869 * @return a new buffered image created from the given image data, 870 * or null 871 * 872 * @exception IllegalArgumentException if stream is null 873 * @exception IOException if a reading error occurs 874 */ 875 public static BufferedImage read(ImageInputStream stream) 876 throws IOException 877 { 878 if (stream == null) 879 throw new IllegalArgumentException("null argument"); 880 881 Iterator providers = getRegistry().getServiceProviders(ImageReaderSpi.class, true); 882 while (providers.hasNext()) 883 { 884 ImageReaderSpi spi = (ImageReaderSpi) providers.next(); 885 if (spi.canDecodeInput(stream)) 886 { 887 ImageReader reader = spi.createReaderInstance(); 888 reader.setInput(stream); 889 return reader.read(0, null); 890 } 891 } 892 return null; 893 } 894 895 /** 896 * Create a buffered image from a URL. An image reader that 897 * supports the given image data is automatically selected from the 898 * collection of registered readers. If no registered reader can 899 * handle the input format, null is returned. 900 * 901 * The image data will be cached in the current cache directory if 902 * caching is enabled. 903 * 904 * This method does not locate readers that read data directly from 905 * a URL. To locate such readers manually, use IIORegistry and 906 * ImageReaderSpi. 907 * 908 * @param input the URL from which to retrieve the image file 909 * 910 * @return a new buffered image created from the given image URL, or 911 * null 912 * 913 * @exception IllegalArgumentException if input is null 914 * @exception IOException if a reading error occurs 915 */ 916 public static BufferedImage read(URL input) 917 throws IOException 918 { 919 if (input == null) 920 throw new IllegalArgumentException("null argument"); 921 922 return read(input.openStream()); 923 } 924 925 /** 926 * Create a buffered image from an input stream. An image reader 927 * that supports the given image data is automatically selected from 928 * the collection of registered readers. If no registered reader 929 * can handle the input format, null is returned. 930 * 931 * The image data will be cached in the current cache directory if 932 * caching is enabled. 933 * 934 * This method does not locate readers that read data directly from 935 * an input stream. To locate such readers manually, use 936 * IIORegistry and ImageReaderSpi. 937 * 938 * @param input the input stream from which to read the image data 939 * 940 * @return a new buffered image created from the given input stream, 941 * or null 942 * 943 * @exception IllegalArgumentException if input is null 944 * @exception IOException if a reading error occurs 945 */ 946 public static BufferedImage read(InputStream input) 947 throws IOException 948 { 949 if (input == null) 950 throw new IllegalArgumentException("null argument"); 951 952 return read(new MemoryCacheImageInputStream(input)); 953 } 954 955 /** 956 * Create a buffered image from a file. An image reader that 957 * supports the given image data is automatically selected from the 958 * collection of registered readers. If no registered reader can 959 * handle the input format, null is returned. 960 * 961 * The image data will be cached in the current cache directory if 962 * caching is enabled. 963 * 964 * This method does not locate readers that read data directly from 965 * a file. To locate such readers manually, use IIORegistry and 966 * ImageReaderSpi. 967 * 968 * @param input the file from which to read image data 969 * 970 * @return a new buffered image created from the given image file, 971 * or null 972 * 973 * @exception IllegalArgumentException if input is null 974 * @exception IOException if a reading error occurs 975 */ 976 public static BufferedImage read(File input) 977 throws IOException 978 { 979 if (input == null) 980 throw new IllegalArgumentException("null argument"); 981 982 return read(new FileInputStream(input)); 983 } 984 985 /** 986 * Create an image input stream from the given object. The 987 * collection of ImageInputStreamSpis registered with the 988 * IIORegistry is searched for an image input stream that can take 989 * input from the given object. null is returned if no such SPI is 990 * registered. 991 * 992 * The image data will be cached in the current cache directory if 993 * caching is enabled. 994 * 995 * @param input an object from which to read image data 996 * 997 * @return an ImageInputStream that can read data from input, or 998 * null 999 * 1000 * @exception IllegalArgumentException if input is null 1001 * @exception IOException if caching is required but not enabled 1002 */ 1003 public static ImageInputStream createImageInputStream (Object input) 1004 throws IOException 1005 { 1006 if (input == null) 1007 throw new IllegalArgumentException ("null argument"); 1008 1009 Iterator spis = getRegistry().getServiceProviders 1010 (ImageInputStreamSpi.class, true); 1011 1012 ImageInputStreamSpi foundSpi = null; 1013 1014 while(spis.hasNext()) 1015 { 1016 ImageInputStreamSpi spi = (ImageInputStreamSpi) spis.next(); 1017 1018 if (input.getClass().equals(spi.getInputClass())) 1019 { 1020 foundSpi = spi; 1021 break; 1022 } 1023 } 1024 1025 return foundSpi == null ? null : 1026 foundSpi.createInputStreamInstance (input, 1027 getUseCache(), 1028 getCacheDirectory()); 1029 } 1030 1031 /** 1032 * Create an image output stream from the given object. The 1033 * collection of ImageOutputStreamSpis registered with the 1034 * IIORegistry is searched for an image output stream that can send 1035 * output to the given object. null is returned if no such SPI is 1036 * registered. 1037 * 1038 * The image data will be cached in the current cache directory if 1039 * caching is enabled. 1040 * 1041 * @param output an object to which to write image data 1042 * 1043 * @return an ImageOutputStream that can send data to output, or 1044 * null 1045 * 1046 * @exception IllegalArgumentException if output is null 1047 * @exception IOException if caching is required but not enabled 1048 */ 1049 public static ImageOutputStream createImageOutputStream (Object output) 1050 throws IOException 1051 { 1052 if (output == null) 1053 throw new IllegalArgumentException ("null argument"); 1054 1055 Iterator spis = getRegistry().getServiceProviders 1056 (ImageOutputStreamSpi.class, true); 1057 1058 ImageOutputStreamSpi foundSpi = null; 1059 1060 while(spis.hasNext()) 1061 { 1062 ImageOutputStreamSpi spi = (ImageOutputStreamSpi) spis.next(); 1063 1064 if (output.getClass().equals(spi.getOutputClass())) 1065 { 1066 foundSpi = spi; 1067 break; 1068 } 1069 } 1070 1071 return foundSpi == null ? null : 1072 foundSpi.createOutputStreamInstance (output, 1073 getUseCache(), 1074 getCacheDirectory()); 1075 } 1076 1077 /** 1078 * Retrieve an image reader corresponding to an image writer, or 1079 * null if writer is not registered or if no corresponding reader is 1080 * registered. 1081 * 1082 * @param writer a registered image writer 1083 * 1084 * @return an image reader corresponding to writer, or null 1085 * 1086 * @exception IllegalArgumentException if writer is null 1087 */ 1088 public static ImageReader getImageReader (ImageWriter writer) 1089 { 1090 if (writer == null) 1091 throw new IllegalArgumentException ("null argument"); 1092 1093 ImageWriterSpi spi = writer.getOriginatingProvider(); 1094 1095 String[] readerSpiNames = spi.getImageReaderSpiNames(); 1096 1097 ImageReader r = null; 1098 1099 if (readerSpiNames != null) 1100 { 1101 try 1102 { 1103 Class readerClass = Class.forName (readerSpiNames[0]); 1104 r = (ImageReader) readerClass.newInstance (); 1105 } 1106 catch (Exception e) 1107 { 1108 return null; 1109 } 1110 } 1111 return r; 1112 } 1113 1114 /** 1115 * Retrieve an iterator over the collection of registered image 1116 * readers that support reading data from the given object. 1117 * 1118 * @param input the object for which to retrieve image readers 1119 * 1120 * @return an iterator over a collection of image readers 1121 */ 1122 public static Iterator<ImageReader> getImageReaders (Object input) 1123 { 1124 if (input == null) 1125 throw new IllegalArgumentException ("null argument"); 1126 1127 Iterator<ImageReaderSpi> spiIterator 1128 = getRegistry().getServiceProviders (ImageReaderSpi.class, 1129 new ReaderObjectFilter(input), 1130 true); 1131 return new ImageReaderIterator(spiIterator); 1132 } 1133 1134 /** 1135 * Retrieve an iterator over the collection of registered image 1136 * writers that support writing images of the given type and in the 1137 * given format. 1138 * 1139 * @param type the output image's colour and sample models 1140 * @param formatName the output image format 1141 * 1142 * @return an iterator over a collection of image writers 1143 */ 1144 public static Iterator<ImageWriter> getImageWriters (ImageTypeSpecifier type, 1145 String formatName) 1146 { 1147 if (type == null || formatName == null) 1148 throw new IllegalArgumentException ("null argument"); 1149 1150 final Iterator<ImageWriterSpi> spiIterator 1151 = getRegistry().getServiceProviders (ImageWriterSpi.class, 1152 new WriterObjectFilter(type, 1153 formatName), 1154 true); 1155 return new ImageWriterIterator(spiIterator); 1156 } 1157 1158 /** 1159 * Retrieve an image writer corresponding to an image reader, or 1160 * null if reader is not registered or if no corresponding writer is 1161 * registered. This method is useful for preserving metadata 1162 * without needing to understand its format, since the returned 1163 * writer will be able to write, unchanged, the metadata passed to 1164 * it by the reader. 1165 * 1166 * @param reader a registered image reader 1167 * 1168 * @return an image writer corresponding to reader, or null 1169 * 1170 * @exception IllegalArgumentException if reader is null 1171 */ 1172 public static ImageWriter getImageWriter (ImageReader reader) 1173 { 1174 if (reader == null) 1175 throw new IllegalArgumentException ("null argument"); 1176 1177 ImageReaderSpi spi = reader.getOriginatingProvider(); 1178 1179 String[] writerSpiNames = spi.getImageWriterSpiNames(); 1180 1181 ImageWriter w = null; 1182 1183 if (writerSpiNames != null) 1184 { 1185 try 1186 { 1187 Class writerClass = Class.forName (writerSpiNames[0]); 1188 w = (ImageWriter) writerClass.newInstance (); 1189 } 1190 catch (Exception e) 1191 { 1192 return null; 1193 } 1194 } 1195 return w; 1196 } 1197 1198 /** 1199 * Retrieve an iterator over a collection of image transcoders that 1200 * support transcoding from the given image reader's metadata format 1201 * to the given writer's metadata format. 1202 * 1203 * @param reader an image reader 1204 * @param writer an image writer 1205 * 1206 * @return an iterator over a collection of image transcoders 1207 * 1208 * @exception IllegalArgumentException if either reader or writer is 1209 * null 1210 */ 1211 public static Iterator<ImageTranscoder> getImageTranscoders (ImageReader reader, 1212 ImageWriter writer) 1213 { 1214 if (reader == null || writer == null) 1215 throw new IllegalArgumentException ("null argument"); 1216 1217 final Iterator<ImageTranscoderSpi> spiIterator 1218 = getRegistry().getServiceProviders (ImageTranscoderSpi.class, 1219 new TranscoderFilter (reader, 1220 writer), 1221 true); 1222 return new Iterator<ImageTranscoder>() 1223 { 1224 public boolean hasNext() 1225 { 1226 return spiIterator.hasNext(); 1227 } 1228 1229 public ImageTranscoder next() 1230 { 1231 return spiIterator.next().createTranscoderInstance(); 1232 } 1233 1234 public void remove() 1235 { 1236 throw new UnsupportedOperationException(); 1237 } 1238 }; 1239 } 1240 }