Jump to content

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

GDI+ standard library 1.45 by tic


  • Please log in to reply
1385 replies to this topic
Learning one
  • Members
  • 1483 posts
  • Last active: Jan 02 2016 02:30 PM
  • Joined: 04 Apr 2009

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

Thanks. :) I would like to say there are more "ready to integrate in Gdip.ahk" functions posted by just me

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


just me
  • Members
  • 1496 posts
  • Last active: Nov 03 2015 04:32 PM
  • Joined: 28 May 2011

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

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

#Include Gdip_All.ahk

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

This issue may be caused by the ICONINFO structure:
typedef struct _ICONINFO {
  BOOL    fIcon;
  DWORD   xHotspot;
  DWORD   yHotspot;
  HBITMAP hbmMask;
  HBITMAP hbmColor;
} ICONINFO, *PICONINFO;
HBITMAP needs to be aligned to an 8 byte boundary for x64. Working changes:

Gdip_CreateBitmapFromFile(sFile, IconNumber=1, IconSize="")
{
	SplitPath, sFile,,, ext
	if ext in exe,dll
	{
		Sizes := IconSize ? IconSize : 256 "|" 128 "|" 64 "|" 48 "|" 32 "|" 16
		[color=#BF0000]BufSize := 12 + (A_PtrSize - 4) + (2 * A_PtrSize)[/color]
      [color=#BF0000]VarSetCapacity(buf, BufSize, 0)[/color]
		Loop, Parse, Sizes, |
		{
			DllCall("PrivateExtractIcons", "str", sFile, "int", IconNumber-1, "int", A_LoopField, "int", A_LoopField, "ptr*", hIcon, "ptr*", 0, "uint", 1, "uint", 0)
			if !hIcon
				continue

			if !DllCall("GetIconInfo", "ptr", hIcon, "ptr", &buf)
			{
				DestroyIcon(hIcon)
				continue
			}
			hbmMask  := [color=#BF0000]NumGet(buf, 12 + (A_PtrSize - 4))[/color]
			hbmColor := [color=#BF0000]NumGet(buf, 12 + (A_PtrSize - 4) + A_PtrSize)[/color]

			if !(hbmColor && DllCall("GetObject", "ptr", hbmColor, "int", [color=#BF0000]BufSize[/color], "ptr", &buf))
			{
				DestroyIcon(hIcon)
				continue
			}
			break
		}
		if !hIcon
			return -1

		Width := NumGet(buf, 4, "int"),  Height := NumGet(buf, 8, "int")
		hbm := CreateDIBSection(Width, -Height), hdc := CreateCompatibleDC(), obm := SelectObject(hdc, hbm)

		if !DllCall("DrawIconEx", "ptr", hdc, "int", 0, "int", 0, "ptr", hIcon, "uint", Width, "uint", Height, "uint", 0, "ptr", 0, "uint", 3)
		{
			DestroyIcon(hIcon)
			return -2
		}

		VarSetCapacity(dib, [color=#BF0000]104[/color])
		DllCall("GetObject", "ptr", hbm, "int", A_PtrSize = 8 ? [color=#BF0000]104[/color] : 84, "ptr", &dib) ; sizeof(DIBSECTION) = 76+2*(A_PtrSize=8?4:0)+2*A_PtrSize
		Stride := NumGet(dib, 12, "int"), Bits := NumGet(dib, 20+(A_PtrSize=8?4:0)) ; padding

		DllCall("gdiplus\GdipCreateBitmapFromScan0", "int", Width, "int", Height, "int", Stride, "int", 0x26200A, "ptr", Bits, "ptr*", pBitmapOld)
		pBitmap := Gdip_CreateBitmap(Width, Height), G := Gdip_GraphicsFromImage(pBitmap)
		Gdip_DrawImage(G, pBitmapOld, 0, 0, Width, Height, 0, 0, Width, Height)
		SelectObject(hdc, obm), DeleteObject(hbm), DeleteDC(hdc)
		Gdip_DeleteGraphics(G), Gdip_DisposeImage(pBitmapOld)
		DestroyIcon(hIcon)
	}
	else
		DllCall("gdiplus\GdipCreateBitmapFromFile", "wstr", sFile, "ptr*", pBitmap)
	return pBitmap
}

Prefer ahkscript.org for the time being.


  • Guests
  • Last active:
  • Joined: --

Equivalent gdi+ could be:

ConvertImage(sInput, sOutput, Width="", Height="", Method="Percent")
{
	pBitmap := Gdip_CreateBitmapFromFile(sInput)
	Width := Gdip_GetImageWidth(pBitmap), Height := Gdip_GetImageHeight(pBitmap)
	
	If (Method = "Percent")
	{
		Width := (Width = -1) ? Height : Width, Height := (Height = -1) ? Width : Height
		dWidth := Round(sWidth*(Width/100)), dHeight := Round(sHeight*(Height/100))
	}
	else If (Method = "Pixels")
	{
		if (Width = -1)
		dWidth := Round((Height/sHeight)*sWidth), dHeight := Height
		else if (Height = -1)
		dHeight := Round((Width/sWidth)*sHeight), dWidth := Width
		else
		dWidth := Width, dHeight := Height
	}
	else
		return -1

	pBitmap1 := Gdip_CreateBitmap(dWidth, dHeight)
	G1 := Gdip_GraphicsFromImage(pBitmap1), Gdip_SetInterpolationMode(G1, 7)

	Gdip_SaveBitmapToFile(pBitmap, sOutput)
	Gdip_DeleteGraphics(G1)
	Gdip_DisposeImage(pBitmap), Gdip_DisposeImage(pBitmap1)
	return 0
}

I havent tested this and didnt really do any error checks. The original has been superceded by the gdi+ lib as it allows a lot more control of what is going on. You can look at the examples for ideas



Hi tic,

Thank you very much for this.

I am trying to use your example of GDI+ to resize image files prior to emailing them. For some reason, my output file ends up the same size as the input file.

I think there may be a problem with the variables loaded here:

Width := Gdip_GetImageWidth(pBitmap), Height := Gdip_GetImageHeight(pBitmap)

I am not sure, and I was having trouble following the function, and was hoping to get a little help. Any help would be greatly appreciated.

Thanks again!

  • Guests
  • Last active:
  • Joined: --
Please disregard the above request. I was able to use a code sample L1 posted in another thread to get the results I desired.

:mrgreen:

ghutch92
  • Members
  • 9 posts
  • Last active: Mar 28 2013 12:05 AM
  • Joined: 16 Oct 2012
I just started using this library and I would like to know how I could program scrolling text like in movie credits. The text will come from a txt file.

I am having a hard time with how to replace in-line text such as :) with a Posted Image and keep the text on the same line.
Example:
I like to see happy faces.
I like to see Posted Image faces.

One more thing would be how to take many lines of text and split it up into different pages based on the text size and screen size. Pages can be saved as a txt file.

Thanks tic for this amazing library.

tic
  • Members
  • 1934 posts
  • Last active: Dec 21 2015 01:05 PM
  • Joined: 22 Apr 2007
A few problems I'm sure with the text parsing, but you get the idea...

pToken := Gdip_Startup()

w := 350, h := 150
Gui, 1: -Caption +E0x80000 +LastFound +AlwaysOnTop +ToolWindow +OwnDialogs
Gui, 1: Show, NA
hwnd1 := WinExist()
hbm := CreateDIBSection(w, h), hdc := CreateCompatibleDC(), obm := SelectObject(hdc, hbm)
G := Gdip_GraphicsFromHDC(hdc), Gdip_SetSmoothingMode(G, 4)

pBrush := Gdip_BrushCreateSolid(0xaa000000)
Gdip_FillRoundedRectangle(G, pBrush, 0, 0, w, h, 5)
Gdip_DeleteBrush(pBrush)

text = Hi! :) Let's learn some GDI+ :) It's easy
match = :)
i := 1
Loop
{
	if (pos := InStr(text, match))
	{
		if (pos > StrLen(match))
		{
			arr%i% := SubStr(text, 1, pos-1)
			i++
		}
		arr%i% := SubStr(text, pos, StrLen(match))
		i++
		StringTrimLeft, text, text, % pos+StrLen(match)-1		;%
	}
	else
	{
		arr%i% := SubStr(text, 1)
		break
	}
}

R1 := R3 := 15
y := 50
Options = x[x] y%y% Left cbbffffff r4 s15 Italic
Loop %i%
{
	if (arr%A_Index% = match)
	{
		pBitmap := Gdip_CreateBitmapFromFile("icon_biggrin.gif")
		Gdip_GetImageDimensions(pBitmap, sw, sh)
		Gdip_DrawImage(G, pBitmap, R1+R3, y, sw, sh)
		Gdip_DisposeImage(pBitmap)
		R1 := R1+R3, R3 := sw
	}
	else
	{
		StringReplace, Options2, Options, [x], % R1+R3, All		;%
		R := Gdip_TextToGraphics(G, arr%A_Index%, Options2, "Arial", w, h)
		StringSplit, R, R, |
	}
}

UpdateLayeredWindow(hwnd1, hdc, (A_ScreenWidth-w)//2, (A_ScreenHeight-h)//2, w, h)
SelectObject(hdc, obm), DeleteObject(hbm), DeleteDC(hdc), Gdip_DeleteGraphics(G)
Gdip_Shutdown(pToken)
return



ghutch92
  • Members
  • 9 posts
  • Last active: Mar 28 2013 12:05 AM
  • Joined: 16 Oct 2012

A few problems I'm sure with the text parsing, but you get the idea...

pToken := Gdip_Startup()

w := 350, h := 150
Gui, 1: -Caption +E0x80000 +LastFound +AlwaysOnTop +ToolWindow +OwnDialogs
Gui, 1: Show, NA
hwnd1 := WinExist()
hbm := CreateDIBSection(w, h), hdc := CreateCompatibleDC(), obm := SelectObject(hdc, hbm)
G := Gdip_GraphicsFromHDC(hdc), Gdip_SetSmoothingMode(G, 4)

pBrush := Gdip_BrushCreateSolid(0xaa000000)
Gdip_FillRoundedRectangle(G, pBrush, 0, 0, w, h, 5)
Gdip_DeleteBrush(pBrush)

text = Hi! :) Let's learn some GDI+ :) It's easy
match = :)
i := 1
Loop
{
	if (pos := InStr(text, match))
	{
		if (pos > StrLen(match))
		{
			arr%i% := SubStr(text, 1, pos-1)
			i++
		}
		arr%i% := SubStr(text, pos, StrLen(match))
		i++
		StringTrimLeft, text, text, % pos+StrLen(match)-1		;%
	}
	else
	{
		arr%i% := SubStr(text, 1)
		break
	}
}

R1 := R3 := 15
y := 50
Options = x[x] y%y% Left cbbffffff r4 s15 Italic
Loop %i%
{
	if (arr%A_Index% = match)
	{
		pBitmap := Gdip_CreateBitmapFromFile("icon_biggrin.gif")
		Gdip_GetImageDimensions(pBitmap, sw, sh)
		Gdip_DrawImage(G, pBitmap, R1+R3, y, sw, sh)
		Gdip_DisposeImage(pBitmap)
		R1 := R1+R3, R3 := sw
	}
	else
	{
		StringReplace, Options2, Options, [x], % R1+R3, All		;%
		R := Gdip_TextToGraphics(G, arr%A_Index%, Options2, "Arial", w, h)
		StringSplit, R, R, |
	}
}

UpdateLayeredWindow(hwnd1, hdc, (A_ScreenWidth-w)//2, (A_ScreenHeight-h)//2, w, h)
SelectObject(hdc, obm), DeleteObject(hbm), DeleteDC(hdc), Gdip_DeleteGraphics(G)
Gdip_Shutdown(pToken)
return


Thanks so much for this example. :)

Do you have any other examples like taking some text and making it scroll like movie credits.

Also how do you find the size of a multiline text bitmap/graphic not the window but the text?

tic
  • Members
  • 1934 posts
  • Last active: Dec 21 2015 01:05 PM
  • Joined: 22 Apr 2007
Scrolling credits. Would need to be modified to suit your needs

pToken := Gdip_Startup()

OnExit, Exit

w := 550, h := 500
Gui, 1: -Caption +E0x80000 +LastFound +AlwaysOnTop +ToolWindow +OwnDialogs
Gui, 1: Show, NA
hwnd1 := WinExist()
hbm := CreateDIBSection(w, h), hdc := CreateCompatibleDC(), obm := SelectObject(hdc, hbm)
G := Gdip_GraphicsFromHDC(hdc), Gdip_SetSmoothingMode(G, 4)
UpdateLayeredWindow(hwnd1, hdc, (A_ScreenWidth-w)//2, (A_ScreenHeight-h)//2, w, h)

pBrush := Gdip_BrushCreateSolid(0xaa000000)

text := "Ben Burtt	 ...	WALL·E / M-O (voice)`n"
		. "lissa Knight	 ...	EVE (voice)`n"
		. "Jeff Garlin	 ...	Captain (voice)`n"
		. "Fred Willard	 ...	Shelby Forthright, BnL CEO`n"
		. "MacInTalk	 ...	AUTO (voice)`n"
		. "John Ratzenberger	 ...	John (voice)`n"
		. "Kathy Najimy	 ...	Mary (voice)`n"
		. "Sigourney Weaver	 ...	Ship's Computer (voice)`n"
		. "Lori Alan	 ...	(voice)`n"
		. "Bob Bergen	 ...	(voice)`n"
		. "John Cygan	 ...	(voice)`n"
		. "Pete Docter	 ...	(voice)`n"
		. "Paul Eiding	 ...	(voice)`n"
		. "Donald Fullilove	 ...	(voice) (as Don Fullilove)`n"
		. "Teresa Ganzel	 ...	(voice)"
StringSplit, text, text, `n

y := 30
Options = x10p y[y] w80p Centre cbbffffff r4 s18 Bold
StringReplace, Options2, Options, [y], %y%, All
R := Gdip_TextToGraphics(G, "I", Options2, "Arial", w, h, 1)
StringSplit, R, R, |
lh := R4*2

SetTimer, Update, 40
return

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

Update:
Gdip_GraphicsClear(G)
Gdip_FillRectangle(G, pBrush, 0, 0, w, h)

Loop %text0%
{
	StringReplace, Options2, Options, [y], %y%, All
	R := Gdip_TextToGraphics(G, text%A_Index%, Options2, "Arial", w, h)
	y += lh
}
StringSplit, R, R, |
if (R2+R4 < 0)
	y := 30
else
	y -= (text0*lh)+3
UpdateLayeredWindow(hwnd1, hdc)
return

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

Exit:
Gdip_DeleteBrush(pBrush)
SelectObject(hdc, obm), DeleteObject(hbm), DeleteDC(hdc), Gdip_DeleteGraphics(G)
Gdip_Shutdown(pToken)
ExitApp
return


ghutch92
  • Members
  • 9 posts
  • Last active: Mar 28 2013 12:05 AM
  • Joined: 16 Oct 2012

Scrolling credits. Would need to be modified to suit your needs

pToken := Gdip_Startup()

OnExit, Exit

w := 550, h := 500
Gui, 1: -Caption +E0x80000 +LastFound +AlwaysOnTop +ToolWindow +OwnDialogs
Gui, 1: Show, NA
hwnd1 := WinExist()
hbm := CreateDIBSection(w, h), hdc := CreateCompatibleDC(), obm := SelectObject(hdc, hbm)
G := Gdip_GraphicsFromHDC(hdc), Gdip_SetSmoothingMode(G, 4)
UpdateLayeredWindow(hwnd1, hdc, (A_ScreenWidth-w)//2, (A_ScreenHeight-h)//2, w, h)

pBrush := Gdip_BrushCreateSolid(0xaa000000)

text := "Ben Burtt	 ...	WALL·E / M-O (voice)`n"
		. "lissa Knight	 ...	EVE (voice)`n"
		. "Jeff Garlin	 ...	Captain (voice)`n"
		. "Fred Willard	 ...	Shelby Forthright, BnL CEO`n"
		. "MacInTalk	 ...	AUTO (voice)`n"
		. "John Ratzenberger	 ...	John (voice)`n"
		. "Kathy Najimy	 ...	Mary (voice)`n"
		. "Sigourney Weaver	 ...	Ship's Computer (voice)`n"
		. "Lori Alan	 ...	(voice)`n"
		. "Bob Bergen	 ...	(voice)`n"
		. "John Cygan	 ...	(voice)`n"
		. "Pete Docter	 ...	(voice)`n"
		. "Paul Eiding	 ...	(voice)`n"
		. "Donald Fullilove	 ...	(voice) (as Don Fullilove)`n"
		. "Teresa Ganzel	 ...	(voice)"
StringSplit, text, text, `n

y := 30
Options = x10p y[y] w80p Centre cbbffffff r4 s18 Bold
StringReplace, Options2, Options, [y], %y%, All
R := Gdip_TextToGraphics(G, "I", Options2, "Arial", w, h, 1)
StringSplit, R, R, |
lh := R4*2

SetTimer, Update, 40
return

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

Update:
Gdip_GraphicsClear(G)
Gdip_FillRectangle(G, pBrush, 0, 0, w, h)

Loop %text0%
{
	StringReplace, Options2, Options, [y], %y%, All
	R := Gdip_TextToGraphics(G, text%A_Index%, Options2, "Arial", w, h)
	y += lh
}
StringSplit, R, R, |
if (R2+R4 < 0)
	y := 30
else
	y -= (text0*lh)+3
UpdateLayeredWindow(hwnd1, hdc)
return

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

Exit:
Gdip_DeleteBrush(pBrush)
SelectObject(hdc, obm), DeleteObject(hbm), DeleteDC(hdc), Gdip_DeleteGraphics(G)
Gdip_Shutdown(pToken)
ExitApp
return


Thanks again. Posted Image

I assume that the texttographics function returns the size of the text graphic. Is this true even for multiline?

RobS1990
  • Members
  • 25 posts
  • Last active: May 13 2015 03:53 AM
  • Joined: 15 Oct 2012
Hi Tic, I'm wondeirng how to use fast imagesearch you outline here: <!-- l --><a class="postlink-local" href="http://www.autohotkey.com/community/viewtopic.php?f=2&t=32238&start=435">viewtopic.php?f=2&t=32238&start=435</a><!-- l -->

How do I get the DLL?

I have downloaded Gdip.ahk from page and read the file, but there is no imagesearch function in that file. I also see the code you posed in the above link refers to a DLL but I can't find where to download the DLL. Sorry if my questions are basic. Are there any examples for imagesearching a window behind another window? Is there something like *transN parameter included, or *n to allow for shades of variation and transparencies included in the function parameters?

I think the OP was last edited in 2011 so maybe all my questions can be solved by finding a recent link :p

Thankyou

Wicked
  • Members
  • 504 posts
  • Last active: Jun 14 2014 06:04 PM
  • Joined: 07 Jun 2008
You don't need another DLL. It points to a function in the machine code. If you search a few pages back in this thread, you'll see others posting versions which support transparency.

3nL8f.png


  • Guests
  • Last active:
  • Joined: --
I've already asked in the original thread for MCodeGen. But since this one is active I will go ahead and risk the ban, especially since it is meant for a GDI related purpose. Does anyone have MCodeGen.ahk available? I've been looking everywhere... :/

Tried my luck with creating c functions with VS2012 and have retrieved what looks like the right code. Other MCode commands are working, but my (extremely simple!) c written functions don't have the proper effect. :/

I'd be very grateful and would give you a big virtual kiss for the script! :D

Uberi
  • Moderators
  • 1119 posts
  • Last active: May 02 2015 06:05 PM
  • Joined: 23 Aug 2010
I checked, and found a copy in the results of my recovery project. For your convenience I've also pasted another copy here.

Wicked
  • Members
  • 504 posts
  • Last active: Jun 14 2014 06:04 PM
  • Joined: 07 Jun 2008
Hello again, guys!

I've been using Gdip_Filter_Colors() for some time. It's what's used to extract all pixels of a certain color from an image. I've been wondering if there's a faster way of doing it:
Gdip_Filter_Colors(pBitmap,Color,Color2){
   Gdip_GetDimensions(pBitmap, w, h)
   pBitmap2 := Gdip_CreateBitmap(w, h)
   Gdip_LockBits(pBitmap, 0, 0, w, h, Stride1, Scan01, BitmapData1)
   Gdip_LockBits(pBitmap2, 0, 0, w, h, Stride2, Scan02, BitmapData2)
   Loop, %h%
   {
      y := A_Index-1
      Loop, %w%
      {
         x := A_Index-1
         ARGB := Gdip_GetLockBitPixel(Scan01, x, y, Stride1)
         if (ARGB==Color)
            Gdip_SetLockBitPixel(Color2,Scan02,x, y,Stride2)
      }
   }
   Gdip_UnlockBits(pBitmap, BitmapData1), Gdip_UnlockBits(pBitmap2, BitmapData2)
   return pBitmap2
}

It just seems as though this method would be slow on a large image. Also, if anyone writes a better method, an allowed variation would be appreciated. :p. I know variation could easily be added to the above in the simple if statement. :p.

3nL8f.png


note1234
  • Members
  • 1 posts
  • Last active: Jan 03 2013 02:39 PM
  • Joined: 28 Oct 2012
How to convert this code to gdi+ pixelsearch.


loop 100
{
PixelSearch, FoundX, FoundY, x1, y1, x2, y2, 0xff866a , 10, fast
if ErrorLevel = 0
Break
}