import java.awt.Transparency; import java.awt.color.*; import java.awt.image.*; import java.io.*; import java.util.zip.*; public class PNGData { private int mNumberOfChunks; private PNGChunk[] mChunks; public PNGData() { mNumberOfChunks = 0; mChunks = new PNGChunk[10]; } public void add(PNGChunk chunk) { mChunks[mNumberOfChunks++] = chunk; if (mNumberOfChunks >= mChunks.length) { PNGChunk[] largerArray = new PNGChunk[mChunks.length + 10]; System.arraycopy(mChunks, 0, largerArray, 0, mChunks.length); mChunks = largerArray; } } public long getWidth() { return getChunk("IHDR").getUnsignedInt(0); } public long getHeight() { return getChunk("IHDR").getUnsignedInt(4); } public short getBitsPerPixel() { return getChunk("IHDR").getUnsignedByte(8); } public short getColorType() { return getChunk("IHDR").getUnsignedByte(9); } public short getCompression() { return getChunk("IHDR").getUnsignedByte(10); } public short getFilter() { return getChunk("IHDR").getUnsignedByte(11); } public short getInterlace() { return getChunk("IHDR").getUnsignedByte(12); } public ColorModel getColorModel() { short colorType = getColorType(); int bitsPerPixel = getBitsPerPixel(); if (colorType == 3) { byte[] paletteData = getChunk("PLTE").getData(); int paletteLength = paletteData.length / 3; return new IndexColorModel(bitsPerPixel, paletteLength, paletteData, 0, false); } System.out.println("Unsupported color type: " + colorType); return null; } public WritableRaster getRaster() { int width = (int)getWidth(); int height = (int)getHeight(); int bitsPerPixel = getBitsPerPixel(); short colorType = getColorType(); if (colorType == 3) { byte[] imageData = getImageData(); DataBuffer db = new DataBufferByte(imageData, imageData.length); WritableRaster raster = Raster.createPackedRaster(db, width, height, bitsPerPixel, null); return raster; } else System.out.println("Unsupported color type!"); return null; } public byte[] getImageData() { try { ByteArrayOutputStream out = new ByteArrayOutputStream(); // Write all the IDAT data into the array. for (int i = 0; i < mNumberOfChunks; i++) { PNGChunk chunk = mChunks[i]; if (chunk.getTypeString().equals("IDAT")) { out.write(chunk.getData()); } } out.flush(); // Now deflate the data. InflaterInputStream in = new InflaterInputStream( new ByteArrayInputStream(out.toByteArray())); ByteArrayOutputStream inflatedOut = new ByteArrayOutputStream(); int readLength; byte[] block = new byte[8192]; while ((readLength = in.read(block)) != -1) inflatedOut.write(block, 0, readLength); inflatedOut.flush(); byte[] imageData = inflatedOut.toByteArray(); // Compute the real length. int width = (int)getWidth(); int height = (int)getHeight(); int bitsPerPixel = getBitsPerPixel(); int length = width * height * bitsPerPixel / 8; byte[] prunedData = new byte[length]; // We can only deal with non-interlaced images. if (getInterlace() == 0) { int index = 0; for (int i = 0; i < length; i++) { if ((i * 8 / bitsPerPixel) % width == 0) { index++; // Skip the filter byte. } prunedData[i] = imageData[index++]; } } else System.out.println("Couldn't undo interlacing."); return prunedData; } catch (IOException ioe) {} return null; } public PNGChunk getChunk(String type) { for (int i = 0; i < mNumberOfChunks; i++) if (mChunks[i].getTypeString().equals(type)) return mChunks[i]; return null; } }