Java/2D Graphics GUI/ImageReader

Материал из Java эксперт
Перейти к: навигация, поиск

Add Image IO Read Progress Listener to ImageReader

<source lang="java"> import java.awt.image.BufferedImage; import java.io.File; import java.io.FileInputStream; import java.util.Iterator; import javax.imageio.ImageIO; import javax.imageio.ImageReader; import javax.imageio.ImageWriter; import javax.imageio.event.IIOReadProgressListener; import javax.imageio.stream.ImageInputStream; import javax.imageio.stream.ImageOutputStream; public class Main{

 static public void main(String args[]) throws Exception {
   FileInputStream fileInputStream = new FileInputStream("a.gif");
   Iterator readers = ImageIO.getImageReadersBySuffix("GIF");
   ImageReader imageReader = (ImageReader) readers.next();
   ImageInputStream imageInputStream = ImageIO.createImageInputStream(fileInputStream);
   imageReader.setInput(imageInputStream, false);
   imageReader.addIIOReadProgressListener(new MyIIOReadProgressListener());
   BufferedImage image = imageReader.read(0);
   Iterator imageWriters = ImageIO.getImageWritersBySuffix("JPG");
   ImageWriter imageWriter = (ImageWriter) imageWriters.next();
   File file = new File("b.JPG");
   ImageOutputStream ios = ImageIO.createImageOutputStream(file);
   imageWriter.setOutput(ios);
   imageWriter.write(image);
 }

} class MyIIOReadProgressListener implements IIOReadProgressListener{

 public void imageComplete(ImageReader source) {
   System.out.println("image complete " + source);
 }
 public void imageProgress(ImageReader source, float percentageDone) {
   System.out.println("image progress " + source + ": " + percentageDone + "%");
 }
 public void imageStarted(ImageReader source, int imageIndex) {
   System.out.println("image #" + imageIndex + " started " + source);
 }
 public void readAborted(ImageReader source) {
   System.out.println("read aborted " + source);
 }
 public void sequenceComplete(ImageReader source) {
   System.out.println("sequence complete " + source);
 }
 public void sequenceStarted(ImageReader source, int minIndex) {
   System.out.println("sequence started " + source + ": " + minIndex);
 }
 public void thumbnailComplete(ImageReader source) {
   System.out.println("thumbnail complete " + source);
 }
 public void thumbnailProgress(ImageReader source, float percentageDone) {
   System.out.println("thumbnail started " + source + ": " + percentageDone + "%");
 }
 public void thumbnailStarted(ImageReader source, int imageIndex, int thumbnailIndex) {
   System.out.println("thumbnail progress " + source + ", " + thumbnailIndex + " of "
       + imageIndex);
 }

}


 </source>   



Detect the file type of the input stream prior to reading the image

<source lang="java"> import java.awt.image.BufferedImage; import java.net.URL; import java.util.Iterator; import javax.imageio.ImageIO; import javax.imageio.ImageReader; import javax.imageio.stream.ImageInputStream; public class Main {

 public static void main(String[] argv) throws Exception {
   ImageInputStream imageStream = ImageIO.createImageInputStream(new URL("").openStream());
   Iterator<ImageReader> readers = ImageIO.getImageReaders(imageStream);
   ImageReader reader = null;
   if (!readers.hasNext()) {
     imageStream.close();
     return;
   } else {
     reader = readers.next();
   }
   String formatName = reader.getFormatName();
   if (!formatName.equalsIgnoreCase("jpeg") && !formatName.equalsIgnoreCase("png")
       && !formatName.equalsIgnoreCase("gif")) {
     imageStream.close();
     return;
   }
   reader.setInput(imageStream, true, true);
   BufferedImage theImage = reader.read(0);
   reader.dispose();
   imageStream.close();
 }

}


 </source>   



Determining the Format of an Image in a File

<source lang="java"> import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.util.Iterator; import javax.imageio.ImageIO; import javax.imageio.ImageReader; import javax.imageio.stream.ImageInputStream; public class Main {

 public static void main(String[] argv) throws Exception {
   File file = new File("image.gif");
   System.out.println(getFormatName(file));
   InputStream is = new FileInputStream(file);
   is.close();
   System.out.println(getFormatName(is));
 }
 private static String getFormatName(Object o) {
   try {
     ImageInputStream iis = ImageIO.createImageInputStream(o);
     Iterator iter = ImageIO.getImageReaders(iis);
     if (!iter.hasNext()) {
       return null;
     }
     ImageReader reader = (ImageReader) iter.next();
     iis.close();
     return reader.getFormatName();
   } catch (IOException e) {
   }
   return null;
 }

}


 </source>   



Get file format, image resolution, number of bits per pixel (JPEG, GIF, BMP, PCX, PNG, IFF, RAS, PBM, PGM, PPM, PSD and SWF files)

<source lang="java"> //optionally number of images, comments and physical resolution from //JPEG, GIF, BMP, PCX, PNG, IFF, RAS, PBM, PGM, PPM, PSD and SWF files //(or input streams) /*

* ImageInfo.java
*
* Version 1.5
*
* A Java class to determine image width, height and color depth for
* a number of image file formats.
*
* Written by Marco Schmidt 
* <http://www.geocities.ru/marcoschmidt.geo/contact.html>.
*
* Contributed to the Public Domain.
*
* Last modification 2004-02-29
*/

/*

* Copyright 2000,2005 wingS development team.
*
* This file is part of wingS (http://wingsframework.org).
*
* wingS is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1
* of the License, or (at your option) any later version.
*
* Please see COPYING for the complete licence.
*/

