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