/// <summary>
 /// Writes the <tt>IconEntry</tt> structure to output
 /// </summary>
 private int WriteIconEntry(BufferedImage img, int fileOffset)
 {
     // Width 1 byte Cursor Width (16, 32 or 64)
     int width = img.getWidth();
     writer.Write((byte)(width == 256 ? 0 : width));
     // Height 1 byte Cursor Height (16, 32 or 64 , most commonly = Width)
     int height = img.getHeight();
     writer.Write((byte)(height == 256 ? 0 : height));
     // ColorCount 1 byte Number of Colors (2,16, 0=256)
     short BitCount = (short)img.getColorModel().getPixelSize();
     int NumColors = 1 << (BitCount == 32 ? 24 : (int)BitCount);
     byte ColorCount = (byte)(NumColors >= 256 ? 0 : NumColors);
     writer.Write((byte)ColorCount);
     // Reserved 1 byte =0
     writer.Write((byte)0);
     // Planes 2 byte =1
     writer.Write((short)1);
     // BitCount 2 byte bits per pixel (1, 4, 8)
     writer.Write((short)BitCount);
     // SizeInBytes 4 byte Size of (InfoHeader + ANDbitmap + XORbitmap)
     int cmapSize = GetColorMapSize(BitCount);
     int xorSize = GetBitmapSize(width, height, BitCount);
     int andSize = GetBitmapSize(width, height, 1);
     int size = 40 + cmapSize + xorSize + andSize;
     writer.Write(size);
     // FileOffset 4 byte FilePos, where InfoHeader starts
     writer.Write(fileOffset);
     return size;
 }
 private void WriteXorBitmap(BufferedImage img)
 {
     Raster raster = img.getRaster();
     switch (img.getColorModel().getPixelSize())
     {
         case 1:
             Write1(raster);
             break;
         case 4:
             Write4(raster);
             break;
         case 8:
             Write8(raster);
             break;
         case 24:
             Write24(raster);
             break;
         case 32:
             Raster alpha = img.getAlphaRaster();
             Write32(raster, alpha);
             break;
     }
 }
 /// <summary>
 /// Writes the <tt>InfoHeader</tt> structure to output
 /// 
 /// </summary>
 private void WriteInfoHeader(BufferedImage img)
 {
     // Size of InfoHeader structure = 40
     writer.Write(40);
     // Width
     writer.Write(img.getWidth());
     // Height
     writer.Write(img.getHeight() * 2);
     // Planes (=1)
     writer.Write((short)1);
     // Bit count
     writer.Write((short)img.getColorModel().getPixelSize());
     // Compression
     writer.Write(0);
     // Image size - compressed size of image or 0 if Compression = 0
     writer.Write(0);
     // horizontal resolution pixels/meter
     writer.Write(0);
     // vertical resolution pixels/meter
     writer.Write(0);
     // Colors used - number of colors actually used
     writer.Write(0);
     // Colors important - number of important colors 0 = all
     writer.Write(0);
 }
        /// <summary>
        /// Encodes the <em>AND</em> bitmap for the given image according the its
        /// alpha channel (transparency) and writes it to the given output.
        /// </summary>
        /// <param name="img">
        ///            the image to encode as the <em>AND</em> bitmap. </param>
        private void WriteAndBitmap(BufferedImage img)
        {
            WritableRaster alpha = img.getAlphaRaster();

            // indexed transparency (eg. GIF files)
            if (img.getColorModel() is IndexColorModel && img.getColorModel().hasAlpha())
            {
                int w = img.getWidth();
                int h = img.getHeight();

                int bytesPerLine = GetBytesPerLine1(w);

                byte[] line = new byte[bytesPerLine];

                IndexColorModel icm = (IndexColorModel)img.getColorModel();
                Raster raster = img.getRaster();

                for (int y = h - 1; y >= 0; y--)
                {
                    for (int x = 0; x < w; x++)
                    {
                        int bi = x / 8;
                        int i = x % 8;
                        // int a = alpha.getSample(x, y, 0);
                        int p = raster.getSample(x, y, 0);
                        int a = icm.getAlpha(p);
                        // invert bit since and mask is applied to xor mask
                        int b = ~a & 1;
                        line[bi] = SetBit(line[bi], i, b);
                    }

                    writer.Write(line);
                }
            }
            // no transparency
            else if (alpha == null)
            {
                int h = img.getHeight();
                int w = img.getWidth();
                // calculate number of bytes per line, including 32-bit padding
                int bytesPerLine = GetBytesPerLine1(w);

                byte[] line = new byte[bytesPerLine];
                for (int i = 0; i < bytesPerLine; i++)
                {
                    line[i] = (byte)0;
                }

                for (int y = h - 1; y >= 0; y--)
                {
                    writer.Write(line);
                }
            }
            // transparency (ARGB, etc. eg. PNG)
            else
            {
                int w = img.getWidth();
                int h = img.getHeight();

                int bytesPerLine = GetBytesPerLine1(w);

                byte[] line = new byte[bytesPerLine];

                for (int y = h - 1; y >= 0; y--)
                {
                    for (int x = 0; x < w; x++)
                    {
                        int bi = x / 8;
                        int i = x % 8;
                        int a = alpha.getSample(x, y, 0);
                        // invert bit since and mask is applied to xor mask
                        int b = ~a & 1;
                        line[bi] = SetBit(line[bi], i, b);
                    }

                    writer.Write(line);
                }
            }
        }