Hi all,
I'm trying to better understand the excellent GDIP UDF by Authenticity
So I set myself a simple project to try and create a tonal histogram of an image; I use this in Photoshop a lot.
I started with an old example by Toady at the below link (Thank you Toady for getting me started)
http://www.autoitscript.com/forum/topic/44771-histogram-and-average-color/
Unfortunately 'PixelGetColor' seems very slow, so I wanted to see how fast GdipGetPixel would be.
So, starting with Toady's example, and using GdipGetPixel function by Vossen and ImageScale and Greyscale functions by Uez (Thank you to all) I have the script below...
However, the reason I'm posting in General Help and Support is I found two functions within GDIP v1.1 (Vista and above?) that may be exactly what I want.
two dllcalls instead of 2000
GdipBitmapGetHistogramSize and GdipBitmapGetHistogram
http://msdn.microsoft.com/en-us/library/windows/desktop/ms536307(v=vs.85).aspx
I know nothing about dllcalls but I've tried altering various examples in GDIP.au3 to see if I can get these to work.
After hours of trying on the 'GdipBitmapGetHistogramSize' I've realized I have no hope without a better understanding; I keep getting '0' as a result.
I would greatly appreciate anyone who comes across this post with the knowledge and time to show me how to call these functions.
Many thanks
Jardz
I'm trying to better understand the excellent GDIP UDF by Authenticity
So I set myself a simple project to try and create a tonal histogram of an image; I use this in Photoshop a lot.
I started with an old example by Toady at the below link (Thank you Toady for getting me started)
http://www.autoitscript.com/forum/topic/44771-histogram-and-average-color/
Unfortunately 'PixelGetColor' seems very slow, so I wanted to see how fast GdipGetPixel would be.
So, starting with Toady's example, and using GdipGetPixel function by Vossen and ImageScale and Greyscale functions by Uez (Thank you to all) I have the script below...
[ autoit ]
#include <GDIP.au3> #include <Array.au3> #include <GUIConstants.au3> Global $iSampleRate = 20000 ; Number of pixels read for histogram, the higher the more accurate but slower. Global $histos, $histo $gui = GUICreate("Histogram",278,200,-1,-1) $pen = GuiCtrlCreateGraphic(10,10, 258, 150) GUICtrlSetBkColor(-1,0xFFFFFF) GUICtrlCreateLabel("Sample Rate:",20,160) $sample = GUICtrlCreateInput($iSampleRate,20,175,70,20) ;GUICtrlSetState(-1, $GUI_DISABLE) $BtnOpen= GUICtrlCreateButton("Open", 180, 165, 78, 30) GUISetState() While 1 Switch GUIGetMsg() Case $BtnOpen _main() Case $GUI_EVENT_CLOSE _GDIPlus_ShutDown() Exit EndSwitch WEnd Func _main() Local $tmp $iSampleRate = GUICtrlRead($sample) If $tmp < 1 and $tmp > 99999999 Then GUICtrlSetData($sample,10000) $iSampleRate = 10000 EndIf Local $sFile = FileOpenDialog("Open File", @WorkingDir, "All Picture Files (*.bmp;*.gif;*.jpg;*.jpeg;*.tif;*.tiff;*.png)", 3) Local $t = TimerInit() $aArrayHist = _Histogram($sFile, $iSampleRate) Local $d = Round(TimerDiff($t)/1000,2) ConsoleWrite("Time to build histogram = " & $d & @CRLF) RenderHistogram($aArrayHist) Local $d = Round(TimerDiff($t)/1000,2) ConsoleWrite("Total Time = " & $d & @CRLF) EndFunc Func RenderHistogram($a) Local $max = _ArrayMax($a,1,1) GuiCtrlDelete($pen) $pen=GuiCtrlCreateGraphic(10,10, 258, 150) GUICtrlSetBkColor(-1,0xFFFFFF) GUICtrlSetState(-1, $GUI_DISABLE) For $i = 1 To UBound($a)-1 GUICtrlSetGraphic($pen,$GUI_GR_MOVE, $i,150) GUICtrlSetGraphic($pen,$GUI_GR_LINE, $i,150 - Round(140*($a[$i]/$max),0)) Next GUICtrlSetColor(-1,0x000000) EndFunc Func _Histogram($fImage, $iSampleRate) If $fImage = "" Then Return SetError(1, 0, 0) If Not FileExists($fImage) Then Return SetError(2, 0, 0) Local $fName = StringRegExpReplace($fImage, ".*\\(.*).{4}", "$1") Local $declared = True If Not $ghGDIPDll Then _GDIPlus_Startup() $declared = False EndIf Local $hImageFromFile = _GDIPlus_ImageLoadFromFile($fImage) Local $iWidth = _GDIPlus_ImageGetWidth($hImageFromFile) Local $iHeight = _GDIPlus_ImageGetHeight($hImageFromFile) Local $ratio If $iWidth*$iHeight > $iSampleRate Then $ratio = $iWidth/$iHeight $iW = Int(Sqrt($iSampleRate*$ratio)) $iH = Int(sqrt($iSampleRate/$ratio)) Else $iW = $iWidth $iH = $iHeight EndIf Local $hImageThumbnail = DllCall($ghGDIPDll, "uint", "GdipCreateBitmapFromScan0", "int", $iW, "int", $iH, "int", 0, "int", 0x0026200A, "ptr", 0, "int*", 0) If @error Then Return SetError(3, 0, 0) $hImageThumbnail = $hImageThumbnail[6] Local $hBmpCtxt = _GDIPlus_ImageGetGraphicsContext($hImageThumbnail) DllCall($ghGDIPDll, "uint", "GdipSetInterpolationMode", "handle", $hBmpCtxt, "int", 7) _GDIPlus_GraphicsDrawImageRect($hBmpCtxt, $hImageFromFile, 0, 0, $iW, $iH) _GDIPlus_ImageDispose($hImageFromFile) _GDIPlus_GraphicsDispose($hBmpCtxt) ; If you don't want to transfer to greyscale then comment out below ;#CS $hImageContext = _GDIPlus_ImageGetGraphicsContext($hImageThumbnail) Local $tNegMatrix, $pNegMatrix $tNegMatrix = _GDIPlus_ColorMatrixCreateGrayScale() $pNegMatrix = DllStructGetPtr($tNegMatrix) $hIA = _GDIPlus_ImageAttributesCreate() _GDIPlus_ImageAttributesSetColorMatrix($hIA, 0, True, $pNegMatrix) _GDIPlus_GraphicsDrawImageRectRectIA($hImageContext, $hImageThumbnail, 0, 0, $iW, $iH, 0, 0, $iW, $iH, $hIA) _GDIPlus_ImageAttributesDispose($hIA) _GDIPlus_GraphicsDispose($hImageContext) ;#CE $aHist = _BuildHistogramArray($hImageThumbnail) _GDIPlus_ImageDispose($hImageThumbnail) _GDIPlus_Shutdown() Return $aHist EndFunc Func _BuildHistogramArray($hBitmap) Local $tArgb, $pArgb, $aRet, $blue, $red, $green, $w, $h $tArgb = DllStructCreate("dword Argb") $pArgb = DllStructGetPtr($tArgb) Local $Hist[257] For $i = 0 To UBound($Hist) - 1 $Hist[$i] = 0 Next $w = _GDIPlus_ImageGetWidth($hBitmap) $h = _GDIPlus_ImageGetHeight($hBitmap) ConsoleWrite("Thumbnail W = " & $w & @CRLF & "Thumbnail H = " & $h & @CRLF) ;-------------Use the following if you've changed the bitmap thumbnail to greyscale otherwise comment out and use the next one---------- For $i = 1 To $h For $j = 1 To $w $aRet = DllCall($ghGDIPDll, "int", "GdipBitmapGetPixel", "hwnd", $hBitmap, "int", $j, "int", $i, "ptr", $pArgb) $Hist[Dec(Hex(DllStructGetData($tArgb, "Argb"),2))+1] +=1 $Hist[0] += 1 Next Next ;-------------If you're keeping bitmap as RGB and not Greyscale then use below to build Array for Histogram------------------------------ #cs For $i = 1 To $h For $j = 1 To $w $aRet = DllCall($ghGDIPDll, "int", "GdipBitmapGetPixel", "hwnd", $hBitmap, "int", $j, "int", $i, "ptr", $pArgb) $color_hex = "0x" & Hex(DllStructGetData($tArgb, "Argb") ,6) $Hist[Round((BitAND($color_hex,255) + BitShift(BitAND($color_hex,65280),0x08) + BitShift(BitAND($color_hex,16711680),0x10))/3,0)+1] += 1 $Hist[0] += 1 Next Next #ce $Hist[2] = ($Hist[1] + $Hist[3])/2 ConsoleWrite("Total Count = " & $Hist[0] & @CRLF) Return $Hist EndFunc Func ScaleImage($hImage, $iScaleW, $iScaleH, $iInterpolationMode = 7) ;coded by UEZ 2012 Local $iWidth = _GDIPlus_ImageGetWidth($hImage) * $iScaleW Local $iHeight = _GDIPlus_ImageGetHeight($hImage) * $iScaleH Local $hBitmap = DllCall($ghGDIPDll, "uint", "GdipCreateBitmapFromScan0", "int", $iWidth, "int", $iHeight, "int", 0, "int", 0x0026200A, "ptr", 0, "int*", 0) If @error Then Return SetError(3, 0, 0) $hBitmap = $hBitmap[6] Local $hBmpCtxt = _GDIPlus_ImageGetGraphicsContext($hBitmap) DllCall($ghGDIPDll, "uint", "GdipSetInterpolationMode", "handle", $hBmpCtxt, "int", $iInterpolationMode) _GDIPlus_GraphicsDrawImageRect($hBmpCtxt, $hImage, 0, 0, $iWidth, $iHeight) _GDIPlus_ImageDispose($hImage) _GDIPlus_GraphicsDispose($hBmpCtxt) Return $hBitmap EndFunc
However, the reason I'm posting in General Help and Support is I found two functions within GDIP v1.1 (Vista and above?) that may be exactly what I want.
two dllcalls instead of 2000
GdipBitmapGetHistogramSize and GdipBitmapGetHistogram
http://msdn.microsoft.com/en-us/library/windows/desktop/ms536307(v=vs.85).aspx
I know nothing about dllcalls but I've tried altering various examples in GDIP.au3 to see if I can get these to work.
After hours of trying on the 'GdipBitmapGetHistogramSize' I've realized I have no hope without a better understanding; I keep getting '0' as a result.
I would greatly appreciate anyone who comes across this post with the knowledge and time to show me how to call these functions.
Many thanks
Jardz