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