Jump to content

GIF Memory Loading


Recommended Posts

Ok. So I saw the script in the example section about using GDI+ to display an animated gif. So i have tried to figure out GDI+ functions before but I've never really been able to grasp them before. Well looking at the script it seems that it just takes the next frame, loads it to memory, reloads the current image control with the new image from memory, than restarts with the next frame. I've stared at this code for a while now, and I havn't really been able to get more than that basic outline. Now here is what I am wondering. Can I take ALL the frames, load them ALL to memory, than call upon them as needed? What are the functions needed for this? Also, as a seperate question, is it possible to directly edit the image stored in memory? I assume it's a basic array of hex values but my knowledge is limited at this low of a level.

A speedy reply would be HIGHLY appreciated. Thankyou very much for help, in advance.

#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <GDIPlus.au3>
#include <Misc.au3>
#include <WinAPI.au3>

Global $Gif = @ScriptDir & "\gif-Green-UFO.gif"
Global $i = 0, $ApX, $ApY, $ApW, $ApH, $eX, $eY

_GDIPlus_Startup()
$hImage = _GDIPlus_ImageLoadFromFile($Gif)

$ApW = _GDIPlus_ImageGetWidth($hImage)
$ApH = _GDIPlus_ImageGetHeight($hImage)
_GDIPlus_ImageDispose($hImage)

$hGUI = GUICreate("", $ApW, $ApH, 0, 0, $WS_POPUP, BitOR($WS_EX_LAYERED, $WS_EX_TOOLWINDOW, $WS_EX_TOPMOST))
GUISetState()

AdlibEnable("FlyUfo", 20)

Do
    ; Load your animated gif
    $hImage = _GDIPlus_ImageLoadFromFile($Gif)

    ; Create a struct to hold the GUID.
    $tDL = DllStructCreate($tagGUID)
    
    ; Get a pointer to the GUID struct.
    $pDimensionIDs = DllStructGetPtr($tDL)

    ; Get the FrameDimensionsCount of the loaded gif
    $GFDC = DllCall($ghGDIPDll, "int", "GdipImageGetFrameDimensionsCount", "ptr", $hImage, "int*", 0)
    
    ; Get the FrameDimensionsList , which fills the GUID struct by passing the GUID pointer and the FrameDimensionsCount.
    DllCall($ghGDIPDll, "int", "GdipImageGetFrameDimensionsList", "ptr", $hImage, "ptr", $pDimensionIDs, "int", $GFDC[2])

    ; Get the FrameCount of the loaded gif by passing the GUID pointer
    $GFC = DllCall($ghGDIPDll, "int", "GdipImageGetFrameCount", "int", $hImage, "ptr", $pDimensionIDs, "int*", 0)
    
    ; If $i = the frame count then reset $i to 0
    If $i = $GFC[3] Then $i = 0

    ; Select the ActiveFrame in the loaded gif by telling it. The frame starts @ 0 ($i)
    DllCall($ghGDIPDll, "int", "GdipImageSelectActiveFrame", "ptr", $hImage, "ptr", $pDimensionIDs, "int", $i)

    ; At this point you can get the CLSID of an encoder and save the frame to file if you want..
    ; Use any Encoder you like. eg: "GIF", "TIF", "BMP", "JPG"
    ; Transparency won't be saved. (You'd need to play with pallets to have the transparency saved)
;~  $sCLSID = _GDIPlus_EncodersGetCLSID ("PNG")
;~  _GDIPlus_ImageSaveToFileEx ($hImage, @MyDocumentsDir & "\Gif_Frame_" & $i & ".png", $sCLSID)
    
    
    ; The rest is just a copy and paste on updating a layered window with the loaded gif.
    ; I tried using _GDIPlus_GraphicsDrawImage() but no matter what I did memory was getting chewed up. leak maybe?
    ; But using the Update layered window and memory use seems to level out and sit pretty idle 
    $hBitmap = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hImage)
    $hScrDC = _WinAPI_GetDC($hGUI)
    $hMemDC = _WinAPI_CreateCompatibleDC($hScrDC)
    $hOld = _WinAPI_SelectObject($hMemDC, $hBitmap)

    $tSize = DllStructCreate($tagSIZE)
    DllStructSetData($tSize, "X", $ApW)
    DllStructSetData($tSize, "Y", $ApH)
    $pSize = DllStructGetPtr($tSize)

    $tSource = DllStructCreate($tagPOINT)
    $pSource = DllStructGetPtr($tSource)

    $tBlend = DllStructCreate($tagBLENDFUNCTION)
    DllStructSetData($tBlend, "Alpha", 255)
    DllStructSetData($tBlend, "Format", 1)
    $pBlend = DllStructGetPtr($tBlend)

    _WinAPI_UpdateLayeredWindow($hGUI, $hScrDC, 0, $pSize, $hMemDC, $pSource, 0, $pBlend, $ULW_ALPHA)
    
    ;Tidy Up at end of each frame, otherwise memory use gets excessive in a short time.
    _GDIPlus_ImageDispose($hImage)
    _WinAPI_ReleaseDC(0, $hScrDC)
    _WinAPI_DeleteObject($hBitmap)
    _WinAPI_DeleteDC($hMemDC)
    
    ; By rights I should be using the const PropertyTagFrameDelay and geting the properties time delay between frames.
    ; I cheated , so shoot me...lol
    Sleep(100)

    $i += 1
Until _IsPressed("1B")

_GDIPlus_Shutdown()

Func FlyUfo()
    Local $Speed = 0
    Do
        If $ApX >= (@DesktopWidth - $ApW) Then
            $eX = "$ApX - 1"
        ElseIf $ApX <= 0 Then
            $eX = "$ApX + 1"
        EndIf
        If $ApY >= (@DesktopHeight - $ApH) Then
            $eY = "$ApY - 1"
        ElseIf $ApY <= 0 Then
            $eY = "$ApY + 1"
        EndIf
        $ApX = Execute($eX)
        $ApY = Execute($eY)
        WinMove($hGUI, "", $ApX, $ApY)
        $Speed += 1
    Until $Speed = 5
EndFunc   ;==>FlyUfo

[center][/center]Working on the next big thing.Currently Playing: Halo 4, League of LegendsXBL GT: iRememberYhslaw

Link to comment
Share on other sites

An infinitely large *sphere* would be perfectly flat; A circle is flat no matter how large or small. :P

Gifs are compressed according to a color scheme, using a lossless compression technique. Some poking around on wikipedia will get you the exact formatting of the bytes. Editing on the fly would be relatively easy once you figured out the format, but would be very tedious to do.

Here is a link to gif animations done in AutoIt. It should help you out :P

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