Jump to content

Read pixel color from .bmp file


Recommended Posts

Hi all,

How can I read pixel color from X coordinate and Y coordinate from bitmap file?

Thanks a lot,

Andreik

Thanks for your question.

It made me look at this script so I could understand what was happening.

I had been experimenting/playing with the _GDIPlus_BitmapLockBits() and _GDIPlus_BitmapUnlockBits() functions in GDIPlus and now have managed to get PixelWrite() and PixelRead() functions. There must be other ways to do this, but I haven't found them yet.

This script is just my discovery script. You can take what you need.

I did discover the bitmap is written over the Title bar. So to drag the image, click on any of the pixels in the top 20 pixel rows.

I left my experimenting with the Alpha channel in, someone may find it interesting.

You may need a desktop magnifying program/script to see the pixels at top left of image.

#include <GuiConstantsEx.au3>
#include <GDIPlus.au3>
#include <ScreenCapture.au3>
#include <Constants.au3>
#include "NomadMemory.au3" ; Constants commented out
#include <WinAPI.au3>
#include <WindowsConstants.au3>

Global $stride, $Scan0, $memOpen

; Example -         http://www.forum.it-berater.org/index.php?topic=66.0;prev_next=prev
; Example -         http://www.xtremevbtalk.com/archive/index.php/t-86403.html
; NomadMemory.au3 - http://www.autoitscript.com/forum/index.php?s=&showtopic=19329&view=findpost&p=394082
Opt('MustDeclareVars', 1)
Opt("PixelCoordMode", 0)
_Main()

