- Screen shot of demo
The function: Along with a demoCode: Select all
ToGrayscale(sBM) { ; By SKAN on CR7J/D39L @ tiny.cc/tograyscale Local ; Original ver. GDI_GrayscaleBitmap() @ https://autohotkey.com/board/topic/82794- P8:=(A_PtrSize=8), VarSetCapacity(BM,P8? 32:24, 0) DllCall("GetObject", "Ptr",sBM, "Int",P8? 32:24, "Ptr",&BM) W := NumGet(BM,4,"Int"), H := NumGet(BM,8,"Int") sDC := DllCall( "CreateCompatibleDC", "Ptr",0, "Ptr") DllCall("DeleteObject", "Ptr",DllCall("SelectObject", "Ptr",sDC, "Ptr",sBM, "Ptr")) tBM := DllCall( "CopyImage", "Ptr" , DllCall( "CreateBitmap", "Int",1, "Int",1, "Int",0x1, "Int",8, "Ptr",0, "Ptr") , "Int",0, "Int",W, "Int",H, "Int",0x2008, "Ptr") tDC := DllCall("CreateCompatibleDC", "Ptr",0, "Ptr") DllCall("DeleteObject", "Ptr",DllCall("SelectObject", "Ptr",tDC, "Ptr",tBM, "Ptr")) Loop % (255, n:=0x000000, VarSetCapacity(RGBQUAD256,256*4,0)) Numput(n+=0x010101, RGBQUAD256, A_Index*4, "Int") DllCall("SetDIBColorTable", "Ptr",tDC, "Int",0, "Int",256, "Ptr",&RGBQUAD256) DllCall("BitBlt", "Ptr",tDC, "Int",0, "Int",0, "Int",W, "Int",H , "Ptr",sDC, "Int",0, "Int",0, "Int",0x00CC0020) Return % (tBM, DllCall("DeleteDC", "Ptr",sDC), DllCall("DeleteDC", "Ptr",tDC)) } ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; Demo follows #NoEnv #SingleInstance, Force SetWorkingDir, %A_ScriptDir% If !FileExist("bluebottlefly.jpg") URLDownloadToFile, https://www.autohotkey.com/boards/download/file.php?id=10624 , bluebottlefly.jpg hBM1 := LoadPicture("bluebottlefly.jpg") hBM2 := ToGrayscale(hBM1) Gui, Margin, 24, 24 Gui, Add, Picture,, HBITMAP:%hBM1% Gui, Add, Picture,x+m, HBITMAP:%hBM2% Gui, Show,, ToGrayscale() Return
ToGrayscale() : Converts GDI bitmap to Greyscale
ToGrayscale() : Converts GDI bitmap to Greyscale
FsGrayscale()
Re: ToGrayscale() : Converts GDI bitmap to Greyscale
Wow. Are the calculations from RGB to Greyscale done by windows itself? I know that RGB channels have different color weights, but I'm not seeing how that is accounted for in the code. (Although your sample looks very good.)
Code: Select all
; Returns a value between 0-255 when given an RGB value.
grayscale(sRGB) {
static rY := 0.212655
static gY := 0.715158
static bY := 0.072187
c1 := 255 & ( sRGB >> 16 )
c2 := 255 & ( sRGB >> 8 )
c3 := 255 & ( sRGB )
loop 3 {
c%A_Index% := c%A_Index% / 255
c%A_Index% := (c%A_Index% <= 0.04045) ? c%A_Index%/12.92 : ((c%A_Index%+0.055)/(1.055))**2.4
}
v := rY*c1 + gY*c2 + bY*c3
v := (v <= 0.0031308) ? v * 12.92 : 1.055*(v**(1.0/2.4))-0.055
return Round(v*255)
}
Re: ToGrayscale() : Converts GDI bitmap to Greyscale
Yes. Windows uses Nearest match method.iseahound wrote:Wow. Are the calculations from RGB to Greyscale done by windows itself?
The magic is here:
Code: Select all
Loop % (255, n:=0x000000, VarSetCapacity(RGBQUAD256,256*4,0))
Numput(n+=0x010101, RGBQUAD256, A_Index*4, "Int")
DllCall("SetDIBColorTable", "Ptr",tDC, "Int",0, "Int",256, "Ptr",&RGBQUAD256)
I create a 256 color table with 256 shades of gray and windows matches nearest color in the table,
probably based on luminosity.
Try replacing n+=0x010101 with n+=0x000101 and you will see a Cyan-scaled image instead of GrayScale.
I conceived/devised this method.
Re: ToGrayscale() : Converts GDI bitmap to Greyscale
I had never compared the results with an another program.iseahound wrote: (Although your sample looks very good.)
I did today. Thanks. I saved hBitmap with GDIP [ SavePicture() ]
Re: ToGrayscale() : Converts GDI bitmap to Greyscale
Hi @SKAN ,
Great and useful function.
One question, can we use this script to convert image in black and white using treshold like in python?
And maybe take one picture and create image augumentation to make few images from one image for use in training object detection.
Thanks,
blue
Great and useful function.
One question, can we use this script to convert image in black and white using treshold like in python?
And maybe take one picture and create image augumentation to make few images from one image for use in training object detection.
Thanks,
blue
Re: ToGrayscale() : Converts GDI bitmap to Greyscale
blue83 wrote: Great and useful function.
Thank you
blue83 wrote: can we use this script to convert image in black and white using treshold like in python?
No built-in method in GDI for it. The returned hBitmap has DIB section. We may get a pointer to the bits and do the conversion manually,
which is usually best done with machine code.
blue83 wrote: And maybe take one picture and create image augumentation to make few images from one image for use in training object detection.
Its above my skillset. I had to Bing to get the faintest idea on what you're talking about.
Re: ToGrayscale() : Converts GDI bitmap to Greyscale
Haha, thank you anyway
Most OCR works better with grayscale image so this is great function.
Thanks,
blue
Most OCR works better with grayscale image so this is great function.
Thanks,
blue
Re: ToGrayscale() : Converts GDI bitmap to Greyscale
@SKAN, thanks for another great addition. I don't think anyone else has such an arsenal of small but very useful scripts.
By the way, for me on both Win10 and Win7, AHK 1.1.33.02, it works great with 32-bit, but for 64-bit only the first image appears.
32-bit:
64-bit:
Regards,
burque505
By the way, for me on both Win10 and Win7, AHK 1.1.33.02, it works great with 32-bit, but for 64-bit only the first image appears.
32-bit:
64-bit:
Regards,
burque505
Re: ToGrayscale() : Converts GDI bitmap to Greyscale
burque505 wrote: @SKAN, thanks for another great addition. I don't think anyone else has such an arsenal of small but very useful scripts.
Thanks
burque505 wrote: By the way, for me on both Win10 and Win7, AHK 1.1.33.02, it works great with 32-bit, but for 64-bit only the first image appears.
Thanks for the report. Fixed.
Re: ToGrayscale() : Converts GDI bitmap to Greyscale
thanks, very useful and clever solution!
EitherMouse - Multiple mice, individual settings . . . . www.EitherMouse.com . . . . forum . . . .
Re: ToGrayscale() : Converts GDI bitmap to Greyscale
blue83 wrote: can we use this script to convert image in black and white using treshold like in python?
blue83 also wrote:
Most OCR works better with grayscale image so this is great function.
Oh! OCR.
It seems simple to add threshold parameter to this function.
But I'm not familiar with python. Do you have a link/screenshot to show how threshold affect the original image
Re: ToGrayscale() : Converts GDI bitmap to Greyscale
Hi @SKAN ,
Here it is.
https://techtutorialsx.com/2019/04/13/python-opencv-converting-image-to-black-and-white/
Also if there is anything to change image brightness?
Thanks,
blue
Here it is.
https://techtutorialsx.com/2019/04/13/python-opencv-converting-image-to-black-and-white/
Also if there is anything to change image brightness?
Thanks,
blue
Re: ToGrayscale() : Converts GDI bitmap to Greyscale
@blue83 Thanks for the link. I will look into it.
Re: ToGrayscale() : Converts GDI bitmap to Greyscale
You're right about the nearest neighbor. I didn't notice at first, but it doesn't seem to be true greyscale. I can see topological rings of grey in the blurred background of the butterfly picture that aren't present in the photoshop equivalent. You could randomize noise and dither the photo to prevent such occurrences, but I think the converting each channel independently and then forming a weighed average has a better visual perception to greyscale.
My greyscale function only converts a single pixel
My greyscale function only converts a single pixel
Re: ToGrayscale() : Converts GDI bitmap to Greyscale
It is a true grayscale. You don't see any colors in it.
I thought the difference is negligible, but no.. you're right. Color matching is botchy. Here is the proof:
Code: Select all
#NoEnv
#Warn
#SingleInstance, Force
SetBatchLines -1
; Creating 32 bit 256x1 color bitmap with all shades of gray
VarSetCapacity(BMBITS, 256*4, 0), pBits := &BMBITS+4, Gray := 0
Loop 255
pBits := NumPut(Gray += 0x010101, pBits+0, "Int")
hBM1 := DllCall("CreateBitmap", "Int",256, "Int",1, "Int",0x1, "Int",32, "Ptr",&BMBITS, "Ptr")
hBM1 := DllCall("CopyImage", "Ptr",hBM1, Int,0, "Int",256, "Int",48, "Int",0x2008, "Ptr")
; Converting above bitmap to 8bit 256 color grayscale
hBM2 := ToGrayscale(hBM1)
Gui, Font, s9, Segoe UI
Gui, Margin, 24, 24
Gui, Add, Picture, xm ym Border, HBITMAP:%hBM1%
Gui, Add, Text, xm y+0 wp h24 0x201, 32 bit color bitmap with 256 shades of Gray
Gui, Add, Picture, xm y+m Border, HBITMAP:%hBM2%
Gui, Add, Text, xm y+0 wp h24 0x201, Converted to 8 bit Grayscale with ToGrayscale()
Gui, Show,, ToGrayscale() demo
Return ; end of auto-execute section4
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ToGrayscale(sBM) { ; By SKAN on CR7J/D39J @ tiny.cc/tograyscale
Local ; Original ver. GDI_GrayscaleBitmap() @ https://autohotkey.com/board/topic/82794-
VarSetCapacity(BM,24,0), DllCall("GetObject", "Ptr",sBM, "Int",24, "Ptr",&BM)
W := NumGet(BM,4,"Int"), H := NumGet(BM,8,"Int")
sDC := DllCall( "CreateCompatibleDC", "Ptr",0, "Ptr")
DllCall("DeleteObject", "Ptr",DllCall("SelectObject", "Ptr",sDC, "Ptr",sBM, "Ptr"))
tBM := DllCall( "CopyImage", "Ptr"
, DllCall( "CreateBitmap", "Int",1, "Int",1, "Int",0x1, "Int",8, "Ptr",0, "Ptr")
, "Int",0, "Int",W, "Int",H, "Int",0x2008, "Ptr")
tDC := DllCall("CreateCompatibleDC", "Ptr",0, "Ptr")
DllCall("DeleteObject", "Ptr",DllCall("SelectObject", "Ptr",tDC, "Ptr",tBM, "Ptr"))
Loop % (255, n:=0x000000, VarSetCapacity(RGBQUAD256,256*4,0))
Numput(n+=0x010101, RGBQUAD256, A_Index*4, "Int")
DllCall("SetDIBColorTable", "Ptr",tDC, "Int",0, "Int",256, "Ptr",&RGBQUAD256)
DllCall("BitBlt", "Ptr",tDC, "Int",0, "Int",0, "Int",W, "Int",H
, "Ptr",sDC, "Int",0, "Int",0, "Int",0x00CC0020)
Return (tBM, DllCall("DeleteDC", "Ptr",sDC), DllCall("DeleteDC", "Ptr",tDC))
}
Ok. I will post a different version that does conversion with machine code.
Re: ToGrayscale() : Converts GDI bitmap to Greyscale
@SKAN i did this a few months back and just posted it here:
https://www.autohotkey.com/boards/viewtopic.php?f=6&t=83208
Re: ToGrayscale() : Converts GDI bitmap to Greyscale
Hi @Xtra,Xtra wrote: ↑13 Nov 2020, 23:19@SKAN i did this a few months back and just posted it here:
https://www.autohotkey.com/boards/viewtopic.php?f=6&t=83208
Thanks for sharing your Gdip_GrayScale().
This topic deals with GDI bitmap, So I will comment on your topic instead.
Re: ToGrayscale() : Converts GDI bitmap to Greyscale
@SKAN it will be interesting to see what you come up with. As always thanks for sharing.
Re: ToGrayscale() : Converts GDI bitmap to Greyscale
Hello @SKAN.
Is it possible to use this to greyscale icon inside an imagelist?
Is it possible to use this to greyscale icon inside an imagelist?