    001/*
    002 * Licensed to the Apache Software Foundation (ASF) under one or more
    003 * contributor license agreements.  See the NOTICE file distributed with
    004 * this work for additional information regarding copyright ownership.
    005 * The ASF licenses this file to You under the Apache License, Version 2.0
    006 * (the "License"); you may not use this file except in compliance with
    007 * the License.  You may obtain a copy of the License at
    008 *
    009 *      http://www.apache.org/licenses/LICENSE-2.0
    010 *
    011 * Unless required by applicable law or agreed to in writing, software
    012 * distributed under the License is distributed on an "AS IS" BASIS,
    013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    014 * See the License for the specific language governing permissions and
    015 * limitations under the License.
    016 */
    017package org.apache.commons.imaging;
    018
    019import static org.apache.commons.imaging.ImagingConstants.PARAM_KEY_FILENAME;
    020import static org.apache.commons.imaging.ImagingConstants.PARAM_KEY_FORMAT;
    021
    022import java.awt.Dimension;
    023import java.awt.color.ICC_Profile;
    024import java.awt.image.BufferedImage;
    025import java.io.BufferedOutputStream;
    026import java.io.ByteArrayOutputStream;
    027import java.io.File;
    028import java.io.FileOutputStream;
    029import java.io.IOException;
    030import java.io.InputStream;
    031import java.io.OutputStream;
    032import java.util.HashMap;
    033import java.util.List;
    034import java.util.Locale;
    035import java.util.Map;
    036
    037import org.apache.commons.imaging.common.ImageMetadata;
    038import org.apache.commons.imaging.common.XmpEmbeddable;
    039import org.apache.commons.imaging.common.bytesource.ByteSource;
    040import org.apache.commons.imaging.common.bytesource.ByteSourceArray;
    041import org.apache.commons.imaging.common.bytesource.ByteSourceFile;
    042import org.apache.commons.imaging.common.bytesource.ByteSourceInputStream;
    043import org.apache.commons.imaging.icc.IccProfileInfo;
    044import org.apache.commons.imaging.icc.IccProfileParser;
    045
    046/**
    047 * The primary application programming interface (API) to the Imaging library.
    048 *
    049 * <h2>Application Notes</h2>
    050 *
    051 * <h3>Using this class</h3>
    052 *
    053 * <p>
    054 * Almost all of the Apache Commons Imaging library's core functionality can
    055 * be accessed through the methods provided by this class.
    056 * The use of the Imaging class is similar to the Java API's ImageIO class,
    057 * though Imaging supports formats and options not included in the standard
    058 * Java API.
    059 * </p>
    060 *
    061 * <p>
    062 * All of methods provided by the Imaging class are declared static.
    063 * </p>
    064 *
    065 * <p>
    066 * The Apache Commons Imaging package is a pure Java implementation.
    067 * </p>
    068 *
    069 * <h3>Format support</h3>
    070 *
    071 * <p>
    072 * While the Apache Commons Imaging package handles a number of different
    073 * graphics formats, support for some formats is not yet complete.
    074 * For the most recent information on support for specific formats, refer to
    075 * <a href="https://commons.apache.org/imaging/formatsupport.html">Format Support</a>
    076 * at the main project development web site.
    077 * </p>
    078 *
    079 * <h3>Optional parameters for image reading and writing</h3>
    080 *
    081 * <p>
    082 * Some of the methods provided by this class accept an optional
    083 * <strong>params</strong> argument that permits the application to specify
    084 * elements for special handling.  If these specifications are not required by
    085 * the application, the params argument may be omitted (as appropriate) or
    086 * a null argument may be provided. In image-writing operations, the option
    087 * parameters may include options such as data-compression type (if any),
    088 * color model, or other format-specific data representations.   The parameters
    089 * map may also be used to provide EXIF Tags and other metadata to those
    090 * formats that support them. In image-reading operations,
    091 * the parameters may include information about special handling in reading
    092 * the image data.
    093 * </p>
    094 *
    095 * <p>
    096 * Optional parameters are specified using a Map object (typically,
    097 * a Java HashMap) to specify a set of keys and values for input.
    098 * The specification for support keys is provided by the ImagingConstants
    099 * interface as well as by format-specific interfaces such as
    100 * JpegContants or TiffConstants.
    101 * </p>
    102 *
    103 * <h3>Example code</h3>
    104 *
    105 * <p>
    106 * See the source of the SampleUsage class and other classes in the
    107 * org.apache.commons.imaging.examples package for examples.
    108 * </p>
    109 *
    110 * @see <a
    111 *      href="https://svn.apache.org/repos/asf/commons/proper/imaging/trunk/src/test/java/org/apache/commons/imaging/examples/SampleUsage.java">org.apache.commons.imaging.examples.SampleUsage</a>
    112 * @see <a href="https://commons.apache.org/imaging/formatsupport.html">Format Support</a>
    113 */
    114public final class Imaging {
    115
    116    private static final int[] MAGIC_NUMBERS_GIF = { 0x47, 0x49, };
    117    private static final int[] MAGIC_NUMBERS_PNG = { 0x89, 0x50, };
    118    private static final int[] MAGIC_NUMBERS_JPEG = { 0xff, 0xd8, };
    119    private static final int[] MAGIC_NUMBERS_BMP = { 0x42, 0x4d, };
    120    private static final int[] MAGIC_NUMBERS_TIFF_MOTOROLA = { 0x4D, 0x4D, };
    121    private static final int[] MAGIC_NUMBERS_TIFF_INTEL = { 0x49, 0x49, };
    122    private static final int[] MAGIC_NUMBERS_PAM = { 0x50, 0x37, };
    123    private static final int[] MAGIC_NUMBERS_PSD = { 0x38, 0x42, };
    124    private static final int[] MAGIC_NUMBERS_PBM_A = { 0x50, 0x31, };
    125    private static final int[] MAGIC_NUMBERS_PBM_B = { 0x50, 0x34, };
    126    private static final int[] MAGIC_NUMBERS_PGM_A = { 0x50, 0x32, };
    127    private static final int[] MAGIC_NUMBERS_PGM_B = { 0x50, 0x35, };
    128    private static final int[] MAGIC_NUMBERS_PPM_A = { 0x50, 0x33, };
    129    private static final int[] MAGIC_NUMBERS_PPM_B = { 0x50, 0x36, };
    130    private static final int[] MAGIC_NUMBERS_JBIG2_1 = { 0x97, 0x4A, };
    131    private static final int[] MAGIC_NUMBERS_JBIG2_2 = { 0x42, 0x32, };
    132    private static final int[] MAGIC_NUMBERS_ICNS = { 0x69, 0x63, };
    133    private static final int[] MAGIC_NUMBERS_DCX = { 0xB1, 0x68, };
    134    private static final int[] MAGIC_NUMBERS_RGBE = { 0x23, 0x3F, };
    135
    136    private Imaging() {
    137        // Instances can not be created
    138    }
    139
    140    /**
    141     * Attempts to determine if a file contains an image recorded in
    142     * a supported graphics format based on its file-name extension
    143     * (for example "&#46;jpg", "&#46;gif", "&#46;png", etc&#46;).
    144     *
    145     * @param file A valid File object providing a reference to
    146     * a file that may contain an image.
    147     * @return true if the file-name includes a supported image
    148     * format file extension; otherwise, false.
    149     */
    150    public static boolean hasImageFileExtension(final File file) {
    151        if (file == null || !file.isFile()) {
    152            return false;
    153        }
    154        return hasImageFileExtension(file.getName());
    155    }
    156
    157    /**
    158     * Attempts to determine if a file contains an image recorded in
    159     * a supported graphics format based on its file-name extension
    160     * (for example "&#46;jpg", "&#46;gif", "&#46;png", etc&#46;).
    161     *
    162     * @param fileName  A valid string representing name of file
    163     * which may contain an image.
    164     * @return true if the file name has an image format file extension.
    165     */
    166    public static boolean hasImageFileExtension(final String fileName) {
    167        if (fileName == null) {
    168            return false;
    169        }
    170
    171        final String normalizedFilename = fileName.toLowerCase(Locale.ENGLISH);
    172
    173        for (final ImageParser imageParser : ImageParser.getAllImageParsers()) {
    174            for (final String extension : imageParser.getAcceptedExtensions()) {
    175                if (normalizedFilename.endsWith(extension.toLowerCase(Locale.ENGLISH))) {
    176                    return true;
    177                }
    178            }
    179        }
    180
    181        return false;
    182    }
    183
    184    /**
    185     * Attempts to determine the image format of a file based on its
    186     * "magic numbers," the first bytes of the data.
    187     * <p>Many graphics format specify identifying byte
    188     * values that appear at the beginning of the data file.  This method
    189     * checks for such identifying elements and returns a ImageFormat
    190     * enumeration indicating what it detects. Note that this
    191     * method can return "false positives" in cases where non-image files
    192     * begin with the specified byte values.
    193     *
    194     * @param bytes  Byte array containing an image file.
    195     * @return An ImageFormat, such as ImageFormat.IMAGE_FORMAT_JPEG. Returns
    196     *         ImageFormat.IMAGE_FORMAT_UNKNOWN if the image type cannot be
    197     *         determined.
    198     * @throws ImageReadException in the event of an unsuccessful
    199     *         attempt to read the image data
    200     * @throws IOException in the event of an unrecoverable I/O condition.
    201     */
    202    public static ImageFormat guessFormat(final byte[] bytes)
    203            throws ImageReadException, IOException {
    204        return guessFormat(new ByteSourceArray(bytes));
    205    }
    206
    207    /**
    208     * Attempts to determine the image format of a file based on its
    209     * "magic numbers," the first bytes of the data.
    210     * <p>Many graphics formats specify identifying byte
    211     * values that appear at the beginning of the data file.  This method
    212     * checks for such identifying elements and returns a ImageFormat
    213     * enumeration indicating what it detects. Note that this
    214     * method can return "false positives" in cases where non-image files
    215     * begin with the specified byte values.
    216     *
    217     * @param file  File containing image data.
    218     * @return An ImageFormat, such as ImageFormat.IMAGE_FORMAT_JPEG. Returns
    219     *         ImageFormat.IMAGE_FORMAT_UNKNOWN if the image type cannot be
    220     *         determined.
    221     * @throws ImageReadException in the event of an unsuccessful
    222     *         attempt to read the image data
    223     * @throws IOException in the event of an unrecoverable I/O condition.
    224     */
    225    public static ImageFormat guessFormat(final File file) throws ImageReadException,
    226            IOException {
    227        return guessFormat(new ByteSourceFile(file));
    228    }
    229
    230    private static boolean compareBytePair(final int[] a, final int[] b) {
    231        if (a.length != 2 && b.length != 2) {
    232            throw new RuntimeException("Invalid Byte Pair.");
    233        }
    234        return (a[0] == b[0]) && (a[1] == b[1]);
    235    }
    236
    237
    238    /**
    239     * Attempts to determine the image format of a file based on its
    240     * "magic numbers," the first bytes of the data.
    241     * <p>Many graphics formats specify identifying byte
    242     * values that appear at the beginning of the data file.  This method
    243     * checks for such identifying elements and returns a ImageFormat
    244     * enumeration indicating what it detects. Note that this
    245     * method can return "false positives" in cases where non-image files
    246     * begin with the specified byte values.
    247     *
    248     * @param byteSource a valid ByteSource object potentially supplying
    249     * data for an image.
    250     * @return An ImageFormat, such as ImageFormat.IMAGE_FORMAT_JPEG. Returns
    251     *         ImageFormat.IMAGE_FORMAT_UNKNOWN if the image type cannot be
    252     *         determined.
    253     * @throws ImageReadException in the event of an unsuccessful
    254     * attempt to read the image data
    255     * @throws IOException in the event of an unrecoverable I/O condition.
    256     */
    257    public static ImageFormat guessFormat(final ByteSource byteSource)
    258            throws ImageReadException, IOException {
    259
    260        if (byteSource == null) {
    261            return ImageFormats.UNKNOWN;
    262        }
    263
    264        try (InputStream is = byteSource.getInputStream()) {
    265            final int i1 = is.read();
    266            final int i2 = is.read();
    267            if ((i1 < 0) || (i2 < 0)) {
    268                throw new ImageReadException(
    269                        "Couldn't read magic numbers to guess format.");
    270            }
    271
    272            final int b1 = i1 & 0xff;
    273            final int b2 = i2 & 0xff;
    274            final int[] bytePair = { b1, b2, };
    275
    276            if (compareBytePair(MAGIC_NUMBERS_GIF, bytePair)) {
    277                return ImageFormats.GIF;
    278            // } else if (b1 == 0x00 && b2 == 0x00) // too similar to TGA
    279            // {
    280            // return ImageFormat.IMAGE_FORMAT_ICO;
    281            } else if (compareBytePair(MAGIC_NUMBERS_PNG, bytePair)) {
    282                return ImageFormats.PNG;
    283            } else if (compareBytePair(MAGIC_NUMBERS_JPEG, bytePair)) {
    284                return ImageFormats.JPEG;
    285            } else if (compareBytePair(MAGIC_NUMBERS_BMP, bytePair)) {
    286                return ImageFormats.BMP;
    287            } else if (compareBytePair(MAGIC_NUMBERS_TIFF_MOTOROLA, bytePair)) {
    288                return ImageFormats.TIFF;
    289            } else if (compareBytePair(MAGIC_NUMBERS_TIFF_INTEL, bytePair)) {
    290                return ImageFormats.TIFF;
    291            } else if (compareBytePair(MAGIC_NUMBERS_PSD, bytePair)) {
    292                return ImageFormats.PSD;
    293            } else if (compareBytePair(MAGIC_NUMBERS_PAM, bytePair)) {
    294                return ImageFormats.PAM;
    295            } else if (compareBytePair(MAGIC_NUMBERS_PBM_A, bytePair)) {
    296                return ImageFormats.PBM;
    297            } else if (compareBytePair(MAGIC_NUMBERS_PBM_B, bytePair)) {
    298                return ImageFormats.PBM;
    299            } else if (compareBytePair(MAGIC_NUMBERS_PGM_A, bytePair)) {
    300                return ImageFormats.PGM;
    301            } else if (compareBytePair(MAGIC_NUMBERS_PGM_B, bytePair)) {
    302                return ImageFormats.PGM;
    303            } else if (compareBytePair(MAGIC_NUMBERS_PPM_A, bytePair)) {
    304                return ImageFormats.PPM;
    305            } else if (compareBytePair(MAGIC_NUMBERS_PPM_B, bytePair)) {
    306                return ImageFormats.PPM;
    307            } else if (compareBytePair(MAGIC_NUMBERS_JBIG2_1, bytePair)) {
    308                final int i3 = is.read();
    309                final int i4 = is.read();
    310                if ((i3 < 0) || (i4 < 0)) {
    311                    throw new ImageReadException(
    312                            "Couldn't read magic numbers to guess format.");
    313                }
    314
    315                final int b3 = i3 & 0xff;
    316                final int b4 = i4 & 0xff;
    317                final int[] bytePair2 = { b3, b4, };
    318                if (compareBytePair(MAGIC_NUMBERS_JBIG2_2, bytePair2)) {
    319                    return ImageFormats.JBIG2;
    320                }
    321            } else if (compareBytePair(MAGIC_NUMBERS_ICNS, bytePair)) {
    322                return ImageFormats.ICNS;
    323            } else if (compareBytePair(MAGIC_NUMBERS_DCX, bytePair)) {
    324                return ImageFormats.DCX;
    325            } else if (compareBytePair(MAGIC_NUMBERS_RGBE, bytePair)) {
    326                return ImageFormats.RGBE;
    327            }
    328            return ImageFormats.UNKNOWN;
    329        }
    330    }
    331
    332    /**
    333     * Extracts an ICC Profile (if present) from JPEG, PNG, PSD (Photoshop) and
    334     * TIFF images.
    335     *
    336     * @param bytes
    337     *            Byte array containing an image file.
    338     * @return An instance of ICC_Profile or null if the image contains no ICC
    339     *         profile.
    340     * @throws ImageReadException if it fails to parse the image
    341     * @throws IOException if it fails to read the image data
    342     */
    343    public static ICC_Profile getICCProfile(final byte[] bytes)
    344            throws ImageReadException, IOException {
    345        return getICCProfile(bytes, null);
    346    }
    347
    348    /**
    349     * Extracts an ICC Profile (if present) from JPEG, PNG, PSD (Photoshop) and
    350     * TIFF images.
    351     *
    352     * @param bytes
    353     *            Byte array containing an image file.
    354     * @param params
    355     *            Map of optional parameters, defined in ImagingConstants.
    356     * @return An instance of ICC_Profile or null if the image contains no ICC
    357     *         profile.
    358     * @throws ImageReadException if it fails to parse the image
    359     * @throws IOException if it fails to read the image data
    360     */
    361    public static ICC_Profile getICCProfile(final byte[] bytes, final Map<String, Object> params)
    362            throws ImageReadException, IOException {
    363        return getICCProfile(new ByteSourceArray(bytes), params);
    364    }
    365
    366    /**
    367     * Extracts an ICC Profile (if present) from JPEG, PNG, PSD (Photoshop) and
    368     * TIFF images.
    369     *
    370     * @param is
    371     *            InputStream from which to read image data.
    372     * @param fileName
    373     *            Filename associated with image data (optional).
    374     * @return An instance of ICC_Profile or null if the image contains no ICC
    375     *         profile.
    376     * @throws ImageReadException if it fails to parse the image
    377     * @throws IOException if it fails to read the image data
    378     */
    379    public static ICC_Profile getICCProfile(final InputStream is, final String fileName)
    380            throws ImageReadException, IOException {
    381        return getICCProfile(is, fileName, null);
    382    }
    383
    384    /**
    385     * Extracts an ICC Profile (if present) from JPEG, PNG, PSD (Photoshop) and
    386     * TIFF images.
    387     *
    388     * @param is
    389     *            InputStream from which to read image data.
    390     * @param fileName
    391     *            Filename associated with image data (optional).
    392     * @param params
    393     *            Map of optional parameters, defined in ImagingConstants.
    394     * @return An instance of ICC_Profile or null if the image contains no ICC
    395     *         profile.
    396     * @throws ImageReadException if it fails to parse the image
    397     * @throws IOException if it fails to read the image data
    398     */
    399    public static ICC_Profile getICCProfile(final InputStream is, final String fileName,
    400            final Map<String, Object> params) throws ImageReadException, IOException {
    401        return getICCProfile(new ByteSourceInputStream(is, fileName), params);
    402    }
    403
    404    /**
    405     * Extracts an ICC Profile (if present) from JPEG, PNG, PSD (Photoshop) and
    406     * TIFF images.
    407     *
    408     * @param file
    409     *            File containing image data.
    410     * @return An instance of ICC_Profile or null if the image contains no ICC
    411     *         profile.
    412     * @throws ImageReadException if it fails to parse the image
    413     * @throws IOException if it fails to read the image data
    414     */
    415    public static ICC_Profile getICCProfile(final File file)
    416            throws ImageReadException, IOException {
    417        return getICCProfile(file, null);
    418    }
    419
    420    /**
    421     * Extracts an ICC Profile (if present) from JPEG, PNG, PSD (Photoshop) and
    422     * TIFF images.
    423     *
    424     * @param file
    425     *            File containing image data.
    426     * @param params
    427     *            Map of optional parameters, defined in ImagingConstants.
    428     * @return An instance of ICC_Profile or null if the image contains no ICC
    429     *         profile.
    430     * @throws ImageReadException if it fails to parse the image
    431     * @throws IOException if it fails to read the image data
    432     */
    433    public static ICC_Profile getICCProfile(final File file, final Map<String, Object> params)
    434            throws ImageReadException, IOException {
    435        return getICCProfile(new ByteSourceFile(file), params);
    436    }
    437
    438    protected static ICC_Profile getICCProfile(final ByteSource byteSource, final Map<String, Object> params)
    439            throws ImageReadException, IOException {
    440        final byte[] bytes = getICCProfileBytes(byteSource, params);
    441        if (bytes == null) {
    442            return null;
    443        }
    444
    445        final IccProfileParser parser = new IccProfileParser();
    446        final IccProfileInfo info = parser.getICCProfileInfo(bytes);
    447        if (info == null) {
    448            return null;
    449        }
    450        if (info.issRGB()) {
    451            return null;
    452        }
    453
    454        return ICC_Profile.getInstance(bytes);
    455    }
    456
    457    /**
    458     * Extracts the raw bytes of an ICC Profile (if present) from JPEG, PNG, PSD
    459     * (Photoshop) and TIFF images.
    460     *
    461     * <p>To parse the result use IccProfileParser or
    462     * ICC_Profile.getInstance(bytes).</p>
    463     *
    464     * @param bytes
    465     *            Byte array containing an image file.
    466     * @return A byte array.
    467     * @see IccProfileParser
    468     * @see ICC_Profile
    469     * @throws ImageReadException if it fails to parse the image
    470     * @throws IOException if it fails to read the image data
    471     */
    472    public static byte[] getICCProfileBytes(final byte[] bytes)
    473            throws ImageReadException, IOException {
    474        return getICCProfileBytes(bytes, null);
    475    }
    476
    477    /**
    478     * Extracts the raw bytes of an ICC Profile (if present) from JPEG, PNG, PSD
    479     * (Photoshop) and TIFF images.
    480     *
    481     * <p>To parse the result use IccProfileParser or
    482     * ICC_Profile.getInstance(bytes).</p>
    483     *
    484     * @param bytes
    485     *            Byte array containing an image file.
    486     * @param params
    487     *            Map of optional parameters, defined in ImagingConstants.
    488     * @return A byte array.
    489     * @see IccProfileParser
    490     * @see ICC_Profile
    491     * @throws ImageReadException if it fails to parse the image
    492     * @throws IOException if it fails to read the image data
    493     */
    494    public static byte[] getICCProfileBytes(final byte[] bytes, final Map<String, Object> params)
    495            throws ImageReadException, IOException {
    496        return getICCProfileBytes(new ByteSourceArray(bytes), params);
    497    }
    498
    499    /**
    500     * Extracts the raw bytes of an ICC Profile (if present) from JPEG, PNG, PSD
    501     * (Photoshop) and TIFF images.
    502     *
    503     * <p>To parse the result use IccProfileParser or
    504     * ICC_Profile.getInstance(bytes).</p>
    505     *
    506     * @param file
    507     *            File containing image data.
    508     * @return A byte array.
    509     * @see IccProfileParser
    510     * @see ICC_Profile
    511     * @throws ImageReadException if it fails to parse the image
    512     * @throws IOException if it fails to read the image data
    513     */
    514    public static byte[] getICCProfileBytes(final File file)
    515            throws ImageReadException, IOException {
    516        return getICCProfileBytes(file, null);
    517    }
    518
    519    /**
    520     * Extracts the raw bytes of an ICC Profile (if present) from JPEG, PNG, PSD
    521     * (Photoshop) and TIFF images.
    522     *
    523     * <p>To parse the result use IccProfileParser or
    524     * ICC_Profile.getInstance(bytes).</p>
    525     *
    526     * @param file
    527     *            File containing image data.
    528     * @param params
    529     *            Map of optional parameters, defined in ImagingConstants.
    530     * @return A byte array.
    531     * @see IccProfileParser
    532     * @see ICC_Profile
    533     * @throws ImageReadException if it fails to parse the image
    534     * @throws IOException if it fails to read the image data
    535     */
    536    public static byte[] getICCProfileBytes(final File file, final Map<String, Object> params)
    537            throws ImageReadException, IOException {
    538        return getICCProfileBytes(new ByteSourceFile(file), params);
    539    }
    540
    541    private static byte[] getICCProfileBytes(final ByteSource byteSource, final Map<String, Object> params)
    542            throws ImageReadException, IOException {
    543        final ImageParser imageParser = getImageParser(byteSource);
    544
    545        return imageParser.getICCProfileBytes(byteSource, params);
    546    }
    547
    548    /**
    549     * Parses the "image info" of an image.
    550     *
    551     * <p>"Image info" is a summary of basic information about the image such as:
    552     * width, height, file format, bit depth, color type, etc.</p>
    553     *
    554     * <p>Not to be confused with "image metadata."</p>
    555     *
    556     * @param fileName
    557     *            String.
    558     * @param bytes
    559     *            Byte array containing an image file.
    560     * @param params
    561     *            Map of optional parameters, defined in ImagingConstants.
    562     * @return An instance of ImageInfo.
    563     * @see ImageInfo
    564     * @throws ImageReadException if it fails to parse the image
    565     * @throws IOException if it fails to read the image data
    566     */
    567    public static ImageInfo getImageInfo(final String fileName, final byte[] bytes,
    568            final Map<String, Object> params) throws ImageReadException, IOException {
    569        return getImageInfo(new ByteSourceArray(fileName, bytes), params);
    570    }
    571
    572    /**
    573     * Parses the "image info" of an image.
    574     *
    575     * <p>"Image info" is a summary of basic information about the image such as:
    576     * width, height, file format, bit depth, color type, etc.</p>
    577     *
    578     * <p>Not to be confused with "image metadata."</p>
    579     *
    580     * @param fileName
    581     *            String.
    582     * @param bytes
    583     *            Byte array containing an image file.
    584     * @return An instance of ImageInfo.
    585     * @see ImageInfo
    586     * @throws ImageReadException if it fails to parse the image
    587     * @throws IOException if it fails to read the image data
    588     */
    589    public static ImageInfo getImageInfo(final String fileName, final byte[] bytes)
    590            throws ImageReadException, IOException {
    591        return getImageInfo(new ByteSourceArray(fileName, bytes), null);
    592    }
    593
    594    /**
    595     * <p>Parses the "image info" of an image.</p>
    596     *
    597     * <p>"Image info" is a summary of basic information about the image such as:
    598     * width, height, file format, bit depth, color type, etc.</p>
    599     *
    600     * <p>Not to be confused with "image metadata."</p>
    601     *
    602     * @param is
    603     *            InputStream from which to read image data.
    604     * @param fileName
    605     *            Filename associated with image data (optional).
    606     * @return An instance of ImageInfo.
    607     * @see ImageInfo
    608     * @throws ImageReadException if it fails to parse the image
    609     * @throws IOException if it fails to read the image data
    610     */
    611    public static ImageInfo getImageInfo(final InputStream is, final String fileName)
    612            throws ImageReadException, IOException {
    613        return getImageInfo(new ByteSourceInputStream(is, fileName), null);
    614    }
    615
    616    /**
    617     * <p>Parses the "image info" of an image.</p>
    618     *
    619     * <p>"Image info" is a summary of basic information about the image such as:
    620     * width, height, file format, bit depth, color type, etc.</p>
    621     *
    622     * <p>Not to be confused with "image metadata."</p>
    623     *
    624     * @param is
    625     *            InputStream from which to read image data.
    626     * @param fileName
    627     *            Filename associated with image data (optional).
    628     * @param params
    629     *            Map of optional parameters, defined in ImagingConstants.
    630     * @return An instance of ImageInfo.
    631     * @see ImageInfo
    632     * @throws ImageReadException if it fails to parse the image
    633     * @throws IOException if it fails to read the image data
    634     */
    635    public static ImageInfo getImageInfo(final InputStream is, final String fileName,
    636            final Map<String, Object> params) throws ImageReadException, IOException {
    637        return getImageInfo(new ByteSourceInputStream(is, fileName), params);
    638    }
    639
    640    /**
    641     * Parses the "image info" of an image.
    642     *
    643     * <p>"Image info" is a summary of basic information about the image such as:
    644     * width, height, file format, bit depth, color type, etc.</p>
    645     *
    646     * <p>Not to be confused with "image metadata."</p>
    647     *
    648     * @param bytes
    649     *            Byte array containing an image file.
    650     * @return An instance of ImageInfo.
    651     * @see ImageInfo
    652     * @throws ImageReadException if it fails to parse the image
    653     * @throws IOException if it fails to read the image data
    654     */
    655    public static ImageInfo getImageInfo(final byte[] bytes)
    656            throws ImageReadException, IOException {
    657        return getImageInfo(new ByteSourceArray(bytes), null);
    658    }
    659
    660    /**
    661     * <p>Parses the "image info" of an image.</p>
    662     *
    663     * <p>"Image info" is a summary of basic information about the image such as:
    664     * width, height, file format, bit depth, color type, etc.</p>
    665     *
    666     * <p>Not to be confused with "image metadata."</p>
    667     *
    668     * @param bytes
    669     *            Byte array containing an image file.
    670     * @param params
    671     *            Map of optional parameters, defined in ImagingConstants.
    672     * @return An instance of ImageInfo.
    673     * @see ImageInfo
    674     * @throws ImageReadException if it fails to parse the image
    675     * @throws IOException if it fails to read the image data
    676     */
    677    public static ImageInfo getImageInfo(final byte[] bytes, final Map<String, Object> params)
    678            throws ImageReadException, IOException {
    679        return getImageInfo(new ByteSourceArray(bytes), params);
    680    }
    681
    682    /**
    683     * <p>Parses the "image info" of an image file.</p>
    684     *
    685     * <p>"Image info" is a summary of basic information about the image such as:
    686     * width, height, file format, bit depth, color type, etc.</p>
    687     *
    688     * <p>Not to be confused with "image metadata."</p>
    689     *
    690     * @param file
    691     *            File containing image data.
    692     * @param params
    693     *            Map of optional parameters, defined in ImagingConstants.
    694     * @return An instance of ImageInfo.
    695     * @see ImageInfo
    696     * @throws ImageReadException if it fails to parse the image
    697     * @throws IOException if it fails to read the image data
    698     */
    699    public static ImageInfo getImageInfo(final File file, final Map<String, Object> params)
    700            throws ImageReadException, IOException {
    701        return getImageInfo(new ByteSourceFile(file), params);
    702    }
    703
    704    /**
    705     * Parses the "image info" of an image file.
    706     *
    707     * <p>"Image info" is a summary of basic information about the image such as:
    708     * width, height, file format, bit depth, color type, etc.</p>
    709     *
    710     * <p>Not to be confused with "image metadata."</p>
    711     *
    712     * @param file
    713     *            File containing image data.
    714     * @return An instance of ImageInfo.
    715     * @see ImageInfo
    716     * @throws ImageReadException if it fails to parse the image
    717     * @throws IOException if it fails to read the image data
    718     */
    719    public static ImageInfo getImageInfo(final File file) throws ImageReadException,
    720            IOException {
    721        return getImageInfo(file, null);
    722    }
    723
    724    private static ImageInfo getImageInfo(final ByteSource byteSource, final Map<String, Object> params)
    725            throws ImageReadException, IOException {
    726        return getImageParser(byteSource).getImageInfo(byteSource, params);
    727    }
    728
    729    private static ImageParser getImageParser(final ByteSource byteSource)
    730            throws ImageReadException, IOException {
    731        final ImageFormat format = guessFormat(byteSource);
    732        if (!format.equals(ImageFormats.UNKNOWN)) {
    733
    734            final ImageParser[] imageParsers = ImageParser.getAllImageParsers();
    735
    736            for (final ImageParser imageParser : imageParsers) {
    737                if (imageParser.canAcceptType(format)) {
    738                    return imageParser;
    739                }
    740            }
    741        }
    742
    743        final String fileName = byteSource.getFileName();
    744        if (fileName != null) {
    745            final ImageParser[] imageParsers = ImageParser.getAllImageParsers();
    746
    747            for (final ImageParser imageParser : imageParsers) {
    748                if (imageParser.canAcceptExtension(fileName)) {
    749                    return imageParser;
    750                }
    751            }
    752        }
    753
    754        throw new ImageReadException("Can't parse this format.");
    755    }
    756
    757    /**
    758     * Determines the width and height of an image.
    759     * <p>
    760     *
    761     * @param is
    762     *            InputStream from which to read image data.
    763     * @param fileName
    764     *            Filename associated with image data (optional).
    765     * @return The width and height of the image.
    766     * @throws ImageReadException if it fails to parse the image
    767     * @throws IOException if it fails to read the image data
    768     */
    769    public static Dimension getImageSize(final InputStream is, final String fileName)
    770            throws ImageReadException, IOException {
    771        return getImageSize(is, fileName, null);
    772    }
    773
    774    /**
    775     * Determines the width and height of an image.
    776     * <p>
    777     *
    778     * @param is
    779     *            InputStream from which to read image data.
    780     * @param fileName
    781     *            Filename associated with image data (optional).
    782     * @param params
    783     *            Map of optional parameters, defined in ImagingConstants.
    784     * @return The width and height of the image.
    785     * @throws ImageReadException if it fails to parse the image
    786     * @throws IOException if it fails to read the image data
    787     */
    788    public static Dimension getImageSize(final InputStream is, final String fileName,
    789            final Map<String, Object> params) throws ImageReadException, IOException {
    790        return getImageSize(new ByteSourceInputStream(is, fileName), params);
    791    }
    792
    793    /**
    794     * Determines the width and height of an image.
    795     * <p>
    796     *
    797     * @param bytes
    798     *            Byte array containing an image file.
    799     * @return The width and height of the image.
    800     * @throws ImageReadException if it fails to parse the image
    801     * @throws IOException if it fails to read the image data
    802     */
    803    public static Dimension getImageSize(final byte[] bytes)
    804            throws ImageReadException, IOException {
    805        return getImageSize(bytes, null);
    806    }
    807
    808    /**
    809     * Determines the width and height of an image.
    810     * <p>
    811     *
    812     * @param bytes
    813     *            Byte array containing an image file.
    814     * @param params
    815     *            Map of optional parameters, defined in ImagingConstants.
    816     * @return The width and height of the image.
    817     * @throws ImageReadException if it fails to parse the image
    818     * @throws IOException if it fails to read the image data
    819     */
    820    public static Dimension getImageSize(final byte[] bytes, final Map<String, Object> params)
    821            throws ImageReadException, IOException {
    822        return getImageSize(new ByteSourceArray(bytes), params);
    823    }
    824
    825    /**
    826     * Determines the width and height of an image file.
    827     * <p>
    828     *
    829     * @param file
    830     *            File containing image data.
    831     * @return The width and height of the image.
    832     * @throws ImageReadException if it fails to parse the image
    833     * @throws IOException if it fails to read the image data
    834     */
    835    public static Dimension getImageSize(final File file) throws ImageReadException,
    836            IOException {
    837        return getImageSize(file, null);
    838    }
    839
    840    /**
    841     * Determines the width and height of an image file.
    842     * <p>
    843     *
    844     * @param file
    845     *            File containing image data.
    846     * @param params
    847     *            Map of optional parameters, defined in ImagingConstants.
    848     * @return The width and height of the image.
    849     * @throws ImageReadException if it fails to parse the image
    850     * @throws IOException if it fails to read the image data
    851     */
    852    public static Dimension getImageSize(final File file, final Map<String, Object> params)
    853            throws ImageReadException, IOException {
    854        return getImageSize(new ByteSourceFile(file), params);
    855    }
    856
    857    public static Dimension getImageSize(final ByteSource byteSource, final Map<String, Object> params)
    858            throws ImageReadException, IOException {
    859        final ImageParser imageParser = getImageParser(byteSource);
    860
    861        return imageParser.getImageSize(byteSource, params);
    862    }
    863
    864    /**
    865     * Extracts the embedded XML metadata as an XML string.
    866     * <p>
    867     *
    868     * @param is
    869     *            InputStream from which to read image data.
    870     * @param fileName
    871     *            Filename associated with image data (optional).
    872     * @return Xmp Xml as String, if present. Otherwise, returns null.
    873     * @throws ImageReadException if it fails to parse the image
    874     * @throws IOException if it fails to read the image data
    875     */
    876    public static String getXmpXml(final InputStream is, final String fileName)
    877            throws ImageReadException, IOException {
    878        return getXmpXml(is, fileName, null);
    879    }
    880
    881    /**
    882     * Extracts the embedded XML metadata as an XML string.
    883     * <p>
    884     *
    885     * @param is
    886     *            InputStream from which to read image data.
    887     * @param fileName
    888     *            Filename associated with image data (optional).
    889     * @param params
    890     *            Map of optional parameters, defined in ImagingConstants.
    891     * @return Xmp Xml as String, if present. Otherwise, returns null.
    892     * @throws ImageReadException if it fails to parse the image
    893     * @throws IOException if it fails to read the image data
    894     */
    895    public static String getXmpXml(final InputStream is, final String fileName, final Map<String, Object> params)
    896            throws ImageReadException, IOException {
    897        return getXmpXml(new ByteSourceInputStream(is, fileName), params);
    898    }
    899
    900    /**
    901     * Extracts the embedded XML metadata as an XML string.
    902     * <p>
    903     *
    904     * @param bytes
    905     *            Byte array containing an image file.
    906     * @return Xmp Xml as String, if present. Otherwise, returns null.
    907     * @throws ImageReadException if it fails to parse the image
    908     * @throws IOException if it fails to read the image data
    909     */
    910    public static String getXmpXml(final byte[] bytes) throws ImageReadException,
    911            IOException {
    912        return getXmpXml(bytes, null);
    913    }
    914
    915    /**
    916     * Extracts the embedded XML metadata as an XML string.
    917     * <p>
    918     *
    919     * @param bytes
    920     *            Byte array containing an image file.
    921     * @param params
    922     *            Map of optional parameters, defined in ImagingConstants.
    923     * @return Xmp Xml as String, if present. Otherwise, returns null.
    924     * @throws ImageReadException if it fails to parse the image
    925     * @throws IOException if it fails to read the image data
    926     */
    927    public static String getXmpXml(final byte[] bytes, final Map<String, Object> params)
    928            throws ImageReadException, IOException {
    929        return getXmpXml(new ByteSourceArray(bytes), params);
    930    }
    931
    932    /**
    933     * Extracts the embedded XML metadata as an XML string.
    934     * <p>
    935     *
    936     * @param file
    937     *            File containing image data.
    938     * @return Xmp Xml as String, if present. Otherwise, returns null.
    939     * @throws ImageReadException if it fails to parse the image
    940     * @throws IOException if it fails to read the image data
    941     */
    942    public static String getXmpXml(final File file) throws ImageReadException,
    943            IOException {
    944        return getXmpXml(file, null);
    945    }
    946
    947    /**
    948     * Extracts the embedded XML metadata as an XML string.
    949     * <p>
    950     *
    951     * @param file
    952     *            File containing image data.
    953     * @param params
    954     *            Map of optional parameters, defined in ImagingConstants.
    955     * @return Xmp Xml as String, if present. Otherwise, returns null.
    956     * @throws ImageReadException if it fails to parse the image
    957     * @throws IOException if it fails to read the image data
    958     */
    959    public static String getXmpXml(final File file, final Map<String, Object> params)
    960            throws ImageReadException, IOException {
    961        return getXmpXml(new ByteSourceFile(file), params);
    962    }
    963
    964    /**
    965     * Extracts the embedded XML metadata as an XML string.
    966     * <p>
    967     *
    968     * @param byteSource
    969     *            File containing image data.
    970     * @param params
    971     *            Map of optional parameters, defined in ImagingConstants.
    972     * @return Xmp Xml as String, if present. Otherwise, returns null.
    973     * @throws ImageReadException if it fails to parse the image
    974     * @throws IOException if it fails to read the image data
    975     */
    976    public static String getXmpXml(final ByteSource byteSource, final Map<String, Object> params)
    977            throws ImageReadException, IOException {
    978        final ImageParser imageParser = getImageParser(byteSource);
    979        if (imageParser instanceof XmpEmbeddable) {
    980            return ((XmpEmbeddable) imageParser).getXmpXml(byteSource, params);
    981        }
    982        return null;
    983    }
    984
    985    /**
    986     * Parses the metadata of an image. This metadata depends on the format of
    987     * the image.
    988     * <p>
    989     * JPEG/JFIF files may contain EXIF and/or IPTC metadata. PNG files may
    990     * contain comments. TIFF files may contain metadata.
    991     * <p>
    992     * The instance of IImageMetadata returned by getMetadata() should be upcast
    993     * (depending on image format).
    994     * <p>
    995     * Not to be confused with "image info."
    996     * <p>
    997     *
    998     * @param bytes
    999     *            Byte array containing an image file.
    1000     * @return An instance of IImageMetadata.
    1001     * @see org.apache.commons.imaging.common.ImageMetadata
    1002     * @throws ImageReadException if it fails to read the image metadata
    1003     * @throws IOException if it fails to read the image data
    1004     */
    1005    public static ImageMetadata getMetadata(final byte[] bytes)
    1006            throws ImageReadException, IOException {
    1007        return getMetadata(bytes, null);
    1008    }
    1009
    1010    /**
    1011     * Parses the metadata of an image. This metadata depends on the format of
    1012     * the image.
    1013     * <p>
    1014     * JPEG/JFIF files may contain EXIF and/or IPTC metadata. PNG files may
    1015     * contain comments. TIFF files may contain metadata.
    1016     * <p>
    1017     * The instance of IImageMetadata returned by getMetadata() should be upcast
    1018     * (depending on image format).
    1019     * <p>
    1020     * Not to be confused with "image info."
    1021     * <p>
    1022     *
    1023     * @param bytes
    1024     *            Byte array containing an image file.
    1025     * @param params
    1026     *            Map of optional parameters, defined in ImagingConstants.
    1027     * @return An instance of IImageMetadata.
    1028     * @see org.apache.commons.imaging.common.ImageMetadata
    1029     * @throws ImageReadException if it fails to read the image metadata
    1030     * @throws IOException if it fails to read the image data
    1031     */
    1032    public static ImageMetadata getMetadata(final byte[] bytes, final Map<String, Object> params)
    1033            throws ImageReadException, IOException {
    1034        return getMetadata(new ByteSourceArray(bytes), params);
    1035    }
    1036
    1037    /**
    1038     * Parses the metadata of an image file. This metadata depends on the format
    1039     * of the image.
    1040     * <p>
    1041     * JPEG/JFIF files may contain EXIF and/or IPTC metadata. PNG files may
    1042     * contain comments. TIFF files may contain metadata.
    1043     * <p>
    1044     * The instance of IImageMetadata returned by getMetadata() should be upcast
    1045     * (depending on image format).
    1046     * <p>
    1047     * Not to be confused with "image info."
    1048     * <p>
    1049     *
    1050     * @param is
    1051     *            InputStream from which to read image data.
    1052     * @param fileName
    1053     *            Filename associated with image data (optional).
    1054     * @return An instance of IImageMetadata.
    1055     * @see org.apache.commons.imaging.common.ImageMetadata
    1056     * @throws ImageReadException if it fails to read the image metadata
    1057     * @throws IOException if it fails to read the image data
    1058     */
    1059    public static ImageMetadata getMetadata(final InputStream is, final String fileName)
    1060            throws ImageReadException, IOException {
    1061        return getMetadata(is, fileName, null);
    1062    }
    1063
    1064    /**
    1065     * Parses the metadata of an image file. This metadata depends on the format
    1066     * of the image.
    1067     * <p>
    1068     * JPEG/JFIF files may contain EXIF and/or IPTC metadata. PNG files may
    1069     * contain comments. TIFF files may contain metadata.
    1070     * <p>
    1071     * The instance of IImageMetadata returned by getMetadata() should be upcast
    1072     * (depending on image format).
    1073     * <p>
    1074     * Not to be confused with "image info."
    1075     * <p>
    1076     *
    1077     * @param is
    1078     *            InputStream from which to read image data.
    1079     * @param fileName
    1080     *            Filename associated with image data (optional).
    1081     * @param params
    1082     *            Map of optional parameters, defined in ImagingConstants.
    1083     * @return An instance of IImageMetadata.
    1084     * @see org.apache.commons.imaging.common.ImageMetadata
    1085     * @throws ImageReadException if it fails to read the image metadata
    1086     * @throws IOException if it fails to read the image data
    1087     */
    1088    public static ImageMetadata getMetadata(final InputStream is, final String fileName,
    1089            final Map<String, Object> params) throws ImageReadException, IOException {
    1090        return getMetadata(new ByteSourceInputStream(is, fileName), params);
    1091    }
    1092
    1093    /**
    1094     * Parses the metadata of an image file. This metadata depends on the format
    1095     * of the image.
    1096     * <p>
    1097     * JPEG/JFIF files may contain EXIF and/or IPTC metadata. PNG files may
    1098     * contain comments. TIFF files may contain metadata.
    1099     * <p>
    1100     * The instance of IImageMetadata returned by getMetadata() should be upcast
    1101     * (depending on image format).
    1102     * <p>
    1103     * Not to be confused with "image info."
    1104     * <p>
    1105     *
    1106     * @param file
    1107     *            File containing image data.
    1108     * @return An instance of IImageMetadata.
    1109     * @see org.apache.commons.imaging.common.ImageMetadata
    1110     * @throws ImageReadException if it fails to read the image metadata
    1111     * @throws IOException if it fails to read the image data
    1112     */
    1113    public static ImageMetadata getMetadata(final File file)
    1114            throws ImageReadException, IOException {
    1115        return getMetadata(file, null);
    1116    }
    1117
    1118    /**
    1119     * Parses the metadata of an image file. This metadata depends on the format
    1120     * of the image.
    1121     * <p>
    1122     * JPEG/JFIF files may contain EXIF and/or IPTC metadata. PNG files may
    1123     * contain comments. TIFF files may contain metadata.
    1124     * <p>
    1125     * The instance of IImageMetadata returned by getMetadata() should be upcast
    1126     * (depending on image format).
    1127     * <p>
    1128     * Not to be confused with "image info."
    1129     * <p>
    1130     *
    1131     * @param file
    1132     *            File containing image data.
    1133     * @param params
    1134     *            Map of optional parameters, defined in ImagingConstants.
    1135     * @return An instance of IImageMetadata.
    1136     * @see org.apache.commons.imaging.common.ImageMetadata
    1137     * @throws ImageReadException if it fails to read the image metadata
    1138     * @throws IOException if it fails to read the image data
    1139     */
    1140    public static ImageMetadata getMetadata(final File file, final Map<String, Object> params)
    1141            throws ImageReadException, IOException {
    1142        return getMetadata(new ByteSourceFile(file), params);
    1143    }
    1144
    1145    private static ImageMetadata getMetadata(final ByteSource byteSource, final Map<String, Object> params)
    1146            throws ImageReadException, IOException {
    1147        final ImageParser imageParser = getImageParser(byteSource);
    1148
    1149        return imageParser.getMetadata(byteSource, params);
    1150    }
    1151
    1152    /**
    1153     * Write the ImageInfo and format-specific information for the image
    1154     * content of the specified byte array to a string.
    1155     * @param bytes A valid array of bytes.
    1156     * @return A valid string.
    1157     * @throws ImageReadException In the event that the specified
    1158     * content does not conform to the format of the specific parser
    1159     * implementation.
    1160     * @throws IOException In the event of unsuccessful read or
    1161     * access operation.
    1162     */
    1163    public static String dumpImageFile(final byte[] bytes) throws ImageReadException,
    1164            IOException {
    1165        return dumpImageFile(new ByteSourceArray(bytes));
    1166    }
    1167
    1168    /**
    1169     * Write the ImageInfo and format-specific information for the image
    1170     * content of the specified file to a string.
    1171     * @param file A valid file reference.
    1172     * @return A valid string.
    1173     * @throws ImageReadException In the event that the specified
    1174     * content does not conform to the format of the specific parser
    1175     * implementation.
    1176     * @throws IOException In the event of unsuccessful read or
    1177     * access operation.
    1178     */
    1179    public static String dumpImageFile(final File file) throws ImageReadException,
    1180            IOException {
    1181        return dumpImageFile(new ByteSourceFile(file));
    1182    }
    1183
    1184    private static String dumpImageFile(final ByteSource byteSource)
    1185            throws ImageReadException, IOException {
    1186        final ImageParser imageParser = getImageParser(byteSource);
    1187
    1188        return imageParser.dumpImageFile(byteSource);
    1189    }
    1190
    1191    /**
    1192     * Attempts to determine the image format of the specified data and
    1193     * evaluates its format compliance.   This method
    1194     * returns a FormatCompliance object which includes information
    1195     * about the data's compliance to a specific format.
    1196     * @param bytes a valid array of bytes containing image data.
    1197     * @return if successful, a valid FormatCompliance object.
    1198     * @throws ImageReadException in the event of unreadable data.
    1199     * @throws IOException in the event of an unrecoverable I/O condition.
    1200     */
    1201    public static FormatCompliance getFormatCompliance(final byte[] bytes)
    1202            throws ImageReadException, IOException {
    1203        return getFormatCompliance(new ByteSourceArray(bytes));
    1204    }
    1205
    1206    /**
    1207     * Attempts to determine the image format of the specified data and
    1208     * evaluates its format compliance.   This method
    1209     * returns a FormatCompliance object which includes information
    1210     * about the data's compliance to a specific format.
    1211     * @param file valid file containing image data
    1212     * @return if successful, a valid FormatCompliance object.
    1213     * @throws ImageReadException in the event of unreadable data.
    1214     * @throws IOException in the event of an unrecoverable I/O condition.
    1215     */
    1216    public static FormatCompliance getFormatCompliance(final File file)
    1217            throws ImageReadException, IOException {
    1218        return getFormatCompliance(new ByteSourceFile(file));
    1219    }
    1220
    1221    private static FormatCompliance getFormatCompliance(final ByteSource byteSource)
    1222            throws ImageReadException, IOException {
    1223        final ImageParser imageParser = getImageParser(byteSource);
    1224
    1225        return imageParser.getFormatCompliance(byteSource);
    1226    }
    1227
    1228    /**
    1229     * Gets all images specified by the InputStream  (some
    1230     * formats may include multiple images within a single data source).
    1231     * @param is A valid InputStream
    1232     * @param fileName image file name
    1233     * @return A valid (potentially empty) list of BufferedImage objects.
    1234     * @throws ImageReadException In the event that the specified
    1235     * content does not conform to the format of the specific parser
    1236     * implementation.
    1237     * @throws IOException In the event of unsuccessful read or
    1238     * access operation.
    1239     */
    1240    public static List<BufferedImage> getAllBufferedImages(final InputStream is,
    1241            final String fileName) throws ImageReadException, IOException {
    1242        return getAllBufferedImages(new ByteSourceInputStream(is, fileName));
    1243    }
    1244
    1245    /**
    1246     * Gets all images specified by the byte array (some
    1247     * formats may include multiple images within a single data source).
    1248     * @param bytes a valid array of bytes
    1249     * @return A valid (potentially empty) list of BufferedImage objects.
    1250     * @throws ImageReadException In the event that the specified
    1251     * content does not conform to the format of the specific parser
    1252     * implementation.
    1253     * @throws IOException In the event of unsuccessful read or
    1254     * access operation.
    1255     */
    1256    public static List<BufferedImage> getAllBufferedImages(final byte[] bytes)
    1257            throws ImageReadException, IOException {
    1258        return getAllBufferedImages(new ByteSourceArray(bytes));
    1259    }
    1260
    1261   /**
    1262     * Gets all images specified by the file (some
    1263     * formats may include multiple images within a single data source).
    1264     * @param file A reference to a valid data file.
    1265     * @return A valid (potentially empty) list of BufferedImage objects.
    1266     * @throws ImageReadException In the event that the specified
    1267     * content does not conform to the format of the specific parser
    1268     * implementation.
    1269     * @throws IOException In the event of unsuccessful read or
    1270     * access operation.
    1271     */
    1272    public static List<BufferedImage> getAllBufferedImages(final File file)
    1273            throws ImageReadException, IOException {
    1274        return getAllBufferedImages(new ByteSourceFile(file));
    1275    }
    1276
    1277
    1278    private static List<BufferedImage> getAllBufferedImages(
    1279            final ByteSource byteSource) throws ImageReadException, IOException {
    1280        final ImageParser imageParser = getImageParser(byteSource);
    1281
    1282        return imageParser.getAllBufferedImages(byteSource);
    1283    }
    1284
    1285
    1286    /**
    1287     * Reads the first image from an InputStream.
    1288     * <p>
    1289     * For the most recent information on support for specific formats, refer to
    1290     * <a href="https://commons.apache.org/imaging/formatsupport.html">Format Support</a>
    1291     * at the main project development web site.   While the Apache Commons
    1292     * Imaging package does not fully support all formats, it  can read
    1293     * image info, metadata and ICC profiles from all image formats that
    1294     * provide this data.
    1295     * @param is a valid ImageStream from which to read data.
    1296     * @return if successful, a valid buffered image
    1297     * @throws ImageReadException in the event of a processing error
    1298     * while reading an image (i.e. a format violation, etc.).
    1299     * @throws IOException  in the event of an unrecoverable I/O exception.
    1300     */
    1301
    1302    public static BufferedImage getBufferedImage(final InputStream is)
    1303            throws ImageReadException, IOException {
    1304        return getBufferedImage(is, null);
    1305    }
    1306
    1307
    1308
    1309    /**
    1310     * Reads the first image from an InputStream
    1311     * using data-processing options specified through a parameters
    1312     * map.  Options may be configured using the ImagingContants
    1313     * interface or the various format-specific implementations provided
    1314     * by this package.
    1315     * <p>
    1316     * For the most recent information on support for specific formats, refer to
    1317     * <a href="https://commons.apache.org/imaging/formatsupport.html">Format Support</a>
    1318     * at the main project development web site.   While the Apache Commons
    1319     * Imaging package does not fully support all formats, it  can read
    1320     * image info, metadata and ICC profiles from all image formats that
    1321     * provide this data.
    1322     * @param is a valid ImageStream from which to read data.
    1323     * @param params an optional parameters map specifying options
    1324     * @return if successful, a valid buffered image
    1325     * @throws ImageReadException in the event of a processing error
    1326     * while reading an image (i.e. a format violation, etc.).
    1327     * @throws IOException  in the event of an unrecoverable I/O exception.
    1328     */
    1329    public static BufferedImage getBufferedImage(final InputStream is, final Map<String, Object> params)
    1330            throws ImageReadException, IOException {
    1331        String fileName = null;
    1332        if (params != null && params.containsKey(PARAM_KEY_FILENAME)) {
    1333            fileName = (String) params.get(PARAM_KEY_FILENAME);
    1334        }
    1335        return getBufferedImage(new ByteSourceInputStream(is, fileName), params);
    1336    }
    1337
    1338    /**
    1339     * Reads the first image from a byte array.
    1340     * <p>
    1341     * For the most recent information on support for specific formats, refer to
    1342     * <a href="https://commons.apache.org/imaging/formatsupport.html">Format Support</a>
    1343     * at the main project development web site.   While the Apache Commons
    1344     * Imaging package does not fully support all formats, it  can read
    1345     * image info, metadata and ICC profiles from all image formats that
    1346     * provide this data.
    1347     * @param bytes a valid array of bytes from which to read data.
    1348     * @return if successful, a valid buffered image
    1349     * @throws ImageReadException in the event of a processing error
    1350     * while reading an image (i.e. a format violation, etc.).
    1351     * @throws IOException  in the event of an unrecoverable I/O exception.
    1352     */
    1353    public static BufferedImage getBufferedImage(final byte[] bytes)
    1354            throws ImageReadException, IOException {
    1355        return getBufferedImage(new ByteSourceArray(bytes), null);
    1356    }
    1357
    1358
    1359    /**
    1360     * Reads the first image from a byte array
    1361     * using data-processing options specified through a parameters
    1362     * map.  Options may be configured using the ImagingContants
    1363     * interface or the various format-specific implementations provided
    1364     * by this package.
    1365     * <p>
    1366     * For the most recent information on support for specific formats, refer to
    1367     * <a href="https://commons.apache.org/imaging/formatsupport.html">Format Support</a>
    1368     * at the main project development web site.   While the Apache Commons
    1369     * Imaging package does not fully support all formats, it  can read
    1370     * image info, metadata and ICC profiles from all image formats that
    1371     * provide this data.
    1372     * @param bytes a valid array of bytes from which to read data.
    1373     * @param params an optional parameters map specifying options.
    1374     * @return if successful, a valid buffered image
    1375     * @throws ImageReadException in the event of a processing error
    1376     * while reading an image (i.e. a format violation, etc.).
    1377     * @throws IOException  in the event of an unrecoverable I/O exception.
    1378     */
    1379    public static BufferedImage getBufferedImage(final byte[] bytes, final Map<String, Object> params)
    1380            throws ImageReadException, IOException {
    1381        return getBufferedImage(new ByteSourceArray(bytes), params);
    1382    }
    1383
    1384
    1385
    1386
    1387    /**
    1388     * Reads the first image from a file.
    1389     * <p>
    1390     * For the most recent information on support for specific formats, refer to
    1391     * <a href="https://commons.apache.org/imaging/formatsupport.html">Format Support</a>
    1392     * at the main project development web site.   While the Apache Commons
    1393     * Imaging package does not fully support all formats, it  can read
    1394     * image info, metadata and ICC profiles from all image formats that
    1395     * provide this data.
    1396     * @param file a valid reference to a file containing image data.
    1397     * @return if successful, a valid buffered image
    1398     * @throws ImageReadException in the event of a processing error
    1399     * while reading an image (i.e. a format violation, etc.).
    1400     * @throws IOException  in the event of an unrecoverable I/O exception.
    1401     */
    1402    public static BufferedImage getBufferedImage(final File file)
    1403            throws ImageReadException, IOException {
    1404        return getBufferedImage(new ByteSourceFile(file), null);
    1405    }
    1406
    1407
    1408    /**
    1409     * Reads the first image from a file
    1410     * using data-processing options specified through a parameters
    1411     * map.  Options may be configured using the ImagingContants
    1412     * interface or the various format-specific implementations provided
    1413     * by this package.
    1414     * <p>
    1415     * For the most recent information on support for specific formats, refer to
    1416     * <a href="https://commons.apache.org/imaging/formatsupport.html">Format Support</a>
    1417     * at the main project development web site.   While the Apache Commons
    1418     * Imaging package does not fully support all formats, it  can read
    1419     * image info, metadata and ICC profiles from all image formats that
    1420     * provide this data.
    1421     * @param file a valid reference to a file containing image data.
    1422     * @param params parameters map.
    1423     * @return if successful, a valid buffered image
    1424     * @throws ImageReadException in the event of a processing error
    1425     * while reading an image (i.e. a format violation, etc.).
    1426     * @throws IOException  in the event of an unrecoverable I/O exception.
    1427     */
    1428    public static BufferedImage getBufferedImage(final File file, final Map<String, Object> params)
    1429            throws ImageReadException, IOException {
    1430        return getBufferedImage(new ByteSourceFile(file), params);
    1431    }
    1432
    1433
    1434
    1435    private static BufferedImage getBufferedImage(final ByteSource byteSource,
    1436            Map<String, Object> params) throws ImageReadException, IOException {
    1437        final ImageParser imageParser = getImageParser(byteSource);
    1438        if (null == params) {
    1439            params = new HashMap<>();
    1440        }
    1441
    1442        return imageParser.getBufferedImage(byteSource, params);
    1443    }
    1444
    1445     /**
    1446     * Writes the content of a BufferedImage to a file using the specified
    1447     * image format.  Specifications for storing the file (such as data compression,
    1448     * color models, metadata tags, etc.) may be specified using an optional
    1449     * parameters map. These specifications are defined in the ImagingConstants
    1450     * interface or in various format-specific implementations.
    1451     * <p>
    1452     * Image writing is not supported for all graphics formats.
    1453     * For the most recent information on support for specific formats, refer to
    1454     * <a href="https://commons.apache.org/imaging/formatsupport.html">Format Support</a>
    1455     * at the main project development web site.   While the Apache Commons
    1456     * Imaging package does not fully support all formats, it  can read
    1457     * image info, metadata and ICC profiles from all image formats that
    1458     * provide this data.
    1459     * @param src a valid BufferedImage object
    1460     * @param file the file to which the output image is to be written
    1461     * @param format the format in which the output image is to be written
    1462     * @param params an optional parameters map (nulls permitted)
    1463     * @throws ImageWriteException in the event of a format violation,
    1464     * unsupported image format, etc.
    1465     * @throws IOException in the event of an unrecoverable I/O exception.
    1466     * @see ImagingConstants
    1467     */
    1468    public static void writeImage(final BufferedImage src, final File file,
    1469            final ImageFormat format, final Map<String, Object> params) throws ImageWriteException,
    1470            IOException {
    1471        try (FileOutputStream fos = new FileOutputStream(file);
    1472                BufferedOutputStream os = new BufferedOutputStream(fos)) {
    1473            writeImage(src, os, format, params);
    1474        }
    1475    }
    1476
    1477
    1478    /**
    1479     * Writes the content of a BufferedImage to a byte array using the specified
    1480     * image format.  Specifications for storing the file (such as data compression,
    1481     * color models, metadata tags, etc.) may be specified using an optional
    1482     * parameters map. These specifications are defined in the ImagingConstants
    1483     * interface or in various format-specific implementations.
    1484     * <p>
    1485     * Image writing is not supported for all graphics formats.
    1486     * For the most recent information on support for specific formats, refer to
    1487     * <a href="https://commons.apache.org/imaging/formatsupport.html">Format Support</a>
    1488     * at the main project development web site.   While the Apache Commons
    1489     * Imaging package does not fully support all formats, it  can read
    1490     * image info, metadata and ICC profiles from all image formats that
    1491     * provide this data.
    1492     * @param src a valid BufferedImage object
    1493     * @param format the format in which the output image is to be written
    1494     * @param params an optional parameters map (nulls permitted)
    1495     * @return if successful, a valid array of bytes.
    1496     * @throws ImageWriteException in the event of a format violation,
    1497     * unsupported image format, etc.
    1498     * @throws IOException in the event of an unrecoverable I/O exception.
    1499     * @see ImagingConstants
    1500     */
    1501    public static byte[] writeImageToBytes(final BufferedImage src,
    1502            final ImageFormat format, final Map<String, Object> params) throws ImageWriteException,
    1503            IOException {
    1504        final ByteArrayOutputStream os = new ByteArrayOutputStream();
    1505
    1506        writeImage(src, os, format, params);
    1507
    1508        return os.toByteArray();
    1509    }
    1510
    1511
    1512     /**
    1513     * Writes the content of a BufferedImage to an OutputStream using the specified
    1514     * image format.  Specifications for storing the file (such as data compression,
    1515     * color models, metadata tags, etc.) may be specified using an optional
    1516     * parameters map. These specifications are defined in the ImagingConstants
    1517     * interface or in various format-specific implementations.
    1518     * <p>
    1519     * Image writing is not supported for all graphics formats.
    1520     * For the most recent information on support for specific formats, refer to
    1521     * <a href="https://commons.apache.org/imaging/formatsupport.html">Format Support</a>
    1522     * at the main project development web site.   While the Apache Commons
    1523     * Imaging package does not fully support all formats, it  can read
    1524     * image info, metadata and ICC profiles from all image formats that
    1525     * provide this data.
    1526     * @param src a valid BufferedImage object
    1527     * @param os the OutputStream to which the output image is to be written
    1528     * @param format the format in which the output image is to be written
    1529     * @param params an optional parameters map (nulls permitted)
    1530     * @throws ImageWriteException in the event of a format violation,
    1531     * unsupported image format, etc.
    1532     * @throws IOException in the event of an unrecoverable I/O exception.
    1533     * @see ImagingConstants
    1534     */
    1535    public static void writeImage(final BufferedImage src, final OutputStream os,
    1536            final ImageFormat format, Map<String, Object> params) throws ImageWriteException,
    1537            IOException {
    1538        final ImageParser[] imageParsers = ImageParser.getAllImageParsers();
    1539
    1540        // make sure params are non-null
    1541        if (params == null) {
    1542            params = new HashMap<>();
    1543        }
    1544
    1545        params.put(PARAM_KEY_FORMAT, format);
    1546
    1547        ImageParser imageParser = null;
    1548        for (final ImageParser imageParser2 : imageParsers) {
    1549            if (imageParser2.canAcceptType(format)) {
    1550                imageParser = imageParser2;
    1551                break;
    1552            }
    1553        }
    1554        if (imageParser != null) {
    1555            imageParser.writeImage(src, os, params);
    1556        } else {
    1557            throw new ImageWriteException("Unknown Format: " + format);
    1558        }
    1559    }
    1560
    1561}