JNA 将 HICON 转换为 Java 图像
JNA Convert HICON to Java Image
我知道已经有 question like this。但它的解决方案不适合我,因为使用 Sehellfolder Methode 你只能得到 16x16 和 32x32 大小的图标。
我提取了一个大小为 256x256 的 HICO,并希望将其转换为 Java 图像,如 BufferedImage。我找到了它的方法。但它不能正常工作:
public static BufferedImage getIcon(final WinDef.HICON hIcon,int ICON_SIZE,short ICON_DEPTH,int ICON_BYTE_SIZE) {
final int width = ICON_SIZE;
final int height = ICON_SIZE;
final short depth = ICON_DEPTH;
final BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
final Memory lpBitsColor = new Memory(width * height * depth / ICON_BYTE_SIZE);
final Memory lpBitsMask = new Memory(width * height * depth / ICON_BYTE_SIZE);
final WinGDI.BITMAPINFO info = new WinGDI.BITMAPINFO();
final WinGDI.BITMAPINFOHEADER hdr = new WinGDI.BITMAPINFOHEADER();
info.bmiHeader = hdr;
hdr.biWidth = width;
hdr.biHeight = height;
hdr.biPlanes = 1;
hdr.biBitCount = depth;
hdr.biCompression = WinGDI.BI_RGB;
final WinDef.HDC hDC = User32.INSTANCE.GetDC(null);
final WinGDI.ICONINFO piconinfo = new WinGDI.ICONINFO();
User32.INSTANCE.GetIconInfo(hIcon, piconinfo);
GDI32.INSTANCE.GetDIBits(hDC, piconinfo.hbmColor, 0, height, lpBitsColor, info, WinGDI.DIB_RGB_COLORS);
GDI32.INSTANCE.GetDIBits(hDC, piconinfo.hbmMask, 0, height, lpBitsMask, info, WinGDI.DIB_RGB_COLORS);
int r, g, b, a, argb;
int x = 0, y = height - 1;
for (int i = 0; i < lpBitsColor.size(); i = i + 3) {
b = lpBitsColor.getByte(i) & 0xFF;
g = lpBitsColor.getByte(i + 1) & 0xFF;
r = lpBitsColor.getByte(i + 2) & 0xFF;
a = 0xFF - lpBitsMask.getByte(i) & 0xFF;
argb = a << 24 | r << 16 | g << 8 | b;
image.setRGB(x, y, argb);
x = (x + 1) % width;
if (x == 0) {
y--;
}
}
User32.INSTANCE.ReleaseDC(null, hDC);
GDI32.INSTANCE.DeleteObject(piconinfo.hbmColor);
GDI32.INSTANCE.DeleteObject(piconinfo.hbmMask);
return image;
}
Resulting Image
你知道效果更好的安迪方法吗?
编辑:
public static BufferedImage getImageByHICON(final int width, final int height, final WinNT.HANDLE hicon, final WinGDI.BITMAPINFOHEADER info) {
final WinGDI.ICONINFO iconinfo = new WinGDI.ICONINFO();
try {
// GDI32 g32 = GDI32.INSTANCE;
// get icon information
if (!User32.INSTANCE.GetIconInfo(new WinDef.HICON(hicon.getPointer()), iconinfo)) { return null; }
final WinDef.HWND hwdn = new WinDef.HWND();
final WinDef.HDC dc = User32.INSTANCE.GetDC(hwdn);
if (dc == null) {
return null; }
try {
final int nBits = width * height * 4;
// final BitmapInfo bmi = new BitmapInfo(1);
final Memory colorBitsMem = new Memory(nBits);
// // Extract the color bitmap
final WinGDI.BITMAPINFO bmi = new WinGDI.BITMAPINFO();
bmi.bmiHeader.biWidth = width;
bmi.bmiHeader.biHeight = -height;
bmi.bmiHeader.biPlanes = 1;
bmi.bmiHeader.biBitCount = 32;
bmi.bmiHeader.biCompression = WinGDI.BI_RGB;
GDI32.INSTANCE.GetDIBits(dc, iconinfo.hbmColor, 0, height, colorBitsMem, bmi, WinGDI.DIB_RGB_COLORS);
// g32.GetDIBits(dc, iconinfo.hbmColor, 0, size, colorBitsMem,
// bmi,
// GDI32.DIB_RGB_COLORS);
final int[] colorBits = colorBitsMem.getIntArray(0, width * height);
if (info.biBitCount < 32) {
final Memory maskBitsMem = new Memory(nBits);
// // Extract the mask bitmap
GDI32.INSTANCE.GetDIBits(dc, iconinfo.hbmMask, 0, height, maskBitsMem, bmi, WinGDI.DIB_PAL_COLORS);
// g32.GetDIBits(dc, iconinfo.hbmMask, 0, size,
// maskBitsMem,
// bmi,
// // GDI32.DIB_RGB_COLORS);
final int[] maskBits = maskBitsMem.getIntArray(0, width * height);
// // // Copy the mask alphas into the color bits
for (int i = 0; i < colorBits.length; i++) {
colorBits[i] = colorBits[i] | (maskBits[i] != 0 ? 0 : 0xFF000000);
}
}
final BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
bi.setRGB(0, 0, width, height, colorBits, 0, height);
return bi;
} finally {
com.sun.jna.platform.win32.User32.INSTANCE.ReleaseDC(hwdn, dc);
}
} finally {
User32.INSTANCE.DestroyIcon(new WinDef.HICON(hicon.getPointer()));
GDI32.INSTANCE.DeleteObject(iconinfo.hbmColor);
GDI32.INSTANCE.DeleteObject(iconinfo.hbmMask);
}
}
Better Image
您需要使用示例 3 中的方法 website
我知道已经有 question like this。但它的解决方案不适合我,因为使用 Sehellfolder Methode 你只能得到 16x16 和 32x32 大小的图标。 我提取了一个大小为 256x256 的 HICO,并希望将其转换为 Java 图像,如 BufferedImage。我找到了它的方法。但它不能正常工作:
public static BufferedImage getIcon(final WinDef.HICON hIcon,int ICON_SIZE,short ICON_DEPTH,int ICON_BYTE_SIZE) {
final int width = ICON_SIZE;
final int height = ICON_SIZE;
final short depth = ICON_DEPTH;
final BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
final Memory lpBitsColor = new Memory(width * height * depth / ICON_BYTE_SIZE);
final Memory lpBitsMask = new Memory(width * height * depth / ICON_BYTE_SIZE);
final WinGDI.BITMAPINFO info = new WinGDI.BITMAPINFO();
final WinGDI.BITMAPINFOHEADER hdr = new WinGDI.BITMAPINFOHEADER();
info.bmiHeader = hdr;
hdr.biWidth = width;
hdr.biHeight = height;
hdr.biPlanes = 1;
hdr.biBitCount = depth;
hdr.biCompression = WinGDI.BI_RGB;
final WinDef.HDC hDC = User32.INSTANCE.GetDC(null);
final WinGDI.ICONINFO piconinfo = new WinGDI.ICONINFO();
User32.INSTANCE.GetIconInfo(hIcon, piconinfo);
GDI32.INSTANCE.GetDIBits(hDC, piconinfo.hbmColor, 0, height, lpBitsColor, info, WinGDI.DIB_RGB_COLORS);
GDI32.INSTANCE.GetDIBits(hDC, piconinfo.hbmMask, 0, height, lpBitsMask, info, WinGDI.DIB_RGB_COLORS);
int r, g, b, a, argb;
int x = 0, y = height - 1;
for (int i = 0; i < lpBitsColor.size(); i = i + 3) {
b = lpBitsColor.getByte(i) & 0xFF;
g = lpBitsColor.getByte(i + 1) & 0xFF;
r = lpBitsColor.getByte(i + 2) & 0xFF;
a = 0xFF - lpBitsMask.getByte(i) & 0xFF;
argb = a << 24 | r << 16 | g << 8 | b;
image.setRGB(x, y, argb);
x = (x + 1) % width;
if (x == 0) {
y--;
}
}
User32.INSTANCE.ReleaseDC(null, hDC);
GDI32.INSTANCE.DeleteObject(piconinfo.hbmColor);
GDI32.INSTANCE.DeleteObject(piconinfo.hbmMask);
return image;
}
Resulting Image
你知道效果更好的安迪方法吗?
编辑:
public static BufferedImage getImageByHICON(final int width, final int height, final WinNT.HANDLE hicon, final WinGDI.BITMAPINFOHEADER info) {
final WinGDI.ICONINFO iconinfo = new WinGDI.ICONINFO();
try {
// GDI32 g32 = GDI32.INSTANCE;
// get icon information
if (!User32.INSTANCE.GetIconInfo(new WinDef.HICON(hicon.getPointer()), iconinfo)) { return null; }
final WinDef.HWND hwdn = new WinDef.HWND();
final WinDef.HDC dc = User32.INSTANCE.GetDC(hwdn);
if (dc == null) {
return null; }
try {
final int nBits = width * height * 4;
// final BitmapInfo bmi = new BitmapInfo(1);
final Memory colorBitsMem = new Memory(nBits);
// // Extract the color bitmap
final WinGDI.BITMAPINFO bmi = new WinGDI.BITMAPINFO();
bmi.bmiHeader.biWidth = width;
bmi.bmiHeader.biHeight = -height;
bmi.bmiHeader.biPlanes = 1;
bmi.bmiHeader.biBitCount = 32;
bmi.bmiHeader.biCompression = WinGDI.BI_RGB;
GDI32.INSTANCE.GetDIBits(dc, iconinfo.hbmColor, 0, height, colorBitsMem, bmi, WinGDI.DIB_RGB_COLORS);
// g32.GetDIBits(dc, iconinfo.hbmColor, 0, size, colorBitsMem,
// bmi,
// GDI32.DIB_RGB_COLORS);
final int[] colorBits = colorBitsMem.getIntArray(0, width * height);
if (info.biBitCount < 32) {
final Memory maskBitsMem = new Memory(nBits);
// // Extract the mask bitmap
GDI32.INSTANCE.GetDIBits(dc, iconinfo.hbmMask, 0, height, maskBitsMem, bmi, WinGDI.DIB_PAL_COLORS);
// g32.GetDIBits(dc, iconinfo.hbmMask, 0, size,
// maskBitsMem,
// bmi,
// // GDI32.DIB_RGB_COLORS);
final int[] maskBits = maskBitsMem.getIntArray(0, width * height);
// // // Copy the mask alphas into the color bits
for (int i = 0; i < colorBits.length; i++) {
colorBits[i] = colorBits[i] | (maskBits[i] != 0 ? 0 : 0xFF000000);
}
}
final BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
bi.setRGB(0, 0, width, height, colorBits, 0, height);
return bi;
} finally {
com.sun.jna.platform.win32.User32.INSTANCE.ReleaseDC(hwdn, dc);
}
} finally {
User32.INSTANCE.DestroyIcon(new WinDef.HICON(hicon.getPointer()));
GDI32.INSTANCE.DeleteObject(iconinfo.hbmColor);
GDI32.INSTANCE.DeleteObject(iconinfo.hbmMask);
}
}
Better Image
您需要使用示例 3 中的方法 website