Jump to content

Sky Slate Blueberry Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate
Photo

GDI+ standard library 1.45 by tic


  • Please log in to reply
1385 replies to this topic
tic
  • Members
  • 1934 posts
  • Last active: Dec 21 2015 01:05 PM
  • Joined: 22 Apr 2007
Also you can do

pBrush := Gdip_BrushCreateSolid(Gdip_ToARGB(A, R, G, B))


tic
  • Members
  • 1934 posts
  • Last active: Dec 21 2015 01:05 PM
  • Joined: 22 Apr 2007
Wicked

You can use the following to read from a BRA in AHK_L unicode, but the BRA library needs to be rewritten to be able to create BRAs, so AHK would need to be used to create BRAs for now

Gdip_BitmapFromBRA(ByRef BRAFromMemIn, File, Alternate=0)
{
   BRAHeader := StrGet(&BRAFromMemIn, "CP0")
   if !BRAHeader
      return -1
   Loop, Parse, BRAHeader, `n
   {
      if (A_Index = 1)
      {
         StringSplit, Header, A_LoopField, |
         if (Header0 != 4 || Header2 != "BRA!")
            return -2
      }
      else if (A_Index = 2)
      {
         StringSplit, Info, A_LoopField, |
         if (Info0 != 3)
            return -3
      }
      else
         break
   }
   if !Alternate
      StringReplace, File, File, \, \\, All
   RegExMatch(BRAHeader, "mi`n)^" (Alternate ? File "\|.+?\|(\d+)\|(\d+)" : "\d+\|" File "\|(\d+)\|(\d+)") "$", FileInfo)
   if !FileInfo
      return -4

   hData := DllCall("GlobalAlloc", "uint", 2, "uptr", FileInfo2, "ptr")
   pData := DllCall("GlobalLock", "ptr", hData, "ptr")
   DllCall("RtlMoveMemory", "ptr", pData, "ptr", &BRAFromMemIn+Info2+FileInfo1, "uptr", FileInfo2)
   DllCall("GlobalUnlock", "ptr", hData)
   DllCall("ole32\CreateStreamOnHGlobal", "ptr", hData, "int", 1, "ptr*", pStream)
   DllCall("gdiplus\GdipCreateBitmapFromStream", "ptr", pStream, "ptr*", pBitmap)
   ObjRelease(pStream)
   return pBitmap
}

A note is that you would need to use the *c option when reading the BRA

FileRead, BRA, *c Gdip.tutorial.file-fish.bra

Thanks to fincs for his help with this

Wicked
  • Members
  • 504 posts
  • Last active: Nov 02 2017 11:07 PM
  • Joined: 07 Jun 2008
OMG, yes! I've never been able to, but always been very excited to, see the BRA files in action! Thank you, tic and fincs!

3nL8f.png


djarkan
  • Members
  • 11 posts
  • Last active: Dec 31 2011 09:02 PM
  • Joined: 30 Mar 2011
hi

link broken to download the gdiplus.dll

Wicked
  • Members
  • 504 posts
  • Last active: Nov 02 2017 11:07 PM
  • Joined: 07 Jun 2008
Another idea for you, tic. :).

Along the lines of filtering out pixels and such, you could take two images (probably of the same dimensions), and filter out pixels that are not the same.

For example, I have these screenshots from RuneScape:
Posted Image
Posted Image
Filtering out pixels that are not identical, I'd be left with the interface on the right, minus the mini-map and the compass, and the interface on the top left.

That's only an example, but I've found the need for such a function many times for other cases. I've just taken the easy road in using Photoshop, but... :p.

3nL8f.png


Learning one
  • Members
  • 1483 posts
  • Last active: Jan 02 2016 02:30 PM
  • Joined: 04 Apr 2009

WARNING: This is old post; continuation here.

Hi tic,

I wrapped some additional GraphicsPath GDI+ functions. Feel free to make them part of your Gdip.ahk library. I'm also posting an example which shows how to work with GraphicsPaths and hatch & linear gradient Brushes. Tested and works on AHK Basic and AHK_L.

Functions


;#####################################################################################
; GraphicsPath functions added by Learning one
;#####################################################################################

; Function Gdip_AddPathBeziers
; Description Adds a sequence of connected Bézier splines to the current figure of this path.
;
; pPath Pointer to the GraphicsPath
; Points the coordinates of all the points passed as x1,y1|x2,y2|x3,y3.....
;
; return status enumeration. 0 = success

