/*
* ImageInfo.java
*
* Version 1.9
*
* A Java class to determine image width, height and color depth for
* a number of image file formats.
*
* Written by Marco Schmidt
*
* Contributed to the Public Domain.
*/
package com.jeecms.common.image;
import java.io.DataInput;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.IOException;
import java.net.URL;
import java.util.Vector;
/**
* Get file format, image resolution, number of bits per pixel and optionally
* number of images, comments and physical resolution from
* JPEG, GIF, BMP, PCX, PNG, IFF, RAS, PBM, PGM, PPM and PSD files
* (or input streams).
* <p>
* Use the class like this:
* <pre>
* ImageInfo ii = new ImageInfo();
* ii.setInput(in); // in can be InputStream or RandomAccessFile
* ii.setDetermineImageNumber(true); // default is false
* ii.setCollectComments(true); // default is false
* if (!ii.check()) {
* System.err.println("Not a supported image file format.");
* return;
* }
* System.out.println(ii.getFormatName() + ", " + ii.getMimeType() +
* ", " + ii.getWidth() + " x " + ii.getHeight() + " pixels, " +
* ii.getBitsPerPixel() + " bits per pixel, " + ii.getNumberOfImages() +
* " image(s), " + ii.getNumberOfComments() + " comment(s).");
* // there are other properties, check out the API documentation
* </pre>
* You can also use this class as a command line program.
* Call it with a number of image file names and URLs as parameters:
* <pre>
* java ImageInfo *.jpg *.png *.gif http://somesite.tld/image.jpg
* </pre>
* or call it without parameters and pipe data to it:
* <pre>
* java ImageInfo < image.jpg
* </pre>
* <p>
* Known limitations:
* <ul>
* <li>When the determination of the number of images is turned off, GIF bits
* per pixel are only read from the global header.
* For some GIFs, local palettes change this to a typically larger
* value. To be certain to get the correct color depth, call
* setDetermineImageNumber(true) before calling check().
* The complete scan over the GIF file will take additional time.</li>
* <li>Transparency information is not included in the bits per pixel count.
* Actually, it was my decision not to include those bits, so it's a feature! ;-)</li>
* </ul>
* <p>
* Requirements:
* <ul>
* <li>Java 1.1 or higher</li>
* </ul>
* <p>
* The latest version can be found at <a href="http://schmidt.devlib.org/image-info/">http://schmidt.devlib.org/image-info/</a>.
* <p>
* Written by Marco Schmidt.
* <p>
* This class is contributed to the Public Domain.
* Use it at your own risk.
* <p>
* <a name="history">History</a>:
* <ul>
* <li><strong>2001-08-24</strong> Initial version.</li>
* <li><strong>2001-10-13</strong> Added support for the file formats BMP and PCX.</li>
* <li><strong>2001-10-16</strong> Fixed bug in read(int[], int, int) that returned
* <li><strong>2002-01-22</strong> Added support for file formats Amiga IFF and Sun Raster (RAS).</li>
* <li><strong>2002-01-24</strong> Added support for file formats Portable Bitmap / Graymap / Pixmap (PBM, PGM, PPM) and Adobe Photoshop (PSD).
* Added new method getMimeType() to return the MIME type associated with a particular file format.</li>
* <li><strong>2002-03-15</strong> Added support to recognize number of images in file. Only works with GIF.
* Use {@link #setDetermineImageNumber} with <code>true</code> as argument to identify animated GIFs
* ({@link #getNumberOfImages()} will return a value larger than <code>1</code>).</li>
* <li><strong>2002-04-10</strong> Fixed a bug in the feature 'determine number of images in animated GIF' introduced with version 1.1.
* Thanks to Marcelo P. Lima for sending in the bug report.
* Released as 1.1.1.</li>
* <li><strong>2002-04-18</strong> Added {@link #setCollectComments(boolean)}.
* That new method lets the user specify whether textual comments are to be
* stored in an internal list when encountered in an input image file / stream.
* Added two methods to return the physical width and height of the image in dpi:
* {@link #getPhysicalWidthDpi()} and {@link #getPhysicalHeightDpi()}.
* If the physical resolution could not be retrieved, these methods return <code>-1</code>.
* </li>
* <li><strong>2002-04-23</strong> Added support for the new properties physical resolution and
* comments for some formats. Released as 1.2.</li>
* <li><strong>2002-06-17</strong> Added support for SWF, sent in by Michael Aird.
* Changed checkJpeg() so that other APP markers than APP0 will not lead to a failure anymore.
* Released as 1.3.</li>
* <li><strong>2003-07-28</strong> Bug fix - skip method now takes return values into consideration.
* Less bytes than necessary may have been skipped, leading to flaws in the retrieved information in some cases.
* Thanks to Bernard Bernstein for pointing that out.
* Released as 1.4.</li>
* <li><strong>2004-02-29</strong> Added support for recognizing progressive JPEG and
* interlaced PNG and GIF. A new method {@link #isProgressive()} returns whether ImageInfo
* has found that the storage type is progressive (or interlaced).
* Thanks to Joe Germuska for suggesting the feature.
* Bug fix: BMP physical resolution is now correctly determined.
* Released as 1.5.</li>
* <li><strong>2004-11-30</strong> Bug fix: recognizing progressive GIFs
* (interlaced in GIF terminology) did not work (thanks to Franz Jeitler for
* pointing this out). Now it should work, but only if the number of images is determined.
* This is because information on interlacing is stored in a local image header.
* In theory, different images could be stored interlaced and non-interlaced in one
* file. However, I think that's unlikely. Right now, the last image in the GIF file
* that is examined by ImageInfo is used for the "progressive" status.</li>
* <li><strong>2005-01-02</strong> Some code clean up (unused methods and variables
* commented out, missing javadoc comments, etc.). Thanks to George Sexton for a long list.
* Removed usage of Boolean.toString because
* it's a Java 1.4+ feature (thanks to Gregor Dupont).
* Changed delimiter character in compact output from semicolon to tabulator
* (for better integration with cut(1) and other Unix tools).
* Added some points to the <a href="http://schmidt.devlib.org/image-info/index.html#knownissues">'Known
* issues' section of the website</a>.
* Released as 1.6.</li>
* <li><strong>2005-07-26</strong> Removed code to identify Flash (SWF) files.
* Has repeatedly led to problems and support requests, and I don't know the
* format and don't have the time and interest to fix it myself.
* I repeatedly included fixes by others which didn't work for some people.
* I give up on SWF. Please do not contact me about it anymore.
* Set package of ImageInfo class to org.devlib.schmidt.imageinfo (a package
* was repeatedly requested by some users).
* Released as 1.7.</li>
* <li><strong>2006-02-23</strong> Removed Flash helper methods which weren't used elsewhere.
* Updated skip method which tries "read" whenever "skip(Bytes)" returns a result of 0.
* The old method didn't work with certain input stream types on truncated data streams.
* Thanks to Martin Leidig for reporting this and sending in code.
* Released as 1.8.</li>
* </li>
* <li><strong>2006-11-13</strong> Removed check that made ImageInfo report JPEG APPx
* markers smaller than 14 bytes as files in unknown format. Such JPEGs seem to be
* generated by Google's Picasa application. First reported with fix by
* Karl von Randow. Released as 1.9.</li>
* </ul>
* @author Marco Schmidt
*/
@SuppressWarnings("unchecked")
public class ImageInfo {
/**
* Return value of {@link #getFormat()} for JPEG streams.
* ImageInfo can extract physical resolution and comments
* from JPEGs (only from APP0 headers).
* Only one image can be stored in a file.
* It is determ