import java.io.DataInput; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.util.ArrayList; import java.util.List; /**

* 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, PSD and SWF files
* (or input streams).
* <p/>
* Use the class like this:
*
 * 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
 * 
* You can also use this class as a command line program.
* Call it with a number of image file names and URLs as parameters:
*
 *   java ImageInfo *.jpg *.png *.gif http://somesite.tld/image.jpg
 * 
* or call it without parameters and pipe data to it:
*
 *   java ImageInfo < image.jpg
 * 
* <p/>
* Known limitations:
*
    *
  • 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.
  • *
  • 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! ;-)
  • *
* <p/>
* Requirements:
*
    *
  • Java 1.1 or higher
  • *
* <p/>
* The latest version can be found at !
    * It is determined whether the GIF stream is interlaced (see {@link #isProgressive()}).
    */
   public static final int FORMAT_GIF = 1;
   /**
    * Return value of {@link #getFormat()} for PNG streams.
    * PNG only supports one image per file.
    * Both physical resolution and comments can be stored with PNG,
    * but ImageInfo is currently not able to extract those.
    * It is determined whether the PNG stream is interlaced (see {@link #isProgressive()}).
    */
   public static final int FORMAT_PNG = 2;
   /**
    * Return value of {@link #getFormat()} for BMP streams.
    * BMP only supports one image per file.
    * BMP does not allow for comments.
    * The physical resolution can be stored.
    */
   public static final int FORMAT_BMP = 3;
   /**
    * Return value of {@link #getFormat()} for PCX streams.
    * PCX does not allow for comments or more than one image per file.
    * However, the physical resolution can be stored.
    */
   public static final int FORMAT_PCX = 4;
   /**
    * Return value of {@link #getFormat()} for IFF streams.
    */
   public static final int FORMAT_IFF = 5;
   /**
    * Return value of {@link #getFormat()} for RAS streams.
    * Sun Raster allows for one image per file only and is not able to
    * store physical resolution or comments.
    */
   public static final int FORMAT_RAS = 6;
   /**
    * Return value of {@link #getFormat()} for PBM streams.
    */
   public static final int FORMAT_PBM = 7;
   /**
    * Return value of {@link #getFormat()} for PGM streams.
    */
   public static final int FORMAT_PGM = 8;
   /**
    * Return value of {@link #getFormat()} for PPM streams.
    */
   public static final int FORMAT_PPM = 9;
   /**
    * Return value of {@link #getFormat()} for PSD streams.
    */
   public static final int FORMAT_PSD = 10;
   /**
    * Return value of {@link #getFormat()} for SWF (Shockwave) streams.
    */
   public static final int FORMAT_SWF = 11;
   public static final int COLOR_TYPE_UNKNOWN = -1;
   public static final int COLOR_TYPE_TRUECOLOR_RGB = 0;
   public static final int COLOR_TYPE_PALETTED = 1;
   public static final int COLOR_TYPE_GRAYSCALE = 2;
   public static final int COLOR_TYPE_BLACK_AND_WHITE = 3;
   /**
    * The names of all supported file formats.
    * The FORMAT_xyz int constants can be used as index values for
    * this array.
    */
   public static final String[] FORMAT_NAMES =
           {"jpeg", "gif", "png", "bmp", "pcx",
            "iff", "ras", "pbm", "pgm", "ppm",
            "psd", "swf"};
   /**
    * The names of the MIME types for all supported file formats.
    * The FORMAT_xyz int constants can be used as index values for
    * this array.
    */
   public static final String[] MIME_TYPE_STRINGS =
           {"image/jpeg", "image/gif", "image/png", "image/bmp", "image/pcx",
            "image/iff", "image/ras", "image/x-portable-bitmap", "image/x-portable-graymap", "image/x-portable-pixmap",
            "image/psd", "application/x-shockwave-flash"};
   private int width;
   private int height;
   private int bitsPerPixel;
   private int colorType = COLOR_TYPE_UNKNOWN;
   private boolean progressive;
   private int format;
   private InputStream in;
   private DataInput din;
   private boolean collectComments = true;
   private List comments;
   private boolean determineNumberOfImages;
   private int numberOfImages;
   private int physicalHeightDpi;
   private int physicalWidthDpi;
   private int bitBuf;
   private int bitPos;
   private void addComment(String s) {
       if (comments == null) {
           comments = new ArrayList();
       }
       comments.add(s);
   }
   /**
    * Call this method after you have provided an input stream or file
    * using {@link #setInput(java.io.InputStream)} or {@link #setInput(java.io.DataInput)}.
    * If true is returned, the file format was known and information
    * on the file"s content can be retrieved using the various getXyz methods.
    *
    * @return if information could be retrieved from input
    */
   public boolean check() {
       format = -1;
       width = -1;
       height = -1;
       bitsPerPixel = -1;
       numberOfImages = 1;
       physicalHeightDpi = -1;
       physicalWidthDpi = -1;
       comments = null;
       try {
           int b1 = read() & 0xff;
           int b2 = read() & 0xff;
           if (b1 == 0x47 && b2 == 0x49) {
               return checkGif();
           } else if (b1 == 0x89 && b2 == 0x50) {
               return checkPng();
           } else if (b1 == 0xff && b2 == 0xd8) {
               return checkJpeg();
           } else if (b1 == 0x42 && b2 == 0x4d) {
               return checkBmp();
           } else if (b1 == 0x0a && b2 < 0x06) {
               return checkPcx();
           } else if (b1 == 0x46 && b2 == 0x4f) {
               return checkIff();
           } else if (b1 == 0x59 && b2 == 0xa6) {
               return checkRas();
           } else if (b1 == 0x50 && b2 >= 0x31 && b2 <= 0x36) {
               return checkPnm(b2 - "0");
           } else if (b1 == 0x38 && b2 == 0x42) {
               return checkPsd();
           } else if (b1 == 0x46 && b2 == 0x57) {
               return checkSwf();
           } else {
               return false;
           }
       } catch (IOException ioe) {
           return false;
       }
   }
   private boolean checkBmp() throws IOException {
       byte[] a = new byte[44];
       if (read(a) != a.length) {
           return false;
       }
       width = getIntLittleEndian(a, 16);
       height = getIntLittleEndian(a, 20);
       if (width < 1 || height < 1) {
           return false;
       }
       bitsPerPixel = getShortLittleEndian(a, 26);
       if (bitsPerPixel != 1 && bitsPerPixel != 4 &&
               bitsPerPixel != 8 && bitsPerPixel != 16 &&
               bitsPerPixel != 24 && bitsPerPixel != 32) {
           return false;
       }
       int x = (int) (getIntLittleEndian(a, 36) * 0.0254);
       if (x > 0) {
           setPhysicalWidthDpi(x);
       }
       int y = (int) (getIntLittleEndian(a, 40) * 0.0254);
       if (y > 0) {
           setPhysicalHeightDpi(y);
       }
       format = FORMAT_BMP;
       return true;
   }
   private boolean checkGif() throws IOException {
       final byte[] GIF_MAGIC_87A = {0x46, 0x38, 0x37, 0x61};
       final byte[] GIF_MAGIC_89A = {0x46, 0x38, 0x39, 0x61};
       byte[] a = new byte[11]; // 4 from the GIF signature + 7 from the global header
       if (read(a) != 11) {
           return false;
       }
       if ((!equals(a, 0, GIF_MAGIC_89A, 0, 4)) &&
               (!equals(a, 0, GIF_MAGIC_87A, 0, 4))) {
           return false;
       }
       format = FORMAT_GIF;
       width = getShortLittleEndian(a, 4);
       height = getShortLittleEndian(a, 6);
       int flags = a[8] & 0xff;
       bitsPerPixel = ((flags >> 4) & 0x07) + 1;
       progressive = (flags & 0x02) != 0;
       if (!determineNumberOfImages) {
           return true;
       }
       // skip global color palette
       if ((flags & 0x80) != 0) {
           int tableSize = (1 << ((flags & 7) + 1)) * 3;
           skip(tableSize);
       }
       numberOfImages = 0;
       int blockType;
       do {
           blockType = read();
           switch (blockType) {
               case (0x2c): // image separator
                   {
                       if (read(a, 0, 9) != 9) {
                           return false;
                       }
                       flags = a[8] & 0xff;
                       int localBitsPerPixel = (flags & 0x07) + 1;
                       if (localBitsPerPixel > bitsPerPixel) {
                           bitsPerPixel = localBitsPerPixel;
                       }
                       if ((flags & 0x80) != 0) {
                           skip((1 << localBitsPerPixel) * 3);
                       }
                       skip(1); // initial code length
                       int n;
                       do {
                           n = read();
                           if (n > 0) {
                               skip(n);
                           } else if (n == -1) {
                               return false;
                           }
                       } while (n > 0);
                       numberOfImages++;
                       break;
                   }
               case (0x21): // extension
                   {
                       int extensionType = read();
                       if (collectComments && extensionType == 0xfe) {
                           StringBuilder sb = new StringBuilder();
                           int n;
                           do {
                               n = read();
                               if (n == -1) {
                                   return false;
                               }
                               if (n > 0) {
                                   for (int i = 0; i < n; i++) {
                                       int ch = read();
                                       if (ch == -1) {
                                           return false;
                                       }
                                       sb.append((char) ch);
                                   }
                               }
                           } while (n > 0);
                       } else {
                           int n;
                           do {
                               n = read();
                               if (n > 0) {
                                   skip(n);
                               } else if (n == -1) {
                                   return false;
                               }
                           } while (n > 0);
                       }
                       break;
                   }
               case (0x3b): // end of file
                   {
                       break;
                   }
               default:
                   {
                       return false;
                   }
           }
       } while (blockType != 0x3b);
       return true;
   }
   private boolean checkIff() throws IOException {
       byte[] a = new byte[10];
       // read remaining 2 bytes of file id, 4 bytes file size 
       // and 4 bytes IFF subformat
       if (read(a, 0, 10) != 10) {
           return false;
       }
       final byte[] IFF_RM = {0x52, 0x4d};
       if (!equals(a, 0, IFF_RM, 0, 2)) {
           return false;
       }
       int type = getIntBigEndian(a, 6);
       if (type != 0x494c424d && // type must be ILBM...
               type != 0x50424d20) { // ...or PBM
           return false;
       }
       // loop chunks to find BMHD chunk
       do {
           if (read(a, 0, 8) != 8) {
               return false;
           }
           int chunkId = getIntBigEndian(a, 0);
           int size = getIntBigEndian(a, 4);
           if ((size & 1) == 1) {
               size++;
           }
           if (chunkId == 0x424d4844) { // BMHD chunk
               if (read(a, 0, 9) != 9) {
                   return false;
               }
               format = FORMAT_IFF;
               width = getShortBigEndian(a, 0);
               height = getShortBigEndian(a, 2);
               bitsPerPixel = a[8] & 0xff;
               return (width > 0 && height > 0 && bitsPerPixel > 0 && bitsPerPixel < 33);
           } else {
               skip(size);
           }
       } while (true);
   }
   private boolean checkJpeg() throws IOException {
       byte[] data = new byte[12];
       while (true) {
           if (read(data, 0, 4) != 4) {
               return false;
           }
           int marker = getShortBigEndian(data, 0);
           int size = getShortBigEndian(data, 2);
           if ((marker & 0xff00) != 0xff00) {
               return false; // not a valid marker
           }
           if (marker == 0xffe0) { // APPx 
               if (size < 14) {
                   return false; // APPx header must be >= 14 bytes
               }
               if (read(data, 0, 12) != 12) {
                   return false;
               }
               final byte[] APP0_ID = {0x4a, 0x46, 0x49, 0x46, 0x00};
               if (equals(APP0_ID, 0, data, 0, 5)) {
                   //System.out.println("data 7=" + data[7]);
                   if (data[7] == 1) {
                       setPhysicalWidthDpi(getShortBigEndian(data, 8));
                       setPhysicalHeightDpi(getShortBigEndian(data, 10));
                   } else if (data[7] == 2) {
                       int x = getShortBigEndian(data, 8);
                       int y = getShortBigEndian(data, 10);
                       setPhysicalWidthDpi((int) (x * 2.54f));
                       setPhysicalHeightDpi((int) (y * 2.54f));
                   }
               }
               skip(size - 14);
           } else if (collectComments && size > 2 && marker == 0xfffe) { // comment
               size -= 2;
               byte[] chars = new byte[size];
               if (read(chars, 0, size) != size) {
                   return false;
               }
               String comment = new String(chars, "iso-8859-1");
               comment = comment.trim();
               addComment(comment);
           } else if (marker >= 0xffc0 && marker <= 0xffcf && marker != 0xffc4 && marker != 0xffc8) {
               if (read(data, 0, 6) != 6) {
                   return false;
               }
               format = FORMAT_JPEG;
               bitsPerPixel = (data[0] & 0xff) * (data[5] & 0xff);
               progressive = marker == 0xffc2 || marker == 0xffc6 ||
                       marker == 0xffca || marker == 0xffce;
               width = getShortBigEndian(data, 3);
               height = getShortBigEndian(data, 1);
               return true;
           } else {
               skip(size - 2);
           }
       }
   }
   private boolean checkPcx() throws IOException {
       byte[] a = new byte[64];
       if (read(a) != a.length) {
           return false;
       }
       if (a[0] != 1) { // encoding, 1=RLE is only valid value
           return false;
       }
       // width / height
       int x1 = getShortLittleEndian(a, 2);
       int y1 = getShortLittleEndian(a, 4);
       int x2 = getShortLittleEndian(a, 6);
       int y2 = getShortLittleEndian(a, 8);
       if (x1 < 0 || x2 < x1 || y1 < 0 || y2 < y1) {
           return false;
       }
       width = x2 - x1 + 1;
       height = y2 - y1 + 1;
       // color depth
       int bits = a[1];
       int planes = a[63];
       if (planes == 1 &&
               (bits == 1 || bits == 2 || bits == 4 || bits == 8)) {
           // paletted
           bitsPerPixel = bits;
       } else if (planes == 3 && bits == 8) {
           // RGB truecolor
           bitsPerPixel = 24;
       } else {
           return false;
       }
       setPhysicalWidthDpi(getShortLittleEndian(a, 10));
       setPhysicalHeightDpi(getShortLittleEndian(a, 10));
       format = FORMAT_PCX;
       return true;
   }
   private boolean checkPng() throws IOException {
       final byte[] PNG_MAGIC = {0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a};
       byte[] a = new byte[27];
       if (read(a) != 27) {
           return false;
       }
       if (!equals(a, 0, PNG_MAGIC, 0, 6)) {
           return false;
       }
       format = FORMAT_PNG;
       width = getIntBigEndian(a, 14);
       height = getIntBigEndian(a, 18);
       bitsPerPixel = a[22] & 0xff;
       colorType = a[23] & 0xff;
       if (colorType == 2 || colorType == 6) {
           bitsPerPixel *= 3;
       }
       progressive = (a[26] & 0xff) != 0;
       return true;
   }
   private boolean checkPnm(int id) throws IOException {
       if (id < 1 || id > 6) {
           return false;
       }
       final int[] PNM_FORMATS = {FORMAT_PBM, FORMAT_PGM, FORMAT_PPM};
       format = PNM_FORMATS[(id - 1) % 3];
       boolean hasPixelResolution = false;
       String s;
       while (true) {
           s = readLine();
           if (s != null) {
               s = s.trim();
           }
           if (s == null || s.length() < 1) {
               continue;
           }
           if (s.charAt(0) == "#") { // comment
               if (collectComments && s.length() > 1) {
                   addComment(s.substring(1));
               }
               continue;
           }
           if (!hasPixelResolution) { // split "343 966" into width=343, height=966
               int spaceIndex = s.indexOf(" ");
               if (spaceIndex == -1) {
                   return false;
               }
               String widthString = s.substring(0, spaceIndex);
               spaceIndex = s.lastIndexOf(" ");
               if (spaceIndex == -1) {
                   return false;
               }
               String heightString = s.substring(spaceIndex + 1);
               try {
                   width = Integer.parseInt(widthString);
                   height = Integer.parseInt(heightString);
               } catch (NumberFormatException nfe) {
                   return false;
               }
               if (width < 1 || height < 1) {
                   return false;
               }
               if (format == FORMAT_PBM) {
                   bitsPerPixel = 1;
                   return true;
               }
               hasPixelResolution = true;
           } else {
               int maxSample;
               try {
                   maxSample = Integer.parseInt(s);
               } catch (NumberFormatException nfe) {
                   return false;
               }
               if (maxSample < 0) {
                   return false;
               }
               for (int i = 0; i < 25; i++) {
                   if (maxSample < (1 << (i + 1))) {
                       bitsPerPixel = i + 1;
                       if (format == FORMAT_PPM) {
                           bitsPerPixel *= 3;
                       }
                       return true;
                   }
               }
               return false;
           }
       }
   }
   private boolean checkPsd() throws IOException {
       byte[] a = new byte[24];
       if (read(a) != a.length) {
           return false;
       }
       final byte[] PSD_MAGIC = {0x50, 0x53};
       if (!equals(a, 0, PSD_MAGIC, 0, 2)) {
           return false;
       }
       format = FORMAT_PSD;
       width = getIntBigEndian(a, 16);
       height = getIntBigEndian(a, 12);
       int channels = getShortBigEndian(a, 10);
       int depth = getShortBigEndian(a, 20);
       bitsPerPixel = channels * depth;
       return (width > 0 && height > 0 && bitsPerPixel > 0 && bitsPerPixel <= 64);
   }
   private boolean checkRas() throws IOException {
       byte[] a = new byte[14];
       if (read(a) != a.length) {
           return false;
       }
       final byte[] RAS_MAGIC = {0x6a, (byte) 0x95};
       if (!equals(a, 0, RAS_MAGIC, 0, 2)) {
           return false;
       }
       format = FORMAT_RAS;
       width = getIntBigEndian(a, 2);
       height = getIntBigEndian(a, 6);
       bitsPerPixel = getIntBigEndian(a, 10);
       return (width > 0 && height > 0 && bitsPerPixel > 0 && bitsPerPixel <= 24);
   }
   // Written by Michael Aird.
   private boolean checkSwf() throws IOException {
       //get rid of the last byte of the signature, the byte of the version and 4 bytes of the size
       byte[] a = new byte[6];
       if (read(a) != a.length) {
           return false;
       }
       format = FORMAT_SWF;
       int bitSize = (int) readUBits(5);
       int minX = readSBits(bitSize);
       int maxX = readSBits(bitSize);
       int minY = readSBits(bitSize);
       int maxY = readSBits(bitSize);
       width = maxX / 20; //cause we"re in twips
       height = maxY / 20;  //cause we"re in twips
       setPhysicalWidthDpi(72);
       setPhysicalHeightDpi(72);
       return (width > 0 && height > 0);
   }
   /**
    * Run over String list, return false iff at least one of the arguments
    * equals -c.
    */
   private static boolean determineVerbosity(String[] args) {
       if (args != null && args.length > 0) {
           for (int i = 0; i < args.length; i++) {
               if ("-c".equals(args[i])) {
                   return false;
               }
           }
       }
       return true;
   }
   private boolean equals(byte[] a1, int offs1, byte[] a2, int offs2, int num) {
       while (num-- > 0) {
           if (a1[offs1++] != a2[offs2++]) {
               return false;
           }
       }
       return true;
   }
   /**
    * If {@link #check()} was successful, returns the image"s number of bits per pixel.
    * Does not include transparency information like the alpha channel.
    *
    * @return number of bits per image pixel
    */
   public int getBitsPerPixel() {
       return bitsPerPixel;
   }
   /**
    * Returns the index"th comment retrieved from the image.
    *
    * @throws java.lang.IllegalArgumentException
    *          if index is smaller than 0 or larger than or equal
    *          to the number of comments retrieved
    * @see #getNumberOfComments
    */
   public String getComment(int index) {
       if (comments == null || index < 0 || index >= comments.size()) {
           throw new IllegalArgumentException("Not a valid comment index: " + index);
       }
       return (String) comments.get(index);
   }
   /**
    * If {@link #check()} was successful, returns the image format as one
    * of the FORMAT_xyz constants from this class.
    * Use {@link #getFormatName()} to get a textual description of the file format.
    *
    * @return file format as a FORMAT_xyz constant
    */
   public int getFormat() {
       return format;
   }
   /**
    * If {@link #check()} was successful, returns the image format"s name.
    * Use {@link #getFormat()} to get a unique number.
    *
    * @return file format name
    */
   public String getFormatName() {
       if (format >= 0 && format < FORMAT_NAMES.length) {
           return FORMAT_NAMES[format];
       } else {
           return "?";
       }
   }
   /**
    * If {@link #check()} was successful, returns one the image"s vertical
    * resolution in pixels.
    *
    * @return image height in pixels
    */
   public int getHeight() {
       return height;
   }
   private int getIntBigEndian(byte[] a, int offs) {
       return
               (a[offs] & 0xff) << 24 |
               (a[offs + 1] & 0xff) << 16 |
               (a[offs + 2] & 0xff) << 8 |
               a[offs + 3] & 0xff;
   }
   private int getIntLittleEndian(byte[] a, int offs) {
       return
               (a[offs + 3] & 0xff) << 24 |
               (a[offs + 2] & 0xff) << 16 |
               (a[offs + 1] & 0xff) << 8 |
               a[offs] & 0xff;
   }
   /**
    * If {@link #check()} was successful, returns a String with the
    * MIME type of the format.
    *
    * @return MIME type, e.g. image/jpeg
    */
   public String getMimeType() {
       if (format >= 0 && format < MIME_TYPE_STRINGS.length) {
           if (format == FORMAT_JPEG && progressive) {
               return "image/pjpeg";
           }
           return MIME_TYPE_STRINGS[format];
       } else {
           return null;
       }
   }
   /**
    * If {@link #check()} was successful and {@link #setCollectComments(boolean)} was called with
    * true as argument, returns the number of comments retrieved
    * from the input image stream / file.
    * Any number >= 0 and smaller than this number of comments is then a
    * valid argument for the {@link #getComment(int)} method.
    *
    * @return number of comments retrieved from input image
    */
   public int getNumberOfComments() {
       if (comments == null) {
           return 0;
       } else {
           return comments.size();
       }
   }
   /**
    * Returns the number of images in the examined file.
    * Assumes that setDetermineImageNumber(true); was called before
    * a successful call to {@link #check()}.
    * This value can currently be only different from 1 for GIF images.
    *
    * @return number of images in file
    */
   public int getNumberOfImages() {
       return numberOfImages;
   }
   /**
    * Returns the physical height of this image in dots per inch (dpi).
    * Assumes that {@link #check()} was successful.
    * Returns -1 on failure.
    *
    * @return physical height (in dpi)
    * @see #getPhysicalWidthDpi()
    * @see #getPhysicalHeightInch()
    */
   public int getPhysicalHeightDpi() {
       return physicalHeightDpi;
   }
   /**
    * If {@link #check()} was successful, returns the physical width of this image in dpi (dots per inch)
    * or -1 if no value could be found.
    *
    * @return physical height (in dpi)
    * @see #getPhysicalHeightDpi()
    * @see #getPhysicalWidthDpi()
    * @see #getPhysicalWidthInch()
    */
   public float getPhysicalHeightInch() {
       int h = getHeight();
       int ph = getPhysicalHeightDpi();
       if (h > 0 && ph > 0) {
           return ((float) h) / ((float) ph);
       } else {
           return -1.0f;
       }
   }
   /**
    * If {@link #check()} was successful, returns the physical width of this image in dpi (dots per inch)
    * or -1 if no value could be found.
    *
    * @return physical width (in dpi)
    * @see #getPhysicalHeightDpi()
    * @see #getPhysicalWidthInch()
    * @see #getPhysicalHeightInch()
    */
   public int getPhysicalWidthDpi() {
       return physicalWidthDpi;
   }
   /**
    * Returns the physical width of an image in inches, or
    * -1.0f if width information is not available.
    * Assumes that {@link #check} has been called successfully.
    *
    * @return physical width in inches or -1.0f on failure
    * @see #getPhysicalWidthDpi
    * @see #getPhysicalHeightInch
    */
   public float getPhysicalWidthInch() {
       int w = getWidth();
       int pw = getPhysicalWidthDpi();
       if (w > 0 && pw > 0) {
           return ((float) w) / ((float) pw);
       } else {
           return -1.0f;
       }
   }
   private int getShortBigEndian(byte[] a, int offs) {
       return
               (a[offs] & 0xff) << 8 |
               (a[offs + 1] & 0xff);
   }
   private int getShortLittleEndian(byte[] a, int offs) {
       return (a[offs] & 0xff) | (a[offs + 1] & 0xff) << 8;
   }
   /**
    * If {@link #check()} was successful, returns one the image"s horizontal
    * resolution in pixels.
    *
    * @return image width in pixels
    */
   public int getWidth() {
       return width;
   }
   /**
    * Returns whether the image is stored in a progressive (also called: interlaced) way.
    *
    * @return true for progressive/interlaced, false otherwise
    */
   public boolean isProgressive() {
       return progressive;
   }
   /**
    * To use this class as a command line application, give it either
    * some file names as parameters (information on them will be
    * printed to standard output, one line per file) or call
    * it with no parameters. It will then check data given to it
    * via standard input.
    *
    * @param args the program arguments which must be file names
    */
   public static void main(String[] args) {
       ImageInfo imageInfo = new ImageInfo();
       imageInfo.setDetermineImageNumber(true);
       boolean verbose = determineVerbosity(args);
       if (args.length == 0) {
           run(null, System.in, imageInfo, verbose);
       } else {
           int index = 0;
           while (index < args.length) {
               InputStream in = null;
               try {
                   String name = args[index++];
                   System.out.print(name + ";");
                   if (name.startsWith("http://")) {
                       in = new URL(name).openConnection().getInputStream();
                   } else {
                       in = new FileInputStream(name);
                   }
                   run(name, in, imageInfo, verbose);
                   in.close();
               } catch (Exception e) {
                   System.out.println(e);
                   try {
                       in.close();
                   } catch (Exception ee) {
                   }
               }
           }
       }
   }
   private static void print(String sourceName, ImageInfo ii, boolean verbose) {
       if (verbose) {
           printVerbose(sourceName, ii);
       } else {
           printCompact(sourceName, ii);
       }
   }
   private static void printCompact(String sourceName, ImageInfo imageInfo) {
       System.out.println(imageInfo.getFormatName() + ";" +
               imageInfo.getMimeType() + ";" +
               imageInfo.getWidth() + ";" +
               imageInfo.getHeight() + ";" +
               imageInfo.getBitsPerPixel() + ";" +
               imageInfo.getNumberOfImages() + ";" +
               imageInfo.getPhysicalWidthDpi() + ";" +
               imageInfo.getPhysicalHeightDpi() + ";" +
               imageInfo.getPhysicalWidthInch() + ";" +
               imageInfo.getPhysicalHeightInch() + ";" +
               imageInfo.isProgressive());
   }
   private static void printLine(int indentLevels, String text, float value, float minValidValue) {
       if (value < minValidValue) {
           return;
       }
       printLine(indentLevels, text, Float.toString(value));
   }
   private static void printLine(int indentLevels, String text, int value, int minValidValue) {
       if (value >= minValidValue) {
           printLine(indentLevels, text, Integer.toString(value));
       }
   }
   private static void printLine(int indentLevels, String text, String value) {
       if (value == null || value.length() == 0) {
           return;
       }
       while (indentLevels-- > 0) {
           System.out.print("\t");
       }
       if (text != null && text.length() > 0) {
           System.out.print(text);
           System.out.print(" ");
       }
       System.out.println(value);
   }
   private static void printVerbose(String sourceName, ImageInfo ii) {
       printLine(0, null, sourceName);
       printLine(1, "File format: ", ii.getFormatName());
       printLine(1, "MIME type: ", ii.getMimeType());
       printLine(1, "Width (pixels): ", ii.getWidth(), 1);
       printLine(1, "Height (pixels): ", ii.getHeight(), 1);
       printLine(1, "Bits per pixel: ", ii.getBitsPerPixel(), 1);
       printLine(1, "Progressive: ", Boolean.toString(ii.isProgressive()));
       printLine(1, "Number of images: ", ii.getNumberOfImages(), 1);
       printLine(1, "Physical width (dpi): ", ii.getPhysicalWidthDpi(), 1);
       printLine(1, "Physical height (dpi): ", ii.getPhysicalHeightDpi(), 1);
       printLine(1, "Physical width (inches): ", ii.getPhysicalWidthInch(), 1.0f);
       printLine(1, "Physical height (inches): ", ii.getPhysicalHeightInch(), 1.0f);
       int numComments = ii.getNumberOfComments();
       printLine(1, "Number of textual comments: ", numComments, 1);
       if (numComments > 0) {
           for (int i = 0; i < numComments; i++) {
               printLine(2, null, ii.getComment(i));
           }
       }
   }
   private int read() throws IOException {
       if (in != null) {
           return in.read();
       } else {
           return din.readByte();
       }
   }
   private int read(byte[] a) throws IOException {
       if (in != null) {
           return in.read(a);
       } else {
           din.readFully(a);
           return a.length;
       }
   }
   private int read(byte[] a, int offset, int num) throws IOException {
       if (in != null) {
           return in.read(a, offset, num);
       } else {
           din.readFully(a, offset, num);
           return num;
       }
   }
   private String readLine() throws IOException {
       return readLine(new StringBuilder());
   }
   private String readLine(StringBuilder sb) throws IOException {
       boolean finished;
       do {
           int value = read();
           finished = (value == -1 || value == 10);
           if (!finished) {
               sb.append((char) value);
           }
       } while (!finished);
       return sb.toString();
   }
   private long readUBits(int numBits) throws IOException {
       if (numBits == 0) {
           return 0;
       }
       int bitsLeft = numBits;
       long result = 0;
       if (bitPos == 0) { //no value in the buffer - read a byte
           if (in != null) {
               bitBuf = in.read();
           } else {
               bitBuf = din.readByte();
           }
           bitPos = 8;
       }
       while (true) {
           int shift = bitsLeft - bitPos;
           if (shift > 0) {
               // Consume the entire buffer
               result |= bitBuf << shift;
               bitsLeft -= bitPos;
               // Get the next byte from the input stream
               if (in != null) {
                   bitBuf = in.read();
               } else {
                   bitBuf = din.readByte();
               }
               bitPos = 8;
           } else {
               // Consume a portion of the buffer
               result |= bitBuf >> -shift;
               bitPos -= bitsLeft;
               bitBuf &= 0xff >> (8 - bitPos); // mask off the consumed bits
               return result;
           }
       }
   }
   /**
    * Read a signed value from the given number of bits
    */
   private int readSBits(int numBits) throws IOException {
       // Get the number as an unsigned value.
       long uBits = readUBits(numBits);
       // Is the number negative?
       if ((uBits & (1L << (numBits - 1))) != 0) {
           // Yes. Extend the sign.
           uBits |= -1L << numBits;
       }
       return (int) uBits;
   }
   private void synchBits() {
       bitBuf = 0;
       bitPos = 0;
   }
   private String readLine(int firstChar) throws IOException {
       StringBuilder result = new StringBuilder();
       result.append((char) firstChar);
       return readLine(result);
   }
   private static void run(String sourceName, InputStream in, ImageInfo imageInfo, boolean verbose) {
       imageInfo.setInput(in);
       imageInfo.setDetermineImageNumber(false);
       imageInfo.setCollectComments(verbose);
       if (imageInfo.check()) {
           print(sourceName, imageInfo, verbose);
       }
   }
   /**
    * Specify whether textual comments are supposed to be extracted from input.
    * Default is false.
    * If enabled, comments will be added to an internal list.
    *
    * @param newValue if true, this class will read comments
    * @see #getNumberOfComments
    * @see #getComment
    */
   public void setCollectComments(boolean newValue) {
       collectComments = newValue;
   }
   /**
    * Specify whether the number of images in a file is to be
    * determined - default is false.
    * This is a special option because some file formats require running over
    * the entire file to find out the number of images, a rather time-consuming
    * task.
    * Not all file formats support more than one image.
    * If this method is called with true as argument,
    * the actual number of images can be queried via
    * {@link #getNumberOfImages()} after a successful call to
    * {@link #check()}.
    *
    * @param newValue will the number of images be determined?
    * @see #getNumberOfImages
    */
   public void setDetermineImageNumber(boolean newValue) {
       determineNumberOfImages = newValue;
   }
   /**
    * Set the input stream to the argument stream (or file).
    * Note that {@link java.io.RandomAccessFile} implements
    * {@link java.io.DataInput}.
    *
    * @param dataInput the input stream to read from
    */
   public void setInput(DataInput dataInput) {
       din = dataInput;
       in = null;
   }
   /**
    * Set the input stream to the argument stream (or file).
    *
    * @param inputStream the input stream to read from
    */
   public void setInput(InputStream inputStream) {
       in = inputStream;
       din = null;
   }
   private void setPhysicalHeightDpi(int newValue) {
       physicalWidthDpi = newValue;
   }
   private void setPhysicalWidthDpi(int newValue) {
       physicalHeightDpi = newValue;
   }
   private void skip(int num) throws IOException {
       while (num > 0) {
           long result;
           if (in != null) {
               result = in.skip(num);
           } else {
               result = din.skipBytes(num);
           }
           if (result > 0) {
               num -= result;
           }
       }
   }

}


 </source>   



