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 w.dispose(); 855 output.close(); 856 return true; 857 } 858 return false; 859 } 860 861 /** 862 * Create a buffered image from an image input stream. An image 863 * reader that supports the given image data is automatically 864 * selected from the collection of registered readers. If no 865 * registered reader can handle the input format, null is returned. 866 * 867 * @param stream the image input stream from which to read image 868 * data 869 * 870 * @return a new buffered image created from the given image data, 871 * or null 872 * 873 * @exception IllegalArgumentException if stream is null 874 * @exception IOException if a reading error occurs 875 */ 876 public static BufferedImage read(ImageInputStream stream) 877 throws IOException 878 { 879 if (stream == null) 880 throw new IllegalArgumentException("null argument"); 881 882 Iterator providers = getRegistry().getServiceProviders(ImageReaderSpi.class, true); 883 while (providers.hasNext()) 884 { 885 ImageReaderSpi spi = (ImageReaderSpi) providers.next(); 886 if (spi.canDecodeInput(stream)) 887 { 888 ImageReader reader = spi.createReaderInstance(); 889 reader.setInput(stream); 890 return reader.read(0, null); 891 } 892 } 893 return null; 894 } 895 896 /** 897 * Create a buffered image from a URL. An image reader that 898 * supports the given image data is automatically selected from the 899 * collection of registered readers. If no registered reader can 900 * handle the input format, null is returned. 901 * 902 * The image data will be cached in the current cache directory if 903 * caching is enabled. 904 * 905 * This method does not locate readers that read data directly from 906 * a URL. To locate such readers manually, use IIORegistry and 907 * ImageReaderSpi. 908 * 909 * @param input the URL from which to retrieve the image file 910 * 911 * @return a new buffered image created from the given image URL, or 912 * null 913 * 914 * @exception IllegalArgumentException if input is null 915 * @exception IOException if a reading error occurs 916 */ 917 public static BufferedImage read(URL input) 918 throws IOException 919 { 920 if (input == null) 921 throw new IllegalArgumentException("null argument"); 922 923 return read(input.openStream()); 924 } 925 926 /** 927 * Create a buffered image from an input stream. An image reader 928 * that supports the given image data is automatically selected from 929 * the collection of registered readers. If no registered reader 930 * can handle the input format, null is returned. 931 * 932 * The image data will be cached in the current cache directory if 933 * caching is enabled. 934 * 935 * This method does not locate readers that read data directly from 936 * an input stream. To locate such readers manually, use 937 * IIORegistry and ImageReaderSpi. 938 * 939 * @param input the input stream from which to read the image data 940 * 941 * @return a new buffered image created from the given input stream, 942 * or null 943 * 944 * @exception IllegalArgumentException if input is null 945 * @exception IOException if a reading error occurs 946 */ 947 public static BufferedImage read(InputStream input) 948 throws IOException 949 { 950 if (input == null) 951 throw new IllegalArgumentException("null argument"); 952 953 return read(new MemoryCacheImageInputStream(input)); 954 } 955 956 /** 957 * Create a buffered image from a file. An image reader that 958 * supports the given image data is automatically selected from the 959 * collection of registered readers. If no registered reader can 960 * handle the input format, null is returned. 961 * 962 * The image data will be cached in the current cache directory if 963 * caching is enabled. 964 * 965 * This method does not locate readers that read data directly from 966 * a file. To locate such readers manually, use IIORegistry and 967 * ImageReaderSpi. 968 * 969 * @param input the file from which to read image data 970 * 971 * @return a new buffered image created from the given image file, 972 * or null 973 * 974 * @exception IllegalArgumentException if input is null 975 * @exception IOException if a reading error occurs 976 */ 977 public static BufferedImage read(File input) 978 throws IOException 979 { 980 if (input == null) 981 throw new IllegalArgumentException("null argument"); 982 983 return read(new FileInputStream(input)); 984 } 985 986 /** 987 * Create an image input stream from the given object. The 988 * collection of ImageInputStreamSpis registered with the 989 * IIORegistry is searched for an image input stream that can take 990 * input from the given object. null is returned if no such SPI is 991 * registered. 992 * 993 * The image data will be cached in the current cache directory if 994 * caching is enabled. 995 * 996 * @param input an object from which to read image data 997 * 998 * @return an ImageInputStream that can read data from input, or 999 * null 1000 * 1001 * @exception IllegalArgumentException if input is null 1002 * @exception IOException if caching is required but not enabled 1003 */ 1004 public static ImageInputStream createImageInputStream (Object input) 1005 throws IOException 1006 { 1007 if (input == null) 1008 throw new IllegalArgumentException ("null argument"); 1009 1010 Iterator spis = getRegistry().getServiceProviders 1011 (ImageInputStreamSpi.class, true); 1012 1013 ImageInputStreamSpi foundSpi = null; 1014 1015 while(spis.hasNext()) 1016 { 1017 ImageInputStreamSpi spi = (ImageInputStreamSpi) spis.next(); 1018 1019 if (input.getClass().equals(spi.getInputClass())) 1020 { 1021 foundSpi = spi; 1022 break; 1023 } 1024 } 1025 1026 return foundSpi == null ? null : 1027 foundSpi.createInputStreamInstance (input, 1028 getUseCache(), 1029 getCacheDirectory()); 1030 } 1031 1032 /** 1033 * Create an image output stream from the given object. The 1034 * collection of ImageOutputStreamSpis registered with the 1035 * IIORegistry is searched for an image output stream that can send 1036 * output to the given object. null is returned if no such SPI is 1037 * registered. 1038 * 1039 * The image data will be cached in the current cache directory if 1040 * caching is enabled. 1041 * 1042 * @param output an object to which to write image data 1043 * 1044 * @return an ImageOutputStream that can send data to output, or 1045 * null 1046 * 1047 * @exception IllegalArgumentException if output is null 1048 * @exception IOException if caching is required but not enabled 1049 */ 1050 public static ImageOutputStream createImageOutputStream (Object output) 1051 throws IOException 1052 { 1053 if (output == null) 1054 throw new IllegalArgumentException ("null argument"); 1055 1056 Iterator spis = getRegistry().getServiceProviders 1057 (ImageOutputStreamSpi.class, true); 1058 1059 ImageOutputStreamSpi foundSpi = null; 1060 1061 while(spis.hasNext()) 1062 { 1063 ImageOutputStreamSpi spi = (ImageOutputStreamSpi) spis.next(); 1064 1065 if (output.getClass().equals(spi.getOutputClass())) 1066 { 1067 foundSpi = spi; 1068 break; 1069 } 1070 } 1071 1072 return foundSpi == null ? null : 1073 foundSpi.createOutputStreamInstance (output, 1074 getUseCache(), 1075 getCacheDirectory()); 1076 } 1077 1078 /** 1079 * Retrieve an image reader corresponding to an image writer, or 1080 * null if writer is not registered or if no corresponding reader is 1081 * registered. 1082 * 1083 * @param writer a registered image writer 1084 * 1085 * @return an image reader corresponding to writer, or null 1086 * 1087 * @exception IllegalArgumentException if writer is null 1088 */ 1089 public static ImageReader getImageReader (ImageWriter writer) 1090 { 1091 if (writer == null) 1092 throw new IllegalArgumentException ("null argument"); 1093 1094 ImageWriterSpi spi = writer.getOriginatingProvider(); 1095 1096 String[] readerSpiNames = spi.getImageReaderSpiNames(); 1097 1098 ImageReader r = null; 1099 1100 if (readerSpiNames != null) 1101 { 1102 try 1103 { 1104 Class readerClass = Class.forName (readerSpiNames[0]); 1105 r = (ImageReader) readerClass.newInstance (); 1106 } 1107 catch (Exception e) 1108 { 1109 return null; 1110 } 1111 } 1112 return r; 1113 } 1114 1115 /** 1116 * Retrieve an iterator over the collection of registered image 1117 * readers that support reading data from the given object. 1118 * 1119 * @param input the object for which to retrieve image readers 1120 * 1121 * @return an iterator over a collection of image readers 1122 */ 1123 public static Iterator<ImageReader> getImageReaders (Object input) 1124 { 1125 if (input == null) 1126 throw new IllegalArgumentException ("null argument"); 1127 1128 Iterator<ImageReaderSpi> spiIterator 1129 = getRegistry().getServiceProviders (ImageReaderSpi.class, 1130 new ReaderObjectFilter(input), 1131 true); 1132 return new ImageReaderIterator(spiIterator); 1133 } 1134 1135 /** 1136 * Retrieve an iterator over the collection of registered image 1137 * writers that support writing images of the given type and in the 1138 * given format. 1139 * 1140 * @param type the output image's colour and sample models 1141 * @param formatName the output image format 1142 * 1143 * @return an iterator over a collection of image writers 1144 */ 1145 public static Iterator<ImageWriter> getImageWriters (ImageTypeSpecifier type, 1146 String formatName) 1147 { 1148 if (type == null || formatName == null) 1149 throw new IllegalArgumentException ("null argument"); 1150 1151 final Iterator<ImageWriterSpi> spiIterator 1152 = getRegistry().getServiceProviders (ImageWriterSpi.class, 1153 new WriterObjectFilter(type, 1154 formatName), 1155 true); 1156 return new ImageWriterIterator(spiIterator); 1157 } 1158 1159 /** 1160 * Retrieve an image writer corresponding to an image reader, or 1161 * null if reader is not registered or if no corresponding writer is 1162 * registered. This method is useful for preserving metadata 1163 * without needing to understand its format, since the returned 1164 * writer will be able to write, unchanged, the metadata passed to 1165 * it by the reader. 1166 * 1167 * @param reader a registered image reader 1168 * 1169 * @return an image writer corresponding to reader, or null 1170 * 1171 * @exception IllegalArgumentException if reader is null 1172 */ 1173 public static ImageWriter getImageWriter (ImageReader reader) 1174 { 1175 if (reader == null) 1176 throw new IllegalArgumentException ("null argument"); 1177 1178 ImageReaderSpi spi = reader.getOriginatingProvider(); 1179 1180 String[] writerSpiNames = spi.getImageWriterSpiNames(); 1181 1182 ImageWriter w = null; 1183 1184 if (writerSpiNames != null) 1185 { 1186 try 1187 { 1188 Class writerClass = Class.forName (writerSpiNames[0]); 1189 w = (ImageWriter) writerClass.newInstance (); 1190 } 1191 catch (Exception e) 1192 { 1193 return null; 1194 } 1195 } 1196 return w; 1197 } 1198 1199 /** 1200 * Retrieve an iterator over a collection of image transcoders that 1201 * support transcoding from the given image reader's metadata format 1202 * to the given writer's metadata format. 1203 * 1204 * @param reader an image reader 1205 * @param writer an image writer 1206 * 1207 * @return an iterator over a collection of image transcoders 1208 * 1209 * @exception IllegalArgumentException if either reader or writer is 1210 * null 1211 */ 1212 public static Iterator<ImageTranscoder> getImageTranscoders (ImageReader reader, 1213 ImageWriter writer) 1214 { 1215 if (reader == null || writer == null) 1216 throw new IllegalArgumentException ("null argument"); 1217 1218 final Iterator<ImageTranscoderSpi> spiIterator 1219 = getRegistry().getServiceProviders (ImageTranscoderSpi.class, 1220 new TranscoderFilter (reader, 1221 writer), 1222 true); 1223 return new Iterator<ImageTranscoder>() 1224 { 1225 public boolean hasNext() 1226 { 1227 return spiIterator.hasNext(); 1228 } 1229 1230 public ImageTranscoder next() 1231 { 1232 return spiIterator.next().createTranscoderInstance(); 1233 } 1234 1235 public void remove() 1236 { 1237 throw new UnsupportedOperationException(); 1238 } 1239 }; 1240 } 1241 }