blob: e0d7ec9904d783e044b545bb24e3779bf2dbe7ff [file] [log] [blame]
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001/*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17/**
18 * @author Rustem V. Rafikov
19 * @version $Revision: 1.3 $
20 */
21
22package javax.imageio;
23
24import javax.imageio.stream.ImageInputStream;
25import javax.imageio.stream.ImageOutputStream;
26import javax.imageio.spi.*;
27import java.io.File;
28import java.io.IOException;
29import java.io.InputStream;
30import java.io.OutputStream;
31import java.util.Iterator;
32import java.util.Arrays;
33import java.awt.image.BufferedImage;
34import java.awt.image.RenderedImage;
35import java.net.URL;
36
37/**
38 * The ImageIO class provides static methods to perform reading and writing
39 * operations using registered ImageReader and ImageWriter objects.
40 *
41 * @since Android 1.0
42 */
43public final class ImageIO {
44
45 /**
46 * The constant registry.
47 */
48 private static final IIORegistry registry = IIORegistry.getDefaultInstance();
49
50 /**
51 * Instantiates a new ImageIO.
52 */
53 private ImageIO() {
54 }
55
56 /**
57 * Scans for plug-ins in the class path, loads spi classes, and registers
58 * them with the IIORegistry.
59 */
60 public static void scanForPlugins() {
61 throw new UnsupportedOperationException("Not supported yet");
62 }
63
64 /**
65 * Sets flag which indicates whether a cache file is used when creating
66 * ImageInputStreams and ImageOutputStreams or not.
67 *
68 * @param useCache
69 * the use cache flag.
70 */
71 public static void setUseCache(boolean useCache) {
72 throw new UnsupportedOperationException("Not supported yet");
73 }
74
75 /**
76 * Gets the flag which indicates whether a cache file is used when creating
77 * ImageInputStreams and ImageOutputStreams or not. This method returns the
78 * current value which is set by setUseCache method.
79 *
80 * @return the use cache flag.
81 */
82 public static boolean getUseCache() {
83 // TODO implement
84 return false;
85 }
86
87 /**
88 * Sets the cache directory.
89 *
90 * @param cacheDirectory
91 * the File which specifies a cache directory.
92 */
93 public static void setCacheDirectory(File cacheDirectory) {
94 throw new UnsupportedOperationException("Not supported yet");
95 }
96
97 /**
98 * Gets the directory where cache files are created, returned the file which
99 * is set by setCacheDirectory method, or null.
100 *
101 * @return the File object which is set by setCacheDirectory method, or
102 * null.
103 */
104 public static File getCacheDirectory() {
105 // TODO implement
106 // -- null indicates system-dep default temporary directory
107 return null;
108 }
109
110 /**
111 * Creates an ImageInputStream from the specified Object. The specified
112 * Object should obtain the input source such as File, or InputStream.
113 *
114 * @param input
115 * the input Object such as File, or InputStream.
116 * @return the ImageInputStream object, or null.
117 * @throws IOException
118 * if an I/O exception has occurred.
119 */
120 public static ImageInputStream createImageInputStream(Object input) throws IOException {
121
122 if (input == null) {
123 throw new IllegalArgumentException("input source cannot be NULL");
124 }
125
126 Iterator<ImageInputStreamSpi> it = registry.getServiceProviders(ImageInputStreamSpi.class,
127 true);
128
129 while (it.hasNext()) {
130 ImageInputStreamSpi spi = it.next();
131 if (spi.getInputClass().isInstance(input)) {
132 return spi.createInputStreamInstance(input);
133 }
134 }
135 return null;
136 }
137
138 /**
139 * Creates an ImageOutputStream using the specified Object. The specified
140 * Object should obtain the output source such as File, or OutputStream.
141 *
142 * @param output
143 * the output Object such as File, or OutputStream.
144 * @return the ImageOutputStream object, or null.
145 * @throws IOException
146 * if an I/O exception has occurred.
147 */
148 public static ImageOutputStream createImageOutputStream(Object output) throws IOException {
149 if (output == null) {
150 throw new IllegalArgumentException("output destination cannot be NULL");
151 }
152
153 Iterator<ImageOutputStreamSpi> it = registry.getServiceProviders(
154 ImageOutputStreamSpi.class, true);
155
156 while (it.hasNext()) {
157 ImageOutputStreamSpi spi = it.next();
158 if (spi.getOutputClass().isInstance(output)) {
159 // todo - use getUseCache and getCacheDir here
160 return spi.createOutputStreamInstance(output);
161 }
162 }
163 return null;
164 }
165
166 /**
167 * Gets the array of format names as String which can be decoded by
168 * registered ImageReader objects.
169 *
170 * @return the array of format names.
171 */
172 public static String[] getReaderFormatNames() {
173 throw new UnsupportedOperationException("Not supported yet");
174 }
175
176 /**
177 * Gets the array of MIME types as String which can be decoded by registered
178 * ImageReader objects.
179 *
180 * @return the array of MIME types.
181 */
182 public static String[] getReaderMIMETypes() {
183 throw new UnsupportedOperationException("Not supported yet");
184 }
185
186 /**
187 * Gets the Iterator of registered ImageReader which are able to decode an
188 * input data specified by input Object.
189 *
190 * @param input
191 * the input Object with encoded data such as ImageInputStream
192 * object.
193 * @return the Iterator of registered ImageReader.
194 */
195 public static Iterator<ImageReader> getImageReaders(Object input) {
196 if (input == null) {
197 throw new NullPointerException("input cannot be NULL");
198 }
199
200 Iterator<ImageReaderSpi> it = registry.getServiceProviders(ImageReaderSpi.class,
201 new CanReadFilter(input), true);
202
203 return new SpiIteratorToReadersIteratorWrapper(it);
204 }
205
206 /**
207 * Gets the Iterator of registered ImageReader which are able to decode the
208 * specified format.
209 *
210 * @param formatName
211 * the format name such as "jpeg", or "gif".
212 * @return the Iterator of registered ImageReader.
213 */
214 public static Iterator<ImageReader> getImageReadersByFormatName(String formatName) {
215 if (formatName == null) {
216 throw new NullPointerException("format name cannot be NULL");
217 }
218
219 Iterator<ImageReaderSpi> it = registry.getServiceProviders(ImageReaderSpi.class,
220 new FormatFilter(formatName), true);
221
222 return new SpiIteratorToReadersIteratorWrapper(it);
223 }
224
225 /**
226 * Gets the Iterator which lists the registered ImageReader objects that are
227 * able to decode files with the specified suffix.
228 *
229 * @param fileSuffix
230 * the file suffix such as "jpg".
231 * @return the Iterator of registered ImageReaders.
232 */
233 public static Iterator<ImageReader> getImageReadersBySuffix(String fileSuffix) {
234 if (fileSuffix == null) {
235 throw new NullPointerException("suffix cannot be NULL");
236 }
237 Iterator<ImageReaderSpi> it = registry.getServiceProviders(ImageReaderSpi.class,
238 new SuffixFilter(fileSuffix), true);
239
240 return new SpiIteratorToReadersIteratorWrapper(it);
241 }
242
243 /**
244 * Gets the Iterator of registered ImageReader objects that are able to
245 * decode files with the specified MIME type.
246 *
247 * @param MIMEType
248 * the MIME type such as "image/jpeg".
249 * @return the Iterator of registered ImageReaders.
250 */
251 public static Iterator<ImageReader> getImageReadersByMIMEType(String MIMEType) {
252 throw new UnsupportedOperationException("Not supported yet");
253 }
254
255 /**
256 * Gets an array of Strings giving the names of the formats supported by
257 * registered ImageWriter objects.
258 *
259 * @return the array of format names.
260 */
261 public static String[] getWriterFormatNames() {
262 throw new UnsupportedOperationException("Not supported yet");
263 }
264
265 /**
266 * Gets an array of Strings giving the MIME types of the formats supported
267 * by registered ImageWriter objects.
268 *
269 * @return the array of MIME types.
270 */
271 public static String[] getWriterMIMETypes() {
272 throw new UnsupportedOperationException("Not supported yet");
273 }
274
275 /**
276 * Gets the Iterator which lists the registered ImageReader objects that are
277 * able to encode the specified image format.
278 *
279 * @param formatName
280 * the image format name such as "jpeg".
281 * @return the Iterator of registered ImageWriter.
282 */
283 public static Iterator<ImageWriter> getImageWritersByFormatName(String formatName) {
284 if (formatName == null) {
285 throw new NullPointerException("format name cannot be NULL");
286 }
287
288 Iterator<ImageWriterSpi> it = registry.getServiceProviders(ImageWriterSpi.class,
289 new FormatFilter(formatName), true);
290
291 return new SpiIteratorToWritersIteratorWrapper(it);
292 }
293
294 /**
295 * Gets the Iterator which lists the registered ImageReader objects that are
296 * able to encode the specified suffix.
297 *
298 * @param fileSuffix
299 * the file suffix such as "jpg".
300 * @return the Iterator of registered ImageWriter.
301 */
302 public static Iterator<ImageWriter> getImageWritersBySuffix(String fileSuffix) {
303 if (fileSuffix == null) {
304 throw new NullPointerException("suffix cannot be NULL");
305 }
306 Iterator<ImageWriterSpi> it = registry.getServiceProviders(ImageWriterSpi.class,
307 new SuffixFilter(fileSuffix), true);
308 return new SpiIteratorToWritersIteratorWrapper(it);
309 }
310
311 /**
312 * Gets the Iterator which lists the registered ImageReader objects that are
313 * able to encode the specified MIME type.
314 *
315 * @param MIMEType
316 * the MIME type such as "image/jpeg".
317 * @return the Iterator of registered ImageWriter.
318 */
319 public static Iterator<ImageWriter> getImageWritersByMIMEType(String MIMEType) {
320 throw new UnsupportedOperationException("Not supported yet");
321 }
322
323 /**
324 * Gets an ImageWriter object which corresponds to the specified
325 * ImageReader, or returns null if the specified ImageReader is not
326 * registered.
327 *
328 * @param reader
329 * the specified ImageReader.
330 * @return the ImageWriter, or null.
331 */
332 public static ImageWriter getImageWriter(ImageReader reader) {
333 throw new UnsupportedOperationException("Not supported yet");
334 }
335
336 /**
337 * Gets an ImageReader object which corresponds to the specified
338 * ImageWriter, or returns null if the specified ImageWriter is not
339 * registered.
340 *
341 * @param writer
342 * the registered ImageWriter object.
343 * @return the ImageReader.
344 */
345 public static ImageReader getImageReader(ImageWriter writer) {
346 throw new UnsupportedOperationException("Not supported yet");
347 }
348
349 /**
350 * Gets the Iterator of ImageWriter objects which are able to encode images
351 * with the specified ImageTypeSpecifier and format.
352 *
353 * @param type
354 * the ImageTypeSpecifier, which defines layout.
355 * @param formatName
356 * the format name.
357 * @return the Iterator of ImageWriter objects.
358 */
359 public static Iterator<ImageWriter> getImageWriters(ImageTypeSpecifier type, String formatName) {
360 if (type == null) {
361 throw new NullPointerException("type cannot be NULL");
362 }
363
364 if (formatName == null) {
365 throw new NullPointerException("format name cannot be NULL");
366 }
367
368 Iterator<ImageWriterSpi> it = registry.getServiceProviders(ImageWriterSpi.class,
369 new FormatAndEncodeFilter(type, formatName), true);
370
371 return new SpiIteratorToWritersIteratorWrapper(it);
372 }
373
374 /**
375 * Gets the Iterator of registered ImageTranscoders which are able to
376 * transcode the metadata of the specified ImageReader object to a suitable
377 * object for encoding by the specified ImageWriter.
378 *
379 * @param reader
380 * the specified ImageReader.
381 * @param writer
382 * the specified ImageWriter.
383 * @return the Iterator of registered ImageTranscoders.
384 */
385 public static Iterator<ImageTranscoder> getImageTranscoders(ImageReader reader,
386 ImageWriter writer) {
387 throw new UnsupportedOperationException("Not supported yet");
388 }
389
390 /**
391 * Reads image data from the specified File and decodes it using the
392 * appropriate registered ImageReader object. The File is wrapped in an
393 * ImageInputStream.
394 *
395 * @param input
396 * the File to be read.
397 * @return the BufferedImage decoded from the specified File, or null.
398 * @throws IOException
399 * if an I/O exception has occurred.
400 */
401 public static BufferedImage read(File input) throws IOException {
402 if (input == null) {
403 throw new IllegalArgumentException("input == null!");
404 }
405
406 ImageInputStream stream = createImageInputStream(input);
407 return read(stream);
408 }
409
410 /**
411 * Reads image data from the specified InputStream and decodes it using an
412 * appropriate registered an ImageReader object.
413 *
414 * @param input
415 * the InputStream.
416 * @return the BufferedImage decoded from the specified InputStream, or
417 * null.
418 * @throws IOException
419 * if an I/O exception has occurred.
420 */
421 public static BufferedImage read(InputStream input) throws IOException {
422 if (input == null) {
423 throw new IllegalArgumentException("input == null!");
424 }
425
426 ImageInputStream stream = createImageInputStream(input);
427 return read(stream);
428 }
429
430 /**
431 * Reads image data from the specified URL and decodes it using the
432 * appropriate registered ImageReader object.
433 *
434 * @param input
435 * the URL to be read.
436 * @return the BufferedImage decoded from the specified URL, or null.
437 * @throws IOException
438 * if an I/O exception has occurred.
439 */
440 public static BufferedImage read(URL input) throws IOException {
441 if (input == null) {
442 throw new IllegalArgumentException("input == null!");
443 }
444
445 InputStream stream = input.openStream();
446 BufferedImage res = read(stream);
447 stream.close();
448
449 return res;
450 }
451
452 /**
453 * Reads image data from the specified ImageInputStream and decodes it using
454 * appropriate registered an ImageReader object.
455 *
456 * @param stream
457 * the ImageInputStream.
458 * @return the BufferedImage decoded from the specified ImageInputStream, or
459 * null.
460 * @throws IOException
461 * if an I/O exception has occurred.
462 */
463 public static BufferedImage read(ImageInputStream stream) throws IOException {
464 if (stream == null) {
465 throw new IllegalArgumentException("stream == null!");
466 }
467
468 Iterator<ImageReader> imageReaders = getImageReaders(stream);
469 if (!imageReaders.hasNext()) {
470 return null;
471 }
472
473 ImageReader reader = imageReaders.next();
474 reader.setInput(stream, false, true);
475 BufferedImage res = reader.read(0);
476 reader.dispose();
477
478 try {
479 stream.close();
480 } catch (IOException e) {
481 // Stream could be already closed, proceed silently in this case
482 }
483
484 return res;
485 }
486
487 /**
488 * Writes the specified image in the specified format (using an appropriate
489 * ImageWriter) to the specified ImageOutputStream.
490 *
491 * @param im
492 * the RenderedImage.
493 * @param formatName
494 * the format name.
495 * @param output
496 * the ImageOutputStream where Image to be written.
497 * @return true, if Image is written successfully, false otherwise.
498 * @throws IOException
499 * if an I/O exception has occurred.
500 */
501 public static boolean write(RenderedImage im, String formatName, ImageOutputStream output)
502 throws IOException {
503
504 if (im == null) {
505 throw new IllegalArgumentException("image cannot be NULL");
506 }
507 if (formatName == null) {
508 throw new IllegalArgumentException("format name cannot be NULL");
509 }
510 if (output == null) {
511 throw new IllegalArgumentException("output cannot be NULL");
512 }
513
514 Iterator<ImageWriter> it = getImageWriters(ImageTypeSpecifier.createFromRenderedImage(im),
515 formatName);
516 if (it.hasNext()) {
517 ImageWriter writer = it.next();
518 writer.setOutput(output);
519 writer.write(im);
520 output.flush();
521 writer.dispose();
522 return true;
523 }
524 return false;
525 }
526
527 /**
528 * Writes the specified image in the specified format (using an appropriate
529 * ImageWriter) to the specified File.
530 *
531 * @param im
532 * the RenderedImage.
533 * @param formatName
534 * the format name.
535 * @param output
536 * the output File where Image to be written.
537 * @return true, if Image is written successfully, false otherwise.
538 * @throws IOException
539 * if an I/O exception has occurred.
540 */
541 public static boolean write(RenderedImage im, String formatName, File output)
542 throws IOException {
543
544 if (output == null) {
545 throw new IllegalArgumentException("output cannot be NULL");
546 }
547
548 if (output.exists()) {
549 output.delete();
550 }
551
552 ImageOutputStream ios = createImageOutputStream(output);
553 boolean rt = write(im, formatName, ios);
554 ios.close();
555 return rt;
556 }
557
558 /**
559 * Writes the specified image in the specified format (using an appropriate
560 * ImageWriter) to the specified OutputStream.
561 *
562 * @param im
563 * the RenderedImage.
564 * @param formatName
565 * the format name.
566 * @param output
567 * the OutputStream where Image is to be written.
568 * @return true, if Image is written successfully, false otherwise.
569 * @throws IOException
570 * if an I/O exception has occurred.
571 */
572 public static boolean write(RenderedImage im, String formatName, OutputStream output)
573 throws IOException {
574
575 if (output == null) {
576 throw new IllegalArgumentException("output cannot be NULL");
577 }
578
579 ImageOutputStream ios = createImageOutputStream(output);
580 boolean rt = write(im, formatName, ios);
581 ios.close();
582 return rt;
583 }
584
585 /**
586 * Filter to match spi by format name.
587 */
588 static class FormatFilter implements ServiceRegistry.Filter {
589
590 /**
591 * The name.
592 */
593 private String name;
594
595 /**
596 * Instantiates a new format filter.
597 *
598 * @param name
599 * the name.
600 */
601 public FormatFilter(String name) {
602 this.name = name;
603 }
604
605 public boolean filter(Object provider) {
606 ImageReaderWriterSpi spi = (ImageReaderWriterSpi)provider;
607 return Arrays.asList(spi.getFormatNames()).contains(name);
608 }
609 }
610
611 /**
612 * Filter to match spi by format name and encoding possibility.
613 */
614 static class FormatAndEncodeFilter extends FormatFilter {
615
616 /**
617 * The type.
618 */
619 private ImageTypeSpecifier type;
620
621 /**
622 * Instantiates a new format and encode filter.
623 *
624 * @param type
625 * the type.
626 * @param name
627 * the name.
628 */
629 public FormatAndEncodeFilter(ImageTypeSpecifier type, String name) {
630 super(name);
631 this.type = type;
632 }
633
634 @Override
635 public boolean filter(Object provider) {
636 ImageWriterSpi spi = (ImageWriterSpi)provider;
637 return super.filter(provider) && spi.canEncodeImage(type);
638 }
639 }
640
641 /**
642 * Filter to match spi by suffix.
643 */
644 static class SuffixFilter implements ServiceRegistry.Filter {
645
646 /**
647 * The suf.
648 */
649 private String suf;
650
651 /**
652 * Instantiates a new suffix filter.
653 *
654 * @param suf
655 * the suf.
656 */
657 public SuffixFilter(String suf) {
658 this.suf = suf;
659 }
660
661 public boolean filter(Object provider) {
662 ImageReaderWriterSpi spi = (ImageReaderWriterSpi)provider;
663 return Arrays.asList(spi.getFileSuffixes()).contains(suf);
664 }
665 }
666
667 /**
668 * Filter to match spi by decoding possibility.
669 */
670 static class CanReadFilter implements ServiceRegistry.Filter {
671
672 /**
673 * The input.
674 */
675 private Object input;
676
677 /**
678 * Instantiates a new can read filter.
679 *
680 * @param input
681 * the input.
682 */
683 public CanReadFilter(Object input) {
684 this.input = input;
685 }
686
687 public boolean filter(Object provider) {
688 ImageReaderSpi spi = (ImageReaderSpi)provider;
689 try {
690 return spi.canDecodeInput(input);
691 } catch (IOException e) {
692 return false;
693 }
694 }
695 }
696
697 /**
698 * Wraps Spi's iterator to ImageWriter iterator.
699 */
700 static class SpiIteratorToWritersIteratorWrapper implements Iterator<ImageWriter> {
701
702 /**
703 * The backend.
704 */
705 private Iterator<ImageWriterSpi> backend;
706
707 /**
708 * Instantiates a new spi iterator to writers iterator wrapper.
709 *
710 * @param backend
711 * the backend.
712 */
713 public SpiIteratorToWritersIteratorWrapper(Iterator<ImageWriterSpi> backend) {
714 this.backend = backend;
715 }
716
717 /**
718 * Next.
719 *
720 * @return the image writer.
721 */
722 public ImageWriter next() {
723 try {
724 return backend.next().createWriterInstance();
725 } catch (IOException e) {
726 e.printStackTrace();
727 return null;
728 }
729 }
730
731 /**
732 * Checks for next.
733 *
734 * @return true, if successful.
735 */
736 public boolean hasNext() {
737 return backend.hasNext();
738 }
739
740 /**
741 * Removes the.
742 */
743 public void remove() {
744 throw new UnsupportedOperationException(
745 "Use deregisterServiceprovider instead of Iterator.remove()");
746 }
747 }
748
749 /**
750 * Wraps spi's iterator to ImageReader iterator.
751 */
752 static class SpiIteratorToReadersIteratorWrapper implements Iterator<ImageReader> {
753
754 /**
755 * The backend.
756 */
757 private Iterator<ImageReaderSpi> backend;
758
759 /**
760 * Instantiates a new spi iterator to readers iterator wrapper.
761 *
762 * @param backend
763 * the backend.
764 */
765 public SpiIteratorToReadersIteratorWrapper(Iterator<ImageReaderSpi> backend) {
766 this.backend = backend;
767 }
768
769 /**
770 * Next.
771 *
772 * @return the image reader.
773 */
774 public ImageReader next() {
775 try {
776 return backend.next().createReaderInstance();
777 } catch (IOException e) {
778 e.printStackTrace();
779 return null;
780 }
781 }
782
783 /**
784 * Checks for next.
785 *
786 * @return true, if successful.
787 */
788 public boolean hasNext() {
789 return backend.hasNext();
790 }
791
792 /**
793 * Removes the.
794 */
795 public void remove() {
796 throw new UnsupportedOperationException(
797 "Use deregisterServiceprovider instead of Iterator.remove()");
798 }
799 }
800}