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