View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.imaging;
18  
19  import java.io.PrintWriter;
20  import java.io.StringWriter;
21  import java.util.ArrayList;
22  import java.util.Collections;
23  import java.util.List;
24  import java.util.logging.Logger;
25  
26  /**
27   * ImageInfo represents a collection of basic properties of an image, such as width, height, format, bit depth, etc.
28   */
29  public class ImageInfo {
30  
31      public enum ColorType {
32          BW("Black and White"), GRAYSCALE("Grayscale"), RGB("RGB"), CMYK("CMYK"), YCbCr("YCbCr"), YCCK("YCCK"), YCC("YCC"), OTHER("Other"), UNKNOWN("Unknown");
33  
34          private final String description;
35  
36          ColorType(final String description) {
37              this.description = description;
38          }
39  
40          @Override
41          public String toString() {
42              return description;
43          }
44      }
45  
46      public enum CompressionAlgorithm {
47          UNKNOWN("Unknown"), NONE("None"), LZW("LZW"), PACKBITS("PackBits"), JPEG_TIFF_OBSOLETE("JPEG Obsolete (TIFF only)"), JPEG("JPEG"),
48          RLE("RLE: Run-Length Encoding"), ADAPTIVE_RLE("Adaptive RLE"), PSD("Photoshop"), PNG_FILTER("PNG Filter"),
49          CCITT_GROUP_3("CCITT Group 3 1-Dimensional Modified Huffman run-length encoding."), CCITT_GROUP_4("CCITT Group 4"), CCITT_1D("CCITT 1D"),
50          DEFLATE("DEFLATE (ZIP)");
51  
52          private final String description;
53  
54          CompressionAlgorithm(final String description) {
55              this.description = description;
56          }
57  
58          @Override
59          public String toString() {
60              return description;
61          }
62      }
63  
64      private static final Logger LOGGER = Logger.getLogger(ImageInfo.class.getName());
65  
66      private final String formatDetails; // version
67  
68      private final int bitsPerPixel;
69      private final List<String> comments;
70  
71      private final ImageFormat format;
72      private final String formatName;
73      private final int height;
74      private final String mimeType;
75  
76      private final int numberOfImages;
77      private final int physicalHeightDpi;
78      private final float physicalHeightInch;
79      private final int physicalWidthDpi;
80      private final float physicalWidthInch;
81      private final int width;
82      private final boolean progressive;
83      private final boolean transparent;
84  
85      private final boolean usesPalette;
86  
87      private final ColorType colorType;
88  
89      private final CompressionAlgorithm compressionAlgorithm;
90  
91      public ImageInfo(final String formatDetails, final int bitsPerPixel, final List<String> comments, final ImageFormat format, final String formatName,
92              final int height, final String mimeType, final int numberOfImages, final int physicalHeightDpi, final float physicalHeightInch,
93              final int physicalWidthDpi, final float physicalWidthInch, final int width, final boolean progressive, final boolean transparent,
94              final boolean usesPalette, final ColorType colorType, final CompressionAlgorithm compressionAlgorithm) {
95          this.formatDetails = formatDetails;
96  
97          this.bitsPerPixel = bitsPerPixel;
98          this.comments = comments == null ? Collections.emptyList() : Collections.unmodifiableList(comments);
99  
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 returns -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 returns -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 returns -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 returns -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 }