package net.charabia.jsmoothgen.pe.res; import java.awt.*; import java.awt.image.BufferedImage; import java.nio.ByteBuffer; import java.nio.ByteOrder; /** * 32 bits res icon with alpha channel */ public class ResIcon32 extends ResIcon { BufferedImage image; /** * Creates a new instance based on the data of the Image argument. * * @param img image * @throws Exception on error */ public ResIcon32(Image img) throws Exception { int width = img.getWidth(null); int height = img.getHeight(null); image = (BufferedImage) img; this.BitsPerPixel = 32; // header size this.Size = 40; this.Width = width; this.Height = height * 2; this.Planes = 1; this.Compression = 0; this.SizeOfBitmap = 0; this.HorzResolution = 0; this.VertResolution = 0; this.ColorsUsed = 0; this.ColorsImportant = 0; } /** * Creates and returns a ByteBuffer containing an image under * the .ico format expected by Windows. * * @return a ByteBuffer with the .ico data */ public ByteBuffer getData() { // transparency mask rows must be double bytes aligned int rowsize = (int) Width / 8; int padding = 0; if ((rowsize % 4) > 0) { padding = (int) ((4 - Width / 8 % 4) * 8); rowsize += 4 - (rowsize % 4); } // transparency line padding size // create transparency mask buffer int transparencyBytesSize = (int) (rowsize * (Height / 2)); int[] transparencyMask = new int[transparencyBytesSize]; // allocate header + pixel count * bytes / pixel + transparency mask size ByteBuffer buf = ByteBuffer.allocate((int) (40 + (Width * ((Height) / 2) * BitsPerPixel/8) + transparencyBytesSize)); buf.order(ByteOrder.LITTLE_ENDIAN); buf.position(0); // write header buf.putInt((int) Size); buf.putInt((int) Width); buf.putInt((int) Height); buf.putShort((short) Planes); buf.putShort((short) BitsPerPixel); buf.putInt((int) Compression); buf.putInt((int) SizeOfBitmap); buf.putInt((int) HorzResolution); buf.putInt((int) VertResolution); buf.putInt((int) ColorsUsed); buf.putInt((int) ColorsImportant); int pixelCount = 0; for (int y = (int) ((Height / 2) - 1); y >= 0; y--) { for (int x = 0; x < Width; x++) { int pix = image.getRGB(x, y); //System.out.println(x+" "+y+":"+Integer.toHexString((pix >> 24) & 0xff)); boolean isTransparent = ((pix >> 24) & 0xff) == 0; if (isTransparent) { int index = pixelCount / 8; byte bitindex = (byte) (pixelCount % 8); transparencyMask[index] |= 0x80 >> bitindex; } buf.putInt(pix); pixelCount++; } // skip to next transparency line pixelCount += padding; } // transparency mask for (int x = 0; x < transparencyBytesSize; x++) { buf.put((byte) (transparencyMask[x] & 0xff)); } buf.position(0); return buf; } public String toString() { StringBuffer out = new StringBuffer(); out.append("Size: ").append(Size); out.append("\nWidth: ").append(Width); out.append("\nHeight: ").append(Height); out.append("\nPlanes: ").append(Planes); out.append("\nBitsPerPixel: ").append(BitsPerPixel); out.append("\nCompression: ").append(Compression); out.append("\nSizeOfBitmap: ").append(SizeOfBitmap); out.append("\nHorzResolution: ").append(HorzResolution); out.append("\nVertResolution: ").append(VertResolution); out.append("\nColorsUsed: ").append(ColorsUsed); out.append("\nColorsImportant: ").append(ColorsImportant); return out.toString(); } }