Mega Code Archive

 
Categories / Java / 2D Graphics GUI
 

Icon Codec

/*   JSmooth: a VM wrapper toolkit for Windows   Copyright (C) 2003 Rodrigo Reyes <reyes@charabia.net>     This program is free software; you can redistribute it and/or modify   it under the terms of the GNU General Public License as published by   the Free Software Foundation; either version 2 of the License, or   (at your option) any later version.     This program is distributed in the hope that it will be useful,   but WITHOUT ANY WARRANTY; without even the implied warranty of   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the   GNU General Public License for more details.     You should have received a copy of the GNU General Public License   along with this program; if not, write to the Free Software   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.    */ import java.io.*; import java.awt.image.*; import java.awt.*; /**  *  * @author  Rodrigo Reyes  */ public class IcoCodec {     static public class IconDir     {         int idType;         int idCount;   public IconDir(BinaryInputStream in) throws IOException   {       in.readUShortLE();       idType = in.readUShortLE();       idCount = in.readUShortLE();   }      public String toString()   {       return "{ idType=" + idType + ", " + idCount + " }";   }     }          static public class IconEntry     {         short  bWidth;         short  bHeight;         short  bColorCount;         short  bReserved;         int  wPlanes;         int  wBitCount;         long dwBytesInRes;         long dwImageOffset;   public IconEntry(BinaryInputStream in) throws IOException   {       bWidth = in.readUByte();       bHeight = in.readUByte();       bColorCount = in.readUByte();       bReserved = in.readUByte();       wPlanes = in.readUShortLE();       wBitCount = in.readUShortLE();       dwBytesInRes = in.readUIntLE();       dwImageOffset = in.readUIntLE();   }   public String toString()   {       StringBuffer buffer = new StringBuffer();       buffer.append("{ bWidth="+bWidth+"\n");       buffer.append("  bHeight="+bHeight+"\n");       buffer.append("  bColorCount="+bColorCount+"\n");       buffer.append("  wPlanes="+wPlanes+"\n");       buffer.append("  wBitCount="+wBitCount+"\n");       buffer.append("  dwBytesInRes="+dwBytesInRes+"\n");       buffer.append("  dwImageOffset="+dwImageOffset+"\n");       buffer.append("}");       return buffer.toString();   }     }     static public class IconHeader     {   public long Size;            /* Size of this header in bytes DWORD 0*/   public long Width;           /* Image width in pixels LONG 4*/   public long Height;          /* Image height in pixels LONG 8*/   public int  Planes;          /* Number of color planes WORD 12 */   public int  BitsPerPixel;    /* Number of bits per pixel WORD 14 */   /* Fields added for Windows 3.x follow this line */   public long Compression;     /* Compression methods used DWORD 16 */   public long SizeOfBitmap;    /* Size of bitmap in bytes DWORD 20 */   public long HorzResolution;  /* Horizontal resolution in pixels per meter LONG 24 */   public long VertResolution;  /* Vertical resolution in pixels per meter LONG 28*/   public long ColorsUsed;      /* Number of colors in the image DWORD 32 */   public long ColorsImportant; /* Minimum number of important colors DWORD 36 */      public IconHeader(BinaryInputStream in) throws IOException   {       Size = in.readUIntLE();       Width = in.readUIntLE();       Height = in.readUIntLE();       Planes = in.readUShortLE();       BitsPerPixel = in.readUShortLE();       Compression = in.readUIntLE();       SizeOfBitmap = in.readUIntLE();       HorzResolution = in.readUIntLE();       VertResolution = in.readUIntLE();       ColorsUsed = in.readUIntLE();       ColorsImportant = in.readUIntLE();   }   public String toString()   {       StringBuffer buffer = new StringBuffer();       buffer.append("Size="); buffer.append(Size);       buffer.append("\nWidth="); buffer.append(Width);       buffer.append("\nHeight="); buffer.append(Height);       buffer.append("\nPlanes="); buffer.append(Planes);       buffer.append("\nBitsPerPixel="); buffer.append(BitsPerPixel);       buffer.append("\nCompression="); buffer.append(Compression);       buffer.append("\nSizeOfBitmap="); buffer.append(SizeOfBitmap);       buffer.append("\nHorzResolution="); buffer.append(HorzResolution);       buffer.append("\nVertResolution="); buffer.append(VertResolution);       buffer.append("\nColorsUsed="); buffer.append(ColorsUsed);       buffer.append("\nColorsImportant="); buffer.append(ColorsImportant);       return buffer.toString();   }     }          static public BufferedImage[] loadImages(File f) throws IOException     {   InputStream istream = new FileInputStream(f);         BufferedInputStream buffin = new BufferedInputStream(istream);   BinaryInputStream in = new BinaryInputStream(buffin);   try {       in.mark(32000);       IconDir dir = new IconDir(in);       //      System.out.println("DIR = " + dir);              IconEntry[] entries = new IconEntry[dir.idCount];       BufferedImage[] images = new BufferedImage[dir.idCount];       for (int i=0; i<dir.idCount; i++)     {         entries[i] = new IconEntry(in);         //        System.out.println("ENTRY " + i + " = " + entries[i]);     }       IconEntry entry = entries[0];       //      System.out.println("ENTRYx = " + entry);       for (int i=0; i<dir.idCount; i++)     {         in.reset();         in.skip(entries[i].dwImageOffset);         IconHeader header = new IconHeader(in);         //        System.out.println("Header: " + header);         long toskip = header.Size - 40;         if (toskip>0)       in.skip((int)toskip);         //        System.out.println("skipped data");                  BufferedImage image = new BufferedImage((int)header.Width, (int)header.Height/2,                   BufferedImage.TYPE_INT_ARGB);                  switch(header.BitsPerPixel)       {       case 4:       case 8:           loadPalettedImage(in, entries[i], header, image);           break;                  default:           throw new Exception("Unsupported ICO color depth: " + header.BitsPerPixel);       }         images[i] = image;     }       return images;   } catch (Exception exc)       {     exc.printStackTrace();       }   return null;     }     static private void loadPalettedImage(BinaryInputStream in, IconEntry entry, IconHeader header, BufferedImage image) throws Exception     {   //  System.out.println("Loading image...");      //  System.out.println("Loading palette...");   //    // First, load the palette   //   int cols = (int)header.ColorsUsed;   if (cols == 0)       {     if (entry.bColorCount != 0)         cols = entry.bColorCount;     else         cols = 1 << header.BitsPerPixel;       }   int[] redp = new int[cols];   int[] greenp = new int[cols];   int[] bluep = new int[cols];   for (int i=0; i<cols; i++)       {     bluep[i] = in.readUByte();     greenp[i] = in.readUByte();     redp[i] = in.readUByte();     in.readUByte();       }   //  System.out.println("Palette read!");   //   // Set the image   int xorbytes = (((int)header.Height/2) * (int)header.Width);   int readbytes = 0;   for (int y=(int)(header.Height/2)-1; y>=0; y--)       {     for (int x=0; x<header.Width; x++)         {       switch(header.BitsPerPixel)           {           case 4:         {             int pix = in.readUByte();             readbytes++;             int col1 = (pix>>4) & 0x0F;             int col2 = pix & 0x0F;             image.setRGB(x, y, (0xFF<<24) | (redp[col1]<<16) | (greenp[col1]<<8) | bluep[col1]);             image.setRGB(++x, y, (0xFF<<24) | (redp[col2]<<16) | (greenp[col2]<<8) | bluep[col2]);         }         break;           case 8:         {             int col1 = in.readUByte();             readbytes++;             image.setRGB(x, y, (0xFF<<24) | (redp[col1]<<16) | (greenp[col1]<<8) | bluep[col1]);         }         break;           }         }       }   //  System.out.println("XOR data read (" + readbytes + " bytes)");   int height = (int)(header.Height/2);   int rowsize = (int)header.Width / 8;   if ((rowsize%4)>0)       {     rowsize += 4 - (rowsize%4);       }      //  System.out.println("rowsize = " + rowsize);   int[] andbytes = new int[rowsize * height ];   for (int i=0; i<andbytes.length; i++)       andbytes[i] = in.readUByte();   for (int y=height-1; y>=0; y--)       {     for (int x=0; x<header.Width; x++)         {       int offset = ((height - (y+1))*rowsize) + (x/8);       if ( (andbytes[offset] & (1<<(7-x%8))) != 0)           {         image.setRGB(x, y, 0);           }         }       }   //  for (int i=0; i<andbytes; i++)   //      {   //    int pix = in.readUByte();   //    readbytes++;   //    int xb = (i*8) % (int)header.Width;   //    int yb = ((int)header.Height/2) - (((i*8) / (int)header.Width)+1);   //    for (int offset=7; offset>=0; offset--)   //        {   //      //   //      // Modify the transparency only if necessary   //      //   //      System.out.println("SET AND (" + xb + "," + yb + ")-" + (7-offset));   //      if (((1<<offset) & pix)!=0)   //          {   //        int argb = image.getRGB(xb+(7-offset), yb);   //        image.setRGB(xb+(7-offset), yb, argb & 0xFFFFFF);   //          }   //        }   //      }      //  System.out.println("AND data read (" + readbytes + " bytes total)");     }          static public void main(String[]args) throws Exception     {   File f = new File(args[0]);   Image img = IcoCodec.loadImages(f)[0];   //  System.out.println("img = " + img);   javax.swing.JFrame jf = new javax.swing.JFrame("Test");   javax.swing.JButton button = new javax.swing.JButton(new javax.swing.ImageIcon(img));   jf.getContentPane().add(button);   jf.pack();   jf.setVisible(true);     }      } /* JSmooth: a VM wrapper toolkit for Windows Copyright (C) 2003 Rodrigo Reyes <reyes@charabia.net> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ class BinaryInputStream extends FilterInputStream {   public BinaryInputStream(InputStream in)   { super(in);   }   public void skip(int toskip) throws IOException   { for (int skipped = 0; skipped >= toskip; skipped += in.skip(toskip - skipped))     ;   }   public byte readByte() throws IOException   { return (byte)read();   }   public short readUByte() throws IOException   { return (short)read();   }   public short readShortBE() throws IOException   { int a = read(); int b = read(); return (short) (((a&0xff)<<8) | (b&0xff));   }   public int readUShortBE() throws IOException   { int a = read(); int b = read(); return ((a&0xff)<<8) | (b&0xff);   }   public short readShortLE() throws IOException   { int a = read(); int b = read(); return (short) (((b&0xff)<<8) | (a&0xff));   }   public int readUShortLE() throws IOException   { int a = read(); int b = read(); return ((b&0xff)<<8) | (a&0xff);   }   public int readIntBE() throws IOException   { int a = read(); int b = read(); int c = read(); int d = read(); return ((a&0xff)<<24) | ((b&0xff)<<16) | ((c&0xff)<<8) | (d&0xff);   }   public long readUIntBE() throws IOException   { int a = read(); int b = read(); int c = read(); int d = read(); return (long)((a&0xff)<<24) | (long)((b&0xff)<<16) | (long)((c&0xff)<<8) | (long)(d&0xff);   }   public int readIntLE() throws IOException   { int a = readByte(); int b = readByte(); int c = readByte(); int d = readByte(); return ((d&0xff)<<24) | ((c&0xff)<<16) | ((b&0xff)<<8) | (a&0xff);   }   public long readUIntLE() throws IOException   { int a = readByte(); int b = readByte(); int c = readByte(); int d = readByte(); return (long)((d&0xff)<<24) | (long)((c&0xff)<<16) | (long)((b&0xff)<<8) | (long)(a&0xff);   } }