Image format info

<source lang="java"> /*

  1. IFNDEF ALT_LICENSE
                          ThinWire(R) RIA Ajax Framework
                Copyright (C) 2003-2007 Custom Credit Systems
 This library is free software; you can redistribute it and/or modify it under
 the terms of the GNU Lesser General Public License as published by the Free
 Software Foundation; either version 2.1 of the License, or (at your option) any
 later version.
 This library is distributed in the hope that it will be useful, but WITHOUT ANY
 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
 PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
 You should have received a copy of the GNU Lesser General Public License along
 with this library; if not, write to the Free Software Foundation, Inc., 59
 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 Users who would rather have a commercial license, warranty or support should
 contact the following company who invented, built and supports the technology:
 
               Custom Credit Systems, Richardson, TX 75081, USA.
               email: info@thinwire.ru    ph: +1 (888) 644-6405
                         http://www.thinwire.ru
  1. ENDIF
[ v1.2_RC2 ] 
  • /

import java.io.DataInput; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.List;

/**

* @author Joshua J. Gertzen
*/

public class ImageInfo {

   public enum Format {GIF,JPEG,PNG}
   
   private String stringValue;
   private String name;
   private Format format;
   private int width;
   private int height;
   public ImageInfo(String name) {
       setName(name);
   }
   
