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}