[GDI+] How to BitBlt a pBitmap to a hBitmap?

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
fabricio234
Posts: 122
Joined: 06 Mar 2020, 21:48

[GDI+] How to BitBlt a pBitmap to a hBitmap?

Post by fabricio234 » 19 Aug 2023, 21:43

Code: Select all

pToken := Gdip_Startup()

;-------------------------------------------------------------------------
; create the pBitmap
file := "C:\Users\ShareX\Screenshots\test.png"
DllCall("gdiplus\GdipCreateBitmapFromFile", "WStr", file, "PtrP", pBitmap)

DllCall("gdiplus\GdipGetImageWidth", "Ptr", pBitmap, "UIntP", w)
DllCall("gdiplus\GdipGetImageHeight", "Ptr", pBitmap, "UIntP", h)

;-------------------------------------------------------------------------
; create the hBitmap
hbm := CreateDIBSection(w, h)
mDC :=DllCall("CreateCompatibleDC", "Ptr",0, "Ptr")
oBM :=DllCall("SelectObject", "Ptr",mDC, "Ptr", hBM, "Ptr")

;-------------------------------------------------------------------------
; BitBlt the pBitmap to the hBitmap
pBitmapDC := DllCall("CreateCompatibleDC", "Ptr",0, "Ptr")
pBitmapOBM := DllCall("SelectObject", "Ptr",pDC, "Ptr", pBitmap, "Ptr")
DllCall("BitBlt","Ptr",mDC,"int", 0, "int", 0,"int",w,"int",h, "Ptr", pBitmapDC, "int",0, "int",0, "uint",0xCC0020)

DllCall("SelectObject", "Ptr", mDC, "Ptr", oBM)
DllCall("DeleteDC", "Ptr", mDC)

;-------------------------------------------------------------------------
; convert the hbitmap back to pBitmap just to save and check if it worked
DllCall("gdiplus\GdipCreateBitmapFromHBITMAP", "UPtr", hbm, "UPtr", 0, "UPtr*", newpBitmap) 
outFile := "C:\Users\ShareX\Screenshots\test_2.png"
Gdip_SaveBitmapToFile(pBitmap, outFile) ; <- works, so it succeeded in creating the pBitmap
Gdip_SaveBitmapToFile(newpBitmap, outFile) ; <- fail the image is black
return

Code: Select all

CreateDIBSection(w, h, bpp:=32, ByRef ppvBits:=0, ByRef bi:="")
{
   VarSetCapacity(bi, 40, 0), NumPut(40, bi, 0, "int")
   , NumPut(w, bi, 4, "int"), NumPut(-h, bi, 8, "int")
   , NumPut(1, bi, 12, "short"), NumPut(bpp, bi, 14, "short")
   return DllCall("CreateDIBSection", "Ptr",0, "Ptr",&bi
   , "int",0, "Ptr*",ppvBits:=0, "Ptr",0, "int",0, "Ptr")
}
when I save the `pBitmap` the image is correct, it's equal to `test.png`
when I save the `newpBitmap` the image is black, so it failed, what's going on?
the value of `newpBitmap` is not 0/null

just me
Posts: 9575
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: [GDI+] How to BitBlt a pBitmap to a hBitmap?

Post by just me » 20 Aug 2023, 05:20

Code: Select all

pBitmapOBM := DllCall("SelectObject", "Ptr",pDC, "Ptr", pBitmap, "Ptr")
You cannot select a GDI+ Bitmap object into a GDI DC.

Maybe this will work:

Code: Select all

;-------------------------------------------------------------------------
; BitBlt the pBitmap to the hBitmap
; pBitmapDC := DllCall("CreateCompatibleDC", "Ptr",0, "Ptr")
; pBitmapOBM := DllCall("SelectObject", "Ptr",pDC, "Ptr", pBitmap, "Ptr")
DllCall("gdiplus\GdipGetImageGraphicsContext", "Ptr", pBitmap, "UPtrP", pGraphics)
DllCall("gdiplus\GdipGetDC", "Ptr", pGraphics, "UPtrP", pBitmapDC)
DllCall("BitBlt", "Ptr", mDC, "int", 0, "int", 0, "int", w, "int", h, "Ptr", pBitmapDC, "int", 0, "int", 0, "uint", 0xCC0020)
DllCall("gdiplus\GdipReleaseDC", "Ptr", pGraphics, "Ptr", pBitmapDC)
DllCall("gdiplus\GdipDeleteGraphics", "Ptr", pGraphics)
; DllCall("SelectObject", "Ptr", mDC, "Ptr", oBM)
; DllCall("DeleteDC", "Ptr", mDC)

fabricio234
Posts: 122
Joined: 06 Mar 2020, 21:48

Re: [GDI+] How to BitBlt a pBitmap to a hBitmap?

Post by fabricio234 » 20 Aug 2023, 11:36

just me wrote:
20 Aug 2023, 05:20

Code: Select all

pBitmapOBM := DllCall("SelectObject", "Ptr",pDC, "Ptr", pBitmap, "Ptr")
You cannot select a GDI+ Bitmap object into a GDI DC.

Maybe this will work:

Code: Select all