   public int getWidth() {
       return width;
   }
   
   public int getHeight() {
       return height;
   }
   
   public Format getFormat() {
       return format;
   }
   
   public String getName() {
       return name;
   }
   
   private void setName(String name) {        
       try {                       
           InputStream is = new FileInputStream(name);
               
           if (is != null) {
               this.name = name;
               ImageParser ii = new ImageParser();                        
               ii.setInput(is);
               
               if (!ii.check())
                   throw new UnsupportedOperationException("Unknown image file format for file.");
               
               switch (ii.getFormat()) {
                   case ImageParser.FORMAT_GIF:
                       this.format = Format.GIF;                        
                       break;
                       
                   case ImageParser.FORMAT_JPEG:
                       this.format = Format.JPEG;
                       break;
                       
                   case ImageParser.FORMAT_PNG:
                       this.format = Format.PNG; 
                       break;
                   
                   default:
                       throw new UnsupportedOperationException("Unsupported image file format "" + ii.getFormatName() + "".");
               }
               this.width = ii.getWidth();
               this.height = ii.getHeight();
           } else {
               this.width = -1;
               this.height = -1;
               this.format = null;
               this.name = "";
           }
       } catch (Exception e) {
           if (!(e instanceof RuntimeException)) e = new RuntimeException(e);
           throw (RuntimeException)e;
       }
   }   
   
