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    public int getBitsPerPixel() {
143        return bitsPerPixel;
144    }
145
146    /**
147     * Returns a list of comments from the image file.
148     * <p/>
149     * This is mostly obsolete.
150     */
151    public List<String> getComments() {
152        return new ArrayList<>(comments);
153    }
154
155    /**
156     * Returns the image file format, ie. ImageFormat.IMAGE_FORMAT_PNG.
157     * <p/>
158     * Returns ImageFormat.IMAGE_FORMAT_UNKNOWN if format is unknown.
159     *
160     * @return A constant defined in ImageFormat.
161     * @see ImageFormats
162     */
163    public ImageFormat getFormat() {
164        return format;
165    }
166
167    /**
168     * Returns a string with the name of the image file format.
169     *
170     * @see #getFormat()
171     */
172    public String getFormatName() {
173        return formatName;
174    }
175
176    /**
177     * Returns the height of the image in pixels.
178     *
179     * @see #getWidth()
180     */
181    public int getHeight() {
182        return height;
183    }
184
185    /**
186     * Returns the MIME type of the image.
187     *
188     * @see #getFormat()
189     */
190    public String getMimeType() {
191        return mimeType;
192    }
193
194    /**
195     * Returns the number of images in the file.
196     * <p>
197     * Applies mostly to GIF and TIFF; reading PSD/Photoshop layers is not
198     * supported, and Jpeg/JFIF EXIF thumbnails are not included in this count.
199     */
200    public int getNumberOfImages() {
201        return numberOfImages;
202    }
203
204    /**
205     * Returns horizontal dpi of the image, if available.
206     * <p>
207     * Applies to TIFF (optional), BMP (always), GIF (constant: 72), Jpeg
208     * (optional), PNG (optional), PNM (constant: 72), PSD/Photoshop (constant:
209     * 72).
210     *
211     * @return returns -1 if not present.
212     */
213    public int getPhysicalHeightDpi() {
214        return physicalHeightDpi;
215    }
216
217    /**
218     * Returns physical height of the image in inches, if available.
219     * <p>
220     * Applies to TIFF (optional), BMP (always), GIF (constant: 72), Jpeg
221     * (optional), PNG (optional), PNM (constant: 72), PSD/Photoshop (constant:
222     * 72).
223     *
224     * @return returns -1 if not present.
225     */
226    public float getPhysicalHeightInch() {
227        return physicalHeightInch;
228    }
229
230    /**
231     * Returns vertical dpi of the image, if available.
232     * <p>
233     * Applies to TIFF (optional), BMP (always), GIF (constant: 72), Jpeg
234     * (optional), PNG (optional), PNM (constant: 72), PSD/Photoshop (constant:
235     * 72).
236     *
237     * @return returns -1 if not present.
238     */
239    public int getPhysicalWidthDpi() {
240        return physicalWidthDpi;
241    }
242
243    /**
244     * Returns physical width of the image in inches, if available.
245     * <p>
246     * Applies to TIFF (optional), BMP (always), GIF (constant: 72), Jpeg
247     * (optional), PNG (optional), PNM (constant: 72), PSD/Photoshop (constant:
248     * 72).
249     *
250     * @return returns -1 if not present.
251     */
252    public float getPhysicalWidthInch() {
253        return physicalWidthInch;
254    }
255
256    /**
257     * Returns the width of the image in pixels.
258     *
259     * @see #getHeight()
260     */
261    public int getWidth() {
262        return width;
263    }
264
265    /**
266     * Returns true if the image is progressive or interlaced.
267     */
268    public boolean isProgressive() {
269        return progressive;
270    }
271
272    /**
273     * Returns the {@link org.apache.commons.imaging.ImageInfo.ColorType} of the image.
274     */
275    public ColorType getColorType() {
276        return colorType;
277    }
278
279    public void dump() {
280        LOGGER.fine(toString());
281    }
282
283    @Override
284    public String toString() {
285        try {
286            final StringWriter sw = new StringWriter();
287            final PrintWriter pw = new PrintWriter(sw);
288
289            toString(pw, "");
290            pw.flush();
291
292            return sw.toString();
293        } catch (final Exception e) {
294            return "Image Data: Error";
295        }
296    }
297
298    public void toString(final PrintWriter pw, final String prefix) {
299        pw.println("Format Details: " + formatDetails);
300
301        pw.println("Bits Per Pixel: " + bitsPerPixel);
302        pw.println("Comments: " + comments.size());
303        for (int i = 0; i < comments.size(); i++) {
304            final String s = comments.get(i);
305            pw.println("\t" + i + ": '" + s + "'");
306
307        }
308        pw.println("Format: " + format.getName());
309        pw.println("Format Name: " + formatName);
310        pw.println("Compression Algorithm: " + compressionAlgorithm);
311        pw.println("Height: " + height);
312        pw.println("MimeType: " + mimeType);
313        pw.println("Number Of Images: " + numberOfImages);
314        pw.println("Physical Height Dpi: " + physicalHeightDpi);
315        pw.println("Physical Height Inch: " + physicalHeightInch);
316        pw.println("Physical Width Dpi: " + physicalWidthDpi);
317        pw.println("Physical Width Inch: " + physicalWidthInch);
318        pw.println("Width: " + width);
319        pw.println("Is Progressive: " + progressive);
320        pw.println("Is Transparent: " + transparent);
321
322        pw.println("Color Type: " + colorType.toString());
323        pw.println("Uses Palette: " + usesPalette);
324
325        pw.flush();
326
327    }
328
329    /**
330     * Returns a description of the file format, ie. format version.
331     */
332    public String getFormatDetails() {
333        return formatDetails;
334    }
335
336    /**
337     * Returns true if the image has transparency.
338     */
339    public boolean isTransparent() {
340        return transparent;
341    }
342
343    /**
344     * Returns true if the image uses a palette.
345     */
346    public boolean usesPalette() {
347        return usesPalette;
348    }
349
350    /**
351     * Returns a description of the compression algorithm, if any.
352     */
353    public CompressionAlgorithm getCompressionAlgorithm() {
354        return compressionAlgorithm;
355    }
356
357}