Jump to content

Pixel Data of an Image (GIF)


Recommended Posts

I may be way over my head on this one, but I figured I'd ask just in case.

Let's say I have a GIF that I want to read color data from (or take a small square chunk and average out the data, either way it doesn't matter). Is there any "easy" way of doing this outside of looking up the GIF specification RFC. And if I would have to do it that way, is there an easier format to read (BMP, I'm guessing?).

Thanks for any help or suggestions.

Link to comment
Share on other sites

If you dont want to look in Specification of formats, You propably will have to use BMP format, just start reading of file from end of header (54b) and read the data by 4 bytes for each pixel (remember that they are BGR not RGB) and the data is saved from bottom to top (I dunno why). But if you want to manipulate the image or view it in GUI you will have to lern about the header data also.

P.S-for more info about BMP format visit: http://en.wikipedia.org/wiki/BMP_file_format

Edited by Uriziel01
Link to comment
Share on other sites

If you dont want to look in Specification of formats, You propably will have to use BMP format, just start reading of file from end of header (54b) and read the data by 4 bytes for each pixel (remember that they are BGR not RGB) and the data is saved from bottom to top (I dunno why). But if you want to manipulate the image or view it in GUI you will have to lern about the header data also.

P.S-for more info about BMP format visit: http://en.wikipedia.org/wiki/BMP_file_format

Tried that in this thread. It works, but it takes a while...

http://www.autoitscript.com/forum/index.php?showtopic=69930

Edited by Paulie
Link to comment
Share on other sites

Let's say I have a GIF that I want to read color data from (or take a small square chunk and average out the data, either way it doesn't matter). Is there any "easy" way of doing this outside of looking up the GIF specification RFC. And if I would have to do it that way, is there an easier format to read (BMP, I'm guessing?).

Thanks for any help or suggestions.

This script may help you. You'll have to modify it to suit your needs.

It uses the GDI+ functions _GDIPlus_BitmapLockBits () and _GDIPlus_BitmapUnlockBits ().

If you un-comment these lines in the script,

CODE
_MemoryWrite ($Scan0 + $j * $stride + $i * 4, $memOpen, $color)

_MemoryWrite ($Scan0 + $j * $stride * 2 + $i * 8, $memOpen, $color)

;$MemContents = _MemoryRead ($Scan0 + $j*$stride + $i*4 , $memOpen)

;$pix = hex($MemContents)

;ConsoleWrite($pix & " " )

Next

;ConsoleWrite( @CRLF )

the pixels are written to the SciTE console. You should be able to redirect into an array for pixel manipulation. I have never check the accuracy of the read data, I was only interested in the write data.

To get it working, I had to comment out previous declared Constants in the NomadMemory.au3 file.

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

; 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 $Scan0, $width, $stride, $height, $format, $pix, $memOpen, $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)
    
    ; Create 24 bit bitmap clone
    $iX = _GDIPlus_ImageGetWidth ($hImage)
    $iY = _GDIPlus_ImageGetHeight ($hImage)
    
    $hClone = _GDIPlus_BitmapCloneArea ($hImage, 0, 0, $iX / 2, $iY / 2, $GDIP_PXF32ARGB) 
    _GDIPlus_ImageSaveToFile ($hClone, @ScriptDir & "\GDIPlus_Image.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 & "\GDIPlus_Image.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 * $stride + $i * 4, $memOpen, $color)
            _MemoryWrite ($Scan0 + $j * $stride * 2 + $i * 8, $memOpen, $color)
            ;$MemContents = _MemoryRead ($Scan0 + $j*$stride + $i*4 , $memOpen)
            ;$pix =  hex($MemContents)
            ;ConsoleWrite($pix & " " )
            
        Next
        ;ConsoleWrite( @CRLF )
    Next
    _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

The 300*100 pixel block take about 10 sec to complete. This isn't fast enought for what I want. I am still looking.

Interesting post link by Paulie.

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