fonts: text to image (pixels don't quite match)

Get help with using AutoHotkey and its commands and hotkeys
User avatar
jeeswg
Posts: 5290
Joined: 19 Dec 2016, 01:58
Location: UK

fonts: text to image (pixels don't quite match)

06 Oct 2017, 07:33

tl;dr
- Text in an Edit control uses anti-aliasing. Text to image via DrawText doesn't. Is it possible to add anti-aliasing effects to the DrawText image.
- How can I get the text, in text to image via Gdip, to look exactly the same it does in an Edit control or in an image created via DrawText.
- The image created via Gdip is smaller than expected.
- Why can't the Gdip approach make use an hFont obtained via WM_GETFONT.

- I've tried printscreening an Edit control and getting the font from an Edit control and doing image to text, but the images don't match, the pixels of the text are slightly different.
- This is a problem when doing OCR, and wanting to 'teach' the script in advance, various characters based on a font.
- The DrawText image looks like it's of a slightly lower quality cf. the Notepad printscreen. [EDIT:] The DrawText image is composed of solid black pixels, whereas the Notepad printscreen appears to have had anti-aliasing effects applied.
- [EDIT:] An example image of anti-aliasing applied to a slash character:
https://ageeky.com/wp-content/uploads/2 ... 343178.jpg
- In the DrawString image, the text is too small. [EDIT:] If we use 37 instead of 28, it looks about right, however, the text is slightly too wide. I tried 37, based on the size to height calculation: MsgBox, % 28 * (A_ScreenDPI / 72) ;37.333333
- The DrawString approach via Gdip, appears to add anti-aliasing, whereas the DrawText approach doesn't.

Code: Select all

;[Gdip functions]
;GDI+ standard library 1.45 by tic - AutoHotkey Community
;https://autohotkey.com/boards/viewtopic.php?f=6&t=6517

q:: ;text to image
;- printscreen Edit control (Notepad)
;- DrawText (using font from Notepad)
;- DrawString (using font from Notepad)

pToken := Gdip_Startup()
vText := "abcdefghijklmnopqrstuvwxyz"
SendMessage, 0x31, 0, 0, Edit1, ahk_class Notepad ;WM_GETFONT := 0x31
hFontOrig := ErrorLevel
hFont := JEE_FontClone(hFontOrig)
JEE_ImgTextToImg(vText, hFont, "", hBitmap, pBitmap)

vPath = %A_Desktop%\z img abc drawtext.png
Gdip_SaveBitmapToFile(pBitmap, vPath)

vPath = %A_Desktop%\z img abc printscreen.png
;ControlGet, hCtl, Hwnd,, Edit1, ahk_class Notepad
WinGet, hWnd, ID, ahk_class Notepad
;pBitmap := Gdip_BitmapFromHWND(hCtl)
pBitmap := Gdip_BitmapFromHWND(hWnd)
Gdip_SaveBitmapToFile(pBitmap, vPath)

;image smaller than expected
vImgW := 572, vImgH := 41
pBitmap := Gdip_CreateBitmap(vImgW, vImgH)
G := Gdip_GraphicsFromImage(pBitmap)
Gdip_TextToGraphics(G, vText, "s28 Bold", "Courier New")
vPath = %A_Desktop%\z img abc drawstring.png
Gdip_SaveBitmapToFile(pBitmap, vPath)

;hFont was defined earlier, but we seem to need to recreate hFont here,
;for the Gdip approach to work
hFamily := Gdip_FontFamilyCreate("Courier New")
hFont := Gdip_FontCreate(hFamily, 28, 1)
vImgW := 572, vImgH := 41
pBitmap := Gdip_CreateBitmap(vImgW, vImgH)
G := Gdip_GraphicsFromImage(pBitmap)
pBrush := Gdip_BrushCreateSolid(0xffabcdef)
CreateRectF(RectF, 0, 0, vImgW, vImgH)
;StringFormatFlagsNoClip := 0x4000
;StringFormatFlagsNoWrap := 0x1000
hFormat := Gdip_StringFormatCreate(0x4000)
Gdip_DrawString(G, vText, hFont, hFormat, pBrush, RectF)
vPath = %A_Desktop%\z img abc drawstring (1).png
Gdip_SaveBitmapToFile(pBitmap, vPath)
Gdip_SetBitmapToClipboard(pBitmap)
Gdip_Shutdown(pToken)
MsgBox, % "done"
return

;==================================================

JEE_ImgTextToImg(vText, hFont, vOpt:="", ByRef hBitmap:="", ByRef pBitmap:="", vColText:="", vColBk:="")
{
	if (vOpt = "x")
		vFunc := "JEE_GdipStartup", pToken := %vFunc%()

	;measure text as image
	hDC := DllCall("gdi32\CreateCompatibleDC", Ptr,0, Ptr)
	DllCall("gdi32\SelectObject", Ptr,hDC, Ptr,hFont, Ptr)
	VarSetCapacity(RECT, 16, 0)

	;didn't work
	;if !(vColText = "")
	;	DllCall("gdi32\SetTextColor", Ptr,hDC, UInt,vColText)
	;if !(vColBk = "")
	;	DllCall("gdi32\SetBkColor", Ptr,hDC, UInt,vColBk)

	;DT_CALCRECT := 0x400
	DllCall("user32\DrawText", Ptr,hDC, Str,vText, Int,-1, Ptr,&RECT, UInt,0x400)
	vImgW := NumGet(&RECT, 8, "Int")
	vImgH := NumGet(&RECT, 12, "Int")

	;create text as image
	hBitmap := DllCall("gdi32\CreateCompatibleBitmap", Ptr,hDC, Int,vImgW, Int,vImgH, Ptr)
	DllCall("gdi32\SelectObject", Ptr,hDC, Ptr,hBitmap, Ptr)
	VarSetCapacity(RECT, 16, 0)
	;DT_NOCLIP := 0x100
	DllCall("user32\DrawText", Ptr,hDC, Str,vText, Int,-1, Ptr,&RECT, UInt,0x100)
	DllCall("gdiplus\GdipCreateBitmapFromHBITMAP", Ptr,hBitmap, Ptr,0, PtrP,pBitmap)
	DllCall("gdiplus\GdipCreateHBITMAPFromBitmap", Ptr,pBitmap, PtrP,hBitmap, UInt,0xffffffff)
	if !IsByRef(pBitmap)
		DllCall("gdiplus\GdipDisposeImage", Ptr,pBitmap)

	if (vOpt = "x")
		vFunc := "JEE_GdipShutdown", %vFunc%(pToken)
}

;==================================================

;e.g. hFontNew := JEE_FontClone(hFont)
JEE_FontClone(hFont)
{
	VarSetCapacity(LOGFONT, 92, 0) ;LOGFONT (Unicode)
	vSize := DllCall("gdi32\GetObject", Ptr,hFont, Int,0, Ptr,0)
	DllCall("gdi32\GetObject", Ptr,hFont, Int,vSize, Ptr,&LOGFONT)
	return DllCall("gdi32\CreateFontIndirect", Ptr,&LOGFONT, Ptr)
}

;==================================================
Links:
Anti-Aliasing and Fonts - YouTube
https://www.youtube.com/watch?v=6H1qNSchH1w
aaexampleIMG_id1386238400_343178.jpg
https://ageeky.com/wp-content/uploads/2 ... 343178.jpg
FindText - Capture screen image into text and then find it - Page 5 - AutoHotkey Community
https://autohotkey.com/boards/viewtopic ... 56#p180956
User avatar
jeeswg
Posts: 5290
Joined: 19 Dec 2016, 01:58
Location: UK

Re: fonts: text to image (pixels don't quite match)

06 Dec 2017, 04:47

- Since the original post, I've found out some more information, cleared up a few things, and made some edits above.
- Fundamentally now, I'm looking for a bit more information re. the Gdip_TextToGraphics function. And also, if it's possible to convert an image from anti-aliasing off to anti-aliasing on.
User avatar
jeeswg
Posts: 5290
Joined: 19 Dec 2016, 01:58
Location: UK

Re: fonts: text to image (pixels don't quite match)

11 Jan 2018, 03:01

- New question. I'm interested as to whether fonts come with default kerning/leading values, or whether there's some approximate rule e.g. font size to pixels between characters/baselines. I'll also try some testing myself (type some text and measure). Thanks.
- kerning (space between characters) [k e r n i n g]
- leading (space between baselines) [pron. 'ledding']

Links:
What’s the Difference Between Leading, Kerning and Tracking? ~ Creative Market Blog
https://creativemarket.com/blog/whats-t ... d-tracking
Kerning - Wikipedia
https://en.wikipedia.org/wiki/Kerning
Leading - Wikipedia
https://en.wikipedia.org/wiki/Leading
User avatar
jeeswg
Posts: 5290
Joined: 19 Dec 2016, 01:58
Location: UK

Re: fonts: text to image (pixels don't quite match)

15 Jan 2018, 03:56

- I've been trying to get DrawText to do text to image with anti-aliasing applied, but still no luck.
- The idea is that I could teach a script the images of various characters in a pixel-based OCR script.
- If the list is not pre-populated in advance, it means that you would have to teach the script new characters every time they are found. Or, you would have to teach the script characters, by having an Edit control open, and repeatedly printscreening it.
- Note: the script needs the JEE_ImgTextToImg function (see above), and the Gdip/Gdip_All library.

Code: Select all

;[requires JEE_ImgTextToImg function]

;[requires Gdip/Gdip_All library]
;GDI+ standard library 1.45 by tic - AutoHotkey Community
;https://autohotkey.com/boards/viewtopic.php?f=6&t=6517

q:: ;text to image
;note: uses DrawText (using font from Notepad)

pToken := Gdip_Startup()
vText := "abcdefghijklmnopqrstuvwxyz"
SendMessage, 0x31, 0, 0, Edit1, ahk_class Notepad ;WM_GETFONT := 0x31
hFontOrig := ErrorLevel

;====================

;from wingdi.h:
;DEFAULT_QUALITY := 0
;DRAFT_QUALITY := 1
;PROOF_QUALITY := 2
;NONANTIALIASED_QUALITY := 3
;ANTIALIASED_QUALITY := 4
;CLEARTYPE_QUALITY := 5
;CLEARTYPE_NATURAL_QUALITY := 6

;clone font but change quality value
vSize := DllCall("gdi32\GetObject", Ptr,hFontOrig, Int,0, Ptr,0)
VarSetCapacity(LOGFONT, vSize)
DllCall("gdi32\GetObject", Ptr,hFontOrig, Int,vSize, Ptr,&LOGFONT)
vQuality := NumGet(&LOGFONT, 26, "UChar") ;lfQuality
;MsgBox, % vQuality
NumPut(5, &LOGFONT, 26, "UChar")
;NumPut(6, &LOGFONT, 26, "UChar")
;vQuality := NumGet(&LOGFONT, 26, "UChar") ;lfQuality
;MsgBox, % vQuality
hFont := DllCall("gdi32\CreateFontIndirect", Ptr,&LOGFONT, Ptr)

;====================

;from WinUser.h:
;FE_FONTSMOOTHINGSTANDARD := 0x1
;FE_FONTSMOOTHINGCLEARTYPE := 0x2

;SPI_GETFONTSMOOTHING := 0x4A
DllCall("SystemParametersInfo", UInt,0x4A, UInt,0, UIntP,vState, UInt,0)
MsgBox, % vState

;SPI_GETFONTSMOOTHINGTYPE := 0x200A
DllCall("SystemParametersInfo", UInt,0x200A, UInt,0, UIntP,vState, UInt,0)
MsgBox, % vState

;SPI_SETFONTSMOOTHING := 0x4B
;enable:
;DllCall("SystemParametersInfo", UInt,0x4B, UInt,1, Ptr,0, UInt,0)
;disable:
;DllCall("SystemParametersInfo", UInt,0x4B, UInt,0, Ptr,0, UInt,0)

;====================

JEE_ImgTextToImg(vText, hFont, "", hBitmap, pBitmap)

vPath = %A_Desktop%\z img abc drawtext.png
;Gdip_SaveBitmapToFile(pBitmap, vPath)

Gdip_SaveBitmapToFile(pBitmap, vPath)
Gdip_SetBitmapToClipboard(pBitmap)

Gdip_DisposeImage(pBitmap)
Gdip_Shutdown(pToken)
MsgBox, % "done"
return

Return to “Ask For Help”

Who is online

Users browsing this forum: Albireo, Bing [Bot], Google [Bot] and 67 guests