   public boolean equals(Object o) {
       return o instanceof ImageInfo && toString().equals(o.toString());
   }
   
   public int hashCode() {
       return toString().hashCode();
   }
   
   public String toString() {
       if (stringValue == null) stringValue = "ImageInfo{name:" + name + ",format:" + format + ",width:" + width + ",height:" + height + "}"; 
       return stringValue;
   }

} /* XXX Note: This class is a public domain class that is used by

* ImageInfo (above) to determine the width and height of an image.
* It is made package-private because it is not intended to be used
* directly.
*/

/*

* ImageInfo.java
*
* Version 1.5
*
* A Java class to determine image width, height and color depth for
* a number of image file formats.
*
* Written by Marco Schmidt 
* <http://www.geocities.ru/marcoschmidt.geo/contact.html>.
*
* Contributed to the Public Domain.
*
* Last modification 2004-02-29
*/

/**

* 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, PSD and SWF files 
* (or input streams).
*

* Use the class like this: *

 * 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
 * 
* You can also use this class as a command line program.
* Call it with a number of image file names and URLs as parameters:
*
 *   java ImageInfo *.jpg *.png *.gif http://somesite.tld/image.jpg
 * 
* or call it without parameters and pipe data to it:
*
 *   java ImageInfo < image.jpg  
 * 
* <p>
* Known limitations:
*
    *
  • 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.
  • *
  • 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! ;-)
  • *
* <p>
* Requirements:
*
    *
  • Java 1.1 or higher
  • *
* <p>
* The latest version can be found at !
    * It is determined whether the GIF stream is interlaced (see {@link #isProgressive()}).
    */
   public static final int FORMAT_GIF = 1;
   /**
    * Return value of {@link #getFormat()} for PNG streams.
    * PNG only supports one image per file.
    * Both physical resolution and comments can be stored with PNG,
    * but ImageInfo is currently not able to extract those.
    * It is determined whether the PNG stream is interlaced (see {@link #isProgressive()}).
    */
   public static final int FORMAT_PNG = 2;
   /**
    * Return value of {@link #getFormat()} for BMP streams.
    * BMP only supports one image per file.
    * BMP does not allow for comments.
    * The physical resolution can be stored.
    */
   public static final int FORMAT_BMP = 3;
   /**
    * Return value of {@link #getFormat()} for PCX streams.
    * PCX does not allow for comments or more than one image per file.
    * However, the physical resolution can be stored.
    */
   public static final int FORMAT_PCX = 4;
   /**
    * Return value of {@link #getFormat()} for IFF streams.
    */
   public static final int FORMAT_IFF = 5;
   /**
    * Return value of {@link #getFormat()} for RAS streams.
    * Sun Raster allows for one image per file only and is not able to
    * store physical resolution or comments.
    */
   public static final int FORMAT_RAS = 6;
   /** Return value of {@link #getFormat()} for PBM streams. */
   public static final int FORMAT_PBM = 7;
   /** Return value of {@link #getFormat()} for PGM streams. */
   public static final int FORMAT_PGM = 8;
   /** Return value of {@link #getFormat()} for PPM streams. */
   public static final int FORMAT_PPM = 9;
   /** Return value of {@link #getFormat()} for PSD streams. */
   public static final int FORMAT_PSD = 10;
   /** Return value of {@link #getFormat()} for SWF (Shockwave) streams. */
   public static final int FORMAT_SWF = 11;
   public static final int COLOR_TYPE_UNKNOWN = -1;
   public static final int COLOR_TYPE_TRUECOLOR_RGB = 0;
   public static final int COLOR_TYPE_PALETTED = 1;
   public static final int COLOR_TYPE_GRAYSCALE= 2;
   public static final int COLOR_TYPE_BLACK_AND_WHITE = 3;
   /**
    * The names of all supported file formats.
    * The FORMAT_xyz int constants can be used as index values for
    * this array.
    */
   private static final String[] FORMAT_NAMES =
       {"JPEG", "GIF", "PNG", "BMP", "PCX", 
        "IFF", "RAS", "PBM", "PGM", "PPM", 
        "PSD", "SWF"};
   /**
    * The names of the MIME types for all supported file formats.
    * The FORMAT_xyz int constants can be used as index values for
    * this array.
    */
   private static final String[] MIME_TYPE_STRINGS =
       {"image/jpeg", "image/gif", "image/png", "image/bmp", "image/pcx", 
        "image/iff", "image/ras", "image/x-portable-bitmap", "image/x-portable-graymap", "image/x-portable-pixmap", 
        "image/psd", "application/x-shockwave-flash"};
   
   private int width;
   private int height;
   private int bitsPerPixel;
   private boolean progressive;
   private int format;
   private InputStream in;
   private DataInput din;
   private boolean collectComments = true;
   private List<String> comments;
   private boolean determineNumberOfImages;
   private int numberOfImages;
   private int physicalHeightDpi;
   private int physicalWidthDpi;
   private int bitBuf;
   private int bitPos;
   private void addComment(String s) {
       if (comments == null) {
           comments = new ArrayList<String>();
       }
       comments.add(s);
   }
           
   /**
    * Call this method after you have provided an input stream or file
    * using {@link #setInput(InputStream)} or {@link #setInput(DataInput)}.
    * If true is returned, the file format was known and information
    * on the file"s content can be retrieved using the various getXyz methods.
    * @return if information could be retrieved from input
    */
   public boolean check() {
       format = -1;
       width = -1;
       height = -1;
       bitsPerPixel = -1;
       numberOfImages = 1;
       physicalHeightDpi = -1;
       physicalWidthDpi = -1;
       comments = null;
       try {
           int b1 = read() & 0xff;
           int b2 = read() & 0xff;
           if (b1 == 0x47 && b2 == 0x49) {
               return checkGif();
           }
           else
           if (b1 == 0x89 && b2 == 0x50) {
               return checkPng();
           }
           else
           if (b1 == 0xff && b2 == 0xd8) {
               return checkJpeg();
           }
           else
           if (b1 == 0x42 && b2 == 0x4d) {
               return checkBmp();
           }
           else
           if (b1 == 0x0a && b2 < 0x06) {
               return checkPcx();
           }
           else
           if (b1 == 0x46 && b2 == 0x4f) {
               return checkIff();
           }
           else
           if (b1 == 0x59 && b2 == 0xa6) {
               return checkRas();
           }
           else
           if (b1 == 0x50 && b2 >= 0x31 && b2 <= 0x36) {
               return checkPnm(b2 - "0");
           }
           else
           if (b1 == 0x38 && b2 == 0x42) {
               return checkPsd();
           }
           else
           if (b1 == 0x46 && b2 == 0x57) {
               return checkSwf();
           }
           else {
               return false;
           }
       } catch (IOException ioe) {
           return false;
       }
   }
   private boolean checkBmp() throws IOException {
       byte[] a = new byte[44];
       if (read(a) != a.length) {
           return false;
       }
       width = getIntLittleEndian(a, 16);
       height = getIntLittleEndian(a, 20);
       if (width < 1 || height < 1) {
           return false;
       }
       bitsPerPixel = getShortLittleEndian(a, 26);
       if (bitsPerPixel != 1 && bitsPerPixel != 4 &&
           bitsPerPixel != 8 && bitsPerPixel != 16 &&
           bitsPerPixel != 24 && bitsPerPixel != 32) {
           return false;
       }
       int x = (int)(getIntLittleEndian(a, 36) * 0.0254);
       if (x > 0) {
           setPhysicalWidthDpi(x);
       }
       int y = (int)(getIntLittleEndian(a, 40) * 0.0254);
       if (y > 0) {
           setPhysicalHeightDpi(y);
       }
       format = FORMAT_BMP;
       return true;
   }
   private boolean checkGif() throws IOException {
       final byte[] GIF_MAGIC_87A = {0x46, 0x38, 0x37, 0x61};
       final byte[] GIF_MAGIC_89A = {0x46, 0x38, 0x39, 0x61};
       byte[] a = new byte[11]; // 4 from the GIF signature + 7 from the global header
       if (read(a) != 11) {
           return false;
       }
       if ((!equals(a, 0, GIF_MAGIC_89A, 0, 4)) &&
           (!equals(a, 0, GIF_MAGIC_87A, 0, 4))) {
           return false;
       }
       format = FORMAT_GIF;
       width = getShortLittleEndian(a, 4);
       height = getShortLittleEndian(a, 6);
       int flags = a[8] & 0xff;
       bitsPerPixel = ((flags >> 4) & 0x07) + 1;
       progressive = (flags & 0x02) != 0;
       if (!determineNumberOfImages) {
           return true;
       }
       // skip global color palette
       if ((flags & 0x80) != 0) {
           int tableSize = (1 << ((flags & 7) + 1)) * 3;
           skip(tableSize);
       }
       numberOfImages = 0;
       int blockType;
       do
       {
           blockType = read();
           switch(blockType)
           {
               case(0x2c): // image separator
               {
                   if (read(a, 0, 9) != 9) {
                       return false;
                   }
                   flags = a[8] & 0xff;
                   int localBitsPerPixel = (flags & 0x07) + 1;
                   if (localBitsPerPixel > bitsPerPixel) {
                       bitsPerPixel = localBitsPerPixel;
                   }
                   if ((flags & 0x80) != 0) {
                       skip((1 << localBitsPerPixel) * 3);
                   }
                   skip(1); // initial code length
                   int n;
                   do
                   {
                       n = read();
                       if (n > 0) {
                           skip(n);
                       }
                       else
                       if (n == -1) {
                           return false;
                       }
                   }
                   while (n > 0);
                   numberOfImages++;
                   break;
               }
               case(0x21): // extension
               {
                   int extensionType = read();
                   if (collectComments && extensionType == 0xfe) {
                       StringBuilder sb = new StringBuilder();
                       int n;
                       do
                       {
                           n = read();
                           if (n == -1) {
                               return false;
                           }
                           if (n > 0) {
                               for (int i = 0; i < n; i++) {
                                   int ch = read();
                                   if (ch == -1) {
                                       return false;
                                   }
                                   sb.append((char)ch);
                               }
                           }
                       }
                       while (n > 0);
                   } else {
                       int n;
                       do
                       {
                           n = read();
                           if (n > 0) {
                               skip(n);
                           }
                           else
                           if (n == -1) {
                               return false;
                           }
                       }
                       while (n > 0);
                   }
                   break;
               }
               case(0x3b): // end of file
               {
                   break;
               }
               default:
               {
                   return false;
               }
           }
       }
       while (blockType != 0x3b);
       return true;
   }
   private boolean checkIff() throws IOException {
       byte[] a = new byte[10];
       // read remaining 2 bytes of file id, 4 bytes file size 
       // and 4 bytes IFF subformat
       if (read(a, 0, 10) != 10) {
           return false;
       }
       final byte[] IFF_RM = {0x52, 0x4d};
       if (!equals(a, 0, IFF_RM, 0, 2)) {
           return false;
       }
       int type = getIntBigEndian(a, 6);
       if (type != 0x494c424d && // type must be ILBM...
           type != 0x50424d20) { // ...or PBM
           return false;
       }
       // loop chunks to find BMHD chunk
       do {
           if (read(a, 0, 8) != 8) {
               return false;
           }
           int chunkId = getIntBigEndian(a, 0);
           int size = getIntBigEndian(a, 4);
           if ((size & 1) == 1) {
               size++;
           }
           if (chunkId == 0x424d4844) { // BMHD chunk
               if (read(a, 0, 9) != 9) {
                   return false;
               }
               format = FORMAT_IFF;
               width = getShortBigEndian(a, 0);
               height = getShortBigEndian(a, 2);
               bitsPerPixel = a[8] & 0xff;
               return (width > 0 && height > 0 && bitsPerPixel > 0 && bitsPerPixel < 33);
           } else {
               skip(size);
           }
       } while (true);
   }
   private boolean checkJpeg() throws IOException {
       byte[] data = new byte[12];
       while (true) {
           if (read(data, 0, 4) != 4) {
               return false;
           }
           int marker = getShortBigEndian(data, 0);
           int size = getShortBigEndian(data, 2);
           if ((marker & 0xff00) != 0xff00) {
               return false; // not a valid marker
           }
           if (marker == 0xffe0) { // APPx 
               if (size < 14) {
                   return false; // APPx header must be >= 14 bytes
               }
               if (read(data, 0, 12) != 12) {
                   return false;
               }
               final byte[] APP0_ID = {0x4a, 0x46, 0x49, 0x46, 0x00};
               if (equals(APP0_ID, 0, data, 0, 5)) {
                   if (data[7] == 1) {
                       setPhysicalWidthDpi(getShortBigEndian(data, 8));
                       setPhysicalHeightDpi(getShortBigEndian(data, 10));
                   }
                   else
                   if (data[7] == 2) {
                       int x = getShortBigEndian(data, 8);
                       int y = getShortBigEndian(data, 10);
                       setPhysicalWidthDpi((int)(x * 2.54f));
                       setPhysicalHeightDpi((int)(y * 2.54f));
                   }
               }
               skip(size - 14);
           }
           else
           if (collectComments && size > 2 && marker == 0xfffe) { // comment
               size -= 2;
               byte[] chars = new byte[size];
               if (read(chars, 0, size) != size) {
                   return false;
               }
               String comment = new String(chars, "iso-8859-1");
               comment = comment.trim();
               addComment(comment);
           }
           else
           if (marker >= 0xffc0 && marker <= 0xffcf && marker != 0xffc4 && marker != 0xffc8) {
               if (read(data, 0, 6) != 6) {
                   return false;
               }
               format = FORMAT_JPEG;
               bitsPerPixel = (data[0] & 0xff) * (data[5] & 0xff);
               progressive = marker == 0xffc2 || marker == 0xffc6 ||
                   marker == 0xffca || marker == 0xffce;
               width = getShortBigEndian(data, 3);
               height = getShortBigEndian(data, 1);
               return true;
           } else {
               skip(size - 2);
           }
       }
   }
   private boolean checkPcx() throws IOException {
       byte[] a = new byte[64];
       if (read(a) != a.length) {
           return false;
       }
       if (a[0] != 1) { // encoding, 1=RLE is only valid value
           return false;
       }
       // width / height
       int x1 = getShortLittleEndian(a, 2);
       int y1 = getShortLittleEndian(a, 4);
       int x2 = getShortLittleEndian(a, 6);
       int y2 = getShortLittleEndian(a, 8);
       if (x1 < 0 || x2 < x1 || y1 < 0 || y2 < y1) {
           return false;
       }
       width = x2 - x1 + 1;
       height = y2 - y1 + 1;
       // color depth
       int bits = a[1];
       int planes = a[63];
       if (planes == 1 &&
           (bits == 1 || bits == 2 || bits == 4 || bits == 8)) {
           // paletted
           bitsPerPixel = bits;
       } else
       if (planes == 3 && bits == 8) {
           // RGB truecolor
           bitsPerPixel = 24;
       } else {
           return false;
       }
       setPhysicalWidthDpi(getShortLittleEndian(a, 10));
       setPhysicalHeightDpi(getShortLittleEndian(a, 10));
       format = FORMAT_PCX;
       return true;
   }
   private boolean checkPng() throws IOException {
       final byte[] PNG_MAGIC = {0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a};
       byte[] a = new byte[27];
       if (read(a) != 27) {
           return false;
       }
       if (!equals(a, 0, PNG_MAGIC, 0, 6)) {
           return false;
       }
       format = FORMAT_PNG;
       width = getIntBigEndian(a, 14);
       height = getIntBigEndian(a, 18);
       bitsPerPixel = a[22] & 0xff;
       int colorType = a[23] & 0xff;
       if (colorType == 2 || colorType == 6) {
           bitsPerPixel *= 3;
       }
       progressive = (a[26] & 0xff) != 0;
       return true;
   }
   private boolean checkPnm(int id) throws IOException {
       if (id < 1 || id > 6) {
           return false;
       }
       final int[] PNM_FORMATS = {FORMAT_PBM, FORMAT_PGM, FORMAT_PPM};
       format = PNM_FORMATS[(id - 1) % 3];
       boolean hasPixelResolution = false;
       String s;
       while (true)
       {
           s = readLine();
           if (s != null) {
               s = s.trim();
           }
           if (s == null || s.length() < 1) {
               continue;
           }
           if (s.charAt(0) == "#") { // comment
               if (collectComments && s.length() > 1) {
                   addComment(s.substring(1));
               }
               continue;
           }
           if (!hasPixelResolution) { // split "343 966" into width=343, height=966
               int spaceIndex = s.indexOf(" ");
               if (spaceIndex == -1) {
                   return false;
               }
               String widthString = s.substring(0, spaceIndex);
               spaceIndex = s.lastIndexOf(" ");
               if (spaceIndex == -1) {
                   return false;
               }
               String heightString = s.substring(spaceIndex + 1);
               try {
                   width = Integer.parseInt(widthString);
                   height = Integer.parseInt(heightString);
               } catch (NumberFormatException nfe) {
                   return false;
               }
               if (width < 1 || height < 1) {
                   return false;
               }
               if (format == FORMAT_PBM) {
                   bitsPerPixel = 1;
                   return true;
               }
               hasPixelResolution = true;
           }
           else
           {
               int maxSample;
               try {
                   maxSample = Integer.parseInt(s);
               } catch (NumberFormatException nfe) {
                   return false;
               }
               if (maxSample < 0) {
                   return false;
               }
               for (int i = 0; i < 25; i++) {
                   if (maxSample < (1 << (i + 1))) {
                       bitsPerPixel = i + 1;
                       if (format == FORMAT_PPM) {
                           bitsPerPixel *= 3;
                       }
                       return true;
                   }
               }
               return false;
           }
       }
   }
   private boolean checkPsd() throws IOException {
       byte[] a = new byte[24];
       if (read(a) != a.length) {
           return false;
       }
       final byte[] PSD_MAGIC = {0x50, 0x53};
       if (!equals(a, 0, PSD_MAGIC, 0, 2)) {
           return false;
       }
       format = FORMAT_PSD;
       width = getIntBigEndian(a, 16);
       height = getIntBigEndian(a, 12);
       int channels = getShortBigEndian(a, 10);
       int depth = getShortBigEndian(a, 20);
       bitsPerPixel = channels * depth;
       return (width > 0 && height > 0 && bitsPerPixel > 0 && bitsPerPixel <= 64);
   }
   private boolean checkRas() throws IOException {
       byte[] a = new byte[14];
       if (read(a) != a.length) {
           return false;
       }
       final byte[] RAS_MAGIC = {0x6a, (byte)0x95};
       if (!equals(a, 0, RAS_MAGIC, 0, 2)) {
           return false;
       }
       format = FORMAT_RAS;
       width = getIntBigEndian(a, 2);
       height = getIntBigEndian(a, 6);
       bitsPerPixel = getIntBigEndian(a, 10);
       return (width > 0 && height > 0 && bitsPerPixel > 0 && bitsPerPixel <= 24);
   }
   // Written by Michael Aird.
   private boolean checkSwf() throws IOException {
       //get rid of the last byte of the signature, the byte of the version and 4 bytes of the size
       byte[] a = new byte[6];
       if (read(a) != a.length) {
           return false;
       }
       format = FORMAT_SWF;
       int bitSize = (int)readUBits( 5 );
       int maxX = (int)readSBits( bitSize );
       int maxY = (int)readSBits( bitSize );
       width = maxX/20; //cause we"re in twips
       height = maxY/20;  //cause we"re in twips
       setPhysicalWidthDpi(72);
       setPhysicalHeightDpi(72);
       return (width > 0 && height > 0);
   }
   private boolean equals(byte[] a1, int offs1, byte[] a2, int offs2, int num) {
       while (num-- > 0) {
           if (a1[offs1++] != a2[offs2++]) {
               return false;
           }
       }
       return true;
   }
   /** 
    * If {@link #check()} was successful, returns the image"s number of bits per pixel.
    * Does not include transparency information like the alpha channel.
    * @return number of bits per image pixel
    */
   public int getBitsPerPixel() {
       return bitsPerPixel;
   }
   /**
    * Returns the index"th comment retrieved from the image.
    * @throws IllegalArgumentException if index is smaller than 0 or larger than or equal
    * to the number of comments retrieved
    * @see #getNumberOfComments
    */
   public String getComment(int index) {
       if (comments == null || index < 0 || index >= comments.size()) {
           throw new IllegalArgumentException("Not a valid comment index: " + index);
       }
       return comments.get(index);
   }
   /**
    * If {@link #check()} was successful, returns the image format as one
    * of the FORMAT_xyz constants from this class.
    * Use {@link #getFormatName()} to get a textual description of the file format.
    * @return file format as a FORMAT_xyz constant
    */
   public int getFormat() {
       return format;
   }
   /**
    * If {@link #check()} was successful, returns the image format"s name.
    * Use {@link #getFormat()} to get a unique number.
    * @return file format name
    */
   public String getFormatName() {
       if (format >= 0 && format < FORMAT_NAMES.length) {
           return FORMAT_NAMES[format];
       } else {
           return "?";
       }
   }
   /** 
    * If {@link #check()} was successful, returns one the image"s vertical
    * resolution in pixels.
    * @return image height in pixels
    */
   public int getHeight() {
       return height;
   }
   private int getIntBigEndian(byte[] a, int offs) {
       return
           (a[offs] & 0xff) << 24 | 
           (a[offs + 1] & 0xff) << 16 | 
           (a[offs + 2] & 0xff) << 8 | 
           a[offs + 3] & 0xff;
   }
   private int getIntLittleEndian(byte[] a, int offs) {
       return
           (a[offs + 3] & 0xff) << 24 | 
           (a[offs + 2] & 0xff) << 16 | 
           (a[offs + 1] & 0xff) << 8 | 
           a[offs] & 0xff;
   }
   /** 
    * If {@link #check()} was successful, returns a String with the
    * MIME type of the format.
    * @return MIME type, e.g. image/jpeg
    */
   public String getMimeType() {
       if (format >= 0 && format < MIME_TYPE_STRINGS.length) {
           if (format == FORMAT_JPEG && progressive)
           {
               return "image/pjpeg";
           }
           return MIME_TYPE_STRINGS[format];
       } else {
           return null;
       }
   }
   /**
    * If {@link #check()} was successful and {@link #setCollectComments(boolean)} was called with
    * true as argument, returns the number of comments retrieved 
    * from the input image stream / file.
    * Any number >= 0 and smaller than this number of comments is then a
    * valid argument for the {@link #getComment(int)} method.
    * @return number of comments retrieved from input image
    */
   public int getNumberOfComments()
   {
       if (comments == null) {
           return 0;
       } else {
           return comments.size();
       }
   }
   /**
    * Returns the number of images in the examined file.
    * Assumes that setDetermineImageNumber(true); was called before
    * a successful call to {@link #check()}.
    * This value can currently be only different from 1 for GIF images.
    * @return number of images in file
    */
   public int getNumberOfImages()
   {
       return numberOfImages;
   }
   /**
    * Returns the physical height of this image in dots per inch (dpi).
    * Assumes that {@link #check()} was successful.
    * Returns -1 on failure.
    * @return physical height (in dpi)
    * @see #getPhysicalWidthDpi()
    * @see #getPhysicalHeightInch()
    */
   public int getPhysicalHeightDpi() {
       return physicalHeightDpi;
   }
   /**
    * If {@link #check()} was successful, returns the physical width of this image in dpi (dots per inch)
    * or -1 if no value could be found.
    * @return physical height (in dpi)
    * @see #getPhysicalHeightDpi()
    * @see #getPhysicalWidthDpi()
    * @see #getPhysicalWidthInch()
    */
   public float getPhysicalHeightInch() {
       int h = getHeight();
       int ph = getPhysicalHeightDpi();
       if (h > 0 && ph > 0) {
           return ((float)h) / ((float)ph);
       } else {
           return -1.0f;
       }
   }
   /**
    * If {@link #check()} was successful, returns the physical width of this image in dpi (dots per inch)
    * or -1 if no value could be found.
    * @return physical width (in dpi)
    * @see #getPhysicalHeightDpi()
    * @see #getPhysicalWidthInch()
    * @see #getPhysicalHeightInch()
    */
   public int getPhysicalWidthDpi() {
       return physicalWidthDpi;
   }
   /**
    * Returns the physical width of an image in inches, or
    * -1.0f if width information is not available.
    * Assumes that {@link #check} has been called successfully.
    * @return physical width in inches or -1.0f on failure
    * @see #getPhysicalWidthDpi
    * @see #getPhysicalHeightInch
    */
   public float getPhysicalWidthInch() {
       int w = getWidth();
       int pw = getPhysicalWidthDpi();
       if (w > 0 && pw > 0) {
           return ((float)w) / ((float)pw);
       } else {
           return -1.0f;
       }
   }
   private int getShortBigEndian(byte[] a, int offs) {
       return
           (a[offs] & 0xff) << 8 | 
           (a[offs + 1] & 0xff);
   }
   private int getShortLittleEndian(byte[] a, int offs) {
       return (a[offs] & 0xff) | (a[offs + 1] & 0xff) << 8;
   }
   /** 
    * If {@link #check()} was successful, returns one the image"s horizontal
    * resolution in pixels.
    * @return image width in pixels
    */
   public int getWidth() {
       return width;
   }
   /**
    * Returns whether the image is stored in a progressive (also called: interlaced) way.
    * @return true for progressive/interlaced, false otherwise
    */
   public boolean isProgressive()
   {
       return progressive;
   }
   private int read() throws IOException {
       if (in != null) {
           return in.read();
       } else {
           return din.readByte();
       }
   }
   private int read(byte[] a) throws IOException {
       if (in != null) {
           return in.read(a);
       } else {
           din.readFully(a);
           return a.length;
       }
   }
   private int read(byte[] a, int offset, int num) throws IOException {
       if (in != null) {
           return in.read(a, offset, num);
       } else {
           din.readFully(a, offset, num);
           return num;
       }
   }
   private String readLine() throws IOException {
       return readLine(new StringBuilder());
   }
   private String readLine(StringBuilder sb) throws IOException {
       boolean finished;
       do {
           int value = read();
           finished = (value == -1 || value == 10);
           if (!finished) {
               sb.append((char)value);
           }
       } while (!finished);
       return sb.toString();
   }
   private long readUBits( int numBits ) throws IOException
   {
       if (numBits == 0) {
           return 0;
       }
       int bitsLeft = numBits;
       long result = 0;
       if (bitPos == 0) { //no value in the buffer - read a byte
           if (in != null) {
               bitBuf = in.read();
           } else {
               bitBuf = din.readByte();
           }
           bitPos = 8;
       }
       
       while( true )
       {
           int shift = bitsLeft - bitPos;
           if( shift > 0 )
           {
               // Consume the entire buffer
               result |= bitBuf << shift;
               bitsLeft -= bitPos;
               // Get the next byte from the input stream
               if (in != null) {
                 bitBuf = in.read();
               } else {
                 bitBuf = din.readByte();
               }
               bitPos = 8;
           }
           else
           {
               // Consume a portion of the buffer
               result |= bitBuf >> -shift;
               bitPos -= bitsLeft;
               bitBuf &= 0xff >> (8 - bitPos); // mask off the consumed bits
               return result;
           }
       }        
   }
   
       /**
    * Read a signed value from the given number of bits
    */
   private int readSBits( int numBits ) throws IOException
   {
       // Get the number as an unsigned value.
       long uBits = readUBits( numBits );
       // Is the number negative?
       if( ( uBits & (1L << (numBits - 1))) != 0 )
       {
           // Yes. Extend the sign.
           uBits |= -1L << numBits;
       }
       return (int)uBits;        
   }  
   /**
    * Specify whether textual comments are supposed to be extracted from input.
    * Default is false.
    * If enabled, comments will be added to an internal list.
    * @param newValue if true, this class will read comments
    * @see #getNumberOfComments
    * @see #getComment
    */
   public void setCollectComments(boolean newValue)
   {
       collectComments = newValue;
   }
   /**
    * Specify whether the number of images in a file is to be
    * determined - default is false.
    * This is a special option because some file formats require running over
    * the entire file to find out the number of images, a rather time-consuming
    * task.
    * Not all file formats support more than one image.
    * If this method is called with true as argument,
    * the actual number of images can be queried via 
    * {@link #getNumberOfImages()} after a successful call to
    * {@link #check()}.
    * @param newValue will the number of images be determined?
    * @see #getNumberOfImages
    */
   public void setDetermineImageNumber(boolean newValue)
   {
       determineNumberOfImages = newValue;
   }
   /**
    * Set the input stream to the argument stream (or file). 
    * Note that {@link java.io.RandomAccessFile} implements
    * {@link java.io.DataInput}.
    * @param dataInput the input stream to read from
    */
   public void setInput(DataInput dataInput) {
       din = dataInput;
       in = null;
   }
   /**
    * Set the input stream to the argument stream (or file).
    * @param inputStream the input stream to read from
    */
   public void setInput(InputStream inputStream) {
       in = inputStream;
       din = null;
   }
   private void setPhysicalHeightDpi(int newValue) {
       physicalWidthDpi = newValue;
   }
   private void setPhysicalWidthDpi(int newValue) {
       physicalHeightDpi = newValue;
   }
   private void skip(int num) throws IOException {
       while (num > 0) {
           long result;
           if (in != null) {
               result = in.skip(num);
           } else {
               result = din.skipBytes(num);
           }
           if (result > 0) {
               num -= result;
           }
       }
   }

}


 </source>   



