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 }