; Notes The first spline is constructed from the first point through the fourth point in the array and uses the second and third points as control points. Each subsequent spline in the sequence needs exactly three more points: the ending point of the previous spline is used as the starting point, the next two points in the sequence are control points, and the third point is the ending point.

Gdip_AddPathBeziers(pPath, Points) {
StringSplit, Points, Points, |
VarSetCapacity(PointF, 8*Points0)
Loop, %Points0%
{
StringSplit, Coord, Points%A_Index%, `,
NumPut(Coord1, PointF, 8*(A_Index-1), "float"), NumPut(Coord2, PointF, (8*(A_Index-1))+4, "float")
}
return DllCall("gdiplus\GdipAddPathBeziers", "uint", pPath, "uint", &PointF, "int", Points0)
}

Gdip_AddPathBezier(pPath, x1, y1, x2, y2, x3, y3, x4, y4) { ; Adds a Bézier spline to the current figure of this path
return DllCall("gdiplus\GdipAddPathBezier", "uint", pPath
, "float", x1, "float", y1, "float", x2, "float", y2
, "float", x3, "float", y3, "float", x4, "float", y4)
}

; Function Gdip_AddPathLines
; Description Adds a sequence of connected lines to the current figure of this path.
;
; pPath Pointer to the GraphicsPath
; Points the coordinates of all the points passed as x1,y1|x2,y2|x3,y3.....
;
; return status enumeration. 0 = success

Gdip_AddPathLines(pPath, Points) {
StringSplit, Points, Points, |
VarSetCapacity(PointF, 8*Points0)
Loop, %Points0%
{
StringSplit, Coord, Points%A_Index%, `,
NumPut(Coord1, PointF, 8*(A_Index-1), "float"), NumPut(Coord2, PointF, (8*(A_Index-1))+4, "float")
}
return DllCall("gdiplus\GdipAddPathLine2", "uint", pPath, "uint", &PointF, "int", Points0)
}

Gdip_AddPathLine(pPath, x1, y1, x2, y2) {
return DllCall("gdiplus\GdipAddPathLine", "uint", pPath
, "float", x1, "float", y1, "float", x2, "float", y2)
}

Gdip_AddPathArc(pPath, x, y, w, h, StartAngle, SweepAngle) {
return DllCall("gdiplus\GdipAddPathArc", "uint", pPath, "float", x, "float", y, "float", w, "float", h, "float", StartAngle, "float", SweepAngle)
}

Gdip_AddPathPie(pPath, x, y, w, h, StartAngle, SweepAngle) {
return DllCall("gdiplus\GdipAddPathPie", "uint", pPath, "float", x, "float", y, "float", w, "float", h, "float", StartAngle, "float", SweepAngle)
}

Gdip_StartPathFigure(pPath) { ; Starts a new figure without closing the current figure. Subsequent points added to this path are added to the new figure.
return DllCall("gdiplus\GdipStartPathFigure", "uint", pPath)
}

Gdip_ClosePathFigure(pPath) { ; Closes the current figure of this path.
return DllCall("gdiplus\GdipClosePathFigure", "uint", pPath)
}

; Function Gdip_DrawPath
; Description draws a sequence of lines and curves defined by a GraphicsPath object
;
; pGraphics Pointer to the Graphics of a bitmap
; pPen Pointer to a pen
; pPath Pointer to a Path
;
; return status enumeration. 0 = success

Gdip_DrawPath(pGraphics, pPen, pPath) {
return DllCall("gdiplus\GdipDrawPath", "uint", pGraphics, "uint", pPen, "uint", pPath)
}

Gdip_WidenPath(pPath, pPen, Matrix=0, Flatness=1) { ; Replaces this path with curves that enclose the area that is filled when this path is drawn by a specified pen. This method also flattens the path.
return DllCall("gdiplus\GdipWidenPath", "uint", pPath, "uint", pPen, "uint", Matrix, "float", Flatness)
}

Gdip_ClonePath(pPath) {
DllCall("gdiplus\GdipClonePath", "uint", pPath, "uint*", pPathClone)
return pPathClone
}

Example


#NoEnv

;=== Create Gui, OnMessage ===
Gui 1: -Caption +E0x80000 +LastFound +AlwaysOnTop +ToolWindow +OwnDialogs
hGui := WinExist()
Gui 1: Show, NA
w := 550, h := 280
OnMessage(0x201, "WM_LBUTTONDOWN")


