More cautious image creation
This commit is contained in:
parent
e09faaf491
commit
1b3f66703f
@ -34,6 +34,8 @@ import com.sun.jna.ptr.PointerByReference;
|
||||
|
||||
public class HBITMAPWrap extends HBITMAP {
|
||||
|
||||
private static final Object lockObject = new Object();
|
||||
|
||||
// NOTE: This is a field (instead of private) so that GC does not try to collect this object
|
||||
private HBITMAP bitmap;
|
||||
|
||||
@ -42,54 +44,58 @@ public class HBITMAPWrap extends HBITMAP {
|
||||
HBITMAP createBitmap(BufferedImage image) {
|
||||
int w = image.getWidth(null);
|
||||
int h = image.getHeight(null);
|
||||
HDC screenDC = User32.GetDC(null);
|
||||
HDC memDC = GDI32.CreateCompatibleDC(screenDC);
|
||||
HBITMAP hBitmap = null;
|
||||
|
||||
try {
|
||||
BufferedImage buf = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB_PRE);
|
||||
Graphics2D g = (Graphics2D) buf.getGraphics();
|
||||
g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER));
|
||||
g.drawImage(image, 0, 0, w, h, null);
|
||||
// all sorts of issues occur if this is called quickly from different threads!
|
||||
synchronized(lockObject) {
|
||||
HDC screenDC = User32.GetDC(null);
|
||||
HDC memDC = GDI32.CreateCompatibleDC(screenDC);
|
||||
HBITMAP hBitmap = null;
|
||||
|
||||
WinGDI.BITMAPINFO bmi = new WinGDI.BITMAPINFO();
|
||||
bmi.bmiHeader.biWidth = w;
|
||||
bmi.bmiHeader.biHeight = h;
|
||||
bmi.bmiHeader.biPlanes = 1;
|
||||
bmi.bmiHeader.biBitCount = 32;
|
||||
bmi.bmiHeader.biCompression = WinGDI.BI_RGB;
|
||||
bmi.bmiHeader.biSizeImage = w * h * 4;
|
||||
try {
|
||||
BufferedImage buf = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB_PRE);
|
||||
Graphics2D g = (Graphics2D) buf.getGraphics();
|
||||
g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER));
|
||||
g.drawImage(image, 0, 0, w, h, null);
|
||||
|
||||
Memory memory = new Memory(w*h*32*4);
|
||||
PointerByReference pointerRef = new PointerByReference(memory);
|
||||
hBitmap = GDI32.CreateDIBSection(memDC, bmi, WinGDI.DIB_RGB_COLORS, pointerRef, null, 0);
|
||||
Pointer pointerToBits = pointerRef.getValue();
|
||||
WinGDI.BITMAPINFO bmi = new WinGDI.BITMAPINFO();
|
||||
bmi.bmiHeader.biWidth = w;
|
||||
bmi.bmiHeader.biHeight = h;
|
||||
bmi.bmiHeader.biPlanes = 1;
|
||||
bmi.bmiHeader.biBitCount = 32;
|
||||
bmi.bmiHeader.biCompression = WinGDI.BI_RGB;
|
||||
bmi.bmiHeader.biSizeImage = w * h * 4;
|
||||
|
||||
if (pointerToBits == null) {
|
||||
// the bitmap was invalid
|
||||
LoggerFactory.getLogger(HBITMAPWrap.class).error("The image was invalid", Kernel32Util.getLastErrorMessage());
|
||||
}
|
||||
else {
|
||||
Raster raster = buf.getData();
|
||||
int[] pixel = new int[4];
|
||||
int[] bits = new int[w * h];
|
||||
for (int y = 0; y < h; y++) {
|
||||
for (int x = 0; x < w; x++) {
|
||||
raster.getPixel(x, h - y - 1, pixel);
|
||||
int red = (pixel[2] & 0xFF) << 0;
|
||||
int green = (pixel[1] & 0xFF) << 8;
|
||||
int blue = (pixel[0] & 0xFF) << 16;
|
||||
int alpha = (pixel[3] & 0xFF) << 24;
|
||||
bits[x + y * w] = alpha | red | green | blue;
|
||||
}
|
||||
Memory memory = new Memory(w*h*32*4);
|
||||
PointerByReference pointerRef = new PointerByReference(memory);
|
||||
hBitmap = GDI32.CreateDIBSection(memDC, bmi, WinGDI.DIB_RGB_COLORS, pointerRef, null, 0);
|
||||
Pointer pointerToBits = pointerRef.getValue();
|
||||
|
||||
if (pointerToBits == null) {
|
||||
// the bitmap was invalid
|
||||
LoggerFactory.getLogger(HBITMAPWrap.class).error("The image was invalid", Kernel32Util.getLastErrorMessage());
|
||||
}
|
||||
else {
|
||||
Raster raster = buf.getData();
|
||||
int[] pixel = new int[4];
|
||||
int[] bits = new int[w * h];
|
||||
for (int y = 0; y < h; y++) {
|
||||
for (int x = 0; x < w; x++) {
|
||||
raster.getPixel(x, h - y - 1, pixel);
|
||||
int red = (pixel[2] & 0xFF) << 0;
|
||||
int green = (pixel[1] & 0xFF) << 8;
|
||||
int blue = (pixel[0] & 0xFF) << 16;
|
||||
int alpha = (pixel[3] & 0xFF) << 24;
|
||||
bits[x + y * w] = alpha | red | green | blue;
|
||||
}
|
||||
}
|
||||
pointerToBits.write(0, bits, 0, bits.length);
|
||||
}
|
||||
pointerToBits.write(0, bits, 0, bits.length);
|
||||
}
|
||||
|
||||
return hBitmap;
|
||||
} finally {
|
||||
User32.ReleaseDC(null, screenDC);
|
||||
GDI32.DeleteDC(memDC);
|
||||
return hBitmap;
|
||||
} finally {
|
||||
User32.ReleaseDC(null, screenDC);
|
||||
GDI32.DeleteDC(memDC);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -27,6 +27,7 @@ import dorkbox.jna.windows.structs.ICONINFO;
|
||||
* http://www.pinvoke.net/default.aspx/user32.createiconindirect
|
||||
*/
|
||||
public class HICONWrap extends HICON {
|
||||
private static final Object lockObject = new Object();
|
||||
|
||||
static HICON createIconIndirect(HBITMAP bm) {
|
||||
ICONINFO info = new ICONINFO();
|
||||
@ -36,7 +37,14 @@ public class HICONWrap extends HICON {
|
||||
|
||||
HICON hicon = User32.CreateIconIndirect(info);
|
||||
if (hicon == null) {
|
||||
throw new GetLastErrorException();
|
||||
// something weird is going on! Try again but more carefully!
|
||||
synchronized(lockObject) {
|
||||
hicon = User32.CreateIconIndirect(info);
|
||||
}
|
||||
|
||||
if (hicon == null) {
|
||||
throw new GetLastErrorException();
|
||||
}
|
||||
}
|
||||
|
||||
return hicon;
|
||||
|
Loading…
Reference in New Issue
Block a user