Image observer blocks until the image is completely loaded. AWT defers the loading of images until they are painted on a graphic.

<source lang="java"> /*

* JCommon : a free general purpose class library for the Java(tm) platform
* 
*
* (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
*
* Project Info:  http://www.jfree.org/jcommon/index.html
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
* USA.
*
* [Java is a trademark or registered trademark of Sun Microsystems, Inc.
* in the United States and other countries.]
*
* -------------------------
* WaitingImageObserver.java
* -------------------------
* (C)opyright 2000-2004, by Thomas Morgner and Contributors.
*
* Original Author:  Thomas Morgner
* Contributor(s):   Stefan Prange;
*
* $Id: WaitingImageObserver.java,v 1.8 2008/09/10 09:24:41 mungady Exp $
*
* Changes (from 8-Feb-2002)
* -------------------------
* 15-Apr-2002 : first version used by ImageElement.
* 16-May-2002 : Line delimiters adjusted
* 04-Jun-2002 : Documentation and added a NullPointerCheck for the constructor.
* 14-Jul-2002 : BugFixed: WaitingImageObserver dead-locked (bugfix by Stefan
*               Prange)
* 18-Mar-2003 : Updated header and made minor Javadoc changes (DG);
* 21-Sep-2003 : Moved from JFreeReport.
*/

