Java/2D Graphics GUI/ImageReader
Содержание
- 1 Add Image IO Read Progress Listener to ImageReader
- 2 Detect the file type of the input stream prior to reading the image
- 3 Determining the Format of an Image in a File
- 4 Get file format, image resolution, number of bits per pixel (JPEG, GIF, BMP, PCX, PNG, IFF, RAS, PBM, PGM, PPM, PSD and SWF files)
- 5 Image format info
- 6 Image observer blocks until the image is completely loaded. AWT defers the loading of images until they are painted on a graphic.
- 7 List the image formats that can be read and written
- 8 Read an Image from a file
- 9 Read an Image from inputStream
- 10 Read an Image from URL
- 11 Show Image with ImageReader
Add Image IO Read Progress Listener to ImageReader
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);
}
}
Detect the file type of the input stream prior to reading the image
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();
}
}
Determining the Format of an Image in a File
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;
}
}
Get file format, image resolution, number of bits per pixel (JPEG, GIF, BMP, PCX, PNG, IFF, RAS, PBM, PGM, PPM, PSD and SWF files)
//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:
* <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 !
* 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 <code>-c</code>.
*/
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. <code>image/jpeg</code>
*/
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
* <code>true</code> 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 <code>setDetermineImageNumber(true);</code> was called before
* a successful call to {@link #check()}.
* This value can currently be only different from <code>1</code> 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 <code>-1</code> 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
* <code>-1.0f</code> if width information is not available.
* Assumes that {@link #check} has been called successfully.
*
* @return physical width in inches or <code>-1.0f</code> 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 <code>false</code>.
* If enabled, comments will be added to an internal list.
*
* @param newValue if <code>true</code>, 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 <code>false</code>.
* 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 <code>true</code> 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;
}
}
}
}
Image format info
/*
#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
#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).
* <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 !
* 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. <code>image/jpeg</code>
*/
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
* <code>true</code> 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 <code>setDetermineImageNumber(true);</code> was called before
* a successful call to {@link #check()}.
* This value can currently be only different from <code>1</code> 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 <code>-1</code> 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
* <code>-1.0f</code> if width information is not available.
* Assumes that {@link #check} has been called successfully.
* @return physical width in inches or <code>-1.0f</code> 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 <code>false</code>.
* If enabled, comments will be added to an internal list.
* @param newValue if <code>true</code>, 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 <code>false</code>.
* 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 <code>true</code> 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;
}
}
}
}
Image observer blocks until the image is completely loaded. AWT defers the loading of images until they are painted on a graphic.
/*
* 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 <code>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</code> 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: <code>WIDTH</code>, <code>HEIGHT</code>,
* <code>PROPERTIES</code>, <code>SOMEBITS</code>,
* <code>FRAMEBITS</code>, <code>ALLBITS</code>,
* <code>ERROR</code>, <code>ABORT</code>.
* @param x the <i>x</i> coordinate.
* @param y the <i>y</i> coordinate.
* @param width the width.
* @param height the height.
*
* @return <code>false</code> if the infoflags indicate that the
* image is completely loaded; <code>true</code> 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 <code>true</code> if loading is complete, and <code>false</code>
* 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;
}
}
List the image formats that can be read and written
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));
}
}
Read an Image from a file
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);
}
}
Read an Image from inputStream
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);
}
}
Read an Image from URL
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);
}
}
Show Image with ImageReader
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);
}
}