127 lines
4.1 KiB
Java
127 lines
4.1 KiB
Java
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();
|
|
}
|
|
|
|
}
|