import java.awt.Graphics; import java.awt.Image; import java.awt.image.BufferedImage; import java.awt.image.ImageObserver; import java.io.Serializable; /**

* This image observer blocks until the image is completely loaded. AWT
* defers the loading of images until they are painted on a graphic.
*
* While printing reports it is not very nice, not to know whether a image
* was completely loaded, so this observer forces the loading of the image
* until a final state (either ALLBITS, ABORT or ERROR) is reached.
*
* @author Thomas Morgner
*/

public class WaitingImageObserver implements ImageObserver, Serializable,

                                            Cloneable

{

 /** For serialization. */
 static final long serialVersionUID = -807204410581383550L;
 /** The lock. */
 private boolean lock;
 /** The image. */
 private Image image;
 /** A flag that signals an error. */
 private boolean error;
 /**
  * Creates a new ImageObserver<code> for the given <code>Image<code>.
  * The observer has to be started by an external thread.
  *
  * @param image  the image to observe (<code>null not permitted).
  */
 public WaitingImageObserver(final Image image) {
   if (image == null) {
     throw new NullPointerException();
   }
   this.image = image;
   this.lock = true;
 }
 /**
  * Callback function used by AWT to inform that more data is available. The
  * observer waits until either all data is loaded or AWT signals that the
  * image cannot be loaded.
  *
  * @param     img   the image being observed.
  * @param     infoflags   the bitwise inclusive OR of the following
  *               flags:  WIDTH, HEIGHT,
  *               PROPERTIES, SOMEBITS,
  *               FRAMEBITS, ALLBITS,
  *               ERROR, ABORT.
  * @param     x   the x coordinate.
  * @param     y   the y coordinate.
  * @param     width    the width.
  * @param     height   the height.
  *
  * @return    false if the infoflags indicate that the
  *            image is completely loaded; true otherwise.
  */
 public synchronized boolean imageUpdate(
     final Image img,
     final int infoflags,
     final int x,
     final int y,
     final int width,
     final int height) {
   if ((infoflags & ImageObserver.ALLBITS) == ImageObserver.ALLBITS) {
       this.lock = false;
       this.error = false;
       notifyAll();
       return false;
   }
   else if ((infoflags & ImageObserver.ABORT) == ImageObserver.ABORT
       || (infoflags & ImageObserver.ERROR) == ImageObserver.ERROR) {
       this.lock = false;
       this.error = true;
       notifyAll();
       return false;
   }
   //notifyAll();
   return true;
 }
 /**
  * The workerthread. Simply draws the image to a BufferedImage"s
  * Graphics-Object and waits for the AWT to load the image.
  */
 public synchronized void waitImageLoaded() {
   if (this.lock == false)
   {
     return;
   }
   final BufferedImage img = new BufferedImage(
       1, 1, BufferedImage.TYPE_INT_RGB
   );
   final Graphics g = img.getGraphics();
   while (this.lock) {
     if (g.drawImage(this.image, 0, 0, img.getWidth(this),
           img.getHeight(this), this)) {
       return;
     }
     try {
       wait(500);
     }
     catch (InterruptedException e) {
       System.out.println("WaitingImageObserver.waitImageLoaded(): InterruptedException thrown"+e);
     }
   }
 }
 /**
  * Returns true if loading is complete, and false
  * otherwise.
  *
  * @return A boolean.
  */
 public boolean isLoadingComplete() {
   return this.lock == false;
 }
 /**
  * Returns true if there is an error condition, and false otherwise.
  *
  * @return A boolean.
  */
 public boolean isError() {
   return this.error;
 }

}


 </source>   