Func _Main()
    Local Const $ULW_ALPHA = 2
    Local $hGUI, $hBitmap, $hGraphic, $hImage, $iX, $iY, $hClone, $tBitmapData[200][150], $pter, $hGUIFake
    Local $width, $height, $format, $pix, $MemContents, $Value, $color, $hBitmap1
    Local $hWnd, $hDC, $hBitmap, $pSize, $tSize, $pSource, $tSource, $pBlend, $tBlend, $Reslt, $hImage1
    Local $ReadMaterial, $iOpacity = 255
    
    ; Create GUI's
    $hGUI = GUICreate("GDI+", 600, 500, -1, -1, 0, BitOR($WS_EX_LAYERED, $WS_EX_TOPMOST))
    GUISetState()
    $hGUIFake = GUICreate("GDI+", 600, 500)
    GUISetState()
    _GDIPlus_Startup ()
    
    $hBitmap = _ScreenCapture_Capture ("")
    $hImage = _GDIPlus_BitmapCreateFromHBITMAP ($hBitmap)
    $hGraphic = _GDIPlus_ImageGetGraphicsContext ($hImage)
    _GDIPlus_GraphicsClear ($hGraphic, 0xFFCC8040)
    $iX = _GDIPlus_ImageGetWidth ($hImage)
    $iY = _GDIPlus_ImageGetHeight ($hImage)
    
    $hClone = _GDIPlus_BitmapCloneArea ($hImage, 0, 0, $iX / 2, $iY / 2, $GDIP_PXF32ARGB)
    _GDIPlus_ImageSaveToFile ($hClone, @ScriptDir & "\GDIP0xFFCC8040.bmp")

    ; Clean up resources
    _GDIPlus_ImageDispose ($hClone)
    _GDIPlus_ImageDispose ($hImage)
    _WinAPI_DeleteObject ($hBitmap)
    
    $hWnd = _WinAPI_GetDC (0)
    $hDC = _WinAPI_CreateCompatibleDC ($hWnd)
    $hBitmap = _WinAPI_CreateCompatibleBitmap ($hWnd, 600, 500)
    _WinAPI_SelectObject ($hDC, $hBitmap)
    $hGraphic = _GDIPlus_GraphicsCreateFromHDC ($hDC)

    ; Load bitmap to memory
    $hBitmap1 = _GDIPlus_BitmapCreateFromFile (@ScriptDir & "\GDIP0xFFCC8040.bmp")
    
    $Reslt = _GDIPlus_BitmapLockBits ($hBitmap1, 0, 20, 301, 101, 3, $GDIP_PXF32ARGB) ;,$GDIP_PXF24RGB)
    If @error Then
        ConsoleWrite($Reslt[0] & @CRLF)
        Exit
    EndIf
    ;get the returned values of _GDIPlus_BitmapLockBits ()
    $width = DllStructGetData($Reslt, "width")
    $height = DllStructGetData($Reslt, "height")
    $stride = DllStructGetData($Reslt, "stride")
    $format = DllStructGetData($Reslt, "format")
    $Scan0 = DllStructGetData($Reslt, "Scan0")
    ; See GDIPlusConstants.au3 (Line 115+) for format Numbers
    $ReadMaterial = "The bitmap image is loading. To pass the time some reading material." & @CRLF & @CRLF & _
            "A snap shot of the top left quarter of the screen has been saved to this " & _
            "script directory as GDIPlus_Image.bmp. This ensures a bitmap is available to be " & _
            "loaded from a file into memory." & @CRLF & "This window will be deleted when the coloured " & _
            "pixels have been written to the area of memory where the bitmap is stored. The final " & _
            "bitmap image that will appear has 2 areas of vertical coloured lines. The second, larger " & _
            "area of pixels was written to memory at twice the spacings, vertically and horizontally. " & _
            @CRLF & @CRLF & "I experimented with the Alpha channel opacity of the ARGB (Alpha Red Green Blue)" & _
            " color format. Every third line from right does not have FF in the Alpha channel, therefore " & _
            "some transparency.  The overall $iOpacity variable is linked to the alpha channel in the blend " & _
            "structure in the _WinAPI_UpdateLayeredWindow() function. By this time the bitmap should be loaded." & _
            @CRLF & "To exit, Click on image to make it the active window, then press escape." & @CRLF & @CRLF & _
            "Contents of $tagGDIPBITMAPDATA. (The output of the _GDIPlus_BitmapLockBits() function):" & @CRLF & _
            "width:  " & $width & @CRLF & _
            "height: " & $height & @CRLF & _
            "stride: " & $stride & @CRLF & _
            "format: " & Hex($format, 8) & @CRLF & _
            "Scan0 : " & $Scan0
    
    $memOpen = _MemoryOpen (_WinAPI_GetCurrentProcessID ())
    GUISetCursor(1)
    GUICtrlCreateLabel($ReadMaterial, 10, 10, 580, 480)
    GUICtrlSetFont(-1, 11, 500)
    
    For $i = 1 To 300
        For $j = 1 To 100
            If $i < 10 Then $color = 0xffff00ff
            If Mod($i, 10) = 0 Then $color = 0xffffff00
            If Mod($i, 20) = 0 Then $color = Random(0xff000000, 0xffff0000, 1)
            If Mod($i, 30) = 0 Then $color = 0x00000000 ;Alpha complete transparent
            If $i = 60 Then $color = 0x40ff0000  ; Alpha 40, red   ff,transparent red shade
            If $i = 90 Then $color = 0x4000ff00  ; Alpha 40, green ff,transparent green shade
            If $i = 120 Then $color = 0x400000ff ; Alpha 40, blue  ff,transparent blue shade
            
            _MemoryWrite ($Scan0 + (($j - 21) * $stride) + (($i - 1) * 4), $memOpen, $color)
            _MemoryWrite ($Scan0 + (($j - 21) * $stride) * 2 + (($i - 1) * 8), $memOpen, $color)
            
            PixelWrite(1, 1)              ;Will write 0xff000000 (black) @ pixel 1,1 
            PixelWrite(2, 1, 0xffffffff)  ;Will write 0xffffffff (white) @ pixel 2,1

            $MemContents = PixelRead($i, $j)
            ;$MemContents = _MemoryRead ($Scan0 + (($j-21) * $stride) + (($i-1)*4), $memOpen)
            
            $pix = Hex($MemContents)
            ConsoleWrite($pix & " ")
            
        Next
        ConsoleWrite(@CRLF)
    Next
    ;_MemoryWrite ($Scan0 + (-20 * $stride) + (0*4), $memOpen, 0xff000000)  ;Pixel 1,1
    ;_MemoryWrite ($Scan0 + (-20 * $stride) + (1*4), $memOpen, 0xff000000)  ;Pixel 2,1
    ;_MemoryWrite ($Scan0 + (-19 * $stride) + (0*4), $memOpen, 0xff000000)  ;Pixel 1,2
    ;_MemoryWrite ($Scan0 + (-19 * $stride) + (1*4), $memOpen, 0xff000000)  ;Pixel 1,2  
    
    _MemoryClose ($memOpen)
    
    _GDIPlus_BitmapUnlockBits ($hBitmap1, $Reslt)
    GUISetCursor(2)
    MsgBox(0, "Ready to Continue", "Bitmap has loaded. Press  OK to continue.")
    GUIDelete($hGUIFake)
    ;$hGraphic = _GDIPlus_GraphicsCreateFromHWND ($hGUI)
    ;msgbox(0,"",$hGraphic)
    $Value = _GDIPlus_GraphicsDrawImage ($hGraphic, $hBitmap1, 0, 0)
    
    $tSize = DllStructCreate($tagSIZE)
    $pSize = DllStructGetPtr($tSize)
    DllStructSetData($tSize, "X", 600)
    DllStructSetData($tSize, "Y", 500)
    $tSource = DllStructCreate($tagPOINT)
    $pSource = DllStructGetPtr($tSource)
    $tBlend = DllStructCreate($tagBLENDFUNCTION)
    $pBlend = DllStructGetPtr($tBlend)
    DllStructSetData($tBlend, "Alpha", $iOpacity)
    DllStructSetData($tBlend, "Format", 1)
    _WinAPI_UpdateLayeredWindow ($hGUI, $hWnd, 0, $pSize, $hDC, $pSource, 0, $pBlend, $ULW_ALPHA)

    ; Clean up resources
    _GDIPlus_GraphicsDispose ($hGraphic)
    _WinAPI_DeleteObject ($hBitmap)
    _WinAPI_DeleteObject ($hBitmap1)
    _GDIPlus_ShutDown ()
    
    ; Loop until user exits
    Do
        Sleep(10)
    Until GUIGetMsg() = $GUI_EVENT_CLOSE
EndFunc   ;==>_Main

Func PixelWrite($x, $y, $col = 0xff000000)
    _MemoryWrite ($Scan0 + (($y - 21) * $stride) + (($x - 1) * 4), $memOpen, $col)
EndFunc   ;==>PixelWrite

Func PixelRead($x, $y)
    Local $ret
    $ret = _MemoryRead ($Scan0 + (($y - 21) * $stride) + (($x - 1) * 4), $memOpen)
    Return $ret
EndFunc   ;==>PixelRead

I hope this helps.

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...