FileDocCategorySizeDatePackage
PNGData.javaAPI DocExample3989Mon Apr 05 11:21:36 BST 1999None

PNGData.java

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;
  }
}