;===GDI+ prepare ===
pToken := Gdip_Startup()
hbm := CreateDIBSection(w, h), hdc := CreateCompatibleDC(), obm := SelectObject(hdc, hbm)
G := Gdip_GraphicsFromHDC(hdc), Gdip_SetSmoothingMode(G, 4)


;=== Background ===
pBrush := Gdip_CreateLineBrushFromRect(0, 0, w, h, 0xff555555, 0xff050505)
Gdip_FillRectangle(G, pBrush, 0, 0, w, h)
Gdip_DeleteBrush(pBrush)

pBrush := Gdip_BrushCreateHatch(0xff000000, 0x00000000, 8)
Gdip_FillRectangle(G, pBrush, 0, 0, w, h)
Gdip_DeleteBrush(pBrush)


;=== Create path (Bat) ===
pPath := Gdip_CreatePath() ; creates a Path (GraphicsPath object)

Gdip_StartPathFigure(pPath) ; starts a new figure in this Path
Gdip_AddPathLine(pPath, 110,95, 220,95) ; adds a line to the current figure of this path
Gdip_AddPathBezier(pPath, 220,95, 228,112, 233,120, 262,120) ; adds bezier
Gdip_AddPathLines(pPath, "262,120|265,95|269,110|280,110|284,95|287,120") ; adds lines
Gdip_AddPathBezier(pPath, 287,120, 305,120, 320,120, 330,95)
Gdip_AddPathLine(pPath, 330,95, 439,95)
Gdip_AddPathBeziers(pPath, "439,95|406,108|381,126|389,159|322,157|287,170|275,206|262,170|227,157|160,159|168,126|144,109|110,95") ; adds beziers
Gdip_ClosePathFigure(pPath) ; closes the current figure of this path


;=== Fill & draw path (Bat) === ; now when the path is finished, we can fill it with brushes and outline with pens
;pPen := Gdip_CreatePen(0x22ffffff, 14), Gdip_DrawPath(G, pPen, pPath), Gdip_DeletePen(pPen) ; uncomment to draw extra outline

pBrush := Gdip_CreateLineBrushFromRect(0, 95, w, (h-190)/2, 0xff110000, 0xff664040)
Gdip_FillPath(G, pBrush, pPath) ; fill Bat background 1
Gdip_DeleteBrush(pBrush)

pBrush := Gdip_BrushCreateHatch(0xff000000, 0x00000000, 21)
Gdip_FillPath(G, pBrush, pPath) ; fill Bat background 2
Gdip_DeleteBrush(pBrush)

pPen := Gdip_CreatePen(0xffa5a5a5, 5)
Gdip_DrawPath(G, pPen, pPath) ; draw Bat outline 1
Gdip_DeletePen(pPen)

pPen := Gdip_CreatePen(0xff000000, 1)
Gdip_DrawPath(G, pPen, pPath) ; draw Bat outline 2
Gdip_DeletePen(pPen)

Gdip_DeletePath(pPath) ; delete the Path as it is no longer needed and wastes memory


