    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 java.io.PrintWriter;
    020import java.io.StringWriter;
    021import java.util.ArrayList;
    022import java.util.List;
    023import java.util.logging.Logger;
    024
    025/**
    026 * ImageInfo represents a collection of basic properties of an image, such as
    027 * width, height, format, bit depth, etc.
    028 */
    029public class ImageInfo {
    030
    031    public enum ColorType {
    032        BW("Black and White"),
    033        GRAYSCALE("Grayscale"),
    034        RGB("RGB"),
    035        CMYK("CMYK"),
    036        YCbCr("YCbCr"),
    037        YCCK("YCCK"),
    038        YCC("YCC"),
    039        OTHER("Other"),
    040        UNKNOWN("Unknown");
    041
    042        private String description;
    043
    044        ColorType(final String description) {
    045            this.description = description;
    046        }
    047
    048        @Override
    049        public String toString() {
    050            return description;
    051        }
    052    }
    053
    054    public enum CompressionAlgorithm {
    055        UNKNOWN("Unknown"),
    056        NONE("None"),
    057        LZW("LZW"),
    058        PACKBITS("PackBits"),
    059        JPEG("JPEG"),
    060        RLE("RLE: Run-Length Encoding"),
    061        ADAPTIVE_RLE("Adaptive RLE"),
    062        PSD("Photoshop"),
    063        PNG_FILTER("PNG Filter"),
    064        CCITT_GROUP_3("CCITT Group 3 1-Dimensional Modified Huffman run-length encoding."),
    065        CCITT_GROUP_4("CCITT Group 4"),
    066        CCITT_1D("CCITT 1D");
    067
    068        private String description;
    069
    070        CompressionAlgorithm(final String description) {
    071            this.description = description;
    072        }
    073
    074        @Override
    075        public String toString() {
    076            return description;
    077        }
    078    }
    079
    080    private static final Logger LOGGER = Logger.getLogger(ImageInfo.class.getName());
    081
    082    private final String formatDetails; // ie version
    083
    084    private final int bitsPerPixel;
    085    private final List<String> comments;
    086
    087    private final ImageFormat format;
    088    private final String formatName;
    089    private final int height;
    090    private final String mimeType;
    091
    092    private final int numberOfImages;
    093    private final int physicalHeightDpi;
    094    private final float physicalHeightInch;
    095    private final int physicalWidthDpi;
    096    private final float physicalWidthInch;
    097    private final int width;
    098    private final boolean progressive;
    099    private final boolean transparent;
    100
    101    private final boolean usesPalette;
    102
    103    private final ColorType colorType;
    104
    105    private final CompressionAlgorithm compressionAlgorithm;
    106
    107    public ImageInfo(final String formatDetails, final int bitsPerPixel,
    108            final List<String> comments, final ImageFormat format, final String formatName,
    109            final int height, final String mimeType, final int numberOfImages,
    110            final int physicalHeightDpi, final float physicalHeightInch,
    111            final int physicalWidthDpi, final float physicalWidthInch, final int width,
    112            final boolean progressive, final boolean transparent, final boolean usesPalette,
    113            final ColorType colorType, final CompressionAlgorithm compressionAlgorithm) {
    114        this.formatDetails = formatDetails;
    115
    116        this.bitsPerPixel = bitsPerPixel;
    117        this.comments = comments;
    118
    119        this.format = format;
    120        this.formatName = formatName;
    121        this.height = height;
    122        this.mimeType = mimeType;
    123
    124        this.numberOfImages = numberOfImages;
    125        this.physicalHeightDpi = physicalHeightDpi;
    126        this.physicalHeightInch = physicalHeightInch;
    127        this.physicalWidthDpi = physicalWidthDpi;
    128        this.physicalWidthInch = physicalWidthInch;
    129        this.width = width;
    130        this.progressive = progressive;
    131
    132        this.transparent = transparent;
    133        this.usesPalette = usesPalette;
    134
    135        this.colorType = colorType;
    136        this.compressionAlgorithm = compressionAlgorithm;
    137    }
    138
    139    /**
    140     * Returns the bits per pixel of the image data.
    141     *
    142     * @return bits per pixel of the image data.
    143     */
    144    public int getBitsPerPixel() {
    145        return bitsPerPixel;
    146    }
    147
    148    /**
    149     * Returns a list of comments from the image file.
    150     *
    151     * <p>This is mostly obsolete.</p>
    152     *
    153     * @return A list of comments.
    154     */
    155    public List<String> getComments() {
    156        return new ArrayList<>(comments);
    157    }
    158
    159    /**
    160     * Returns the image file format, ie. ImageFormat.IMAGE_FORMAT_PNG.
    161     *
    162     * <p>Returns ImageFormat.IMAGE_FORMAT_UNKNOWN if format is unknown.</p>
    163     *
    164     * @return a constant defined in ImageFormat.
    165     * @see ImageFormats
    166     */
    167    public ImageFormat getFormat() {
    168        return format;
    169    }
    170
    171    /**
    172     * Returns a string with the name of the image file format.
    173     *
    174     * @return the name of the image file format.
    175     * @see #getFormat()
    176     */
    177    public String getFormatName() {
    178        return formatName;
    179    }
    180
    181    /**
    182     * Returns the height of the image in pixels.
    183     *
    184     * @return image height in pixels.
    185     * @see #getWidth()
    186     */
    187    public int getHeight() {
    188        return height;
    189    }
    190
    191    /**
    192     * Returns the MIME type of the image.
    193     *
    194     * @return image MIME type.
    195     * @see #getFormat()
    196     */
    197    public String getMimeType() {
    198        return mimeType;
    199    }
    200
    201    /**
    202     * Returns the number of images in the file.
    203     *
    204     * <p>Applies mostly to GIF and TIFF; reading PSD/Photoshop layers is not
    205     * supported, and Jpeg/JFIF EXIF thumbnails are not included in this count.</p>
    206     *
    207     * @return number of images in the file.
    208     */
    209    public int getNumberOfImages() {
    210        return numberOfImages;
    211    }
    212
    213    /**
    214     * Returns horizontal dpi of the image, if available.
    215     *
    216     * <p>Applies to TIFF (optional), BMP (always), GIF (constant: 72), Jpeg
    217     * (optional), PNG (optional), PNM (constant: 72), PSD/Photoshop (constant:
    218     * 72).</p>
    219     *
    220     * @return returns -1 if not present.
    221     */
    222    public int getPhysicalHeightDpi() {
    223        return physicalHeightDpi;
    224    }
    225
    226    /**
    227     * Returns physical height of the image in inches, if available.
    228     *
    229     * <p>Applies to TIFF (optional), BMP (always), GIF (constant: 72), Jpeg
    230     * (optional), PNG (optional), PNM (constant: 72), PSD/Photoshop (constant:
    231     * 72).</p>
    232     *
    233     * @return returns -1 if not present.
    234     */
    235    public float getPhysicalHeightInch() {
    236        return physicalHeightInch;
    237    }
    238
    239    /**
    240     * Returns vertical dpi of the image, if available.
    241     *
    242     * <p>Applies to TIFF (optional), BMP (always), GIF (constant: 72), Jpeg
    243     * (optional), PNG (optional), PNM (constant: 72), PSD/Photoshop (constant:
    244     * 72).</p>
    245     *
    246     * @return returns -1 if not present.
    247     */
    248    public int getPhysicalWidthDpi() {
    249        return physicalWidthDpi;
    250    }
    251
    252    /**
    253     * Returns physical width of the image in inches, if available.
    254     *
    255     * <p>Applies to TIFF (optional), BMP (always), GIF (constant: 72), Jpeg
    256     * (optional), PNG (optional), PNM (constant: 72), PSD/Photoshop (constant:
    257     * 72).</p>
    258     *
    259     * @return returns -1 if not present.
    260     */
    261    public float getPhysicalWidthInch() {
    262        return physicalWidthInch;
    263    }
    264
    265    /**
    266     * Returns the width of the image in pixels.
    267     *
    268     * @return image width in pixels.
    269     * @see #getHeight()
    270     */
    271    public int getWidth() {
    272        return width;
    273    }
    274
    275    /**
    276     * Returns true if the image is progressive or interlaced.
    277     *
    278     * @return {@code true} if the image is progressive or interlaced, {@code false} otherwise.
    279     */
    280    public boolean isProgressive() {
    281        return progressive;
    282    }
    283
    284    /**
    285     * Returns the {@link org.apache.commons.imaging.ImageInfo.ColorType} of the image.
    286     *
    287     * @return image color type.
    288     */
    289    public ColorType getColorType() {
    290        return colorType;
    291    }
    292
    293    public void dump() {
    294        LOGGER.fine(toString());
    295    }
    296
    297    @Override
    298    public String toString() {
    299        try {
    300            final StringWriter sw = new StringWriter();
    301            final PrintWriter pw = new PrintWriter(sw);
    302
    303            toString(pw, "");
    304            pw.flush();
    305
    306            return sw.toString();
    307        } catch (final Exception e) {
    308            return "Image Data: Error";
    309        }
    310    }
    311
    312    public void toString(final PrintWriter pw, final String prefix) {
    313        pw.println("Format Details: " + formatDetails);
    314
    315        pw.println("Bits Per Pixel: " + bitsPerPixel);
    316        pw.println("Comments: " + comments.size());
    317        for (int i = 0; i < comments.size(); i++) {
    318            final String s = comments.get(i);
    319            pw.println("\t" + i + ": '" + s + "'");
    320
    321        }
    322        pw.println("Format: " + format.getName());
    323        pw.println("Format Name: " + formatName);
    324        pw.println("Compression Algorithm: " + compressionAlgorithm);
    325        pw.println("Height: " + height);
    326        pw.println("MimeType: " + mimeType);
    327        pw.println("Number Of Images: " + numberOfImages);
    328        pw.println("Physical Height Dpi: " + physicalHeightDpi);
    329        pw.println("Physical Height Inch: " + physicalHeightInch);
    330        pw.println("Physical Width Dpi: " + physicalWidthDpi);
    331        pw.println("Physical Width Inch: " + physicalWidthInch);
    332        pw.println("Width: " + width);
    333        pw.println("Is Progressive: " + progressive);
    334        pw.println("Is Transparent: " + transparent);
    335
    336        pw.println("Color Type: " + colorType.toString());
    337        pw.println("Uses Palette: " + usesPalette);
    338
    339        pw.flush();
    340
    341    }
    342
    343    /**
    344     * Returns a description of the file format, ie. format version.
    345     *
    346     * @return file format description.
    347     */
    348    public String getFormatDetails() {
    349        return formatDetails;
    350    }
    351
    352    /**
    353     * Returns true if the image has transparency.
    354     *
    355     * @return {@code true} if the image has transparency, {@code false} otherwise.
    356     */
    357    public boolean isTransparent() {
    358        return transparent;
    359    }
    360
    361    /**
    362     * Returns true if the image uses a palette.
    363     *
    364     * @return {@code true} if the image uses a palette, {@code false} otherwise.
    365     */
    366    public boolean usesPalette() {
    367        return usesPalette;
    368    }
    369
    370    /**
    371     * Returns a description of the compression algorithm, if any.
    372     *
    373     * @return compression algorithm description.
    374     */
    375    public CompressionAlgorithm getCompressionAlgorithm() {
    376        return compressionAlgorithm;
    377    }
    378
    379}