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 }