Jump to content

PixelGetColor vs. _GDIPlus_BitmapLockBits


QED
 Share

Recommended Posts

In a recent discussion, it was found (with AdmiralAlkex’s help) that having DWM enabled caused a massive performance hit (factor of 1,000) when using PixelGetColor.

I have only used the _GDIPlus_BitmapLockBits method which according to this example is 20x faster than the "GetPixel" method. Initially I was happy to accept this claim on face value, but after the above discussion I was not so sure. So I made this little script to compare the two methods.

The results are highly sensitive to calculations inside the loop so I've kept each loop as simple as possible. For each method, the pixel located at (1,1) is sampled n times. This should give you an idea of the raw "pixel getting power" of each method.

The main take-aways for me are:

1. GDIPlus does NOT suffer any performance hit if DWM is enabled.

2. GDIPlus outperforms PixelGetColor by a factor of ~5 if DWM is disabled and by a factor of ~5,000 if DWM is enabled.

3. Calling _GDIPlus_BitmapLockBits inside the loop (for each pixel-get) slows it down by a factor of ~30. In this very rare case it would be better to use PixelGetColor with DWM disabled.

4. The overhead using GDIPlus is ~5 ms which includes startup, locking, reading, unlocking, disposing and shutdown time. This is still much better than the ~20 ms PixelGetColor takes with DWM enabled.

#include <GDIPlus.au3> ; for GDI+
$wnd=WinGetHandle("Test")

; PixelGet method
$n1 = 100 ; set to ~100 if DWM enabled, otherwise ~100,000 (larger samples are more accurate)
$start_time = TimerInit()
For $i = 1 To $n1
    PixelGetColor( 1, 1, $wnd)
Next
$time1=int(TimerDiff($start_time))/$n1
ConsoleWrite("PixelGet avg (ms/pixel): "&$time1&@CRLF)

; GDI+ method
_GDIPlus_Startup ()
$hGraphic = _GDIPlus_GraphicsCreateFromHWND ($wnd)
$BitmapData = _GDIPlus_BitmapLockBits($hGraphic, 0, 0, 10, 10, $GDIP_ILMREAD, $GDIP_PXF32RGB)
$Scan0 = DllStructGetData($BitmapData, "Scan0")
$Stride = DllStructGetData($BitmapData, "Stride")
$pixel = $Scan0 + $Stride + 4

$n2 = 1000000 ; one million iterations should take ~3 sec
$start_time=TimerInit()
For $i = 1 To $n2
    DllStructCreate("dword", $pixel)
Next
$time2=int(TimerDiff($start_time))/$n2
ConsoleWrite("GDIPlus  avg (ms/pixel): "&$time2&@crlf)

ConsoleWrite("GDIPlus = "&round($time1/$time2,1)&" x PixelGet"&@crlf)

_GDIPlus_BitmapUnlockBits($hGraphic, $BitmapData)
_GDIPlus_GraphicsDispose ($hGraphic)
_GDIPlus_ShutDown ()

Exit
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...