PNG class

From J2me wiki


import javax.microedition.lcdui.*;

class Png
{
  static int[]   crc_table;
  static int   dataptr;
  static int   crcfrom;
  static int   pngsize;
  static byte[]   data;
  static byte[]   PNG_header={-119,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,0,0,0,0,0,8,3,0,0,0};
  static byte[]   PNG_End={0,0,0,0,73,69,78,68,-82,66,96,-126};
  
  static
  {
     crc_table = new int[256];
     
     for (int n = 0; n < 256; n++)
     {
        int c = n;
        for (int k = 8;  --k >= 0; )
        {
           if ((c & 1) != 0)
              c = 0xedb88320 ^ (c >>> 1);
           else
              c = c >>> 1;
        }         
        crc_table[n] = c;
     }
  }

  static Image create(int width, int height, int palette, byte[] idata, byte[] pal, int trans, int flips, int imgStart, int palStart)
  {
     int i,j;
     Image temp;
     
     if(flips>3)            // If rotating swap width and height around
     {
        int t=width;
        width=height;
        height=t;
     }      
     
     pngsize = palette*3 + (width+1)*height + 80;
     
     if(trans>-1) pngsize += 13 + trans; 
     
     data = new byte[pngsize];
     
     // Create PNG Header      
     for(i=0;i<PNG_header.length;i++)
        data[i] = PNG_header[i];

     data[19] = (byte)width;
     data[23] = (byte)height;
  
     dataptr=29;
     
     writeInt(calc_crc(data, 12, 17));

     writeInt(palette*3);
     
     crcfrom=dataptr;
     
     writeInt(0x504c5445);      // PLTE Header
     
     for(i=0;i<palette*3;i++)
        data[dataptr++]=pal[i+palStart*3];
     
     writeInt(calc_crc(data, crcfrom, dataptr - crcfrom));
     
     if(trans>-1)
     {
        writeInt(trans+1);

        crcfrom=dataptr;      

        writeInt(0x74524e53);      // tRNS Header
        
        for(i=0;i<trans;i++)
           data[dataptr++]=(byte)0xff;
        
        data[dataptr++]=0;
        
        writeInt(calc_crc(data, crcfrom, dataptr - crcfrom));
     }
     
     int compsize = (width+1) * height;
     
     writeInt(compsize+11);         // Write IDAT Length
     
     crcfrom=dataptr;      
     
     writeInt(0x49444154);         // IDAT Header
     
     data[dataptr++]=(byte)0x78;      // PNG compression flags
     data[dataptr++]=(byte)0xda;      // PNG compression flags
     data[dataptr++]=(byte)0x01;      // PNG final block / No compression

     data[dataptr++]=(byte)(compsize & 0xff);      // Write data length (little endian)
     data[dataptr++]=(byte)((compsize>>>8) & 0xff);
     
     data[dataptr]=(byte)(~data[dataptr-2]);         // Write inverse length
     dataptr++;
     data[dataptr]=(byte)(~data[dataptr-2]);   
     dataptr++;
     
     int adlerstart = dataptr;
  
     switch(flips)
     {
        case 0:      // No Flip

           i=imgStart;            
           for(int y=0;y<height;y++)
           {
              data[dataptr++]=0;
              for(int x=0;x<width;x++)
                 data[dataptr++]=idata[i++];
           }
           break;
           
        case 1:      // X Flip
           
           for(int y=0;y<height;y++)
           {
              i=(y+1)*width-1+imgStart;
              data[dataptr++]=0;
              for(int x=0;x<width;x++)
                 data[dataptr++]=idata[i--];
           }
           break;
           
        case 2:      // Y Flip
           
           for(int y=0;y<height;y++)
           {
              i=(height-y-1)*width+imgStart;
              data[dataptr++]=0;      // No Filter flag for each line
              for(int x=0;x<width;x++)
                 data[dataptr++]=idata[i++];
           }
           break;   
           
        case 3:      // XY Flip
           
           for(int y=0;y<height;y++)
           {
              i=(height-y)*width-1+imgStart;
              data[dataptr++]=0;      // No Filter flag for each line
              for(int x=0;x<width;x++)
                 data[dataptr++]=idata[i--];
           }
           break;
           
        case 4:   // Rotated 90 CW
           
           j=(width-1)*height+imgStart;
           for(int y=0;y<height;y++)
           {
              i=j+y;
              data[dataptr++]=0;
              for(int x=0;x<width;x++)
              {
                 data[dataptr++]=idata[i];
                 i-=height;
              }
           }
           break;
           
        case 5:   // Rotated 90 CCW
           
           j=height+imgStart-1;
           for(int y=0;y<height;y++)
           {
              i=j-y;
              data[dataptr++]=0;
              for(int x=0;x<width;x++)
              {
                 data[dataptr++]=idata[i];
                 i+=height;
              }
           }
           break;               
     }
     
     int adler1=1;
     int adler2=0;

     for(i=0;i<compsize;i++)
     {
        adler1=adler1+((int)data[adlerstart+i]&0xff);
        adler2=adler1+adler2;
        adler1%=65521;
        adler2%=65521;
     }      
     writeInt((adler2<<16) | adler1 );      
     writeInt(calc_crc(data, crcfrom, dataptr - crcfrom));
     
     for(i=0;i<PNG_End.length;i++)
        data[dataptr++] = PNG_End[i];
     
     temp = Image.createImage (data,0, dataptr);
     data = null;      
     return temp;
  }
  
  static void writeInt(long crc)
  {
     data[dataptr++]=(byte)((crc>>>24)&255);
     data[dataptr++]=(byte)((crc>>>16)&255);      
     data[dataptr++]=(byte)((crc>>>8)&255);      
     data[dataptr++]=(byte)(crc&255);
  }
  
  static long calc_crc (byte[] buf, int off, int len)
  {
     int c = ~0;
     while (--len >= 0)
     c = crc_table[(c ^ buf[off++]) & 0xff] ^ (c >>> 8);      
     return (long) ~c & 0xffffffffL;
  }   
}


credit: user Glen