;-------------------------------------------------------------------------
; BitBlt the pBitmap to the hBitmap
; pBitmapDC := DllCall("CreateCompatibleDC", "Ptr",0, "Ptr")
; pBitmapOBM := DllCall("SelectObject", "Ptr",pDC, "Ptr", pBitmap, "Ptr")
DllCall("gdiplus\GdipGetImageGraphicsContext", "Ptr", pBitmap, "UPtrP", pGraphics)
DllCall("gdiplus\GdipGetDC", "Ptr", pGraphics, "UPtrP", pBitmapDC)
DllCall("BitBlt", "Ptr", mDC, "int", 0, "int", 0, "int", w, "int", h, "Ptr", pBitmapDC, "int", 0, "int", 0, "uint", 0xCC0020)
DllCall("gdiplus\GdipReleaseDC", "Ptr", pGraphics, "Ptr", pBitmapDC)
DllCall("gdiplus\GdipDeleteGraphics", "Ptr", pGraphics)
; DllCall("SelectObject", "Ptr", mDC, "Ptr", oBM)
; DllCall("DeleteDC", "Ptr", mDC)
I tried it, same result, the image saved is black

User avatar
DevWithCoffee
Posts: 55
Joined: 13 Oct 2020, 12:16

Re: [GDI+] How to BitBlt a pBitmap to a hBitmap?

Post by DevWithCoffee » 20 Aug 2023, 14:51

Hello, what version of your GDI+?

User avatar
Hellbent
Posts: 2114
Joined: 23 Sep 2017, 13:34

Re: [GDI+] How to BitBlt a pBitmap to a hBitmap?

Post by Hellbent » 20 Aug 2023, 16:34

What are you trying to do?
The best I can guess is that you want to draw an image on a gui and then save the image on the gui rather than the original image, but that only makes sense if you are trying to alter the image or otherwise combine multiple images together and then save them?
If you are trying to create an edited image you should do it all with pBitmaps unless there is some formatting or pixel level manipulation you are trying to do. What you do is create a canvas pBitmap and draw everything to it, or you take the main image bitmap and draw everything to it.


Here is the DrawImage function from the gdi+ lib by tic.
It is what I would use to draw one bitmap onto another, the canvas bitmap can then get converted to hBitmap and displayed in the gui.

Code: Select all

;#####################################################################################

; Function				Gdip_DrawImage
; Description			This function draws a bitmap into the Graphics of another bitmap
;
; pGraphics				Pointer to the Graphics of a bitmap
; pBitmap				Pointer to a bitmap to be drawn
; dx					x-coord of destination upper-left corner
; dy					y-coord of destination upper-left corner
; dw					width of destination image
; dh					height of destination image
; sx					x-coordinate of source upper-left corner
; sy					y-coordinate of source upper-left corner
; sw					width of source image
; sh					height of source image
; Matrix				a matrix used to alter image attributes when drawing
;
; return				status enumeration. 0 = success
;
; notes					if sx,sy,sw,sh are missed then the entire source bitmap will be used
;						Gdip_DrawImage performs faster
;						Matrix can be omitted to just draw with no alteration to ARGB
;						Matrix may be passed as a digit from 0 - 1 to change just transparency
;						Matrix can be passed as a matrix with any delimiter. For example:
;						MatrixBright=
;						(
;						1.5		|0		|0		|0		|0
;						0		|1.5	|0		|0		|0
;						0		|0		|1.5	|0		|0
;						0		|0		|0		|1		|0
;						0.05	|0.05	|0.05	|0		|1
;						)
;
; notes					MatrixBright = 1.5|0|0|0|0|0|1.5|0|0|0|0|0|1.5|0|0|0|0|0|1|0|0.05|0.05|0.05|0|1
;						MatrixGreyScale = 0.299|0.299|0.299|0|0|0.587|0.587|0.587|0|0|0.114|0.114|0.114|0|0|0|0|0|1|0|0|0|0|0|1
;						MatrixNegative = -1|0|0|0|0|0|-1|0|0|0|0|0|-1|0|0|0|0|0|1|0|0|0|0|0|1

Gdip_DrawImage(pGraphics, pBitmap, dx="", dy="", dw="", dh="", sx="", sy="", sw="", sh="", Matrix=1)
{
	Ptr := A_PtrSize ? "UPtr" : "UInt"
	
	if (Matrix&1 = "")
		ImageAttr := Gdip_SetImageAttributesColorMatrix(Matrix)
	else if (Matrix != 1)
		ImageAttr := Gdip_SetImageAttributesColorMatrix("1|0|0|0|0|0|1|0|0|0|0|0|1|0|0|0|0|0|" Matrix "|0|0|0|0|0|1")

	if (sx = "" && sy = "" && sw = "" && sh = "")
	{
		if (dx = "" && dy = "" && dw = "" && dh = "")
		{
			sx := dx := 0, sy := dy := 0
			sw := dw := Gdip_GetImageWidth(pBitmap)
			sh := dh := Gdip_GetImageHeight(pBitmap)
		}
		else
		{
			sx := sy := 0
			sw := Gdip_GetImageWidth(pBitmap)
			sh := Gdip_GetImageHeight(pBitmap)
		}
	}

	E := DllCall("gdiplus\GdipDrawImageRectRect"
				, Ptr, pGraphics
				, Ptr, pBitmap
				, "float", dx
				, "float", dy
				, "float", dw
				, "float", dh
				, "float", sx
				, "float", sy
				, "float", sw
				, "float", sh
				, "int", 2
				, Ptr, ImageAttr
				, Ptr, 0
				, Ptr, 0)
	if ImageAttr
		Gdip_DisposeImageAttributes(ImageAttr)
	return E
}

;#####################################################################################

Post Reply

Return to “Ask for Help (v1)”