public static Dimension getPngDimension(File file) throws IOException
{
RandomAccessFile raf = new RandomAccessFile(file, "r");
try
{
byte[] header = new byte[8];
raf.readFully(header);
while (true)
{
byte[] _len = new byte[4];
raf.readFully(_len);
int len = readInt(_len, 0);
byte[] _ctype = new byte[4];
raf.readFully(_ctype);
char[] _ctypec = new char[4];
for (int i = 0; i < 4; i++)
_ctypec[i] = (char) _ctype[i];
String type = new String(_ctypec);
byte[] cdata = new byte[len + 4];
raf.readFully(cdata);
if (type.equals("IHDR"))
{
int w = readInt(cdata, 0);
int h = readInt(cdata, 4);
return new Dimension(w, h);
}
else if (type.equals("IDAT"))
{
continue;
}
else if (type.equals("IEND"))
{
throw new IllegalStateException("PNG corrupt?");
}
}
}
finally
{
raf.close();
}
}
public static final int readInt(byte[] buf, int off)
{
int val = 0;
val |= (buf[off + 0] & 0xFF) << 24;
val |= (buf[off + 1] & 0xFF) << 16;
val |= (buf[off + 2] & 0xFF) << 8;
val |= (buf[off + 3] & 0xFF) << 0;
return val;
}
I’d suggest doing either no error checking at all, or doing it all, not half-baked mixture.
Currently that method is not checking the validity of the 8 bytes of png signature, or the integrity of the chunk CRCs.
It is however checking that the IHDR appears before the IEND… but doesn’t check that the IHDR chunk appears first. (something explicitly required in the spec.)
If you arn’t going to do any error checking at all, you can get a png’s dimensions with something as simple as (disclaimer - haven’t actually tested this code ):-
public static Dimension getPngDimension(File file) throws IOException {
RandomAccessFile raf = new RandomAccessFile(file, "r");
try{
raf.seek(8+4+4);
return new Dimension(raf.readInt(),raf.readInt());
}
finally {
raf.close();
}
}
Yeah, sorry. I took it from a PNG loader, that can progressively load pixels (line by line). Which is nice if you’re working with huge images.
I could have removed much more code.
I use ImageReader to retrieve information about contents of a source image.
imageReader is instancied with the static getImageReaderBy*() functions and has a ImageReader.getWidth() ImageReader.getHeight() capabilities among others.