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