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