List the image formats that can be read and written

<source lang="java"> import java.util.Arrays; import javax.imageio.ImageIO; public class Main {

 public static void main(String[] argv) throws Exception {
   String[] formatNames = ImageIO.getReaderFormatNames();
   System.out.println(Arrays.toString(formatNames));
 }

}


 </source>   



Read an Image from a file

<source lang="java"> import java.awt.BorderLayout; import java.awt.Image; import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; import java.io.InputStream; import java.net.URL; import javax.imageio.ImageIO; import javax.swing.ImageIcon; import javax.swing.JFrame; import javax.swing.JLabel; public class Main {

 public static void main(String[] argv) throws Exception {
   File sourceimage = new File("source.gif");
   Image image = ImageIO.read(sourceimage);
   JFrame frame = new JFrame();
   JLabel label = new JLabel(new ImageIcon(image));
   frame.getContentPane().add(label, BorderLayout.CENTER);
   frame.pack();
   frame.setVisible(true);
 }

}


 </source>   



Read an Image from inputStream

<source lang="java"> import java.awt.BorderLayout; import java.awt.Image; import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; import java.io.InputStream; import java.net.URL; import javax.imageio.ImageIO; import javax.swing.ImageIcon; import javax.swing.JFrame; import javax.swing.JLabel; public class Main {

 public static void main(String[] argv) throws Exception {
   InputStream is = new BufferedInputStream(new FileInputStream("s.gif"));
   Image image = ImageIO.read(is);
   JFrame frame = new JFrame();
   JLabel label = new JLabel(new ImageIcon(image));
   frame.getContentPane().add(label, BorderLayout.CENTER);
   frame.pack();
   frame.setVisible(true);
 }

}


 </source>   



Read an Image from URL

<source lang="java"> import java.awt.BorderLayout; import java.awt.Image; import java.net.URL; import javax.imageio.ImageIO; import javax.swing.ImageIcon; import javax.swing.JFrame; import javax.swing.JLabel; public class Main {

 public static void main(String[] argv) throws Exception {
   URL url = new URL("http://yourServer.ru/source.gif");
   Image image = ImageIO.read(url);
   JFrame frame = new JFrame();
   JLabel label = new JLabel(new ImageIcon(image));
   frame.getContentPane().add(label, BorderLayout.CENTER);
   frame.pack();
   frame.setVisible(true);
 }

}


 </source>   



Show Image with ImageReader

<source lang="java"> import java.awt.Graphics; import java.awt.Panel; import java.awt.image.BufferedImage; import java.io.FileInputStream; import java.util.Iterator; import javax.imageio.ImageIO; import javax.imageio.ImageReader; import javax.imageio.stream.ImageInputStream; import javax.swing.JFrame; public class Main extends Panel {

 private BufferedImage images[];
 private int imageIndex = 0;
 public Main() throws Exception {
   String filename = "a.png";
   FileInputStream inputStream = new FileInputStream(filename);
   String extensionName = filename.substring(filename.lastIndexOf(".") + 1);
   Iterator readers = ImageIO.getImageReadersBySuffix(extensionName);
   ImageReader imageReader = (ImageReader) readers.next();
   ImageInputStream imageInputStream = ImageIO.createImageInputStream(inputStream);
   imageReader.setInput(imageInputStream, false);
   int num = imageReader.getNumImages(true);
   images = new BufferedImage[num];
   for (int i = 0; i < num; ++i) {
     images[i] = imageReader.read(i);
   }
   inputStream.close();
 }
 public void paint(Graphics g) {
   if (images == null)
     return;
   g.drawImage(images[imageIndex], 0, 0, null);
   imageIndex = (imageIndex + 1) % images.length;
 }
 static public void main(String args[]) throws Exception {
   JFrame frame = new JFrame();
   Panel panel = new Main();
   frame.add(panel);
   frame.setSize(400, 400);
   frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
   frame.setVisible(true);
 }

}


</source>