· 5 years ago · Jul 09, 2020, 09:36 PM
1; Gdip_All.ahk - GDI+ library compilation of user contributed GDI+ functions
2; made by Marius Șucan: https://github.com/marius-sucan/AHK-GDIp-Library-Compilation
3; a fork from: https://github.com/mmikeww/AHKv2-Gdip
4; based on https://github.com/tariqporter/Gdip
5; Supports: AHK_L / AHK_H Unicode/ANSI x86/x64 and AHK v2 alpha
6; This file is the AHK v1.1 edition; for AHK v2 compatible edition, please see the repository.
7;
8; NOTES: The drawing of GDI+ Bitmaps is limited to a size
9; of 32767 pixels in either direction (width, height).
10; To calculate the largest bitmap you can create:
11; The maximum object size is 2GB = 2,147,483,648 bytes
12; Default bitmap is 32bpp (4 bytes), the largest area we can have is 2GB / 4 = 536,870,912 bytes
13; If we want a square, the largest we can get is sqrt(2GB/4) = 23,170 pixels
14;
15; Gdip standard library versions:
16; by Marius Șucan - gathered user-contributed functions and implemented hundreds of new functions
17; - v1.84 on 05/06/2020
18; - v1.83 on 24/05/2020
19; - v1.82 on 11/03/2020
20; - v1.81 on 25/02/2020
21; - v1.80 on 11/01/2019
22; - v1.79 on 10/28/2019
23; - v1.78 on 10/27/2019
24; - v1.77 on 10/06/2019
25; - v1.76 on 09/27/2019
26; - v1.75 on 09/23/2019
27; - v1.74 on 09/19/2019
28; - v1.73 on 09/17/2019
29; - v1.72 on 09/16/2019
30; - v1.71 on 09/15/2019
31; - v1.70 on 09/13/2019
32; - v1.69 on 09/12/2019
33; - v1.68 on 09/11/2019
34; - v1.67 on 09/10/2019
35; - v1.66 on 09/09/2019
36; - v1.65 on 09/08/2019
37; - v1.64 on 09/07/2019
38; - v1.63 on 09/06/2019
39; - v1.62 on 09/05/2019
40; - v1.61 on 09/04/2019
41; - v1.60 on 09/03/2019
42; - v1.59 on 09/01/2019
43; - v1.58 on 08/29/2019
44; - v1.57 on 08/23/2019
45; - v1.56 on 08/21/2019
46; - v1.55 on 08/14/2019
47;
48; bug fixes and AHK v2 compatibility by mmikeww and others
49; - v1.54 on 11/15/2017
50; - v1.53 on 06/19/2017
51; - v1.52 on 06/11/2017
52; - v1.51 on 01/27/2017
53; - v1.50 on 11/20/2016
54;
55; - v1.47 on 02/20/2014 [?]
56;
57; modified by Rseding91 using fincs 64 bit compatible
58; - v1.45 on 05/01/2013
59;
60; by tic (Tariq Porter)
61; - v1.45 on 07/09/2011
62; - v1.01 on 31/05/2008
63;
64; Detailed history:
65; - 05/06/2020 = Synchronized with mmikeww's repository and fixed a few bugs
66; - 24/05/2020 = Added a few more functions and fixed or improved already exiting functions
67; - 11/02/2020 = Imported updated MDMF functions from mmikeww, and AHK v2 examples, and other minor changes
68; - 25/02/2020 = Added several new functions, including for color conversions [from Tidbit], improved/fixed several functions
69; - 11/01/2019 = Implemented support for a private font file for Gdip_AddPathStringSimplified()
70; - 10/28/2019 = Added 7 new GDI+ functions and fixes related to Gdip_CreateFontFamilyFromFile()
71; - 10/27/2019 = Added 5 new GDI+ functions and bug fixes for Gdip_TestBitmapUniformity(), Gdip_RotateBitmapAtCenter() and Gdip_ResizeBitmap()
72; - 10/06/2019 = Added more parameters to Gdip_GraphicsFromImage/HDC/HWND and added Gdip_GetPixelColor()
73; - 09/27/2019 = bug fixes...
74; - 09/23/2019 = Added 4 new functions and improved Gdip_CreateBitmap() [ Marius Șucan ]
75; - 09/19/2019 = Added 4 new functions and improved Gdip_RotateBitmapAtCenter() [ Marius Șucan ]
76; - 09/17/2019 = Added 6 new GDI+ functions and renamed curve related functions [ Marius Șucan ]
77; - 09/16/2019 = Added 10 new GDI+ functions [ Marius Șucan ]
78; - 09/15/2019 = Added 3 new GDI+ functions and improved Gdip_DrawStringAlongPolygon() [ Marius Șucan ]
79; - 09/13/2019 = Added 10 new GDI+ functions [ Marius Șucan ]
80; - 09/12/2019 = Added 6 new GDI+ functions [ Marius Șucan ]
81; - 09/11/2019 = Added 10 new GDI+ functions [ Marius Șucan ]
82; - 09/10/2019 = Added 17 new GDI+ functions [ Marius Șucan ]
83; - 09/09/2019 = Added 14 new GDI+ functions [ Marius Șucan ]
84; - 09/08/2019 = Added 3 new functions and fixed Gdip_SetPenDashArray() [ Marius Șucan ]
85; - 09/07/2019 = Added 12 new functions [ Marius Șucan ]
86; - 09/06/2019 = Added 14 new GDI+ functions [ Marius Șucan ]
87; - 09/05/2019 = Added 27 new GDI+ functions [ Marius Șucan ]
88; - 09/04/2019 = Added 36 new GDI+ functions [ Marius Șucan ]
89; - 09/03/2019 = Added about 37 new GDI+ functions [ Marius Șucan ]
90; - 08/29/2019 = Fixed Gdip_GetPropertyTagName() [on AHK v2], Gdip_GetPenColor() and Gdip_GetSolidFillColor(), added Gdip_LoadImageFromFile()
91; - 08/23/2019 = Added Gdip_FillRoundedRectangle2() and Gdip_DrawRoundedRectangle2(); extracted from Gdip2 by Tariq [tic] and corrected functions names
92; - 08/21/2019 = Added GenerateColorMatrix() by Marius Șucan
93; - 08/19/2019 = Added 12 functions. Extracted from a class wrapper for GDI+ written by nnnik in 2017.
94; - 08/18/2019 = Added Gdip_AddPathRectangle() and eight PathGradient related functions by JustMe
95; - 08/16/2019 = Added Gdip_DrawImageFX(), Gdip_CreateEffect() and other related functions [ Marius Șucan ]
96; - 08/15/2019 = Added Gdip_DrawRoundedLine() by DevX and Rabiator
97; - 08/15/2019 = Added 11 GraphicsPath related functions by "Learning one" and updated by Marius Șucan
98; - 08/14/2019 = Added Gdip_IsVisiblePathPoint() and RotateAtCenter() by RazorHalo
99; - 08/08/2019 = Added Gdi_GetDIBits() and Gdi_CreateDIBitmap() by Marius Șucan
100; - 07/19/2019 = Added Gdip_GetHistogram() by swagfag and GetProperty GDI+ functions by JustMe
101; - 11/15/2017 = compatibility with both AHK v2 and v1, restored by nnnik
102; - 06/19/2017 = Fixed few bugs from old syntax by Bartlomiej Uliasz
103; - 06/11/2017 = made code compatible with new AHK v2.0-a079-be5df98 by Bartlomiej Uliasz
104; - 01/27/2017 = fixed some bugs and made #Warn All compatible by Bartlomiej Uliasz
105; - 11/20/2016 = fixed Gdip_BitmapFromBRA() by 'just me'
106; - 11/18/2016 = backward compatible support for both AHK v1.1 and AHK v2
107; - 11/15/2016 = initial AHK v2 support by guest3456
108; - 02/20/2014 = fixed Gdip_CreateRegion() and Gdip_GetClipRegion() on AHK Unicode x86
109; - 05/13/2013 = fixed Gdip_SetBitmapToClipboard() on AHK Unicode x64
110; - 07/09/2011 = v1.45 release by tic (Tariq Porter)
111; - 31/05/2008 = v1.01 release by tic (Tariq Porter)
112;
113;#####################################################################################
114; STATUS ENUMERATION
115; Return values for functions specified to have status enumerated return type
116;#####################################################################################
117;
118; Ok = = 0
119; GenericError = 1
120; InvalidParameter = 2
121; OutOfMemory = 3
122; ObjectBusy = 4
123; InsufficientBuffer = 5
124; NotImplemented = 6
125; Win32Error = 7
126; WrongState = 8
127; Aborted = 9
128; FileNotFound = 10
129; ValueOverflow = 11
130; AccessDenied = 12
131; UnknownImageFormat = 13
132; FontFamilyNotFound = 14
133; FontStyleNotFound = 15
134; NotTrueTypeFont = 16
135; UnsupportedGdiplusVersion= 17
136; GdiplusNotInitialized = 18
137; PropertyNotFound = 19
138; PropertyNotSupported = 20
139; ProfileNotFound = 21
140;
141;#####################################################################################
142; FUNCTIONS LIST
143; See functions-list.txt file.
144;#####################################################################################
145
146; Function: UpdateLayeredWindow
147; Description: Updates a layered window with the handle to the DC of a gdi bitmap
148;
149; hwnd Handle of the layered window to update
150; hdc Handle to the DC of the GDI bitmap to update the window with
151; x, y x, y coordinates to place the window
152; w, h Width and height of the window
153; Alpha Default = 255 : The transparency (0-255) to set the window transparency
154;
155; return If the function succeeds, the return value is nonzero
156;
157; notes If x or y are omitted, the layered window will use its current coordinates
158; If w or h are omitted, the current width and height will be used
159
160UpdateLayeredWindow(hwnd, hdc, x:="", y:="", w:="", h:="", Alpha:=255) {
161 Ptr := "UPtr"
162 if ((x != "") && (y != ""))
163 VarSetCapacity(pt, 8), NumPut(x, pt, 0, "UInt"), NumPut(y, pt, 4, "UInt")
164
165 if (w = "") || (h = "")
166 GetWindowRect(hwnd, W, H)
167
168 return DllCall("UpdateLayeredWindow"
169 , Ptr, hwnd
170 , Ptr, 0
171 , Ptr, ((x = "") && (y = "")) ? 0 : &pt
172 , "int64*", w|h<<32
173 , Ptr, hdc
174 , "int64*", 0
175 , "uint", 0
176 , "UInt*", Alpha<<16|1<<24
177 , "uint", 2)
178}
179
180;#####################################################################################
181
182; Function BitBlt
183; Description The BitBlt function performs a bit-block transfer of the color data corresponding to a rectangle
184; of pixels from the specified source device context into a destination device context.
185;
186; dDC handle to destination DC
187; dX, dY x, y coordinates of the destination upper-left corner
188; dW, dH width and height of the area to copy
189; sDC handle to source DC
190; sX, sY x, y coordinates of the source upper-left corner
191; Raster raster operation code
192;
193; return If the function succeeds, the return value is nonzero
194;
195; notes If no raster operation is specified, then SRCCOPY is used, which copies the source directly to the destination rectangle
196;
197; Raster operation codes:
198; BLACKNESS = 0x00000042
199; NOTSRCERASE = 0x001100A6
200; NOTSRCCOPY = 0x00330008
201; SRCERASE = 0x00440328
202; DSTINVERT = 0x00550009
203; PATINVERT = 0x005A0049
204; SRCINVERT = 0x00660046
205; SRCAND = 0x008800C6
206; MERGEPAINT = 0x00BB0226
207; MERGECOPY = 0x00C000CA
208; SRCCOPY = 0x00CC0020
209; SRCPAINT = 0x00EE0086
210; PATCOPY = 0x00F00021
211; PATPAINT = 0x00FB0A09
212; WHITENESS = 0x00FF0062
213; CAPTUREBLT = 0x40000000
214; NOMIRRORBITMAP = 0x80000000
215
216BitBlt(ddc, dx, dy, dw, dh, sdc, sx, sy, raster:="") {
217; This function works only with GDI hBitmaps that
218; are Device-Dependent Bitmaps [DDB].
219
220 Ptr := "UPtr"
221 return DllCall("gdi32\BitBlt"
222 , Ptr, dDC
223 , "int", dX, "int", dY
224 , "int", dW, "int", dH
225 , Ptr, sDC
226 , "int", sX, "int", sY
227 , "uint", Raster ? Raster : 0x00CC0020)
228}
229
230;#####################################################################################
231
232; Function StretchBlt
233; Description The StretchBlt function copies a bitmap from a source rectangle into a destination rectangle,
234; stretching or compressing the bitmap to fit the dimensions of the destination rectangle, if necessary.
235; The system stretches or compresses the bitmap according to the stretching mode currently set in the destination device context.
236;
237; ddc handle to destination DC
238; dX, dY x, y coordinates of the destination upper-left corner
239; dW, dH width and height of the destination rectangle
240; sdc handle to source DC
241; sX, sY x, y coordinates of the source upper-left corner
242; sW, sH width and height of the source rectangle
243; Raster raster operation code
244;
245; return If the function succeeds, the return value is nonzero
246;
247; notes If no raster operation is specified, then SRCCOPY is used. It uses the same raster operations as BitBlt
248
249StretchBlt(ddc, dx, dy, dw, dh, sdc, sx, sy, sw, sh, Raster:="") {
250 Ptr := "UPtr"
251
252 return DllCall("gdi32\StretchBlt"
253 , Ptr, ddc
254 , "int", dX, "int", dY
255 , "int", dW, "int", dH
256 , Ptr, sdc
257 , "int", sX, "int", sY
258 , "int", sW, "int", sH
259 , "uint", Raster ? Raster : 0x00CC0020)
260}
261
262;#####################################################################################
263
264; Function SetStretchBltMode
265; Description The SetStretchBltMode function sets the bitmap stretching mode in the specified device context
266;
267; hdc handle to the DC
268; iStretchMode The stretching mode, describing how the target will be stretched
269;
270; return If the function succeeds, the return value is the previous stretching mode. If it fails it will return 0
271;
272
273SetStretchBltMode(hdc, iStretchMode:=4) {
274; iStretchMode options:
275; BLACKONWHITE = 1
276; COLORONCOLOR = 3
277; HALFTONE = 4
278; WHITEONBLACK = 2
279; STRETCH_ANDSCANS = BLACKONWHITE
280; STRETCH_DELETESCANS = COLORONCOLOR
281; STRETCH_HALFTONE = HALFTONE
282; STRETCH_ORSCANS = WHITEONBLACK
283
284 return DllCall("gdi32\SetStretchBltMode"
285 , "UPtr", hdc
286 , "int", iStretchMode)
287}
288
289;#####################################################################################
290
291; Function SetImage
292; Description Associates a new image with a static control
293;
294; hwnd handle of the control to update
295; hBitmap a gdi bitmap to associate the static control with
296;
297; return If the function succeeds, the return value is nonzero
298
299SetImage(hwnd, hBitmap) {
300; STM_SETIMAGE = 0x172
301; Example: Gui, Add, Text, 0xE w500 h300 hwndhPic ; SS_Bitmap = 0xE
302
303 Ptr := "UPtr"
304 E := DllCall("SendMessage", Ptr, hwnd, "UInt", 0x172, "UInt", 0x0, Ptr, hBitmap )
305 DeleteObject(E)
306 return E
307}
308
309;#####################################################################################
310
311; Function SetSysColorToControl
312; Description Sets a solid colour to a control
313;
314; hwnd handle of the control to update
315; SysColor A system colour to set to the control
316;
317; return If the function succeeds, the return value is zero
318;
319; notes A control must have the 0xE style set to it so it is recognised as a bitmap
320; By default SysColor=15 is used which is COLOR_3DFACE. This is the standard background for a control
321
322SetSysColorToControl(hwnd, SysColor:=15) {
323; SysColor options:
324; 3DDKSHADOW = 21
325; 3DFACE = 15
326; 3DHIGHLIGHT = 20
327; 3DHILIGHT = 20
328; 3DLIGHT = 22
329; 3DSHADOW = 16
330; ACTIVEBORDER = 10
331; ACTIVECAPTION = 2
332; APPWORKSPACE = 12
333; BACKGROUND = 1
334; BTNFACE = 15
335; BTNHIGHLIGHT = 20
336; BTNHILIGHT = 20
337; BTNSHADOW = 16
338; BTNTEXT = 18
339; CAPTIONTEXT = 9
340; DESKTOP = 1
341; GRADIENTACTIVECAPTION 27
342; GRADIENTINACTIVECAPTION = 28
343; GRAYTEXT = 17
344; HIGHLIGHT = 13
345; HIGHLIGHTTEXT = 14
346; HOTLIGHT = 26
347; INACTIVEBORDER = 11
348; INACTIVECAPTION = 3
349; INACTIVECAPTIONTEXT = 19
350; INFOBK = 24
351; INFOTEXT = 23
352; MENU = 4
353; MENUHILIGHT = 29
354; MENUBAR = 30
355; MENUTEXT = 7
356; SCROLLBAR = 0
357; WINDOW = 5
358; WINDOWFRAME = 6
359; WINDOWTEXT = 8
360 Ptr := "UPtr"
361 GetWindowRect(hwnd, W, H)
362 bc := DllCall("GetSysColor", "Int", SysColor, "UInt")
363 pBrushClear := Gdip_BrushCreateSolid(0xff000000 | (bc >> 16 | bc & 0xff00 | (bc & 0xff) << 16))
364 pBitmap := Gdip_CreateBitmap(w, h)
365 G := Gdip_GraphicsFromImage(pBitmap)
366 Gdip_FillRectangle(G, pBrushClear, 0, 0, w, h)
367 hBitmap := Gdip_CreateHBITMAPFromBitmap(pBitmap)
368 SetImage(hwnd, hBitmap)
369 Gdip_DeleteBrush(pBrushClear)
370 Gdip_DeleteGraphics(G)
371 Gdip_DisposeImage(pBitmap)
372 DeleteObject(hBitmap)
373 return 0
374}
375
376;#####################################################################################
377
378; Function Gdip_BitmapFromScreen
379; Description Gets a gdi+ bitmap from the screen
380;
381; Screen 0 = All screens
382; Any numerical value = Just that screen
383; x|y|w|h = Take specific coordinates with a width and height
384; Raster raster operation code
385;
386; return If the function succeeds, the return value is a pointer to a gdi+ bitmap
387; -1: one or more of x,y,w,h parameters were not passed properly
388;
389; notes If no raster operation is specified, then SRCCOPY is used to the returned bitmap
390
391Gdip_BitmapFromScreen(Screen:=0, Raster:="") {
392 hhdc := 0
393 Ptr := "UPtr"
394 if (Screen = 0)
395 {
396 _x := DllCall("GetSystemMetrics", "Int", 76 )
397 _y := DllCall("GetSystemMetrics", "Int", 77 )
398 _w := DllCall("GetSystemMetrics", "Int", 78 )
399 _h := DllCall("GetSystemMetrics", "Int", 79 )
400 } else if (SubStr(Screen, 1, 5) = "hwnd:")
401 {
402 hwnd := SubStr(Screen, 6)
403 if !WinExist("ahk_id " hwnd)
404 return -2
405
406 GetWindowRect(hwnd, _w, _h)
407 _x := _y := 0
408 hhdc := GetDCEx(hwnd, 3)
409 } else if IsInteger(Screen)
410 {
411 M := GetMonitorInfo(Screen)
412 _x := M.Left, _y := M.Top, _w := M.Right-M.Left, _h := M.Bottom-M.Top
413 } else
414 {
415 S := StrSplit(Screen, "|")
416 _x := S[1], _y := S[2], _w := S[3], _h := S[4]
417 }
418
419 if (_x = "") || (_y = "") || (_w = "") || (_h = "")
420 return -1
421
422 chdc := CreateCompatibleDC(), hbm := CreateDIBSection(_w, _h, chdc)
423 obm := SelectObject(chdc, hbm), hhdc := hhdc ? hhdc : GetDC()
424 BitBlt(chdc, 0, 0, _w, _h, hhdc, _x, _y, Raster)
425 ReleaseDC(hhdc)
426
427 pBitmap := Gdip_CreateBitmapFromHBITMAP(hbm)
428 SelectObject(chdc, obm), DeleteObject(hbm), DeleteDC(hhdc), DeleteDC(chdc)
429 return pBitmap
430}
431
432;#####################################################################################
433
434; Function Gdip_BitmapFromHWND
435; Description Uses PrintWindow to get a handle to the specified window and return a bitmap from it
436;
437; hwnd handle to the window to get a bitmap from
438; clientOnly capture only the client area of the window, without title bar and border
439;
440; return If the function succeeds, the return value is a pointer to a gdi+ bitmap
441
442Gdip_BitmapFromHWND(hwnd, clientOnly:=0) {
443 ; Restore the window if minimized! Must be visible for capture.
444 if DllCall("IsIconic", "ptr", hwnd)
445 DllCall("ShowWindow", "ptr", hwnd, "int", 4)
446
447 Ptr := "UPtr"
448 thisFlag := 0
449 If (clientOnly=1)
450 {
451 VarSetCapacity(rc, 16, 0)
452 DllCall("GetClientRect", "ptr", hwnd, "ptr", &rc)
453 Width := NumGet(rc, 8, "int")
454 Height := NumGet(rc, 12, "int")
455 thisFlag := 1
456 } Else GetWindowRect(hwnd, Width, Height)
457
458 hbm := CreateDIBSection(Width, Height)
459 hdc := CreateCompatibleDC(), obm := SelectObject(hdc, hbm)
460 PrintWindow(hwnd, hdc, 2 + thisFlag)
461 pBitmap := Gdip_CreateBitmapFromHBITMAP(hbm)
462 SelectObject(hdc, obm), DeleteObject(hbm), DeleteDC(hdc)
463 return pBitmap
464}
465
466;#####################################################################################
467
468; Function CreateRectF
469; Description Creates a RectF object, containing a the coordinates and dimensions of a rectangle
470;
471; RectF Name to call the RectF object
472; x, y x, y coordinates of the upper left corner of the rectangle
473; w, h Width and height of the rectangle
474;
475; return No return value
476
477CreateRectF(ByRef RectF, x, y, w, h) {
478 VarSetCapacity(RectF, 16)
479 NumPut(x, RectF, 0, "float"), NumPut(y, RectF, 4, "float")
480 NumPut(w, RectF, 8, "float"), NumPut(h, RectF, 12, "float")
481}
482
483;#####################################################################################
484
485; Function CreateRect
486; Description Creates a Rect object, containing a the coordinates and dimensions of a rectangle
487;
488; Rect Name to call the Rect object
489; x, y x, y coordinates of the upper left corner of the rectangle
490; x2, y2 x, y coordinates of the bottom right corner of the rectangle
491
492; return No return value
493
494CreateRect(ByRef Rect, x, y, x2, y2) {
495; modified by Marius Șucan according to dangerdogL2121
496; found on https://autohotkey.com/board/topic/29449-gdi-standard-library-145-by-tic/page-93
497
498 VarSetCapacity(Rect, 16)
499 NumPut(x, Rect, 0, "uint"), NumPut(y, Rect, 4, "uint")
500 NumPut(x2, Rect, 8, "uint"), NumPut(y2, Rect, 12, "uint")
501}
502;#####################################################################################
503
504; Function CreateSizeF
505; Description Creates a SizeF object, containing an 2 values
506;
507; SizeF Name to call the SizeF object
508; w, h width and height values for the SizeF object
509;
510; return No Return value
511
512CreateSizeF(ByRef SizeF, w, h) {
513 VarSetCapacity(SizeF, 8)
514 NumPut(w, SizeF, 0, "float")
515 NumPut(h, SizeF, 4, "float")
516}
517
518;#####################################################################################
519
520; Function CreatePointF
521; Description Creates a SizeF object, containing two values
522;
523; SizeF Name to call the SizeF object
524; x, y x, y values for the SizeF object
525;
526; return No Return value
527
528CreatePointF(ByRef PointF, x, y) {
529 VarSetCapacity(PointF, 8)
530 NumPut(x, PointF, 0, "float")
531 NumPut(y, PointF, 4, "float")
532}
533
534CreatePointsF(ByRef PointsF, inPoints) {
535 Points := StrSplit(inPoints, "|")
536 PointsCount := Points.Length()
537 VarSetCapacity(PointsF, 8 * PointsCount, 0)
538 for eachPoint, Point in Points
539 {
540 Coord := StrSplit(Point, ",")
541 NumPut(Coord[1], &PointsF, 8*(A_Index-1), "float")
542 NumPut(Coord[2], &PointsF, (8*(A_Index-1))+4, "float")
543 }
544 Return PointsCount
545}
546
547;#####################################################################################
548
549; Function CreateDIBSection
550; Description The CreateDIBSection function creates a DIB (Device Independent Bitmap) that applications can write to directly
551;
552; w, h width and height of the bitmap to create
553; hdc a handle to the device context to use the palette from
554; bpp bits per pixel (32 = ARGB)
555; ppvBits A pointer to a variable that receives a pointer to the location of the DIB bit values
556;
557; return returns a DIB. A gdi bitmap
558;
559; notes ppvBits will receive the location of the pixels in the DIB
560
561CreateDIBSection(w, h, hdc:="", bpp:=32, ByRef ppvBits:=0, Usage:=0, hSection:=0, Offset:=0) {
562; A GDI function that creates a new hBitmap,
563; a device-independent bitmap [DIB].
564; A DIB consists of two distinct parts:
565; a BITMAPINFO structure describing the dimensions
566; and colors of the bitmap, and an array of bytes
567; defining the pixels of the bitmap.
568
569 Ptr := "UPtr"
570 hdc2 := hdc ? hdc : GetDC()
571 VarSetCapacity(bi, 40, 0)
572 NumPut(40, bi, 0, "uint")
573 NumPut(w, bi, 4, "uint")
574 NumPut(h, bi, 8, "uint")
575 NumPut(1, bi, 12, "ushort")
576 NumPut(bpp, bi, 14, "ushort")
577 NumPut(0, bi, 16, "uInt")
578
579 hbm := DllCall("CreateDIBSection"
580 , Ptr, hdc2
581 , Ptr, &bi ; BITMAPINFO
582 , "uint", Usage
583 , "UPtr*", ppvBits
584 , Ptr, hSection
585 , "uint", OffSet, Ptr)
586
587 if !hdc
588 ReleaseDC(hdc2)
589 return hbm
590}
591
592;#####################################################################################
593
594; Function PrintWindow
595; Description The PrintWindow function copies a visual window into the specified device context (DC), typically a printer DC
596;
597; hwnd A handle to the window that will be copied
598; hdc A handle to the device context
599; Flags Drawing options
600;
601; return If the function succeeds, it returns a nonzero value
602;
603; PW_CLIENTONLY = 1
604
605PrintWindow(hwnd, hdc, Flags:=2) {
606; set Flags to 2, to capture hardware accelerated windows
607; this only applies on Windows 8.1 and later versions.
608
609 Ptr := "UPtr"
610 return DllCall("PrintWindow", Ptr, hwnd, Ptr, hdc, "uint", Flags)
611}
612
613;#####################################################################################
614
615; Function DestroyIcon
616; Description Destroys an icon and frees any memory the icon occupied
617;
618; hIcon Handle to the icon to be destroyed. The icon must not be in use
619;
620; return If the function succeeds, the return value is nonzero
621
622DestroyIcon(hIcon) {
623 return DllCall("DestroyIcon", "UPtr", hIcon)
624}
625
626;#####################################################################################
627
628; Function: GetIconDimensions
629; Description: Retrieves a given icon/cursor's width and height
630;
631; hIcon Pointer to an icon or cursor
632; Width, Height ByRef variables. These variables are set to the icon's width and height
633;
634; return If the function succeeds, the return value is zero, otherwise:
635; -1 = Could not retrieve the icon's info. Check A_LastError for extended information
636; -2 = Could not delete the icon's bitmask bitmap
637; -3 = Could not delete the icon's color bitmap
638
639GetIconDimensions(hIcon, ByRef Width, ByRef Height) {
640 Ptr := "UPtr"
641 Width := Height := 0
642
643 VarSetCapacity(ICONINFO, size := 16 + 2 * A_PtrSize, 0)
644 if !DllCall("user32\GetIconInfo", Ptr, hIcon, Ptr, &ICONINFO)
645 return -1
646
647 hbmMask := NumGet(&ICONINFO, 16, Ptr)
648 hbmColor := NumGet(&ICONINFO, 16 + A_PtrSize, Ptr)
649 VarSetCapacity(BITMAP, size, 0)
650
651 if DllCall("gdi32\GetObject", Ptr, hbmColor, "Int", size, Ptr, &BITMAP)
652 {
653 Width := NumGet(&BITMAP, 4, "Int")
654 Height := NumGet(&BITMAP, 8, "Int")
655 }
656
657 if !DeleteObject(hbmMask)
658 return -2
659
660 if !DeleteObject(hbmColor)
661 return -3
662
663 return 0
664}
665
666PaintDesktop(hdc) {
667 return DllCall("PaintDesktop", "UPtr", hdc)
668}
669
670;#####################################################################################
671
672; Function CreateCompatibleDC
673; Description This function creates a memory device context (DC) compatible with the specified device
674;
675; hdc Handle to an existing device context
676;
677; return returns the handle to a device context or 0 on failure
678;
679; notes If this handle is 0 (by default), the function creates a memory device context compatible with the application's current screen
680
681CreateCompatibleDC(hdc:=0) {
682 return DllCall("CreateCompatibleDC", "UPtr", hdc)
683}
684
685;#####################################################################################
686
687; Function SelectObject
688; Description The SelectObject function selects an object into the specified device context (DC). The new object replaces the previous object of the same type
689;
690; hdc Handle to a DC
691; hgdiobj A handle to the object to be selected into the DC
692;
693; return If the selected object is not a region and the function succeeds, the return value is a handle to the object being replaced
694;
695; notes The specified object must have been created by using one of the following functions
696; Bitmap - CreateBitmap, CreateBitmapIndirect, CreateCompatibleBitmap, CreateDIBitmap, CreateDIBSection (A single bitmap cannot be selected into more than one DC at the same time)
697; Brush - CreateBrushIndirect, CreateDIBPatternBrush, CreateDIBPatternBrushPt, CreateHatchBrush, CreatePatternBrush, CreateSolidBrush
698; Font - CreateFont, CreateFontIndirect
699; Pen - CreatePen, CreatePenIndirect
700; Region - CombineRgn, CreateEllipticRgn, CreateEllipticRgnIndirect, CreatePolygonRgn, CreateRectRgn, CreateRectRgnIndirect
701;
702; notes If the selected object is a region and the function succeeds, the return value is one of the following value
703;
704; SIMPLEREGION = 2 Region consists of a single rectangle
705; COMPLEXREGION = 3 Region consists of more than one rectangle
706; NULLREGION = 1 Region is empty
707
708SelectObject(hdc, hgdiobj) {
709 Ptr := "UPtr"
710 return DllCall("SelectObject", Ptr, hdc, Ptr, hgdiobj)
711}
712
713;#####################################################################################
714
715; Function DeleteObject
716; Description This function deletes a logical pen, brush, font, bitmap, region, or palette, freeing all system resources associated with the object
717; After the object is deleted, the specified handle is no longer valid
718;
719; hObject Handle to a logical pen, brush, font, bitmap, region, or palette to delete
720;
721; return Nonzero indicates success. Zero indicates that the specified handle is not valid or that the handle is currently selected into a device context
722
723DeleteObject(hObject) {
724 return DllCall("DeleteObject", "UPtr", hObject)
725}
726
727;#####################################################################################
728
729; Function GetDC
730; Description This function retrieves a handle to a display device context (DC) for the client area of the specified window.
731; The display device context can be used in subsequent graphics display interface (GDI) functions to draw in the client area of the window.
732;
733; hwnd Handle to the window whose device context is to be retrieved. If this value is NULL, GetDC retrieves the device context for the entire screen
734;
735; return The handle the device context for the specified window's client area indicates success. NULL indicates failure
736
737GetDC(hwnd:=0) {
738 return DllCall("GetDC", "UPtr", hwnd)
739}
740
741GetDCEx(hwnd, flags:=0, hrgnClip:=0) {
742; Device Context extended flags:
743; DCX_CACHE = 0x2
744; DCX_CLIPCHILDREN = 0x8
745; DCX_CLIPSIBLINGS = 0x10
746; DCX_EXCLUDERGN = 0x40
747; DCX_EXCLUDEUPDATE = 0x100
748; DCX_INTERSECTRGN = 0x80
749; DCX_INTERSECTUPDATE = 0x200
750; DCX_LOCKWINDOWUPDATE = 0x400
751; DCX_NORECOMPUTE = 0x100000
752; DCX_NORESETATTRS = 0x4
753; DCX_PARENTCLIP = 0x20
754; DCX_VALIDATE = 0x200000
755; DCX_WINDOW = 0x1
756
757 Ptr := "UPtr"
758 return DllCall("GetDCEx", Ptr, hwnd, Ptr, hrgnClip, "int", flags)
759}
760
761;#####################################################################################
762
763; Function ReleaseDC
764; Description This function releases a device context (DC), freeing it for use by other applications. The effect of ReleaseDC depends on the type of device context
765;
766; hdc Handle to the device context to be released
767; hwnd Handle to the window whose device context is to be released
768;
769; return 1 = released
770; 0 = not released
771;
772; notes The application must call the ReleaseDC function for each call to the GetWindowDC function and for each call to the GetDC function that retrieves a common device context
773; An application cannot use the ReleaseDC function to release a device context that was created by calling the CreateDC function; instead, it must use the DeleteDC function.
774
775ReleaseDC(hdc, hwnd:=0) {
776 Ptr := "UPtr"
777 return DllCall("ReleaseDC", Ptr, hwnd, Ptr, hdc)
778}
779
780;#####################################################################################
781
782; Function DeleteDC
783; Description The DeleteDC function deletes the specified device context (DC)
784;
785; hdc A handle to the device context
786;
787; return If the function succeeds, the return value is nonzero
788;
789; notes An application must not delete a DC whose handle was obtained by calling the GetDC function. Instead, it must call the ReleaseDC function to free the DC
790
791DeleteDC(hdc) {
792 return DllCall("DeleteDC", "UPtr", hdc)
793}
794
795;#####################################################################################
796
797; Function Gdip_LibraryVersion
798; Description Get the current library version
799;
800; return the library version
801;
802; notes This is useful for non compiled programs to ensure that a person doesn't run an old version when testing your scripts
803
804Gdip_LibraryVersion() {
805 return 1.45
806}
807
808;#####################################################################################
809
810; Function Gdip_LibrarySubVersion
811; Description Get the current library sub version
812;
813; return the library sub version
814;
815; notes This is the sub-version currently maintained by Rseding91
816; Updated by guest3456 preliminary AHK v2 support
817; Updated by Marius Șucan reflecting the work on Gdip_all extended compilation
818
819Gdip_LibrarySubVersion() {
820 return 1.84
821}
822
823;#####################################################################################
824
825; Function: Gdip_BitmapFromBRA
826; Description: Gets a pointer to a gdi+ bitmap from a BRA file
827;
828; BRAFromMemIn The variable for a BRA file read to memory
829; File The name of the file, or its number that you would like (This depends on alternate parameter)
830; Alternate Changes whether the File parameter is the file name or its number
831;
832; return If the function succeeds, the return value is a pointer to a gdi+ bitmap
833; -1 = The BRA variable is empty
834; -2 = The BRA has an incorrect header
835; -3 = The BRA has information missing
836; -4 = Could not find file inside the BRA
837
838Gdip_BitmapFromBRA(ByRef BRAFromMemIn, File, Alternate := 0) {
839 pBitmap := 0
840 pStream := 0
841
842 If !(BRAFromMemIn)
843 Return -1
844 Headers := StrSplit(StrGet(&BRAFromMemIn, 256, "CP0"), "`n")
845 Header := StrSplit(Headers.1, "|")
846 If (Header.Length() != 4) || (Header.2 != "BRA!")
847 Return -2
848 _Info := StrSplit(Headers.2, "|")
849 If (_Info.Length() != 3)
850 Return -3
851 OffsetTOC := StrPut(Headers.1, "CP0") + StrPut(Headers.2, "CP0") ; + 2
852 OffsetData := _Info.2
853 SearchIndex := Alternate ? 1 : 2
854 TOC := StrGet(&BRAFromMemIn + OffsetTOC, OffsetData - OffsetTOC - 1, "CP0")
855 RX1 := A_AhkVersion < "2" ? "mi`nO)^" : "mi`n)^"
856 Offset := Size := 0
857 If RegExMatch(TOC, RX1 . (Alternate ? File "\|.+?" : "\d+\|" . File) . "\|(\d+)\|(\d+)$", FileInfo) {
858 Offset := OffsetData + FileInfo.1
859 Size := FileInfo.2
860 }
861 If (Size=0)
862 Return -4
863 hData := DllCall("GlobalAlloc", "UInt", 2, "UInt", Size, "UPtr")
864 pData := DllCall("GlobalLock", "Ptr", hData, "UPtr")
865 DllCall("RtlMoveMemory", "Ptr", pData, "Ptr", &BRAFromMemIn + Offset, "Ptr", Size)
866 DllCall("GlobalUnlock", "Ptr", hData)
867 DllCall("Ole32.dll\CreateStreamOnHGlobal", "Ptr", hData, "Int", 1, "PtrP", pStream)
868 DllCall("gdiplus\GdipCreateBitmapFromStream", "Ptr", pStream, "PtrP", pBitmap)
869 ObjRelease(pStream)
870 Return pBitmap
871}
872
873;#####################################################################################
874
875; Function: Gdip_BitmapFromBase64
876; Description: Creates a bitmap from a Base64 encoded string
877;
878; Base64 ByRef variable. Base64 encoded string. Immutable, ByRef to avoid performance overhead of passing long strings.
879;
880; return If the function succeeds, the return value is a pointer to a bitmap, otherwise:
881; -1 = Could not calculate the length of the required buffer
882; -2 = Could not decode the Base64 encoded string
883; -3 = Could not create a memory stream
884
885Gdip_BitmapFromBase64(ByRef Base64) {
886 Ptr := "UPtr"
887 pBitmap := 0
888 DecLen := 0
889
890 ; calculate the length of the buffer needed
891 if !(DllCall("crypt32\CryptStringToBinary", Ptr, &Base64, "UInt", 0, "UInt", 0x01, Ptr, 0, "UIntP", DecLen, Ptr, 0, Ptr, 0))
892 return -1
893
894 VarSetCapacity(Dec, DecLen, 0)
895
896 ; decode the Base64 encoded string
897 if !(DllCall("crypt32\CryptStringToBinary", Ptr, &Base64, "UInt", 0, "UInt", 0x01, Ptr, &Dec, "UIntP", DecLen, Ptr, 0, Ptr, 0))
898 return -2
899
900 ; create a memory stream
901 if !(pStream := DllCall("shlwapi\SHCreateMemStream", Ptr, &Dec, "UInt", DecLen, "UPtr"))
902 return -3
903
904 DllCall("gdiplus\GdipCreateBitmapFromStreamICM", Ptr, pStream, "PtrP", pBitmap)
905 ObjRelease(pStream)
906
907 return pBitmap
908}
909
910;#####################################################################################
911
912; Function Gdip_DrawRectangle
913; Description This function uses a pen to draw the outline of a rectangle into the Graphics of a bitmap
914;
915; pGraphics Pointer to the Graphics of a bitmap
916; pPen Pointer to a pen
917; x, y x, y coordinates of the top left of the rectangle
918; w, h width and height of the rectangle
919;
920; return status enumeration. 0 = success
921;
922; notes as all coordinates are taken from the top left of each pixel, then the entire width/height should be specified as subtracting the pen width
923
924Gdip_DrawRectangle(pGraphics, pPen, x, y, w, h) {
925 Ptr := "UPtr"
926 return DllCall("gdiplus\GdipDrawRectangle", Ptr, pGraphics, Ptr, pPen, "float", x, "float", y, "float", w, "float", h)
927}
928
929;#####################################################################################
930
931; Function Gdip_DrawRoundedRectangle
932; Description This function uses a pen to draw the outline of a rounded rectangle into the Graphics of a bitmap
933;
934; pGraphics Pointer to the Graphics of a bitmap
935; pPen Pointer to a pen
936; x, y x, y coordinates of the top left of the rounded rectangle
937; w, h width and height of the rectanlge
938; r radius of the rounded corners
939;
940; return status enumeration. 0 = success
941;
942; notes as all coordinates are taken from the top left of each pixel, then the entire width/height should be specified as subtracting the pen width
943
944Gdip_DrawRoundedRectangle(pGraphics, pPen, x, y, w, h, r) {
945 Gdip_SetClipRect(pGraphics, x-r, y-r, 2*r, 2*r, 4)
946 Gdip_SetClipRect(pGraphics, x+w-r, y-r, 2*r, 2*r, 4)
947 Gdip_SetClipRect(pGraphics, x-r, y+h-r, 2*r, 2*r, 4)
948 Gdip_SetClipRect(pGraphics, x+w-r, y+h-r, 2*r, 2*r, 4)
949 _E := Gdip_DrawRectangle(pGraphics, pPen, x, y, w, h)
950 Gdip_ResetClip(pGraphics)
951 Gdip_SetClipRect(pGraphics, x-(2*r), y+r, w+(4*r), h-(2*r), 4)
952 Gdip_SetClipRect(pGraphics, x+r, y-(2*r), w-(2*r), h+(4*r), 4)
953 Gdip_DrawEllipse(pGraphics, pPen, x, y, 2*r, 2*r)
954 Gdip_DrawEllipse(pGraphics, pPen, x+w-(2*r), y, 2*r, 2*r)
955 Gdip_DrawEllipse(pGraphics, pPen, x, y+h-(2*r), 2*r, 2*r)
956 Gdip_DrawEllipse(pGraphics, pPen, x+w-(2*r), y+h-(2*r), 2*r, 2*r)
957 Gdip_ResetClip(pGraphics)
958 return _E
959}
960
961Gdip_DrawRoundedRectangle2(pGraphics, pPen, x, y, w, h, r, Angle:=0) {
962; extracted from: https://github.com/tariqporter/Gdip2/blob/master/lib/Object.ahk
963; and adapted by Marius Șucan
964
965 penWidth := Gdip_GetPenWidth(pPen)
966 pw := penWidth / 2
967 if (w <= h && (r + pw > w / 2))
968 {
969 r := (w / 2 > pw) ? w / 2 - pw : 0
970 } else if (h < w && r + pw > h / 2)
971 {
972 r := (h / 2 > pw) ? h / 2 - pw : 0
973 } else if (r < pw / 2)
974 {
975 r := pw / 2
976 }
977
978 r2 := r * 2
979 path1 := Gdip_CreatePath(0)
980 Gdip_AddPathArc(path1, x + pw, y + pw, r2, r2, 180, 90)
981 Gdip_AddPathLine(path1, x + pw + r, y + pw, x + w - r - pw, y + pw)
982 Gdip_AddPathArc(path1, x + w - r2 - pw, y + pw, r2, r2, 270, 90)
983 Gdip_AddPathLine(path1, x + w - pw, y + r + pw, x + w - pw, y + h - r - pw)
984 Gdip_AddPathArc(path1, x + w - r2 - pw, y + h - r2 - pw, r2, r2, 0, 90)
985 Gdip_AddPathLine(path1, x + w - r - pw, y + h - pw, x + r + pw, y + h - pw)
986 Gdip_AddPathArc(path1, x + pw, y + h - r2 - pw, r2, r2, 90, 90)
987 Gdip_AddPathLine(path1, x + pw, y + h - r - pw, x + pw, y + r + pw)
988 Gdip_ClosePathFigure(path1)
989 If (Angle>0)
990 Gdip_RotatePathAtCenter(path1, Angle)
991 _E := Gdip_DrawPath(pGraphics, pPen, path1)
992 Gdip_DeletePath(path1)
993 return _E
994}
995
996;#####################################################################################
997
998; Function Gdip_DrawEllipse
999; Description This function uses a pen to draw the outline of an ellipse into the Graphics of a bitmap
1000;
1001; pGraphics Pointer to the Graphics of a bitmap
1002; pPen Pointer to a pen
1003; x, y x, y coordinates of the top left of the rectangle the ellipse will be drawn into
1004; w, h width and height of the ellipse
1005;
1006; return status enumeration. 0 = success
1007;
1008; notes as all coordinates are taken from the top left of each pixel, then the entire width/height should be specified as subtracting the pen width
1009
1010Gdip_DrawEllipse(pGraphics, pPen, x, y, w, h) {
1011 Ptr := "UPtr"
1012 return DllCall("gdiplus\GdipDrawEllipse", Ptr, pGraphics, Ptr, pPen, "float", x, "float", y, "float", w, "float", h)
1013}
1014
1015;#####################################################################################
1016
1017; Function Gdip_DrawBezier
1018; Description This function uses a pen to draw the outline of a bezier (a weighted curve) into the Graphics of a bitmap
1019; A Bezier spline does not pass through its control points. The control points act as magnets, pulling the curve
1020; in certain directions to influence the way the spline bends.
1021
1022; pGraphics Pointer to the Graphics of a bitmap
1023; pPen Pointer to a pen
1024; x1, y1 x, y coordinates of the start of the bezier
1025; x2, y2 x, y coordinates of the first arc of the bezier
1026; x3, y3 x, y coordinates of the second arc of the bezier
1027; x4, y4 x, y coordinates of the end of the bezier
1028;
1029; return status enumeration. 0 = success
1030;
1031; notes as all coordinates are taken from the top left of each pixel, then the entire width/height should be specified as subtracting the pen width
1032
1033Gdip_DrawBezier(pGraphics, pPen, x1, y1, x2, y2, x3, y3, x4, y4) {
1034 Ptr := "UPtr"
1035 return DllCall("gdiplus\GdipDrawBezier"
1036 , Ptr, pGraphics
1037 , Ptr, pPen
1038 , "float", x1
1039 , "float", y1
1040 , "float", x2
1041 , "float", y2
1042 , "float", x3
1043 , "float", y3
1044 , "float", x4
1045 , "float", y4)
1046}
1047
1048;#####################################################################################
1049
1050; Function Gdip_DrawBezierCurve
1051; Description This function uses a pen to draw beziers
1052; Parameters:
1053; pGraphics Pointer to the Graphics of a bitmap
1054; pPen Pointer to a pen
1055; Points
1056; An array of starting and control points of a Bezier line
1057; A single Bezier line consists of 4 points a starting point 2 control
1058; points and an end point.
1059; The line never actually goes through the control points.
1060; The control points define the tangent in the starting and end points and their
1061; distance controls how strongly the curve follows there.
1062;
1063; Return: status enumeration. 0 = success
1064;
1065; This function was extracted and modified by Marius Șucan from
1066; a class based wrapper around the GDI+ API made by nnnik.
1067; Source: https://github.com/nnnik/classGDIp
1068;
1069; Points array format:
1070; Points := "x1,y1|x2,y2|x3,y3|x4,y4" [... and so on]
1071
1072Gdip_DrawBezierCurve(pGraphics, pPen, Points) {
1073 iCount := CreatePointsF(PointsF, Points)
1074 return DllCall("gdiplus\GdipDrawBeziers", "UPtr", pGraphics, "UPtr", pPen, "UPtr", &PointsF, "UInt", iCount)
1075}
1076
1077Gdip_DrawClosedCurve(pGraphics, pPen, Points, Tension:="") {
1078; Draws a closed cardinal spline on a pGraphics object using a pPen object.
1079; A cardinal spline is a curve that passes through each point in the array.
1080
1081; Tension: Non-negative real number that controls the length of the curve and how the curve bends. A value of
1082; zero specifies that the spline is a sequence of straight lines. As the value increases, the curve becomes fuller.
1083; Number that specifies how tightly the curve bends through the coordinates of the closed cardinal spline.
1084
1085; Example points array:
1086; Points := "x1,y1|x2,y2|x3,y3" [and so on]
1087; At least three points must be defined.
1088
1089 iCount := CreatePointsF(PointsF, Points)
1090 If Tension
1091 return DllCall("gdiplus\GdipDrawClosedCurve2", "UPtr", pGraphics, "UPtr", pPen, "UPtr", &PointsF, "UInt", iCount, "float", Tension)
1092 Else
1093 return DllCall("gdiplus\GdipDrawClosedCurve", "UPtr", pGraphics, "UPtr", pPen, "UPtr", &PointsF, "UInt", iCount)
1094}
1095
1096Gdip_DrawCurve(pGraphics, pPen, Points, Tension:="") {
1097; Draws an open spline on a pGraphics object using a pPen object.
1098; A cardinal spline is a curve that passes through each point in the array.
1099
1100; Tension: Non-negative real number that controls the length of the curve and how the curve bends. A value of
1101; zero specifies that the spline is a sequence of straight lines. As the value increases, the curve becomes fuller.
1102; Number that specifies how tightly the curve bends through the coordinates of the closed cardinal spline.
1103
1104; Example points array:
1105; Points := "x1,y1|x2,y2|x3,y3" [and so on]
1106; At least three points must be defined.
1107
1108 iCount := CreatePointsF(PointsF, Points)
1109 If Tension
1110 return DllCall("gdiplus\GdipDrawCurve2", "UPtr", pGraphics, "UPtr", pPen, "UPtr", &PointsF, "UInt", iCount, "float", Tension)
1111 Else
1112 return DllCall("gdiplus\GdipDrawCurve", "UPtr", pGraphics, "UPtr", pPen, "UPtr", &PointsF, "UInt", iCount)
1113}
1114
1115Gdip_DrawPolygon(pGraphics, pPen, Points) {
1116; Draws a closed polygonal line on a pGraphics object using a pPen object.
1117;
1118; Example points array:
1119; Points := "x1,y1|x2,y2|x3,y3" [and so on]
1120
1121 iCount := CreatePointsF(PointsF, Points)
1122 return DllCall("gdiplus\GdipDrawPolygon", "UPtr", pGraphics, "UPtr", pPen, "UPtr", &PointsF, "UInt", iCount)
1123}
1124
1125;#####################################################################################
1126
1127; Function Gdip_DrawArc
1128; Description This function uses a pen to draw the outline of an arc into the Graphics of a bitmap
1129;
1130; pGraphics Pointer to the Graphics of a bitmap
1131; pPen Pointer to a pen
1132; x, y x, y coordinates of the start of the arc
1133; w, h width and height of the arc
1134; StartAngle specifies the angle between the x-axis and the starting point of the arc
1135; SweepAngle specifies the angle between the starting and ending points of the arc
1136;
1137; return status enumeration. 0 = success
1138;
1139; notes as all coordinates are taken from the top left of each pixel, then the entire width/height should be specified as subtracting the pen width
1140
1141Gdip_DrawArc(pGraphics, pPen, x, y, w, h, StartAngle, SweepAngle) {
1142 Ptr := "UPtr"
1143 return DllCall("gdiplus\GdipDrawArc"
1144 , Ptr, pGraphics
1145 , Ptr, pPen
1146 , "float", x, "float", y
1147 , "float", w, "float", h
1148 , "float", StartAngle
1149 , "float", SweepAngle)
1150}
1151
1152;#####################################################################################
1153
1154; Function Gdip_DrawPie
1155; Description This function uses a pen to draw the outline of a pie into the Graphics of a bitmap
1156;
1157; pGraphics Pointer to the Graphics of a bitmap
1158; pPen Pointer to a pen
1159; x, y x, y coordinates of the start of the pie
1160; w, h width and height of the pie
1161; StartAngle specifies the angle between the x-axis and the starting point of the pie
1162; SweepAngle specifies the angle between the starting and ending points of the pie
1163;
1164; return status enumeration. 0 = success
1165;
1166; notes as all coordinates are taken from the top left of each pixel, then the entire width/height should be specified as subtracting the pen width
1167
1168Gdip_DrawPie(pGraphics, pPen, x, y, w, h, StartAngle, SweepAngle) {
1169 Ptr := "UPtr"
1170
1171 return DllCall("gdiplus\GdipDrawPie", Ptr, pGraphics, Ptr, pPen, "float", x, "float", y, "float", w, "float", h, "float", StartAngle, "float", SweepAngle)
1172}
1173
1174;#####################################################################################
1175
1176; Function Gdip_DrawLine
1177; Description This function uses a pen to draw a line into the Graphics of a bitmap
1178;
1179; pGraphics Pointer to the Graphics of a bitmap
1180; pPen Pointer to a pen
1181; x1, y1 x, y coordinates of the start of the line
1182; x2, y2 x, y coordinates of the end of the line
1183;
1184; return status enumeration. 0 = success
1185
1186Gdip_DrawLine(pGraphics, pPen, x1, y1, x2, y2) {
1187 Ptr := "UPtr"
1188 return DllCall("gdiplus\GdipDrawLine"
1189 , Ptr, pGraphics
1190 , Ptr, pPen
1191 , "float", x1, "float", y1
1192 , "float", x2, "float", y2)
1193}
1194
1195;#####################################################################################
1196
1197; Function Gdip_DrawLines
1198; Description This function uses a pen to draw a series of joined lines into the Graphics of a bitmap
1199;
1200; pGraphics Pointer to the Graphics of a bitmap
1201; pPen Pointer to a pen
1202; Points the coordinates of all the points passed as x1,y1|x2,y2|x3,y3.....
1203;
1204; return status enumeration. 0 = success
1205
1206Gdip_DrawLines(pGraphics, pPen, Points) {
1207 Ptr := "UPtr"
1208 iCount := CreatePointsF(PointsF, Points)
1209 return DllCall("gdiplus\GdipDrawLines", Ptr, pGraphics, Ptr, pPen, Ptr, &PointsF, "int", iCount)
1210}
1211
1212;#####################################################################################
1213
1214; Function Gdip_FillRectangle
1215; Description This function uses a brush to fill a rectangle in the Graphics of a bitmap
1216;
1217; pGraphics Pointer to the Graphics of a bitmap
1218; pBrush Pointer to a brush
1219; x, y x, y coordinates of the top left of the rectangle
1220; w, h width and height of the rectangle
1221;
1222; return status enumeration. 0 = success
1223
1224Gdip_FillRectangle(pGraphics, pBrush, x, y, w, h) {
1225 Ptr := "UPtr"
1226 return DllCall("gdiplus\GdipFillRectangle"
1227 , Ptr, pGraphics
1228 , Ptr, pBrush
1229 , "float", x, "float", y
1230 , "float", w, "float", h)
1231}
1232
1233;#####################################################################################
1234
1235; Function Gdip_FillRoundedRectangle
1236; Description This function uses a brush to fill a rounded rectangle in the Graphics of a bitmap
1237;
1238; pGraphics Pointer to the Graphics of a bitmap
1239; pBrush Pointer to a brush
1240; x, y x, y coordinates of the top left of the rounded rectangle
1241; w, h width and height of the rectanlge
1242; r radius of the rounded corners
1243;
1244; return status enumeration. 0 = success
1245
1246Gdip_FillRoundedRectangle2(pGraphics, pBrush, x, y, w, h, r) {
1247; extracted from: https://github.com/tariqporter/Gdip2/blob/master/lib/Object.ahk
1248; and adapted by Marius Șucan
1249
1250 r := (w <= h) ? (r < w // 2) ? r : w // 2 : (r < h // 2) ? r : h // 2
1251 path1 := Gdip_CreatePath(0)
1252 Gdip_AddPathRectangle(path1, x+r, y, w-(2*r), r)
1253 Gdip_AddPathRectangle(path1, x+r, y+h-r, w-(2*r), r)
1254 Gdip_AddPathRectangle(path1, x, y+r, r, h-(2*r))
1255 Gdip_AddPathRectangle(path1, x+w-r, y+r, r, h-(2*r))
1256 Gdip_AddPathRectangle(path1, x+r, y+r, w-(2*r), h-(2*r))
1257 Gdip_AddPathPie(path1, x, y, 2*r, 2*r, 180, 90)
1258 Gdip_AddPathPie(path1, x+w-(2*r), y, 2*r, 2*r, 270, 90)
1259 Gdip_AddPathPie(path1, x, y+h-(2*r), 2*r, 2*r, 90, 90)
1260 Gdip_AddPathPie(path1, x+w-(2*r), y+h-(2*r), 2*r, 2*r, 0, 90)
1261 E := Gdip_FillPath(pGraphics, pBrush, path1)
1262 Gdip_DeletePath(path1)
1263 return E
1264}
1265
1266Gdip_FillRoundedRectangle(pGraphics, pBrush, x, y, w, h, r) {
1267 Region := Gdip_GetClipRegion(pGraphics)
1268 Gdip_SetClipRect(pGraphics, x-r, y-r, 2*r, 2*r, 4)
1269 Gdip_SetClipRect(pGraphics, x+w-r, y-r, 2*r, 2*r, 4)
1270 Gdip_SetClipRect(pGraphics, x-r, y+h-r, 2*r, 2*r, 4)
1271 Gdip_SetClipRect(pGraphics, x+w-r, y+h-r, 2*r, 2*r, 4)
1272 _E := Gdip_FillRectangle(pGraphics, pBrush, x, y, w, h)
1273 Gdip_SetClipRegion(pGraphics, Region, 0)
1274 Gdip_SetClipRect(pGraphics, x-(2*r), y+r, w+(4*r), h-(2*r), 4)
1275 Gdip_SetClipRect(pGraphics, x+r, y-(2*r), w-(2*r), h+(4*r), 4)
1276 Gdip_FillEllipse(pGraphics, pBrush, x, y, 2*r, 2*r)
1277 Gdip_FillEllipse(pGraphics, pBrush, x+w-(2*r), y, 2*r, 2*r)
1278 Gdip_FillEllipse(pGraphics, pBrush, x, y+h-(2*r), 2*r, 2*r)
1279 Gdip_FillEllipse(pGraphics, pBrush, x+w-(2*r), y+h-(2*r), 2*r, 2*r)
1280 Gdip_SetClipRegion(pGraphics, Region, 0)
1281 Gdip_DeleteRegion(Region)
1282 return _E
1283}
1284
1285;#####################################################################################
1286
1287; Function Gdip_FillPolygon
1288; Description This function uses a brush to fill a polygon in the Graphics of a bitmap
1289;
1290; pGraphics Pointer to the Graphics of a bitmap
1291; pBrush Pointer to a brush
1292; Points the coordinates of all the points passed as x1,y1|x2,y2|x3,y3.....
1293;
1294; return status enumeration. 0 = success
1295;
1296; notes Alternate will fill the polygon as a whole, wheras winding will fill each new "segment"
1297; Alternate = 0
1298; Winding = 1
1299
1300Gdip_FillPolygon(pGraphics, pBrush, Points, FillMode:=0) {
1301 Ptr := "UPtr"
1302 iCount := CreatePointsF(PointsF, Points)
1303 return DllCall("gdiplus\GdipFillPolygon", Ptr, pGraphics, Ptr, pBrush, Ptr, &PointsF, "int", iCount, "int", FillMode)
1304}
1305
1306;#####################################################################################
1307
1308; Function Gdip_FillPie
1309; Description This function uses a brush to fill a pie in the Graphics of a bitmap
1310;
1311; pGraphics Pointer to the Graphics of a bitmap
1312; pBrush Pointer to a brush
1313; x, y x, y coordinates of the top left of the pie
1314; w, h width and height of the pie
1315; StartAngle specifies the angle between the x-axis and the starting point of the pie
1316; SweepAngle specifies the angle between the starting and ending points of the pie
1317;
1318; return status enumeration. 0 = success
1319
1320Gdip_FillPie(pGraphics, pBrush, x, y, w, h, StartAngle, SweepAngle) {
1321 Ptr := "UPtr"
1322 return DllCall("gdiplus\GdipFillPie"
1323 , Ptr, pGraphics
1324 , Ptr, pBrush
1325 , "float", x
1326 , "float", y
1327 , "float", w
1328 , "float", h
1329 , "float", StartAngle
1330 , "float", SweepAngle)
1331}
1332
1333;#####################################################################################
1334
1335; Function Gdip_FillEllipse
1336; Description This function uses a brush to fill an ellipse in the Graphics of a bitmap
1337;
1338; pGraphics Pointer to the Graphics of a bitmap
1339; pBrush Pointer to a brush
1340; x, y x, y coordinates of the top left of the ellipse
1341; w, h width and height of the ellipse
1342;
1343; return status enumeration. 0 = success
1344
1345Gdip_FillEllipse(pGraphics, pBrush, x, y, w, h) {
1346 Ptr := "UPtr"
1347 return DllCall("gdiplus\GdipFillEllipse", Ptr, pGraphics, Ptr, pBrush, "float", x, "float", y, "float", w, "float", h)
1348}
1349
1350;#####################################################################################
1351
1352; Function Gdip_FillRegion
1353; Description This function uses a brush to fill a region in the Graphics of a bitmap
1354;
1355; pGraphics Pointer to the Graphics of a bitmap
1356; pBrush Pointer to a brush
1357; Region Pointer to a Region
1358;
1359; return status enumeration. 0 = success
1360;
1361; notes You can create a region Gdip_CreateRegion() and then add to this
1362
1363Gdip_FillRegion(pGraphics, pBrush, Region) {
1364 Ptr := "UPtr"
1365 return DllCall("gdiplus\GdipFillRegion", Ptr, pGraphics, Ptr, pBrush, Ptr, Region)
1366}
1367
1368;#####################################################################################
1369
1370; Function Gdip_FillPath
1371; Description This function uses a brush to fill a path in the Graphics of a bitmap
1372;
1373; pGraphics Pointer to the Graphics of a bitmap
1374; pBrush Pointer to a brush
1375; Region Pointer to a Path
1376;
1377; return status enumeration. 0 = success
1378
1379Gdip_FillPath(pGraphics, pBrush, pPath) {
1380 Ptr := "UPtr"
1381 return DllCall("gdiplus\GdipFillPath", Ptr, pGraphics, Ptr, pBrush, Ptr, pPath)
1382}
1383;#####################################################################################
1384
1385; Function Gdip_FillClosedCurve
1386; Description This function fills a closed cardinal spline on a pGraphics object
1387; using a pBrush object.
1388; A cardinal spline is a curve that passes through each point in the array.
1389;
1390; pGraphics Pointer to the Graphics of a bitmap
1391; pBrush Pointer to a brush
1392;
1393; Points array format:
1394; Points := "x1,y1|x2,y2|x3,y3|x4,y4" [... and so on]
1395;
1396; Tension Non-negative real number that controls the length of the curve and how the curve bends. A value of
1397; zero specifies that the spline is a sequence of straight lines. As the value increases, the curve becomes fuller.
1398; Number that specifies how tightly the curve bends through the coordinates of the closed cardinal spline.
1399;
1400; Fill mode: 0 - [Alternate] The areas are filled according to the even-odd parity rule
1401; 1 - [Winding] The areas are filled according to the non-zero winding rule
1402;
1403; return status enumeration. 0 = success
1404
1405Gdip_FillClosedCurve(pGraphics, pBrush, Points, Tension:="", FillMode:=0) {
1406 Ptr := "UPtr"
1407 iCount := CreatePointsF(PointsF, Points)
1408 If Tension
1409 Return DllCall("gdiplus\GdipFillClosedCurve2", Ptr, pGraphics, Ptr, pBrush, "UPtr", &PointsF, "int", iCount, "float", Tension, "int", FillMode)
1410 Else
1411 Return DllCall("gdiplus\GdipFillClosedCurve", Ptr, pGraphics, Ptr, pBrush, "UPtr", &PointsF, "int", iCount)
1412}
1413
1414;#####################################################################################
1415
1416; Function Gdip_DrawImagePointsRect
1417; Description This function draws a bitmap into the Graphics of another bitmap and skews it
1418;
1419; pGraphics Pointer to the Graphics of a bitmap
1420; pBitmap Pointer to a bitmap to be drawn
1421; Points Points passed as x1,y1|x2,y2|x3,y3 (3 points: top left, top right, bottom left) describing the drawing of the bitmap
1422; sX, sY x, y coordinates of the source upper-left corner
1423; sW, sH width and height of the source rectangle
1424; Matrix a color matrix used to alter image attributes when drawing
1425; Unit see Gdip_DrawImage()
1426; Return status enumeration. 0 = success
1427;
1428; Notes If sx, sy, sw, sh are omitted the entire source bitmap will be used.
1429; Matrix can be omitted to just draw with no alteration to ARGB.
1430; Matrix may be passed as a digit from 0 - 1 to change just transparency.
1431; Matrix can be passed as a matrix with "|" delimiter.
1432; To generate a color matrix using user-friendly parameters,
1433; use GenerateColorMatrix()
1434
1435Gdip_DrawImagePointsRect(pGraphics, pBitmap, Points, sx:="", sy:="", sw:="", sh:="", Matrix:=1, Unit:=2, ImageAttr:=0) {
1436 Ptr := "UPtr"
1437 If !ImageAttr
1438 {
1439 if !IsNumber(Matrix)
1440 ImageAttr := Gdip_SetImageAttributesColorMatrix(Matrix)
1441 else if (Matrix != 1)
1442 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")
1443 } Else usrImageAttr := 1
1444
1445 if (sx="" && sy="" && sw="" && sh="")
1446 {
1447 sx := sy := 0
1448 Gdip_GetImageDimensions(pBitmap, sw, sh)
1449 }
1450
1451 iCount := CreatePointsF(PointsF, Points)
1452 _E := DllCall("gdiplus\GdipDrawImagePointsRect"
1453 , Ptr, pGraphics
1454 , Ptr, pBitmap
1455 , Ptr, &PointsF
1456 , "int", iCount
1457 , "float", sX
1458 , "float", sY
1459 , "float", sW
1460 , "float", sH
1461 , "int", Unit
1462 , Ptr, ImageAttr ? ImageAttr : 0
1463 , Ptr, 0
1464 , Ptr, 0)
1465
1466 if (ImageAttr && usrImageAttr!=1)
1467 Gdip_DisposeImageAttributes(ImageAttr)
1468
1469 return _E
1470}
1471
1472;#####################################################################################
1473
1474; Function Gdip_DrawImage
1475; Description This function draws a bitmap into the Graphics of another bitmap
1476;
1477; pGraphics Pointer to the Graphics of a bitmap
1478; pBitmap Pointer to a bitmap to be drawn
1479; dX, dY x, y coordinates of the destination upper-left corner
1480; dW, dH width and height of the destination image
1481; sX, sY x, y coordinates of the source upper-left corner
1482; sW, sH width and height of the source image
1483; Matrix a color matrix used to alter image attributes when drawing
1484; Unit Unit of measurement:
1485; 0 - World coordinates, a nonphysical unit
1486; 1 - Display units
1487; 2 - A unit is 1 pixel
1488; 3 - A unit is 1 point or 1/72 inch
1489; 4 - A unit is 1 inch
1490; 5 - A unit is 1/300 inch
1491; 6 - A unit is 1 millimeter
1492;
1493; return status enumeration. 0 = success
1494;
1495; notes When sx,sy,sw,sh are omitted the entire source bitmap will be used
1496; Gdip_DrawImage performs faster.
1497; Matrix can be omitted to just draw with no alteration to ARGB
1498; Matrix may be passed as a digit from 0.0 - 1.0 to change just transparency
1499; Matrix can be passed as a matrix with "|" as delimiter. For example:
1500; MatrixBright=
1501; (
1502; 1.5 |0 |0 |0 |0
1503; 0 |1.5 |0 |0 |0
1504; 0 |0 |1.5 |0 |0
1505; 0 |0 |0 |1 |0
1506; 0.05 |0.05 |0.05 |0 |1
1507; )
1508;
1509; example color matrix:
1510; 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
1511; 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
1512; MatrixNegative = -1|0|0|0|0|0|-1|0|0|0|0|0|-1|0|0|0|0|0|1|0|1|1|1|0|1
1513; To generate a color matrix using user-friendly parameters,
1514; use GenerateColorMatrix()
1515
1516Gdip_DrawImage(pGraphics, pBitmap, dx:="", dy:="", dw:="", dh:="", sx:="", sy:="", sw:="", sh:="", Matrix:=1, Unit:=2, ImageAttr:=0) {
1517 Ptr := "UPtr"
1518 If !ImageAttr
1519 {
1520 if !IsNumber(Matrix)
1521 ImageAttr := Gdip_SetImageAttributesColorMatrix(Matrix)
1522 else if (Matrix!=1)
1523 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")
1524 } Else usrImageAttr := 1
1525
1526 If (dx!="" && dy!="" && dw="" && dh="" && sx="" && sy="" && sw="" && sh="")
1527 {
1528 sx := sy := 0
1529 sw := dw := Gdip_GetImageWidth(pBitmap)
1530 sh := dh := Gdip_GetImageHeight(pBitmap)
1531 } Else If (sx="" && sy="" && sw="" && sh="")
1532 {
1533 If (dx="" && dy="" && dw="" && dh="")
1534 {
1535 sx := dx := 0, sy := dy := 0
1536 sw := dw := Gdip_GetImageWidth(pBitmap)
1537 sh := dh := Gdip_GetImageHeight(pBitmap)
1538 } Else
1539 {
1540 sx := sy := 0
1541 Gdip_GetImageDimensions(pBitmap, sw, sh)
1542 }
1543 }
1544
1545 _E := DllCall("gdiplus\GdipDrawImageRectRect"
1546 , Ptr, pGraphics
1547 , Ptr, pBitmap
1548 , "float", dX, "float", dY
1549 , "float", dW, "float", dH
1550 , "float", sX, "float", sY
1551 , "float", sW, "float", sH
1552 , "int", Unit
1553 , Ptr, ImageAttr ? ImageAttr : 0
1554 , Ptr, 0, Ptr, 0)
1555
1556 if (ImageAttr && usrImageAttr!=1)
1557 Gdip_DisposeImageAttributes(ImageAttr)
1558
1559 return _E
1560}
1561
1562Gdip_DrawImageFast(pGraphics, pBitmap, X:=0, Y:=0) {
1563; This function performs faster than Gdip_DrawImage().
1564; X, Y - the coordinates of the destination upper-left corner
1565; where the pBitmap will be drawn.
1566
1567 Ptr := "UPtr"
1568 _E := DllCall("gdiplus\GdipDrawImage"
1569 , Ptr, pGraphics
1570 , Ptr, pBitmap
1571 , "float", X
1572 , "float", Y)
1573 return _E
1574}
1575
1576Gdip_DrawImageRect(pGraphics, pBitmap, X, Y, W, H) {
1577; X, Y - the coordinates of the destination upper-left corner
1578; where the pBitmap will be drawn.
1579; W, H - the width and height of the destination rectangle, where the pBitmap will be drawn.
1580
1581 Ptr := "UPtr"
1582 _E := DllCall("gdiplus\GdipDrawImageRect"
1583 , Ptr, pGraphics
1584 , Ptr, pBitmap
1585 , "float", X, "float", Y
1586 , "float", W, "float", H)
1587 return _E
1588}
1589
1590;#####################################################################################
1591
1592; Function Gdip_SetImageAttributesColorMatrix
1593; Description This function creates an image color matrix ready for drawing if no ImageAttr is given.
1594; It can set or clear the color and/or grayscale-adjustment matrices for a specified ImageAttr object.
1595;
1596; clrMatrix A color-adjustment matrix used to alter image attributes when drawing
1597; passed with "|" as delimeter.
1598; grayMatrix A grayscale-adjustment matrix used to alter image attributes when drawing
1599; passed with "|" as delimeter. This applies only when ColorMatrixFlag=2.
1600;
1601; ColorAdjustType The category for which the color and grayscale-adjustment matrices are set or cleared.
1602; 0 - adjustments apply to all categories that do not have adjustment settings of their own
1603; 1 - adjustments apply to bitmapped images
1604; 2 - adjustments apply to brush operations in metafiles
1605; 3 - adjustments apply to pen operations in metafiles
1606; 4 - adjustments apply to text drawn in metafiles
1607;
1608; fEnable If True, the specified matrices (color, grayscale or both) adjustments for the specified
1609; category are applied; otherwise the category is cleared
1610;
1611; ColorMatrixFlag Type of image and color that will be affected by the adjustment matrices:
1612; 0 - All color values (including grays) are adjusted by the same color-adjustment matrix.
1613; 1 - Colors are adjusted but gray shades are not adjusted.
1614; A gray shade is any color that has the same value for its red, green, and blue components.
1615; 2 - Colors are adjusted by one matrix and gray shades are adjusted by another matrix.
1616
1617; ImageAttr A pointer to an ImageAttributes object.
1618; If this parameter is omitted, a new one is created.
1619
1620; return It return 0 on success, if an ImageAttr object was given,
1621; otherwise, it returns the handle of a new ImageAttr object [if succesful].
1622;
1623; 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
1624; 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
1625; MatrixNegative = -1|0|0|0|0|0|-1|0|0|0|0|0|-1|0|0|0|0|0|1|0|1|1|1|0|1
1626; To generate a color matrix using user-friendly parameters,
1627; use GenerateColorMatrix()
1628; additional remarks:
1629; In my tests, it seems that the grayscale matrix is not functioning properly.
1630; Grayscale images are rendered invisible [with zero opacity] for some reason...
1631; TO DO: fix this?
1632
1633Gdip_SetImageAttributesColorMatrix(clrMatrix, ImageAttr:=0, grayMatrix:=0, ColorAdjustType:=1, fEnable:=1, ColorMatrixFlag:=0) {
1634 Ptr := "UPtr"
1635 If (StrLen(clrMatrix)<5 && ImageAttr)
1636 Return -1
1637
1638 If StrLen(clrMatrix)<5
1639 Return
1640
1641 VarSetCapacity(ColourMatrix, 100, 0)
1642 Matrix := RegExReplace(RegExReplace(clrMatrix, "^[^\d-\.]+([\d\.])", "$1", , 1), "[^\d-\.]+", "|")
1643 Matrix := StrSplit(Matrix, "|")
1644 Loop 25
1645 {
1646 M := (Matrix[A_Index] != "") ? Matrix[A_Index] : Mod(A_Index-1, 6) ? 0 : 1
1647 NumPut(M, ColourMatrix, (A_Index-1)*4, "float")
1648 }
1649
1650 Matrix := ""
1651 Matrix := RegExReplace(RegExReplace(grayMatrix, "^[^\d-\.]+([\d\.])", "$1", , 1), "[^\d-\.]+", "|")
1652 Matrix := StrSplit(Matrix, "|")
1653 If (StrLen(Matrix)>2 && ColorMatrixFlag=2)
1654 {
1655 VarSetCapacity(GrayscaleMatrix, 100, 0)
1656 Loop 25
1657 {
1658 M := (Matrix[A_Index] != "") ? Matrix[A_Index] : Mod(A_Index-1, 6) ? 0 : 1
1659 NumPut(M, GrayscaleMatrix, (A_Index-1)*4, "float")
1660 }
1661 }
1662
1663 If !ImageAttr
1664 {
1665 created := 1
1666 ImageAttr := Gdip_CreateImageAttributes()
1667 }
1668
1669 E := DllCall("gdiplus\GdipSetImageAttributesColorMatrix"
1670 , Ptr, ImageAttr
1671 , "int", ColorAdjustType
1672 , "int", fEnable
1673 , Ptr, &ColourMatrix
1674 , Ptr, &GrayscaleMatrix
1675 , "int", ColorMatrixFlag)
1676
1677 E := created=1 ? ImageAttr : E
1678 return E
1679}
1680
1681Gdip_CreateImageAttributes() {
1682 ImageAttr := 0
1683 DllCall("gdiplus\GdipCreateImageAttributes", "UPtr*", ImageAttr)
1684 return ImageAttr
1685}
1686
1687Gdip_CloneImageAttributes(ImageAttr) {
1688 Ptr := "UPtr"
1689 newImageAttr := 0
1690 DllCall("gdiplus\GdipCloneImageAttributes", Ptr, ImageAttr, "UPtr*", newImageAttr)
1691 return newImageAttr
1692}
1693
1694Gdip_SetImageAttributesThreshold(ImageAttr, Threshold, ColorAdjustType:=1, fEnable:=1) {
1695; Sets or clears the threshold (transparency range) for a specified category by ColorAdjustType
1696; The threshold is a value from 0 through 1 that specifies a cutoff point for each color component. For example,
1697; suppose the threshold is set to 0.7, and suppose you are rendering a color whose red, green, and blue
1698; components are 230, 50, and 220. The red component, 230, is greater than 0.7ª255, so the red component will
1699; be changed to 255 (full intensity). The green component, 50, is less than 0.7ª255, so the green component will
1700; be changed to 0. The blue component, 220, is greater than 0.7ª255, so the blue component will be changed to 255.
1701
1702 Ptr := "UPtr"
1703 return DllCall("gdiplus\GdipSetImageAttributesThreshold", Ptr, ImageAttr, "int", ColorAdjustType, "int", fEnable, "float", Threshold)
1704}
1705
1706Gdip_SetImageAttributesResetMatrix(ImageAttr, ColorAdjustType) {
1707; Sets the color-adjustment matrix of a specified category to the identity matrix.
1708
1709 Ptr := "UPtr"
1710 return DllCall("gdiplus\GdipSetImageAttributesToIdentity", Ptr, ImageAttr, "int", ColorAdjustType)
1711}
1712
1713Gdip_SetImageAttributesGamma(ImageAttr, Gamma, ColorAdjustType:=1, fEnable:=1) {
1714; Gamma from 0.1 to 5.0
1715
1716 Ptr := "UPtr"
1717 return DllCall("gdiplus\GdipSetImageAttributesGamma", Ptr, ImageAttr, "int", ColorAdjustType, "int", fEnable, "float", Gamma)
1718}
1719
1720Gdip_SetImageAttributesToggle(ImageAttr, ColorAdjustType, fEnable) {
1721; Turns on or off color adjustment for a specified category defined by ColorAdjustType
1722; fEnable - 0 or 1
1723
1724 Ptr := "UPtr"
1725 return DllCall("gdiplus\GdipSetImageAttributesNoOp", Ptr, ImageAttr, "int", ColorAdjustType, "int", fEnable)
1726}
1727
1728Gdip_SetImageAttributesOutputChannel(ImageAttr, ColorChannelFlags, ColorAdjustType:=1, fEnable:=1) {
1729; ColorChannelFlags - The output channel, can be any combination:
1730; 0 - Cyan color channel
1731; 1 - Magenta color channel
1732; 2 - Yellow color channel
1733; 3 - Black color channel
1734; 4 - The previous selected channel
1735
1736 Ptr := "UPtr"
1737 return DllCall("gdiplus\GdipSetImageAttributesOutputChannel", Ptr, ImageAttr, "int", ColorAdjustType, "int", fEnable, "int", ColorChannelFlags)
1738}
1739
1740Gdip_SetImageAttributesColorKeys(ImageAttr, ARGBLow, ARGBHigh, ColorAdjustType:=1, fEnable:=1) {
1741; initial tests of this function lead to a crash of the application ...
1742
1743 Ptr := "UPtr"
1744 Return DllCall("gdiplus\GdipSetImageAttributesColorKeys", Ptr, ImageAttr, "int", ColorAdjustType, "int", fEnable, "uint", ARGBLow, "uint", ARGBHigh)
1745}
1746
1747Gdip_SetImageAttributesWrapMode(ImageAttr, WrapMode, ARGB) {
1748; ImageAttr - Pointer to an ImageAttribute object
1749; WrapMode - Specifies how repeated copies of an image are used to tile an area:
1750; 0 - Tile - Tiling without flipping
1751; 1 - TileFlipX - Tiles are flipped horizontally as you move from one tile to the next in a row
1752; 2 - TileFlipY - Tiles are flipped vertically as you move from one tile to the next in a column
1753; 3 - TileFlipXY - Tiles are flipped horizontally as you move along a row and flipped vertically as you move along a column
1754; 4 - Clamp - No tiling takes place
1755; ARGB - Alpha, Red, Green and Blue components of the color of pixels outside of a rendered image.
1756; This color is visible if the wrap mode is set to 4 and the source rectangle of the image is greater than the
1757; image itself.
1758
1759 Ptr := "UPtr"
1760 Return DllCall("gdiplus\GdipSetImageAttributesWrapMode", Ptr, ImageAttr, "int", WrapMode, "uint", ARGB, "int", 0)
1761}
1762
1763Gdip_ResetImageAttributes(ImageAttr, ColorAdjustType) {
1764; Clears all color and grayscale-adjustment settings for a specified category defined by ColorAdjustType.
1765;
1766; ImageAttr - a pointer to an ImageAttributes object.
1767; ColorAdjustType - The category for which color adjustment is reset:
1768; see Gdip_SetImageAttributesColorMatrix() for details.
1769
1770 Ptr := "UPtr"
1771 DllCall("gdiplus\GdipResetImageAttributes", Ptr, ImageAttr, "int", ColorAdjustType)
1772}
1773
1774;#####################################################################################
1775
1776; Function Gdip_GraphicsFromImage
1777; Description This function gets the graphics for a bitmap used for drawing functions
1778;
1779; pBitmap Pointer to a bitmap to get the pointer to its graphics
1780;
1781; return returns a pointer to the graphics of a bitmap
1782;
1783; notes a bitmap can be drawn into the graphics of another bitmap
1784
1785Gdip_GraphicsFromImage(pBitmap, InterpolationMode:="", SmoothingMode:="", PageUnit:="", CompositingQuality:="") {
1786 pGraphics := 0
1787 DllCall("gdiplus\GdipGetImageGraphicsContext", "UPtr", pBitmap, "UPtr*", pGraphics)
1788 If pGraphics
1789 {
1790 If (InterpolationMode!="")
1791 Gdip_SetInterpolationMode(pGraphics, InterpolationMode)
1792 If (SmoothingMode!="")
1793 Gdip_SetSmoothingMode(pGraphics, SmoothingMode)
1794 If (PageUnit!="")
1795 Gdip_SetPageUnit(pGraphics, PageUnit)
1796 If (CompositingQuality!="")
1797 Gdip_SetCompositingMode(pGraphics, CompositingQuality)
1798 }
1799 return pGraphics
1800}
1801
1802;#####################################################################################
1803
1804; Function Gdip_GraphicsFromHDC
1805; Description This function gets the graphics from the handle of a device context.
1806;
1807; hDC The handle to the device context.
1808; hDevice Handle to a device that will be associated with the new Graphics object.
1809;
1810; return A pointer to the graphics of a bitmap.
1811;
1812; notes You can draw a bitmap into the graphics of another bitmap.
1813
1814Gdip_GraphicsFromHDC(hDC, hDevice:="", InterpolationMode:="", SmoothingMode:="", PageUnit:="", CompositingQuality:="") {
1815 pGraphics := 0
1816 If hDevice
1817 DllCall("Gdiplus\GdipCreateFromHDC2", "UPtr", hDC, "UPtr", hDevice, "UPtr*", pGraphics)
1818 Else
1819 DllCall("gdiplus\GdipCreateFromHDC", "UPtr", hdc, "UPtr*", pGraphics)
1820
1821 If pGraphics
1822 {
1823 If (InterpolationMode!="")
1824 Gdip_SetInterpolationMode(pGraphics, InterpolationMode)
1825 If (SmoothingMode!="")
1826 Gdip_SetSmoothingMode(pGraphics, SmoothingMode)
1827 If (PageUnit!="")
1828 Gdip_SetPageUnit(pGraphics, PageUnit)
1829 If (CompositingQuality!="")
1830 Gdip_SetCompositingMode(pGraphics, CompositingQuality)
1831 }
1832
1833 return pGraphics
1834}
1835
1836Gdip_GraphicsFromHWND(HWND, useICM:=0, InterpolationMode:="", SmoothingMode:="", PageUnit:="", CompositingQuality:="") {
1837; Creates a pGraphics object that is associated with a specified window handle [HWND]
1838; If useICM=1, the created graphics uses ICM [color management - (International Color Consortium = ICC)].
1839 pGraphics := 0
1840 function2call := (useICM=1) ? "GdipCreateFromHWNDICM" : "GdipCreateFromHWND"
1841 DllCall("gdiplus\" function2call, "UPtr", HWND, "UPtr*", pGraphics)
1842
1843 If pGraphics
1844 {
1845 If (InterpolationMode!="")
1846 Gdip_SetInterpolationMode(pGraphics, InterpolationMode)
1847 If (SmoothingMode!="")
1848 Gdip_SetSmoothingMode(pGraphics, SmoothingMode)
1849 If (PageUnit!="")
1850 Gdip_SetPageUnit(pGraphics, PageUnit)
1851 If (CompositingQuality!="")
1852 Gdip_SetCompositingMode(pGraphics, CompositingQuality)
1853 }
1854 return pGraphics
1855}
1856
1857;#####################################################################################
1858
1859; Function Gdip_GetDC
1860; Description This function gets the device context of the passed Graphics
1861;
1862; hDC This is the handle to the device context
1863;
1864; return returns the device context for the graphics of a bitmap
1865
1866Gdip_GetDC(pGraphics) {
1867 hDC := 0
1868 DllCall("gdiplus\GdipGetDC", "UPtr", pGraphics, "UPtr*", hDC)
1869 return hDC
1870}
1871
1872;#####################################################################################
1873
1874; Function Gdip_ReleaseDC
1875; Description This function releases a device context from use for further use
1876;
1877; pGraphics Pointer to the graphics of a bitmap
1878; hdc This is the handle to the device context
1879;
1880; return status enumeration. 0 = success
1881
1882Gdip_ReleaseDC(pGraphics, hdc) {
1883 Ptr := "UPtr"
1884 return DllCall("gdiplus\GdipReleaseDC", Ptr, pGraphics, Ptr, hdc)
1885}
1886
1887;#####################################################################################
1888
1889; Function Gdip_GraphicsClear
1890; Description Clears the graphics of a bitmap ready for further drawing
1891;
1892; pGraphics Pointer to the graphics of a bitmap
1893; ARGB The colour to clear the graphics to
1894;
1895; return status enumeration. 0 = success
1896;
1897; notes By default this will make the background invisible
1898; Using clipping regions you can clear a particular area on the graphics rather than clearing the entire graphics
1899
1900Gdip_GraphicsClear(pGraphics, ARGB:=0x00ffffff) {
1901 return DllCall("gdiplus\GdipGraphicsClear", "UPtr", pGraphics, "int", ARGB)
1902}
1903
1904Gdip_GraphicsFlush(pGraphics, intent) {
1905; intent - Specifies whether the method returns immediately or waits for any existing operations to finish:
1906; 0 - Flush all batched rendering operations and return immediately
1907; 1 - Flush all batched rendering operations and wait for them to complete
1908
1909 return DllCall("gdiplus\GdipFlush", "UPtr", pGraphics, "int", intent)
1910}
1911
1912;#####################################################################################
1913
1914; Function Gdip_BlurBitmap
1915; Description Gives a pointer to a blurred bitmap from a pointer to a bitmap
1916;
1917; pBitmap Pointer to a bitmap to be blurred
1918; BlurAmount The Amount to blur a bitmap by from 1 (least blur) to 100 (most blur)
1919;
1920; return If the function succeeds, the return value is a pointer to the new blurred bitmap
1921; -1 = The blur parameter is outside the range 1-100
1922;
1923; notes This function will not dispose of the original bitmap
1924
1925Gdip_BlurBitmap(pBitmap, BlurAmount) {
1926 if (BlurAmount > 100) || (BlurAmount < 1)
1927 return -1
1928
1929 Gdip_GetImageDimensions(pBitmap, sWidth, sHeight)
1930 dWidth := sWidth//BlurAmount
1931 dHeight := sHeight//BlurAmount
1932
1933 pBitmap1 := Gdip_CreateBitmap(dWidth, dHeight)
1934 G1 := Gdip_GraphicsFromImage(pBitmap1)
1935 Gdip_SetInterpolationMode(G1, 7)
1936 Gdip_DrawImage(G1, pBitmap, 0, 0, dWidth, dHeight, 0, 0, sWidth, sHeight)
1937
1938 Gdip_DeleteGraphics(G1)
1939 pBitmap2 := Gdip_CreateBitmap(sWidth, sHeight)
1940 G2 := Gdip_GraphicsFromImage(pBitmap2)
1941 Gdip_SetInterpolationMode(G2, 7)
1942 Gdip_DrawImage(G2, pBitmap1, 0, 0, sWidth, sHeight, 0, 0, dWidth, dHeight)
1943
1944 Gdip_DeleteGraphics(G2)
1945 Gdip_DisposeImage(pBitmap1)
1946 return pBitmap2
1947}
1948
1949;#####################################################################################
1950
1951; Function: Gdip_SaveBitmapToFile
1952; Description: Saves a bitmap to a file in any supported format onto disk
1953;
1954; pBitmap Pointer to a bitmap
1955; sOutput The name of the file that the bitmap will be saved to. Supported extensions are: .BMP,.DIB,.RLE,.JPG,.JPEG,.JPE,.JFIF,.GIF,.TIF,.TIFF,.PNG
1956; Quality If saving as jpg (.JPG,.JPEG,.JPE,.JFIF) then quality can be 1-100 with default at maximum quality
1957; toBase64 If set to 1, instead of saving the file to disk, the function will return on success the base64 data
1958; A "base64" string is the binary image data encoded into text using only 64 characters.
1959; To convert it back into an image use: Gdip_BitmapFromBase64()
1960;
1961; return If the function succeeds, the return value is zero, otherwise:
1962; -1 = Extension supplied is not a supported file format
1963; -2 = Could not get a list of encoders on system
1964; -3 = Could not find matching encoder for specified file format
1965; -4 = Could not get WideChar name of output file
1966; -5 = Could not save file to disk
1967; -6 = Could not save image to stream [for base64]
1968; -7 = Could not convert to base64
1969;
1970; notes This function will use the extension supplied from the sOutput parameter to determine the output format
1971
1972Gdip_SaveBitmapToFile(pBitmap, sOutput, Quality:=75, toBase64:=0) {
1973 Ptr := "UPtr"
1974 nCount := 0
1975 nSize := 0
1976 _p := 0
1977
1978 SplitPath sOutput,,, Extension
1979 If !RegExMatch(Extension, "^(?i:BMP|DIB|RLE|JPG|JPEG|JPE|JFIF|GIF|TIF|TIFF|PNG)$")
1980 Return -1
1981
1982 Extension := "." Extension
1983 DllCall("gdiplus\GdipGetImageEncodersSize", "uint*", nCount, "uint*", nSize)
1984 VarSetCapacity(ci, nSize)
1985 DllCall("gdiplus\GdipGetImageEncoders", "uint", nCount, "uint", nSize, Ptr, &ci)
1986 If !(nCount && nSize)
1987 Return -2
1988
1989 If (A_IsUnicode)
1990 {
1991 StrGet_Name := "StrGet"
1992 N := (A_AhkVersion < 2) ? nCount : "nCount"
1993 Loop %N%
1994 {
1995 sString := %StrGet_Name%(NumGet(ci, (idx := (48+7*A_PtrSize)*(A_Index-1))+32+3*A_PtrSize), "UTF-16")
1996 If !InStr(sString, "*" Extension)
1997 Continue
1998
1999 pCodec := &ci+idx
2000 Break
2001 }
2002 } Else
2003 {
2004 N := (A_AhkVersion < 2) ? nCount : "nCount"
2005 Loop %N%
2006 {
2007 Location := NumGet(ci, 76*(A_Index-1)+44)
2008 nSize := DllCall("WideCharToMultiByte", "uint", 0, "uint", 0, "uint", Location, "int", -1, "uint", 0, "int", 0, "uint", 0, "uint", 0)
2009 VarSetCapacity(sString, nSize)
2010 DllCall("WideCharToMultiByte", "uint", 0, "uint", 0, "uint", Location, "int", -1, "str", sString, "int", nSize, "uint", 0, "uint", 0)
2011 If !InStr(sString, "*" Extension)
2012 Continue
2013
2014 pCodec := &ci+76*(A_Index-1)
2015 Break
2016 }
2017 }
2018
2019 If !pCodec
2020 Return -3
2021
2022 If (Quality!=75)
2023 {
2024 Quality := (Quality < 0) ? 0 : (Quality > 100) ? 100 : Quality
2025 If (quality>90 && toBase64=1)
2026 Quality := 90
2027
2028 If RegExMatch(Extension, "^\.(?i:JPG|JPEG|JPE|JFIF)$")
2029 {
2030 DllCall("gdiplus\GdipGetEncoderParameterListSize", Ptr, pBitmap, Ptr, pCodec, "uint*", nSize)
2031 VarSetCapacity(EncoderParameters, nSize, 0)
2032 DllCall("gdiplus\GdipGetEncoderParameterList", Ptr, pBitmap, Ptr, pCodec, "uint", nSize, Ptr, &EncoderParameters)
2033 nCount := NumGet(EncoderParameters, "UInt")
2034 N := (A_AhkVersion < 2) ? nCount : "nCount"
2035 Loop %N%
2036 {
2037 elem := (24+A_PtrSize)*(A_Index-1) + 4 + (pad := A_PtrSize = 8 ? 4 : 0)
2038 If (NumGet(EncoderParameters, elem+16, "UInt") = 1) && (NumGet(EncoderParameters, elem+20, "UInt") = 6)
2039 {
2040 _p := elem+&EncoderParameters-pad-4
2041 NumPut(Quality, NumGet(NumPut(4, NumPut(1, _p+0)+20, "UInt")), "UInt")
2042 Break
2043 }
2044 }
2045 }
2046 }
2047
2048 If (toBase64=1)
2049 {
2050 ; part of the function extracted from ImagePut by iseahound
2051 ; https://www.autohotkey.com/boards/viewtopic.php?f=6&t=76301&sid=bfb7c648736849c3c53f08ea6b0b1309
2052 DllCall("ole32\CreateStreamOnHGlobal", "ptr",0, "int",true, "ptr*",pStream)
2053 _E := DllCall("gdiplus\GdipSaveImageToStream", "ptr",pBitmap, "ptr",pStream, "ptr",pCodec, "uint", _p ? _p : 0)
2054 If _E
2055 Return -6
2056
2057 DllCall("ole32\GetHGlobalFromStream", "ptr",pStream, "uint*",hData)
2058 pData := DllCall("GlobalLock", "ptr",hData, "ptr")
2059 nSize := DllCall("GlobalSize", "uint",pData)
2060
2061 VarSetCapacity(bin, nSize, 0)
2062 DllCall("RtlMoveMemory", "ptr",&bin, "ptr",pData, "uptr",nSize)
2063 DllCall("GlobalUnlock", "ptr",hData)
2064 ObjRelease(pStream)
2065 DllCall("GlobalFree", "ptr",hData)
2066
2067 ; Using CryptBinaryToStringA saves about 2MB in memory.
2068 DllCall("Crypt32.dll\CryptBinaryToStringA", "ptr",&bin, "uint",nSize, "uint",0x40000001, "ptr",0, "uint*",base64Length)
2069 VarSetCapacity(base64, base64Length, 0)
2070 _E := DllCall("Crypt32.dll\CryptBinaryToStringA", "ptr",&bin, "uint",nSize, "uint",0x40000001, "ptr",&base64, "uint*",base64Length)
2071 If !_E
2072 Return -7
2073
2074 VarSetCapacity(bin, 0)
2075 Return StrGet(&base64, base64Length, "CP0")
2076 }
2077
2078 If (!A_IsUnicode)
2079 {
2080 nSize := DllCall("MultiByteToWideChar", "uint", 0, "uint", 0, Ptr, &sOutput, "int", -1, Ptr, 0, "int", 0)
2081 VarSetCapacity(wOutput, nSize*2)
2082 DllCall("MultiByteToWideChar", "uint", 0, "uint", 0, Ptr, &sOutput, "int", -1, Ptr, &wOutput, "int", nSize)
2083 VarSetCapacity(wOutput, -1)
2084 If !VarSetCapacity(wOutput)
2085 Return -4
2086 _E := DllCall("gdiplus\GdipSaveImageToFile", Ptr, pBitmap, Ptr, &wOutput, Ptr, pCodec, "uint", _p ? _p : 0)
2087 } Else
2088 _E := DllCall("gdiplus\GdipSaveImageToFile", Ptr, pBitmap, Ptr, &sOutput, Ptr, pCodec, "uint", _p ? _p : 0)
2089
2090 Return _E ? -5 : 0
2091}
2092
2093;#####################################################################################
2094
2095; Function Gdip_GetPixel
2096; Description Gets the ARGB of a pixel in a bitmap
2097;
2098; pBitmap Pointer to a bitmap
2099; x, y x, y coordinates of the pixel
2100;
2101; return Returns the ARGB value of the pixel
2102
2103Gdip_GetPixel(pBitmap, x, y) {
2104 ARGB := 0
2105 DllCall("gdiplus\GdipBitmapGetPixel", "UPtr", pBitmap, "int", x, "int", y, "uint*", ARGB)
2106 return ARGB
2107 ; should use Format("{1:#x}", ARGB)
2108}
2109
2110Gdip_GetPixelColor(pBitmap, x, y, Format) {
2111 ARGBdec := Gdip_GetPixel(pBitmap, x, y)
2112 If (format=1) ; in ARGB [HEX; 00-FF] with 0x prefix
2113 {
2114 Return Format("{1:#x}", ARGBdec)
2115 } Else If (format=2) ; in RGBA [0-255]
2116 {
2117 Gdip_FromARGB(ARGBdec, A, R, G, B)
2118 Return R "," G "," B "," A
2119 } Else If (format=3) ; in BGR [HEX; 00-FF] with 0x prefix
2120 {
2121 clr := Format("{1:#x}", ARGBdec)
2122 Return "0x" SubStr(clr, -1) SubStr(clr, 7, 2) SubStr(clr, 5, 2)
2123 } Else If (format=4) ; in RGB [HEX; 00-FF] with no prefix
2124 {
2125 Return SubStr(Format("{1:#x}", ARGBdec), 5)
2126 } Else Return ARGBdec
2127}
2128
2129;#####################################################################################
2130
2131; Function Gdip_SetPixel
2132; Description Sets the ARGB of a pixel in a bitmap
2133;
2134; pBitmap Pointer to a bitmap
2135; x, y x, y coordinates of the pixel
2136;
2137; return status enumeration. 0 = success
2138
2139Gdip_SetPixel(pBitmap, x, y, ARGB) {
2140 return DllCall("gdiplus\GdipBitmapSetPixel", "UPtr", pBitmap, "int", x, "int", y, "int", ARGB)
2141}
2142
2143;#####################################################################################
2144
2145; Function Gdip_GetImageWidth
2146; Description Gives the width of a bitmap
2147;
2148; pBitmap Pointer to a bitmap
2149;
2150; return Returns the width in pixels of the supplied bitmap
2151
2152Gdip_GetImageWidth(pBitmap) {
2153 Width := 0
2154 DllCall("gdiplus\GdipGetImageWidth", "UPtr", pBitmap, "uint*", Width)
2155 return Width
2156}
2157
2158;#####################################################################################
2159
2160; Function Gdip_GetImageHeight
2161; Description Gives the height of a bitmap
2162;
2163; pBitmap Pointer to a bitmap
2164;
2165; return Returns the height in pixels of the supplied bitmap
2166
2167Gdip_GetImageHeight(pBitmap) {
2168 Height := 0
2169 DllCall("gdiplus\GdipGetImageHeight", "UPtr", pBitmap, "uint*", Height)
2170 return Height
2171}
2172
2173;#####################################################################################
2174
2175; Function Gdip_GetImageDimensions
2176; Description Gives the width and height of a bitmap
2177;
2178; pBitmap Pointer to a bitmap
2179; Width ByRef variable. This variable will be set to the width of the bitmap
2180; Height ByRef variable. This variable will be set to the height of the bitmap
2181;
2182; return GDI+ status enumeration return value
2183
2184Gdip_GetImageDimensions(pBitmap, ByRef Width, ByRef Height) {
2185 If StrLen(pBitmap)<3
2186 Return -1
2187
2188 Width := 0, Height := 0
2189 E := Gdip_GetImageDimension(pBitmap, Width, Height)
2190 Width := Round(Width)
2191 Height := Round(Height)
2192 return E
2193}
2194
2195Gdip_GetImageDimension(pBitmap, ByRef w, ByRef h) {
2196 Ptr := "UPtr"
2197 return DllCall("gdiplus\GdipGetImageDimension", Ptr, pBitmap, "float*", w, "float*", h)
2198}
2199
2200Gdip_GetImageBounds(pBitmap) {
2201 Ptr := "UPtr"
2202 rData := {}
2203
2204 VarSetCapacity(RectF, 16, 0)
2205 status := DllCall("gdiplus\GdipGetImageBounds", Ptr, pBitmap, Ptr, &RectF, "Int*", 0)
2206
2207 If (!status) {
2208 rData.x := NumGet(&RectF, 0, "float")
2209 , rData.y := NumGet(&RectF, 4, "float")
2210 , rData.w := NumGet(&RectF, 8, "float")
2211 , rData.h := NumGet(&RectF, 12, "float")
2212 } Else {
2213 Return status
2214 }
2215
2216 return rData
2217}
2218
2219Gdip_GetImageFlags(pBitmap) {
2220; Gets a set of flags that indicate certain attributes of this Image object.
2221; Returns an element of the ImageFlags Enumeration that holds a set of single-bit flags.
2222; ImageFlags enumeration
2223 ; None := 0x0000 ; Specifies no format information.
2224 ; ; Low-word: shared with SINKFLAG_x:
2225 ; Scalable := 0x00001 ; the image can be scaled.
2226 ; HasAlpha := 0x00002 ; the pixel data contains alpha values.
2227 ; HasTranslucent := 0x00004 ; the pixel data has alpha values other than 0 (transparent) and 255 (opaque).
2228 ; PartiallyScalable := 0x00008 ; the pixel data is partially scalable with some limitations.
2229 ; ; Low-word: color space definition:
2230 ; ColorSpaceRGB := 0x00010 ; the image is stored using an RGB color space.
2231 ; ColorSpaceCMYK := 0x00020 ; the image is stored using a CMYK color space.
2232 ; ColorSpaceGRAY := 0x00040 ; the image is a grayscale image.
2233 ; ColorSpaceYCBCR := 0x00080 ; the image is stored using a YCBCR color space.
2234 ; ColorSpaceYCCK := 0x00100 ; the image is stored using a YCCK color space.
2235 ; ; Low-word: image size info:
2236 ; HasRealDPI := 0x01000 ; dots per inch information is stored in the image.
2237 ; HasRealPixelSize := 0x02000 ; the pixel size is stored in the image.
2238 ; ; High-word:
2239 ; ReadOnly := 0x10000 ; the pixel data is read-only.
2240 ; Caching := 0x20000 ; the pixel data can be cached for faster access.
2241; function extracted from : https://github.com/flipeador/Library-AutoHotkey/tree/master/graphics
2242; by flipeador
2243
2244 Flags := 0
2245 DllCall("Gdiplus.dll\GdipGetImageFlags", "Ptr", pBitmap, "UInt*", Flags)
2246 Return Flags
2247}
2248
2249Gdip_GetImageRawFormat(pBitmap) {
2250; retrieves the pBitmap [file] format
2251
2252 Static RawFormatsList := {"{B96B3CA9-0728-11D3-9D7B-0000F81EF32E}":"Undefined", "{B96B3CAA-0728-11D3-9D7B-0000F81EF32E}":"MemoryBMP", "{B96B3CAB-0728-11D3-9D7B-0000F81EF32E}":"BMP", "{B96B3CAC-0728-11D3-9D7B-0000F81EF32E}":"EMF", "{B96B3CAD-0728-11D3-9D7B-0000F81EF32E}":"WMF", "{B96B3CAE-0728-11D3-9D7B-0000F81EF32E}":"JPEG", "{B96B3CAF-0728-11D3-9D7B-0000F81EF32E}":"PNG", "{B96B3CB0-0728-11D3-9D7B-0000F81EF32E}":"GIF", "{B96B3CB1-0728-11D3-9D7B-0000F81EF32E}":"TIFF", "{B96B3CB2-0728-11D3-9D7B-0000F81EF32E}":"EXIF", "{B96B3CB5-0728-11D3-9D7B-0000F81EF32E}":"Icon"}
2253 Ptr := "UPtr"
2254 VarSetCapacity(pGuid, 16, 0)
2255 E1 := DllCall("gdiplus\GdipGetImageRawFormat", Ptr, pBitmap, "Ptr", &pGuid)
2256
2257 size := VarSetCapacity(sguid, (38 << !!A_IsUnicode) + 1, 0)
2258 E2 := DllCall("ole32.dll\StringFromGUID2", "ptr", &pguid, "ptr", &sguid, "int", size)
2259 R1 := E2 ? StrGet(&sguid) : E2
2260 R2 := RawFormatsList[R1]
2261 Return R2 ? R2 : R1
2262}
2263
2264Gdip_GetImagePixelFormat(pBitmap, mode:=0) {
2265; Mode options
2266; 0 - in decimal
2267; 1 - in hex
2268; 2 - in human readable format
2269;
2270; PXF01INDEXED = 0x00030101 ; 1 bpp, indexed
2271; PXF04INDEXED = 0x00030402 ; 4 bpp, indexed
2272; PXF08INDEXED = 0x00030803 ; 8 bpp, indexed
2273; PXF16GRAYSCALE = 0x00101004; 16 bpp, grayscale
2274; PXF16RGB555 = 0x00021005 ; 16 bpp; 5 bits for each RGB
2275; PXF16RGB565 = 0x00021006 ; 16 bpp; 5 bits red, 6 bits green, and 5 bits blue
2276; PXF16ARGB1555 = 0x00061007 ; 16 bpp; 1 bit for alpha and 5 bits for each RGB component
2277; PXF24RGB = 0x00021808 ; 24 bpp; 8 bits for each RGB
2278; PXF32RGB = 0x00022009 ; 32 bpp; 8 bits for each RGB, no alpha.
2279; PXF32ARGB = 0x0026200A ; 32 bpp; 8 bits for each RGB and alpha
2280; PXF32PARGB = 0x000E200B ; 32 bpp; 8 bits for each RGB and alpha, pre-mulitiplied
2281; PXF48RGB = 0x0010300C ; 48 bpp; 16 bits for each RGB
2282; PXF64ARGB = 0x0034400D ; 64 bpp; 16 bits for each RGB and alpha
2283; PXF64PARGB = 0x001A400E ; 64 bpp; 16 bits for each RGB and alpha, pre-multiplied
2284
2285; INDEXED [1-bits, 4-bits and 8-bits] pixel formats rely on color palettes.
2286; The color information for the pixels is stored in palettes.
2287; Indexed images always contain a palette - a special table of colors.
2288; Each pixel is an index in this table. Usually a palette contains 256
2289; or less entries. That's why the maximum depth of an indexed pixel is 8 bpp.
2290; Using palettes is a common practice when working with small color depths.
2291
2292; modified by Marius Șucan
2293
2294 Static PixelFormatsList := {0x30101:"1-INDEXED", 0x30402:"4-INDEXED", 0x30803:"8-INDEXED", 0x101004:"16-GRAYSCALE", 0x021005:"16-RGB555", 0x21006:"16-RGB565", 0x61007:"16-ARGB1555", 0x21808:"24-RGB", 0x22009:"32-RGB", 0x26200A:"32-ARGB", 0xE200B:"32-PARGB", 0x10300C:"48-RGB", 0x34400D:"64-ARGB", 0x1A400E:"64-PARGB"}
2295 PixelFormat := 0
2296 E := DllCall("gdiplus\GdipGetImagePixelFormat", "UPtr", pBitmap, "UPtr*", PixelFormat)
2297 If E
2298 Return -1
2299
2300 If (mode=0)
2301 Return PixelFormat
2302
2303 inHEX := Format("{1:#x}", PixelFormat)
2304 If (PixelFormatsList.Haskey(inHEX) && mode=2)
2305 result := PixelFormatsList[inHEX]
2306 Else
2307 result := inHEX
2308 return result
2309}
2310
2311Gdip_GetImageType(pBitmap) {
2312; RETURN VALUES:
2313; UNKNOWN = 0
2314; BITMAP = 1
2315; METAFILE = 2
2316; ERROR = -1
2317 result := 0
2318 E := DllCall("gdiplus\GdipGetImageType", Ptr, pBitmap, "int*", result)
2319 If E
2320 Return -1
2321 Return result
2322}
2323
2324Gdip_GetDPI(pGraphics, ByRef DpiX, ByRef DpiY) {
2325 DpiX := Gdip_GetDpiX(pGraphics)
2326 DpiY := Gdip_GetDpiY(pGraphics)
2327}
2328
2329Gdip_GetDpiX(pGraphics) {
2330 dpix := 0
2331 DllCall("gdiplus\GdipGetDpiX", "UPtr", pGraphics, "float*", dpix)
2332 return Round(dpix)
2333}
2334
2335Gdip_GetDpiY(pGraphics) {
2336 dpiy := 0
2337 DllCall("gdiplus\GdipGetDpiY", "UPtr", pGraphics, "float*", dpiy)
2338 return Round(dpiy)
2339}
2340
2341Gdip_GetImageHorizontalResolution(pBitmap) {
2342 dpix := 0
2343 DllCall("gdiplus\GdipGetImageHorizontalResolution", "UPtr", pBitmap, "float*", dpix)
2344 return Round(dpix)
2345}
2346
2347Gdip_GetImageVerticalResolution(pBitmap) {
2348 dpiy := 0
2349 DllCall("gdiplus\GdipGetImageVerticalResolution", "UPtr", pBitmap, "float*", dpiy)
2350 return Round(dpiy)
2351}
2352
2353Gdip_BitmapSetResolution(pBitmap, dpix, dpiy) {
2354 return DllCall("gdiplus\GdipBitmapSetResolution", "UPtr", pBitmap, "float", dpix, "float", dpiy)
2355}
2356
2357Gdip_BitmapGetDPIResolution(pBitmap, ByRef dpix, ByRef dpiy) {
2358 dpix := dpiy := 0
2359 If StrLen(pBitmap)<3
2360 Return
2361
2362 dpix := Gdip_GetImageHorizontalResolution(pBitmap)
2363 dpiy := Gdip_GetImageVerticalResolution(pBitmap)
2364}
2365
2366Gdip_CreateBitmapFromGraphics(pGraphics, Width, Height) {
2367 Ptr := "UPtr"
2368 PtrA := "UPtr*"
2369 pBitmap := 0
2370 DllCall("gdiplus\GdipCreateBitmapFromGraphics", "int", Width, "int", Height, Ptr, pGraphics, PtrA, pBitmap)
2371 Return pBitmap
2372}
2373
2374Gdip_CreateBitmapFromFile(sFile, IconNumber:=1, IconSize:="", useICM:=0) {
2375 Ptr := "UPtr"
2376 PtrA := "UPtr*"
2377 pBitmap := 0
2378 pBitmapOld := 0
2379 hIcon := 0
2380
2381 SplitPath sFile,,, Extension
2382 if RegExMatch(Extension, "^(?i:exe|dll)$")
2383 {
2384 Sizes := IconSize ? IconSize : 256 "|" 128 "|" 64 "|" 48 "|" 32 "|" 16
2385 BufSize := 16 + (2*A_PtrSize)
2386
2387 VarSetCapacity(buf, BufSize, 0)
2388 For eachSize, Size in StrSplit( Sizes, "|" )
2389 {
2390 DllCall("PrivateExtractIcons", "str", sFile, "int", IconNumber-1, "int", Size, "int", Size, PtrA, hIcon, PtrA, 0, "uint", 1, "uint", 0)
2391 if !hIcon
2392 continue
2393
2394 if !DllCall("GetIconInfo", Ptr, hIcon, Ptr, &buf)
2395 {
2396 DestroyIcon(hIcon)
2397 continue
2398 }
2399
2400 hbmMask := NumGet(buf, 12 + (A_PtrSize - 4))
2401 hbmColor := NumGet(buf, 12 + (A_PtrSize - 4) + A_PtrSize)
2402 if !(hbmColor && DllCall("GetObject", Ptr, hbmColor, "int", BufSize, Ptr, &buf))
2403 {
2404 DestroyIcon(hIcon)
2405 continue
2406 }
2407 break
2408 }
2409 if !hIcon
2410 return -1
2411
2412 Width := NumGet(buf, 4, "int"), Height := NumGet(buf, 8, "int")
2413 hbm := CreateDIBSection(Width, -Height), hdc := CreateCompatibleDC(), obm := SelectObject(hdc, hbm)
2414 if !DllCall("DrawIconEx", Ptr, hdc, "int", 0, "int", 0, Ptr, hIcon, "uint", Width, "uint", Height, "uint", 0, Ptr, 0, "uint", 3)
2415 {
2416 DestroyIcon(hIcon)
2417 return -2
2418 }
2419
2420 VarSetCapacity(dib, 104)
2421 DllCall("GetObject", Ptr, hbm, "int", A_PtrSize = 8 ? 104 : 84, Ptr, &dib) ; sizeof(DIBSECTION) = 76+2*(A_PtrSize=8?4:0)+2*A_PtrSize
2422 Stride := NumGet(dib, 12, "Int")
2423 Bits := NumGet(dib, 20 + (A_PtrSize = 8 ? 4 : 0)) ; padding
2424 pBitmapOld := Gdip_CreateBitmap(Width, Height, 0, Stride, Bits)
2425 pBitmap := Gdip_CreateBitmap(Width, Height)
2426 _G := Gdip_GraphicsFromImage(pBitmap)
2427 Gdip_DrawImage(_G, pBitmapOld, 0, 0, Width, Height, 0, 0, Width, Height)
2428 SelectObject(hdc, obm), DeleteObject(hbm), DeleteDC(hdc)
2429 Gdip_DeleteGraphics(_G), Gdip_DisposeImage(pBitmapOld)
2430 DestroyIcon(hIcon)
2431 } else
2432 {
2433 function2call := (useICM=1) ? "GdipCreateBitmapFromFileICM" : "GdipCreateBitmapFromFile"
2434 if (!A_IsUnicode)
2435 {
2436 VarSetCapacity(wFile, 1024)
2437 DllCall("kernel32\MultiByteToWideChar", "uint", 0, "uint", 0, Ptr, &sFile, "int", -1, Ptr, &wFile, "int", 512)
2438 DllCall("gdiplus\" function2call, Ptr, &wFile, PtrA, pBitmap)
2439 } else
2440 DllCall("gdiplus\" function2call, Ptr, &sFile, PtrA, pBitmap)
2441 }
2442
2443 return pBitmap
2444}
2445
2446Gdip_CreateARGBBitmapFromHBITMAP(hImage) {
2447; function by iseahound found on:
2448; https://www.autohotkey.com/boards/viewtopic.php?f=6&t=63345
2449; part of https://github.com/iseahound/Graphics/blob/master/lib/Graphics.ahk
2450
2451 ; struct BITMAP - https://docs.microsoft.com/en-us/windows/desktop/api/wingdi/ns-wingdi-tagbitmap
2452 DllCall("GetObject"
2453 , "ptr", hImage
2454 , "int", VarSetCapacity(dib, 76+2*(A_PtrSize=8?4:0)+2*A_PtrSize)
2455 , "ptr", &dib) ; sizeof(DIBSECTION) = x86:84, x64:104
2456 width := NumGet(dib, 4, "uint")
2457 height := NumGet(dib, 8, "uint")
2458 bpp := NumGet(dib, 18, "ushort")
2459
2460 ; Fallback to built-in method if pixels are not ARGB.
2461 if (bpp!=32)
2462 return Gdip_CreateBitmapFromHBITMAP(hImage)
2463
2464 ; Create a handle to a device context and associate the hImage.
2465 hdc := CreateCompatibleDC()
2466 obm := SelectObject(hdc, hImage)
2467
2468 ; Buffer the hImage with a top-down device independent bitmap via negative height.
2469 ; Note that a DIB is an hBitmap, pixels are formatted as pARGB, and has a pointer to the bits.
2470 cdc := CreateCompatibleDC(hdc)
2471 hbm := CreateDIBSection(width, -height, hdc, 32, pBits)
2472 ob2 := SelectObject(cdc, hbm)
2473
2474 ; Create a new Bitmap (different from an hBitmap) which holds ARGB pixel values.
2475 pBitmap := Gdip_CreateBitmap(width, height)
2476
2477 ; Create a Scan0 buffer pointing to pBits. The buffer has pixel format pARGB.
2478 CreateRect(Rect, 0, 0, width, height)
2479 VarSetCapacity(BitmapData, 16+2*A_PtrSize, 0)
2480 , NumPut( width, BitmapData, 0, "uint") ; Width
2481 , NumPut( height, BitmapData, 4, "uint") ; Height
2482 , NumPut( 4 * width, BitmapData, 8, "int") ; Stride
2483 , NumPut( 0xE200B, BitmapData, 12, "int") ; PixelFormat
2484 , NumPut( pBits, BitmapData, 16, "ptr") ; Scan0
2485 DllCall("gdiplus\GdipBitmapLockBits"
2486 , "ptr", pBitmap
2487 , "ptr", &Rect
2488 , "uint", 6 ; ImageLockMode.UserInputBuffer | ImageLockMode.WriteOnly
2489 , "int", 0xE200B ; Format32bppPArgb
2490 , "ptr", &BitmapData)
2491
2492 ; Ensure that our hBitmap (hImage) is top-down by copying it to a top-down bitmap.
2493 BitBlt(cdc, 0, 0, width, height, hdc, 0, 0)
2494
2495 ; Convert the pARGB pixels copied into the device independent bitmap (hbm) to ARGB.
2496 DllCall("gdiplus\GdipBitmapUnlockBits", "ptr",pBitmap, "ptr",&BitmapData)
2497
2498 ; Cleanup the buffer and device contexts.
2499 SelectObject(cdc, ob2)
2500 DeleteObject(hbm), DeleteDC(cdc)
2501 SelectObject(hdc, obm), DeleteDC(hdc)
2502
2503 return pBitmap
2504}
2505
2506Gdip_CreateBitmapFromHBITMAP(hBitmap, hPalette:=0) {
2507; Creates a Bitmap GDI+ object from a GDI bitmap handle.
2508; hPalette - Handle to a GDI palette used to define the bitmap colors
2509; if the hBitmap is a device-dependent bitmap [DDB].
2510
2511 Ptr := "UPtr"
2512 pBitmap := 0
2513 DllCall("gdiplus\GdipCreateBitmapFromHBITMAP", Ptr, hBitmap, Ptr, hPalette, "UPtr*", pBitmap)
2514 return pBitmap
2515}
2516
2517Gdip_CreateHBITMAPFromBitmap(pBitmap, Background:=0xffffffff) {
2518; background should be zero, to not alter alpha channel of the image
2519 hBitmap := 0
2520 DllCall("gdiplus\GdipCreateHBITMAPFromBitmap", "UPtr", pBitmap, "UPtr*", hBitmap, "int", Background)
2521 return hBitmap
2522}
2523
2524Gdip_CreateARGBHBITMAPFromBitmap(ByRef pBitmap) {
2525 ; function by iseahound ; source: https://github.com/mmikeww/AHKv2-Gdip
2526 ; modified to rely on already present functions [within the library]
2527
2528 ; This version is about 25% faster than Gdip_CreateHBITMAPFromBitmap().
2529 ; Get Bitmap width and height.
2530
2531 Gdip_GetImageDimensions(pBitmap, Width, Height)
2532
2533 ; Convert the source pBitmap into a hBitmap manually.
2534 ; struct BITMAPINFOHEADER - https://docs.microsoft.com/en-us/windows/win32/api/wingdi/ns-wingdi-bitmapinfoheader
2535 hdc := CreateCompatibleDC()
2536 hbm := CreateDIBSection(width, -height, hdc, 32, pBits)
2537 obm := SelectObject(hdc, hbm)
2538
2539 ; Transfer data from source pBitmap to an hBitmap manually.
2540 CreateRect(Rect, 0, 0, width, height)
2541 VarSetCapacity(BitmapData, 16+2*A_PtrSize, 0) ; sizeof(BitmapData) = 24, 32
2542 , NumPut( width, BitmapData, 0, "uint") ; Width
2543 , NumPut( height, BitmapData, 4, "uint") ; Height
2544 , NumPut( 4 * width, BitmapData, 8, "int") ; Stride
2545 , NumPut( 0xE200B, BitmapData, 12, "int") ; PixelFormat
2546 , NumPut( pBits, BitmapData, 16, "ptr") ; Scan0
2547 DllCall("gdiplus\GdipBitmapLockBits"
2548 , "ptr", pBitmap
2549 , "ptr", &Rect
2550 , "uint", 5 ; ImageLockMode.UserInputBuffer | ImageLockMode.ReadOnly
2551 , "int", 0xE200B ; Format32bppPArgb
2552 , "ptr", &BitmapData) ; Contains the pointer (pBits) to the hbm.
2553 DllCall("gdiplus\GdipBitmapUnlockBits", "ptr", pBitmap, "ptr", &BitmapData)
2554
2555 ; Cleanup the hBitmap and device contexts.
2556 SelectObject(hdc, obm)
2557 DeleteObject(hdc)
2558 return hbm
2559}
2560
2561Gdip_CreateBitmapFromHICON(hIcon) {
2562 pBitmap := 0
2563 DllCall("gdiplus\GdipCreateBitmapFromHICON", "UPtr", hIcon, "UPtr*", pBitmap)
2564 return pBitmap
2565}
2566
2567Gdip_CreateHICONFromBitmap(pBitmap) {
2568 hIcon := 0
2569 DllCall("gdiplus\GdipCreateHICONFromBitmap", "UPtr", pBitmap, "UPtr*", hIcon)
2570 return hIcon
2571}
2572
2573Gdip_CreateBitmap(Width, Height, PixelFormat:=0, Stride:=0, Scan0:=0) {
2574; By default, this function creates a new 32-ARGB bitmap.
2575; modified by Marius Șucan
2576
2577 pBitmap := 0
2578 If !PixelFormat
2579 PixelFormat := 0x26200A ; 32-ARGB
2580
2581 DllCall("gdiplus\GdipCreateBitmapFromScan0"
2582 , "int", Width
2583 , "int", Height
2584 , "int", Stride
2585 , "int", PixelFormat
2586 , "UPtr", Scan0
2587 , "UPtr*", pBitmap)
2588 Return pBitmap
2589}
2590
2591Gdip_CreateBitmapFromClipboard() {
2592; modified by Marius Șucan
2593
2594 Ptr := "UPtr"
2595 pid := DllCall("GetCurrentProcessId","uint")
2596 hwnd := WinExist("ahk_pid " . pid)
2597 if !DllCall("IsClipboardFormatAvailable", "uint", 8) ; CF_DIB = 8
2598 {
2599 if DllCall("IsClipboardFormatAvailable", "uint", 2) ; CF_BITMAP = 2
2600 {
2601 if !DllCall("OpenClipboard", Ptr, hwnd)
2602 return -1
2603
2604 hData := DllCall("User32.dll\GetClipboardData", "UInt", 2, "UPtr")
2605 hBitmap := DllCall("User32.dll\CopyImage", "UPtr", hData, "UInt", 0, "Int", 0, "Int", 0, "UInt", 0x2000, "Ptr")
2606 DllCall("CloseClipboard")
2607 return hBitmap
2608 }
2609 return -2
2610 }
2611
2612 if !DllCall("OpenClipboard", Ptr, hwnd)
2613 return -1
2614
2615 hBitmap := DllCall("GetClipboardData", "uint", 2, Ptr)
2616 if !hBitmap
2617 {
2618 DllCall("CloseClipboard")
2619 return -3
2620 }
2621
2622 DllCall("CloseClipboard")
2623 pBitmap := Gdip_CreateARGBBitmapFromHBITMAP(hBitmap)
2624 If hBitmap
2625 DeleteObject(hBitmap)
2626
2627 if !pBitmap
2628 return -4
2629
2630 return pBitmap
2631}
2632
2633Gdip_SetBitmapToClipboard(pBitmap) {
2634; modified by Marius Șucan to have this function report errors
2635
2636 Ptr := "UPtr"
2637 off1 := A_PtrSize = 8 ? 52 : 44
2638 off2 := A_PtrSize = 8 ? 32 : 24
2639
2640 pid := DllCall("GetCurrentProcessId","uint")
2641 hwnd := WinExist("ahk_pid " . pid)
2642 r1 := DllCall("OpenClipboard", Ptr, hwnd)
2643 If !r1
2644 Return -1
2645
2646 hBitmap := Gdip_CreateHBITMAPFromBitmap(pBitmap, 0)
2647 If !hBitmap
2648 {
2649 DllCall("CloseClipboard")
2650 Return -3
2651 }
2652
2653 r2 := DllCall("EmptyClipboard")
2654 If !r2
2655 {
2656 DeleteObject(hBitmap)
2657 DllCall("CloseClipboard")
2658 Return -2
2659 }
2660
2661 DllCall("GetObject", Ptr, hBitmap, "int", VarSetCapacity(oi, A_PtrSize = 8 ? 104 : 84, 0), Ptr, &oi)
2662 hdib := DllCall("GlobalAlloc", "uint", 2, Ptr, 40+NumGet(oi, off1, "UInt"), Ptr)
2663 pdib := DllCall("GlobalLock", Ptr, hdib, Ptr)
2664 DllCall("RtlMoveMemory", Ptr, pdib, Ptr, &oi+off2, Ptr, 40)
2665 DllCall("RtlMoveMemory", Ptr, pdib+40, Ptr, NumGet(oi, off2 - A_PtrSize, Ptr), Ptr, NumGet(oi, off1, "UInt"))
2666 DllCall("GlobalUnlock", Ptr, hdib)
2667 DeleteObject(hBitmap)
2668 r3 := DllCall("SetClipboardData", "uint", 8, Ptr, hdib) ; CF_DIB = 8
2669 DllCall("CloseClipboard")
2670 DllCall("GlobalFree", Ptr, hdib)
2671 E := r3 ? 0 : -4 ; 0 - success
2672 Return E
2673}
2674
2675Gdip_CloneBitmapArea(pBitmap, x:="", y:="", w:=0, h:=0, PixelFormat:=0, KeepPixelFormat:=0) {
2676; The new pBitmap is by default in the 32-ARGB PixelFormat.
2677;
2678; If the specified coordinates exceed the boundaries of pBitmap
2679; the resulted pBitmap is erroneuous / defective.
2680 pBitmapDest := 0
2681 If !PixelFormat
2682 PixelFormat := 0x26200A ; 32-ARGB
2683
2684 If (KeepPixelFormat=1)
2685 PixelFormat := Gdip_GetImagePixelFormat(pBitmap, 1)
2686
2687 If (y="")
2688 y := 0
2689
2690 If (x="")
2691 x := 0
2692
2693 If (!w && !h)
2694 Gdip_GetImageDimensions(pBitmap, w, h)
2695
2696 E := DllCall("gdiplus\GdipCloneBitmapArea"
2697 , "float", x, "float", y
2698 , "float", w, "float", h
2699 , "int", PixelFormat
2700 , "UPtr", pBitmap
2701 , "UPtr*", pBitmapDest)
2702 return pBitmapDest
2703}
2704
2705Gdip_CloneBitmap(pBitmap) {
2706; the new pBitmap will have the same PixelFormat, unchanged.
2707
2708 pBitmapDest := 0
2709 E := DllCall("gdiplus\GdipCloneImage"
2710 , "UPtr", pBitmap
2711 , "UPtr*", pBitmapDest)
2712 return pBitmapDest
2713}
2714
2715Gdip_BitmapSelectActiveFrame(pBitmap, FrameIndex) {
2716; Selects as the active frame the given FrameIndex
2717; within an animated GIF or a multi-paged TIFF.
2718; On succes, it returns the frames count.
2719; On fail, the return value is -1.
2720
2721 Countu := 0
2722 CountFrames := 0
2723 Ptr := "UPtr"
2724 DllCall("gdiplus\GdipImageGetFrameDimensionsCount", Ptr, pBitmap, "UInt*", Countu)
2725 VarSetCapacity(dIDs, 16, 0)
2726 DllCall("gdiplus\GdipImageGetFrameDimensionsList", Ptr, pBitmap, "Uint", &dIDs, "UInt", Countu)
2727 DllCall("gdiplus\GdipImageGetFrameCount", Ptr, pBitmap, "Uint", &dIDs, "UInt*", CountFrames)
2728 If (FrameIndex>CountFrames)
2729 FrameIndex := CountFrames
2730 Else If (FrameIndex<1)
2731 FrameIndex := 0
2732
2733 E := DllCall("gdiplus\GdipImageSelectActiveFrame", Ptr, pBitmap, Ptr, &dIDs, "uint", FrameIndex)
2734 If E
2735 Return -1
2736 Return CountFrames
2737}
2738
2739Gdip_GetBitmapFramesCount(pBitmap) {
2740; The function returns the number of frames or pages a given pBitmap has.
2741; GDI+ only supports multi-frames/pages for GIFs and TIFFs.
2742; Function written by SBC in September 2010 and
2743; extracted from his «Picture Viewer» script.
2744; https://autohotkey.com/board/topic/58226-ahk-picture-viewer/
2745
2746 Countu := 0
2747 CountFrames := 0
2748 Ptr := "UPtr"
2749 DllCall("gdiplus\GdipImageGetFrameDimensionsCount", Ptr, pBitmap, "UInt*", Countu)
2750 VarSetCapacity(dIDs, 16, 0)
2751 DllCall("gdiplus\GdipImageGetFrameDimensionsList", Ptr, pBitmap, "Uint", &dIDs, "UInt", Countu)
2752 DllCall("gdiplus\GdipImageGetFrameCount", Ptr, pBitmap, "Uint", &dIDs, "UInt*", CountFrames)
2753 Return CountFrames
2754}
2755
2756Gdip_CreateCachedBitmap(pBitmap, pGraphics) {
2757; Creates a CachedBitmap object based on a Bitmap object and a pGraphics object. The cached bitmap takes
2758; the pixel data from the Bitmap object and stores it in a format that is optimized for the display device
2759; associated with the pGraphics object.
2760
2761 pCachedBitmap := 0
2762 Ptr := "UPtr"
2763 E := DllCall("gdiplus\GdipCreateCachedBitmap", Ptr, pBitmap, Ptr, pGraphics, "Ptr*", pCachedBitmap)
2764 return pCachedBitmap
2765}
2766
2767Gdip_DeleteCachedBitmap(pCachedBitmap) {
2768 Ptr := "UPtr"
2769 return DllCall("gdiplus\GdipDeleteCachedBitmap", Ptr, pCachedBitmap)
2770}
2771
2772Gdip_DrawCachedBitmap(pGraphics, pCachedBitmap, X, Y) {
2773 Ptr := "UPtr"
2774 return DllCall("gdiplus\GdipDrawCachedBitmap", Ptr, pGraphics, Ptr, pCachedBitmap, "int", X, "int", Y)
2775}
2776
2777Gdip_ImageRotateFlip(pBitmap, RotateFlipType:=1) {
2778; RotateFlipType options:
2779; RotateNoneFlipNone = 0
2780; Rotate90FlipNone = 1
2781; Rotate180FlipNone = 2
2782; Rotate270FlipNone = 3
2783; RotateNoneFlipX = 4
2784; Rotate90FlipX = 5
2785; Rotate180FlipX = 6
2786; Rotate270FlipX = 7
2787; RotateNoneFlipY = Rotate180FlipX
2788; Rotate90FlipY = Rotate270FlipX
2789; Rotate180FlipY = RotateNoneFlipX
2790; Rotate270FlipY = Rotate90FlipX
2791; RotateNoneFlipXY = Rotate180FlipNone
2792; Rotate90FlipXY = Rotate270FlipNone
2793; Rotate180FlipXY = RotateNoneFlipNone
2794; Rotate270FlipXY = Rotate90FlipNone
2795
2796 return DllCall("gdiplus\GdipImageRotateFlip", "UPtr", pBitmap, "int", RotateFlipType)
2797}
2798
2799Gdip_RotateBitmapAtCenter(pBitmap, Angle, pBrush:=0, InterpolationMode:=7, PixelFormat:=0) {
2800; the pBrush will be used to fill the background of the image
2801; by default, it is black.
2802; It returns the pointer to a new pBitmap.
2803
2804 If !Angle
2805 {
2806 newBitmap := Gdip_CloneBitmap(pBitmap)
2807 Return newBitmap
2808 }
2809
2810 Gdip_GetImageDimensions(pBitmap, Width, Height)
2811 Gdip_GetRotatedDimensions(Width, Height, Angle, RWidth, RHeight)
2812 Gdip_GetRotatedTranslation(Width, Height, Angle, xTranslation, yTranslation)
2813 If (RWidth*RHeight>536848912) || (Rwidth>32100) || (RHeight>32100)
2814 Return
2815
2816 If (pBrush=0)
2817 {
2818 pBrush := Gdip_BrushCreateSolid("0xFF000000")
2819 defaultBrush := 1
2820 }
2821
2822 PixelFormatReadable := Gdip_GetImagePixelFormat(pBitmap, 2)
2823 If InStr(PixelFormatReadable, "indexed")
2824 {
2825 hbm := CreateDIBSection(RWidth, RHeight,,24)
2826 hdc := CreateCompatibleDC()
2827 obm := SelectObject(hdc, hbm)
2828 G := Gdip_GraphicsFromHDC(hdc)
2829 indexedMode := 1
2830 } Else
2831 {
2832 newBitmap := Gdip_CreateBitmap(RWidth, RHeight, PixelFormat)
2833 G := Gdip_GraphicsFromImage(newBitmap)
2834 }
2835
2836 Gdip_SetInterpolationMode(G, InterpolationMode)
2837 Gdip_SetSmoothingMode(G, 4)
2838 If StrLen(pBrush)>1
2839 Gdip_FillRectangle(G, pBrush, 0, 0, RWidth, RHeight)
2840 Gdip_TranslateWorldTransform(G, xTranslation, yTranslation)
2841 Gdip_RotateWorldTransform(G, Angle)
2842 Gdip_DrawImageRect(G, pBitmap, 0, 0, Width, Height)
2843
2844 If (indexedMode=1)
2845 {
2846 newBitmap := Gdip_CreateBitmapFromHBITMAP(hbm)
2847 SelectObject(hdc, obm)
2848 DeleteObject(hbm)
2849 DeleteDC(hdc)
2850 }
2851
2852 Gdip_DeleteGraphics(G)
2853 If (defaultBrush=1)
2854 Gdip_DeleteBrush(pBrush)
2855
2856 Return newBitmap
2857}
2858
2859Gdip_ResizeBitmap(pBitmap, givenW, givenH, KeepRatio, InterpolationMode:="", KeepPixelFormat:=0, checkTooLarge:=0) {
2860; KeepPixelFormat can receive a specific PixelFormat.
2861; The function returns a pointer to a new pBitmap.
2862; Default is 0 = 32-ARGB
2863
2864 Gdip_GetImageDimensions(pBitmap, Width, Height)
2865 If (KeepRatio=1)
2866 {
2867 calcIMGdimensions(Width, Height, givenW, givenH, ResizedW, ResizedH)
2868 } Else
2869 {
2870 ResizedW := givenW
2871 ResizedH := givenH
2872 }
2873
2874 If (((ResizedW*ResizedH>536848912) || (ResizedW>32100) || (ResizedH>32100)) && checkTooLarge=1)
2875 Return
2876
2877 PixelFormatReadable := Gdip_GetImagePixelFormat(pBitmap, 2)
2878 If (KeepPixelFormat=1)
2879 PixelFormat := Gdip_GetImagePixelFormat(pBitmap, 1)
2880 If Strlen(KeepPixelFormat)>3
2881 PixelFormat := KeepPixelFormat
2882
2883 If InStr(PixelFormatReadable, "indexed")
2884 {
2885 hbm := CreateDIBSection(ResizedW, ResizedH,,24)
2886 hdc := CreateCompatibleDC()
2887 obm := SelectObject(hdc, hbm)
2888 G := Gdip_GraphicsFromHDC(hdc, InterpolationMode, 4)
2889 Gdip_DrawImageRect(G, pBitmap, 0, 0, ResizedW, ResizedH)
2890 newBitmap := Gdip_CreateBitmapFromHBITMAP(hbm)
2891 If (KeepPixelFormat=1)
2892 Gdip_BitmapSetColorDepth(newBitmap, SubStr(PixelFormatReadable, 1, 1), 1)
2893 SelectObject(hdc, obm)
2894 DeleteObject(hbm)
2895 DeleteDC(hdc)
2896 Gdip_DeleteGraphics(G)
2897 } Else
2898 {
2899 newBitmap := Gdip_CreateBitmap(ResizedW, ResizedH, PixelFormat)
2900 G := Gdip_GraphicsFromImage(newBitmap, InterpolationMode)
2901 Gdip_DrawImageRect(G, pBitmap, 0, 0, ResizedW, ResizedH)
2902 Gdip_DeleteGraphics(G)
2903 }
2904
2905 Return newBitmap
2906}
2907
2908;#####################################################################################
2909; pPen functions
2910; With Gdip_SetPenBrushFill() or Gdip_CreatePenFromBrush() functions,
2911; pPen objects can have gradients or textures.
2912;#####################################################################################
2913
2914Gdip_CreatePen(ARGB, w, Unit:=2) {
2915 pPen := 0
2916 E := DllCall("gdiplus\GdipCreatePen1", "UInt", ARGB, "float", w, "int", Unit, "UPtr*", pPen)
2917 return pPen
2918}
2919
2920Gdip_CreatePenFromBrush(pBrush, w, Unit:=2) {
2921; Unit - Unit of measurement for the pen size:
2922; 0 - World coordinates, a non-physical unit
2923; 1 - Display units
2924; 2 - A unit is 1 pixel [default]
2925; 3 - A unit is 1 point or 1/72 inch
2926; 4 - A unit is 1 inch
2927; 5 - A unit is 1/300 inch
2928; 6 - A unit is 1 millimeter
2929
2930 pPen := 0
2931 E := DllCall("gdiplus\GdipCreatePen2", "UPtr", pBrush, "float", w, "int", 2, "UPtr*", pPen, "int", Unit)
2932 return pPen
2933}
2934
2935Gdip_SetPenWidth(pPen, width) {
2936 return DllCall("gdiplus\GdipSetPenWidth", "UPtr", pPen, "float", width)
2937}
2938
2939Gdip_GetPenWidth(pPen) {
2940 width := 0
2941 E := DllCall("gdiplus\GdipGetPenWidth", "UPtr", pPen, "float*", width)
2942 If E
2943 return -1
2944 return width
2945}
2946
2947Gdip_GetPenDashStyle(pPen) {
2948 DashStyle := 0
2949 E := DllCall("gdiplus\GdipGetPenDashStyle", "UPtr", pPen, "float*", DashStyle)
2950 If E
2951 return -1
2952 return DashStyle
2953}
2954
2955Gdip_SetPenColor(pPen, ARGB) {
2956 return DllCall("gdiplus\GdipSetPenColor", "UPtr", pPen, "UInt", ARGB)
2957}
2958
2959Gdip_GetPenColor(pPen) {
2960 ARGB := 0
2961 E := DllCall("gdiplus\GdipGetPenColor", "UPtr", pPen, "UInt*", ARGB)
2962 If E
2963 return -1
2964 return Format("{1:#x}", ARGB)
2965}
2966
2967Gdip_SetPenBrushFill(pPen, pBrush) {
2968 return DllCall("gdiplus\GdipSetPenBrushFill", "UPtr", pPen, "UPtr", pBrush)
2969}
2970
2971Gdip_ResetPenTransform(pPen) {
2972 Ptr := "UPtr"
2973 Return DllCall("gdiplus\GdipResetPenTransform", Ptr, pPen)
2974}
2975
2976Gdip_MultiplyPenTransform(pPen, hMatrix, matrixOrder:=0) {
2977 Ptr := "UPtr"
2978 Return DllCall("gdiplus\GdipMultiplyPenTransform", Ptr, pPen, Ptr, hMatrix, "int", matrixOrder)
2979}
2980
2981Gdip_RotatePenTransform(pPen, Angle, matrixOrder:=0) {
2982 Ptr := "UPtr"
2983 Return DllCall("gdiplus\GdipRotatePenTransform", Ptr, pPen, "float", Angle, "int", matrixOrder)
2984}
2985
2986Gdip_ScalePenTransform(pPen, ScaleX, ScaleY, matrixOrder:=0) {
2987 Ptr := "UPtr"
2988 Return DllCall("gdiplus\GdipScalePenTransform", Ptr, pPen, "float", ScaleX, "float", ScaleY, "int", matrixOrder)
2989}
2990
2991Gdip_TranslatePenTransform(pPen, X, Y, matrixOrder:=0) {
2992 Ptr := "UPtr"
2993 Return DllCall("gdiplus\GdipTranslatePenTransform", Ptr, pPen, "float", X, "float", Y, "int", matrixOrder)
2994}
2995
2996Gdip_SetPenTransform(pPen, pMatrix) {
2997 Ptr := "UPtr"
2998 return DllCall("gdiplus\GdipSetPenTransform", Ptr, pPen, Ptr, pMatrix)
2999}
3000
3001Gdip_GetPenTransform(pPen) {
3002 Ptr := "UPtr"
3003 pMatrix := 0
3004 DllCall("gdiplus\GdipGetPenTransform", Ptr, pPen, "UPtr*", pMatrix)
3005 Return pMatrix
3006}
3007
3008Gdip_GetPenBrushFill(pPen) {
3009; Gets the pBrush object that is currently set for the pPen object
3010 Ptr := "UPtr"
3011 pBrush := 0
3012 E := DllCall("gdiplus\GdipGetPenBrushFill", Ptr, pPen, "int*", pBrush)
3013 Return pBrush
3014}
3015
3016Gdip_GetPenFillType(pPen) {
3017; Description: Gets the type of brush fill currently set for a Pen object
3018; Return values:
3019; 0 - The pen draws with a solid color
3020; 1 - The pen draws with a hatch pattern that is specified by a HatchBrush object
3021; 2 - The pen draws with a texture that is specified by a TextureBrush object
3022; 3 - The pen draws with a color gradient that is specified by a PathGradientBrush object
3023; 4 - The pen draws with a color gradient that is specified by a LinearGradientBrush object
3024; -1 - The pen type is unknown
3025; -2 - Error
3026
3027 Ptr := "UPtr"
3028 result := 0
3029 E := DllCall("gdiplus\GdipGetPenFillType", Ptr, pPen, "int*", result)
3030 If E
3031 return -2
3032 Return result
3033}
3034
3035Gdip_GetPenStartCap(pPen) {
3036 result := 0
3037 Ptr := "UPtr"
3038 E := DllCall("gdiplus\GdipGetPenStartCap", Ptr, pPen, "int*", result)
3039 If E
3040 return -1
3041 Return result
3042}
3043
3044Gdip_GetPenEndCap(pPen) {
3045 result := 0
3046 Ptr := "UPtr"
3047 E := DllCall("gdiplus\GdipGetPenEndCap", Ptr, pPen, "int*", result)
3048 If E
3049 return -1
3050 Return result
3051}
3052
3053Gdip_GetPenDashCaps(pPen) {
3054 result := 0
3055 Ptr := "UPtr"
3056 E := DllCall("gdiplus\GdipGetPenDashCap197819", Ptr, pPen, "int*", result)
3057 If E
3058 return -1
3059 Return result
3060}
3061
3062Gdip_GetPenAlignment(pPen) {
3063 result := 0
3064 Ptr := "UPtr"
3065 E := DllCall("gdiplus\GdipGetPenMode", Ptr, pPen, "int*", result)
3066 If E
3067 return -1
3068 Return result
3069}
3070
3071;#####################################################################################
3072; Function - Gdip_SetPenLineCaps
3073; Description - Sets the cap styles for the start, end, and dashes in a line drawn with the pPen object
3074; Parameters
3075; pPen - Pointer to a Pen object. Start and end caps do not apply to closed lines.
3076; - StartCap - Line cap style for the start cap:
3077; 0x00 - Line ends at the last point. The end is squared off
3078; 0x01 - Square cap. The center of the square is the last point in the line. The height and width of the square are the line width.
3079; 0x02 - Circular cap. The center of the circle is the last point in the line. The diameter of the circle is the line width.
3080; 0x03 - Triangular cap. The base of the triangle is the last point in the line. The base of the triangle is the line width.
3081; 0x10 - Line ends are not anchored.
3082; 0x11 - Line ends are anchored with a square. The center of the square is the last point in the line. The height and width of the square are the line width.
3083; 0x12 - Line ends are anchored with a circle. The center of the circle is at the last point in the line. The circle is wider than the line.
3084; 0x13 - Line ends are anchored with a diamond (a square turned at 45 degrees). The center of the diamond is at the last point in the line. The diamond is wider than the line.
3085; 0x14 - Line ends are anchored with arrowheads. The arrowhead point is located at the last point in the line. The arrowhead is wider than the line.
3086; 0xff - Line ends are made from a CustomLineCap object.
3087; EndCap - Line cap style for the end cap (same values as StartCap)
3088; DashCap - Start and end caps for a dashed line:
3089; 0 - A square cap that squares off both ends of each dash
3090; 2 - A circular cap that rounds off both ends of each dash
3091; 3 - A triangular cap that points both ends of each dash
3092; Return value: status enumeration
3093
3094Gdip_SetPenLineCaps(pPen, StartCap, EndCap, DashCap) {
3095 Ptr := "UPtr"
3096 Return DllCall("gdiplus\GdipSetPenLineCap197819", Ptr, pPen, "int", StartCap, "int", EndCap, "int", DashCap)
3097}
3098
3099Gdip_SetPenStartCap(pPen, LineCap) {
3100 Ptr := "UPtr"
3101 Return DllCall("gdiplus\GdipSetPenStartCap", Ptr, pPen, "int", LineCap)
3102}
3103
3104Gdip_SetPenEndCap(pPen, LineCap) {
3105 Ptr := "UPtr"
3106 Return DllCall("gdiplus\GdipSetPenEndCap", Ptr, pPen, "int", LineCap)
3107}
3108
3109Gdip_SetPenDashCaps(pPen, LineCap) {
3110; If you set the alignment of a Pen object to
3111; Pen Alignment Inset, you cannot use that pen
3112; to draw triangular dash caps.
3113
3114 Ptr := "UPtr"
3115 Return DllCall("gdiplus\GdipSetPenDashCap197819", Ptr, pPen, "int", LineCap)
3116}
3117
3118Gdip_SetPenAlignment(pPen, Alignment) {
3119; Specifies the alignment setting of the pen relative to the line that is drawn. The default value is Center.
3120; If you set the alignment of a Pen object to Inset, you cannot use that pen to draw compound lines or triangular dash caps.
3121; Alignment options:
3122; 0 [Center] - Specifies that the pen is aligned on the center of the line that is drawn.
3123; 1 [Inset] - Specifies, when drawing a polygon, that the pen is aligned on the inside of the edge of the polygon.
3124
3125 Ptr := "UPtr"
3126 Return DllCall("gdiplus\GdipSetPenMode", Ptr, pPen, "int", Alignment)
3127}
3128
3129Gdip_GetPenCompoundCount(pPen) {
3130 result := 0
3131 E := DllCall("gdiplus\GdipGetPenCompoundCount", Ptr, pPen, "int*", result)
3132 If E
3133 Return -1
3134 Return result
3135}
3136
3137Gdip_SetPenCompoundArray(pPen, inCompounds) {
3138; Parameters - pPen - Pointer to a pPen object
3139; inCompounds - A string of compound values:
3140; "value1|value2|value3" [and so on]
3141; ExampleCompounds := "0.0|0.2|0.7|1.0"
3142; Remarks - The elements in the string array must be in increasing order, between 0 and not greater than 1.
3143; Suppose you want a pen to draw two parallel lines where the width of the first line is 20 percent of the pen's
3144; width, the width of the space that separates the two lines is 50 percent of the pen's width, and the width
3145; of the second line is 30 percent of the pen's width. Start by creating a pPen object and an array of compound
3146; values. For this, you can then set the compound array by passing the array with the values "0.0|0.2|0.7|1.0".
3147; Return status enumeration
3148
3149 arrCompounds := StrSplit(inCompounds, "|")
3150 totalCompounds := arrCompounds.Length()
3151 VarSetCapacity(pCompounds, 8 * totalCompounds, 0)
3152 Loop %totalCompounds%
3153 NumPut(arrCompounds[A_Index], &pCompounds, 4*(A_Index - 1), "float")
3154
3155 Ptr := "UPtr"
3156 Return DllCall("gdiplus\GdipSetPenCompoundArray", Ptr, pPen, Ptr, &pCompounds, "int", totalCompounds)
3157}
3158
3159Gdip_SetPenDashStyle(pPen, DashStyle) {
3160; DashStyle options:
3161; Solid = 0
3162; Dash = 1
3163; Dot = 2
3164; DashDot = 3
3165; DashDotDot = 4
3166; Custom = 5
3167; https://technet.microsoft.com/pt-br/ms534104(v=vs.71).aspx
3168; function by IPhilip
3169 Ptr := "UPtr"
3170 Return DllCall("gdiplus\GdipSetPenDashStyle", Ptr, pPen, "Int", DashStyle)
3171}
3172
3173Gdip_SetPenDashArray(pPen, Dashes) {
3174; Description Sets custom dashes and spaces for the pPen object.
3175;
3176; Parameters pPen - Pointer to a Pen object
3177; Dashes - The string that specifies the length of the custom dashes and spaces:
3178; Format: "dL1,sL1,dL2,sL2,dL3,sL3" [... and so on]
3179; dLn - Dash N length
3180; sLn - Space N length
3181; ExampleDashesArgument := "3,6,8,4,2,1"
3182;
3183; Remarks This function sets the dash style for the pPen object to DashStyleCustom (6).
3184; Return status enumeration.
3185
3186 Ptr := "UPtr"
3187 Points := StrSplit(Dashes, ",")
3188 PointsCount := Points.Length()
3189 VarSetCapacity(PointsF, 8 * PointsCount, 0)
3190 Loop %PointsCount%
3191 NumPut(Points[A_Index], &PointsF, 4*(A_Index - 1), "float")
3192
3193 Return DllCall("gdiplus\GdipSetPenDashArray", Ptr, pPen, Ptr, &PointsF, "int", PointsCount)
3194}
3195
3196Gdip_SetPenDashOffset(pPen, Offset) {
3197; Sets the distance from the start of the line to the start of the first space in a dashed line
3198; Offset - Real number that specifies the number of times to shift the spaces in a dashed line. Each shift is
3199; equal to the length of a space in the dashed line
3200
3201 Ptr := "UPtr"
3202 Return DllCall("gdiplus\GdipSetPenDashOffset", Ptr, pPen, "float", Offset)
3203}
3204
3205Gdip_GetPenDashArray(pPen) {
3206 iCount := Gdip_GetPenDashCount(pPen)
3207 If (iCount=-1)
3208 Return 0
3209
3210 VarSetCapacity(PointsF, 8 * iCount, 0)
3211 Ptr := "UPtr"
3212 DllCall("gdiplus\GdipGetPenDashArray", Ptr, pPen, "uPtr", &PointsF, "int", iCount)
3213
3214 Loop %iCount%
3215 {
3216 A := NumGet(&PointsF, 4*(A_Index-1), "float")
3217 printList .= A ","
3218 }
3219
3220 Return Trim(printList, ",")
3221}
3222
3223Gdip_GetPenCompoundArray(pPen) {
3224 iCount := Gdip_GetPenCompoundCount(pPen)
3225 VarSetCapacity(PointsF, 4 * iCount, 0)
3226 Ptr := "UPtr"
3227 DllCall("gdiplus\GdipGetPenCompoundArray", Ptr, pPen, "uPtr", &PointsF, "int", iCount)
3228
3229 Loop %iCount%
3230 {
3231 A := NumGet(&PointsF, 4*(A_Index-1), "float")
3232 printList .= A "|"
3233 }
3234
3235 Return Trim(printList, "|")
3236}
3237
3238Gdip_SetPenLineJoin(pPen, LineJoin) {
3239; LineJoin - Line join style:
3240; MITER = 0 - it produces a sharp corner or a clipped corner, depending on whether the length of the miter exceeds the miter limit.
3241; BEVEL = 1 - it produces a diagonal corner.
3242; ROUND = 2 - it produces a smooth, circular arc between the lines.
3243; MITERCLIPPED = 3 - it produces a sharp corner or a beveled corner, depending on whether the length of the miter exceeds the miter limit.
3244
3245 Ptr := "UPtr"
3246 Return DllCall("gdiplus\GdipSetPenLineJoin", Ptr, pPen, "int", LineJoin)
3247}
3248
3249Gdip_SetPenMiterLimit(pPen, MiterLimit) {
3250; MiterLimit - Real number that specifies the miter limit of the Pen object. A real number value that is less
3251; than 1.0 will be replaced with 1.0,
3252;
3253; Remarks
3254; The miter length is the distance from the intersection of the line walls on the inside of the join to the
3255; intersection of the line walls outside of the join. The miter length can be large when the angle between two
3256; lines is small. The miter limit is the maximum allowed ratio of miter length to stroke width. The default
3257; value is 10.0.
3258; If the miter length of the join of the intersection exceeds the limit of the join, then the join will be
3259; beveled to keep it within the limit of the join of the intersection
3260
3261 Ptr := "UPtr"
3262 Return DllCall("gdiplus\GdipSetPenMiterLimit", Ptr, pPen, "float", MiterLimit)
3263}
3264
3265Gdip_SetPenUnit(pPen, Unit) {
3266; Sets the unit of measurement for a pPen object.
3267; Unit - New unit of measurement for the pen:
3268; 0 - World coordinates, a non-physical unit
3269; 1 - Display units
3270; 2 - A unit is 1 pixel
3271; 3 - A unit is 1 point or 1/72 inch
3272; 4 - A unit is 1 inch
3273; 5 - A unit is 1/300 inch
3274; 6 - A unit is 1 millimeter
3275
3276 Ptr := "UPtr"
3277 Return DllCall("gdiplus\GdipSetPenUnit", Ptr, pPen, "int", Unit)
3278}
3279
3280Gdip_GetPenDashCount(pPen) {
3281 result := 0
3282 E := DllCall("gdiplus\GdipGetPenDashCount", Ptr, pPen, "int*", result)
3283 If E
3284 Return -1
3285 Return result
3286}
3287
3288Gdip_GetPenDashOffset(pPen) {
3289 result := 0
3290 E := DllCall("gdiplus\GdipGetPenDashOffset", Ptr, pPen, "float*", result)
3291 If E
3292 Return -1
3293 Return result
3294}
3295
3296Gdip_GetPenLineJoin(pPen) {
3297 result := 0
3298 E := DllCall("gdiplus\GdipGetPenLineJoin", Ptr, pPen, "int*", result)
3299 If E
3300 Return -1
3301 Return result
3302}
3303
3304Gdip_GetPenMiterLimit(pPen) {
3305 result := 0
3306 E := DllCall("gdiplus\GdipGetPenMiterLimit", Ptr, pPen, "float*", result)
3307 If E
3308 Return -1
3309 Return result
3310}
3311
3312Gdip_GetPenUnit(pPen) {
3313 result := 0
3314 E := DllCall("gdiplus\GdipGetPenUnit", Ptr, pPen, "int*", result)
3315 If E
3316 Return -1
3317 Return result
3318}
3319
3320Gdip_ClonePen(pPen) {
3321 newPen := 0
3322 E := DllCall("gdiplus\GdipClonePen", "UPtr", pPen, "UPtr*", newPen)
3323 Return newPen
3324}
3325
3326;#####################################################################################
3327; pBrush functions [types: SolidFill, Texture, Hatch patterns, PathGradient and LinearGradient]
3328; pBrush objects can be used by pPen objects via Gdip_SetPenBrushFill()
3329;#####################################################################################
3330
3331Gdip_BrushCreateSolid(ARGB:=0xff000000) {
3332 pBrush := 0
3333 E := DllCall("gdiplus\GdipCreateSolidFill", "UInt", ARGB, "UPtr*", pBrush)
3334 return pBrush
3335}
3336
3337Gdip_SetSolidFillColor(pBrush, ARGB) {
3338 return DllCall("gdiplus\GdipSetSolidFillColor", "UPtr", pBrush, "UInt", ARGB)
3339}
3340
3341Gdip_GetSolidFillColor(pBrush) {
3342 ARGB := 0
3343 E := DllCall("gdiplus\GdipGetSolidFillColor", "UPtr", pBrush, "UInt*", ARGB)
3344 If E
3345 return -1
3346 return Format("{1:#x}", ARGB)
3347}
3348
3349Gdip_BrushCreateHatch(ARGBfront, ARGBback, HatchStyle:=0) {
3350; HatchStyle options:
3351; Horizontal = 0
3352; Vertical = 1
3353; ForwardDiagonal = 2
3354; BackwardDiagonal = 3
3355; Cross = 4
3356; DiagonalCross = 5
3357; 05Percent = 6
3358; 10Percent = 7
3359; 20Percent = 8
3360; 25Percent = 9
3361; 30Percent = 10
3362; 40Percent = 11
3363; 50Percent = 12
3364; 60Percent = 13
3365; 70Percent = 14
3366; 75Percent = 15
3367; 80Percent = 16
3368; 90Percent = 17
3369; LightDownwardDiagonal = 18
3370; LightUpwardDiagonal = 19
3371; DarkDownwardDiagonal = 20
3372; DarkUpwardDiagonal = 21
3373; WideDownwardDiagonal = 22
3374; WideUpwardDiagonal = 23
3375; LightVertical = 24
3376; LightHorizontal = 25
3377; NarrowVertical = 26
3378; NarrowHorizontal = 27
3379; DarkVertical = 28
3380; DarkHorizontal = 29
3381; DashedDownwardDiagonal = 30
3382; DashedUpwardDiagonal = 31
3383; DashedHorizontal = 32
3384; DashedVertical = 33
3385; SmallConfetti = 34
3386; LargeConfetti = 35
3387; ZigZag = 36
3388; Wave = 37
3389; DiagonalBrick = 38
3390; HorizontalBrick = 39
3391; Weave = 40
3392; Plaid = 41
3393; Divot = 42
3394; DottedGrid = 43
3395; DottedDiamond = 44
3396; Shingle = 45
3397; Trellis = 46
3398; Sphere = 47
3399; SmallGrid = 48
3400; SmallCheckerBoard = 49
3401; LargeCheckerBoard = 50
3402; OutlinedDiamond = 51
3403; SolidDiamond = 52
3404; Total = 53
3405 pBrush := 0
3406 E := DllCall("gdiplus\GdipCreateHatchBrush", "int", HatchStyle, "UInt", ARGBfront, "UInt", ARGBback, "UPtr*", pBrush)
3407 return pBrush
3408}
3409
3410Gdip_GetHatchBackgroundColor(pHatchBrush) {
3411 ARGB := 0
3412 Ptr := "UPtr"
3413 E := DllCall("gdiplus\GdipGetHatchBackgroundColor", Ptr, pHatchBrush, "uint*", ARGB)
3414 If E
3415 Return -1
3416 return Format("{1:#x}", ARGB)
3417}
3418
3419Gdip_GetHatchForegroundColor(pHatchBrush) {
3420 ARGB := 0
3421 Ptr := "UPtr"
3422 E := DllCall("gdiplus\GdipGetHatchForegroundColor", Ptr, pHatchBrush, "uint*", ARGB)
3423 If E
3424 Return -1
3425 return Format("{1:#x}", ARGB)
3426}
3427
3428Gdip_GetHatchStyle(pHatchBrush) {
3429 result := 0
3430 Ptr := "UPtr"
3431 E := DllCall("gdiplus\GdipGetHatchStyle", Ptr, pHatchBrush, "int*", result)
3432 If E
3433 Return -1
3434 Return result
3435}
3436
3437;#####################################################################################
3438
3439; Function: Gdip_CreateTextureBrush
3440; Description: Creates a TextureBrush object based on an image, a wrap mode and a defining rectangle.
3441;
3442; pBitmap Pointer to an Image object
3443; WrapMode Wrap mode that specifies how repeated copies of an image are used to tile an area when it is
3444; painted with the texture brush:
3445; 0 - Tile - Tiling without flipping
3446; 1 - TileFlipX - Tiles are flipped horizontally as you move from one tile to the next in a row
3447; 2 - TileFlipY - Tiles are flipped vertically as you move from one tile to the next in a column
3448; 3 - TileFlipXY - Tiles are flipped horizontally as you move along a row and flipped vertically as you move along a column
3449; 4 - Clamp - No tiling takes place
3450; x, y x, y coordinates of the image portion to be used by this brush
3451; w, h Width and height of the image portion
3452; matrix A color matrix to alter the colors of the given pBitmap
3453; ScaleX, ScaleY x, y scaling factor for the texture
3454; Angle Rotates the texture at given angle
3455;
3456; return If the function succeeds, the return value is nonzero
3457; notes If w and h are omitted, the entire pBitmap is used
3458; Matrix can be omitted to just draw with no alteration to the ARGB channels
3459; Matrix may be passed as a digit from 0.0 - 1.0 to change just transparency
3460; Matrix can be passed as a matrix with "|" as delimiter.
3461; Function modified by Marius Șucan, to allow use of color matrix and ImageAttributes object.
3462
3463Gdip_CreateTextureBrush(pBitmap, WrapMode:=1, x:=0, y:=0, w:="", h:="", matrix:="", ScaleX:="", ScaleY:="", Angle:=0, ImageAttr:=0) {
3464 Ptr := "UPtr"
3465 PtrA := "UPtr*"
3466 pBrush := 0
3467
3468 if !(w && h)
3469 {
3470 DllCall("gdiplus\GdipCreateTexture", Ptr, pBitmap, "int", WrapMode, PtrA, pBrush)
3471 } else
3472 {
3473 If !ImageAttr
3474 {
3475 if !IsNumber(Matrix)
3476 ImageAttr := Gdip_SetImageAttributesColorMatrix(Matrix)
3477 else if (Matrix != 1)
3478 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")
3479 } Else usrImageAttr := 1
3480
3481 If ImageAttr
3482 {
3483 DllCall("gdiplus\GdipCreateTextureIA", Ptr, pBitmap, Ptr, ImageAttr, "float", x, "float", y, "float", w, "float", h, PtrA, pBrush)
3484 If pBrush
3485 Gdip_SetTextureWrapMode(pBrush, WrapMode)
3486 } Else
3487 DllCall("gdiplus\GdipCreateTexture2", Ptr, pBitmap, "int", WrapMode, "float", x, "float", y, "float", w, "float", h, PtrA, pBrush)
3488 }
3489
3490 if (ImageAttr && usrImageAttr!=1)
3491 Gdip_DisposeImageAttributes(ImageAttr)
3492
3493 If (ScaleX && ScaleX && pBrush)
3494 Gdip_ScaleTextureTransform(pBrush, ScaleX, ScaleY)
3495
3496 If (Angle && pBrush)
3497 Gdip_RotateTextureTransform(pBrush, Angle)
3498
3499 return pBrush
3500}
3501
3502Gdip_RotateTextureTransform(pTexBrush, Angle, MatrixOrder:=0) {
3503; MatrixOrder options:
3504; Prepend = 0; The new operation is applied before the old operation.
3505; Append = 1; The new operation is applied after the old operation.
3506; Order of matrices multiplication:.
3507
3508 Ptr := "UPtr"
3509 return DllCall("gdiplus\GdipRotateTextureTransform", Ptr, pTexBrush, "float", Angle, "int", MatrixOrder)
3510}
3511
3512Gdip_ScaleTextureTransform(pTexBrush, ScaleX, ScaleY, MatrixOrder:=0) {
3513 Ptr := "UPtr"
3514 return DllCall("gdiplus\GdipScaleTextureTransform", Ptr, pTexBrush, "float", ScaleX, "float", ScaleY, "int", MatrixOrder)
3515}
3516
3517Gdip_TranslateTextureTransform(pTexBrush, X, Y, MatrixOrder:=0) {
3518 Ptr := "UPtr"
3519 return DllCall("gdiplus\GdipTranslateTextureTransform", Ptr, pTexBrush, "float", X, "float", Y, "int", MatrixOrder)
3520}
3521
3522Gdip_MultiplyTextureTransform(pTexBrush, hMatrix, matrixOrder:=0) {
3523 Ptr := "UPtr"
3524 Return DllCall("gdiplus\GdipMultiplyTextureTransform", Ptr, pTexBrush, Ptr, hMatrix, "int", matrixOrder)
3525}
3526
3527Gdip_SetTextureTransform(pTexBrush, hMatrix) {
3528 Ptr := "UPtr"
3529 return DllCall("gdiplus\GdipSetTextureTransform", Ptr, pTexBrush, Ptr, hMatrix)
3530}
3531
3532Gdip_GetTextureTransform(pTexBrush) {
3533 hMatrix := 0
3534 Ptr := "UPtr"
3535 DllCall("gdiplus\GdipGetTextureTransform", Ptr, pTexBrush, "UPtr*", hMatrix)
3536 Return hMatrix
3537}
3538
3539Gdip_ResetTextureTransform(pTexBrush) {
3540 Ptr := "UPtr"
3541 return DllCall("gdiplus\GdipResetTextureTransform", Ptr, pTexBrush)
3542}
3543
3544Gdip_SetTextureWrapMode(pTexBrush, WrapMode) {
3545; WrapMode options:
3546; 0 - Tile - Tiling without flipping
3547; 1 - TileFlipX - Tiles are flipped horizontally as you move from one tile to the next in a row
3548; 2 - TileFlipY - Tiles are flipped vertically as you move from one tile to the next in a column
3549; 3 - TileFlipXY - Tiles are flipped horizontally as you move along a row and flipped vertically as you move along a column
3550; 4 - Clamp - No tiling takes place
3551
3552 Ptr := "UPtr"
3553 return DllCall("gdiplus\GdipSetTextureWrapMode", Ptr, pTexBrush, "int", WrapMode)
3554}
3555
3556Gdip_GetTextureWrapMode(pTexBrush) {
3557 result := 0
3558 Ptr := "UPtr"
3559 E := DllCall("gdiplus\GdipGetTextureWrapMode", Ptr, pTexBrush, "int*", result)
3560 If E
3561 return -1
3562 Return result
3563}
3564
3565Gdip_GetTextureImage(pTexBrush) {
3566 Ptr := "UPtr"
3567 pBitmapDest := 0
3568 E := DllCall("gdiplus\GdipGetTextureImage", Ptr, pTexBrush
3569 , "UPtr*", pBitmapDest)
3570 Return pBitmapDest
3571}
3572
3573;#####################################################################################
3574; LinearGradientBrush functions
3575;#####################################################################################
3576
3577Gdip_CreateLineBrush(x1, y1, x2, y2, ARGB1, ARGB2, WrapMode:=1) {
3578 return Gdip_CreateLinearGrBrush(x1, y1, x2, y2, ARGB1, ARGB2, WrapMode)
3579}
3580
3581Gdip_CreateLinearGrBrush(x1, y1, x2, y2, ARGB1, ARGB2, WrapMode:=1) {
3582; Linear gradient brush.
3583; WrapMode specifies how the pattern is repeated once it exceeds the defined space
3584; Tile [no flipping] = 0
3585; TileFlipX = 1
3586; TileFlipY = 2
3587; TileFlipXY = 3
3588; Clamp [no tiling] = 4
3589 Ptr := "UPtr"
3590 CreatePointF(PointF1, x1, y1)
3591 CreatePointF(PointF2, x2, y2)
3592 pLinearGradientBrush := 0
3593 DllCall("gdiplus\GdipCreateLineBrush", Ptr, &PointF1, Ptr, &PointF2, "Uint", ARGB1, "Uint", ARGB2, "int", WrapMode, "UPtr*", pLinearGradientBrush)
3594 return pLinearGradientBrush
3595}
3596
3597Gdip_SetLinearGrBrushColors(pLinearGradientBrush, ARGB1, ARGB2) {
3598 Ptr := "UPtr"
3599 return DllCall("gdiplus\GdipSetLineColors", Ptr, pLinearGradientBrush, "UInt", ARGB1, "UInt", ARGB2)
3600}
3601
3602Gdip_GetLinearGrBrushColors(pLinearGradientBrush, ByRef ARGB1, ByRef ARGB2) {
3603 Ptr := "UPtr"
3604 VarSetCapacity(colors, 8, 0)
3605 E := DllCall("gdiplus\GdipGetLineColors", Ptr, pLinearGradientBrush, "Ptr", &colors)
3606 ARGB1 := NumGet(colors, 0, "UInt")
3607 ARGB2 := NumGet(colors, 4, "UInt")
3608 ARGB1 := Format("{1:#x}", ARGB1)
3609 ARGB2 := Format("{1:#x}", ARGB2)
3610 return E
3611}
3612
3613Gdip_CreateLineBrushFromRect(x, y, w, h, ARGB1, ARGB2, LinearGradientMode:=1, WrapMode:=1) {
3614 return Gdip_CreateLinearGrBrushFromRect(x, y, w, h, ARGB1, ARGB2, LinearGradientMode, WrapMode)
3615}
3616
3617Gdip_CreateLinearGrBrushFromRect(x, y, w, h, ARGB1, ARGB2, LinearGradientMode:=1, WrapMode:=1) {
3618; WrapMode options [LinearGradientMode]:
3619; Horizontal = 0
3620; Vertical = 1
3621; ForwardDiagonal = 2
3622; BackwardDiagonal = 3
3623 CreateRectF(RectF, x, y, w, h)
3624 pLinearGradientBrush := 0
3625 E := DllCall("gdiplus\GdipCreateLineBrushFromRect", "UPtr", &RectF, "int", ARGB1, "int", ARGB2, "int", LinearGradientMode, "int", WrapMode, "UPtr*", pLinearGradientBrush)
3626 return pLinearGradientBrush
3627}
3628
3629Gdip_GetLinearGrBrushGammaCorrection(pLinearGradientBrush) {
3630 Ptr := "UPtr"
3631 result := 0
3632 E := DllCall("gdiplus\GdipGetLineGammaCorrection", Ptr, pLinearGradientBrush, "int*", result)
3633 If E
3634 Return -1
3635 Return result
3636}
3637
3638Gdip_SetLinearGrBrushGammaCorrection(pLinearGradientBrush, UseGammaCorrection) {
3639 Ptr := "UPtr"
3640 Return DllCall("gdiplus\GdipSetLineGammaCorrection", Ptr, pLinearGradientBrush, "int", UseGammaCorrection)
3641}
3642
3643Gdip_GetLinearGrBrushRect(pLinearGradientBrush) {
3644 Ptr := "UPtr"
3645 rData := {}
3646 VarSetCapacity(RectF, 16, 0)
3647 status := DllCall("gdiplus\GdipGetLineRect", Ptr, pLinearGradientBrush, Ptr, &RectF)
3648
3649 If (!status) {
3650 rData.x := NumGet(&RectF, 0, "float")
3651 , rData.y := NumGet(&RectF, 4, "float")
3652 , rData.w := NumGet(&RectF, 8, "float")
3653 , rData.h := NumGet(&RectF, 12, "float")
3654 } Else {
3655 Return status
3656 }
3657
3658 return rData
3659}
3660
3661Gdip_ResetLinearGrBrushTransform(pLinearGradientBrush) {
3662 Ptr := "UPtr"
3663 return DllCall("gdiplus\GdipResetLineTransform", Ptr, pLinearGradientBrush)
3664}
3665
3666Gdip_ScaleLinearGrBrushTransform(pLinearGradientBrush, ScaleX, ScaleY, matrixOrder:=0) {
3667 Ptr := "UPtr"
3668 return DllCall("gdiplus\GdipScaleLineTransform", Ptr, pLinearGradientBrush, "float", ScaleX, "float", ScaleY, "int", matrixOrder)
3669}
3670
3671Gdip_MultiplyLinearGrBrushTransform(pLinearGradientBrush, hMatrix, matrixOrder:=0) {
3672 Ptr := "UPtr"
3673 Return DllCall("gdiplus\GdipMultiplyLineTransform", Ptr, pLinearGradientBrush, Ptr, hMatrix, "int", matrixOrder)
3674}
3675
3676Gdip_TranslateLinearGrBrushTransform(pLinearGradientBrush, X, Y, matrixOrder:=0) {
3677 Ptr := "UPtr"
3678 return DllCall("gdiplus\GdipTranslateLineTransform", Ptr, pLinearGradientBrush, "float", X, "float", Y, "int", matrixOrder)
3679}
3680
3681Gdip_RotateLinearGrBrushTransform(pLinearGradientBrush, Angle, matrixOrder:=0) {
3682 Ptr := "UPtr"
3683 return DllCall("gdiplus\GdipRotateLineTransform", Ptr, pLinearGradientBrush, "float", Angle, "int", matrixOrder)
3684}
3685
3686Gdip_SetLinearGrBrushTransform(pLinearGradientBrush, pMatrix) {
3687 Ptr := "UPtr"
3688 return DllCall("gdiplus\GdipSetLineTransform", Ptr, pLinearGradientBrush, Ptr, pMatrix)
3689}
3690
3691Gdip_GetLinearGrBrushTransform(pLineGradientBrush) {
3692 Ptr := "UPtr"
3693 pMatrix := 0
3694 DllCall("gdiplus\GdipGetLineTransform", Ptr, pLineGradientBrush, "UPtr*", pMatrix)
3695 Return pMatrix
3696}
3697
3698Gdip_RotateLinearGrBrushAtCenter(pLinearGradientBrush, Angle, MatrixOrder:=1) {
3699; function by Marius Șucan
3700; based on Gdip_RotatePathAtCenter() by RazorHalo
3701
3702 Rect := Gdip_GetLinearGrBrushRect(pLinearGradientBrush) ; boundaries
3703 cX := Rect.x + (Rect.w / 2)
3704 cY := Rect.y + (Rect.h / 2)
3705 pMatrix := Gdip_CreateMatrix()
3706 Gdip_TranslateMatrix(pMatrix, -cX , -cY)
3707 Gdip_RotateMatrix(pMatrix, Angle, MatrixOrder)
3708 Gdip_TranslateMatrix(pMatrix, cX, cY, MatrixOrder)
3709 E := Gdip_SetLinearGrBrushTransform(pLinearGradientBrush, pMatrix)
3710 Gdip_DeleteMatrix(pMatrix)
3711 Return E
3712}
3713
3714Gdip_GetLinearGrBrushWrapMode(pLinearGradientBrush) {
3715 Ptr := "UPtr"
3716 result := 0
3717 E := DllCall("gdiplus\GdipGetLineWrapMode", Ptr, pLinearGradientBrush, "int*", result)
3718 If E
3719 return -1
3720 Return result
3721}
3722
3723Gdip_SetLinearGrBrushLinearBlend(pLinearGradientBrush, nFocus, nScale) {
3724; https://purebasic.developpez.com/tutoriels/gdi/documentation/GdiPlus/LinearGradientBrush/html/GdipSetLineLinearBlend.html
3725
3726 Ptr := "UPtr"
3727 Return DllCall("gdiplus\GdipSetLineLinearBlend", Ptr, pLinearGradientBrush, "float", nFocus, "float", nScale)
3728}
3729
3730Gdip_SetLinearGrBrushSigmaBlend(pLinearGradientBrush, nFocus, nScale) {
3731; https://purebasic.developpez.com/tutoriels/gdi/documentation/GdiPlus/LinearGradientBrush/html/GdipSetLineSigmaBlend.html
3732 Ptr := "UPtr"
3733 Return DllCall("gdiplus\GdipSetLineSigmaBlend", Ptr, pLinearGradientBrush, "float", nFocus, "float", nScale)
3734}
3735
3736Gdip_SetLinearGrBrushWrapMode(pLinearGradientBrush, WrapMode) {
3737 Ptr := "UPtr"
3738 Return DllCall("gdiplus\GdipSetLineWrapMode", Ptr, pLinearGradientBrush, "int", WrapMode)
3739}
3740
3741Gdip_GetLinearGrBrushBlendCount(pLinearGradientBrush) {
3742 Ptr := "UPtr"
3743 result := 0
3744 E := DllCall("gdiplus\GdipGetLineBlendCount", Ptr, pLinearGradientBrush, "int*", result)
3745 If E
3746 return -1
3747 Return result
3748}
3749
3750Gdip_SetLinearGrBrushPresetBlend(pBrush, pA, pB, pC, pD, clr1, clr2, clr3, clr4) {
3751 Ptr := "UPtr"
3752 CreateRectF(POSITIONS, pA, pB, pC, pD)
3753 CreateRect(COLORS, clr1, clr2, clr3, clr4)
3754 E:= DllCall("gdiplus\GdipSetLinePresetBlend", Ptr, pBrush, "Ptr", &COLORS, "Ptr", &POSITIONS, "Int", 4)
3755 Return E
3756}
3757
3758Gdip_CloneBrush(pBrush) {
3759 pBrushClone := 0
3760 E := DllCall("gdiplus\GdipCloneBrush", "UPtr", pBrush, "UPtr*", pBrushClone)
3761 return pBrushClone
3762}
3763
3764Gdip_GetBrushType(pBrush) {
3765; Possible brush types [return values]:
3766; 0 - Solid color
3767; 1 - Hatch pattern fill
3768; 2 - Texture fill
3769; 3 - Path gradient
3770; 4 - Linear gradient
3771; -1 - error
3772
3773 Ptr := "UPtr"
3774 result := 0
3775 E := DllCall("gdiplus\GdipGetBrushType", Ptr, pBrush, "int*", result)
3776 If E
3777 return -1
3778 Return result
3779}
3780
3781;#####################################################################################
3782; Delete resources
3783;#####################################################################################
3784
3785Gdip_DeleteRegion(Region) {
3786 return DllCall("gdiplus\GdipDeleteRegion", "UPtr", Region)
3787}
3788
3789Gdip_DeletePen(pPen) {
3790 return DllCall("gdiplus\GdipDeletePen", "UPtr", pPen)
3791}
3792
3793Gdip_DeleteBrush(pBrush) {
3794 return DllCall("gdiplus\GdipDeleteBrush", "UPtr", pBrush)
3795}
3796
3797Gdip_DisposeImage(pBitmap, noErr:=0) {
3798; modified by Marius Șucan to help avoid crashes
3799; by disposing a non-existent pBitmap
3800
3801 If (StrLen(pBitmap)<=2 && noErr=1)
3802 Return 0
3803
3804 r := DllCall("gdiplus\GdipDisposeImage", "UPtr", pBitmap)
3805 If (r=2 || r=1) && (noErr=1)
3806 r := 0
3807 Return r
3808}
3809
3810Gdip_DeleteGraphics(pGraphics) {
3811 return DllCall("gdiplus\GdipDeleteGraphics", "UPtr", pGraphics)
3812}
3813
3814Gdip_DisposeImageAttributes(ImageAttr) {
3815 return DllCall("gdiplus\GdipDisposeImageAttributes", "UPtr", ImageAttr)
3816}
3817
3818Gdip_DeleteFont(hFont) {
3819 return DllCall("gdiplus\GdipDeleteFont", "UPtr", hFont)
3820}
3821
3822Gdip_DeleteStringFormat(hStringFormat) {
3823 return DllCall("gdiplus\GdipDeleteStringFormat", "UPtr", hStringFormat)
3824}
3825
3826Gdip_DeleteFontFamily(hFontFamily) {
3827 return DllCall("gdiplus\GdipDeleteFontFamily", "UPtr", hFontFamily)
3828}
3829
3830Gdip_DeletePrivateFontCollection(hFontCollection) {
3831 Return DllCall("gdiplus\GdipDeletePrivateFontCollection", "ptr*", hFontCollection)
3832}
3833
3834Gdip_DeleteMatrix(hMatrix) {
3835 return DllCall("gdiplus\GdipDeleteMatrix", "UPtr", hMatrix)
3836}
3837
3838;#####################################################################################
3839; Text functions
3840; Easy to use functions:
3841; Gdip_DrawOrientedString() - allows to draw strings or string contours/outlines,
3842; or both, rotated at any angle. On success, its boundaries are returned.
3843; Gdip_DrawStringAlongPolygon() - allows you to draw a string along a pPath
3844; or multiple given coordinates.
3845; Gdip_TextToGraphics() - allows you to draw strings or measure their boundaries.
3846;#####################################################################################
3847
3848Gdip_DrawOrientedString(pGraphics, String, FontName, Size, Style, X, Y, Width, Height, Angle:=0, pBrush:=0, pPen:=0, Align:=0, ScaleX:=1) {
3849; FontName can be a name of an already installed font or it can point to a font file
3850; to be loaded and used to draw the string.
3851
3852; Size - in em, in world units [font size]
3853; Remarks: a high value might be required; over 60, 90... to see the text.
3854; X, Y - coordinates for the rectangle where the text will be drawn
3855; W, H - width and heigh for the rectangle where the text will be drawn
3856; Angle - the angle at which the text should be rotated
3857
3858; pBrush - a pointer to a pBrush object to fill the text with
3859; pPen - a pointer to a pPen object to draw the outline [contour] of the text
3860; Remarks: both are optional, but one at least must be given, otherwise
3861; the function fails, returns -3.
3862; For example, if you want only the contour of the text, pass only a pPen object.
3863
3864; Align options:
3865; Near/left = 0
3866; Center = 1
3867; Far/right = 2
3868
3869; Style options:
3870; Regular = 0
3871; Bold = 1
3872; Italic = 2
3873; BoldItalic = 3
3874; Underline = 4
3875; Strikeout = 8
3876
3877; ScaleX - if you want to distort the text [make it wider or narrower]
3878
3879; On success, the function returns an array:
3880; PathBounds.x , PathBounds.y , PathBounds.w , PathBounds.h
3881
3882 If (!pBrush && !pPen)
3883 Return -3
3884
3885 If RegExMatch(FontName, "^(.\:\\.)")
3886 {
3887 hFontCollection := Gdip_NewPrivateFontCollection()
3888 hFontFamily := Gdip_CreateFontFamilyFromFile(FontName, hFontCollection)
3889 } Else hFontFamily := Gdip_FontFamilyCreate(FontName)
3890
3891 If !hFontFamily
3892 hFontFamily := Gdip_FontFamilyCreateGeneric(1)
3893
3894 If !hFontFamily
3895 {
3896 If hFontCollection
3897 Gdip_DeletePrivateFontCollection(hFontCollection)
3898 Return -1
3899 }
3900
3901 FormatStyle := 0x4000
3902 hStringFormat := Gdip_StringFormatCreate(FormatStyle)
3903 If !hStringFormat
3904 hStringFormat := Gdip_StringFormatGetGeneric(1)
3905
3906 If !hStringFormat
3907 {
3908 Gdip_DeleteFontFamily(hFontFamily)
3909 If hFontCollection
3910 Gdip_DeletePrivateFontCollection(hFontCollection)
3911 Return -2
3912 }
3913
3914 Gdip_SetStringFormatTrimming(hStringFormat, 3)
3915 Gdip_SetStringFormatAlign(hStringFormat, Align)
3916 pPath := Gdip_CreatePath()
3917
3918 E := Gdip_AddPathString(pPath, String, hFontFamily, Style, Size, hStringFormat, X, Y, Width, Height)
3919 If (ScaleX>0 && ScaleX!=1)
3920 {
3921 hMatrix := Gdip_CreateMatrix()
3922 Gdip_ScaleMatrix(hMatrix, ScaleX, 1)
3923 Gdip_TransformPath(pPath, hMatrix)
3924 Gdip_DeleteMatrix(hMatrix)
3925 }
3926 Gdip_RotatePathAtCenter(pPath, Angle)
3927
3928 If (!E && pBrush)
3929 E := Gdip_FillPath(pGraphics, pBrush, pPath)
3930 If (!E && pPen)
3931 E := Gdip_DrawPath(pGraphics, pPen, pPath)
3932 PathBounds := Gdip_GetPathWorldBounds(pPath)
3933 Gdip_DeleteStringFormat(hStringFormat)
3934 Gdip_DeleteFontFamily(hFontFamily)
3935 Gdip_DeletePath(pPath)
3936 If hFontCollection
3937 Gdip_DeletePrivateFontCollection(hFontCollection)
3938 Return E ? E : PathBounds
3939}
3940
3941Gdip_TextToGraphics(pGraphics, Text, Options, Font:="Arial", Width:="", Height:="", Measure:=0, userBrush:=0, Unit:=0) {
3942; Font parameter can be a name of an already installed font or it can point to a font file
3943; to be loaded and used to draw the string.
3944;
3945; Set Unit to 3 [Pts] to have the texts rendered at the same size
3946; with the texts rendered in GUIs with -DPIscale
3947;
3948; userBrush - if a pBrush object is passed, this will be used to draw the text
3949; Remarks: by changing the alignment, the text will be rendered at a different X
3950; coordinate position; the position of the text is set relative to
3951; the given X position coordinate and the text width..
3952; See also Gdip_SetStringFormatAlign().
3953;
3954; On success, the function returns a string in the following format:
3955; "x|y|width|height|chars|lines"
3956; The first four elements represent the boundaries of the text.
3957; The string is returned by Gdip_MeasureString()
3958
3959 Static Styles := "Regular|Bold|Italic|BoldItalic|Underline|Strikeout"
3960 , Alignments := "Near|Left|Centre|Center|Far|Right"
3961
3962 IWidth := Width, IHeight:= Height
3963 pattern_opts := (A_AhkVersion < "2") ? "iO)" : "i)"
3964 RegExMatch(Options, pattern_opts "X([\-\d\.]+)(p*)", xpos)
3965 RegExMatch(Options, pattern_opts "Y([\-\d\.]+)(p*)", ypos)
3966 RegExMatch(Options, pattern_opts "W([\-\d\.]+)(p*)", Width)
3967 RegExMatch(Options, pattern_opts "H([\-\d\.]+)(p*)", Height)
3968 RegExMatch(Options, pattern_opts "C(?!(entre|enter))([a-f\d]+)", Colour)
3969 RegExMatch(Options, pattern_opts "Top|Up|Bottom|Down|vCentre|vCenter", vPos)
3970 RegExMatch(Options, pattern_opts "NoWrap", NoWrap)
3971 RegExMatch(Options, pattern_opts "R(\d)", Rendering)
3972 RegExMatch(Options, pattern_opts "S(\d+)(p*)", Size)
3973
3974 If (width && height && !NoWrap) || (Iwidth && Iheight && !NoWrap)
3975 mustTrimText := Measure=1 ? 0 : 1
3976
3977 if Colour && IsInteger(Colour[2]) && !Gdip_DeleteBrush(Gdip_CloneBrush(Colour[2]))
3978 {
3979 PassBrush := 1
3980 pBrush := Colour[2]
3981 }
3982
3983 if !(IWidth && IHeight) && ((xpos && xpos[2]) || (ypos && ypos[2]) || (Width && Width[2]) || (Height && Height[2]) || (Size && Size[2]))
3984 return -1
3985
3986 Style := 0
3987 For eachStyle, valStyle in StrSplit(Styles, "|")
3988 {
3989 if RegExMatch(Options, "\b" valStyle)
3990 Style |= (valStyle != "StrikeOut") ? (A_Index-1) : 8
3991 }
3992
3993 Align := 0
3994 For eachAlignment, valAlignment in StrSplit(Alignments, "|")
3995 {
3996 if RegExMatch(Options, "\b" valAlignment)
3997 Align |= A_Index//2.1 ; 0|0|1|1|2|2
3998 }
3999
4000 xpos := (xpos && (xpos[1] != "")) ? xpos[2] ? IWidth*(xpos[1]/100) : xpos[1] : 0
4001 ypos := (ypos && (ypos[1] != "")) ? ypos[2] ? IHeight*(ypos[1]/100) : ypos[1] : 0
4002 Width := (Width && Width[1]) ? Width[2] ? IWidth*(Width[1]/100) : Width[1] : IWidth
4003 Height := (Height && Height[1]) ? Height[2] ? IHeight*(Height[1]/100) : Height[1] : IHeight
4004 If !PassBrush
4005 Colour := "0x" (Colour && Colour[2] ? Colour[2] : "ff000000")
4006 Rendering := (Rendering && (Rendering[1] >= 0) && (Rendering[1] <= 5)) ? Rendering[1] : 4
4007 Size := (Size && (Size[1] > 0)) ? Size[2] ? IHeight*(Size[1]/100) : Size[1] : 12
4008 If RegExMatch(Font, "^(.\:\\.)")
4009 {
4010 hFontCollection := Gdip_NewPrivateFontCollection()
4011 hFontFamily := Gdip_CreateFontFamilyFromFile(Font, hFontCollection)
4012 } Else hFontFamily := Gdip_FontFamilyCreate(Font)
4013
4014 If !hFontFamily
4015 hFontFamily := Gdip_FontFamilyCreateGeneric(1)
4016
4017 hFont := Gdip_FontCreate(hFontFamily, Size, Style, Unit)
4018 FormatStyle := NoWrap ? 0x4000 | 0x1000 : 0x4000
4019 hStringFormat := Gdip_StringFormatCreate(FormatStyle)
4020 If !hStringFormat
4021 hStringFormat := Gdip_StringFormatGetGeneric(1)
4022
4023 pBrush := PassBrush ? pBrush : Gdip_BrushCreateSolid(Colour)
4024 if !(hFontFamily && hFont && hStringFormat && pBrush && pGraphics)
4025 {
4026 E := !pGraphics ? -2 : !hFontFamily ? -3 : !hFont ? -4 : !hStringFormat ? -5 : !pBrush ? -6 : 0
4027 If pBrush
4028 Gdip_DeleteBrush(pBrush)
4029 If hStringFormat
4030 Gdip_DeleteStringFormat(hStringFormat)
4031 If hFont
4032 Gdip_DeleteFont(hFont)
4033 If hFontFamily
4034 Gdip_DeleteFontFamily(hFontFamily)
4035 If hFontCollection
4036 Gdip_DeletePrivateFontCollection(hFontCollection)
4037 return E
4038 }
4039
4040 CreateRectF(RC, xpos, ypos, Width, Height)
4041 Gdip_SetStringFormatAlign(hStringFormat, Align)
4042 If (mustTrimText=1)
4043 Gdip_SetStringFormatTrimming(hStringFormat, 3)
4044 Gdip_SetTextRenderingHint(pGraphics, Rendering)
4045 ReturnRC := Gdip_MeasureString(pGraphics, Text, hFont, hStringFormat, RC)
4046 ReturnRCtest := StrSplit(ReturnRC, "|")
4047 testX := Floor(ReturnRCtest[1]) - 2
4048 If (testX>xpos) ; error correction for different text alignments
4049 {
4050 nxpos := Floor(xpos - (testX - xpos))
4051 CreateRectF(RC, nxpos, ypos, Width, Height)
4052 ReturnRC := Gdip_MeasureString(pGraphics, Text, hFont, hStringFormat, RC)
4053 ; MsgBox, % nxpos "--" xpos "--" ypos "`n" width "--" height "`n" ReturnRC
4054 }
4055
4056 If vPos
4057 {
4058 ReturnRC := StrSplit(ReturnRC, "|")
4059 if (vPos[0] = "vCentre") || (vPos[0] = "vCenter")
4060 ypos += (Height-ReturnRC[4])//2
4061 else if (vPos[0] = "Top") || (vPos[0] = "Up")
4062 ypos := 0
4063 else if (vPos[0] = "Bottom") || (vPos[0] = "Down")
4064 ypos := Height-ReturnRC[4]
4065
4066 CreateRectF(RC, xpos, ypos, Width, ReturnRC[4])
4067 ReturnRC := Gdip_MeasureString(pGraphics, Text, hFont, hStringFormat, RC)
4068 }
4069
4070 thisBrush := userBrush ? userBrush : pBrush
4071 if !Measure
4072 _E := Gdip_DrawString(pGraphics, Text, hFont, hStringFormat, thisBrush, RC)
4073
4074 if !PassBrush
4075 Gdip_DeleteBrush(pBrush)
4076 Gdip_DeleteStringFormat(hStringFormat)
4077 Gdip_DeleteFont(hFont)
4078 Gdip_DeleteFontFamily(hFontFamily)
4079 If hFontCollection
4080 Gdip_DeletePrivateFontCollection(hFontCollection)
4081 return _E ? _E : ReturnRC
4082}
4083
4084Gdip_DrawString(pGraphics, sString, hFont, hStringFormat, pBrush, ByRef RectF) {
4085 Ptr := "UPtr"
4086 if (!A_IsUnicode)
4087 {
4088 nSize := DllCall("MultiByteToWideChar", "uint", 0, "uint", 0, Ptr, &sString, "int", -1, Ptr, 0, "int", 0)
4089 VarSetCapacity(wString, nSize*2)
4090 DllCall("MultiByteToWideChar", "uint", 0, "uint", 0, Ptr, &sString, "int", -1, Ptr, &wString, "int", nSize)
4091 }
4092
4093 return DllCall("gdiplus\GdipDrawString"
4094 , Ptr, pGraphics
4095 , Ptr, A_IsUnicode ? &sString : &wString
4096 , "int", -1
4097 , Ptr, hFont
4098 , Ptr, &RectF
4099 , Ptr, hStringFormat
4100 , Ptr, pBrush)
4101}
4102
4103Gdip_MeasureString(pGraphics, sString, hFont, hStringFormat, ByRef RectF) {
4104; The function returns a string in the following format:
4105; "x|y|width|height|chars|lines"
4106; The first four elements represent the boundaries of the text
4107
4108 Ptr := "UPtr"
4109 VarSetCapacity(RC, 16)
4110 if !A_IsUnicode
4111 {
4112 nSize := DllCall("MultiByteToWideChar", "uint", 0, "uint", 0, Ptr, &sString, "int", -1, "uint", 0, "int", 0)
4113 VarSetCapacity(wString, nSize*2)
4114 DllCall("MultiByteToWideChar", "uint", 0, "uint", 0, Ptr, &sString, "int", -1, Ptr, &wString, "int", nSize)
4115 }
4116
4117 Chars := 0
4118 Lines := 0
4119 DllCall("gdiplus\GdipMeasureString"
4120 , Ptr, pGraphics
4121 , Ptr, A_IsUnicode ? &sString : &wString
4122 , "int", -1
4123 , Ptr, hFont
4124 , Ptr, &RectF
4125 , Ptr, hStringFormat
4126 , Ptr, &RC
4127 , "uint*", Chars
4128 , "uint*", Lines)
4129
4130 return &RC ? NumGet(RC, 0, "float") "|" NumGet(RC, 4, "float") "|" NumGet(RC, 8, "float") "|" NumGet(RC, 12, "float") "|" Chars "|" Lines : 0
4131}
4132
4133Gdip_DrawStringAlongPolygon(pGraphics, String, FontName, FontSize, Style, pBrush, DriverPoints:=0, pPath:=0, minDist:=0, flatness:=4, hMatrix:=0, Unit:=0) {
4134; The function allows you to draw a text string along a polygonal line.
4135; Each point on the line corresponds to a letter.
4136; If they are too close, the letters will overlap. If they are fewer than
4137; the string length, the text is going to be truncated.
4138; If given, a pPath object will be segmented according to the precision defined by «flatness».
4139;
4140; pGraphics - a pointer to a pGraphics object where to draw the text
4141; FontName can be the name of an already installed font or it can point to a font file
4142; to be loaded and used to draw the string.
4143; FontSize - in em, in world units
4144; a high value might be required; over 60, 90... to see the text.
4145; pBrush - a pointer to a pBrush object to fill the text with
4146; DriverPoints - a string with X, Y coordinates where the letters
4147; of the string will be drawn. Each X/Y pair corresponds to a letter.
4148; "x1,y1|x2,y2|x3,y3" [...and so on]
4149; pPath - A pointer to a pPath object.
4150; It will be used only if DriverPoints parameter is omitted.
4151; If both DriverPoints and pPath are omitted, the function will return -4.
4152; Intermmediate points will be generated if there are more glyphs / letters than defined points.
4153;
4154; flatness - from 0.1 to 5; the precision for arcs, beziers and curves segmentation;
4155; the lower the number is, the higher density of points is;
4156; it applies only for given pPath objects
4157;
4158; minDist - the minimum distance between letters; by default it is FontSize/4
4159; does not apply for pPath objects; use the flatness parameter to control points density
4160;
4161; Style options:
4162; Regular = 0
4163; Bold = 1
4164; Italic = 2
4165; BoldItalic = 3
4166; Underline = 4
4167; Strikeout = 8
4168;
4169; Set Unit to 3 [Pts] to have the texts rendered at the same size
4170; with the texts rendered in GUIs with -DPIscale
4171
4172 If (!minDist || minDist<1)
4173 minDist := FontSize//4 + 1
4174
4175 If (pPath && !DriverPoints)
4176 {
4177 newPath := Gdip_ClonePath(pPath)
4178 Gdip_PathOutline(newPath, flatness)
4179 DriverPoints := Gdip_GetPathPoints(newPath)
4180 Gdip_DeletePath(newPath)
4181 If !DriverPoints
4182 Return -5
4183 }
4184
4185 If (!pPath && !DriverPoints)
4186 Return -4
4187
4188 If RegExMatch(FontName, "^(.\:\\.)")
4189 {
4190 hFontCollection := Gdip_NewPrivateFontCollection()
4191 hFontFamily := Gdip_CreateFontFamilyFromFile(FontName, hFontCollection)
4192 } Else hFontFamily := Gdip_FontFamilyCreate(FontName)
4193
4194 If !hFontFamily
4195 hFontFamily := Gdip_FontFamilyCreateGeneric(1)
4196
4197 If !hFontFamily
4198 {
4199 If hFontCollection
4200 Gdip_DeletePrivateFontCollection(hFontCollection)
4201 Return -1
4202 }
4203
4204 hFont := Gdip_FontCreate(hFontFamily, FontSize, Style, Unit)
4205 If !hFont
4206 {
4207 If hFontCollection
4208 Gdip_DeletePrivateFontCollection(hFontCollection)
4209 Gdip_DeleteFontFamily(hFontFamily)
4210 Return -2
4211 }
4212
4213 Points := StrSplit(DriverPoints, "|")
4214 PointsCount := Points.Length()
4215 If (PointsCount<2)
4216 {
4217 If hFontCollection
4218 Gdip_DeletePrivateFontCollection(hFontCollection)
4219 Gdip_DeleteFont(hFont)
4220 Gdip_DeleteFontFamily(hFontFamily)
4221 Return -3
4222 }
4223
4224 txtLen := StrLen(String)
4225 If (PointsCount<txtLen)
4226 {
4227 loopsMax := txtLen * 3
4228 newDriverPoints := DriverPoints
4229 Loop %loopsMax%
4230 {
4231 newDriverPoints := GenerateIntermediatePoints(newDriverPoints, minDist, totalResult)
4232 If (totalResult>=txtLen)
4233 Break
4234 }
4235 String := SubStr(String, 1, totalResult)
4236 } Else newDriverPoints := DriverPoints
4237
4238 E := Gdip_DrawDrivenString(pGraphics, String, hFont, pBrush, newDriverPoints, 1, hMatrix)
4239 Gdip_DeleteFont(hFont)
4240 Gdip_DeleteFontFamily(hFontFamily)
4241 If hFontCollection
4242 Gdip_DeletePrivateFontCollection(hFontCollection)
4243 return E
4244}
4245
4246GenerateIntermediatePoints(PointsList, minDist, ByRef resultPointsCount) {
4247; function used by Gdip_DrawFreeFormString()
4248 AllPoints := StrSplit(PointsList, "|")
4249 PointsCount := AllPoints.Length()
4250 thizIndex := 0.5
4251 resultPointsCount := 0
4252 loopsMax := PointsCount*2
4253 Loop %loopsMax%
4254 {
4255 thizIndex += 0.5
4256 thisIndex := InStr(thizIndex, ".5") ? thizIndex : Trim(Round(thizIndex))
4257 thisPoint := AllPoints[thisIndex]
4258 theseCoords := StrSplit(thisPoint, ",")
4259 If (theseCoords[1]!="" && theseCoords[2]!="")
4260 {
4261 resultPointsCount++
4262 newPointsList .= theseCoords[1] "," theseCoords[2] "|"
4263 } Else
4264 {
4265 aIndex := Trim(Round(thizIndex - 0.5))
4266 bIndex := Trim(Round(thizIndex + 0.5))
4267 theseAcoords := StrSplit(AllPoints[aIndex], ",")
4268 theseBcoords := StrSplit(AllPoints[bIndex], ",")
4269 If (theseAcoords[1]!="" && theseAcoords[2]!="")
4270 && (theseBcoords[1]!="" && theseBcoords[2]!="")
4271 {
4272 newPosX := (theseAcoords[1] + theseBcoords[1])//2
4273 newPosY := (theseAcoords[2] + theseBcoords[2])//2
4274 distPosX := newPosX - theseAcoords[1]
4275 distPosY := newPosY - theseAcoords[2]
4276 If (distPosX>minDist || distPosY>minDist)
4277 {
4278 newPointsList .= newPosX "," newPosY "|"
4279 resultPointsCount++
4280 }
4281 }
4282 }
4283 }
4284 If !newPointsList
4285 Return PointsList
4286 Return Trim(newPointsList, "|")
4287}
4288
4289Gdip_DrawDrivenString(pGraphics, String, hFont, pBrush, DriverPoints, Flags:=1, hMatrix:=0) {
4290; Parameters:
4291; pBrush - pointer to a pBrush object used to draw the text into the given pGraphics
4292; hFont - pointer for a Font object used to draw the given text that determines font, size and style
4293; hMatrix - pointer to a transformation matrix object that specifies the transformation matrix to apply to each value in the DriverPoints
4294; DriverPoints - a list of points coordinates that determines where the glyphs [letters] will be drawn
4295; "x1,y1|x2,y2|x3,y3" [... and so on]
4296; Flags options:
4297; 1 - The string array contains Unicode character values. If this flag is not set, each value in $vText is
4298; interpreted as an index to a font glyph that defines a character to be displayed
4299; 2 - The string is displayed vertically
4300; 4 - The glyph positions are calculated from the position of the first glyph. If this flag is not set, the
4301; glyph positions are obtained from an array of coordinates ($aPoints)
4302; 8 - Less memory should be used for cache of antialiased glyphs. This also produces lower quality. If this
4303; flag is not set, more memory is used, but the quality is higher
4304
4305 txtLen := -1 ; StrLen(String)
4306 Ptr := "UPtr"
4307 iCount := CreatePointsF(PointsF, DriverPoints)
4308 return DllCall("gdiplus\GdipDrawDriverString", Ptr, pGraphics, "UPtr", &String, "int", txtLen, Ptr, hFont, Ptr, pBrush, Ptr, &PointsF, "int", Flags, Ptr, hMatrix)
4309}
4310
4311Gdip_StringFormatCreate(FormatFlags:=0, LangID:=0) {
4312; Format options [StringFormatFlags]
4313; DirectionRightToLeft = 0x00000001
4314; - Activates is right to left reading order. For horizontal text, characters are read from right to left. For vertical text, columns are read from right to left.
4315; DirectionVertical = 0x00000002
4316; - Individual lines of text are drawn vertically on the display device.
4317; NoFitBlackBox = 0x00000004
4318; - Parts of characters are allowed to overhang the string's layout rectangle.
4319; DisplayFormatControl = 0x00000020
4320; - Unicode layout control characters are displayed with a representative character.
4321; NoFontFallback = 0x00000400
4322; - Prevent using an alternate font for characters that are not supported in the requested font.
4323; MeasureTrailingSpaces = 0x00000800
4324; - The spaces at the end of each line are included in a string measurement.
4325; NoWrap = 0x00001000
4326; - Disable text wrapping
4327; LineLimit = 0x00002000
4328; - Only entire lines are laid out in the layout rectangle.
4329; NoClip = 0x00004000
4330; - Characters overhanging the layout rectangle and text extending outside the layout rectangle are allowed to show.
4331
4332 hStringFormat := 0
4333 E := DllCall("gdiplus\GdipCreateStringFormat", "int", FormatFlags, "int", LangID, "UPtr*", hStringFormat)
4334 return hStringFormat
4335}
4336
4337Gdip_CloneStringFormat(hStringFormat) {
4338 Ptr := "UPtr"
4339 newHStringFormat := 0
4340 DllCall("gdiplus\GdipCloneStringFormat", Ptr, hStringFormat, "uint*", newHStringFormat)
4341 Return newHStringFormat
4342}
4343
4344Gdip_StringFormatGetGeneric(whichFormat:=0) {
4345; Default = 0
4346; Typographic := 1
4347 hStringFormat := 0
4348 If (whichFormat=1)
4349 DllCall("gdiplus\GdipStringFormatGetGenericTypographic", "UPtr*", hStringFormat)
4350 Else
4351 DllCall("gdiplus\GdipStringFormatGetGenericDefault", "UPtr*", hStringFormat)
4352 Return hStringFormat
4353}
4354
4355Gdip_SetStringFormatAlign(hStringFormat, Align) {
4356; Text alignments:
4357; 0 - [Near / Left] Alignment is towards the origin of the bounding rectangle
4358; 1 - [Center] Alignment is centered between origin and extent (width) of the formatting rectangle
4359; 2 - [Far / Right] Alignment is to the far extent (right side) of the formatting rectangle
4360
4361 return DllCall("gdiplus\GdipSetStringFormatAlign", "UPtr", hStringFormat, "int", Align)
4362}
4363
4364Gdip_GetStringFormatAlign(hStringFormat) {
4365 Ptr := "UPtr"
4366 result := 0
4367 E := DllCall("gdiplus\GdipGetStringFormatAlign", Ptr, hStringFormat, "int*", result)
4368 If E
4369 Return -1
4370 Return result
4371}
4372
4373Gdip_GetStringFormatLineAlign(hStringFormat) {
4374 Ptr := "UPtr"
4375 result := 0
4376 E := DllCall("gdiplus\GdipGetStringFormatLineAlign", Ptr, hStringFormat, "int*", result)
4377 If E
4378 Return -1
4379 Return result
4380}
4381
4382Gdip_GetStringFormatDigitSubstitution(hStringFormat) {
4383 Ptr := "UPtr"
4384 result := 0
4385 E := DllCall("gdiplus\GdipGetStringFormatDigitSubstitution", Ptr, hStringFormat, "ushort*", 0, "int*", result)
4386 If E
4387 Return -1
4388 Return result
4389}
4390
4391Gdip_GetStringFormatHotkeyPrefix(hStringFormat) {
4392 Ptr := "UPtr"
4393 result := 0
4394 E := DllCall("gdiplus\GdipGetStringFormatHotkeyPrefix", Ptr, hStringFormat, "int*", result)
4395 If E
4396 Return -1
4397 Return result
4398}
4399
4400Gdip_GetStringFormatTrimming(hStringFormat) {
4401 Ptr := "UPtr"
4402 result := 0
4403 E := DllCall("gdiplus\GdipGetStringFormatTrimming", Ptr, hStringFormat, "int*", result)
4404 If E
4405 Return -1
4406 Return result
4407}
4408
4409Gdip_SetStringFormatLineAlign(hStringFormat, StringAlign) {
4410; The line alignment setting specifies how to align the string vertically in the layout rectangle.
4411; The layout rectangle is used to position the displayed string
4412; StringAlign - Type of line alignment to use:
4413; 0 - [Left] Alignment is towards the origin of the bounding rectangle
4414; 1 - [Center] Alignment is centered between origin and the height of the formatting rectangle
4415; 2 - [Right] Alignment is to the far extent (right side) of the formatting rectangle
4416
4417 Ptr := "UPtr"
4418 Return DllCall("gdiplus\GdipSetStringFormatLineAlign", Ptr, hStringFormat, "int", StringAlign)
4419}
4420
4421Gdip_SetStringFormatDigitSubstitution(hStringFormat, DigitSubstitute, LangID:=0) {
4422; Sets the language ID and the digit substitution method that is used by a StringFormat object
4423; DigitSubstitute - Digit substitution method that will be used by the StringFormat object:
4424; 0 - A user-defined substitution scheme
4425; 1 - Digit substitution is disabled
4426; 2 - Substitution digits that correspond with the official national language of the user's locale
4427; 3 - Substitution digits that correspond with the user's native script or language
4428
4429 Ptr := "UPtr"
4430 return DllCall("gdiplus\GdipSetStringFormatDigitSubstitution", Ptr, hStringFormat, "ushort", LangID, "int", DigitSubstitute)
4431}
4432
4433Gdip_SetStringFormatFlags(hStringFormat, Flags) {
4434; see Gdip_StringFormatCreate() for possible StringFormatFlags
4435 Ptr := "UPtr"
4436 return DllCall("gdiplus\GdipSetStringFormatFlags", Ptr, hStringFormat, "int", Flags)
4437}
4438
4439Gdip_SetStringFormatHotkeyPrefix(hStringFormat, PrefixProcessMode) {
4440; Sets the type of processing that is performed on a string when a hot key prefix (&) is encountered
4441; PrefixProcessMode - Type of hot key prefix processing to use:
4442; 0 - No hot key processing occurs.
4443; 1 - Unicode text is scanned for ampersands (&). All pairs of ampersands are replaced by a single ampersand.
4444; All single ampersands are removed, the first character that follows a single ampersand is displayed underlined.
4445; 2 - Same as 1 but a character following a single ampersand is not displayed underlined.
4446
4447 Ptr := "UPtr"
4448 return DllCall("gdiplus\GdipSetStringFormatHotkeyPrefix", Ptr, hStringFormat, "int", PrefixProcessMode)
4449}
4450
4451Gdip_SetStringFormatTrimming(hStringFormat, TrimMode) {
4452; TrimMode - The trimming style to use:
4453; 0 - No trimming is done
4454; 1 - String is broken at the boundary of the last character that is inside the layout rectangle
4455; 2 - String is broken at the boundary of the last word that is inside the layout rectangle
4456; 3 - String is broken at the boundary of the last character that is inside the layout rectangle and an ellipsis (...) is inserted after the character
4457; 4 - String is broken at the boundary of the last word that is inside the layout rectangle and an ellipsis (...) is inserted after the word
4458; 5 - The center is removed from the string and replaced by an ellipsis. The algorithm keeps as much of the last portion of the string as possible
4459
4460 Ptr := "UPtr"
4461 return DllCall("gdiplus\GdipSetStringFormatTrimming", Ptr, hStringFormat, "int", TrimMode)
4462}
4463
4464Gdip_FontCreate(hFontFamily, Size, Style:=0, Unit:=0) {
4465; Font style options:
4466; Regular = 0
4467; Bold = 1
4468; Italic = 2
4469; BoldItalic = 3
4470; Underline = 4
4471; Strikeout = 8
4472; Unit options: see Gdip_SetPageUnit()
4473 hFont := 0
4474 DllCall("gdiplus\GdipCreateFont", "UPtr", hFontFamily, "float", Size, "int", Style, "int", Unit, "UPtr*", hFont)
4475 return hFont
4476}
4477
4478Gdip_FontFamilyCreate(FontName) {
4479 Ptr := "UPtr"
4480 if (!A_IsUnicode)
4481 {
4482 nSize := DllCall("MultiByteToWideChar", "uint", 0, "uint", 0, Ptr, &FontName, "int", -1, "uint", 0, "int", 0)
4483 VarSetCapacity(wFontName, nSize*2)
4484 DllCall("MultiByteToWideChar", "uint", 0, "uint", 0, Ptr, &FontName, "int", -1, Ptr, &wFontName, "int", nSize)
4485 }
4486 hFontFamily := 0
4487 _E := DllCall("gdiplus\GdipCreateFontFamilyFromName"
4488 , Ptr, A_IsUnicode ? &FontName : &wFontName
4489 , "uint", 0
4490 , "UPtr*", hFontFamily)
4491
4492 return hFontFamily
4493}
4494
4495Gdip_NewPrivateFontCollection() {
4496 hFontCollection := 0
4497 DllCall("gdiplus\GdipNewPrivateFontCollection", "ptr*", hFontCollection)
4498 Return hFontCollection
4499}
4500
4501Gdip_CreateFontFamilyFromFile(FontFile, hFontCollection, FontName:="") {
4502; hFontCollection - the collection to add the font to
4503; Pass the result of Gdip_NewPrivateFontCollection() to this parameter
4504; to create a private collection of fonts.
4505; After no longer needing the private fonts, use Gdip_DeletePrivateFontCollection()
4506; to free up resources.
4507;
4508; GDI+ does not support PostScript fonts or OpenType fonts which do not have TrueType outlines.
4509;
4510; function by tmplinshi
4511; source: https://www.autohotkey.com/boards/viewtopic.php?f=6&t=813&p=298435#p297794
4512; modified by Marius Șucan
4513 If !hFontCollection
4514 Return
4515
4516 hFontFamily := 0
4517 E := DllCall("gdiplus\GdipPrivateAddFontFile", "ptr", hFontCollection, "str", FontFile)
4518 if (FontName="" && !E)
4519 {
4520 VarSetCapacity(pFontFamily, 10, 0)
4521 DllCall("gdiplus\GdipGetFontCollectionFamilyList", "ptr", hFontCollection, "int", 1, "ptr", &pFontFamily, "int*", found)
4522
4523 VarSetCapacity(FontName, 100)
4524 DllCall("gdiplus\GdipGetFamilyName", "ptr", NumGet(pFontFamily, 0, "ptr"), "str", FontName, "ushort", 1033)
4525 }
4526
4527 If !E
4528 DllCall("gdiplus\GdipCreateFontFamilyFromName", "str", FontName, "ptr", hFontCollection, "uint*", hFontFamily)
4529 Return hFontFamily
4530}
4531
4532Gdip_FontFamilyCreateGeneric(whichStyle) {
4533; This function returns a hFontFamily font object that uses a generic font.
4534;
4535; whichStyle options:
4536; 0 - monospace generic font
4537; 1 - sans-serif generic font
4538; 2 - serif generic font
4539
4540 hFontFamily := 0
4541 If (whichStyle=0)
4542 DllCall("gdiplus\GdipGetGenericFontFamilyMonospace", "UPtr*", hFontFamily)
4543 Else If (whichStyle=1)
4544 DllCall("gdiplus\GdipGetGenericFontFamilySansSerif", "UPtr*", hFontFamily)
4545 Else If (whichStyle=2)
4546 DllCall("gdiplus\GdipGetGenericFontFamilySerif", "UPtr*", hFontFamily)
4547 Return hFontFamily
4548}
4549
4550Gdip_CreateFontFromDC(hDC) {
4551; a font must be selected in the hDC for this function to work
4552; function extracted from a class based wrapper around the GDI+ API made by nnnik
4553
4554 pFont := 0
4555 r := DllCall("gdiplus\GdipCreateFontFromDC", "UPtr", hDC, "UPtr*", pFont)
4556 Return pFont
4557}
4558
4559Gdip_CreateFontFromLogfontW(hDC, LogFont) {
4560; extracted from: https://github.com/flipeador/Library-AutoHotkey/tree/master/graphics
4561; by flipeador
4562;
4563; Creates a Font object directly from a GDI logical font.
4564; The GDI logical font is a LOGFONTW structure, which is the wide character version of a logical font.
4565; Parameters:
4566; hDC:
4567; A handle to a Windows device context that has a font selected.
4568; LogFont:
4569; A LOGFONTW structure that contains attributes of the font.
4570; The LOGFONTW structure is the wide character version of the logical font.
4571;
4572; https://docs.microsoft.com/en-us/windows/win32/api/gdiplusheaders/nf-gdiplusheaders-font-font(inhdc_inconstlogfontw)
4573
4574 pFont := 0
4575 DllCall("Gdiplus\GdipCreateFontFromLogfontW", "Ptr", hDC, "Ptr", LogFont, "UPtrP", pFont)
4576 return pFont
4577}
4578
4579Gdip_GetFontHeight(hFont, pGraphics:=0) {
4580; Gets the line spacing of a font in the current unit of a specified pGraphics object.
4581; The line spacing is the vertical distance between the base lines of two consecutive lines of text.
4582; Therefore, the line spacing includes the blank space between lines along with the height of
4583; the character itself.
4584
4585 Ptr := "UPtr"
4586 result := 0
4587 DllCall("gdiplus\GdipGetFontHeight", Ptr, hFont, Ptr, pGraphics, "float*", result)
4588 Return result
4589}
4590
4591Gdip_GetFontHeightGivenDPI(hFont, DPI:=72) {
4592; Remarks: it seems to always yield the same value
4593; regardless of the given DPI.
4594
4595 Ptr := "UPtr"
4596 result := 0
4597 DllCall("gdiplus\GdipGetFontHeightGivenDPI", Ptr, hFont, "float", DPI, "float*", result)
4598 Return result
4599}
4600
4601Gdip_GetFontSize(hFont) {
4602 Ptr := "UPtr"
4603 result := 0
4604 DllCall("gdiplus\GdipGetFontSize", Ptr, hFont, "float*", result)
4605 Return result
4606}
4607
4608Gdip_GetFontStyle(hFont) {
4609; see also Gdip_FontCreate()
4610 Ptr := "UPtr"
4611 result := 0
4612 E := DllCall("gdiplus\GdipGetFontStyle", Ptr, hFont, "int*", result)
4613 If E
4614 Return -1
4615 Return result
4616}
4617
4618Gdip_GetFontUnit(hFont) {
4619; Gets the unit of measure of a Font object.
4620 Ptr := "UPtr"
4621 result := 0
4622 E := DllCall("gdiplus\GdipGetFontUnit", Ptr, hFont, "int*", result)
4623 If E
4624 Return -1
4625 Return result
4626}
4627
4628Gdip_CloneFont(hfont) {
4629 Ptr := "UPtr"
4630 newHFont := 0
4631 DllCall("gdiplus\GdipCloneFont", Ptr, hFont, "UPtr*", newHFont)
4632 Return newHFont
4633}
4634
4635Gdip_GetFontFamily(hFont) {
4636; On success returns a handle to a hFontFamily object
4637 Ptr := "UPtr"
4638 hFontFamily := 0
4639 DllCall("gdiplus\GdipGetFamily", Ptr, hFont, "UPtr*", hFontFamily)
4640 Return hFontFamily
4641}
4642
4643
4644Gdip_CloneFontFamily(hFontFamily) {
4645 Ptr := "UPtr"
4646 newHFontFamily := 0
4647 DllCall("gdiplus\GdipCloneFontFamily", Ptr, hFontFamily, "UPtr*", newHFontFamily)
4648 Return newHFontFamily
4649}
4650
4651Gdip_IsFontStyleAvailable(hFontFamily, Style) {
4652; Remarks: given a proper hFontFamily object, it seems to be always
4653; returning 1 [true] regardless of Style...
4654
4655 Ptr := "UPtr"
4656 result := 0
4657 E := DllCall("gdiplus\GdipIsStyleAvailable", Ptr, hFontFamily, "int", Style, "Int*", result)
4658 If E
4659 Return -1
4660 Return result
4661}
4662
4663Gdip_GetFontFamilyCellScents(hFontFamily, ByRef Ascent, ByRef Descent, Style:=0) {
4664; Ascent and Descent values are given in «design units»
4665
4666 Ptr := "UPtr"
4667 Ascent := 0
4668 Descent := 0
4669 E := DllCall("gdiplus\GdipGetCellAscent", Ptr, hFontFamily, "int", Style, "ushort*", Ascent)
4670 E := DllCall("gdiplus\GdipGetCellDescent", Ptr, hFontFamily, "int", Style, "ushort*", Descent)
4671 Return E
4672}
4673
4674Gdip_GetFontFamilyEmHeight(hFontFamily, Style:=0) {
4675; EmHeight returned in «design units»
4676 Ptr := "UPtr"
4677 result := 0
4678 DllCall("gdiplus\GdipGetEmHeight", Ptr, hFontFamily, "int", Style, "ushort*", result)
4679 Return result
4680}
4681
4682Gdip_GetFontFamilyLineSpacing(hFontFamily, Style:=0) {
4683; Line spacing returned in «design units»
4684 Ptr := "UPtr"
4685 result := 0
4686 DllCall("gdiplus\GdipGetLineSpacing", Ptr, hFontFamily, "int", Style, "ushort*", result)
4687 Return result
4688}
4689
4690Gdip_GetFontFamilyName(hFontFamily) {
4691 Ptr := "UPtr"
4692 VarSetCapacity(FontName, 90)
4693 DllCall("gdiplus\GdipGetFamilyName", Ptr, hFontFamily, "Ptr", &FontName, "ushort", 0)
4694 Return FontName
4695}
4696
4697
4698;#####################################################################################
4699; Matrix functions
4700;#####################################################################################
4701
4702Gdip_CreateAffineMatrix(m11, m12, m21, m22, x, y) {
4703 hMatrix := 0
4704 DllCall("gdiplus\GdipCreateMatrix2", "float", m11, "float", m12, "float", m21, "float", m22, "float", x, "float", y, "UPtr*", hMatrix)
4705 return hMatrix
4706}
4707
4708Gdip_CreateMatrix() {
4709 hMatrix := 0
4710 DllCall("gdiplus\GdipCreateMatrix", "UPtr*", hMatrix)
4711 return hMatrix
4712}
4713
4714Gdip_InvertMatrix(hMatrix) {
4715; Replaces the elements of a matrix with the elements of its inverse
4716 Ptr := "UPtr"
4717 Return DllCall("gdiplus\GdipInvertMatrix", Ptr, hMatrix)
4718}
4719
4720Gdip_IsMatrixEqual(hMatrixA, hMatrixB) {
4721; compares two matrices; if identical, the function returns 1
4722 Ptr := "UPtr"
4723 result := 0
4724 E := DllCall("gdiplus\GdipIsMatrixEqual", Ptr, hMatrixA, Ptr, hMatrixB, "int*", result)
4725 If E
4726 Return -1
4727 Return result
4728}
4729
4730Gdip_IsMatrixIdentity(hMatrix) {
4731; The identity matrix represents a transformation with no scaling, translation, rotation and conversion, and
4732; represents a transformation that does nothing.
4733 Ptr := "UPtr"
4734 result := 0
4735 E := DllCall("gdiplus\GdipIsMatrixIdentity", Ptr, hMatrix, "int*", result)
4736 If E
4737 Return -1
4738 Return result
4739}
4740
4741Gdip_IsMatrixInvertible(hMatrix) {
4742 Ptr := "UPtr"
4743 result := 0
4744 E := DllCall("gdiplus\GdipIsMatrixInvertible", Ptr, hMatrix, "int*", result)
4745 If E
4746 Return -1
4747 Return result
4748}
4749
4750Gdip_MultiplyMatrix(hMatrixA, hMatrixB, matrixOrder) {
4751; Updates hMatrixA with the product of itself and hMatrixB
4752; matrixOrder - Order of matrices multiplication:
4753; 0 - The second matrix is on the left
4754; 1 - The second matrix is on the right
4755
4756 Ptr := "UPtr"
4757 Return DllCall("gdiplus\GdipMultiplyMatrix", Ptr, hMatrixA, Ptr, hMatrixB, "int", matrixOrder)
4758}
4759
4760Gdip_CloneMatrix(hMatrix) {
4761 Ptr := "UPtr"
4762 newHMatrix := 0
4763 DllCall("gdiplus\GdipCloneMatrix", Ptr, hMatrix, "UPtr*", newHMatrix)
4764 return newHMatrix
4765}
4766
4767;#####################################################################################
4768; GraphicsPath functions
4769; pPath objects are rendered/drawn by pGraphics object using:
4770; - a) Gdip_FillPath() with an associated pBrush object created with any of the following functions:
4771; - Gdip_BrushCreateSolid() - SolidFill
4772; - Gdip_CreateTextureBrush() - Texture brush derived from a pBitmap
4773; - Gdip_CreateLinearGrBrush() - LinearGradient
4774; - Gdip_BrushCreateHatch() - Hatch pattern
4775; - Gdip_PathGradientCreateFromPath()
4776; - b) Gdip_DrawPath() with an associated pPen created with Gdip_CreatePen()
4777;
4778; A pPath object can be converted using:
4779; - a) Gdip_PathGradientCreateFromPath() to a PathGradient brush object
4780; - b) Gdip_CreateRegionPath() to a region object
4781;#####################################################################################
4782
4783Gdip_CreatePath(BrushMode:=0) {
4784; Alternate = 0
4785; Winding = 1
4786 pPath := 0
4787 DllCall("gdiplus\GdipCreatePath", "int", BrushMode, "UPtr*", pPath)
4788 return pPath
4789}
4790
4791Gdip_AddPathEllipse(pPath, x, y, w, h) {
4792 return DllCall("gdiplus\GdipAddPathEllipse", "UPtr", pPath, "float", x, "float", y, "float", w, "float", h)
4793}
4794
4795Gdip_AddPathRectangle(pPath, x, y, w, h) {
4796 return DllCall("gdiplus\GdipAddPathRectangle", "UPtr", pPath, "float", x, "float", y, "float", w, "float", h)
4797}
4798
4799Gdip_AddPathRoundedRectangle(pPath, x, y, w, h, r) {
4800; extracted from: https://github.com/tariqporter/Gdip2/blob/master/lib/Object.ahk
4801; and adapted by Marius Șucan
4802 E := 0
4803 r := (w <= h) ? (r < w / 2) ? r : w / 2 : (r < h / 2) ? r : h / 2
4804 If (E := Gdip_AddPathRectangle(pPath, x+r, y, w-(2*r), r))
4805 Return E
4806 If (E := Gdip_AddPathRectangle(pPath, x+r, y+h-r, w-(2*r), r))
4807 Return E
4808 If (E := Gdip_AddPathRectangle(pPath, x, y+r, r, h-(2*r)))
4809 Return E
4810 If (E := Gdip_AddPathRectangle(pPath, x+w-r, y+r, r, h-(2*r)))
4811 Return E
4812 If (E := Gdip_AddPathRectangle(pPath, x+r, y+r, w-(2*r), h-(2*r)))
4813 Return E
4814 If (E := Gdip_AddPathPie(pPath, x, y, 2*r, 2*r, 180, 90))
4815 Return E
4816 If (E := Gdip_AddPathPie(pPath, x+w-(2*r), y, 2*r, 2*r, 270, 90))
4817 Return E
4818 If (E := Gdip_AddPathPie(pPath, x, y+h-(2*r), 2*r, 2*r, 90, 90))
4819 Return E
4820 If (E := Gdip_AddPathPie(pPath, x+w-(2*r), y+h-(2*r), 2*r, 2*r, 0, 90))
4821 Return E
4822 Return E
4823}
4824
4825
4826Gdip_AddPathPolygon(pPath, Points) {
4827; Points: the coordinates of all the points passed as x1,y1|x2,y2|x3,y3..... [minimum three points must be given]
4828
4829 Ptr := "UPtr"
4830 iCount := CreatePointsF(PointsF, Points)
4831 return DllCall("gdiplus\GdipAddPathPolygon", Ptr, pPath, Ptr, &PointsF, "int", iCount)
4832}
4833
4834Gdip_AddPathClosedCurve(pPath, Points, Tension:="") {
4835; Adds a closed cardinal spline to a path.
4836; A cardinal spline is a curve that passes through each point in the array.
4837;
4838; Parameters:
4839; pPath: Pointer to the GraphicsPath
4840; Points: the coordinates of all the points passed as x1,y1|x2,y2|x3,y3..... [minimum three points must be given]
4841; Tension: Non-negative real number that controls the length of the curve and how the curve bends. A value of
4842; zero specifies that the spline is a sequence of straight lines. As the value increases, the curve becomes fuller.
4843
4844 Ptr := "UPtr"
4845 iCount := CreatePointsF(PointsF, Points)
4846 If Tension
4847 return DllCall("gdiplus\GdipAddPathClosedCurve2", Ptr, pPath, Ptr, &PointsF, "int", iCount, "float", Tension)
4848 Else
4849 return DllCall("gdiplus\GdipAddPathClosedCurve", Ptr, pPath, Ptr, &PointsF, "int", iCount)
4850}
4851
4852Gdip_AddPathCurve(pPath, Points, Tension:="") {
4853; Adds a cardinal spline to the current figure of a path
4854; A cardinal spline is a curve that passes through each point in the array.
4855;
4856; Parameters:
4857; pPath: Pointer to the GraphicsPath
4858; Points: the coordinates of all the points passed as x1,y1|x2,y2|x3,y3..... [minimum three points must be given]
4859; Tension: Non-negative real number that controls the length of the curve and how the curve bends. A value of
4860; zero specifies that the spline is a sequence of straight lines. As the value increases, the curve becomes fuller.
4861
4862 Ptr := "UPtr"
4863 iCount := CreatePointsF(PointsF, Points)
4864 If Tension
4865 return DllCall("gdiplus\GdipAddPathCurve2", Ptr, pPath, Ptr, &PointsF, "int", iCount, "float", Tension)
4866 Else
4867 return DllCall("gdiplus\GdipAddPathCurve", Ptr, pPath, Ptr, &PointsF, "int", iCount)
4868}
4869
4870Gdip_AddPathToPath(pPathA, pPathB, fConnect) {
4871; Adds a path into another path.
4872;
4873; Parameters:
4874; pPathA and pPathB - Pointers to GraphicsPath objects
4875; fConnect - Specifies whether the first figure in the added path is part of the last figure in this path:
4876; 1 - The first figure in the added pPathB is part of the last figure in the pPathB path.
4877; 0 - The first figure in the added pPathB is separated from the last figure in the pPathA path.
4878;
4879; Remarks: Even if the value of the fConnect parameter is 1, this function might not be able to make the first figure
4880; of the added pPathB path part of the last figure of the pPathA path. If either of those figures is closed,
4881; then they must remain separated figures.
4882
4883 Ptr := "UPtr"
4884 return DllCall("gdiplus\GdipAddPathCurve2", Ptr, pPathA, Ptr, pPathB, "int", fConnect)
4885}
4886
4887Gdip_AddPathStringSimplified(pPath, String, FontName, Size, Style, X, Y, Width, Height, Align:=0, NoWrap:=0) {
4888; Adds the outline of a given string with the given font name, size and style
4889; to a Path object.
4890
4891; Size - in em, in world units [font size]
4892; Remarks: a high value might be required; over 60, 90... to see the text.
4893
4894; X, Y - coordinates for the rectangle where the text will be placed
4895; W, H - width and heigh for the rectangle where the text will be placed
4896
4897; Align options:
4898; Near/left = 0
4899; Center = 1
4900; Far/right = 2
4901
4902; Style options:
4903; Regular = 0
4904; Bold = 1
4905; Italic = 2
4906; BoldItalic = 3
4907; Underline = 4
4908; Strikeout = 8
4909
4910 FormatStyle := NoWrap ? 0x4000 | 0x1000 : 0x4000
4911 If RegExMatch(FontName, "^(.\:\\.)")
4912 {
4913 hFontCollection := Gdip_NewPrivateFontCollection()
4914 hFontFamily := Gdip_CreateFontFamilyFromFile(FontName, hFontCollection)
4915 } Else hFontFamily := Gdip_FontFamilyCreate(FontName)
4916
4917 If !hFontFamily
4918 hFontFamily := Gdip_FontFamilyCreateGeneric(1)
4919
4920 If !hFontFamily
4921 {
4922 If hFontCollection
4923 Gdip_DeletePrivateFontCollection(hFontCollection)
4924 Return -1
4925 }
4926
4927 hStringFormat := Gdip_StringFormatCreate(FormatStyle)
4928 If !hStringFormat
4929 hStringFormat := Gdip_StringFormatGetGeneric(1)
4930
4931 If !hStringFormat
4932 {
4933 Gdip_DeleteFontFamily(hFontFamily)
4934 If hFontCollection
4935 Gdip_DeletePrivateFontCollection(hFontCollection)
4936 Return -2
4937 }
4938
4939 Gdip_SetStringFormatTrimming(hStringFormat, 3)
4940 Gdip_SetStringFormatAlign(hStringFormat, Align)
4941 E := Gdip_AddPathString(pPath, String, hFontFamily, Style, Size, hStringFormat, X, Y, Width, Height)
4942 Gdip_DeleteStringFormat(hStringFormat)
4943 Gdip_DeleteFontFamily(hFontFamily)
4944 If hFontCollection
4945 Gdip_DeletePrivateFontCollection(hFontCollection)
4946 Return E
4947}
4948
4949Gdip_AddPathString(pPath, String, hFontFamily, Style, Size, hStringFormat, X, Y, W, H) {
4950 Ptr := "UPtr"
4951 CreateRectF(RectF, X, Y, W, H)
4952 E := DllCall("gdiplus\GdipAddPathString", Ptr, pPath, "WStr", String, "int", -1, Ptr, hFontFamily, "int", Style, "float", Size, Ptr, &RectF, Ptr, hStringFormat)
4953 Return E
4954}
4955
4956
4957Gdip_SetPathFillMode(pPath, FillMode) {
4958; Parameters
4959; pPath - Pointer to a GraphicsPath object
4960; FillMode - Path fill mode:
4961; 0 - [Alternate] The areas are filled according to the even-odd parity rule
4962; 1 - [Winding] The areas are filled according to the non-zero winding rule
4963
4964 return DllCall("gdiplus\GdipSetPathFillMode", "UPtr", pPath, "int", FillMode)
4965}
4966
4967Gdip_GetPathFillMode(pPath) {
4968 Ptr := "UPtr"
4969 result := 0
4970 E := DllCall("gdiplus\GdipGetPathFillMode", Ptr, pPath, "int*", result)
4971 If E
4972 Return -1
4973 Return result
4974}
4975
4976Gdip_GetPathLastPoint(pPath, ByRef X, ByRef Y) {
4977 Ptr := "UPtr"
4978 VarSetCapacity(PointF, 8, 0)
4979 E := DllCall("gdiplus\GdipGetPathLastPoint", Ptr, pPath, "UPtr", &PointF)
4980 If !E
4981 {
4982 x := NumGet(PointF, 0, "float")
4983 y := NumGet(PointF, 4, "float")
4984 }
4985
4986 Return E
4987}
4988
4989Gdip_GetPathPointsCount(pPath) {
4990 Ptr := "UPtr"
4991 result := 0
4992 E := DllCall("gdiplus\GdipGetPointCount", Ptr, pPath, "int*", result)
4993 If E
4994 Return -1
4995 Return result
4996}
4997
4998Gdip_GetPathPoints(pPath) {
4999 PointsCount := Gdip_GetPathPointsCount(pPath)
5000 If (PointsCount=-1)
5001 Return 0
5002
5003 Ptr := "UPtr"
5004 VarSetCapacity(PointsF, 8 * PointsCount, 0)
5005 DllCall("gdiplus\GdipGetPathPoints", Ptr, pPath, Ptr, &PointsF, "intP", PointsCount)
5006 Loop %PointsCount%
5007 {
5008 A := NumGet(&PointsF, 8*(A_Index-1), "float")
5009 B := NumGet(&PointsF, (8*(A_Index-1))+4, "float")
5010 printList .= A "," B "|"
5011 }
5012 Return Trim(printList, "|")
5013}
5014
5015Gdip_FlattenPath(pPath, flatness, hMatrix:=0) {
5016; flatness - a precision value that specifies the maximum error between the path and
5017; its flattened [segmented] approximation. Reducing the flatness increases the number
5018; of line segments in the approximation.
5019;
5020; hMatrix - a pointer to a transformation matrix to apply.
5021 Ptr := "UPtr"
5022 return DllCall("gdiplus\GdipFlattenPath", Ptr, pPath, Ptr, hMatrix, "float", flatness)
5023}
5024
5025Gdip_WidenPath(pPath, pPen, hMatrix:=0, Flatness:=1) {
5026; Replaces this path with curves that enclose the area that is filled when this path is drawn by a specified pen.
5027; This method also flattens the path.
5028
5029 Ptr := "UPtr"
5030 return DllCall("gdiplus\GdipWidenPath", Ptr, pPath, "uint", pPen, Ptr, hMatrix, "float", Flatness)
5031}
5032
5033Gdip_PathOutline(pPath, flatness:=1, hMatrix:=0) {
5034; Transforms and flattens [segmentates] a pPath object, and then converts the path's data points
5035; so that they represent only the outline of the given path.
5036;
5037; flatness - a precision value that specifies the maximum error between the path and
5038; its flattened [segmented] approximation. Reducing the flatness increases the number
5039; of line segments in the resulted approximation.
5040;
5041; hMatrix - a pointer to a transformation matrix to apply.
5042
5043 Ptr := "UPtr"
5044 return DllCall("gdiplus\GdipWindingModeOutline", Ptr, pPath, Ptr, hMatrix, "float", flatness)
5045}
5046
5047Gdip_ResetPath(pPath) {
5048; Empties a path and sets the fill mode to alternate (0)
5049
5050 Ptr := "UPtr"
5051 Return DllCall("gdiplus\GdipResetPath", Ptr, pPath)
5052}
5053
5054Gdip_ReversePath(pPath) {
5055; Reverses the order of the points that define a path's lines and curves
5056
5057 Ptr := "UPtr"
5058 Return DllCall("gdiplus\GdipReversePath", Ptr, pPath)
5059}
5060
5061Gdip_IsOutlineVisiblePathPoint(pGraphics, pPath, pPen, X, Y) {
5062 result := 0
5063 E := DllCall("gdiplus\GdipIsOutlineVisiblePathPoint", Ptr, pPath, "float", X, "float", Y, Ptr, pPen, Ptr, pGraphics, "int*", result)
5064 If E
5065 Return -1
5066 Return result
5067}
5068
5069Gdip_IsVisiblePathPoint(pPath, x, y, pGraphics) {
5070; Function by RazorHalo, modified by Marius Șucan
5071 Ptr := "UPtr"
5072 result := 0
5073 E := DllCall("gdiplus\GdipIsVisiblePathPoint", Ptr, pPath, "float", x, "float", y, Ptr, pGraphics, "UPtr*", result)
5074 If E
5075 return -1
5076 return result
5077}
5078
5079Gdip_DeletePath(pPath) {
5080 return DllCall("gdiplus\GdipDeletePath", "UPtr", pPath)
5081}
5082
5083;#####################################################################################
5084; pGraphics rendering options functions
5085;#####################################################################################
5086
5087Gdip_SetTextRenderingHint(pGraphics, RenderingHint) {
5088; RenderingHint options:
5089; SystemDefault = 0
5090; SingleBitPerPixelGridFit = 1
5091; SingleBitPerPixel = 2
5092; AntiAliasGridFit = 3
5093; AntiAlias = 4
5094 return DllCall("gdiplus\GdipSetTextRenderingHint", "UPtr", pGraphics, "int", RenderingHint)
5095}
5096
5097Gdip_SetInterpolationMode(pGraphics, InterpolationMode) {
5098; InterpolationMode options:
5099; Default = 0
5100; LowQuality = 1
5101; HighQuality = 2
5102; Bilinear = 3
5103; Bicubic = 4
5104; NearestNeighbor = 5
5105; HighQualityBilinear = 6
5106; HighQualityBicubic = 7
5107 return DllCall("gdiplus\GdipSetInterpolationMode", "UPtr", pGraphics, "int", InterpolationMode)
5108}
5109
5110Gdip_SetSmoothingMode(pGraphics, SmoothingMode) {
5111; SmoothingMode options:
5112; Default = 0
5113; HighSpeed = 1
5114; HighQuality = 2
5115; None = 3
5116; AntiAlias = 4
5117; AntiAlias8x4 = 5
5118; AntiAlias8x8 = 6
5119 return DllCall("gdiplus\GdipSetSmoothingMode", "UPtr", pGraphics, "int", SmoothingMode)
5120}
5121
5122Gdip_SetCompositingMode(pGraphics, CompositingMode) {
5123; CompositingMode_SourceOver = 0 (blended / default)
5124; CompositingMode_SourceCopy = 1 (overwrite)
5125
5126 return DllCall("gdiplus\GdipSetCompositingMode", "UPtr", pGraphics, "int", CompositingMode)
5127}
5128
5129Gdip_SetCompositingQuality(pGraphics, CompositionQuality) {
5130; CompositionQuality options:
5131; 0 - Gamma correction is not applied.
5132; 1 - Gamma correction is not applied. High speed, low quality.
5133; 2 - Gamma correction is applied. Composition of high quality and speed.
5134; 3 - Gamma correction is applied.
5135; 4 - Gamma correction is not applied. Linear values are used.
5136
5137 Ptr := "UPtr"
5138 return DllCall("gdiplus\GdipSetCompositingQuality", Ptr, pGraphics, "int", CompositionQuality)
5139}
5140
5141Gdip_SetPageScale(pGraphics, Scale) {
5142; Sets the scaling factor for the page transformation of a pGraphics object.
5143; The page transformation converts page coordinates to device coordinates.
5144
5145 Ptr := "UPtr"
5146 return DllCall("gdiplus\GdipSetPageScale", Ptr, pGraphics, "float", Scale)
5147}
5148
5149Gdip_SetPageUnit(pGraphics, Unit) {
5150; Sets the unit of measurement for a pGraphics object.
5151; Unit of measuremnet options:
5152; 0 - World coordinates, a non-physical unit
5153; 1 - Display units
5154; 2 - A unit is 1 pixel
5155; 3 - A unit is 1 point or 1/72 inch
5156; 4 - A unit is 1 inch
5157; 5 - A unit is 1/300 inch
5158; 6 - A unit is 1 millimeter
5159
5160 Ptr := "UPtr"
5161 return DllCall("gdiplus\GdipSetPageUnit", Ptr, pGraphics, "int", Unit)
5162}
5163
5164Gdip_SetPixelOffsetMode(pGraphics, PixelOffsetMode) {
5165; Sets the pixel offset mode of a pGraphics object.
5166; PixelOffsetMode options:
5167; HighSpeed = QualityModeLow - Default
5168; 0, 1, 3 - Pixel centers have integer coordinates
5169; ModeHalf - ModeHighQuality
5170; 2, 4 - Pixel centers have coordinates that are half way between integer values (i.e. 0.5, 20, 105.5, etc...)
5171
5172 Ptr := "UPtr"
5173 return DllCall("gdiplus\GdipSetPixelOffsetMode", Ptr, pGraphics, "int", PixelOffsetMode)
5174}
5175
5176Gdip_SetRenderingOrigin(pGraphics, X, Y) {
5177; The rendering origin is used to set the dither origin for 8-bits-per-pixel and 16-bits-per-pixel dithering
5178; and is also used to set the origin for hatch brushes
5179 Ptr := "UPtr"
5180 return DllCall("gdiplus\GdipSetRenderingOrigin", Ptr, pGraphics, "int", X, "int", Y)
5181}
5182
5183Gdip_SetTextContrast(pGraphics, Contrast) {
5184; Contrast - A number between 0 and 12, which defines the value of contrast used for antialiasing text
5185
5186 Ptr := "UPtr"
5187 return DllCall("gdiplus\GdipSetTextContrast", Ptr, pGraphics, "uint", Contrast)
5188}
5189
5190Gdip_RestoreGraphics(pGraphics, State) {
5191 ; Sets the state of this Graphics object to the state stored by a previous call to the Save method of this Graphics object.
5192 ; Parameters:
5193 ; State:
5194 ; A value returned by a previous call to the Save method that identifies a block of saved state.
5195 ; Return value:
5196 ; Returns TRUE if successful, or FALSE otherwise. To get extended error information, check «Gdiplus.LastStatus».
5197 ; https://docs.microsoft.com/en-us/windows/win32/api/gdiplusgraphics/nf-gdiplusgraphics-graphics-restore
5198 return DllCall("Gdiplus\GdipRestoreGraphics", "UPtr", pGraphics, "UInt", State)
5199}
5200
5201Gdip_SaveGraphics(pGraphics) {
5202 ; Saves the current state (transformations, clipping region, and quality settings) of this Graphics object.
5203 ; You can restore the state later by calling the Restore method.
5204 ; Return value:
5205 ; Returns a value that identifies the saved state.
5206 ; Pass this value to the Restore method when you want to restore the state.
5207 ; Remarks:
5208 ; The identifier returned by a given call to the Save method can be passed only once to the Restore method.
5209 ; https://docs.microsoft.com/en-us/windows/win32/api/gdiplusgraphics/nf-gdiplusgraphics-graphics-save
5210 State := 0
5211 DllCall("Gdiplus\GdipSaveGraphics", "Ptr", pGraphics, "UIntP", State)
5212 return State
5213}
5214
5215Gdip_GetTextContrast(pGraphics) {
5216 Ptr := "UPtr"
5217 result := 0
5218 E := DllCall("gdiplus\GdipGetTextContrast", Ptr, pGraphics, "uint*", result)
5219 If E
5220 return -1
5221 Return result
5222}
5223
5224Gdip_GetCompositingMode(pGraphics) {
5225 Ptr := "UPtr"
5226 result := 0
5227 E := DllCall("gdiplus\GdipGetCompositingMode", Ptr, pGraphics, "int*", result)
5228 If E
5229 return -1
5230 Return result
5231}
5232
5233Gdip_GetCompositingQuality(pGraphics) {
5234 Ptr := "UPtr"
5235 result := 0
5236 E := DllCall("gdiplus\GdipGetCompositingQuality", Ptr, pGraphics, "int*", result)
5237 If E
5238 return -1
5239 Return result
5240}
5241
5242Gdip_GetInterpolationMode(pGraphics) {
5243 Ptr := "UPtr"
5244 result := 0
5245 E := DllCall("gdiplus\GdipGetInterpolationMode", Ptr, pGraphics, "int*", result)
5246 If E
5247 return -1
5248 Return result
5249}
5250
5251Gdip_GetSmoothingMode(pGraphics) {
5252 Ptr := "UPtr"
5253 result := 0
5254 E := DllCall("gdiplus\GdipGetSmoothingMode", Ptr, pGraphics, "int*", result)
5255 If E
5256 return -1
5257 Return result
5258}
5259
5260Gdip_GetPageScale(pGraphics) {
5261 Ptr := "UPtr"
5262 result := 0
5263 E := DllCall("gdiplus\GdipGetPageScale", Ptr, pGraphics, "float*", result)
5264 If E
5265 return -1
5266 Return result
5267}
5268
5269Gdip_GetPageUnit(pGraphics) {
5270 Ptr := "UPtr"
5271 result := 0
5272 E := DllCall("gdiplus\GdipGetPageUnit", Ptr, pGraphics, "int*", result)
5273 If E
5274 return -1
5275 Return result
5276}
5277
5278Gdip_GetPixelOffsetMode(pGraphics) {
5279 Ptr := "UPtr"
5280 result := 0
5281 E := DllCall("gdiplus\GdipGetPixelOffsetMode", Ptr, pGraphics, "int*", result)
5282 If E
5283 return -1
5284 Return result
5285}
5286
5287Gdip_GetRenderingOrigin(pGraphics, ByRef X, ByRef Y) {
5288 Ptr := "UPtr"
5289 x := 0
5290 y := 0
5291 return DllCall("gdiplus\GdipGetRenderingOrigin", Ptr, pGraphics, "uint*", X, "uint*", Y)
5292}
5293
5294Gdip_GetTextRenderingHint(pGraphics) {
5295 Ptr := "UPtr"
5296 result := 0
5297 E := DllCall("gdiplus\GdipGetTextRenderingHint", Ptr, pGraphics, "int*", result)
5298 If E
5299 return -1
5300 Return result
5301}
5302
5303;#####################################################################################
5304; More pGraphics functions
5305;#####################################################################################
5306
5307Gdip_RotateWorldTransform(pGraphics, Angle, MatrixOrder:=0) {
5308; MatrixOrder options:
5309; Prepend = 0; The new operation is applied before the old operation.
5310; Append = 1; The new operation is applied after the old operation.
5311; Order of matrices multiplication:.
5312
5313 return DllCall("gdiplus\GdipRotateWorldTransform", "UPtr", pGraphics, "float", Angle, "int", MatrixOrder)
5314}
5315
5316Gdip_ScaleWorldTransform(pGraphics, ScaleX, ScaleY, MatrixOrder:=0) {
5317 return DllCall("gdiplus\GdipScaleWorldTransform", "UPtr", pGraphics, "float", ScaleX, "float", ScaleY, "int", MatrixOrder)
5318}
5319
5320Gdip_TranslateWorldTransform(pGraphics, x, y, MatrixOrder:=0) {
5321 return DllCall("gdiplus\GdipTranslateWorldTransform", "UPtr", pGraphics, "float", x, "float", y, "int", MatrixOrder)
5322}
5323
5324Gdip_MultiplyWorldTransform(pGraphics, hMatrix, matrixOrder:=0) {
5325 Ptr := "UPtr"
5326 Return DllCall("gdiplus\GdipMultiplyWorldTransform", Ptr, pGraphics, Ptr, hMatrix, "int", matrixOrder)
5327}
5328
5329Gdip_ResetWorldTransform(pGraphics) {
5330 return DllCall("gdiplus\GdipResetWorldTransform", "UPtr", pGraphics)
5331}
5332
5333Gdip_ResetPageTransform(pGraphics) {
5334 return DllCall("gdiplus\GdipResetPageTransform", "UPtr", pGraphics)
5335}
5336
5337Gdip_SetWorldTransform(pGraphics, hMatrix) {
5338 Ptr := "UPtr"
5339 return DllCall("gdiplus\GdipSetWorldTransform", Ptr, pGraphics, Ptr, hMatrix)
5340}
5341
5342Gdip_GetRotatedTranslation(Width, Height, Angle, ByRef xTranslation, ByRef yTranslation) {
5343 pi := 3.14159, TAngle := Angle*(pi/180)
5344
5345 Bound := (Angle >= 0) ? Mod(Angle, 360) : 360-Mod(-Angle, -360)
5346 if ((Bound >= 0) && (Bound <= 90))
5347 xTranslation := Height*Sin(TAngle), yTranslation := 0
5348 else if ((Bound > 90) && (Bound <= 180))
5349 xTranslation := (Height*Sin(TAngle))-(Width*Cos(TAngle)), yTranslation := -Height*Cos(TAngle)
5350 else if ((Bound > 180) && (Bound <= 270))
5351 xTranslation := -(Width*Cos(TAngle)), yTranslation := -(Height*Cos(TAngle))-(Width*Sin(TAngle))
5352 else if ((Bound > 270) && (Bound <= 360))
5353 xTranslation := 0, yTranslation := -Width*Sin(TAngle)
5354}
5355
5356Gdip_GetRotatedDimensions(Width, Height, Angle, ByRef RWidth, ByRef RHeight) {
5357; modified by Marius Șucan; removed Ceil()
5358 Static pi := 3.14159
5359 if !(Width && Height)
5360 return -1
5361
5362 TAngle := Angle*(pi/180)
5363 RWidth := Abs(Width*Cos(TAngle))+Abs(Height*Sin(TAngle))
5364 RHeight := Abs(Width*Sin(TAngle))+Abs(Height*Cos(Tangle))
5365}
5366
5367Gdip_GetRotatedEllipseDimensions(Width, Height, Angle, ByRef RWidth, ByRef RHeight) {
5368 if !(Width && Height)
5369 return -1
5370
5371 pPath := Gdip_CreatePath()
5372 Gdip_AddPathEllipse(pPath, 0, 0, Width, Height)
5373 ; testAngle := Mod(Angle, 30)
5374 pMatrix := Gdip_CreateMatrix()
5375 Gdip_RotateMatrix(pMatrix, Angle, MatrixOrder)
5376 E := Gdip_TransformPath(pPath, pMatrix)
5377 Gdip_DeleteMatrix(pMatrix)
5378 pathBounds := Gdip_GetPathWorldBounds(pPath)
5379 Gdip_DeletePath(pPath)
5380 RWidth := pathBounds.w
5381 RHeight := pathBounds.h
5382 Return E
5383}
5384
5385Gdip_GetWorldTransform(pGraphics) {
5386; Returns the world transformation matrix of a pGraphics object.
5387; On error, it returns -1
5388 Ptr := "UPtr"
5389 hMatrix := 0
5390 E := DllCall("gdiplus\GdipGetWorldTransform", Ptr, pGraphics, "UPtr*", hMatrix)
5391 Return hMatrix
5392}
5393
5394Gdip_IsVisibleGraphPoint(pGraphics, X, Y) {
5395 Ptr := "UPtr"
5396 result := 0
5397 E := DllCall("gdiplus\GdipIsVisiblePoint", Ptr, pGraphics, "float", X, "float", Y, "int*", result)
5398 If E
5399 Return -1
5400 Return result
5401}
5402
5403Gdip_IsVisibleGraphRect(pGraphics, X, Y, Width, Height) {
5404 Ptr := "UPtr"
5405 result := 0
5406 E := DllCall("gdiplus\GdipIsVisibleRect", Ptr, pGraphics, "float", X, "float", Y, "float", Width, "float", Height, "int*", result)
5407 If E
5408 Return -1
5409 Return result
5410}
5411
5412Gdip_IsVisibleGraphRectEntirely(pGraphics, X, Y, Width, Height) {
5413 a := Gdip_IsVisibleGraphPoint(pGraphics, X, Y)
5414 b := Gdip_IsVisibleGraphPoint(pGraphics, X + Width, Y)
5415 c := Gdip_IsVisibleGraphPoint(pGraphics, X + Width, Y + Height)
5416 d := Gdip_IsVisibleGraphPoint(pGraphics, X, Y + Height)
5417 If (a=1 && b=1 && c=1 && d=1)
5418 Return 1
5419 Else If (a=-1 || b=-1 || c=-1 || d=-1)
5420 Return -1
5421 Else
5422 Return 0
5423}
5424
5425;#####################################################################################
5426; Region and clip functions [pGraphics related]
5427;
5428; One of the properties of the pGraphics class is the clip region.
5429; All drawing done in a given pGraphics object can be restricted
5430; to the clip region of that pGraphics object.
5431
5432; The GDI+ Region class allows you to define a custom shape.
5433; The shape[s] can be made up of lines, polygons, and curves.
5434;
5435; Two common uses for regions are hit testing and clipping.
5436; Hit testing is determining whether the mouse was clicked
5437; in a certain region of the screen.
5438;
5439; Clipping is restricting drawing to a certain region in
5440; a given pGraphics object.
5441;
5442;#####################################################################################
5443
5444Gdip_IsClipEmpty(pGraphics) {
5445; Determines whether the clipping region of a pGraphics object is empty
5446
5447 Ptr := "UPtr"
5448 result := 0
5449 E := DllCall("gdiplus\GdipIsClipEmpty", Ptr, pGraphics, "int*", result)
5450 If E
5451 Return -1
5452 Return result
5453}
5454
5455Gdip_IsVisibleClipEmpty(pGraphics) {
5456 Ptr := "UPtr"
5457 result := 0
5458 E := DllCall("gdiplus\GdipIsVisibleClipEmpty", Ptr, pGraphics, "uint*", result)
5459 If E
5460 Return -1
5461 Return result
5462}
5463
5464;#####################################################################################
5465
5466; Name............. Gdip_SetClipFromGraphics
5467;
5468; Parameters:
5469; pGraphicsA Pointer to a pGraphics object
5470; pGrahpicsB Pointer to a pGraphics object that contains the clipping region to be combined with
5471; the clipping region of the pGraphicsA object
5472; CombineMode Regions combination mode:
5473; 0 - The existing region is replaced by the new region
5474; 1 - The existing region is replaced by the intersection of itself and the new region
5475; 2 - The existing region is replaced by the union of itself and the new region
5476; 3 - The existing region is replaced by the result of performing an XOR on the two regions
5477; 4 - The existing region is replaced by the portion of itself that is outside of the new region
5478; 5 - The existing region is replaced by the portion of the new region that is outside of the existing region
5479; return Status enumeration value
5480
5481Gdip_SetClipFromGraphics(pGraphics, pGraphicsSrc, CombineMode:=0) {
5482 Ptr := "UPtr"
5483 return DllCall("gdiplus\GdipSetClipGraphics", Ptr, pGraphics, Ptr, pGraphicsSrc, "int", CombineMode)
5484}
5485
5486Gdip_GetClipBounds(pGraphics) {
5487 Ptr := "UPtr"
5488 rData := {}
5489
5490 VarSetCapacity(RectF, 16, 0)
5491 status := DllCall("gdiplus\GdipGetClipBounds", Ptr, pGraphics, Ptr, &RectF)
5492
5493 If (!status) {
5494 rData.x := NumGet(&RectF, 0, "float")
5495 , rData.y := NumGet(&RectF, 4, "float")
5496 , rData.w := NumGet(&RectF, 8, "float")
5497 , rData.h := NumGet(&RectF, 12, "float")
5498 } Else {
5499 Return status
5500 }
5501
5502 return rData
5503}
5504
5505Gdip_GetVisibleClipBounds(pGraphics) {
5506 Ptr := "UPtr"
5507 rData := {}
5508
5509 VarSetCapacity(RectF, 16, 0)
5510 status := DllCall("gdiplus\GdipGetVisibleClipBounds", Ptr, pGraphics, Ptr, &RectF)
5511
5512 If (!status) {
5513 rData.x := NumGet(&RectF, 0, "float")
5514 , rData.y := NumGet(&RectF, 4, "float")
5515 , rData.w := NumGet(&RectF, 8, "float")
5516 , rData.h := NumGet(&RectF, 12, "float")
5517 } Else {
5518 Return status
5519 }
5520
5521 return rData
5522}
5523
5524Gdip_TranslateClip(pGraphics, dX, dY) {
5525 Ptr := "UPtr"
5526 return DllCall("gdiplus\GdipTranslateClip", Ptr, pGraphics, "float", dX, "float", dY)
5527}
5528
5529Gdip_ResetClip(pGraphics) {
5530 return DllCall("gdiplus\GdipResetClip", "UPtr", pGraphics)
5531}
5532
5533Gdip_GetClipRegion(pGraphics) {
5534 Region := Gdip_CreateRegion()
5535 E := DllCall("gdiplus\GdipGetClip", "UPtr", pGraphics, "UInt", Region)
5536 If E
5537 return -1
5538 return Region
5539}
5540
5541Gdip_SetClipRegion(pGraphics, Region, CombineMode:=0) {
5542 ; see CombineMode options from Gdip_SetClipRect()
5543
5544 Ptr := "UPtr"
5545 return DllCall("gdiplus\GdipSetClipRegion", Ptr, pGraphics, Ptr, Region, "int", CombineMode)
5546}
5547
5548Gdip_SetClipRect(pGraphics, x, y, w, h, CombineMode:=0) {
5549; CombineMode options:
5550; Replace = 0
5551; Intersect = 1
5552; Union = 2
5553; Xor = 3
5554; Exclude = 4
5555; Complement = 5
5556
5557 return DllCall("gdiplus\GdipSetClipRect", "UPtr", pGraphics, "float", x, "float", y, "float", w, "float", h, "int", CombineMode)
5558}
5559
5560Gdip_SetClipPath(pGraphics, pPath, CombineMode:=0) {
5561 Ptr := "UPtr"
5562 return DllCall("gdiplus\GdipSetClipPath", Ptr, pGraphics, Ptr, pPath, "int", CombineMode)
5563}
5564
5565Gdip_CreateRegion() {
5566 Region := 0
5567 DllCall("gdiplus\GdipCreateRegion", "UInt*", Region)
5568 return Region
5569}
5570
5571Gdip_CombineRegionRegion(Region, Region2, CombineMode) {
5572; Updates this region to the portion of itself that intersects another region. Added by Learning one
5573; see CombineMode options from Gdip_SetClipRect()
5574
5575 Ptr := "UPtr"
5576 return DllCall("gdiplus\GdipCombineRegionRegion", Ptr, Region, Ptr, Region2, "int", CombineMode)
5577}
5578
5579Gdip_CombineRegionRect(Region, x, y, w, h, CombineMode) {
5580; Updates this region to the portion of itself that intersects with the given rectangle.
5581; see CombineMode options from Gdip_SetClipRect()
5582
5583 Ptr := "UPtr"
5584 CreateRectF(RectF, x, y, w, h)
5585 return DllCall("gdiplus\GdipCombineRegionRect", Ptr, Region, Ptr, &RectF, "int", CombineMode)
5586}
5587
5588Gdip_CombineRegionPath(Region, pPath, CombineMode) {
5589; see CombineMode options from Gdip_SetClipRect()
5590 Ptr := "UPtr"
5591 return DllCall("gdiplus\GdipCombineRegionPath", Ptr, Region, Ptr, pPath, "int", CombineMode)
5592}
5593
5594Gdip_CreateRegionPath(pPath) {
5595; Creates a region that is defined by a GraphicsPath [pPath object]. Written by Learning one.
5596
5597 Ptr := "UPtr"
5598 Region := 0
5599 E := DllCall("gdiplus\GdipCreateRegionPath", Ptr, pPath, "UInt*", Region)
5600 If E
5601 return -1
5602 return Region
5603}
5604
5605Gdip_CreateRegionRect(x, y, w, h) {
5606 CreateRectF(RectF, x, y, w, h)
5607 E := DllCall("gdiplus\GdipCreateRegionRect", "UPtr", &RectF, "UInt*", Region)
5608 If E
5609 return -1
5610 return Region
5611}
5612
5613Gdip_IsEmptyRegion(pGraphics, Region) {
5614 Ptr := "UPtr"
5615 result := 0
5616 E := DllCall("gdiplus\GdipIsEmptyRegion", Ptr, Region, Ptr, pGraphics, "uInt*", result)
5617 If E
5618 return -1
5619 Return result
5620}
5621
5622Gdip_IsEqualRegion(pGraphics, Region1, Region2) {
5623 Ptr := "UPtr"
5624 result := 0
5625 E := DllCall("gdiplus\GdipIsEqualRegion", Ptr, Region1, Ptr, Region2, Ptr, pGraphics, "uInt*", result)
5626 If E
5627 return -1
5628 Return result
5629}
5630
5631Gdip_IsInfiniteRegion(pGraphics, Region) {
5632 Ptr := "UPtr"
5633 result := 0
5634 E := DllCall("gdiplus\GdipIsInfiniteRegion", Ptr, Region, Ptr, pGraphics, "uInt*", result)
5635 If E
5636 return -1
5637 Return result
5638}
5639
5640Gdip_IsVisibleRegionPoint(pGraphics, Region, x, y) {
5641 Ptr := "UPtr"
5642 result := 0
5643 E := DllCall("gdiplus\GdipIsVisibleRegionPoint", Ptr, Region, "float", X, "float", Y, Ptr, pGraphics, "uInt*", result)
5644 If E
5645 return -1
5646 Return result
5647}
5648
5649Gdip_IsVisibleRegionRect(pGraphics, Region, x, y, width, height) {
5650 Ptr := "UPtr"
5651 result := 0
5652 E := DllCall("gdiplus\GdipIsVisibleRegionRect", Ptr, Region, "float", X, "float", Y, "float", Width, "float", Height, Ptr, pGraphics, "uInt*", result)
5653 If E
5654 return -1
5655 Return result
5656}
5657
5658Gdip_IsVisibleRegionRectEntirely(pGraphics, Region, x, y, width, height) {
5659 a := Gdip_IsVisibleRegionPoint(pGraphics, Region, X, Y)
5660 b := Gdip_IsVisibleRegionPoint(pGraphics, Region, X + Width, Y)
5661 c := Gdip_IsVisibleRegionPoint(pGraphics, Region, X + Width, Y + Height)
5662 d := Gdip_IsVisibleRegionPoint(pGraphics, Region, X, Y + Height)
5663 If (a=1 && b=1 && c=1 && d=1)
5664 Return 1
5665 Else If (a=-1 || b=-1 || c=-1 || d=-1)
5666 Return -1
5667 Else
5668 Return 0
5669}
5670
5671Gdip_SetEmptyRegion(Region) {
5672 Ptr := "UPtr"
5673 return DllCall("gdiplus\GdipSetEmpty", Ptr, Region)
5674}
5675
5676Gdip_SetInfiniteRegion(Region) {
5677 Ptr := "UPtr"
5678 return DllCall("gdiplus\GdipSetInfinite", Ptr, Region)
5679}
5680
5681Gdip_GetRegionBounds(pGraphics, Region) {
5682 Ptr := "UPtr"
5683 rData := {}
5684
5685 VarSetCapacity(RectF, 16, 0)
5686 status := DllCall("gdiplus\GdipGetRegionBounds", Ptr, Region, Ptr, pGraphics, Ptr, &RectF)
5687
5688 If (!status) {
5689 rData.x := NumGet(&RectF, 0, "float")
5690 , rData.y := NumGet(&RectF, 4, "float")
5691 , rData.w := NumGet(&RectF, 8, "float")
5692 , rData.h := NumGet(&RectF, 12, "float")
5693 } Else {
5694 Return status
5695 }
5696
5697 return rData
5698}
5699
5700Gdip_TranslateRegion(Region, X, Y) {
5701 Ptr := "UPtr"
5702 return DllCall("gdiplus\GdipTranslateRegion", Ptr, Region, "float", X, "float", Y)
5703}
5704
5705Gdip_RotateRegionAtCenter(pGraphics, Region, Angle, MatrixOrder:=1) {
5706; function by Marius Șucan
5707; based on Gdip_RotatePathAtCenter() by RazorHalo
5708
5709 Rect := Gdip_GetRegionBounds(pGraphics, Region)
5710 cX := Rect.x + (Rect.w / 2)
5711 cY := Rect.y + (Rect.h / 2)
5712 pMatrix := Gdip_CreateMatrix()
5713 Gdip_TranslateMatrix(pMatrix, -cX , -cY)
5714 Gdip_RotateMatrix(pMatrix, Angle, MatrixOrder)
5715 Gdip_TranslateMatrix(pMatrix, cX, cY, MatrixOrder)
5716 E := Gdip_TransformRegion(Region, pMatrix)
5717 Gdip_DeleteMatrix(pMatrix)
5718 Return E
5719}
5720
5721Gdip_TransformRegion(Region, pMatrix) {
5722 Ptr := "UPtr"
5723 return DllCall("gdiplus\GdipTransformRegion", Ptr, Region, Ptr, pMatrix)
5724}
5725
5726Gdip_CloneRegion(Region) {
5727 Ptr := "UPtr"
5728 newRegion := 0
5729 DllCall("gdiplus\GdipCloneRegion", Ptr, Region, "UInt*", newRegion)
5730 return newRegion
5731}
5732
5733;#####################################################################################
5734; BitmapLockBits
5735;#####################################################################################
5736
5737Gdip_LockBits(pBitmap, x, y, w, h, ByRef Stride, ByRef Scan0, ByRef BitmapData, LockMode := 3, PixelFormat := 0x26200a) {
5738 Ptr := "UPtr"
5739
5740 CreateRect(_Rect, x, y, w, h)
5741 VarSetCapacity(BitmapData, 16+2*A_PtrSize, 0)
5742 _E := DllCall("Gdiplus\GdipBitmapLockBits", Ptr, pBitmap, Ptr, &_Rect, "uint", LockMode, "int", PixelFormat, Ptr, &BitmapData)
5743 Stride := NumGet(BitmapData, 8, "Int")
5744 Scan0 := NumGet(BitmapData, 16, Ptr)
5745 return _E
5746}
5747
5748Gdip_UnlockBits(pBitmap, ByRef BitmapData) {
5749 Ptr := "UPtr"
5750 return DllCall("Gdiplus\GdipBitmapUnlockBits", Ptr, pBitmap, Ptr, &BitmapData)
5751}
5752
5753Gdip_SetLockBitPixel(ARGB, Scan0, x, y, Stride) {
5754 NumPut(ARGB, Scan0+0, (x*4)+(y*Stride), "UInt")
5755}
5756
5757Gdip_GetLockBitPixel(Scan0, x, y, Stride) {
5758 return NumGet(Scan0+0, (x*4)+(y*Stride), "UInt")
5759}
5760
5761;#####################################################################################
5762
5763Gdip_PixelateBitmap(pBitmap, ByRef pBitmapOut, BlockSize) {
5764; it does not work on x64, AHK_L Unicode, Windows 10
5765
5766 static PixelateBitmap
5767 Ptr := "UPtr"
5768 if (!PixelateBitmap)
5769 {
5770 if (A_PtrSize!=8) ; x86 machine code
5771 MCode_PixelateBitmap := "
5772 (LTrim Join
5773 558BEC83EC3C8B4514538B5D1C99F7FB56578BC88955EC894DD885C90F8E830200008B451099F7FB8365DC008365E000894DC88955F08945E833FF897DD4
5774 397DE80F8E160100008BCB0FAFCB894DCC33C08945F88945FC89451C8945143BD87E608B45088D50028BC82BCA8BF02BF2418945F48B45E02955F4894DC4
5775 8D0CB80FAFCB03CA895DD08BD1895DE40FB64416030145140FB60201451C8B45C40FB604100145FC8B45F40FB604020145F883C204FF4DE475D6034D18FF
5776 4DD075C98B4DCC8B451499F7F98945148B451C99F7F989451C8B45FC99F7F98945FC8B45F899F7F98945F885DB7E648B450C8D50028BC82BCA83C103894D
5777 C48BC82BCA41894DF48B4DD48945E48B45E02955E48D0C880FAFCB03CA895DD08BD18BF38A45148B7DC48804178A451C8B7DF488028A45FC8804178A45F8
5778 8B7DE488043A83C2044E75DA034D18FF4DD075CE8B4DCC8B7DD447897DD43B7DE80F8CF2FEFFFF837DF0000F842C01000033C08945F88945FC89451C8945
5779 148945E43BD87E65837DF0007E578B4DDC034DE48B75E80FAF4D180FAFF38B45088D500203CA8D0CB18BF08BF88945F48B45F02BF22BFA2955F48945CC0F
5780 B6440E030145140FB60101451C0FB6440F010145FC8B45F40FB604010145F883C104FF4DCC75D8FF45E4395DE47C9B8B4DF00FAFCB85C9740B8B451499F7
5781 F9894514EB048365140033F63BCE740B8B451C99F7F989451CEB0389751C3BCE740B8B45FC99F7F98945FCEB038975FC3BCE740B8B45F899F7F98945F8EB
5782 038975F88975E43BDE7E5A837DF0007E4C8B4DDC034DE48B75E80FAF4D180FAFF38B450C8D500203CA8D0CB18BF08BF82BF22BFA2BC28B55F08955CC8A55
5783 1488540E038A551C88118A55FC88540F018A55F888140183C104FF4DCC75DFFF45E4395DE47CA68B45180145E0015DDCFF4DC80F8594FDFFFF8B451099F7
5784 FB8955F08945E885C00F8E450100008B45EC0FAFC38365DC008945D48B45E88945CC33C08945F88945FC89451C8945148945103945EC7E6085DB7E518B4D
5785 D88B45080FAFCB034D108D50020FAF4D18034DDC8BF08BF88945F403CA2BF22BFA2955F4895DC80FB6440E030145140FB60101451C0FB6440F010145FC8B
5786 45F40FB604080145F883C104FF4DC875D8FF45108B45103B45EC7CA08B4DD485C9740B8B451499F7F9894514EB048365140033F63BCE740B8B451C99F7F9
5787 89451CEB0389751C3BCE740B8B45FC99F7F98945FCEB038975FC3BCE740B8B45F899F7F98945F8EB038975F88975103975EC7E5585DB7E468B4DD88B450C
5788 0FAFCB034D108D50020FAF4D18034DDC8BF08BF803CA2BF22BFA2BC2895DC88A551488540E038A551C88118A55FC88540F018A55F888140183C104FF4DC8
5789 75DFFF45108B45103B45EC7CAB8BC3C1E0020145DCFF4DCC0F85CEFEFFFF8B4DEC33C08945F88945FC89451C8945148945103BC87E6C3945F07E5C8B4DD8
5790 8B75E80FAFCB034D100FAFF30FAF4D188B45088D500203CA8D0CB18BF08BF88945F48B45F02BF22BFA2955F48945C80FB6440E030145140FB60101451C0F
5791 B6440F010145FC8B45F40FB604010145F883C104FF4DC875D833C0FF45108B4DEC394D107C940FAF4DF03BC874068B451499F7F933F68945143BCE740B8B
5792 451C99F7F989451CEB0389751C3BCE740B8B45FC99F7F98945FCEB038975FC3BCE740B8B45F899F7F98945F8EB038975F88975083975EC7E63EB0233F639
5793 75F07E4F8B4DD88B75E80FAFCB034D080FAFF30FAF4D188B450C8D500203CA8D0CB18BF08BF82BF22BFA2BC28B55F08955108A551488540E038A551C8811
5794 8A55FC88540F018A55F888140883C104FF4D1075DFFF45088B45083B45EC7C9F5F5E33C05BC9C21800
5795 )"
5796 else ; x64 machine code
5797 MCode_PixelateBitmap := "
5798 (LTrim Join
5799 4489442418488954241048894C24085355565741544155415641574883EC28418BC1448B8C24980000004C8BDA99488BD941F7F9448BD0448BFA8954240C
5800 448994248800000085C00F8E9D020000418BC04533E4458BF299448924244C8954241041F7F933C9898C24980000008BEA89542404448BE889442408EB05
5801 4C8B5C24784585ED0F8E1A010000458BF1418BFD48897C2418450FAFF14533D233F633ED4533E44533ED4585C97E5B4C63BC2490000000418D040A410FAF
5802 C148984C8D441802498BD9498BD04D8BD90FB642010FB64AFF4403E80FB60203E90FB64AFE4883C2044403E003F149FFCB75DE4D03C748FFCB75D0488B7C
5803 24188B8C24980000004C8B5C2478418BC59941F7FE448BE8418BC49941F7FE448BE08BC59941F7FE8BE88BC69941F7FE8BF04585C97E4048639C24900000
5804 004103CA4D8BC1410FAFC94863C94A8D541902488BCA498BC144886901448821408869FF408871FE4883C10448FFC875E84803D349FFC875DA8B8C249800
5805 0000488B5C24704C8B5C24784183C20448FFCF48897C24180F850AFFFFFF8B6C2404448B2424448B6C24084C8B74241085ED0F840A01000033FF33DB4533
5806 DB4533D24533C04585C97E53488B74247085ED7E42438D0C04418BC50FAF8C2490000000410FAFC18D04814863C8488D5431028BCD0FB642014403D00FB6
5807 024883C2044403D80FB642FB03D80FB642FA03F848FFC975DE41FFC0453BC17CB28BCD410FAFC985C9740A418BC299F7F98BF0EB0233F685C9740B418BC3
5808 99F7F9448BD8EB034533DB85C9740A8BC399F7F9448BD0EB034533D285C9740A8BC799F7F9448BC0EB034533C033D24585C97E4D4C8B74247885ED7E3841
5809 8D0C14418BC50FAF8C2490000000410FAFC18D04814863C84A8D4431028BCD40887001448818448850FF448840FE4883C00448FFC975E8FFC2413BD17CBD
5810 4C8B7424108B8C2498000000038C2490000000488B5C24704503E149FFCE44892424898C24980000004C897424100F859EFDFFFF448B7C240C448B842480
5811 000000418BC09941F7F98BE8448BEA89942498000000896C240C85C00F8E3B010000448BAC2488000000418BCF448BF5410FAFC9898C248000000033FF33
5812 ED33F64533DB4533D24533C04585FF7E524585C97E40418BC5410FAFC14103C00FAF84249000000003C74898488D541802498BD90FB642014403D00FB602
5813 4883C2044403D80FB642FB03F00FB642FA03E848FFCB75DE488B5C247041FFC0453BC77CAE85C9740B418BC299F7F9448BE0EB034533E485C9740A418BC3
5814 99F7F98BD8EB0233DB85C9740A8BC699F7F9448BD8EB034533DB85C9740A8BC599F7F9448BD0EB034533D24533C04585FF7E4E488B4C24784585C97E3541
5815 8BC5410FAFC14103C00FAF84249000000003C74898488D540802498BC144886201881A44885AFF448852FE4883C20448FFC875E941FFC0453BC77CBE8B8C
5816 2480000000488B5C2470418BC1C1E00203F849FFCE0F85ECFEFFFF448BAC24980000008B6C240C448BA4248800000033FF33DB4533DB4533D24533C04585
5817 FF7E5A488B7424704585ED7E48418BCC8BC5410FAFC94103C80FAF8C2490000000410FAFC18D04814863C8488D543102418BCD0FB642014403D00FB60248
5818 83C2044403D80FB642FB03D80FB642FA03F848FFC975DE41FFC0453BC77CAB418BCF410FAFCD85C9740A418BC299F7F98BF0EB0233F685C9740B418BC399
5819 F7F9448BD8EB034533DB85C9740A8BC399F7F9448BD0EB034533D285C9740A8BC799F7F9448BC0EB034533C033D24585FF7E4E4585ED7E42418BCC8BC541
5820 0FAFC903CA0FAF8C2490000000410FAFC18D04814863C8488B442478488D440102418BCD40887001448818448850FF448840FE4883C00448FFC975E8FFC2
5821 413BD77CB233C04883C428415F415E415D415C5F5E5D5BC3
5822 )"
5823 VarSetCapacity(PixelateBitmap, StrLen(MCode_PixelateBitmap)//2)
5824 nCount := StrLen(MCode_PixelateBitmap)//2
5825 N := (A_AhkVersion < 2) ? nCount : "nCount"
5826 Loop %N%
5827 NumPut("0x" SubStr(MCode_PixelateBitmap, (2*A_Index)-1, 2), PixelateBitmap, A_Index-1, "UChar")
5828 DllCall("VirtualProtect", Ptr, &PixelateBitmap, Ptr, VarSetCapacity(PixelateBitmap), "uint", 0x40, "UPtr*", 0)
5829 }
5830
5831 Gdip_GetImageDimensions(pBitmap, Width, Height)
5832 if (Width != Gdip_GetImageWidth(pBitmapOut) || Height != Gdip_GetImageHeight(pBitmapOut))
5833 return -1
5834
5835 if (BlockSize > Width || BlockSize > Height)
5836 return -2
5837
5838 E1 := Gdip_LockBits(pBitmap, 0, 0, Width, Height, Stride1, Scan01, BitmapData1)
5839 E2 := Gdip_LockBits(pBitmapOut, 0, 0, Width, Height, Stride2, Scan02, BitmapData2)
5840 if (E1 || E2)
5841 return -3
5842
5843 ; E := - unused exit code
5844 DllCall(&PixelateBitmap, Ptr, Scan01, Ptr, Scan02, "int", Width, "int", Height, "int", Stride1, "int", BlockSize)
5845
5846 Gdip_UnlockBits(pBitmap, BitmapData1), Gdip_UnlockBits(pBitmapOut, BitmapData2)
5847 return 0
5848}
5849
5850;#####################################################################################
5851
5852Gdip_ToARGB(A, R, G, B) {
5853 return (A << 24) | (R << 16) | (G << 8) | B
5854}
5855
5856Gdip_FromARGB(ARGB, ByRef A, ByRef R, ByRef G, ByRef B) {
5857 A := (0xff000000 & ARGB) >> 24
5858 R := (0x00ff0000 & ARGB) >> 16
5859 G := (0x0000ff00 & ARGB) >> 8
5860 B := 0x000000ff & ARGB
5861}
5862
5863Gdip_AFromARGB(ARGB) {
5864 return (0xff000000 & ARGB) >> 24
5865}
5866
5867Gdip_RFromARGB(ARGB) {
5868 return (0x00ff0000 & ARGB) >> 16
5869}
5870
5871Gdip_GFromARGB(ARGB) {
5872 return (0x0000ff00 & ARGB) >> 8
5873}
5874
5875Gdip_BFromARGB(ARGB) {
5876 return 0x000000ff & ARGB
5877}
5878
5879;#####################################################################################
5880
5881StrGetB(Address, Length:=-1, Encoding:=0) {
5882 ; Flexible parameter handling:
5883 if !IsInteger(Length)
5884 Encoding := Length, Length := -1
5885
5886 ; Check for obvious errors.
5887 if (Address+0 < 1024)
5888 return
5889
5890 ; Ensure 'Encoding' contains a numeric identifier.
5891 if (Encoding = "UTF-16")
5892 Encoding := 1200
5893 else if (Encoding = "UTF-8")
5894 Encoding := 65001
5895 else if SubStr(Encoding,1,2)="CP"
5896 Encoding := SubStr(Encoding,3)
5897
5898 if !Encoding ; "" or 0
5899 {
5900 ; No conversion necessary, but we might not want the whole string.
5901 if (Length == -1)
5902 Length := DllCall("lstrlen", "uint", Address)
5903 VarSetCapacity(String, Length)
5904 DllCall("lstrcpyn", "str", String, "uint", Address, "int", Length + 1)
5905 }
5906 else if (Encoding = 1200) ; UTF-16
5907 {
5908 char_count := DllCall("WideCharToMultiByte", "uint", 0, "uint", 0x400, "uint", Address, "int", Length, "uint", 0, "uint", 0, "uint", 0, "uint", 0)
5909 VarSetCapacity(String, char_count)
5910 DllCall("WideCharToMultiByte", "uint", 0, "uint", 0x400, "uint", Address, "int", Length, "str", String, "int", char_count, "uint", 0, "uint", 0)
5911 }
5912 else if IsInteger(Encoding)
5913 {
5914 ; Convert from target encoding to UTF-16 then to the active code page.
5915 char_count := DllCall("MultiByteToWideChar", "uint", Encoding, "uint", 0, "uint", Address, "int", Length, "uint", 0, "int", 0)
5916 VarSetCapacity(String, char_count * 2)
5917 char_count := DllCall("MultiByteToWideChar", "uint", Encoding, "uint", 0, "uint", Address, "int", Length, "uint", &String, "int", char_count * 2)
5918 String := StrGetB(&String, char_count, 1200)
5919 }
5920
5921 return String
5922}
5923
5924Gdip_Startup(multipleInstances:=0) {
5925 Ptr := "UPtr"
5926 pToken := 0
5927
5928 If (multipleInstances=0)
5929 {
5930 if !DllCall("GetModuleHandle", "str", "gdiplus", Ptr)
5931 DllCall("LoadLibrary", "str", "gdiplus")
5932 } Else DllCall("LoadLibrary", "str", "gdiplus")
5933
5934 VarSetCapacity(si, A_PtrSize = 8 ? 24 : 16, 0), si := Chr(1)
5935 DllCall("gdiplus\GdiplusStartup", "UPtr*", pToken, Ptr, &si, Ptr, 0)
5936 return pToken
5937}
5938
5939Gdip_Shutdown(pToken) {
5940 Ptr := "UPtr"
5941
5942 DllCall("gdiplus\GdiplusShutdown", Ptr, pToken)
5943 hModule := DllCall("GetModuleHandle", "str", "gdiplus", Ptr)
5944 if hModule
5945 DllCall("FreeLibrary", Ptr, hModule)
5946 return 0
5947}
5948
5949;#####################################################################################
5950; in AHK v1: uses normal 'if var is' command
5951; in AHK v2: all if's are expression-if, so the Integer variable is dereferenced to the string
5952;#####################################################################################
5953IsInteger(Var) {
5954 Static Integer := "Integer"
5955 If Var Is Integer
5956 Return True
5957 Return False
5958}
5959
5960IsNumber(Var) {
5961 Static number := "number"
5962 If Var Is number
5963 Return True
5964 Return False
5965}
5966
5967; ======================================================================================================================
5968; Multiple Display Monitors Functions -> msdn.microsoft.com/en-us/library/dd145072(v=vs.85).aspx
5969; by 'just me'
5970; https://autohotkey.com/boards/viewtopic.php?f=6&t=4606
5971; ======================================================================================================================
5972
5973GetMonitorCount() {
5974 Monitors := MDMF_Enum()
5975 for k,v in Monitors
5976 count := A_Index
5977 return count
5978}
5979
5980GetMonitorInfo(MonitorNum) {
5981 Monitors := MDMF_Enum()
5982 for k,v in Monitors
5983 if (v.Num = MonitorNum)
5984 return v
5985}
5986
5987GetPrimaryMonitor() {
5988 Monitors := MDMF_Enum()
5989 for k,v in Monitors
5990 If (v.Primary)
5991 return v.Num
5992}
5993
5994; ----------------------------------------------------------------------------------------------------------------------
5995; Name ..........: MDMF - Multiple Display Monitor Functions
5996; Description ...: Various functions for multiple display monitor environments
5997; Tested with ...: AHK 1.1.32.00 (A32/U32/U64) and 2.0-a108-a2fa0498 (U32/U64)
5998; Original Author: just me (https://www.autohotkey.com/boards/viewtopic.php?f=6&t=4606)
5999; Mod Authors ...: iPhilip, guest3456
6000; Changes .......: Modified to work with v2.0-a108 and changed 'Count' key to 'TotalCount' to avoid conflicts
6001; ................ Modified MDMF_Enum() so that it works under both AHK v1 and v2.
6002; ................ Modified MDMF_EnumProc() to provide Count and Primary keys to the Monitors array.
6003; ................ Modified MDMF_FromHWND() to allow flag values that determine the function's return value if the
6004; ................ window does not intersect any display monitor.
6005; ................ Modified MDMF_FromPoint() to allow the cursor position to be returned ByRef if not specified and
6006; ................ allow flag values that determine the function's return value if the point is not contained within
6007; ................ any display monitor.
6008; ................ Modified MDMF_FromRect() to allow flag values that determine the function's return value if the
6009; ................ rectangle does not intersect any display monitor.
6010;................. Modified MDMF_GetInfo() with minor changes.
6011; ----------------------------------------------------------------------------------------------------------------------
6012;
6013; ======================================================================================================================
6014; Multiple Display Monitors Functions -> msdn.microsoft.com/en-us/library/dd145072(v=vs.85).aspx =======================
6015; ======================================================================================================================
6016; Enumerates display monitors and returns an object containing the properties of all monitors or the specified monitor.
6017; ======================================================================================================================
6018
6019MDMF_Enum(HMON := "") {
6020 Static CallbackFunc := Func(A_AhkVersion < "2" ? "RegisterCallback" : "CallbackCreate")
6021 Static EnumProc := CallbackFunc.Call("MDMF_EnumProc")
6022 Static Obj := (A_AhkVersion < "2") ? "Object" : "Map"
6023 Static Monitors := {}
6024 If (HMON = "") ; new enumeration
6025 {
6026 Monitors := %Obj%("TotalCount", 0)
6027 If !DllCall("User32.dll\EnumDisplayMonitors", "Ptr", 0, "Ptr", 0, "Ptr", EnumProc, "Ptr", &Monitors, "Int")
6028 Return False
6029 }
6030 Return (HMON = "") ? Monitors : Monitors.HasKey(HMON) ? Monitors[HMON] : False
6031}
6032; ======================================================================================================================
6033; Callback function that is called by the MDMF_Enum function.
6034; ======================================================================================================================
6035MDMF_EnumProc(HMON, HDC, PRECT, ObjectAddr) {
6036 Monitors := Object(ObjectAddr)
6037 Monitors[HMON] := MDMF_GetInfo(HMON)
6038 Monitors["TotalCount"]++
6039 If (Monitors[HMON].Primary)
6040 Monitors["Primary"] := HMON
6041 Return True
6042}
6043; ======================================================================================================================
6044; Retrieves the display monitor that has the largest area of intersection with a specified window.
6045; The following flag values determine the function's return value if the window does not intersect any display monitor:
6046; MONITOR_DEFAULTTONULL = 0 - Returns NULL.
6047; MONITOR_DEFAULTTOPRIMARY = 1 - Returns a handle to the primary display monitor.
6048; MONITOR_DEFAULTTONEAREST = 2 - Returns a handle to the display monitor that is nearest to the window.
6049; ======================================================================================================================
6050MDMF_FromHWND(HWND, Flag := 0) {
6051 Return DllCall("User32.dll\MonitorFromWindow", "Ptr", HWND, "UInt", Flag, "Ptr")
6052}
6053; ======================================================================================================================
6054; Retrieves the display monitor that contains a specified point.
6055; If either X or Y is empty, the function will use the current cursor position for this value and return it ByRef.
6056; The following flag values determine the function's return value if the point is not contained within any
6057; display monitor:
6058; MONITOR_DEFAULTTONULL = 0 - Returns NULL.
6059; MONITOR_DEFAULTTOPRIMARY = 1 - Returns a handle to the primary display monitor.
6060; MONITOR_DEFAULTTONEAREST = 2 - Returns a handle to the display monitor that is nearest to the point.
6061; ======================================================================================================================
6062MDMF_FromPoint(ByRef X := "", ByRef Y := "", Flag := 0) {
6063 If (X = "") || (Y = "") {
6064 VarSetCapacity(PT, 8, 0)
6065 DllCall("User32.dll\GetCursorPos", "Ptr", &PT, "Int")
6066 If (X = "")
6067 X := NumGet(PT, 0, "Int")
6068 If (Y = "")
6069 Y := NumGet(PT, 4, "Int")
6070 }
6071 Return DllCall("User32.dll\MonitorFromPoint", "Int64", (X & 0xFFFFFFFF) | (Y << 32), "UInt", Flag, "Ptr")
6072}
6073; ======================================================================================================================
6074; Retrieves the display monitor that has the largest area of intersection with a specified rectangle.
6075; Parameters are consistent with the common AHK definition of a rectangle, which is X, Y, W, H instead of
6076; Left, Top, Right, Bottom.
6077; The following flag values determine the function's return value if the rectangle does not intersect any
6078; display monitor:
6079; MONITOR_DEFAULTTONULL = 0 - Returns NULL.
6080; MONITOR_DEFAULTTOPRIMARY = 1 - Returns a handle to the primary display monitor.
6081; MONITOR_DEFAULTTONEAREST = 2 - Returns a handle to the display monitor that is nearest to the rectangle.
6082; ======================================================================================================================
6083MDMF_FromRect(X, Y, W, H, Flag := 0) {
6084 VarSetCapacity(RC, 16, 0)
6085 NumPut(X, RC, 0, "Int"), NumPut(Y, RC, 4, "Int"), NumPut(X + W, RC, 8, "Int"), NumPut(Y + H, RC, 12, "Int")
6086 Return DllCall("User32.dll\MonitorFromRect", "Ptr", &RC, "UInt", Flag, "Ptr")
6087}
6088; ======================================================================================================================
6089; Retrieves information about a display monitor.
6090; ======================================================================================================================
6091MDMF_GetInfo(HMON) {
6092 NumPut(VarSetCapacity(MIEX, 40 + (32 << !!A_IsUnicode)), MIEX, 0, "UInt")
6093 If DllCall("User32.dll\GetMonitorInfo", "Ptr", HMON, "Ptr", &MIEX, "Int")
6094 Return {Name: (Name := StrGet(&MIEX + 40, 32)) ; CCHDEVICENAME = 32
6095 , Num: RegExReplace(Name, ".*(\d+)$", "$1")
6096 , Left: NumGet(MIEX, 4, "Int") ; display rectangle
6097 , Top: NumGet(MIEX, 8, "Int") ; "
6098 , Right: NumGet(MIEX, 12, "Int") ; "
6099 , Bottom: NumGet(MIEX, 16, "Int") ; "
6100 , WALeft: NumGet(MIEX, 20, "Int") ; work area
6101 , WATop: NumGet(MIEX, 24, "Int") ; "
6102 , WARight: NumGet(MIEX, 28, "Int") ; "
6103 , WABottom: NumGet(MIEX, 32, "Int") ; "
6104 , Primary: NumGet(MIEX, 36, "UInt")} ; contains a non-zero value for the primary monitor.
6105 Return False
6106}
6107
6108;######################################################################################################################################
6109; The following functions are written by Just Me
6110; Taken from https://autohotkey.com/board/topic/85238-get-image-metadata-using-gdi-ahk-l/
6111; October 2013; minimal modifications by Marius Șucan in July 2019
6112
6113Gdip_LoadImageFromFile(sFile, useICM:=0) {
6114; An Image object encapsulates a bitmap or a metafile and stores attributes that you can retrieve.
6115 pImage := 0
6116 function2call := (useICM=1) ? "GdipLoadImageFromFileICM" : "GdipLoadImageFromFile"
6117 R := DllCall("gdiplus\" function2call, "WStr", sFile, "UPtrP", pImage)
6118 ErrorLevel := R
6119 Return pImage
6120}
6121
6122;######################################################################################################################################
6123; Gdip_GetPropertyCount() - Gets the number of properties (pieces of metadata) stored in this Image object.
6124; Parameters:
6125; pImage - Pointer to the Image object.
6126; Return values:
6127; On success - Number of properties.
6128; On failure - 0, ErrorLevel contains the GDIP status
6129;######################################################################################################################################
6130
6131Gdip_GetPropertyCount(pImage) {
6132 PropCount := 0
6133 Ptr := "UPtr"
6134 R := DllCall("gdiplus\GdipGetPropertyCount", Ptr, pImage, "UIntP", PropCount)
6135 ErrorLevel := R
6136 Return PropCount
6137}
6138
6139;######################################################################################################################################
6140; Gdip_GetPropertyIdList() - Gets an aray of the property identifiers used in the metadata of this Image object.
6141; Parameters:
6142; pImage - Pointer to the Image object.
6143; Return values:
6144; On success - Array containing the property identifiers as integer keys and the name retrieved from
6145; Gdip_GetPropertyTagName(PropID) as values.
6146; The total number of properties is stored in Array.Count.
6147; On failure - False, ErrorLevel contains the GDIP status
6148;######################################################################################################################################
6149
6150Gdip_GetPropertyIdList(pImage) {
6151 PropNum := Gdip_GetPropertyCount(pImage)
6152 Ptr := "UPtr"
6153 If (ErrorLevel) || (PropNum = 0)
6154 Return False
6155 VarSetCapacity(PropIDList, 4 * PropNum, 0)
6156 R := DllCall("gdiplus\GdipGetPropertyIdList", Ptr, pImage, "UInt", PropNum, "Ptr", &PropIDList)
6157 If (R) {
6158 ErrorLevel := R
6159 Return False
6160 }
6161
6162 PropArray := {Count: PropNum}
6163 Loop %PropNum%
6164 {
6165 PropID := NumGet(PropIDList, (A_Index - 1) << 2, "UInt")
6166 PropArray[PropID] := Gdip_GetPropertyTagName(PropID)
6167 }
6168 Return PropArray
6169}
6170
6171;######################################################################################################################################
6172; Gdip_GetPropertyItem() - Gets a specified property item (piece of metadata) from this Image object.
6173; Parameters:
6174; pImage - Pointer to the Image object.
6175; PropID - Integer that identifies the property item to be retrieved (see Gdip_GetPropertyTagName()).
6176; Return values:
6177; On success - Property item object containing three keys:
6178; Length - Length of the value in bytes.
6179; Type - Type of the value (see Gdip_GetPropertyTagType()).
6180; Value - The value itself.
6181; On failure - False, ErrorLevel contains the GDIP status
6182;######################################################################################################################################
6183
6184Gdip_GetPropertyItem(pImage, PropID) {
6185 PropItem := {Length: 0, Type: 0, Value: ""}
6186 ItemSize := 0
6187 R := DllCall("gdiplus\GdipGetPropertyItemSize", "Ptr", pImage, "UInt", PropID, "UIntP", ItemSize)
6188 If (R) {
6189 ErrorLevel := R
6190 Return False
6191 }
6192
6193 Ptr := "UPtr"
6194 VarSetCapacity(Item, ItemSize, 0)
6195 R := DllCall("gdiplus\GdipGetPropertyItem", Ptr, pImage, "UInt", PropID, "UInt", ItemSize, "Ptr", &Item)
6196 If (R) {
6197 ErrorLevel := R
6198 Return False
6199 }
6200 PropLen := NumGet(Item, 4, "UInt")
6201 PropType := NumGet(Item, 8, "Short")
6202 PropAddr := NumGet(Item, 8 + A_PtrSize, "UPtr")
6203 PropItem.Length := PropLen
6204 PropItem.Type := PropType
6205 If (PropLen > 0)
6206 {
6207 PropVal := ""
6208 Gdip_GetPropertyItemValue(PropVal, PropLen, PropType, PropAddr)
6209 If (PropType = 1) || (PropType = 7) {
6210 PropItem.SetCapacity("Value", PropLen)
6211 ValAddr := PropItem.GetAddress("Value")
6212 DllCall("Kernel32.dll\RtlMoveMemory", "Ptr", ValAddr, "Ptr", &PropVal, "Ptr", PropLen)
6213 } Else {
6214 PropItem.Value := PropVal
6215 }
6216 }
6217 ErrorLevel := 0
6218 Return PropItem
6219}
6220
6221;######################################################################################################################################
6222; Gdip_GetAllPropertyItems() - Gets all the property items (metadata) stored in this Image object.
6223; Parameters:
6224; pImage - Pointer to the Image object.
6225; Return values:
6226; On success - Properties object containing one integer key for each property ID. Each value is an object
6227; containing three keys:
6228; Length - Length of the value in bytes.
6229; Type - Type of the value (see Gdip_GetPropertyTagType()).
6230; Value - The value itself.
6231; The total number of properties is stored in Properties.Count.
6232; On failure - False, ErrorLevel contains the GDIP status
6233;######################################################################################################################################
6234
6235Gdip_GetAllPropertyItems(pImage) {
6236 BufSize := PropNum := ErrorLevel := 0
6237 R := DllCall("gdiplus\GdipGetPropertySize", "Ptr", pImage, "UIntP", BufSize, "UIntP", PropNum)
6238 If (R) || (PropNum = 0) {
6239 ErrorLevel := R ? R : 19 ; 19 = PropertyNotFound
6240 Return False
6241 }
6242 VarSetCapacity(Buffer, BufSize, 0)
6243 Ptr := "UPtr"
6244 R := DllCall("gdiplus\GdipGetAllPropertyItems", Ptr, pImage, "UInt", BufSize, "UInt", PropNum, "Ptr", &Buffer)
6245 If (R) {
6246 ErrorLevel := R
6247 Return False
6248 }
6249 PropsObj := {Count: PropNum}
6250 PropSize := 8 + (2 * A_PtrSize)
6251
6252 Loop %PropNum%
6253 {
6254 OffSet := PropSize * (A_Index - 1)
6255 PropID := NumGet(Buffer, OffSet, "UInt")
6256 PropLen := NumGet(Buffer, OffSet + 4, "UInt")
6257 PropType := NumGet(Buffer, OffSet + 8, "Short")
6258 PropAddr := NumGet(Buffer, OffSet + 8 + A_PtrSize, "UPtr")
6259 PropVal := ""
6260 PropsObj[PropID] := {}
6261 PropsObj[PropID, "Length"] := PropLen
6262 PropsObj[PropID, "Type"] := PropType
6263 PropsObj[PropID, "Value"] := PropVal
6264 If (PropLen > 0)
6265 {
6266 Gdip_GetPropertyItemValue(PropVal, PropLen, PropType, PropAddr)
6267 If (PropType = 1) || (PropType = 7)
6268 {
6269 PropsObj[PropID].SetCapacity("Value", PropLen)
6270 ValAddr := PropsObj[PropID].GetAddress("Value")
6271 DllCall("Kernel32.dll\RtlMoveMemory", "Ptr", ValAddr, "Ptr", PropAddr, "Ptr", PropLen)
6272 } Else {
6273 PropsObj[PropID].Value := PropVal
6274 }
6275 }
6276 }
6277 ErrorLevel := 0
6278 Return PropsObj
6279}
6280
6281;######################################################################################################################################
6282; Gdip_GetPropertyTagName() - Gets the name for the integer identifier of this property as defined in "Gdiplusimaging.h".
6283; Parameters:
6284; PropID - Integer that identifies the property item to be retrieved.
6285; Return values:
6286; On success - Corresponding name.
6287; On failure - "Unknown"
6288;######################################################################################################################################
6289
6290Gdip_GetPropertyTagName(PropID) {
6291; All tags are taken from "Gdiplusimaging.h", probably there will be more.
6292; For most of them you'll find a description on http://msdn.microsoft.com/en-us/library/ms534418(VS.85).aspx
6293;
6294; modified by Marius Șucan in July/August 2019:
6295; I transformed the function to not yield errors on AHK v2
6296
6297 Static PropTagsA := {0x0001:"GPS LatitudeRef",0x0002:"GPS Latitude",0x0003:"GPS LongitudeRef",0x0004:"GPS Longitude",0x0005:"GPS AltitudeRef",0x0006:"GPS Altitude",0x0007:"GPS Time",0x0008:"GPS Satellites",0x0009:"GPS Status",0x000A:"GPS MeasureMode",0x001D:"GPS Date",0x001E:"GPS Differential",0x00FE:"NewSubfileType",0x00FF:"SubfileType",0x0102:"Bits Per Sample",0x0103:"Compression",0x0106:"Photometric Interpolation",0x0107:"ThreshHolding",0x010A:"Fill Order",0x010D:"Document Name",0x010E:"Image Description",0x010F:"Equipment Make",0x0110:"Equipment Model",0x0112:"Orientation",0x0115:"Samples Per Pixel",0x0118:"Min Sample Value",0x0119:"Max Sample Value",0x011D:"Page Name",0x0122:"GrayResponseUnit",0x0123:"GrayResponseCurve",0x0128:"Resolution Unit",0x012D:"Transfer Function",0x0131:"Software Used",0x0132:"Internal Date Time",0x013B:"Artist"
6298 ,0x013C:"Host Computer",0x013D:"Predictor",0x013E:"White Point",0x013F:"Primary Chromaticities",0x0140:"Color Map",0x014C:"Ink Set",0x014D:"Ink Names",0x014E:"Number Of Inks",0x0150:"Dot Range",0x0151:"Target Printer",0x0152:"Extra Samples",0x0153:"Sample Format",0x0156:"Transfer Range",0x0200:"JPEGProc",0x0205:"JPEGLosslessPredictors",0x0301:"Gamma",0x0302:"ICC Profile Descriptor",0x0303:"SRGB Rendering Intent",0x0320:"Image Title",0x5010:"JPEG Quality",0x5011:"Grid Size",0x501A:"Color Transfer Function",0x5100:"Frame Delay",0x5101:"Loop Count",0x5110:"Pixel Unit",0x5111:"Pixel Per Unit X",0x5112:"Pixel Per Unit Y",0x8298:"Copyright",0x829A:"EXIF Exposure Time",0x829D:"EXIF F Number",0x8773:"ICC Profile",0x8822:"EXIF ExposureProg",0x8824:"EXIF SpectralSense",0x8827:"EXIF ISO Speed",0x9003:"EXIF Date Original",0x9004:"EXIF Date Digitized"
6299 ,0x9102:"EXIF CompBPP",0x9201:"EXIF Shutter Speed",0x9202:"EXIF Aperture",0x9203:"EXIF Brightness",0x9204:"EXIF Exposure Bias",0x9205:"EXIF Max. Aperture",0x9206:"EXIF Subject Dist",0x9207:"EXIF Metering Mode",0x9208:"EXIF Light Source",0x9209:"EXIF Flash",0x920A:"EXIF Focal Length",0x9214:"EXIF Subject Area",0x927C:"EXIF Maker Note",0x9286:"EXIF Comments",0xA001:"EXIF Color Space",0xA002:"EXIF PixXDim",0xA003:"EXIF PixYDim",0xA004:"EXIF Related WAV",0xA005:"EXIF Interop",0xA20B:"EXIF Flash Energy",0xA20E:"EXIF Focal X Res",0xA20F:"EXIF Focal Y Res",0xA210:"EXIF FocalResUnit",0xA214:"EXIF Subject Loc",0xA215:"EXIF Exposure Index",0xA217:"EXIF Sensing Method",0xA300:"EXIF File Source",0xA301:"EXIF Scene Type",0xA401:"EXIF Custom Rendered",0xA402:"EXIF Exposure Mode",0xA403:"EXIF White Balance",0xA404:"EXIF Digital Zoom Ratio"
6300 ,0xA405:"EXIF Focal Length In 35mm Film",0xA406:"EXIF Scene Capture Type",0xA407:"EXIF Gain Control",0xA408:"EXIF Contrast",0xA409:"EXIF Saturation",0xA40A:"EXIF Sharpness",0xA40B:"EXIF Device Setting Description",0xA40C:"EXIF Subject Distance Range",0xA420:"EXIF Unique Image ID"}
6301
6302 Static PropTagsB := {0x0000:"GpsVer",0x000B:"GpsGpsDop",0x000C:"GpsSpeedRef",0x000D:"GpsSpeed",0x000E:"GpsTrackRef",0x000F:"GpsTrack",0x0010:"GpsImgDirRef",0x0011:"GpsImgDir",0x0012:"GpsMapDatum",0x0013:"GpsDestLatRef",0x0014:"GpsDestLat",0x0015:"GpsDestLongRef",0x0016:"GpsDestLong",0x0017:"GpsDestBearRef",0x0018:"GpsDestBear",0x0019:"GpsDestDistRef",0x001A:"GpsDestDist",0x001B:"GpsProcessingMethod",0x001C:"GpsAreaInformation",0x0100:"Original Image Width",0x0101:"Original Image Height",0x0108:"CellWidth",0x0109:"CellHeight",0x0111:"Strip Offsets",0x0116:"RowsPerStrip",0x0117:"StripBytesCount",0x011A:"XResolution",0x011B:"YResolution",0x011C:"Planar Config",0x011E:"XPosition",0x011F:"YPosition",0x0120:"FreeOffset",0x0121:"FreeByteCounts",0x0124:"T4Option",0x0125:"T6Option",0x0129:"PageNumber",0x0141:"Halftone Hints",0x0142:"TileWidth",0x0143:"TileLength",0x0144:"TileOffset"
6303 ,0x0145:"TileByteCounts",0x0154:"SMin Sample Value",0x0155:"SMax Sample Value",0x0201:"JPEGInterFormat",0x0202:"JPEGInterLength",0x0203:"JPEGRestartInterval",0x0206:"JPEGPointTransforms",0x0207:"JPEGQTables",0x0208:"JPEGDCTables",0x0209:"JPEGACTables",0x0211:"YCbCrCoefficients",0x0212:"YCbCrSubsampling",0x0213:"YCbCrPositioning",0x0214:"REFBlackWhite",0x5001:"ResolutionXUnit",0x5002:"ResolutionYUnit",0x5003:"ResolutionXLengthUnit",0x5004:"ResolutionYLengthUnit",0x5005:"PrintFlags",0x5006:"PrintFlagsVersion",0x5007:"PrintFlagsCrop",0x5008:"PrintFlagsBleedWidth",0x5009:"PrintFlagsBleedWidthScale",0x500A:"HalftoneLPI",0x500B:"HalftoneLPIUnit",0x500C:"HalftoneDegree",0x500D:"HalftoneShape",0x500E:"HalftoneMisc",0x500F:"HalftoneScreen",0x5012:"ThumbnailFormat",0x5013:"ThumbnailWidth",0x5014:"ThumbnailHeight",0x5015:"ThumbnailColorDepth"
6304 ,0x5016:"ThumbnailPlanes",0x5017:"ThumbnailRawBytes",0x5018:"ThumbnailSize",0x5019:"ThumbnailCompressedSize",0x501B:"ThumbnailData",0x5020:"ThumbnailImageWidth",0x5021:"ThumbnailImageHeight",0x5022:"ThumbnailBitsPerSample",0x5023:"ThumbnailCompression",0x5024:"ThumbnailPhotometricInterp",0x5025:"ThumbnailImageDescription",0x5026:"ThumbnailEquipMake",0x5027:"ThumbnailEquipModel",0x5028:"ThumbnailStripOffsets",0x5029:"ThumbnailOrientation",0x502A:"ThumbnailSamplesPerPixel",0x502B:"ThumbnailRowsPerStrip",0x502C:"ThumbnailStripBytesCount",0x502D:"ThumbnailResolutionX",0x502E:"ThumbnailResolutionY",0x502F:"ThumbnailPlanarConfig",0x5030:"ThumbnailResolutionUnit",0x5031:"ThumbnailTransferFunction",0x5032:"ThumbnailSoftwareUsed",0x5033:"ThumbnailDateTime",0x5034:"ThumbnailArtist",0x5035:"ThumbnailWhitePoint"
6305 ,0x5036:"ThumbnailPrimaryChromaticities",0x5037:"ThumbnailYCbCrCoefficients",0x5038:"ThumbnailYCbCrSubsampling",0x5039:"ThumbnailYCbCrPositioning",0x503A:"ThumbnailRefBlackWhite",0x503B:"ThumbnailCopyRight",0x5090:"LuminanceTable",0x5091:"ChrominanceTable",0x5102:"Global Palette",0x5103:"Index Background",0x5104:"Index Transparent",0x5113:"Palette Histogram",0x8769:"ExifIFD",0x8825:"GpsIFD",0x8828:"ExifOECF",0x9000:"ExifVer",0x9101:"EXIF CompConfig",0x9290:"EXIF DTSubsec",0x9291:"EXIF DTOrigSS",0x9292:"EXIF DTDigSS",0xA000:"EXIF FPXVer",0xA20C:"EXIF Spatial FR",0xA302:"EXIF CfaPattern"}
6306
6307 r := PropTagsA.HasKey(PropID) ? PropTagsA[PropID] : "Unknown"
6308 If (r="Unknown")
6309 r := PropTagsB.HasKey(PropID) ? PropTagsB[PropID] : "Unknown"
6310 Return r
6311}
6312
6313;######################################################################################################################################
6314; Gdip_GetPropertyTagType() - Gets the name for he type of this property's value as defined in "Gdiplusimaging.h".
6315; Parameters:
6316; PropType - Integer that identifies the type of the property item to be retrieved.
6317; Return values:
6318; On success - Corresponding type.
6319; On failure - "Unknown"
6320;######################################################################################################################################
6321
6322Gdip_GetPropertyTagType(PropType) {
6323 Static PropTypes := {1: "Byte", 2: "ASCII", 3: "Short", 4: "Long", 5: "Rational", 7: "Undefined", 9: "SLong", 10: "SRational"}
6324 Return PropTypes.HasKey(PropType) ? PropTypes[PropType] : "Unknown"
6325}
6326
6327Gdip_GetPropertyItemValue(ByRef PropVal, PropLen, PropType, PropAddr) {
6328; Gdip_GetPropertyItemValue() - Reserved for internal use
6329 PropVal := ""
6330 If (PropType = 2)
6331 {
6332 PropVal := StrGet(PropAddr, PropLen, "CP0")
6333 Return True
6334 }
6335
6336 If (PropType = 3)
6337 {
6338 PropyLen := PropLen // 2
6339 Loop %PropyLen%
6340 PropVal .= (A_Index > 1 ? " " : "") . NumGet(PropAddr + 0, (A_Index - 1) << 1, "Short")
6341 Return True
6342 }
6343
6344 If (PropType = 4) || (PropType = 9)
6345 {
6346 NumType := PropType = 4 ? "UInt" : "Int"
6347 PropyLen := PropLen // 4
6348 Loop %PropyLen%
6349 PropVal .= (A_Index > 1 ? " " : "") . NumGet(PropAddr + 0, (A_Index - 1) << 2, NumType)
6350 Return True
6351 }
6352
6353 If (PropType = 5) || (PropType = 10)
6354 {
6355 NumType := PropType = 5 ? "UInt" : "Int"
6356 PropyLen := PropLen // 8
6357 Loop %PropyLen%
6358 PropVal .= (A_Index > 1 ? " " : "") . NumGet(PropAddr + 0, (A_Index - 1) << 2, NumType)
6359 . "/" . NumGet(PropAddr + 4, (A_Index - 1) << 2, NumType)
6360 Return True
6361 }
6362
6363 If (PropType = 1) || (PropType = 7)
6364 {
6365 VarSetCapacity(PropVal, PropLen, 0)
6366 DllCall("Kernel32.dll\RtlMoveMemory", "Ptr", &PropVal, "Ptr", PropAddr, "Ptr", PropLen)
6367 Return True
6368 }
6369 Return False
6370}
6371
6372;#####################################################################################
6373; RotateAtCenter() and related Functions by RazorHalo
6374; from https://www.autohotkey.com/boards/viewtopic.php?f=6&t=6517&start=260
6375; in April 2019.
6376;#####################################################################################
6377; The Matrix order has to be "Append" for the transformations to be applied
6378; in the correct order - instead of the default "Prepend"
6379
6380Gdip_RotatePathAtCenter(pPath, Angle, MatrixOrder:=1, withinBounds:=0, withinBkeepRatio:=1) {
6381; modified by Marius Șucan - added withinBounds option
6382
6383 ; Gets the bounding rectangle of the GraphicsPath
6384 ; returns array x, y, w, h
6385 Rect := Gdip_GetPathWorldBounds(pPath)
6386
6387 ; Calculate center of bounding rectangle which will be the center of the graphics path
6388 cX := Rect.x + (Rect.w / 2)
6389 cY := Rect.y + (Rect.h / 2)
6390
6391 ; Create a Matrix for the transformations
6392 pMatrix := Gdip_CreateMatrix()
6393
6394 ; Move the GraphicsPath center to the origin (0, 0) of the graphics object
6395 Gdip_TranslateMatrix(pMatrix, -cX , -cY)
6396
6397 ; Rotate matrix on graphics object origin
6398 Gdip_RotateMatrix(pMatrix, Angle, MatrixOrder)
6399
6400 ; Move the GraphicsPath origin point back to its original position
6401 Gdip_TranslateMatrix(pMatrix, cX, cY, MatrixOrder)
6402
6403 ; Apply the transformations
6404 E := Gdip_TransformPath(pPath, pMatrix)
6405
6406 ; Delete Matrix
6407 Gdip_DeleteMatrix(pMatrix)
6408
6409 If (withinBounds=1 && !E && Angle!=0)
6410 {
6411 nRect := Gdip_GetPathWorldBounds(pPath)
6412 ncX := nRect.x + (nRect.w / 2)
6413 ncY := nRect.y + (nRect.h / 2)
6414 pMatrix := Gdip_CreateMatrix()
6415 Gdip_TranslateMatrix(pMatrix, -ncX , -ncY)
6416 sX := Rect.w / nRect.w
6417 sY := Rect.h / nRect.h
6418 If (withinBkeepRatio=1)
6419 {
6420 sX := min(sX, sY)
6421 sY := min(sX, sY)
6422 }
6423 Gdip_ScaleMatrix(pMatrix, sX, sY, MatrixOrder)
6424 Gdip_TranslateMatrix(pMatrix, ncX, ncY, MatrixOrder)
6425 If (sX!=0 && sY!=0)
6426 E := Gdip_TransformPath(pPath, pMatrix)
6427 Gdip_DeleteMatrix(pMatrix)
6428 }
6429 Return E
6430}
6431
6432;#####################################################################################
6433; Matrix transformations functions by RazorHalo
6434;
6435; NOTE: Be aware of the order that transformations are applied. You may need
6436; to pass MatrixOrder as 1 for "Append"
6437; the (default is 0 for "Prepend") to get the correct results.
6438
6439Gdip_ResetMatrix(hMatrix) {
6440 Ptr := "UPtr"
6441 return DllCall("gdiplus\GdipResetMatrix", Ptr, hMatrix)
6442}
6443
6444Gdip_RotateMatrix(hMatrix, Angle, MatrixOrder:=0) {
6445 Ptr := "UPtr"
6446 return DllCall("gdiplus\GdipRotateMatrix", Ptr, hMatrix, "float", Angle, "Int", MatrixOrder)
6447}
6448
6449
6450Gdip_GetPathWorldBounds(pPath, hMatrix:=0, pPen:=0) {
6451; hMatrix to use for calculating the boundaries
6452; pPen to use for calculating the boundaries
6453; Both will not affect the actual GraphicsPath.
6454
6455 Ptr := "UPtr"
6456 rData := {}
6457
6458 VarSetCapacity(RectF, 16, 0)
6459 status := DllCall("gdiplus\GdipGetPathWorldBounds", Ptr, pPath, Ptr, &RectF, Ptr, hMatrix, Ptr, pPen)
6460
6461 If (!status) {
6462 rData.x := NumGet(&RectF, 0, "float")
6463 , rData.y := NumGet(&RectF, 4, "float")
6464 , rData.w := NumGet(&RectF, 8, "float")
6465 , rData.h := NumGet(&RectF, 12, "float")
6466 } Else {
6467 Return status
6468 }
6469
6470 return rData
6471}
6472
6473Gdip_ScaleMatrix(hMatrix, ScaleX, ScaleY, MatrixOrder:=0) {
6474 Ptr := "UPtr"
6475 return DllCall("gdiplus\GdipScaleMatrix", Ptr, hMatrix, "float", ScaleX, "float", ScaleY, "Int", MatrixOrder)
6476}
6477
6478Gdip_TranslateMatrix(hMatrix, offsetX, offsetY, MatrixOrder:=0) {
6479 Ptr := "UPtr"
6480 return DllCall("gdiplus\GdipTranslateMatrix", Ptr, hMatrix, "float", offsetX, "float", offsetY, "Int", MatrixOrder)
6481}
6482
6483Gdip_TransformPath(pPath, hMatrix) {
6484 Ptr := "UPtr"
6485 return DllCall("gdiplus\GdipTransformPath", Ptr, pPath, Ptr, hMatrix)
6486}
6487
6488Gdip_SetMatrixElements(hMatrix, m11, m12, m21, m22, x, y) {
6489 Ptr := "UPtr"
6490 return DllCall("gdiplus\GdipSetMatrixElements", Ptr, hMatrix, "float", m11, "float", m12, "float", m21, "float", m22, "float", x, "float", y)
6491}
6492
6493Gdip_GetMatrixLastStatus(pMatrix) {
6494 Ptr := "UPtr"
6495 return DllCall("gdiplus\GdipGetLastStatus", Ptr, pMatrix)
6496}
6497
6498;#####################################################################################
6499; GraphicsPath functions written by Learning one
6500; found on https://autohotkey.com/board/topic/29449-gdi-standard-library-145-by-tic/page-75
6501; Updated on 14/08/2019 by Marius Șucan
6502;#####################################################################################
6503;
6504; Function: Gdip_AddPathBeziers
6505; Description: Adds a sequence of connected Bézier splines to the current figure of this path.
6506; A Bezier spline does not pass through its control points. The control points act as magnets, pulling the curve
6507; in certain directions to influence the way the spline bends.
6508;
6509; pPath: Pointer to the GraphicsPath.
6510; Points: The coordinates of all the points passed as x1,y1|x2,y2|x3,y3...
6511;
6512; Return: Status enumeration. 0 = success.
6513;
6514; 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.
6515
6516Gdip_AddPathBeziers(pPath, Points) {
6517 Ptr := "UPtr"
6518 iCount := CreatePointsF(PointsF, Points)
6519 return DllCall("gdiplus\GdipAddPathBeziers", Ptr, pPath, Ptr, &PointsF, "int", iCount)
6520}
6521
6522Gdip_AddPathBezier(pPath, x1, y1, x2, y2, x3, y3, x4, y4) {
6523 ; Adds a Bézier spline to the current figure of this path
6524 Ptr := "UPtr"
6525 return DllCall("gdiplus\GdipAddPathBezier", Ptr, pPath
6526 , "float", x1, "float", y1, "float", x2, "float", y2
6527 , "float", x3, "float", y3, "float", x4, "float", y4)
6528}
6529
6530;#####################################################################################
6531; Function: Gdip_AddPathLines
6532; Description: Adds a sequence of connected lines to the current figure of this path.
6533;
6534; pPath: Pointer to the GraphicsPath
6535; Points: the coordinates of all the points passed as x1,y1|x2,y2|x3,y3.....
6536;
6537; Return: status enumeration. 0 = success.
6538
6539Gdip_AddPathLines(pPath, Points) {
6540 Ptr := "UPtr"
6541 iCount := CreatePointsF(PointsF, Points)
6542 return DllCall("gdiplus\GdipAddPathLine2", Ptr, pPath, Ptr, &PointsF, "int", iCount)
6543}
6544
6545Gdip_AddPathLine(pPath, x1, y1, x2, y2) {
6546 Ptr := "UPtr"
6547 return DllCall("gdiplus\GdipAddPathLine", Ptr, pPath, "float", x1, "float", y1, "float", x2, "float", y2)
6548}
6549
6550Gdip_AddPathArc(pPath, x, y, w, h, StartAngle, SweepAngle) {
6551 Ptr := "UPtr"
6552 return DllCall("gdiplus\GdipAddPathArc", Ptr, pPath, "float", x, "float", y, "float", w, "float", h, "float", StartAngle, "float", SweepAngle)
6553}
6554
6555Gdip_AddPathPie(pPath, x, y, w, h, StartAngle, SweepAngle) {
6556 Ptr := "UPtr"
6557 return DllCall("gdiplus\GdipAddPathPie", Ptr, pPath, "float", x, "float", y, "float", w, "float", h, "float", StartAngle, "float", SweepAngle)
6558}
6559
6560Gdip_StartPathFigure(pPath) {
6561; Starts a new figure without closing the current figure.
6562; Subsequent points added to this path are added to the new figure.
6563 Ptr := "UPtr"
6564 return DllCall("gdiplus\GdipStartPathFigure", Ptr, pPath)
6565}
6566
6567Gdip_ClosePathFigure(pPath) {
6568; Closes the current figure of this path.
6569 Ptr := "UPtr"
6570 return DllCall("gdiplus\GdipClosePathFigure", Ptr, pPath)
6571}
6572
6573Gdip_ClosePathFigures(pPath) {
6574; Closes the current figure of this path.
6575 Ptr := "UPtr"
6576 return DllCall("gdiplus\GdipClosePathFigures", Ptr, pPath)
6577}
6578
6579;#####################################################################################
6580; Function: Gdip_DrawPath
6581; Description: Draws a sequence of lines and curves defined by a GraphicsPath object
6582;
6583; pGraphics: Pointer to the Graphics of a bitmap
6584; pPen: Pointer to a pen object
6585; pPath: Pointer to a Path object
6586;
6587; Return: status enumeration. 0 = success.
6588
6589Gdip_DrawPath(pGraphics, pPen, pPath) {
6590 Ptr := "UPtr"
6591 return DllCall("gdiplus\GdipDrawPath", Ptr, pGraphics, Ptr, pPen, Ptr, pPath)
6592}
6593
6594Gdip_ClonePath(pPath) {
6595 Ptr := "UPtr"
6596 PtrA := "UPtr*"
6597 pPathClone := 0
6598
6599 DllCall("gdiplus\GdipClonePath", Ptr, pPath, PtrA, pPathClone)
6600 return pPathClone
6601}
6602
6603;######################################################################################################################################
6604; The following PathGradient brush functions were written by 'Just Me' in March 2012
6605; source: https://autohotkey.com/board/topic/29449-gdi-standard-library-145-by-tic/page-65
6606;######################################################################################################################################
6607
6608Gdip_PathGradientCreateFromPath(pPath) {
6609 ; Creates and returns a path gradient brush.
6610 ; pPath path object returned from Gdip_CreatePath()
6611 pBrush := 0
6612 DllCall("gdiplus\GdipCreatePathGradientFromPath", "Ptr", pPath, "PtrP", pBrush)
6613 Return pBrush
6614}
6615
6616Gdip_PathGradientSetCenterPoint(pBrush, X, Y) {
6617 ; Sets the center point of this path gradient brush.
6618 ; pBrush Brush object returned from Gdip_PathGradientCreateFromPath().
6619 ; X, Y X, y coordinates in pixels
6620 VarSetCapacity(POINTF, 8)
6621 NumPut(X, POINTF, 0, "Float")
6622 NumPut(Y, POINTF, 4, "Float")
6623 Return DllCall("gdiplus\GdipSetPathGradientCenterPoint", "Ptr", pBrush, "Ptr", &POINTF)
6624}
6625
6626Gdip_PathGradientSetCenterColor(pBrush, CenterColor) {
6627 ; Sets the center color of this path gradient brush.
6628 ; pBrush Brush object returned from Gdip_PathGradientCreateFromPath().
6629 ; CenterColor ARGB color value: A(lpha)R(ed)G(reen)B(lue).
6630 Return DllCall("gdiplus\GdipSetPathGradientCenterColor", "Ptr", pBrush, "UInt", CenterColor)
6631}
6632
6633Gdip_PathGradientSetSurroundColors(pBrush, SurroundColors) {
6634 ; Sets the surround colors of this path gradient brush.
6635 ; pBrush Brush object returned from Gdip_PathGradientCreateFromPath().
6636 ; SurroundColours One or more ARGB color values seperated by pipe (|)).
6637 ; updated by Marius Șucan
6638
6639 Colors := StrSplit(SurroundColors, "|")
6640 tColors := Colors.Length()
6641 VarSetCapacity(ColorArray, 4 * tColors, 0)
6642
6643 Loop %tColors% {
6644 NumPut(Colors[A_Index], ColorArray, 4 * (A_Index - 1), "UInt")
6645 }
6646
6647 Return DllCall("gdiplus\GdipSetPathGradientSurroundColorsWithCount", "Ptr", pBrush, "Ptr", &ColorArray
6648 , "IntP", tColors)
6649}
6650
6651Gdip_PathGradientSetSigmaBlend(pBrush, Focus, Scale:=1) {
6652 ; Sets the blend shape of this path gradient brush to bell shape.
6653 ; pBrush Brush object returned from Gdip_PathGradientCreateFromPath().
6654 ; Focus Number that specifies where the center color will be at its highest intensity.
6655 ; Values: 1.0 (center) - 0.0 (border)
6656 ; Scale Number that specifies the maximum intensity of center color that gets blended with
6657 ; the boundary color.
6658 ; Values: 1.0 (100 %) - 0.0 (0 %)
6659 Return DllCall("gdiplus\GdipSetPathGradientSigmaBlend", "Ptr", pBrush, "Float", Focus, "Float", Scale)
6660}
6661
6662Gdip_PathGradientSetLinearBlend(pBrush, Focus, Scale:=1) {
6663 ; Sets the blend shape of this path gradient brush to triangular shape.
6664 ; pBrush Brush object returned from Gdip_PathGradientCreateFromPath()
6665 ; Focus Number that specifies where the center color will be at its highest intensity.
6666 ; Values: 1.0 (center) - 0.0 (border)
6667 ; Scale Number that specifies the maximum intensity of center color that gets blended with
6668 ; the boundary color.
6669 ; Values: 1.0 (100 %) - 0.0 (0 %)
6670 Return DllCall("gdiplus\GdipSetPathGradientLinearBlend", "Ptr", pBrush, "Float", Focus, "Float", Scale)
6671}
6672
6673Gdip_PathGradientSetFocusScales(pBrush, xScale, yScale) {
6674 ; Sets the focus scales of this path gradient brush.
6675 ; pBrush Brush object returned from Gdip_PathGradientCreateFromPath().
6676 ; xScale Number that specifies the x focus scale.
6677 ; Values: 0.0 (0 %) - 1.0 (100 %)
6678 ; yScale Number that specifies the y focus scale.
6679 ; Values: 0.0 (0 %) - 1.0 (100 %)
6680 Return DllCall("gdiplus\GdipSetPathGradientFocusScales", "Ptr", pBrush, "Float", xScale, "Float", yScale)
6681}
6682
6683Gdip_AddPathGradient(pGraphics, x, y, w, h, cX, cY, cClr, sClr, BlendFocus, ScaleX, ScaleY, Shape, Angle:=0) {
6684; Parameters:
6685; X, Y - coordinates where to add the gradient path object
6686; W, H - the width and height of the path gradient object
6687; cX, cY - the coordinates of the Center Point of the gradient within the wdith and height object boundaries
6688; cClr - the center color in 0xARGB
6689; sClr - the surrounding color in 0xARGB
6690; BlendFocus - 0.0 to 1.0; where the center color reaches the highest intensity
6691; Shape - 1 = rectangle ; 0 = ellipse
6692; Angle - Rotate the pPathGradientBrush at given angle
6693;
6694; function based on the example provided by Just Me for the path gradient functions
6695; adaptations/modifications by Marius Șucan
6696
6697 pPath := Gdip_CreatePath()
6698 If (Shape=1)
6699 Gdip_AddPathRectangle(pPath, x, y, W, H)
6700 Else
6701 Gdip_AddPathEllipse(pPath, x, y, W, H)
6702 zBrush := Gdip_PathGradientCreateFromPath(pPath)
6703 If (Angle!=0)
6704 Gdip_RotatePathGradientAtCenter(zBrush, Angle)
6705 Gdip_PathGradientSetCenterPoint(zBrush, cX, cY)
6706 Gdip_PathGradientSetCenterColor(zBrush, cClr)
6707 Gdip_PathGradientSetSurroundColors(zBrush, sClr)
6708 Gdip_PathGradientSetSigmaBlend(zBrush, BlendFocus)
6709 Gdip_PathGradientSetLinearBlend(zBrush, BlendFocus)
6710 Gdip_PathGradientSetFocusScales(zBrush, ScaleX, ScaleY)
6711 E := Gdip_FillPath(pGraphics, zBrush, pPath)
6712 Gdip_DeleteBrush(zBrush)
6713 Gdip_DeletePath(pPath)
6714 Return E
6715}
6716
6717;######################################################################################################################################
6718; The following PathGradient brush functions were written by Marius Șucan
6719;######################################################################################################################################
6720
6721Gdip_CreatePathGradient(Points, WrapMode) {
6722; Creates a PathGradientBrush object based on an array of points and initializes the wrap mode of the brush
6723;
6724; Points array format:
6725; Points := "x1,y1|x2,y2|x3,y3|x4,y4" [... and so on]
6726;
6727; WrapMode options: specifies how an area is tiled when it is painted with a brush:
6728; 0 - Tile - Tiling without flipping
6729; 1 - TileFlipX - Tiles are flipped horizontally as you move from one tile to the next in a row
6730; 2 - TileFlipY - Tiles are flipped vertically as you move from one tile to the next in a column
6731; 3 - TileFlipXY - Tiles are flipped horizontally as you move along a row and flipped vertically as you move along a column
6732; 4 - Clamp - No tiling
6733
6734 Ptr := "UPtr"
6735 iCount := CreatePointsF(PointsF, Points)
6736 pPathGradientBrush := 0
6737 DllCall("gdiplus\GdipCreatePathGradient", Ptr, &PointsF, "int", iCount, "int", WrapMode, "int*", pPathGradientBrush)
6738 Return pPathGradientBrush
6739}
6740
6741Gdip_PathGradientGetGammaCorrection(pPathGradientBrush) {
6742 Ptr := "UPtr"
6743 result := 0
6744 E := DllCall("gdiplus\GdipGetPathGradientGammaCorrection", Ptr, pPathGradientBrush, "int*", result)
6745 If E
6746 return -1
6747 Return result
6748}
6749
6750Gdip_PathGradientGetPointCount(pPathGradientBrush) {
6751 Ptr := "UPtr"
6752 result := 0
6753 E := DllCall("gdiplus\GdipGetPathGradientPointCount", Ptr, pPathGradientBrush, "int*", result)
6754 If E
6755 return -1
6756 Return result
6757}
6758
6759Gdip_PathGradientGetWrapMode(pPathGradientBrush) {
6760 Ptr := "UPtr"
6761 result := 0
6762 E := DllCall("gdiplus\GdipGetPathGradientWrapMode", Ptr, pPathGradientBrush, "int*", result)
6763 If E
6764 return -1
6765 Return result
6766}
6767
6768Gdip_PathGradientGetRect(pPathGradientBrush) {
6769 Ptr := "UPtr"
6770 rData := {}
6771
6772 VarSetCapacity(RectF, 16, 0)
6773 status := DllCall("gdiplus\GdipGetPathGradientRect", Ptr, pPathGradientBrush, Ptr, &RectF)
6774
6775 If (!status) {
6776 rData.x := NumGet(&RectF, 0, "float")
6777 , rData.y := NumGet(&RectF, 4, "float")
6778 , rData.w := NumGet(&RectF, 8, "float")
6779 , rData.h := NumGet(&RectF, 12, "float")
6780 } Else {
6781 Return status
6782 }
6783
6784 return rData
6785}
6786
6787Gdip_PathGradientResetTransform(pPathGradientBrush) {
6788 Ptr := "UPtr"
6789 return DllCall("gdiplus\GdipResetPathGradientTransform", Ptr, pPathGradientBrush)
6790}
6791
6792Gdip_PathGradientRotateTransform(pPathGradientBrush, Angle, matrixOrder:=0) {
6793 Ptr := "UPtr"
6794 return DllCall("gdiplus\GdipRotatePathGradientTransform", Ptr, pPathGradientBrush, "float", Angle, "int", matrixOrder)
6795}
6796
6797Gdip_PathGradientScaleTransform(pPathGradientBrush, ScaleX, ScaleY, matrixOrder:=0) {
6798 Ptr := "UPtr"
6799 return DllCall("gdiplus\GdipScalePathGradientTransform", Ptr, pPathGradientBrush, "float", ScaleX, "float", ScaleY, "int", matrixOrder)
6800}
6801
6802Gdip_PathGradientTranslateTransform(pPathGradientBrush, X, Y, matrixOrder:=0) {
6803 Ptr := "UPtr"
6804 Return DllCall("gdiplus\GdipTranslatePathGradientTransform", Ptr, pPathGradientBrush, "float", X, "float", Y, "int", matrixOrder)
6805}
6806
6807Gdip_PathGradientMultiplyTransform(pPathGradientBrush, hMatrix, matrixOrder:=0) {
6808 Ptr := "UPtr"
6809 Return DllCall("gdiplus\GdipMultiplyPathGradientTransform", Ptr, pPathGradientBrush, Ptr, hMatrix, "int", matrixOrder)
6810}
6811
6812Gdip_PathGradientSetTransform(pPathGradientBrush, pMatrix) {
6813 Ptr := "UPtr"
6814 return DllCall("gdiplus\GdipSetPathGradientTransform", Ptr, pPathGradientBrush, Ptr, pMatrix)
6815}
6816
6817Gdip_PathGradientGetTransform(pPathGradientBrush) {
6818 Ptr := "UPtr"
6819 pMatrix := 0
6820 DllCall("gdiplus\GdipGetPathGradientTransform", Ptr, pPathGradientBrush, "UPtr*", pMatrix)
6821 Return pMatrix
6822}
6823
6824Gdip_RotatePathGradientAtCenter(pPathGradientBrush, Angle, MatrixOrder:=1) {
6825; function by Marius Șucan
6826; based on Gdip_RotatePathAtCenter() by RazorHalo
6827
6828 Rect := Gdip_PathGradientGetRect(pPathGradientBrush)
6829 cX := Rect.x + (Rect.w / 2)
6830 cY := Rect.y + (Rect.h / 2)
6831 pMatrix := Gdip_CreateMatrix()
6832 Gdip_TranslateMatrix(pMatrix, -cX , -cY)
6833 Gdip_RotateMatrix(pMatrix, Angle, MatrixOrder)
6834 Gdip_TranslateMatrix(pMatrix, cX, cY, MatrixOrder)
6835 E := Gdip_PathGradientSetTransform(pPathGradientBrush, pMatrix)
6836 Gdip_DeleteMatrix(pMatrix)
6837 Return E
6838}
6839
6840
6841Gdip_PathGradientSetGammaCorrection(pPathGradientBrush, UseGammaCorrection) {
6842; Specifies whether gamma correction is enabled for a path gradient brush
6843; UseGammaCorrection: 1 or 0.
6844 Ptr := "UPtr"
6845 return DllCall("gdiplus\GdipSetPathGradientGammaCorrection", Ptr, pPathGradientBrush, "int", UseGammaCorrection)
6846}
6847
6848Gdip_PathGradientSetWrapMode(pPathGradientBrush, WrapMode) {
6849; WrapMode options: specifies how an area is tiled when it is painted with a brush:
6850; 0 - Tile - Tiling without flipping
6851; 1 - TileFlipX - Tiles are flipped horizontally as you move from one tile to the next in a row
6852; 2 - TileFlipY - Tiles are flipped vertically as you move from one tile to the next in a column
6853; 3 - TileFlipXY - Tiles are flipped horizontally as you move along a row and flipped vertically as you move along a column
6854; 4 - Clamp - No tiling
6855
6856 Ptr := "UPtr"
6857 return DllCall("gdiplus\GdipSetPathGradientWrapMode", Ptr, pPathGradientBrush, "int", WrapMode)
6858}
6859
6860Gdip_PathGradientGetCenterColor(pPathGradientBrush) {
6861 Ptr := "UPtr"
6862 ARGB := 0
6863 E := DllCall("gdiplus\GdipGetPathGradientCenterColor", Ptr, pPathGradientBrush, "uint*", ARGB)
6864 If E
6865 return -1
6866 Return Format("{1:#x}", ARGB)
6867}
6868
6869Gdip_PathGradientGetCenterPoint(pPathGradientBrush, ByRef X, ByRef Y) {
6870 Ptr := "UPtr"
6871 VarSetCapacity(PointF, 8, 0)
6872 E := DllCall("gdiplus\GdipGetPathGradientCenterPoint", Ptr, pPathGradientBrush, "UPtr", &PointF)
6873 If !E
6874 {
6875 x := NumGet(PointF, 0, "float")
6876 y := NumGet(PointF, 4, "float")
6877 }
6878 Return E
6879}
6880
6881Gdip_PathGradientGetFocusScales(pPathGradientBrush, ByRef X, ByRef Y) {
6882 Ptr := "UPtr"
6883 x := 0
6884 y := 0
6885 Return DllCall("gdiplus\GdipGetPathGradientFocusScales", Ptr, pPathGradientBrush, "float*", X, "float*", Y)
6886}
6887
6888Gdip_PathGradientGetSurroundColorCount(pPathGradientBrush) {
6889 Ptr := "UPtr"
6890 result := 0
6891 E := DllCall("gdiplus\GdipGetPathGradientSurroundColorCount", Ptr, pPathGradientBrush, "int*", result)
6892 If E
6893 return -1
6894 Return result
6895}
6896
6897Gdip_GetPathGradientSurroundColors(pPathGradientBrush) {
6898 iCount := Gdip_PathGradientGetSurroundColorCount(pPathGradientBrush)
6899 If (iCount=-1)
6900 Return 0
6901
6902
6903 Ptr := "UPtr"
6904 VarSetCapacity(sColors, 8 * iCount, 0)
6905 DllCall("gdiplus\GdipGetPathGradientSurroundColorsWithCount", Ptr, pPathGradientBrush, Ptr, &sColors, "intP", iCount)
6906 Loop %iCount%
6907 {
6908 A := NumGet(&sColors, 8*(A_Index-1), "uint")
6909 printList .= Format("{1:#x}", A) ","
6910 }
6911
6912 Return Trim(printList, ",")
6913}
6914
6915;######################################################################################################################################
6916; Function written by swagfag in July 2019
6917; source https://www.autohotkey.com/boards/viewtopic.php?f=6&t=62550
6918; modified by Marius Șucan
6919; whichFormat = 2; histogram for each channel: R, G, B
6920; whichFormat = 3; histogram of the luminance/brightness of the image
6921; Return: Status enumerated return type; 0 = OK/Success
6922
6923Gdip_GetHistogram(pBitmap, whichFormat, ByRef newArrayA, ByRef newArrayB, ByRef newArrayC) {
6924 Static sizeofUInt := 4
6925
6926 ; HistogramFormats := {ARGB: 0, PARGB: 1, RGB: 2, Gray: 3, B: 4, G: 5, R: 6, A: 7}
6927 z := DllCall("gdiplus\GdipBitmapGetHistogramSize", "UInt", whichFormat, "UInt*", numEntries)
6928
6929 newArrayA := [], newArrayB := [], newArrayC := []
6930 VarSetCapacity(ch0, numEntries * sizeofUInt)
6931 VarSetCapacity(ch1, numEntries * sizeofUInt)
6932 VarSetCapacity(ch2, numEntries * sizeofUInt)
6933 If (whichFormat=2)
6934 r := DllCall("gdiplus\GdipBitmapGetHistogram", "Ptr", pBitmap, "UInt", whichFormat, "UInt", numEntries, "Ptr", &ch0, "Ptr", &ch1, "Ptr", &ch2, "Ptr", 0)
6935 Else If (whichFormat>2)
6936 r := DllCall("gdiplus\GdipBitmapGetHistogram", "Ptr", pBitmap, "UInt", whichFormat, "UInt", numEntries, "Ptr", &ch0, "Ptr", 0, "Ptr", 0, "Ptr", 0)
6937
6938 Loop %numEntries%
6939 {
6940 i := A_Index - 1
6941 r := NumGet(&ch0+0, i * sizeofUInt, "UInt")
6942 newArrayA[i] := r
6943
6944 If (whichFormat=2)
6945 {
6946 g := NumGet(&ch1+0, i * sizeofUInt, "UInt")
6947 b := NumGet(&ch2+0, i * sizeofUInt, "UInt")
6948 newArrayB[i] := g
6949 newArrayC[i] := b
6950 }
6951 }
6952
6953 Return r
6954}
6955
6956Gdip_DrawRoundedLine(G, x1, y1, x2, y2, LineWidth, LineColor) {
6957; function by DevX and Rabiator found on:
6958; https://autohotkey.com/board/topic/29449-gdi-standard-library-145-by-tic/page-11
6959
6960 pPen := Gdip_CreatePen(LineColor, LineWidth)
6961 Gdip_DrawLine(G, pPen, x1, y1, x2, y2)
6962 Gdip_DeletePen(pPen)
6963
6964 pPen := Gdip_CreatePen(LineColor, LineWidth/2)
6965 Gdip_DrawEllipse(G, pPen, x1-LineWidth/4, y1-LineWidth/4, LineWidth/2, LineWidth/2)
6966 Gdip_DrawEllipse(G, pPen, x2-LineWidth/4, y2-LineWidth/4, LineWidth/2, LineWidth/2)
6967 Gdip_DeletePen(pPen)
6968}
6969
6970Gdi_CreateBitmap(hDC:="", w:=1, h:=1, BitCount:=32, Planes:=1, pBits:=0) {
6971; Creates a GDI bitmap; it can be a DIB or DDB.
6972; https://docs.microsoft.com/en-us/windows/win32/api/wingdi/nf-wingdi-createcompatiblebitmap
6973 If (hDC="")
6974 Return DllCall("Gdi32\CreateBitmap", "Int", w, "Int", h, "UInt", Planes, "UInt", BitCount, "Ptr", pBits, "UPtr")
6975 Else
6976 Return DllCall("gdi32\CreateCompatibleBitmap", "UPtr", hdc, "int", w, "int", h)
6977}
6978
6979Gdi_CreateDIBitmap(hdc, bmpInfoHeader, CBM_INIT, pBits, BITMAPINFO, DIB_COLORS) {
6980; This function creates a hBitmap, a device-dependent bitmap [DDB]
6981; from a pointer of data-bits [pBits].
6982;
6983; The hBitmap is created according to the information found in
6984; the BITMAPINFO and bmpInfoHeader pointers.
6985;
6986; If the function fails, the return value is NULL,
6987; otherwise a handle to the hBitmap
6988;
6989; Function written by Marius Șucan.
6990; Many thanks to Drugwash for the help offered.
6991
6992 Ptr := "UPtr"
6993 hBitmap := DllCall("CreateDIBitmap"
6994 , Ptr, hdc
6995 , Ptr, bmpInfoHeader
6996 , "uint", CBM_INIT ; =4
6997 , Ptr, pBits
6998 , Ptr, BITMAPINFO
6999 , "uint", DIB_COLORS, Ptr) ; PAL=1 ; RGB=2
7000
7001 Return hBitmap
7002}
7003
7004Gdip_CreateBitmapFromGdiDib(BITMAPINFO, BitmapData) {
7005 Ptr := "UPtr"
7006 pBitmap := 0
7007 E := DllCall("gdiplus\GdipCreateBitmapFromGdiDib", Ptr, BITMAPINFO, Ptr, BitmapData, "UPtr*", pBitmap)
7008 Return pBitmap
7009}
7010
7011Gdi_StretchDIBits(hDestDC, dX, dY, dW, dH, sX, sY, sW, sH, tBITMAPINFO, DIB_COLORS, pBits, RasterOper) {
7012 Ptr := "UPtr"
7013 Return DllCall("StretchDIBits"
7014 , Ptr, hDestDC, "int", dX, "int", dY
7015 , "int", dW, "int", dH, "int", sX, "int", sY
7016 , "int", sW, "int", sH, Ptr, pBits, Ptr, tBITMAPINFO
7017 , "int", DIB_COLORS, "uint", RasterOper)
7018}
7019
7020Gdi_SetDIBitsToDevice(hDC, dX, dY, Width, Height, sX, sY, StartScan, ScanLines, pBits, BITMAPINFO, DIB_COLORS) {
7021 Ptr := "UPtr"
7022 Return DllCall("SetDIBitsToDevice", Ptr, hDC
7023 , "int", dX, "int", dY
7024 , "uint", Width, "uint", Height
7025 , "int", sX, "int", sY
7026 , "uint", StartScan, "uint", ScanLines
7027 , Ptr, pBits, Ptr, BITMAPINFO, "uint", DIB_COLORS)
7028}
7029
7030Gdi_GetDIBits(hDC, hBitmap, start, cLines, pBits, BITMAPINFO, DIB_COLORS) {
7031; hDC - A handle to the device context.
7032; hBitmap - A handle to the GDI bitmap. This must be a compatible bitmap (DDB).
7033; pbits --A pointer to a buffer to receive the bitmap data.
7034; If this parameter is NULL, the function passes the dimensions
7035; and format of the bitmap to the BITMAPINFO structure pointed to
7036; by the BITMAPINFO parameter.
7037; A DDB is a Device-Dependent Bitmap, (as opposed to a DIB, or Device-Independent Bitmap).
7038; That means: a DDB does not contain color values; instead, the colors are in a
7039; device-dependent format. Therefore, it requires a hDC.
7040;
7041; This function returns the data-bits as device-independent bitmap
7042; from a hBitmap into the pBits pointer.
7043;
7044; Return: if the function fails, the return value is zero.
7045; It can also return ERROR_INVALID_PARAMETER.
7046; Function written by Marius Șucan.
7047
7048 Ptr := "UPtr"
7049 Return DllCall("GetDIBits"
7050 , Ptr, hDC
7051 , Ptr, hBitmap
7052 , "uint", start
7053 , "uint", cLines
7054 , Ptr, pBits
7055 , Ptr, BITMAPINFO
7056 , "uint", DIB_COLORS, Ptr) ; PAL=1 ; RGB=2
7057}
7058
7059;#####################################################################################
7060
7061; Function Gdip_DrawImageFX
7062; Description This function draws a bitmap into the pGraphics that can use an Effect.
7063;
7064; pGraphics Pointer to the Graphics of a bitmap
7065; pBitmap Pointer to a bitmap to be drawn
7066; dX, dY x, y coordinates of the destination upper-left corner where the image will be painted
7067; sX, sY x, y coordinates of the source upper-left corner
7068; sW, sH width and height of the source image
7069; Matrix a color matrix used to alter image attributes when drawing
7070; pEffect a pointer to an Effect object to apply when drawing the image
7071; hMatrix a pointer to a transformation matrix
7072; Unit Unit of measurement:
7073; 0 - World coordinates, a nonphysical unit
7074; 1 - Display units
7075; 2 - A unit is 1 pixel
7076; 3 - A unit is 1 point or 1/72 inch
7077; 4 - A unit is 1 inch
7078; 5 - A unit is 1/300 inch
7079; 6 - A unit is 1 millimeter
7080;
7081; return status enumeration. 0 = success
7082;
7083; notes on the color matrix:
7084; Matrix can be omitted to just draw with no alteration to ARGB
7085; Matrix may be passed as a digit from 0.0 - 1.0 to change just transparency
7086; Matrix can be passed as a matrix with "|" as delimiter. For example:
7087; MatrixBright=
7088; (
7089; 1.5 |0 |0 |0 |0
7090; 0 |1.5 |0 |0 |0
7091; 0 |0 |1.5 |0 |0
7092; 0 |0 |0 |1 |0
7093; 0.05 |0.05 |0.05 |0 |1
7094; )
7095;
7096; example color matrix:
7097; 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
7098; 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
7099; MatrixNegative = -1|0|0|0|0|0|-1|0|0|0|0|0|-1|0|0|0|0|0|1|0|1|1|1|0|1
7100; To generate a color matrix using user-friendly parameters,
7101; use GenerateColorMatrix()
7102; Function written by Marius Șucan.
7103
7104
7105Gdip_DrawImageFX(pGraphics, pBitmap, dX:="", dY:="", sX:="", sY:="", sW:="", sH:="", matrix:="", pEffect:="", ImageAttr:=0, hMatrix:=0, Unit:=2) {
7106 Ptr := "UPtr"
7107 If !ImageAttr
7108 {
7109 if !IsNumber(Matrix)
7110 ImageAttr := Gdip_SetImageAttributesColorMatrix(Matrix)
7111 else if (Matrix != 1)
7112 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")
7113 } Else usrImageAttr := 1
7114
7115 if (sX="" && sY="")
7116 sX := sY := 0
7117
7118 if (sW="" && sH="")
7119 Gdip_GetImageDimensions(pBitmap, sW, sH)
7120
7121 if (!hMatrix && dX!="" && dY!="")
7122 {
7123 hMatrix := dhMatrix := Gdip_CreateMatrix()
7124 Gdip_TranslateMatrix(dhMatrix, dX, dY, 1)
7125 }
7126
7127 CreateRectF(sourceRect, sX, sY, sW, sH)
7128 E := DllCall("gdiplus\GdipDrawImageFX"
7129 , Ptr, pGraphics
7130 , Ptr, pBitmap
7131 , Ptr, &sourceRect
7132 , Ptr, hMatrix ? hMatrix : 0 ; transformation matrix
7133 , Ptr, pEffect
7134 , Ptr, ImageAttr ? ImageAttr : 0
7135 , "Uint", Unit) ; srcUnit
7136 ; r4 := GetStatus(A_LineNumber ":GdipDrawImageFX",r4)
7137
7138 If dhMatrix
7139 Gdip_DeleteMatrix(dhMatrix)
7140
7141 If (ImageAttr && usrImageAttr!=1)
7142 Gdip_DisposeImageAttributes(ImageAttr)
7143
7144 Return E
7145}
7146
7147Gdip_BitmapApplyEffect(pBitmap, pEffect, x:="", y:="", w:="", h:=0) {
7148; X, Y - coordinates for the rectangle where the effect is applied
7149; W, H - width and heigh for the rectangle where the effect is applied
7150; If X, Y, W or H are omitted , the effect is applied on the entire pBitmap
7151;
7152; written by Marius Șucan
7153; many thanks to Drugwash for the help provided
7154 If InStr(pEffect, "err-")
7155 Return pEffect
7156
7157 If (!x && !y && !w && !h)
7158 {
7159 Gdip_GetImageDimensions(pBitmap, Width, Height)
7160 CreateRectF(RectF, 0, 0, Width, Height)
7161 } Else CreateRectF(RectF, X, Y, W, H)
7162
7163 Ptr := "UPtr"
7164 E := DllCall("gdiplus\GdipBitmapApplyEffect"
7165 , Ptr, pBitmap
7166 , Ptr, pEffect
7167 , Ptr, &RectF
7168 , Ptr, 0
7169 , Ptr, 0
7170 , Ptr, 0)
7171
7172 Return E
7173}
7174
7175COM_CLSIDfromString(ByRef CLSID, String) {
7176 VarSetCapacity(CLSID, 16, 0)
7177 E := DllCall("ole32\CLSIDFromString", "WStr", String, "UPtr", &CLSID)
7178 Return E
7179}
7180
7181Gdip_CreateEffect(whichFX, paramA, paramB, paramC:=0) {
7182/*
7183 whichFX options:
7184 1 - Blur
7185 paramA - radius [0, 255]
7186 paramB - bool [0, 1]
7187 2 - Sharpen
7188 paramA - radius [0, 255]
7189 paramB - amount [0, 100]
7190 3 - ! ColorMatrix
7191 4 - ! ColorLUT
7192 5 - BrightnessContrast
7193 paramA - brightness [-255, 255]
7194 paramB - contrast [-100, 100]
7195 6 - HueSaturationLightness
7196 paramA - hue [-180, 180]
7197 paramB - saturation [-100, 100]
7198 paramC - light [-100, 100]
7199 7 - LevelsAdjust
7200 paramA - highlights [0, 100]
7201 paramB - midtones [-100, 100]
7202 paramC - shadows [0, 100]
7203 8 - Tint
7204 paramA - hue [-180, 180]
7205 paramB - amount [0, 100]
7206 9 - ColorBalance
7207 paramA - Cyan / Red [-100, 100]
7208 paramB - Magenta / Green [-100, 100]
7209 paramC - Yellow / Blue [-100, 100]
7210 10 - ! RedEyeCorrection
7211 11 - ColorCurve
7212 paramA - Type of adjustments [0, 7]
7213 0 - AdjustExposure [-255, 255]
7214 1 - AdjustDensity [-255, 255]
7215 2 - AdjustContrast [-100, 100]
7216 3 - AdjustHighlight [-100, 100]
7217 4 - AdjustShadow [-100, 100]
7218 5 - AdjustMidtone [-100, 100]
7219 6 - AdjustWhiteSaturation [0, 255]
7220 7 - AdjustBlackSaturation [0, 255]
7221 paramB - Apply ColorCurve on channels [1, 4]
7222 1 - Red
7223 2 - Green
7224 3 - Blue
7225 4 - All channels
7226 paramC - An adjust value within range according to paramA
7227 Effects marked with "!" are not yet implemented.
7228 Through ParamA, ParamB and ParamC, the effects can be controlled.
7229 Function written by Marius Șucan. Many thanks to Drugwash for the help provided,
7230*/
7231
7232 Static gdipImgFX := {1:"633C80A4-1843-482b-9EF2-BE2834C5FDD4", 2:"63CBF3EE-C526-402c-8F71-62C540BF5142", 3:"718F2615-7933-40e3-A511-5F68FE14DD74", 4:"A7CE72A9-0F7F-40d7-B3CC-D0C02D5C3212", 5:"D3A1DBE1-8EC4-4c17-9F4C-EA97AD1C343D", 6:"8B2DD6C3-EB07-4d87-A5F0-7108E26A9C5F", 7:"99C354EC-2A31-4f3a-8C34-17A803B33A25", 8:"1077AF00-2848-4441-9489-44AD4C2D7A2C", 9:"537E597D-251E-48da-9664-29CA496B70F8", 10:"74D29D05-69A4-4266-9549-3CC52836B632", 11:"DD6A0022-58E4-4a67-9D9B-D48EB881A53D"}
7233 Ptr := A_PtrSize=8 ? "UPtr" : "UInt"
7234 Ptr2 := A_PtrSize=8 ? "Ptr*" : "PtrP"
7235 pEffect := 0
7236 r1 := COM_CLSIDfromString(eFXguid, "{" gdipImgFX[whichFX] "}" )
7237 If r1
7238 Return "err-" r1
7239
7240 If (A_PtrSize=4) ; 32 bits
7241 {
7242 r2 := DllCall("gdiplus\GdipCreateEffect"
7243 , "UInt", NumGet(eFXguid, 0, "UInt")
7244 , "UInt", NumGet(eFXguid, 4, "UInt")
7245 , "UInt", NumGet(eFXguid, 8, "UInt")
7246 , "UInt", NumGet(eFXguid, 12, "UInt")
7247 , Ptr2, pEffect)
7248 } Else
7249 {
7250 r2 := DllCall("gdiplus\GdipCreateEffect"
7251 , Ptr, &eFXguid
7252 , Ptr2, pEffect)
7253 }
7254 If r2
7255 Return "err-" r2
7256
7257 ; r2 := GetStatus(A_LineNumber ":GdipCreateEffect", r2)
7258
7259 VarSetCapacity(FXparams, 16, 0)
7260 If (whichFX=1) ; Blur FX
7261 {
7262 NumPut(paramA, FXparams, 0, "Float") ; radius [0, 255]
7263 NumPut(paramB, FXparams, 4, "Uchar") ; bool 0, 1
7264 } Else If (whichFX=2) ; Sharpen FX
7265 {
7266 NumPut(paramA, FXparams, 0, "Float") ; radius [0, 255]
7267 NumPut(paramB, FXparams, 4, "Float") ; amount [0, 100]
7268 } Else If (whichFX=5) ; Brightness / Contrast
7269 {
7270 NumPut(paramA, FXparams, 0, "Int") ; brightness [-255, 255]
7271 NumPut(paramB, FXparams, 4, "Int") ; contrast [-100, 100]
7272 } Else If (whichFX=6) ; Hue / Saturation / Lightness
7273 {
7274 NumPut(paramA, FXparams, 0, "Int") ; hue [-180, 180]
7275 NumPut(paramB, FXparams, 4, "Int") ; saturation [-100, 100]
7276 NumPut(paramC, FXparams, 8, "Int") ; light [-100, 100]
7277 } Else If (whichFX=7) ; Levels adjust
7278 {
7279 NumPut(paramA, FXparams, 0, "Int") ; highlights [0, 100]
7280 NumPut(paramB, FXparams, 4, "Int") ; midtones [-100, 100]
7281 NumPut(paramC, FXparams, 8, "Int") ; shadows [0, 100]
7282 } Else If (whichFX=8) ; Tint adjust
7283 {
7284 NumPut(paramA, FXparams, 0, "Int") ; hue [180, 180]
7285 NumPut(paramB, FXparams, 4, "Int") ; amount [0, 100]
7286 } Else If (whichFX=9) ; Colors balance
7287 {
7288 NumPut(paramA, FXparams, 0, "Int") ; Cyan / Red [-100, 100]
7289 NumPut(paramB, FXparams, 4, "Int") ; Magenta / Green [-100, 100]
7290 NumPut(paramC, FXparams, 8, "Int") ; Yellow / Blue [-100, 100]
7291 } Else If (whichFX=11) ; ColorCurve
7292 {
7293 NumPut(paramA, FXparams, 0, "Int") ; Type of adjustment [0, 7]
7294 NumPut(paramB, FXparams, 4, "Int") ; Channels to affect [1, 4]
7295 NumPut(paramC, FXparams, 8, "Int") ; Adjustment value [based on the type of adjustment]
7296 }
7297
7298 DllCall("gdiplus\GdipGetEffectParameterSize", Ptr, pEffect, "uint*", FXsize)
7299 r3 := DllCall("gdiplus\GdipSetEffectParameters", Ptr, pEffect, Ptr, &FXparams, "UInt", FXsize)
7300 If r3
7301 {
7302 Gdip_DisposeEffect(pEffect)
7303 Return "err-" r3
7304 }
7305 ; r3 := GetStatus(A_LineNumber ":GdipSetEffectParameters", r3)
7306 ; ToolTip, % r1 " -- " r2 " -- " r3 " -- " r4,,, 2
7307 Return pEffect
7308}
7309
7310Gdip_DisposeEffect(pEffect) {
7311 Ptr := "UPtr"
7312 r := DllCall("gdiplus\GdipDeleteEffect", Ptr, pEffect)
7313 Return r
7314}
7315
7316GenerateColorMatrix(modus, bright:=1, contrast:=0, saturation:=1, alph:=1, chnRdec:=0, chnGdec:=0, chnBdec:=0) {
7317; parameters ranges / intervals:
7318; bright: [0.001 - 20.0]
7319; contrast: [-20.0 - 1.00]
7320; saturation: [0.001 - 5.00]
7321; alph: [0.001 - 5.00]
7322;
7323; modus options:
7324; 0 - personalized colors based on the bright, contrast [hue], saturation parameters
7325; 1 - personalized colors based on the bright, contrast, saturation parameters
7326; 2 - grayscale image
7327; 3 - grayscale R channel
7328; 4 - grayscale G channel
7329; 5 - grayscale B channel
7330; 6 - negative / invert image
7331; 7 - alpha channel as grayscale image
7332;
7333; chnRdec, chnGdec, chnBdec only apply in modus=1
7334; these represent offsets for the RGB channels
7335
7336; in modus=0 the parameters have other ranges:
7337; bright: [-5.00 - 5.00]
7338; hue: [-1.57 - 1.57] ; pi/2 - contrast stands for hue in this mode
7339; saturation: [0.001 - 5.00]
7340; formulas for modus=0 were written by Smurth
7341; extracted from https://autohotkey.com/board/topic/29449-gdi-standard-library-145-by-tic/page-86
7342;
7343; function written by Marius Șucan
7344; infos from http://www.graficaobscura.com/matrix/index.html
7345; real NTSC values: r := 0.300, g := 0.587, b := 0.115
7346
7347 Static NTSCr := 0.308, NTSCg := 0.650, NTSCb := 0.095 ; personalized values
7348 matrix := ""
7349
7350 If (modus=2) ; grayscale
7351 {
7352 LGA := (bright<=1) ? bright/1.5 - 0.6666 : bright - 1
7353 Ra := NTSCr + LGA
7354 If (Ra<0)
7355 Ra := 0
7356 Ga := NTSCg + LGA
7357 If (Ga<0)
7358 Ga := 0
7359 Ba := NTSCb + LGA
7360 If (Ba<0)
7361 Ba := 0
7362 matrix := Ra "|" Ra "|" Ra "|0|0|" Ga "|" Ga "|" Ga "|0|0|" Ba "|" Ba "|" Ba "|0|0|0|0|0|" alph "|0|" contrast "|" contrast "|" contrast "|0|1"
7363 } Else If (modus=3) ; grayscale R
7364 {
7365 Ga := 0, Ba := 0, GGA := 0
7366 Ra := bright
7367 matrix := Ra "|" Ra "|" Ra "|0|0|" Ga "|" Ga "|" Ga "|0|0|" Ba "|" Ba "|" Ba "|0|0|0|0|0|25|0|" GGA+0.01 "|" GGA "|" GGA "|0|1"
7368 } Else If (modus=4) ; grayscale G
7369 {
7370 Ra := 0, Ba := 0, GGA := 0
7371 Ga := bright
7372 matrix := Ra "|" Ra "|" Ra "|0|0|" Ga "|" Ga "|" Ga "|0|0|" Ba "|" Ba "|" Ba "|0|0|0|0|0|25|0|" GGA "|" GGA+0.01 "|" GGA "|0|1"
7373 } Else If (modus=5) ; grayscale B
7374 {
7375 Ra := 0, Ga := 0, GGA := 0
7376 Ba := bright
7377 matrix := Ra "|" Ra "|" Ra "|0|0|" Ga "|" Ga "|" Ga "|0|0|" Ba "|" Ba "|" Ba "|0|0|0|0|0|25|0|" GGA "|" GGA "|" GGA+0.01 "|0|1"
7378 } Else If (modus=6) ; negative / invert
7379 {
7380 matrix := "-1|0|0|0|0|0|-1|0|0|0|0|0|-1|0|0|0|0|0|" alph "|0|1|1|1|0|1"
7381 } Else If (modus=1) ; personalized saturation, contrast and brightness
7382 {
7383 bL := bright, aL := alph
7384 G := contrast, sL := saturation
7385 sLi := 1 - saturation
7386 bLa := bright - 1
7387 If (sL>1)
7388 {
7389 z := (bL<1) ? bL : 1
7390 sL := sL*z
7391 If (sL<0.98)
7392 sL := 0.98
7393
7394 y := z*(1 - sL)
7395 mA := z*(y*NTSCr + sL + bLa + chnRdec)
7396 mB := z*(y*NTSCr)
7397 mC := z*(y*NTSCr)
7398 mD := z*(y*NTSCg)
7399 mE := z*(y*NTSCg + sL + bLa + chnGdec)
7400 mF := z*(y*NTSCg)
7401 mG := z*(y*NTSCb)
7402 mH := z*(y*NTSCb)
7403 mI := z*(y*NTSCb + sL + bLa + chnBdec)
7404 mtrx:= mA "|" mB "|" mC "| 0 |0"
7405 . "|" mD "|" mE "|" mF "| 0 |0"
7406 . "|" mG "|" mH "|" mI "| 0 |0"
7407 . "| 0 | 0 | 0 |" aL "|0"
7408 . "|" G "|" G "|" G "| 0 |1"
7409 } Else
7410 {
7411 z := (bL<1) ? bL : 1
7412 tR := NTSCr - 0.5 + bL/2
7413 tG := NTSCg - 0.5 + bL/2
7414 tB := NTSCb - 0.5 + bL/2
7415 rB := z*(tR*sLi+bL*(1 - sLi) + chnRdec)
7416 gB := z*(tG*sLi+bL*(1 - sLi) + chnGdec)
7417 bB := z*(tB*sLi+bL*(1 - sLi) + chnBdec) ; Formula used: A*w + B*(1 – w)
7418 rF := z*(NTSCr*sLi + (bL/2 - 0.5)*sLi)
7419 gF := z*(NTSCg*sLi + (bL/2 - 0.5)*sLi)
7420 bF := z*(NTSCb*sLi + (bL/2 - 0.5)*sLi)
7421
7422 rB := rB*z+rF*(1 - z)
7423 gB := gB*z+gF*(1 - z)
7424 bB := bB*z+bF*(1 - z) ; Formula used: A*w + B*(1 – w)
7425 If (rB<0)
7426 rB := 0
7427 If (gB<0)
7428 gB := 0
7429 If (bB<0)
7430 bB := 0
7431 If (rF<0)
7432 rF := 0
7433
7434 If (gF<0)
7435 gF := 0
7436
7437 If (bF<0)
7438 bF := 0
7439
7440 ; ToolTip, % rB " - " rF " --- " gB " - " gF
7441 mtrx:= rB "|" rF "|" rF "| 0 |0"
7442 . "|" gF "|" gB "|" gF "| 0 |0"
7443 . "|" bF "|" bF "|" bB "| 0 |0"
7444 . "| 0 | 0 | 0 |" aL "|0"
7445 . "|" G "|" G "|" G "| 0 |1"
7446 ; matrix adjusted for lisibility
7447 }
7448 matrix := StrReplace(mtrx, A_Space)
7449 } Else If (modus=0) ; personalized hue, saturation and brightness
7450 {
7451 s1 := contrast ; in this mode, contrast stands for hue
7452 s2 := saturation
7453 s3 := bright
7454 aL := alph
7455
7456 s1 := s2*sin(s1)
7457 sc := 1-s2
7458 r := NTSCr*sc-s1
7459 g := NTSCg*sc-s1
7460 b := NTSCb*sc-s1
7461
7462 rB := r+s2+3*s1
7463 gB := g+s2+3*s1
7464 bB := b+s2+3*s1
7465 mtrx := rB "|" r "|" r "| 0 |0"
7466 . "|" g "|" gB "|" g "| 0 |0"
7467 . "|" b "|" b "|" bB "| 0 |0"
7468 . "| 0 | 0 | 0 |" aL "|0"
7469 . "|" s3 "|" s3 "|" s3 "| 0 |1"
7470 matrix := StrReplace(mtrx, A_Space)
7471 } Else If (modus=7)
7472 {
7473 mtrx := "0|0|0|0|0"
7474 . "|0|0|0|0|0"
7475 . "|0|0|0|0|0"
7476 . "|1|1|1|25|0"
7477 . "|0|0|0|0|1"
7478 matrix := StrReplace(mtrx, A_Space)
7479 }
7480 Return matrix
7481}
7482
7483Gdip_CompareBitmaps(pBitmapA, pBitmapB, accuracy:=25) {
7484; On success, it returns the percentage of similarity between the given pBitmaps.
7485; If the given pBitmaps do not have the same resolution,
7486; the return value is -1.
7487;
7488; Function by Tic, from June 2010
7489; Source: https://autohotkey.com/board/topic/29449-gdi-standard-library-145-by-tic/page-27
7490;
7491; Warning: it can be very slow with really large images and high accuracy.
7492;
7493; Updated and modified by Marius Șucan in September 2019.
7494; Added accuracy factor.
7495
7496 If (accuracy>99)
7497 accuracy := 100
7498 Else If (accuracy<5)
7499 accuracy := 5
7500
7501 Gdip_GetImageDimensions(pBitmapA, WidthA, HeightA)
7502 Gdip_GetImageDimensions(pBitmapB, WidthB, HeightB)
7503 If (accuracy!=100)
7504 {
7505 pBitmap1 := Gdip_ResizeBitmap(pBitmapA, Floor(WidthA*(accuracy/100)), Floor(HeightA*(accuracy/100)), 0, 5)
7506 pBitmap2 := Gdip_ResizeBitmap(pBitmapB, Floor(WidthB*(accuracy/100)), Floor(HeightB*(accuracy/100)), 0, 5)
7507 } Else
7508 {
7509 pBitmap1 := pBitmapA
7510 pBitmap2 := pBitmapB
7511 }
7512
7513 Gdip_GetImageDimensions(pBitmap1, Width1, Height1)
7514 Gdip_GetImageDimensions(pBitmap2, Width2, Height2)
7515 if (!Width1 || !Height1 || !Width2 || !Height2
7516 || Width1 != Width2 || Height1 != Height2)
7517 Return -1
7518
7519 E1 := Gdip_LockBits(pBitmap1, 0, 0, Width1, Height1, Stride1, Scan01, BitmapData1)
7520 E2 := Gdip_LockBits(pBitmap2, 0, 0, Width2, Height2, Stride2, Scan02, BitmapData2)
7521 z := 0
7522 Loop %Height1%
7523 {
7524 y++
7525 Loop %Width1%
7526 {
7527 Gdip_FromARGB(Gdip_GetLockBitPixel(Scan01, A_Index-1, y-1, Stride1), A1, R1, G1, B1)
7528 Gdip_FromARGB(Gdip_GetLockBitPixel(Scan02, A_Index-1, y-1, Stride2), A2, R2, G2, B2)
7529 z += Abs(A2-A1) + Abs(R2-R1) + Abs(G2-G1) + Abs(B2-B1)
7530 }
7531 }
7532
7533 Gdip_UnlockBits(pBitmap1, BitmapData1), Gdip_UnlockBits(pBitmap2, BitmapData2)
7534 If (accuracy!=100)
7535 {
7536 Gdip_DisposeImage(pBitmap1)
7537 Gdip_DisposeImage(pBitmap2)
7538 }
7539 Return z/(Width1*Width2*3*255/100)
7540}
7541
7542Gdip_RetrieveBitmapChannel(pBitmap, channel) {
7543; Channel to retrive:
7544; 1 - Red
7545; 2 - Green
7546; 3 - Blue
7547; 4 - Alpha
7548; On success, the function will return a pBitmap
7549; in 32-ARGB PixelFormat containing a grayscale
7550; rendition of the retrieved channel.
7551
7552 If (channel="1")
7553 matrix := GenerateColorMatrix(3)
7554 Else If (channel="2")
7555 matrix := GenerateColorMatrix(4)
7556 Else If (channel="3")
7557 matrix := GenerateColorMatrix(5)
7558 Else If (channel="4")
7559 matrix := GenerateColorMatrix(7)
7560 Else Return
7561
7562 Gdip_GetImageDimensions(pBitmap, imgW, imgH)
7563 If (!imgW || !imgH)
7564 Return
7565
7566 pBrush := Gdip_BrushCreateSolid(0xff000000)
7567 newBitmap := Gdip_CreateBitmap(imgW, imgH)
7568 If !newBitmap
7569 Return
7570
7571 G := Gdip_GraphicsFromImage(newBitmap)
7572 Gdip_SetInterpolationMode(G, 7)
7573 Gdip_FillRectangle(G, pBrush, 0, 0, imgW, imgH)
7574 Gdip_DrawImage(G, pBitmap, 0, 0, imgW, imgH, 0, 0, imgW, imgH, matrix)
7575 Gdip_DeleteBrush(pBrush)
7576 Gdip_DeleteGraphics(G)
7577 Return newBitmap
7578}
7579
7580Gdip_RenderPixelsOpaque(pBitmap, pBrush:=0, alphaLevel:=0) {
7581; alphaLevel - from 0 [transparent] to 1 or beyond [opaque]
7582;
7583; This function is meant to make opaque partially transparent pixels.
7584; It returns a pointer to a new pBitmap.
7585;
7586; If pBrush is given, the background of the image is filled using it,
7587; otherwise, the pixels that are 100% transparent
7588; might remain transparent.
7589
7590 Gdip_GetImageDimensions(pBitmap, imgW, imgH)
7591 newBitmap := Gdip_CreateBitmap(imgW, imgH)
7592 G := Gdip_GraphicsFromImage(newBitmap)
7593 Gdip_SetInterpolationMode(G, 7)
7594 If alphaLevel
7595 matrix := GenerateColorMatrix(0, 0, 0, 1, alphaLevel)
7596 Else
7597 matrix := GenerateColorMatrix(0, 0, 0, 1, 25)
7598 If pBrush
7599 Gdip_FillRectangle(G, pBrush, 0, 0, imgW, imgH)
7600
7601 Gdip_DrawImage(G, pBitmap, 0, 0, imgW, imgH, 0, 0, imgW, imgH, matrix)
7602 Gdip_DeleteGraphics(G)
7603 Return newBitmap
7604}
7605
7606Gdip_TestBitmapUniformity(pBitmap, HistogramFormat:=3, ByRef maxLevelIndex:=0, ByRef maxLevelPixels:=0) {
7607; This function tests whether the given pBitmap
7608; is in a single shade [color] or not.
7609
7610; If HistogramFormat parameter is set to 3, the function
7611; retrieves the intensity/gray histogram and checks
7612; how many pixels are for each level [0, 255].
7613;
7614; If all pixels are found at a single level,
7615; the return value is 1, because the pBitmap is considered
7616; uniform, in a single shade.
7617;
7618; One can set the HistogramFormat to 4 [R], 5 [G], 6 [B] or 7 [A]
7619; to test for the uniformity of a specific channel.
7620;
7621; A threshold value of 0.0005% of all the pixels, is used.
7622; This is to ensure that a few pixels do not change the status.
7623
7624 LevelsArray := []
7625 maxLevelIndex := maxLevelPixels := nrPixels := 9
7626 Gdip_GetImageDimensions(pBitmap, Width, Height)
7627 Gdip_GetHistogram(pBitmap, HistogramFormat, LevelsArray, 0, 0)
7628 Loop 256
7629 {
7630 nrPixels := Round(LevelsArray[A_Index - 1])
7631 If (nrPixels>0)
7632 histoList .= nrPixels "." A_Index - 1 "|"
7633 }
7634 Sort histoList, NURD|
7635 histoList := Trim(histoList, "|")
7636 histoListSortedArray := StrSplit(histoList, "|")
7637 maxLevel := StrSplit(histoListSortedArray[1], ".")
7638 maxLevelIndex := maxLevel[2]
7639 maxLevelPixels := maxLevel[1]
7640 ; ToolTip, % maxLevelIndex " -- " maxLevelPixels " | " histoListSortedArray[1] "`n" histoList, , , 3
7641 pixelsThreshold := Round((Width * Height) * 0.0005) + 1
7642 If (Floor(histoListSortedArray[2])<pixelsThreshold)
7643 Return 1
7644 Else
7645 Return 0
7646}
7647
7648Gdip_SetBitmapAlphaChannel(pBitmap, AlphaMaskBitmap) {
7649; Replaces the alpha channel of the given pBitmap
7650; based on the red channel of AlphaMaskBitmap.
7651; AlphaMaskBitmap must be grayscale for optimal results.
7652; Both pBitmap and AlphaMaskBitmap must be in 32-ARGB PixelFormat.
7653
7654 Gdip_GetImageDimensions(pBitmap, Width1, Height1)
7655 Gdip_GetImageDimensions(AlphaMaskBitmap, Width2, Height2)
7656 if (!Width1 || !Height1 || !Width2 || !Height2
7657 || Width1 != Width2 || Height1 != Height2)
7658 Return -1
7659
7660 newBitmap := Gdip_RenderPixelsOpaque(pBitmap)
7661 alphaUniform := Gdip_TestBitmapUniformity(AlphaMaskBitmap, 3, maxLevelIndex, maxLevelPixels)
7662 If (alphaUniform=1)
7663 {
7664 ; if the given AlphaMaskBitmap is only in a single shade,
7665 ; the opacity of the pixels in the given pBitmap is set
7666 ; using a ColorMatrix.
7667 newAlpha := Round(maxLevelIndex/255, 2)
7668 If (newAlpha<0.1)
7669 newAlpha := 0.1
7670
7671 nBitmap := Gdip_RenderPixelsOpaque(pBitmap, 0 , newAlpha)
7672 Gdip_DisposeImage(newBitmap)
7673 Return nBitmap
7674 }
7675
7676 E1 := Gdip_LockBits(newBitmap, 0, 0, Width1, Height1, Stride1, Scan01, BitmapData1)
7677 E2 := Gdip_LockBits(AlphaMaskBitmap, 0, 0, Width2, Height2, Stride2, Scan02, BitmapData2)
7678 Loop %Height1%
7679 {
7680 y++
7681 Loop %Width1%
7682 {
7683 pX := A_Index-1, pY := y-1
7684 R2 := Gdip_RFromARGB(NumGet(Scan02+0, (pX*4)+(pY*Stride2), "UInt")) ; Gdip_GetLockBitPixel()
7685 If (R2>254)
7686 Continue
7687 Gdip_FromARGB(NumGet(Scan01+0, (pX*4)+(pY*Stride1), "UInt"), A1, R1, G1, B1)
7688 NumPut(Gdip_ToARGB(R2, R1, G1, B1), Scan01+0, (pX*4)+(pY*Stride1), "UInt") ; Gdip_SetLockBitPixel()
7689 }
7690 }
7691
7692 Gdip_UnlockBits(newBitmap, BitmapData1)
7693 Gdip_UnlockBits(AlphaMaskBitmap, BitmapData2)
7694 return newBitmap
7695}
7696
7697calcIMGdimensions(imgW, imgH, givenW, givenH, ByRef ResizedW, ByRef ResizedH) {
7698; This function calculates from original imgW and imgH
7699; new image dimensions that maintain the aspect ratio
7700; and are within the boundaries of givenW and givenH.
7701;
7702; imgW, imgH - original image width and height
7703; givenW, givenH - the width and height [in pixels] to adapt to
7704; ResizedW, ResizedH - the width and height resulted from adapting imgW, imgH to givenW, givenH
7705; by keeping the aspect ratio
7706
7707 PicRatio := Round(imgW/imgH, 5)
7708 givenRatio := Round(givenW/givenH, 5)
7709 If (imgW <= givenW) && (imgH <= givenH)
7710 {
7711 ResizedW := givenW
7712 ResizedH := Round(ResizedW / PicRatio)
7713 If (ResizedH>givenH)
7714 {
7715 ResizedH := (imgH <= givenH) ? givenH : imgH
7716 ResizedW := Round(ResizedH * PicRatio)
7717 }
7718 } Else If (PicRatio > givenRatio)
7719 {
7720 ResizedW := givenW
7721 ResizedH := Round(ResizedW / PicRatio)
7722 } Else
7723 {
7724 ResizedH := (imgH >= givenH) ? givenH : imgH ;set the maximum picture height to the original height
7725 ResizedW := Round(ResizedH * PicRatio)
7726 }
7727}
7728
7729GetWindowRect(hwnd, ByRef W, ByRef H) {
7730 ; function by GeekDude: https://gist.github.com/G33kDude/5b7ba418e685e52c3e6507e5c6972959
7731 ; W10 compatible function to find a window's visible boundaries
7732 ; modified by Marius Șucanto return an array
7733 size := VarSetCapacity(rect, 16, 0)
7734 er := DllCall("dwmapi\DwmGetWindowAttribute"
7735 , "UPtr", hWnd ; HWND hwnd
7736 , "UInt", 9 ; DWORD dwAttribute (DWMWA_EXTENDED_FRAME_BOUNDS)
7737 , "UPtr", &rect ; PVOID pvAttribute
7738 , "UInt", size ; DWORD cbAttribute
7739 , "UInt") ; HRESULT
7740
7741 If er
7742 DllCall("GetWindowRect", "UPtr", hwnd, "UPtr", &rect, "UInt")
7743
7744 r := []
7745 r.x1 := NumGet(rect, 0, "Int"), r.y1 := NumGet(rect, 4, "Int")
7746 r.x2 := NumGet(rect, 8, "Int"), r.y2 := NumGet(rect, 12, "Int")
7747 r.w := Abs(max(r.x1, r.x2) - min(r.x1, r.x2))
7748 r.h := Abs(max(r.y1, r.y2) - min(r.y1, r.y2))
7749 W := r.w
7750 H := r.h
7751 ; ToolTip, % r.w " --- " r.h , , , 2
7752 Return r
7753}
7754
7755Gdip_BitmapConvertGray(pBitmap, hue:=0, vibrance:=-40, brightness:=1, contrast:=0, KeepPixelFormat:=0) {
7756; hue, vibrance, contrast and brightness parameters
7757; influence the resulted new grayscale pBitmap.
7758;
7759; KeepPixelFormat can receive a specific PixelFormat.
7760; The function returns a pointer to a new pBitmap.
7761
7762 Gdip_GetImageDimensions(pBitmap, Width, Height)
7763 If (KeepPixelFormat=1)
7764 PixelFormat := Gdip_GetImagePixelFormat(pBitmap, 1)
7765 If StrLen(KeepPixelFormat)>3
7766 PixelFormat := KeepPixelFormat
7767
7768 newBitmap := Gdip_CreateBitmap(Width, Height, PixelFormat)
7769 G := Gdip_GraphicsFromImage(newBitmap)
7770 Gdip_SetInterpolationMode(G, InterpolationMode)
7771 pEffect := Gdip_CreateEffect(6, hue, vibrance, 0)
7772 matrix := GenerateColorMatrix(2, brightness, contrast)
7773 r1 := Gdip_DrawImageFX(G, pBitmap, 0, 0, 0, 0, Width, Height, matrix, pEffect)
7774 Gdip_DisposeEffect(pEffect)
7775 Gdip_DeleteGraphics(G)
7776 Return newBitmap
7777}
7778
7779Gdip_BitmapSetColorDepth(pBitmap, bitsDepth, useDithering:=1) {
7780; Return 0 = OK - Success
7781
7782 ditheringMode := (useDithering=1) ? 9 : 1
7783 If (useDithering=1 && bitsDepth=16)
7784 ditheringMode := 2
7785
7786 Colors := 2**bitsDepth
7787 If bitsDepth Between 2 and 4
7788 bitsDepth := "40s"
7789 If bitsDepth Between 5 and 8
7790 bitsDepth := "80s"
7791 If (bitsDepth="BW")
7792 E := Gdip_BitmapConvertFormat(pBitmap, 0x30101, ditheringMode, 2, 2, 2, 2, 0, 0)
7793 Else If (bitsDepth=1)
7794 E := Gdip_BitmapConvertFormat(pBitmap, 0x30101, ditheringMode, 1, 2, 1, 2, 0, 0)
7795 Else If (bitsDepth="40s")
7796 E := Gdip_BitmapConvertFormat(pBitmap, 0x30402, ditheringMode, 1, Colors, 1, Colors, 0, 0)
7797 Else If (bitsDepth="80s")
7798 E := Gdip_BitmapConvertFormat(pBitmap, 0x30803, ditheringMode, 1, Colors, 1, Colors, 0, 0)
7799 Else If (bitsDepth=16)
7800 E := Gdip_BitmapConvertFormat(pBitmap, 0x21005, ditheringMode, 1, Colors, 1, Colors, 0, 0)
7801 Else If (bitsDepth=24)
7802 E := Gdip_BitmapConvertFormat(pBitmap, 0x21808, 2, 1, 0, 0, 0, 0, 0)
7803 Else If (bitsDepth=32)
7804 E := Gdip_BitmapConvertFormat(pBitmap, 0x26200A, 2, 1, 0, 0, 0, 0, 0)
7805 Else
7806 E := -1
7807 Return E
7808}
7809
7810Gdip_BitmapConvertFormat(pBitmap, PixelFormat, DitherType, DitherPaletteType, PaletteEntries, PaletteType, OptimalColors, UseTransparentColor:=0, AlphaThresholdPercent:=0) {
7811; pBitmap - Handle to a pBitmap object on which the color conversion is applied.
7812
7813; PixelFormat options: see Gdip_GetImagePixelFormat()
7814; Pixel format constant that specifies the new pixel format.
7815
7816; PaletteEntries Number of Entries.
7817; OptimalColors - Integer that specifies the number of colors you want to have in an optimal palette based on a specified pBitmap.
7818; This parameter is relevant if PaletteType parameter is set to PaletteTypeOptimal [1].
7819; UseTransparentColor Boolean value that specifies whether to include the transparent color in the palette.
7820; AlphaThresholdPercent - Real number in the range 0.0 through 100.0 that specifies which pixels in the source bitmap will map to the transparent color in the converted bitmap.
7821;
7822; PaletteType options:
7823; Custom = 0 ; Arbitrary custom palette provided by caller.
7824; Optimal = 1 ; Optimal palette generated using a median-cut algorithm.
7825; FixedBW = 2 ; Black and white palette.
7826;
7827; Symmetric halftone palettes. Each of these halftone palettes will be a superset of the system palette.
7828; e.g. Halftone8 will have its 8-color on-off primaries and the 16 system colors added. With duplicates removed, that leaves 16 colors.
7829; FixedHalftone8 = 3 ; 8-color, on-off primaries
7830; FixedHalftone27 = 4 ; 3 intensity levels of each color
7831; FixedHalftone64 = 5 ; 4 intensity levels of each color
7832; FixedHalftone125 = 6 ; 5 intensity levels of each color
7833; FixedHalftone216 = 7 ; 6 intensity levels of each color
7834;
7835; Assymetric halftone palettes. These are somewhat less useful than the symmetric ones, but are included for completeness.
7836; These do not include all of the system colors.
7837; FixedHalftone252 = 8 ; 6-red, 7-green, 6-blue intensities
7838; FixedHalftone256 = 9 ; 8-red, 8-green, 4-blue intensities
7839;
7840; DitherType options:
7841; None = 0
7842; Solid = 1
7843; - it picks the nearest matching color with no attempt to halftone or dither. May be used on an arbitrary palette.
7844;
7845; Ordered dithers and spiral dithers must be used with a fixed palette.
7846; NOTE: DitherOrdered4x4 is unique in that it may apply to 16bpp conversions also.
7847; Ordered4x4 = 2
7848; Ordered8x8 = 3
7849; Ordered16x16 = 4
7850; Ordered91x91 = 5
7851; Spiral4x4 = 6
7852; Spiral8x8 = 7
7853; DualSpiral4x4 = 8
7854; DualSpiral8x8 = 9
7855; ErrorDiffusion = 10 ; may be used with any palette
7856; Return 0 = OK - Success
7857
7858 VarSetCapacity(hPalette, 4 * PaletteEntries + 8, 0)
7859
7860; tPalette := DllStructCreate("uint Flags; uint Count; uint ARGB[" & $iEntries & "];")
7861 NumPut(PaletteType, &hPalette, 0, "uint")
7862 NumPut(PaletteEntries, &hPalette, 4, "uint")
7863 NumPut(0, &hPalette, 8, "uint")
7864
7865 Ptr := "UPtr"
7866 E1 := DllCall("gdiplus\GdipInitializePalette", "UPtr", &hPalette, "uint", PaletteType, "uint", OptimalColors, "Int", UseTransparentColor, Ptr, pBitmap)
7867 E2 := DllCall("gdiplus\GdipBitmapConvertFormat", Ptr, pBitmap, "uint", PixelFormat, "uint", DitherType, "uint", DitherPaletteType, "uPtr", &hPalette, "float", AlphaThresholdPercent)
7868 E := E1 ? E1 : E2
7869 Return E
7870}
7871
7872Gdip_GetImageThumbnail(pBitmap, W, H) {
7873; by jballi, source
7874; https://www.autohotkey.com/boards/viewtopic.php?style=7&t=70508
7875
7876 DllCall("gdiplus\GdipGetImageThumbnail"
7877 ,"UPtr",pBitmap ;-- *image
7878 ,"UInt",W ;-- thumbWidth
7879 ,"UInt",H ;-- thumbHeight
7880 ,"UPtr*",pThumbnail ;-- **thumbImage
7881 ,"UPtr",0 ;-- callback
7882 ,"UPtr",0) ;-- callbackData
7883
7884 Return pThumbnail
7885}
7886
7887; =================================================
7888; The following functions were written by Tidbit
7889; handed to me by himself to be included here.
7890; =================================================
7891
7892ConvertRGBtoHSL(R, G, B) {
7893; http://www.easyrgb.com/index.php?X=MATH&H=18#text18
7894 SetFormat, float, 0.5 ; for some reason I need this for some colors to work.
7895
7896 R := (R / 255)
7897 G := (G / 255)
7898 B := (B / 255)
7899
7900 Min := min(R, G, B)
7901 Max := max(R, G, B)
7902 del_Max := Max - Min
7903
7904 L := (Max + Min) / 2
7905
7906 if (del_Max = 0)
7907 {
7908 H := S := 0
7909 } else
7910 {
7911 if (L < 0.5)
7912 S := del_Max / (Max + Min)
7913 else
7914 S := del_Max / (2 - Max - Min)
7915
7916 del_R := (((Max - R) / 6) + (del_Max / 2)) / del_Max
7917 del_G := (((Max - G) / 6) + (del_Max / 2)) / del_Max
7918 del_B := (((Max - B) / 6) + (del_Max / 2)) / del_Max
7919
7920 if (R = Max)
7921 {
7922 H := del_B - del_G
7923 } else
7924 {
7925 if (G = Max)
7926 H := (1 / 3) + del_R - del_B
7927 else if (B = Max)
7928 H := (2 / 3) + del_G - del_R
7929 }
7930 if (H < 0)
7931 H += 1
7932 if (H > 1)
7933 H -= 1
7934 }
7935 ; return round(h*360) "," s "," l
7936 ; return (h*360) "," s "," l
7937 return [abs(round(h*360)), abs(s), abs(l)]
7938}
7939
7940ConvertHSLtoRGB(H, S, L) {
7941; http://www.had2know.com/technology/hsl-rgb-color-converter.html
7942
7943 H := H/360
7944 if (S == 0)
7945 {
7946 R := L*255
7947 G := L*255
7948 B := L*255
7949 } else
7950 {
7951 if (L < 0.5)
7952 var_2 := L * (1 + S)
7953 else
7954 var_2 := (L + S) - (S * L)
7955 var_1 := 2 * L - var_2
7956
7957 R := 255 * ConvertHueToRGB(var_1, var_2, H + (1 / 3))
7958 G := 255 * ConvertHueToRGB(var_1, var_2, H)
7959 B := 255 * ConvertHueToRGB(var_1, var_2, H - (1 / 3))
7960 }
7961 ; Return round(R) "," round(G) "," round(B)
7962 ; Return (R) "," (G) "," (B)
7963 Return [round(R), round(G), round(B)]
7964}
7965
7966ConvertHueToRGB(v1, v2, vH) {
7967 vH := ((vH<0) ? ++vH : vH)
7968 vH := ((vH>1) ? --vH : vH)
7969 return ((6 * vH) < 1) ? (v1 + (v2 - v1) * 6 * vH)
7970 : ((2 * vH) < 1) ? (v2)
7971 : ((3 * vH) < 2) ? (v1 + (v2 - v1) * ((2 / 3) - vH) * 6)
7972 : v1
7973}
7974
7975Gdip_ErrrorHandler(errCode, throwErrorMsg, additionalInfo:="") {
7976 Static errList := {1:"Generic_Error", 2:"Invalid_Parameter"
7977 , 3:"Out_Of_Memory", 4:"Object_Busy"
7978 , 5:"Insufficient_Buffer", 6:"Not_Implemented"
7979 , 7:"Win32_Error", 8:"Wrong_State"
7980 , 9:"Aborted", 10:"File_Not_Found"
7981 , 11:"Value_Overflow", 12:"Access_Denied"
7982 , 13:"Unknown_Image_Format", 14:"Font_Family_Not_Found"
7983 , 15:"Font_Style_Not_Found", 16:"Not_TrueType_Font"
7984 , 17:"Unsupported_GdiPlus_Version", 18:"Not_Initialized"
7985 , 19:"Property_Not_Found", 20:"Property_Not_Supported"
7986 , 21:"Profile_Not_Found", 100:"Unknown_Wrapper_Error"}
7987
7988 If !errCode
7989 Return
7990
7991 aerrCode := (errCode<0) ? 100 : errCode
7992 If errList.HasKey(aerrCode)
7993 GdipErrMsg := "GDI+ ERROR: " errList[aerrCode] " [CODE: " aerrCode "]" additionalInfo
7994 Else
7995 GdipErrMsg := "GDI+ UNKNOWN ERROR: " aerrCode additionalInfo
7996
7997 If (throwErrorMsg=1)
7998 MsgBox, % GdipErrMsg
7999
8000 Return GdipErrMsg
8001}