我想从特定应用程序检索图像并将其转换为图像。图片供以后使用。
我现在有一个HBITMAP从windows API调用。在尝试了很多之后,我无法将创建的HBITMAP转换为图像。图像(或至少一个[]字节)。
rc := w32.GetClientRect(hwnd)
if rc != nil {
// create
HDCScreen := w32.GetWindowDC(hwnd)
hdc := w32.CreateCompatibleDC(HDCScreen)
hbmp := w32.CreateCompatibleBitmap(HDCScreen, int(rc.Right)-int(rc.Left), int(rc.Bottom)-int(rc.Top))
w32.SelectObject(hdc, w32.HGDIOBJ(hbmp))
// Print to memory hdc
w32.PrintWindow(hwnd, hdc, 0x00000002)
// ------------------------------------------------
var bmpInfo *w32.BITMAPINFO = &w32.BITMAPINFO{}
bmpInfo.BmiHeader.BiSize = uint32(unsafe.Sizeof(bmpInfo.BmiHeader))
firstDIBits := w32.GetDIBits(HDCScreen, hbmp, 0, 0, nil, bmpInfo, w32.DIB_RGB_COLORS)
fmt.Printf("firstDIBits: %vn", firstDIBits)
var lpPixels *[]byte
bmpInfo.BmiHeader.BiBitCount = 32
bmpInfo.BmiHeader.BiCompression = w32.BI_RGB
bmpInfo.BmiHeader.BiHeight = int32(math.Abs(float64(bmpInfo.BmiHeader.BiHeight)))
bmpInfo.BmiHeader.BiCompression = w32.BI_RGB
secondDIBits := w32.GetDIBits(hdc, hbmp, 0, uint(bmpInfo.BmiHeader.BiHeight), unsafe.Pointer(lpPixels), bmpInfo, w32.DIB_RGB_COLORS)
fmt.Printf("secondDIBits: %vn", secondDIBits)
fmt.Printf("lpPixels: %vn", lpPixels)
// ------------------------------------------------
// copy to clipBoard
w32.OpenClipboard(0)
w32.EmptyClipboard()
w32.SetClipboardData(w32.CF_BITMAP, w32.HANDLE(hbmp))
w32.CloseClipboard()
// release
w32.DeleteDC(hdc)
w32.DeleteObject(w32.HGDIOBJ(hbmp))
w32.ReleaseDC(0, HDCScreen)
}
GetDIBits()调用返回1,但lpPixels总是nil。
Bitmap类继承自Image类。在我看来,你不需要转换。
根据Doc:GetDIBits函数
[出]lpvBits
指向缓冲区的指针,用于接收位图数据。如果此参数为NULL,函数将位图的尺寸和格式传递给lpbi形参指向的BITMAPINFO结构
我不太了解Go语言,但是GetDIBits的lpvBits参数似乎不正确。我建议你可以参考线程:
使用GetDIBits加载位图
如何使用GetDIBits函数
终于成功了。把代码贴出来,也许能帮到别人。:)
rect := image.Rect(0, 0, 1920, 1080)
img := image.NewRGBA(rect)
rc := w32.GetClientRect(hwnd)
if rc != nil {
width := int(rc.Right) - int(rc.Left)
height := int(rc.Bottom) - int(rc.Top)
hwndwin := win.HWND(hwnd)
hdc := win.GetDC(hwndwin)
if hdc == 0 {
panic("GetDC failed")
}
defer win.ReleaseDC(hwndwin, hdc)
memory_device := win.CreateCompatibleDC(hdc)
if memory_device == 0 {
panic("CreateCompatibleDC failed")
}
defer win.DeleteDC(memory_device)
bitmap := win.CreateCompatibleBitmap(hdc, int32(width), int32(height))
if bitmap == 0 {
panic("CreateCompatibleBitmap failed")
}
defer win.DeleteObject(win.HGDIOBJ(bitmap))
var header win.BITMAPINFOHEADER
header.BiSize = uint32(unsafe.Sizeof(header))
header.BiPlanes = 1
header.BiBitCount = 32
header.BiWidth = int32(width)
header.BiHeight = int32(-height)
header.BiCompression = win.BI_RGB
header.BiSizeImage = 0
// GetDIBits balks at using Go memory on some systems. The MSDN example uses GlobalAlloc
// https://docs.microsoft.com/en-gb/windows/desktop/gdi/capturing-an-image
bitmapDataSize := uintptr(((int64(width)*int64(header.BiBitCount) + 31) / 32) * 4 * int64(height))
hmem := win.GlobalAlloc(win.GMEM_MOVEABLE, bitmapDataSize)
defer win.GlobalFree(hmem)
memptr := win.GlobalLock(hmem)
defer win.GlobalUnlock(hmem)
old := win.SelectObject(memory_device, win.HGDIOBJ(bitmap))
if old == 0 {
panic("SelectObject failed")
}
defer win.SelectObject(memory_device, old)
if !win.BitBlt(memory_device, 0, 0, int32(width), int32(height), hdc, int32(0), int32(0), win.SRCCOPY) {
panic("BitBlt failed")
}
if win.GetDIBits(hdc, bitmap, 0, uint32(height), (*uint8)(memptr), (*win.BITMAPINFO)(unsafe.Pointer(&header)), win.DIB_RGB_COLORS) == 0 {
panic("GetDIBits failed")
}
i := 0
src := uintptr(memptr)
for y := 0; y < height; y++ {
for x := 0; x < width; x++ {
v0 := *(*uint8)(unsafe.Pointer(src))
v1 := *(*uint8)(unsafe.Pointer(src + 1))
v2 := *(*uint8)(unsafe.Pointer(src + 2))
// BGRA => RGBA, and set A to 255
img.Pix[i], img.Pix[i+1], img.Pix[i+2], img.Pix[i+3] = v2, v1, v0, 255
i += 4
src += 4
}
}