View Javadoc
1   /*
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  package org.apache.commons.imaging;
18  
19  import java.awt.Dimension;
20  import java.awt.image.BufferedImage;
21  import java.io.File;
22  import java.io.IOException;
23  import java.io.OutputStream;
24  import java.io.PrintWriter;
25  import java.io.StringWriter;
26  import java.nio.ByteOrder;
27  import java.util.ArrayList;
28  import java.util.Arrays;
29  import java.util.List;
30  import java.util.Locale;
31  import java.util.logging.Level;
32  import java.util.logging.Logger;
33  
34  import org.apache.commons.imaging.bytesource.ByteSource;
35  import org.apache.commons.imaging.common.BinaryFileParser;
36  import org.apache.commons.imaging.common.BufferedImageFactory;
37  import org.apache.commons.imaging.common.ImageMetadata;
38  import org.apache.commons.imaging.common.SimpleBufferedImageFactory;
39  import org.apache.commons.imaging.formats.bmp.BmpImageParser;
40  import org.apache.commons.imaging.formats.dcx.DcxImageParser;
41  import org.apache.commons.imaging.formats.gif.GifImageParser;
42  import org.apache.commons.imaging.formats.icns.IcnsImageParser;
43  import org.apache.commons.imaging.formats.ico.IcoImageParser;
44  import org.apache.commons.imaging.formats.jpeg.JpegImageParser;
45  import org.apache.commons.imaging.formats.pcx.PcxImageParser;
46  import org.apache.commons.imaging.formats.png.PngImageParser;
47  import org.apache.commons.imaging.formats.pnm.PnmImageParser;
48  import org.apache.commons.imaging.formats.psd.PsdImageParser;
49  import org.apache.commons.imaging.formats.rgbe.RgbeImageParser;
50  import org.apache.commons.imaging.formats.tiff.TiffImageParser;
51  import org.apache.commons.imaging.formats.wbmp.WbmpImageParser;
52  import org.apache.commons.imaging.formats.webp.WebPImageParser;
53  import org.apache.commons.imaging.formats.xbm.XbmImageParser;
54  import org.apache.commons.imaging.formats.xpm.XpmImageParser;
55  import org.apache.commons.lang3.ArrayUtils;
56  
57  /**
58   * Provides the abstract base class for all image reading and writing utilities. ImageParser implementations are expected to extend this class providing logic
59   * for identifying and processing data in their own specific format. Specific implementations are found under the com.apache.commons.imaging.formats package.
60   *
61   * <h2>Application Notes</h2>
62   *
63   * <h3>Format support</h3>
64   *
65   * For the most recent information on format support for the Apache Commons Imaging package, refer to
66   * <a href="https://commons.apache.org/imaging/formatsupport.html">Format Support</a> at the main project development web site.
67   *
68   * <h3>On the accuracy of this Javadoc</h3>
69   *
70   * The original authors of this class did not supply documentation. The Javadoc for this class is based on inspection of the source code. In some cases, the
71   * purpose and usage for particular methods was deduced from the source and may not perfectly reflect the intentions of the original. Therefore, you should not
72   * assume that the documentation is perfect, especially in the more obscure and specialized areas of implementation.
73   *
74   * <h3>The "params" argument</h3>
75   *
76   * <p>
77   * Many of the methods specified by this class accept an argument of type {@code T} defining the parameters to be used when processing an image. For example,
78   * some of the output formats permit of different kinds of image compression or color models. Some of the reading methods permit the calling application to
79   * require strict format compliance.
80   * </p>
81   *
82   * @param <T> type of parameters used by this image parser
83   */
84  public abstract class AbstractImageParser<T extends ImagingParameters<T>> extends BinaryFileParser {
85  
86      private static final Logger LOGGER = Logger.getLogger(AbstractImageParser.class.getName());
87  
88      /**
89       * Gets an array of new instances of all image parsers.
90       *
91       * @return A valid array of image parsers
92       */
93      public static List<AbstractImageParser<?>> getAllImageParsers() {
94          return Arrays.asList(new BmpImageParser(), new DcxImageParser(), new GifImageParser(), new IcnsImageParser(), new IcoImageParser(),
95                  new JpegImageParser(), new PcxImageParser(), new PngImageParser(), new PnmImageParser(), new PsdImageParser(), new RgbeImageParser(),
96                  new TiffImageParser(), new WebPImageParser(), new WbmpImageParser(), new XbmImageParser(), new XpmImageParser()
97          // new JBig2ImageParser(),
98          // new TgaImageParser(),
99          );
100     }
101 
102     /**
103      * Constructs a new instance with the default, big-endian, byte order.
104      */
105     public AbstractImageParser() {
106         // empty
107     }
108 
109     /**
110      * Constructs a new instance.
111      *
112      * @param byteOrder the byte order.
113      */
114     public AbstractImageParser(final ByteOrder byteOrder) {
115         super(byteOrder);
116     }
117 
118     /**
119      * Tests whether the ImageParser implementation can accept the specified file based on its extension.
120      *
121      * @param file An valid file reference.
122      * @return If the parser can accept the format, true; otherwise, false.
123      */
124     public boolean canAcceptExtension(final File file) {
125         return canAcceptExtension(file.getName());
126     }
127 
128     /**
129      * Tests whether the ImageParser implementation can accept the specified file name based on its extension.
130      *
131      * @param fileName A valid string giving a file name or file path.
132      * @return If the parser can accept the format, true; otherwise, false.
133      */
134     public final boolean canAcceptExtension(final String fileName) {
135         final String[] extensions = getAcceptedExtensions();
136         if (extensions == null) {
137             return true;
138         }
139         final int index = fileName.lastIndexOf('.');
140         if (index >= 0 && ArrayUtils.contains(extensions, fileName.substring(index + 1).toLowerCase(Locale.ROOT))) {
141             return true;
142         }
143         return false;
144     }
145 
146     /**
147      * Tests whether the ImageParser implementation can accept the specified format.
148      *
149      * @param imageFormat An instance of ImageFormat.
150      * @return If the parser can accept the format, true; otherwise, false.
151      */
152     public boolean canAcceptType(final ImageFormat imageFormat) {
153         return ArrayUtils.contains(getAcceptedTypes(), imageFormat);
154     }
155 
156     /**
157      * Writes the ImageInfo and format-specific information for the image content of the specified byte array to a string.
158      *
159      * @param bytes A valid array of bytes.
160      * @return A valid string.
161      * @throws ImagingException In the event that the specified content does not conform to the format of the specific parser implementation.
162      * @throws IOException      In the event of unsuccessful read or access operation.
163      */
164     public final String dumpImageFile(final byte[] bytes) throws ImagingException, IOException {
165         return dumpImageFile(ByteSource.array(bytes));
166     }
167 
168     /**
169      * Writes the ImageInfo and format-specific information for the image content of the specified byte source to a string.
170      *
171      * @param byteSource A valid byte source.
172      * @return A valid string.
173      * @throws ImagingException In the event that the specified content does not conform to the format of the specific parser implementation.
174      * @throws IOException      In the event of unsuccessful read or access operation.
175      */
176     public final String dumpImageFile(final ByteSource byteSource) throws ImagingException, IOException {
177         final StringWriter sw = new StringWriter();
178         final PrintWriter pw = new PrintWriter(sw);
179 
180         dumpImageFile(pw, byteSource);
181 
182         pw.flush();
183 
184         return sw.toString();
185     }
186 
187     /**
188      * Writes the ImageInfo and format-specific information for the image content of the specified file to a string.
189      *
190      * @param file A valid file reference.
191      * @return A valid string.
192      * @throws ImagingException In the event that the specified content does not conform to the format of the specific parser implementation.
193      * @throws IOException      In the event of unsuccessful read or access operation.
194      */
195     public final String dumpImageFile(final File file) throws ImagingException, IOException {
196         if (!canAcceptExtension(file)) {
197             return null;
198         }
199 
200         if (LOGGER.isLoggable(Level.FINEST)) {
201             LOGGER.finest(getName() + ": " + file.getName());
202         }
203 
204         return dumpImageFile(ByteSource.file(file));
205     }
206 
207     /**
208      * Writes the ImageInfo and format-specific information for the image content of the specified byte source to a PrintWriter
209      *
210      * @param pw         print writer used for writing the ImageInfo
211      * @param byteSource A valid byte source.
212      * @return A valid PrintWriter.
213      * @throws ImagingException In the event that the specified content does not conform to the format of the specific parser implementation.
214      * @throws IOException      In the event of unsuccessful read or access operation.
215      */
216     public boolean dumpImageFile(final PrintWriter pw, final ByteSource byteSource) throws ImagingException, IOException {
217         return false;
218     }
219 
220     /**
221      * Gets an array of all accepted extensions
222      *
223      * @return A valid array of one or more elements.
224      */
225     protected abstract String[] getAcceptedExtensions();
226 
227     /**
228      * Gets an array of ImageFormat objects describing all accepted types
229      *
230      * @return A valid array of one or more elements.
231      */
232     protected abstract ImageFormat[] getAcceptedTypes();
233 
234     /**
235      * Gets all images specified by the byte array (some formats may include multiple images within a single data source).
236      *
237      * @param bytes A valid byte array
238      * @return A valid (potentially empty) list of BufferedImage objects.
239      * @throws ImagingException In the event that the specified content does not conform to the format of the specific parser implementation.
240      * @throws IOException      In the event of unsuccessful read or access operation.
241      */
242     public final List<BufferedImage> getAllBufferedImages(final byte[] bytes) throws ImagingException, IOException {
243         return getAllBufferedImages(ByteSource.array(bytes));
244     }
245 
246     /**
247      * Gets all images specified by the byte source (some formats may include multiple images within a single data source).
248      *
249      * @param byteSource A valid instance of ByteSource.
250      * @return A valid (potentially empty) list of BufferedImage objects.
251      * @throws ImagingException In the event that the specified content does not conform to the format of the specific parser implementation.
252      * @throws IOException      In the event of unsuccessful read or access operation.
253      */
254     public List<BufferedImage> getAllBufferedImages(final ByteSource byteSource) throws ImagingException, IOException {
255         final BufferedImage bi = getBufferedImage(byteSource, null);
256 
257         final List<BufferedImage> result = new ArrayList<>();
258 
259         // FIXME this doesn't look like we're actually getting all images contained in the given ByteSource...
260         result.add(bi);
261 
262         return result;
263     }
264 
265     /**
266      * Gets all images specified by indicated file (some formats may include multiple images within a single data source).
267      *
268      * @param file A valid reference to a file.
269      * @return A valid (potentially empty) list of BufferedImage objects.
270      * @throws ImagingException In the event that the specified content does not conform to the format of the specific parser implementation.
271      * @throws IOException      In the event of unsuccessful read or access operation.
272      */
273     public final List<BufferedImage> getAllBufferedImages(final File file) throws ImagingException, IOException {
274         if (!canAcceptExtension(file)) {
275             return null;
276         }
277 
278         return getAllBufferedImages(ByteSource.file(file));
279     }
280 
281     /**
282      * Gets a buffered image specified by the byte array (for sources that specify multiple images, choice of which image is returned is implementation
283      * dependent).
284      *
285      * @param bytes  A valid byte array
286      * @param params Optional instructions for special-handling or interpretation of the input data (null objects are permitted and must be supported by
287      *               implementations).
288      * @return A valid instance of BufferedImage.
289      * @throws ImagingException In the event that the specified content does not conform to the format of the specific parser implementation.
290      * @throws IOException      In the event of unsuccessful read or access operation.
291      */
292     public final BufferedImage getBufferedImage(final byte[] bytes, final T params) throws ImagingException, IOException {
293         return getBufferedImage(ByteSource.array(bytes), params);
294     }
295 
296     /**
297      * Gets a buffered image specified by the byte source (for sources that specify multiple images, choice of which image is returned is implementation
298      * dependent).
299      *
300      * @param byteSource A valid instance of ByteSource
301      * @param params     Optional instructions for special-handling or interpretation of the input data (null objects are permitted and must be supported by
302      *                   implementations).
303      * @return A valid instance of BufferedImage.
304      * @throws ImagingException In the event that the specified content does not conform to the format of the specific parser implementation.
305      * @throws IOException      In the event of unsuccessful read or access operation.
306      */
307     public abstract BufferedImage getBufferedImage(ByteSource byteSource, T params) throws ImagingException, IOException;
308 
309     /**
310      * Gets a buffered image specified by the indicated file (for sources that specify multiple images, choice of which image is returned is implementation
311      * dependent).
312      *
313      * @param file   A valid file reference.
314      * @param params Optional instructions for special-handling or interpretation of the input data (null objects are permitted and must be supported by
315      *               implementations).
316      * @return A valid instance of BufferedImage.
317      * @throws ImagingException In the event that the specified content does not conform to the format of the specific parser implementation.
318      * @throws IOException      In the event of unsuccessful read or access operation.
319      */
320     public final BufferedImage getBufferedImage(final File file, final T params) throws ImagingException, IOException {
321         if (!canAcceptExtension(file)) {
322             return null;
323         }
324 
325         return getBufferedImage(ByteSource.file(file), params);
326     }
327 
328     /**
329      * Gets an instance of IBufferedImageFactory based on the presence of a specification for ImagingConstants.&#46;BUFFERED_IMAGE_FACTORY within the supplied
330      * params.
331      *
332      * @param params optional parameters.
333      * @return A valid instance of an implementation of a IBufferedImageFactory.
334      */
335     protected BufferedImageFactory getBufferedImageFactory(final T params) {
336         if (params == null) {
337             return new SimpleBufferedImageFactory();
338         }
339 
340         final BufferedImageFactory result = params.getBufferedImageFactory();
341 
342         if (null != result) {
343             return result;
344         }
345 
346         return new SimpleBufferedImageFactory();
347     }
348 
349     /**
350      * Gets the default extension for the format specified by an implementation of ImageParser. Some parsers can support more than one extension (i.e. .JPEG,
351      * .JPG; .TIF, .TIFF, etc.).
352      *
353      * @return A valid string.
354      */
355     public abstract String getDefaultExtension();
356 
357     /**
358      * Gets a default parameters instance for this parser.
359      *
360      * @return default parameters instance
361      */
362     public abstract T getDefaultParameters();
363 
364     /**
365      * Determines the format compliance of the content of the supplied byte array based on rules provided by a specific implementation.
366      *
367      * @param bytes A valid byte array.
368      * @return A valid FormatCompliance object.
369      * @throws ImagingException may be thrown by sub-classes
370      * @throws IOException      may be thrown by sub-classes
371      */
372     public final FormatCompliance getFormatCompliance(final byte[] bytes) throws ImagingException, IOException {
373         return getFormatCompliance(ByteSource.array(bytes));
374     }
375 
376     /**
377      * Determines the format compliance of the content of the supplied byte source based on rules provided by a specific implementation.
378      *
379      * @param byteSource A valid instance of ByteSource
380      * @return true if the content is format-compliant; otherwise, false
381      * @throws ImagingException may be thrown by sub-classes
382      * @throws IOException      may be thrown by sub-classes
383      */
384     public FormatCompliance getFormatCompliance(final ByteSource byteSource) throws ImagingException, IOException {
385         return null;
386     }
387 
388     /**
389      * Determines the format compliance of the specified file based on rules provided by a specific implementation.
390      *
391      * @param file A valid reference to a file.
392      * @return A valid format compliance object.
393      * @throws ImagingException may be thrown by sub-classes
394      * @throws IOException      may be thrown by sub-classes
395      */
396     public final FormatCompliance getFormatCompliance(final File file) throws ImagingException, IOException {
397         if (!canAcceptExtension(file)) {
398             return null;
399         }
400 
401         return getFormatCompliance(ByteSource.file(file));
402     }
403 
404     /**
405      * Gets an array of bytes describing the International Color Consortium (ICC) specification for the color space of the image contained in the input byte
406      * array. Not all formats support ICC profiles.
407      *
408      * @param bytes A valid array of bytes.
409      * @return If available, a valid array of bytes; otherwise, a null
410      * @throws ImagingException In the event that the specified content does not conform to the format of the specific parser implementation.
411      * @throws IOException      In the event of unsuccessful read or access operation.
412      */
413     public final byte[] getIccProfileBytes(final byte[] bytes) throws ImagingException, IOException {
414         return getIccProfileBytes(bytes, null);
415     }
416 
417     /**
418      * Gets an array of bytes describing the International Color Consortium (ICC) specification for the color space of the image contained in the input byte
419      * array. Not all formats support ICC profiles.
420      *
421      * @param bytes  A valid array of bytes.
422      * @param params Optional instructions for special-handling or interpretation of the input data.
423      * @return If available, a valid array of bytes; otherwise, a null
424      * @throws ImagingException In the event that the specified content does not conform to the format of the specific parser implementation.
425      * @throws IOException      In the event of unsuccessful read or access operation.
426      */
427     public final byte[] getIccProfileBytes(final byte[] bytes, final T params) throws ImagingException, IOException {
428         return getIccProfileBytes(ByteSource.array(bytes), params);
429     }
430 
431     /**
432      * Gets an array of bytes describing the International Color Consortium (ICC) specification for the color space of the image contained in the input
433      * byteSource. Not all formats support ICC profiles.
434      *
435      * @param byteSource A valid ByteSource.
436      * @param params     Optional instructions for special-handling or interpretation of the input data.
437      * @return If available, a valid array of bytes; otherwise, a null
438      * @throws ImagingException In the event that the specified content does not conform to the format of the specific parser implementation.
439      * @throws IOException      In the event of unsuccessful read or access operation.
440      */
441     public abstract byte[] getIccProfileBytes(ByteSource byteSource, T params) throws ImagingException, IOException;
442 
443     /**
444      * Gets an array of bytes describing the International Color Consortium (ICC) specification for the color space of the image contained in the input file.
445      * Not all formats support ICC profiles.
446      *
447      * @param file A valid file reference.
448      * @return If available, a valid array of bytes; otherwise, a null
449      * @throws ImagingException In the event that the specified content does not conform to the format of the specific parser implementation.
450      * @throws IOException      In the event of unsuccessful read or access operation.
451      */
452     public final byte[] getIccProfileBytes(final File file) throws ImagingException, IOException {
453         return getIccProfileBytes(file, null);
454     }
455 
456     /**
457      * Gets an array of bytes describing the International Color Consortium (ICC) specification for the color space of the image contained in the input file.
458      * Not all formats support ICC profiles.
459      *
460      * @param file   A valid file reference.
461      * @param params Optional instructions for special-handling or interpretation of the input data.
462      * @return If available, a valid array of bytes; otherwise, a null
463      * @throws ImagingException In the event that the specified content does not conform to the format of the specific parser implementation.
464      * @throws IOException      In the event of unsuccessful read or access operation.
465      */
466     public final byte[] getIccProfileBytes(final File file, final T params) throws ImagingException, IOException {
467         if (!canAcceptExtension(file)) {
468             return null;
469         }
470 
471         if (LOGGER.isLoggable(Level.FINEST)) {
472             LOGGER.finest(getName() + ": " + file.getName());
473         }
474 
475         return getIccProfileBytes(ByteSource.file(file), params);
476     }
477 
478     /**
479      * Gets image information from the specified array of bytes. Format-specific ImageParser implementations are expected to return a valid ImageInfo object or
480      * to throw an ImageReadException if unable to process the specified data.
481      * <p>
482      * The params argument provides a mechanism for individual implementations to pass optional information into the parser. Not all formats will require this
483      * capability. Because the base class may call this method with a null params argument, implementations should <strong>always</strong> include logic for
484      * ignoring null input.
485      *
486      * @param bytes  A valid array of bytes
487      * @param params Optional instructions for special-handling or interpretation of the input data (null objects are permitted and must be supported by
488      *               implementations).
489      * @return A valid image information object describing the content extracted from the specified data.
490      * @throws ImagingException In the event that the specified content does not conform to the format of the specific parser implementation.
491      * @throws IOException      In the event of unsuccessful data access operation.
492      */
493     public final ImageInfo getImageInfo(final byte[] bytes, final T params) throws ImagingException, IOException {
494         return getImageInfo(ByteSource.array(bytes), params);
495     }
496 
497     /**
498      * Gets image information from the specified ByteSource. Format-specific ImageParser implementations are expected to return a valid ImageInfo object or to
499      * throw an ImageReadException if unable to process the specified data.
500      *
501      * @param byteSource A valid ByteSource object
502      * @return A valid image information object describing the content extracted from the specified data.
503      * @throws ImagingException In the event that the specified content does not conform to the format of the specific parser implementation.
504      * @throws IOException      In the event of unsuccessful data access operation.
505      */
506     public final ImageInfo getImageInfo(final ByteSource byteSource) throws ImagingException, IOException {
507         return getImageInfo(byteSource, null);
508     }
509 
510     /**
511      * Gets image information from the specified ByteSource. Format-specific ImageParser implementations are expected to return a valid ImageInfo object or to
512      * throw an ImageReadException if unable to process the specified data.
513      *
514      * <p>
515      * The params argument provides a mechanism for individual implementations to pass optional information into the parser. Not all formats will require this
516      * capability. Because the base class may call this method with a null params argument, implementations should <strong>always</strong> include logic for
517      * ignoring null input.
518      *
519      * @param byteSource A valid ByteSource object
520      * @param params     Optional instructions for special-handling or interpretation of the input data (null objects are permitted and must be supported by
521      *                   implementations).
522      * @return A valid image information object describing the content extracted from the specified data.
523      * @throws ImagingException In the event that the specified content does not conform to the format of the specific parser implementation.
524      * @throws IOException      In the event of unsuccessful data access operation.
525      */
526     public abstract ImageInfo getImageInfo(ByteSource byteSource, T params) throws ImagingException, IOException;
527 
528     /**
529      * Gets image information from the specified file Format-specific ImageParser implementations are expected to return a valid ImageInfo object or to throw an
530      * ImageReadException if unable to process the specified data.
531      * <p>
532      * The params argument provides a mechanism for individual implementations to pass optional information into the parser. Not all formats will require this
533      * capability. Because the base class may call this method with a null params argument, implementations should <strong>always</strong> include logic for
534      * ignoring null input.
535      *
536      * @param file   A valid File object
537      * @param params Optional instructions for special-handling or interpretation of the input data (null objects are permitted and must be supported by
538      *               implementations).
539      * @return A valid image information object describing the content extracted from the specified data.
540      * @throws ImagingException In the event that the specified content does not conform to the format of the specific parser implementation.
541      * @throws IOException      In the event of unsuccessful file read or access operation.
542      */
543     public final ImageInfo getImageInfo(final File file, final T params) throws ImagingException, IOException {
544         if (!canAcceptExtension(file)) {
545             return null;
546         }
547 
548         return getImageInfo(ByteSource.file(file), params);
549     }
550 
551     /**
552      * Gets the size of the image described by the specified byte array.
553      *
554      * @param bytes A valid byte array.
555      * @return A valid instance of Dimension.
556      * @throws ImagingException In the event that the specified content does not conform to the format of the specific parser implementation.
557      * @throws IOException      In the event of unsuccessful read or access operation.
558      */
559     public final Dimension getImageSize(final byte[] bytes) throws ImagingException, IOException {
560         return getImageSize(bytes, null);
561     }
562 
563     /**
564      * Gets the size of the image described by the specified byte array.
565      *
566      * @param bytes  A valid byte array.
567      * @param params Optional instructions for special-handling or interpretation of the input data.
568      * @return A valid instance of Dimension.
569      * @throws ImagingException In the event that the specified content does not conform to the format of the specific parser implementation.
570      * @throws IOException      In the event of unsuccessful read or access operation.
571      */
572     public final Dimension getImageSize(final byte[] bytes, final T params) throws ImagingException, IOException {
573         return getImageSize(ByteSource.array(bytes), params);
574     }
575 
576     /**
577      * Gets the size of the image described by the specified ByteSource.
578      *
579      * @param byteSource A valid reference to a ByteSource.
580      * @param params     Optional instructions for special-handling or interpretation of the input data.
581      * @return A valid instance of Dimension.
582      * @throws ImagingException In the event that the specified content does not conform to the format of the specific parser implementation.
583      * @throws IOException      In the event of unsuccessful read or access operation.
584      */
585     public abstract Dimension getImageSize(ByteSource byteSource, T params) throws ImagingException, IOException;
586 
587     /**
588      * Gets the size of the image described by the specified file.
589      *
590      * @param file A valid reference to a file.
591      * @return A valid instance of Dimension.
592      * @throws ImagingException In the event that the specified content does not conform to the format of the specific parser implementation.
593      * @throws IOException      In the event of unsuccessful read or access operation.
594      */
595     public final Dimension getImageSize(final File file) throws ImagingException, IOException {
596         return getImageSize(file, null);
597     }
598 
599     /**
600      * Gets the size of the image described by the specified file.
601      *
602      * @param file   A valid reference to a file.
603      * @param params Optional instructions for special-handling or interpretation of the input data.
604      * @return A valid instance of Dimension.
605      * @throws ImagingException In the event that the specified content does not conform to the format of the specific parser implementation.
606      * @throws IOException      In the event of unsuccessful read or access operation.
607      */
608     public final Dimension getImageSize(final File file, final T params) throws ImagingException, IOException {
609 
610         if (!canAcceptExtension(file)) {
611             return null;
612         }
613 
614         return getImageSize(ByteSource.file(file), params);
615     }
616 
617     /**
618      * Gets image metadata from the specified array of bytes. Format-specific ImageParser implementations are expected to return a valid IImageMetadata object
619      * or to throw an ImageReadException if unable to process the specified data.
620      *
621      * @param bytes A valid array of bytes
622      * @return A valid, potentially subject-matter-specific implementation of the IImageMetadata interface describing the content extracted from the source
623      *         content.
624      * @throws ImagingException In the event that the specified content does not conform to the format of the specific parser implementation.
625      * @throws IOException      In the event of unsuccessful data read operation.
626      */
627     public final ImageMetadata getMetadata(final byte[] bytes) throws ImagingException, IOException {
628         return getMetadata(bytes, null);
629     }
630 
631     /**
632      * Gets image metadata from the specified array of bytes. Format-specific ImageParser implementations are expected to return a valid IImageMetadata object
633      * or to throw an ImageReadException if unable to process the specified data.
634      *
635      * <p>
636      * The params argument provides a mechanism for individual implementations to pass optional information into the parser. Not all formats will require this
637      * capability. Because the base class may call this method with a null params argument, implementations should <strong>always</strong> include logic for
638      * ignoring null input.
639      *
640      * @param bytes  A valid array of bytes
641      * @param params Optional instructions for special-handling or interpretation of the input data (null objects are permitted and must be supported by
642      *               implementations).
643      * @return A valid image metadata object describing the content extracted from the specified content.
644      * @throws ImagingException In the event that the specified content does not conform to the format of the specific parser implementation.
645      * @throws IOException      In the event of unsuccessful data read operation.
646      */
647     public final ImageMetadata getMetadata(final byte[] bytes, final T params) throws ImagingException, IOException {
648         return getMetadata(ByteSource.array(bytes), params);
649     }
650 
651     /**
652      * Gets image metadata from the specified byte source. Format-specific ImageParser implementations are expected to return a valid IImageMetadata object or
653      * to throw an ImageReadException if unable to process the specified byte source.
654      *
655      * @param byteSource A valid byte source.
656      * @return A valid, potentially subject-matter-specific implementation of the IImageMetadata interface describing the content extracted from the source
657      *         content.
658      * @throws ImagingException In the event that the ByteSource content does not conform to the format of the specific parser implementation.
659      * @throws IOException      In the event of unsuccessful data read operation.
660      */
661     public final ImageMetadata getMetadata(final ByteSource byteSource) throws ImagingException, IOException {
662         return getMetadata(byteSource, null);
663     }
664 
665     /**
666      * Gets image metadata from the specified byte source. Format-specific ImageParser implementations are expected to return a valid IImageMetadata object or
667      * to throw an ImageReadException if unable to process the specified byte source.
668      *
669      * <p>
670      * The params argument provides a mechanism for individual implementations to pass optional information into the parser. Not all formats will require this
671      * capability. Because the base class may call this method with a null params argument, implementations should <strong>always</strong> include logic for
672      * ignoring null input.
673      *
674      * @param byteSource A valid byte source.
675      * @param params     Optional instructions for special-handling or interpretation of the input data (null objects are permitted and must be supported by
676      *                   implementations).
677      * @return A valid, potentially subject-matter-specific implementation of the IImageMetadata interface describing the content extracted from the source
678      *         content.
679      * @throws ImagingException In the event that the ByteSource content does not conform to the format of the specific parser implementation.
680      * @throws IOException      In the event of unsuccessful data read operation.
681      */
682     public abstract ImageMetadata getMetadata(ByteSource byteSource, T params) throws ImagingException, IOException;
683 
684     /**
685      * Gets image metadata from the specified file. Format-specific ImageParser implementations are expected to return a valid IImageMetadata object or to throw
686      * an ImageReadException if unable to process the specified data.
687      *
688      * @param file A valid reference to a file.
689      * @return A valid image metadata object describing the content extracted from the specified content.
690      * @throws ImagingException In the event that the specified content does not conform to the format of the specific parser implementation.
691      * @throws IOException      In the event of unsuccessful file read or access operation.
692      */
693     public final ImageMetadata getMetadata(final File file) throws ImagingException, IOException {
694         return getMetadata(file, null);
695     }
696 
697     /**
698      * Gets image metadata from the specified file. Format-specific ImageParser implementations are expected to return a valid IImageMetadata object or to throw
699      * an ImageReadException if unable to process the specified data.
700      *
701      * <p>
702      * The params argument provides a mechanism for individual implementations to pass optional information into the parser. Not all formats will require this
703      * capability. Because the base class may call this method with a null params argument, implementations should <strong>always</strong> include logic for
704      * ignoring null input.
705      *
706      * @param file   A valid reference to a file.
707      * @param params Optional instructions for special-handling or interpretation of the input data (null objects are permitted and must be supported by
708      *               implementations).
709      * @return A valid image metadata object describing the content extracted from the specified content.
710      * @throws ImagingException In the event that the specified content does not conform to the format of the specific parser implementation.
711      * @throws IOException      In the event of unsuccessful file read or access operation.
712      */
713     public final ImageMetadata getMetadata(final File file, final T params) throws ImagingException, IOException {
714         if (LOGGER.isLoggable(Level.FINEST)) {
715             LOGGER.finest(getName() + ".getMetadata" + ": " + file.getName());
716         }
717 
718         if (!canAcceptExtension(file)) {
719             return null;
720         }
721 
722         return getMetadata(ByteSource.file(file), params);
723     }
724 
725     /**
726      * Gets a descriptive name for the implementation of an ImageParser.
727      *
728      * @return a valid, subject-matter-specific string.
729      */
730     public abstract String getName();
731 
732     /**
733      * Writes the content of a BufferedImage to the specified output stream.
734      *
735      * <p>
736      * The params argument provides a mechanism for individual implementations to pass optional information into the parser. Not all formats will support this
737      * capability. Currently, some of the parsers do not check for null arguments.
738      * </p>
739      *
740      * @param src    An image giving the source content for output
741      * @param os     A valid output stream for storing the formatted image
742      * @param params optional parameters, defining format-specific instructions for output (such as selections for data compression, color models, etc.)
743      * @throws ImagingException In the event that the output format cannot handle the input image or invalid params are specified.
744      * @throws IOException      In the event of an write error from the output stream.
745      */
746     public void writeImage(final BufferedImage src, final OutputStream os, final T params) throws ImagingException, IOException {
747         throw new ImagingException("This image format (" + getName() + ") cannot be written.");
748     }
749 }