840 lines · 34.6 KB · Java
RawDownload
                    // code added to make it work with ImageDecoder arch                      sendPixels(0,0,width,height,bPixels,0,width);                      //end of adding                  }            }    /* Here, the function "visit(row,column,height,width)" obtains the      next transmitted pixel and paints a rectangle of the specified      height and width, whose upper-left corner is at the specified row      and column, using the color indicated by the pixel.  Note that row      and column are measured from 0,0 at the upper left corner. */             /* code not needed, don't deal with target             if((t=target)!=null) {               if(properties!=null) t.setProperties(properties);                 t.imageComplete(ImageConsumer.STATICIMAGEDONE);                 */               imageComplete(ImageConsumer.STATICIMAGEDONE, true);               /* code not needed }               is.close();               */        } catch(IOException e) {            if(!aborted) {                /* code not needed                   if((t=target)!=null) {                   PNGEncoder.prChunk(e.toString(),inbuf,pos,limit-pos,true);                */                property("error", e);                /* code not needed                   t.setProperties(properties);                   t.imageComplete(ImageConsumer.IMAGEERROR|ImageConsumer.STATICIMAGEDONE);                */                imageComplete(ImageConsumer.IMAGEERROR|ImageConsumer.STATICIMAGEDONE, true);                throw e;            }        } finally {          try { close(); } catch(Throwable e){}          /* code not needed             target = null;             endTurn();             */        }    }     private boolean sendPixels(int x, int y, int w, int h, int[] pixels,                               int offset, int pixlength) {        int count = setPixels(x, y, w, h, cm,                              pixels, offset, pixlength);        if (count <= 0) {            aborted = true;        }        return !aborted;    }    private boolean sendPixels(int x, int y, int w, int h, byte[] pixels,                               int offset, int pixlength) {        int count = setPixels(x, y, w, h, cm,                              pixels, offset, pixlength);        if (count <= 0) {            aborted = true;        }        return !aborted;    }     private void filterRow(byte rowByteBuffer[], byte[] prevRow,                           int rowFilter, int rowByteWidth, int bytesPerSample)        throws IOException {        int x = 0;        switch (rowFilter) {          case 0:            break;          case 1:            for (x = bytesPerSample; x < rowByteWidth; x++)                rowByteBuffer[x] += rowByteBuffer[x - bytesPerSample];            break;          case 2:            if (prevRow != null)                for ( ; x < rowByteWidth; x++)                    rowByteBuffer[x] += prevRow[x];            break;          case 3:            if (prevRow != null) {                for ( ; x < bytesPerSample; x++)                    rowByteBuffer[x] += (0xff & prevRow[x])>>1;                for ( ; x < rowByteWidth; x++)                    rowByteBuffer[x] += ((prevRow[x]&0xFF) + (rowByteBuffer[x - bytesPerSample]&0xFF))>>1;            } else                for (x = bytesPerSample; x < rowByteWidth; x++)                    rowByteBuffer[x] += (rowByteBuffer[x - bytesPerSample]&0xFF)>>1;            break;          case 4:            if (prevRow != null) {                for ( ; x < bytesPerSample; x++)                    rowByteBuffer[x] += prevRow[x];                for ( ; x < rowByteWidth; x++) {                    int a, b, c, p, pa, pb, pc, rval;                    a = rowByteBuffer[x - bytesPerSample]&0xFF;                    b = prevRow[x]&0xFF;                    c = prevRow[x - bytesPerSample]&0xFF;                    p = a + b - c;                    pa = p > a ? p - a : a - p;                    pb = p > b ? p - b : b - p;                    pc = p > c ? p - c : c - p;                    rowByteBuffer[x] += (pa <= pb) && (pa <= pc) ? a : pb <= pc ? b : c;                }            } else                for (x = bytesPerSample; x < rowByteWidth; x++)                    rowByteBuffer[x] += rowByteBuffer[x - bytesPerSample];            break;          default:            throw new PNGException("Illegal filter");        }    }    private static final byte[] startingRow =  { 0, 0, 0, 4, 0, 2, 0, 1 };    private static final byte[] startingCol =  { 0, 0, 4, 0, 2, 0, 1, 0 };    private static final byte[] rowIncrement = { 1, 8, 8, 8, 4, 4, 2, 2 };    private static final byte[] colIncrement = { 1, 8, 8, 4, 4, 2, 2, 1 };    private static final byte[] blockHeight =  { 1, 8, 8, 4, 4, 2, 2, 1 };    private static final byte[] blockWidth =   { 1, 8, 4, 4, 2, 2, 1, 1 };     //abstract public class ChunkReader extends FilterInputStream {  int pos, limit;    int chunkStart;   int chunkKey, chunkLength, chunkCRC;    boolean seenEOF;     private static final byte[] signature = { (byte) 137, (byte) 80, (byte) 78,        (byte) 71, (byte) 13, (byte) 10, (byte) 26, (byte) 10 };   PNGFilterInputStream inputStream;  InputStream underlyingInputStream;   /* code changed    public PNGImageDecoder(InputStream in, ImageConsumer t) throws IOException {    */  public PNGImageDecoder(InputStreamImageSource src, InputStream input) throws IOException {    // code added    super(src, input);    inputStream = new PNGFilterInputStream(this, input);    underlyingInputStream = inputStream.underlyingInputStream;    // end of adding    /* code changed       super(in);       target = t;       waitTurn();       new Thread(this).start();       */    }  /* code changed to make it work with ImageDecoder architecture    static int ThreadLimit = 10;    private synchronized static void waitTurn() {        try {            while(ThreadLimit<=0) PNGImageDecoder.class.wait(1000);        } catch(InterruptedException e){}        ThreadLimit--;    }    private synchronized static void endTurn() {        if(ThreadLimit<=0) PNGImageDecoder.class.notify();        ThreadLimit++;    }    */    byte[] inbuf = new byte[4096];    private void fill() throws IOException {        if(!seenEOF) {            if(pos>0 && pos<limit) {                System.arraycopy(inbuf,pos,inbuf,0,limit-pos);                limit = limit-pos;                pos = 0;            } else if(pos>=limit) {                pos = 0; limit = 0;            }            int bsize = inbuf.length;            while(limit<bsize) {                int n = underlyingInputStream.read(inbuf,limit,bsize-limit);                if(n<=0) { seenEOF=true; break; }                limit += n;            }        }    }    private boolean need(int n) throws IOException {        if(limit-pos>=n) return true;        fill();        if(limit-pos>=n) return true;        if(seenEOF) return false;        byte nin[] = new byte[n+100];        System.arraycopy(inbuf,pos,nin,0,limit-pos);        limit = limit-pos;        pos = 0;        inbuf = nin;        fill();        return limit-pos>=n;    }    private final int getInt(int pos) {        return ((inbuf[pos  ]&0xFF)<<24)             | ((inbuf[pos+1]&0xFF)<<16)             | ((inbuf[pos+2]&0xFF)<< 8)             | ((inbuf[pos+3]&0xFF)    );    }    private final int getShort(int pos) {        return (short)(((inbuf[pos  ]&0xFF)<<8)                     | ((inbuf[pos+1]&0xFF)   ));    }    private final int getByte(int pos) {        return inbuf[pos]&0xFF;    }    private final boolean getChunk() throws IOException {        chunkLength = 0;        if (!need(8)) return false;        chunkLength = getInt(pos);        chunkKey = getInt(pos+4);        if(chunkLength<0) throw new PNGException("bogus length: "+chunkLength);        if (!need(chunkLength+12)) return false;        chunkCRC = getInt(pos+8+chunkLength);        chunkStart = pos+8;        int calcCRC = crc(inbuf,pos+4,chunkLength+4);        if(chunkCRC!=calcCRC && checkCRC) throw new PNGException("crc corruption");        pos+=chunkLength+12;        return true;    }    private void readAll() throws IOException {        while(getChunk()) handleChunk(chunkKey,inbuf,chunkStart,chunkLength);    }    boolean getData() throws IOException {        while(chunkLength==0 && getChunk())            if(handleChunk(chunkKey,inbuf,chunkStart,chunkLength))                chunkLength = 0;        return chunkLength>0;    }    //abstract protected boolean handleChunk(int key, byte[] buf, int st, int len)    //    throws IOException;    private static boolean checkCRC = true;    public static boolean getCheckCRC() { return checkCRC; }    public static void setCheckCRC(boolean c) { checkCRC = c; }     protected void wrc(int c) {        c = c&0xFF;        if(c<=' '||c>'z') c = '?';        System.out.write(c);    }    protected void wrk(int n) {        wrc(n>>24);        wrc(n>>16);        wrc(n>>8);        wrc(n);    }    public void print() {        wrk(chunkKey);        System.out.print(" "+chunkLength+"\n");    }     /* Table of CRCs of all 8-bit messages. */    private static final int[] crc_table = new int[256];     /* Make the table for a fast CRC. */    static {        for (int n = 0; n < 256; n++) {            int c = n;            for (int k = 0; k < 8; k++)                if ((c & 1) != 0)                    c = 0xedb88320 ^ (c >>> 1);                else                    c = c >>> 1;            crc_table[n] = c;        }    }     /* Update a running CRC with the bytes buf[0..len-1]--the CRC    should be initialized to all 1's, and the transmitted value    is the 1's complement of the final running CRC (see the    crc() routine below)). */     static private int update_crc(int crc, byte[] buf, int offset, int len) {        int c = crc;        while (--len>=0)            c = crc_table[(c ^ buf[offset++]) & 0xff] ^ (c >>> 8);        return c;    }     /* Return the CRC of the bytes buf[0..len-1]. */    static private int crc(byte[] buf, int offset, int len) {        return update_crc(0xffffffff, buf, offset, len) ^ 0xffffffff;    }    public static class Chromaticities {        public float whiteX, whiteY, redX, redY, greenX, greenY, blueX, blueY;        Chromaticities(int wx, int wy, int rx, int ry, int gx, int gy, int bx, int by) {            whiteX = wx/100000.0f;            whiteY = wy/100000.0f;            redX = rx/100000.0f;            redY = ry/100000.0f;            greenX = gx/100000.0f;            greenY = gy/100000.0f;            blueX = bx/100000.0f;            blueY = by/100000.0f;        }        public String toString() {            return "Chromaticities(white="+whiteX+","+whiteY+";red="+                redX+","+redY+";green="+                greenX+","+greenY+";blue="+                blueX+","+blueY+")";        }    }} // the following class are added to make it work with ImageDecoder architecture class PNGFilterInputStream extends FilterInputStream {  PNGImageDecoder owner;  public InputStream underlyingInputStream;  public PNGFilterInputStream(PNGImageDecoder owner, InputStream is) {    super(is);    underlyingInputStream = in;    this.owner = owner;  }     public int available() throws IOException {        return owner.limit-owner.pos+in.available();}    public boolean markSupported() { return false; }    public int read() throws IOException {        if(owner.chunkLength<=0) if(!owner.getData()) return -1;        owner.chunkLength--;        return owner.inbuf[owner.chunkStart++]&0xFF;    }    public int read(byte[] b) throws IOException{return read(b,0,b.length);}    public int read(byte[] b, int st, int len) throws IOException {        if(owner.chunkLength<=0) if(!owner.getData()) return -1;        if(owner.chunkLength<len) len = owner.chunkLength;        System.arraycopy(owner.inbuf,owner.chunkStart,b,st,len);        owner.chunkLength-=len;        owner.chunkStart+=len;        return len;    }  public long skip(long n) throws IOException {        int i;        for(i = 0; i<n && read()>=0; i++);        return i;    }  }

Lines 501–840 of 840. Previous lines