;=== Update, Delete, Shutdown ===
UpdateLayeredWindow(hGui, hdc, (A_ScreenWidth-w)//2, (A_ScreenHeight-h)//2, w, h)
SelectObject(hdc, obm), DeleteObject(hbm), DeleteDC(hdc)
Gdip_DeleteGraphics(G)
Gdip_Shutdown(pToken)
return


Esc::ExitApp


;===Functions===========================================================================
#Include Gdip.ahk

WM_LBUTTONDOWN() {
PostMessage, 0xA1, 2
}

;#####################################################################################
; GraphicsPath functions added by Learning one
;#####################################################################################

; Function Gdip_AddPathBeziers
; Description Adds a sequence of connected Bézier splines to the current figure of this path.
;
; pPath Pointer to the GraphicsPath
; Points the coordinates of all the points passed as x1,y1|x2,y2|x3,y3.....
;
; return status enumeration. 0 = success

; Notes The first spline is constructed from the first point through the fourth point in the array and uses the second and third points as control points. Each subsequent spline in the sequence needs exactly three more points: the ending point of the previous spline is used as the starting point, the next two points in the sequence are control points, and the third point is the ending point.

Gdip_AddPathBeziers(pPath, Points) {
StringSplit, Points, Points, |
VarSetCapacity(PointF, 8*Points0)
Loop, %Points0%
{
StringSplit, Coord, Points%A_Index%, `,
NumPut(Coord1, PointF, 8*(A_Index-1), "float"), NumPut(Coord2, PointF, (8*(A_Index-1))+4, "float")
}
return DllCall("gdiplus\GdipAddPathBeziers", "uint", pPath, "uint", &PointF, "int", Points0)
}

Gdip_AddPathBezier(pPath, x1, y1, x2, y2, x3, y3, x4, y4) { ; Adds a Bézier spline to the current figure of this path
return DllCall("gdiplus\GdipAddPathBezier", "uint", pPath
, "float", x1, "float", y1, "float", x2, "float", y2
, "float", x3, "float", y3, "float", x4, "float", y4)
}

; Function Gdip_AddPathLines
; Description Adds a sequence of connected lines to the current figure of this path.
;
; pPath Pointer to the GraphicsPath
; Points the coordinates of all the points passed as x1,y1|x2,y2|x3,y3.....
;
; return status enumeration. 0 = success

Gdip_AddPathLines(pPath, Points) {
StringSplit, Points, Points, |
VarSetCapacity(PointF, 8*Points0)
Loop, %Points0%
{
StringSplit, Coord, Points%A_Index%, `,
NumPut(Coord1, PointF, 8*(A_Index-1), "float"), NumPut(Coord2, PointF, (8*(A_Index-1))+4, "float")
}
return DllCall("gdiplus\GdipAddPathLine2", "uint", pPath, "uint", &PointF, "int", Points0)
}

Gdip_AddPathLine(pPath, x1, y1, x2, y2) {
return DllCall("gdiplus\GdipAddPathLine", "uint", pPath
, "float", x1, "float", y1, "float", x2, "float", y2)
}

Gdip_AddPathArc(pPath, x, y, w, h, StartAngle, SweepAngle) {
return DllCall("gdiplus\GdipAddPathArc", "uint", pPath, "float", x, "float", y, "float", w, "float", h, "float", StartAngle, "float", SweepAngle)
}

Gdip_AddPathPie(pPath, x, y, w, h, StartAngle, SweepAngle) {
return DllCall("gdiplus\GdipAddPathPie", "uint", pPath, "float", x, "float", y, "float", w, "float", h, "float", StartAngle, "float", SweepAngle)
}

Gdip_StartPathFigure(pPath) { ; Starts a new figure without closing the current figure. Subsequent points added to this path are added to the new figure.
return DllCall("gdiplus\GdipStartPathFigure", "uint", pPath)
}

Gdip_ClosePathFigure(pPath) { ; Closes the current figure of this path.
return DllCall("gdiplus\GdipClosePathFigure", "uint", pPath)
}

; Function Gdip_DrawPath
; Description draws a sequence of lines and curves defined by a GraphicsPath object
;
; pGraphics Pointer to the Graphics of a bitmap
; pPen Pointer to a pen
; pPath Pointer to a Path
;
; return status enumeration. 0 = success

Gdip_DrawPath(pGraphics, pPen, pPath) {
return DllCall("gdiplus\GdipDrawPath", "uint", pGraphics, "uint", pPen, "uint", pPath)
}

Gdip_WidenPath(pPath, pPen, Matrix=0, Flatness=1) { ; Replaces this path with curves that enclose the area that is filled when this path is drawn by a specified pen. This method also flattens the path.
return DllCall("gdiplus\GdipWidenPath", "uint", pPath, "uint", pPen, "uint", Matrix, "float", Flatness)
}

Gdip_ClonePath(pPath) {
DllCall("gdiplus\GdipClonePath", "uint", pPath, "uint*", pPathClone)
return pPathClone
}

Screenshot of example
pHgh3.jpg

EDIT 21.09.2012.: added: Gdip_WidenPath, Gdip_AddPathBezier, Gdip_ClonePath, updated example.


My Website • Recommended: AutoHotkey Unicode 32-bit • Join DropBox, Copy


  • Guests
  • Last active:
  • Joined: --
Hi everyone,

I am trying my best to understand, but would really appreciate if someone could explain in simple terms for me.

What i am wanting to do is do an imagesearch of a printscreen

From this thread i see i can probably do it with Gdip.ahk, but i am struggling to work out how to use it.

Very basic idea

Print Screen active window, save as image.png
Search this image with another saved image2.png

Does that make sensee?

Regards

Surreall

Rseding91
  • Members
  • 703 posts
  • Last active: Apr 02 2016 05:05 AM
  • Joined: 07 Jun 2010

http://www.autohotke...ll/Gdip_All.ahk
Good job, but Gdip_SaveBitmapToFile() does not work when you run the script with AutoHotkey_L 64-bit Unicode and try to extract icon from exe.

; Run the script with AutoHotkey_L 64-bit Unicode
FullPath := A_AhkPath
pToken := Gdip_Startup()
pBitmap := Gdip_CreateBitmapFromFile(FullPath)	; (FullPath,1,48) doesn't help
MsgBox % pBitmap								; returns -2 on 64-bit
Gdip_SaveBitmapToFile(pBitmap, A_ScriptDir "\Gdiptest.png")
Gdip_DisposeImage(pBitmap)
Gdip_Shutdown(pToken)
Run, % A_ScriptDir "\Gdiptest.png"
ExitApp

#Include Gdip_All.ahk



It looks like the problem is with the standard gdip library as well: that works with _L but not with basic.

Surreall
  • Members
  • 34 posts
  • Last active: Apr 02 2015 03:50 PM
  • Joined: 07 Oct 2009
Hey all,

I got it working okay on taking screenshots of windows, but when i use it to take a screenshot of a game window it returns a black image, but the window border is showing okay in the image.

Any ideas why i get a black inner?

Regards

Surreall

EDIT: Alt-Prntscreen grabs a pic fine, i am on windows 7 64 bit if that makes a difference

Uberi
  • Moderators
  • 1119 posts
  • Last active: May 02 2015 06:05 PM
  • Joined: 23 Aug 2010
That usually happens if the application uses owner draw and doesn't rely on WM_PAINT to perform painting.

I'm not sure how the Alt+PrintScreen method does it without repainting, but it might be worth looking into that or just sending Alt+PrintScreen to the window.

Surreall
  • Members
  • 34 posts
  • Last active: Apr 02 2015 03:50 PM
  • Joined: 07 Oct 2009

That usually happens if the application uses owner draw and doesn't rely on WM_PAINT to perform painting.

I'm not sure how the Alt+PrintScreen method does it without repainting, but it might be worth looking into that or just sending Alt+PrintScreen to the window.


I tried sending Alt+printscreen, and that also doesnt work. (using controlsend) I get a 1 Kb file lol

Regards

Surreall

GeekDude
  • Spam Officer
  • 391 posts
  • Last active: Oct 05 2015 08:13 PM
  • Joined: 23 Nov 2009
Did you try pasting into paint?

Surreall
  • Members
  • 34 posts
  • Last active: Apr 02 2015 03:50 PM
  • Joined: 07 Oct 2009

Did you try pasting into paint?


Yes, i got a this doesnt support this type of file error

Here is the code


pToken := Gdip_Startup()
pBitmap := Gdip_BitmapFromHWND(WinExist("Game Window")) ; hwnd = name of window, eg pBitmapNotepad := Gdip_BitmapFromHWND(WinExist("Notepad"))

MsgBox % pBitmap                     
Gdip_SaveBitmapToFile(pBitmap, A_ScriptDir "\Gdiptest.png")
Gdip_DisposeImage(pBitmap)
Gdip_Shutdown(pToken)
Run, % A_ScriptDir "\Gdiptest.png"
ExitApp


guest3456
  • Members
  • 1704 posts
  • Last active: Nov 19 2015 11:58 AM
  • Joined: 10 Mar 2011

Hey all,

I got it working okay on taking screenshots of windows, but when i use it to take a screenshot of a game window it returns a black image, but the window border is showing okay in the image.


some games just dont allow you to do it, it sucks

tic
  • Members
  • 1934 posts
  • Last active: Dec 21 2015 01:05 PM
  • Joined: 22 Apr 2007

Here is the code

pBitmap := Gdip_BitmapFromHWND(WinExist("Game Window"))


Don't use Gdip_BitmapFromHWND. That will try and raise WM_PAINT. Use Gdip_BitmapFromScreen

Gdip_BitmapFromScreen("hwnd:" WinExist("Game Window"))

Learning one

Awesome! I'll definitely try and release an update soon