smashly Posted July 30, 2008 Share Posted July 30, 2008 (edited) For some intresting reading of fixes, updates and corrections in running animated gifs with gdi then check out ProgAndy's handy work further down the thread.For those that are using Zedna's Resources.au3 then jump to this post for more info on running animated gifs from a resource once again skip further down the thread.Or just jump straight to Zedna's Resources thread and get the latest news on his awesome work. Here Edited October 5, 2008 by smashly Link to comment Share on other sites More sharing options...
monoceres Posted July 30, 2008 Share Posted July 30, 2008 This is so weird, I was just reading the documentation on msdn for using animated gifs in GDI+, luckily I didn't start yet Anyways, this is good job and this is a definite keeper for future use Good job! Broken link? PM me and I'll send you the file! Link to comment Share on other sites More sharing options...
Zedna Posted July 30, 2008 Share Posted July 30, 2008 This looks VERY good. It's just pity you are using _WinAPI_UpdateLayeredWindow() which doesn't work on my WIN98 but it can be overcome. Resources UDF ResourcesEx UDF AutoIt Forum Search Link to comment Share on other sites More sharing options...
Gigglestick Posted July 30, 2008 Share Posted July 30, 2008 ...which doesn't work on my WIN98...O.M.F.G. algiuxas 1 My UDFs: ExitCodes Link to comment Share on other sites More sharing options...
Zedna Posted July 30, 2008 Share Posted July 30, 2008 O.M.F.G.Stay calm :-) I will move to XP in the near future. Resources UDF ResourcesEx UDF AutoIt Forum Search Link to comment Share on other sites More sharing options...
monoceres Posted July 30, 2008 Share Posted July 30, 2008 Stay calm :-) I will move to XP in the near future.Sorry for OT, but has there always been a little bug in your avatar?Just noticed it Broken link? PM me and I'll send you the file! Link to comment Share on other sites More sharing options...
Zedna Posted July 30, 2008 Share Posted July 30, 2008 Sorry for OT, but has there always been a little bug in your avatar?Just noticed it Sorry for OT too.What bug?If you mean picture representing my avatar it's just abstract organism. I have this avatar all the time on this forum. Resources UDF ResourcesEx UDF AutoIt Forum Search Link to comment Share on other sites More sharing options...
BillLuvsU Posted July 31, 2008 Share Posted July 31, 2008 (edited) Jesus. Oh jesus. JESUS JESUS JESUS JESUS. This is perfect. This solves so many problems. OMG I ****ING LOVE YOU. It means I'll have to rewrite a little but other than that this IS PERFECT. I knew I should have done some research into GDI. Edit: Could you help me out some? I havn't ever really done any work with GDI and I'm scared of breaking your script. Could you forge it into function form right quick for me? Shouldn't take to long. Just a simple function that creates the gif then returns the handle. Also one to stop/start it. Like, I will bear your children if you do this for me. This has me really excited in case you didn't notice. Edited July 31, 2008 by BillLuvsU [center][/center]Working on the next big thing.Currently Playing: Halo 4, League of LegendsXBL GT: iRememberYhslaw Link to comment Share on other sites More sharing options...
rasim Posted July 31, 2008 Share Posted July 31, 2008 smashlyCool! Very nice job! I like it! 5 stars! Link to comment Share on other sites More sharing options...
Zedna Posted July 31, 2008 Share Posted July 31, 2008 Could you help me out some? I havn't ever really done any work with GDI and I'm scared of breaking your script. Could you forge it into function form right quick for me? Shouldn't take to long. Just a simple function that creates the gif then returns the handle. Also one to stop/start it. Like, I will bear your children if you do this for me. This has me really excited in case you didn't notice. Here is changed original script. You can Pause/unPause animation, in Pause mode you can navigate through frames by Left/Right Note: Moving of window is intentionally disabled in this example --> you can uncomment AdlibEnable("FlyUfo", 20) expandcollapse popup#include <GUIConstantsEx.au3> #include <WindowsConstants.au3> #include <GDIPlus.au3> #include <Misc.au3> #include <WinAPI.au3> HotKeySet("{Esc}", "Quit") HotKeySet("{Left}", "Left") HotKeySet("{Right}", "Right") HotKeySet("{Pause}", "Pause") Global $Gif = @ScriptDir & "\gif-Green-UFO.gif" Global $i = 0, $ApX, $ApY, $ApW, $ApH, $eX, $eY Global $hImage, $hBitmap, $hScrDC, $hMemDC, $tSize, $pSize, $tSource, $pSource, $tBlend, $pBlend Global $GFC, $GFDC, $pDimensionIDs, $tDL Global $Pause $hGUI = GUICreate("", 0, 0, 0, 0, $WS_POPUP, BitOR($WS_EX_LAYERED, $WS_EX_TOOLWINDOW, $WS_EX_TOPMOST)) GUISetState() GifInit() ; move the window with animated GIF image ;~ AdlibEnable("FlyUfo", 20) While 1 ; If $i = the frame count then reset $i to 0 If $i = $GFC Then $i = 0 GifDrawFrame($i) ; 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 WEnd Func Quit() ;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) _GDIPlus_Shutdown() HotKeySet("{Esc}") HotKeySet("{Left}") HotKeySet("{Right}") HotKeySet("{Pause}") Exit EndFunc Func GifInit() _GDIPlus_Startup() ; Load your animated gif $hImage = _GDIPlus_ImageLoadFromFile($Gif) $ApW = _GDIPlus_ImageGetWidth($hImage) $ApH = _GDIPlus_ImageGetHeight($hImage) $hScrDC = _WinAPI_GetDC($hGUI) $hMemDC = _WinAPI_CreateCompatibleDC($hScrDC) $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) ; 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) $GFC = $GFC[3] EndFunc Func GifDrawFrame($i) ; 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) ; 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) $hOld = _WinAPI_SelectObject($hMemDC, $hBitmap) _WinAPI_UpdateLayeredWindow($hGUI, $hScrDC, 0, $pSize, $hMemDC, $pSource, 0, $pBlend, $ULW_ALPHA) EndFunc ; move the window with animated GIF image 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 Func Left() If WinActive($hGUI) Then If Not $Pause Then Return $i -= 1 If $i = -1 Then $i = $GFC - 1 GifDrawFrame($i) Else HotKeySet("{Left}") Send("{Left}") HotKeySet("{Left}", "Left") EndIf EndFunc Func Right() If WinActive($hGUI) Then If Not $Pause Then Return $i += 1 If $i = $GFC Then $i = 0 GifDrawFrame($i) Else HotKeySet("{Right}") Send("{Right}") HotKeySet("{Right}", "Right") EndIf EndFunc Func Pause() If WinActive($hGUI) Then $Pause = Not $Pause If Not $Pause Then Return ;~ WinSetTitle($hGUI, '', $Gif & " PAUSED") While $Pause Sleep(100) WEnd ;~ WinSetTitle($hGUI, '', $Gif) Else HotKeySet("{PAUSE}") Send("{PAUSE}") HotKeySet("{PAUSE}", "Pause") EndIf EndFunc Resources UDF ResourcesEx UDF AutoIt Forum Search Link to comment Share on other sites More sharing options...
BillLuvsU Posted July 31, 2008 Share Posted July 31, 2008 Ok, thankyou very much Zedna. Your example helps me understand this alot better. I know enough now to bend it to my will. [center][/center]Working on the next big thing.Currently Playing: Halo 4, League of LegendsXBL GT: iRememberYhslaw Link to comment Share on other sites More sharing options...
smashly Posted July 31, 2008 Author Share Posted July 31, 2008 Here is changed original script. You can Pause/unPause animation, in Pause mode you can navigate through frames by Left/Right Note: Moving of window is intentionally disabled in this example --> you can uncomment AdlibEnable("FlyUfo", 20) expandcollapse popup#include <GUIConstantsEx.au3> #include <WindowsConstants.au3> #include <GDIPlus.au3> #include <Misc.au3> #include <WinAPI.au3> HotKeySet("{Esc}", "Quit") HotKeySet("{Left}", "Left") HotKeySet("{Right}", "Right") HotKeySet("{Pause}", "Pause") Global $Gif = @ScriptDir & "\gif-Green-UFO.gif" Global $i = 0, $ApX, $ApY, $ApW, $ApH, $eX, $eY Global $hImage, $hBitmap, $hScrDC, $hMemDC, $tSize, $pSize, $tSource, $pSource, $tBlend, $pBlend Global $GFC, $GFDC, $pDimensionIDs, $tDL Global $Pause $hGUI = GUICreate("", 0, 0, 0, 0, $WS_POPUP, BitOR($WS_EX_LAYERED, $WS_EX_TOOLWINDOW, $WS_EX_TOPMOST)) GUISetState() GifInit() ; move the window with animated GIF image ;~ AdlibEnable("FlyUfo", 20) While 1 ; If $i = the frame count then reset $i to 0 If $i = $GFC Then $i = 0 GifDrawFrame($i) ; 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 WEnd Func Quit() ;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) _GDIPlus_Shutdown() HotKeySet("{Esc}") HotKeySet("{Left}") HotKeySet("{Right}") HotKeySet("{Pause}") Exit EndFunc Func GifInit() _GDIPlus_Startup() ; Load your animated gif $hImage = _GDIPlus_ImageLoadFromFile($Gif) $ApW = _GDIPlus_ImageGetWidth($hImage) $ApH = _GDIPlus_ImageGetHeight($hImage) $hScrDC = _WinAPI_GetDC($hGUI) $hMemDC = _WinAPI_CreateCompatibleDC($hScrDC) $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) ; 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) $GFC = $GFC[3] EndFunc Func GifDrawFrame($i) ; 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) ; 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) $hOld = _WinAPI_SelectObject($hMemDC, $hBitmap) _WinAPI_UpdateLayeredWindow($hGUI, $hScrDC, 0, $pSize, $hMemDC, $pSource, 0, $pBlend, $ULW_ALPHA) EndFunc ; move the window with animated GIF image 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 Func Left() If WinActive($hGUI) Then If Not $Pause Then Return $i -= 1 If $i = -1 Then $i = $GFC - 1 GifDrawFrame($i) Else HotKeySet("{Left}") Send("{Left}") HotKeySet("{Left}", "Left") EndIf EndFunc Func Right() If WinActive($hGUI) Then If Not $Pause Then Return $i += 1 If $i = $GFC Then $i = 0 GifDrawFrame($i) Else HotKeySet("{Right}") Send("{Right}") HotKeySet("{Right}", "Right") EndIf EndFunc Func Pause() If WinActive($hGUI) Then $Pause = Not $Pause If Not $Pause Then Return ;~ WinSetTitle($hGUI, '', $Gif & " PAUSED") While $Pause Sleep(100) WEnd ;~ WinSetTitle($hGUI, '', $Gif) Else HotKeySet("{PAUSE}") Send("{PAUSE}") HotKeySet("{PAUSE}", "Pause") EndIf EndFuncThank You.. saves me having to do it I was actually writing a simple interface to create/add/remove/extract frames to and from a gif, so I didn't really feel like writing another breakdown. You can actually use any format input images and it'll create a multi page gif. But saving with a selected transparency is little bamboozling, it's like gdi+ save image refuses to save an image without screwing with the color palete. I think I have to save the image into a stream, then set the pixels in the stream, then get a pointer to the stream and save the data from the stream to a file. urg, ms blows when it comes to ease of use in some functions! Bit more research needed for me to finalize it. Cheers Link to comment Share on other sites More sharing options...
Zedna Posted July 31, 2008 Share Posted July 31, 2008 Thank You.. saves me having to do it I was actually writing a simple interface to create/add/remove/extract frames to and from a gif, so I didn't really feel like writing another breakdown.You can actually use any format input images and it'll create a multi page gif.But saving with a selected transparency is little bamboozling, it's like gdi+ save image refuses to save an image without screwing with the color palete.I think I have to save the image into a stream, then set the pixels in the stream, then get a pointer to the stream and save the data from the stream to a file. urg, ms blows when it comes to ease of use in some functions! Bit more research needed for me to finalize it. CheersI like this your GDI+ GIF animation observation :-)But I have no experiences with images transparency at all. Resources UDF ResourcesEx UDF AutoIt Forum Search Link to comment Share on other sites More sharing options...
ProgAndy Posted July 31, 2008 Share Posted July 31, 2008 (edited) Greate Work, smashly and Zedna I added handling for the Properties FrameDelay and LoopCount expandcollapse popup#include <GUIConstantsEx.au3> #include <WindowsConstants.au3> #include <GDIPlus.au3> #include <Misc.au3> #include <WinAPI.au3> HotKeySet("{Esc}", "Quit") HotKeySet("{Left}", "Left") HotKeySet("{Right}", "Right") HotKeySet("{Pause}", "Pause") Global $Gif = @ScriptDir & "\gif-Green-UFO.gif" Global $i = 0, $ApX, $ApY, $ApW, $ApH, $eX, $eY Global $hImage, $hBitmap, $hScrDC, $hMemDC, $tSize, $pSize, $tSource, $pSource, $tBlend, $pBlend Global $GFC, $GFDC, $pDimensionIDs, $tDL Global $Pause Global $MadeLoops, $LoopCount Global $FrameDelays Global Const $tagPropertyItem = "long id; long length; int Type; ptr value" Global Const $PropertyTagFrameDelay = 0x5100 Global Const $PropertyTagLoopCount = 0x5101 Global Const $PropertyTagTypeByte = 1 Global Const $PropertyTagTypeASCII = 2 Global Const $PropertyTagTypeShort = 3 Global Const $PropertyTagTypeLong = 4 Global Const $PropertyTagTypeRational = 5 Global Const $PropertyTagTypeUndefined = 7 Global Const $PropertyTagTypeSLong = 9 Global Const $PropertyTagTypeSRational = 10 $hGUI = GUICreate("", 0, 0, 0, 0, $WS_POPUP, BitOR($WS_EX_LAYERED, $WS_EX_TOOLWINDOW, $WS_EX_TOPMOST)) GUISetState() GifInit() ; move the window with animated GIF image ;~ AdlibEnable("FlyUfo", 20) While 1 If $LoopCount = 0 Or ($LoopCount > $MadeLoops) Then ; If $i = the frame count then reset $i to 0 If $i = $GFC Then $i = 0 GifDrawFrame($i) If UBound($FrameDelays) > $i And $FrameDelays[$i] > 0 Then Sleep($FrameDelays[$i]) ; Sleep for Frame Delay :) Else Sleep(100) ConsoleWrite("Fallback, no time found :)" & @CRLF) EndIf $i += 1 Else Sleep(100) EndIf WEnd Func Quit() ;Tidy Up at end of each frame, otherwise memory use gets excessive in a short time. _GDIPlus_ImageDispose($hImage) _WinAPI_ReleaseDC(0, $hScrDC) _WinAPI_DeleteDC($hMemDC) _GDIPlus_Shutdown() HotKeySet("{Esc}") HotKeySet("{Left}") HotKeySet("{Right}") HotKeySet("{Pause}") Exit EndFunc ;==>Quit Func GifInit() _GDIPlus_Startup() ; Load your animated gif $hImage = _GDIPlus_ImageLoadFromFile($Gif) $ApW = _GDIPlus_ImageGetWidth($hImage) $ApH = _GDIPlus_ImageGetHeight($hImage) $hScrDC = _WinAPI_GetDC($hGUI) $hMemDC = _WinAPI_CreateCompatibleDC($hScrDC) $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) ; 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) $GFC = $GFC[3] $FrameDelays = _GetFrameDelays($hImage, $GFC) $LoopCount = _GetGifLoopCount($hImage) EndFunc ;==>GifInit Func GifDrawFrame($i) ; 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) ; 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) $hOld = _WinAPI_SelectObject($hMemDC, $hBitmap) _WinAPI_UpdateLayeredWindow($hGUI, $hScrDC, 0, $pSize, $hMemDC, $pSource, 0, $pBlend, $ULW_ALPHA) _WinAPI_SelectObject($hMemDC, $hOld) _WinAPI_DeleteObject($hBitmap) ; Needs to be deleted after each creation, not just in the end once :P EndFunc ;==>GifDrawFrame ; move the window with animated GIF image 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 Func Left() If WinActive($hGUI) Then If Not $Pause Then Return $i -= 1 If $i = -1 Then $i = $GFC - 1 GifDrawFrame($i) Else HotKeySet("{Left}") Send("{Left}") HotKeySet("{Left}", "Left") EndIf EndFunc ;==>Left Func Right() If WinActive($hGUI) Then If Not $Pause Then Return $i += 1 If $i = $GFC Then $i = 0 GifDrawFrame($i) Else HotKeySet("{Right}") Send("{Right}") HotKeySet("{Right}", "Right") EndIf EndFunc ;==>Right Func Pause() If WinActive($hGUI) Then $Pause = Not $Pause If Not $Pause Then Return ;~ WinSetTitle($hGUI, '', $Gif & " PAUSED") While $Pause Sleep(100) WEnd ;~ WinSetTitle($hGUI, '', $Gif) Else HotKeySet("{PAUSE}") Send("{PAUSE}") HotKeySet("{PAUSE}", "Pause") EndIf EndFunc ;==>Pause ; Author: Prog@ndy (converted from VB :) ) ; VB-Source: http://www.activevb.de/tipps/vb6tipps/tipp0675.html Func _GetFrameDelays(ByRef $hImage, $FrameCount) Local $lOutFrameDelay[$FrameCount] ;~ Dim lProp() As Byte ;~ Dim lPropCount As Long Local $lSize ;As Long ;~ Dim lPropSize As Long ;~ Dim tPropItem As PropertyItem Local $PropID = $PropertyTagFrameDelay If Not _CheckForProperty($hImage, $PropID) Then Return SetError(1, 0, 0) Local $PropertySize = DllCall($ghGDIPDll, "int", "GdipGetPropertyItemSize", "ptr", $hImage, "dword", $PropID, "uint*", 0) ;~ ' Datengröße vom EXIF-Tag ;~ ' "PropertyTagFrameDelay" ermitteln If $PropertySize[0] = 0 Then $tPropItem = DllStructCreate($tagPropertyItem & ";byte[" & $PropertySize[3] & "]"); Create Property-ItemStruct and save enough memory for its data Local $PropertyItem = DllCall($ghGDIPDll, "int", "GdipGetPropertyItem", "ptr", $hImage, "dword", $PropID, "dword", $PropertySize[3], "ptr", DllStructGetPtr($tPropItem)) If $PropertyItem[0] <> 0 Then Return SetError(1, 0, 0) $lSize = DllStructGetData($tPropItem, "length") ;~ ' PropertyTyp ermitteln Switch DllStructGetData($tPropItem, "Type") Case $PropertyTagTypeByte $lProp = DllStructCreate("byte[" & $lSize & "]", DllStructGetData($tPropItem, "value")) ;~ $lSize = "byte" ConsoleWrite("byte" & @CRLF) Case $PropertyTagTypeShort $lProp = DllStructCreate("short[" & Ceiling($lSize / 2) & "]", DllStructGetData($tPropItem, "value")) ;~ $lSize = "ushort" ConsoleWrite("short" & @CRLF) Case $PropertyTagTypeLong $lProp = DllStructCreate("long[" & Ceiling($lSize / 4) & "]", DllStructGetData($tPropItem, "value")) ;~ $lSize = "long" ConsoleWrite("long" & @CRLF) EndSwitch ;~ ' Pausenzeiten der einzelnen ;~ ' Bilder aus Bytearray kopieren For $lPropCount = 0 To $FrameCount - 1 $lOutFrameDelay[$lPropCount] = DllStructGetData($lProp, 1, $lPropCount + 1) * 10 Next EndIf ;~ _MemGlobalFree(DllStructGetData($tPropItem,"value")) ;~ _MemVirtualFree(DllStructGetData($tPropItem,"value"),$lSize,$MEM_RELEASE) Return $lOutFrameDelay EndFunc ;==>_GetFrameDelays ; Author: Prog@ndy (converted from VB :) ) ; VB-Source: http://www.activevb.de/tipps/vb6tipps/tipp0675.html ;~ '------------------------------------------------------ ;~ ' Funktion : GetGifLoopCount ;~ ' Beschreibung : Auslesen der Wiederholungen ;~ ' Übergabewert : lInBitmap = GDI+ Bitmapobjekt ;~ ' lOutLoopCount = Anzahl der Wiederholungen ;~ '------------------------------------------------------ Func _GetGifLoopCount(ByRef $hImage) Local $tPropItem Local $lProp Local $lSize ;~ ' ist der EXIF-Tag ;~ ' "PropertyTagLoopCount" vorhanden If _CheckForProperty($hImage, _ $PropertyTagLoopCount) = True Then ;~ ' Datengröße vom EXIF-Tag ;~ ' "PropertyTagLoopCount" ermitteln Local $PropertySize = DllCall($ghGDIPDll, "int", "GdipGetPropertyItemSize", "ptr", $hImage, "dword", $PropertyTagLoopCount, "uint*", 0) If $PropertySize[0] = 0 Then ;~ ' Daten auslesen $tPropItem = DllStructCreate($tagPropertyItem & ";byte[" & $PropertySize[3] & "]"); Create Property-ItemStruct and save enough memory for its data Local $PropertyItem = DllCall($ghGDIPDll, "int", "GdipGetPropertyItem", "ptr", $hImage, "dword", $PropertyTagLoopCount, "dword", $PropertySize[3], "ptr", DllStructGetPtr($tPropItem)) If $PropertyItem[0] <> 0 Then Return SetError(1, 0, 0) $lSize = DllStructGetData($tPropItem, "length") ;~ ' PropertyTyp ermitteln Switch DllStructGetData($tPropItem, "Type") Case $PropertyTagTypeByte $lProp = DllStructCreate("byte[" & $lSize & "]", DllStructGetData($tPropItem, "value")) ;~ $lSize = "byte" ConsoleWrite("byte" & @CRLF) Case $PropertyTagTypeShort $lProp = DllStructCreate("short[" & Ceiling($lSize / 2) & "]", DllStructGetData($tPropItem, "value")) ;~ $lSize = "ushort" ConsoleWrite("short" & @CRLF) Case $PropertyTagTypeLong $lProp = DllStructCreate("long[" & Ceiling($lSize / 4) & "]", DllStructGetData($tPropItem, "value")) ;~ $lSize = "long" ConsoleWrite("long" & @CRLF) EndSwitch Return DllStructGetData($lProp, 1, 1) EndIf Else ;~ ' wenn der EXIF-Tag ;~ ' "PropertyTagLoopCount" fehlt Return 0 EndIf EndFunc ;==>_GetGifLoopCount ; Author: Prog@ndy (converted from VB :) ) ; VB-Source: http://www.activevb.de/tipps/vb6tipps/tipp0675.html ;~ '------------------------------------------------------ ;~ ' Funktion : CheckLoopCount ;~ ' Beschreibung : Überprüft, ob der EXIF-Tag LoopCount ;~ ' vorhanden sind ;~ ' Übergabewert : lInBitmap = GDI+ Bitmapobjekt ;~ ' Rückgabewert : True = LoopCount vorhanden ;~ ' False = LoopCount nicht vorhanden ;~ '------------------------------------------------------ Func _CheckForProperty( _ ByRef $hImage, _ $PropertyID) Local $lPropItem Local $lPropList Local $bRet = False ;~ ' Anzahl der EXIF-Metatags ermitteln Local $PropertyCount = DllCall($ghGDIPDll, "int", "GdipGetPropertyCount", "ptr", $hImage, "long*", 0) If $PropertyCount[0] = 0 Then ;~ ' sind EXIF-Metatags vorhanden If ($PropertyCount[2] > 0) Then ;~ ' Array zur Aufnahme der ;~ ' EXIF-Metatags dimensionieren Local $lPropList = DllStructCreate("dword[" & $PropertyCount[2] & "]") ;~ ' Liste der EXIF-Metatags auslesen -> lPropList() Local $PropertyList = DllCall($ghGDIPDll, "int", "GdipGetPropertyIdList", "ptr", $hImage, "long", $PropertyCount[2], "ptr", DllStructGetPtr($lPropList)) If $PropertyList[0] = 0 Then ;~ ' Liste der EXIF-Metatags durchlaufen For $lPropItem = 1 To $PropertyCount[2] ;~ ' ist in der Liste der EXIF-Metatag ;~ ' PropertyID vorhanden If DllStructGetData($lPropList, $lPropItem) = $PropertyID Then ;~ ' wenn ja, dann Rückgabewert setzen und ;~ ' Schleife verlassen $bRet = True ExitLoop EndIf Next EndIf EndIf EndIf ;~ ' Rückgabewert ausgeben Return $bRet EndFunc ;==>_CheckForProperty //Edit BUGFIX from next post inlcuded. Edited July 31, 2008 by ProgAndy *GERMAN* [note: you are not allowed to remove author / modified info from my UDFs]My UDFs:[_SetImageBinaryToCtrl] [_TaskDialog] [AutoItObject] [Animated GIF (GDI+)] [ClipPut for Image] [FreeImage] [GDI32 UDFs] [GDIPlus Progressbar] [Hotkey-Selector] [Multiline Inputbox] [MySQL without ODBC] [RichEdit UDFs] [SpeechAPI Example] [WinHTTP]UDFs included in AutoIt: FTP_Ex (as FTPEx), _WinAPI_SetLayeredWindowAttributes Link to comment Share on other sites More sharing options...
Zedna Posted July 31, 2008 Share Posted July 31, 2008 (edited) Greate Work, smashly and Zedna I added handling for the Properties FrameDelay and LoopCount Thanks for correction of my memory leak and nice addition ProgAndy. I see just little \"bug\" in main loop: GifDrawFrame($i) should be placed BEFORE Sleep() and not AFTER While 1 If $LoopCount = 0 Or ($LoopCount > $MadeLoops) Then ; If $i = the frame count then reset $i to 0 If $i = $GFC Then $i = 0 GifDrawFrame($i) If UBound($FrameDelays) > $i And $FrameDelays[$i] > 0 Then Sleep($FrameDelays[$i]) ; Sleep for Frame Delay Else Sleep(100) ConsoleWrite(\"Fallback, no time found \" & @CRLF) EndIf $i += 1 Else Sleep(100) EndIf WEnd Edited July 31, 2008 by Zedna Resources UDF ResourcesEx UDF AutoIt Forum Search Link to comment Share on other sites More sharing options...
smashly Posted July 31, 2008 Author Share Posted July 31, 2008 Greate Work, smashly and Zedna I added handling for the Properties FrameDelay and LoopCount expandcollapse popup#include <GUIConstantsEx.au3> #include <WindowsConstants.au3> #include <GDIPlus.au3> #include <Misc.au3> #include <WinAPI.au3> HotKeySet("{Esc}", "Quit") HotKeySet("{Left}", "Left") HotKeySet("{Right}", "Right") HotKeySet("{Pause}", "Pause") Global $Gif = @ScriptDir & "\gif-Green-UFO.gif" Global $i = 0, $ApX, $ApY, $ApW, $ApH, $eX, $eY Global $hImage, $hBitmap, $hScrDC, $hMemDC, $tSize, $pSize, $tSource, $pSource, $tBlend, $pBlend Global $GFC, $GFDC, $pDimensionIDs, $tDL Global $Pause Global $MadeLoops, $LoopCount Global $FrameDelays Global Const $tagPropertyItem = "long id; long length; int Type; ptr value" Global Const $PropertyTagFrameDelay = 0x5100 Global Const $PropertyTagLoopCount = 0x5101 Global Const $PropertyTagTypeByte = 1 Global Const $PropertyTagTypeASCII = 2 Global Const $PropertyTagTypeShort = 3 Global Const $PropertyTagTypeLong = 4 Global Const $PropertyTagTypeRational = 5 Global Const $PropertyTagTypeUndefined = 7 Global Const $PropertyTagTypeSLong = 9 Global Const $PropertyTagTypeSRational = 10 $hGUI = GUICreate("", 0, 0, 0, 0, $WS_POPUP, BitOR($WS_EX_LAYERED, $WS_EX_TOOLWINDOW, $WS_EX_TOPMOST)) GUISetState() GifInit() ; move the window with animated GIF image ;~ AdlibEnable("FlyUfo", 20) While 1 If $LoopCount = 0 Or ($LoopCount > $MadeLoops) Then ; If $i = the frame count then reset $i to 0 If $i = $GFC Then $i = 0 If UBound($FrameDelays) > $i And $FrameDelays[$i] > 0 Then Sleep($FrameDelays[$i]) ; Sleep for Frame Delay :) Else Sleep(100) ConsoleWrite("Fallback, no time found :)" & @CRLF) EndIf GifDrawFrame($i) $i += 1 Else Sleep(100) EndIf WEnd Func Quit() ;Tidy Up at end of each frame, otherwise memory use gets excessive in a short time. _GDIPlus_ImageDispose($hImage) _WinAPI_ReleaseDC(0, $hScrDC) _WinAPI_DeleteDC($hMemDC) _GDIPlus_Shutdown() HotKeySet("{Esc}") HotKeySet("{Left}") HotKeySet("{Right}") HotKeySet("{Pause}") Exit EndFunc ;==>Quit Func GifInit() _GDIPlus_Startup() ; Load your animated gif $hImage = _GDIPlus_ImageLoadFromFile($Gif) $ApW = _GDIPlus_ImageGetWidth($hImage) $ApH = _GDIPlus_ImageGetHeight($hImage) $hScrDC = _WinAPI_GetDC($hGUI) $hMemDC = _WinAPI_CreateCompatibleDC($hScrDC) $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) ; 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) $GFC = $GFC[3] $FrameDelays = _GetFrameDelays($hImage, $GFC) $LoopCount = _GetGifLoopCount($hImage) EndFunc ;==>GifInit Func GifDrawFrame($i) ; 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) ; 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) $hOld = _WinAPI_SelectObject($hMemDC, $hBitmap) _WinAPI_UpdateLayeredWindow($hGUI, $hScrDC, 0, $pSize, $hMemDC, $pSource, 0, $pBlend, $ULW_ALPHA) _WinAPI_SelectObject($hMemDC, $hOld) _WinAPI_DeleteObject($hBitmap) ; Needs to be deleted after each creation, not just in the end once :P EndFunc ;==>GifDrawFrame ; move the window with animated GIF image 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 Func Left() If WinActive($hGUI) Then If Not $Pause Then Return $i -= 1 If $i = -1 Then $i = $GFC - 1 GifDrawFrame($i) Else HotKeySet("{Left}") Send("{Left}") HotKeySet("{Left}", "Left") EndIf EndFunc ;==>Left Func Right() If WinActive($hGUI) Then If Not $Pause Then Return $i += 1 If $i = $GFC Then $i = 0 GifDrawFrame($i) Else HotKeySet("{Right}") Send("{Right}") HotKeySet("{Right}", "Right") EndIf EndFunc ;==>Right Func Pause() If WinActive($hGUI) Then $Pause = Not $Pause If Not $Pause Then Return ;~ WinSetTitle($hGUI, '', $Gif & " PAUSED") While $Pause Sleep(100) WEnd ;~ WinSetTitle($hGUI, '', $Gif) Else HotKeySet("{PAUSE}") Send("{PAUSE}") HotKeySet("{PAUSE}", "Pause") EndIf EndFunc ;==>Pause ; Author: Prog@ndy (converted from VB :) ) ; VB-Source: http://www.activevb.de/tipps/vb6tipps/tipp0675.html Func _GetFrameDelays(ByRef $hImage, $FrameCount) Local $lOutFrameDelay[$FrameCount] ;~ Dim lProp() As Byte ;~ Dim lPropCount As Long Local $lSize ;As Long ;~ Dim lPropSize As Long ;~ Dim tPropItem As PropertyItem Local $PropID = $PropertyTagFrameDelay If Not _CheckForProperty($hImage, $PropID) Then Return SetError(1, 0, 0) Local $PropertySize = DllCall($ghGDIPDll, "int", "GdipGetPropertyItemSize", "ptr", $hImage, "dword", $PropID, "uint*", 0) ;~ ' Datengröße vom EXIF-Tag ;~ ' "PropertyTagFrameDelay" ermitteln If $PropertySize[0] = 0 Then $tPropItem = DllStructCreate($tagPropertyItem & ";byte[" & $PropertySize[3] & "]"); Create Property-ItemStruct and save enough memory for its data Local $PropertyItem = DllCall($ghGDIPDll, "int", "GdipGetPropertyItem", "ptr", $hImage, "dword", $PropID, "dword", $PropertySize[3], "ptr", DllStructGetPtr($tPropItem)) If $PropertyItem[0] <> 0 Then Return SetError(1, 0, 0) $lSize = DllStructGetData($tPropItem, "length") ;~ ' PropertyTyp ermitteln Switch DllStructGetData($tPropItem, "Type") Case $PropertyTagTypeByte $lProp = DllStructCreate("byte[" & $lSize & "]", DllStructGetData($tPropItem, "value")) ;~ $lSize = "byte" ConsoleWrite("byte" & @CRLF) Case $PropertyTagTypeShort $lProp = DllStructCreate("short[" & Ceiling($lSize / 2) & "]", DllStructGetData($tPropItem, "value")) ;~ $lSize = "ushort" ConsoleWrite("short" & @CRLF) Case $PropertyTagTypeLong $lProp = DllStructCreate("long[" & Ceiling($lSize / 4) & "]", DllStructGetData($tPropItem, "value")) ;~ $lSize = "long" ConsoleWrite("long" & @CRLF) EndSwitch ;~ ' Pausenzeiten der einzelnen ;~ ' Bilder aus Bytearray kopieren For $lPropCount = 0 To $FrameCount - 1 $lOutFrameDelay[$lPropCount] = DllStructGetData($lProp, 1, $lPropCount + 1) * 10 Next EndIf ;~ _MemGlobalFree(DllStructGetData($tPropItem,"value")) ;~ _MemVirtualFree(DllStructGetData($tPropItem,"value"),$lSize,$MEM_RELEASE) Return $lOutFrameDelay EndFunc ;==>_GetFrameDelays ; Author: Prog@ndy (converted from VB :) ) ; VB-Source: http://www.activevb.de/tipps/vb6tipps/tipp0675.html ;~ '------------------------------------------------------ ;~ ' Funktion : GetGifLoopCount ;~ ' Beschreibung : Auslesen der Wiederholungen ;~ ' Übergabewert : lInBitmap = GDI+ Bitmapobjekt ;~ ' lOutLoopCount = Anzahl der Wiederholungen ;~ '------------------------------------------------------ Func _GetGifLoopCount(ByRef $hImage) Local $tPropItem Local $lProp Local $lSize ;~ ' ist der EXIF-Tag ;~ ' "PropertyTagLoopCount" vorhanden If _CheckForProperty($hImage, _ $PropertyTagLoopCount) = True Then ;~ ' Datengröße vom EXIF-Tag ;~ ' "PropertyTagLoopCount" ermitteln Local $PropertySize = DllCall($ghGDIPDll, "int", "GdipGetPropertyItemSize", "ptr", $hImage, "dword", $PropertyTagLoopCount, "uint*", 0) If $PropertySize[0] = 0 Then ;~ ' Daten auslesen $tPropItem = DllStructCreate($tagPropertyItem & ";byte[" & $PropertySize[3] & "]"); Create Property-ItemStruct and save enough memory for its data Local $PropertyItem = DllCall($ghGDIPDll, "int", "GdipGetPropertyItem", "ptr", $hImage, "dword", $PropertyTagLoopCount, "dword", $PropertySize[3], "ptr", DllStructGetPtr($tPropItem)) If $PropertyItem[0] <> 0 Then Return SetError(1, 0, 0) $lSize = DllStructGetData($tPropItem, "length") ;~ ' PropertyTyp ermitteln Switch DllStructGetData($tPropItem, "Type") Case $PropertyTagTypeByte $lProp = DllStructCreate("byte[" & $lSize & "]", DllStructGetData($tPropItem, "value")) ;~ $lSize = "byte" ConsoleWrite("byte" & @CRLF) Case $PropertyTagTypeShort $lProp = DllStructCreate("short[" & Ceiling($lSize / 2) & "]", DllStructGetData($tPropItem, "value")) ;~ $lSize = "ushort" ConsoleWrite("short" & @CRLF) Case $PropertyTagTypeLong $lProp = DllStructCreate("long[" & Ceiling($lSize / 4) & "]", DllStructGetData($tPropItem, "value")) ;~ $lSize = "long" ConsoleWrite("long" & @CRLF) EndSwitch Return DllStructGetData($lProp, 1, 1) EndIf Else ;~ ' wenn der EXIF-Tag ;~ ' "PropertyTagLoopCount" fehlt Return 0 EndIf EndFunc ;==>_GetGifLoopCount ; Author: Prog@ndy (converted from VB :) ) ; VB-Source: http://www.activevb.de/tipps/vb6tipps/tipp0675.html ;~ '------------------------------------------------------ ;~ ' Funktion : CheckLoopCount ;~ ' Beschreibung : Überprüft, ob der EXIF-Tag LoopCount ;~ ' vorhanden sind ;~ ' Übergabewert : lInBitmap = GDI+ Bitmapobjekt ;~ ' Rückgabewert : True = LoopCount vorhanden ;~ ' False = LoopCount nicht vorhanden ;~ '------------------------------------------------------ Func _CheckForProperty( _ ByRef $hImage, _ $PropertyID) Local $lPropItem Local $lPropList Local $bRet = False ;~ ' Anzahl der EXIF-Metatags ermitteln Local $PropertyCount = DllCall($ghGDIPDll, "int", "GdipGetPropertyCount", "ptr", $hImage, "long*", 0) If $PropertyCount[0] = 0 Then ;~ ' sind EXIF-Metatags vorhanden If ($PropertyCount[2] > 0) Then ;~ ' Array zur Aufnahme der ;~ ' EXIF-Metatags dimensionieren Local $lPropList = DllStructCreate("dword[" & $PropertyCount[2] & "]") ;~ ' Liste der EXIF-Metatags auslesen -> lPropList() Local $PropertyList = DllCall($ghGDIPDll, "int", "GdipGetPropertyIdList", "ptr", $hImage, "long", $PropertyCount[2], "ptr", DllStructGetPtr($lPropList)) If $PropertyList[0] = 0 Then ;~ ' Liste der EXIF-Metatags durchlaufen For $lPropItem = 1 To $PropertyCount[2] ;~ ' ist in der Liste der EXIF-Metatag ;~ ' PropertyID vorhanden If DllStructGetData($lPropList, $lPropItem) = $PropertyID Then ;~ ' wenn ja, dann Rückgabewert setzen und ;~ ' Schleife verlassen $bRet = True ExitLoop EndIf Next EndIf EndIf EndIf ;~ ' Rückgabewert ausgeben Return $bRet EndFunc ;==>_CheckForPropertyNice work ProgAndy, I got lazy when I got to the frame time delay hence me doing the dirty hard set sleep. Now if we can work out why GraphicsDrawImage is chewing memory when used in a continuous loop then we could get rid of the update layered window for every frame. I tried a few things. Like setting GDI+ flush, delete graphics per cylce but _GDIPlus_GraphicsDrawImage() seems to just increase memory use every couple of cycles through the loop. Other ways of drawing the frames could be use api SendMessage to display the frames on a control which also works ok. Cheers Link to comment Share on other sites More sharing options...
ProgAndy Posted July 31, 2008 Share Posted July 31, 2008 OK, I tried it with _SetBitmapToCtrl from Zednas Resource UDf -> It works. Also, I used a Timer for drawing new frames -> No blocking of other Functions or slower drawing then . The time for the Timer is set each time to the new value, so this should be OK, too. expandcollapse popup#include <GUIConstantsEx.au3> #include <WindowsConstants.au3> #include <GDIPlus.au3> #include <Misc.au3> #include <WinAPI.au3> #include <Timers.au3> HotKeySet("{Esc}", "Quit") HotKeySet("{Left}", "Left") HotKeySet("{Right}", "Right") HotKeySet("{Pause}", "Pause") Global $Gif = @ScriptDir & "\gif-Green-UFO.gif" Global $i = 0, $ApX, $ApY, $ApW, $ApH, $eX, $eY Global $hImage, $hBitmap, $hScrDC, $hMemDC, $tSize, $pSize, $tSource, $pSource, $tBlend, $pBlend Global $GFC, $GFDC, $pDimensionIDs, $tDL Global $Pause Global $MadeLoops, $LoopCount Global $FrameDelays Global $GIF_TimerID = -1 Global Const $tagPropertyItem = "long id; long length; int Type; ptr value" Global Const $PropertyTagFrameDelay = 0x5100 Global Const $PropertyTagLoopCount = 0x5101 Global Const $PropertyTagTypeByte = 1 Global Const $PropertyTagTypeASCII = 2 Global Const $PropertyTagTypeShort = 3 Global Const $PropertyTagTypeLong = 4 Global Const $PropertyTagTypeRational = 5 Global Const $PropertyTagTypeUndefined = 7 Global Const $PropertyTagTypeSLong = 9 Global Const $PropertyTagTypeSRational = 10 ;~ $hGUI = GUICreate("", 0, 0, 0, 0, $WS_POPUP, BitOR($WS_EX_LAYERED, $WS_EX_TOOLWINDOW, $WS_EX_TOPMOST)) $hGUI = GUICreate("GIF Animation",300,300) GUICtrlCreateLabel("text behind GIF",5,15,100,25) Global $IMG_Ctrl= GUICtrlCreateLabel("",10,10,10,10) ; For Drawing :) GUICtrlSetBkColor(-1,$GUI_BKCOLOR_TRANSPARENT) ; Transparency's working :) GUISetState() GifInit() ; move the window with animated GIF image ;~ AdlibEnable("FlyUfo", 20) $GIF_TimerID = _Timer_SetTimer($hGUI, 100, "_Draw_Timer") ; Start Animation While 1 If GUIGetMsg() = -3 Then Quit() WEnd Func _Draw_Timer($hWnd, $Msg, $iIDTimer, $dwTime) If $LoopCount = 0 Or ($LoopCount > $MadeLoops) Then ; If $i = the frame count then reset $i to 0 If $GIF_TimerID = 0 Then $GIF_TimerID = -1 If $i = $GFC Then $i = 0 If UBound($FrameDelays) > $i And $FrameDelays[$i] > 0 Then _Timer_SetTimer($hWnd, $FrameDelays[$i], "_Draw_Timer", $iIDTimer) Else _Timer_SetTimer($hWnd, 100, "_Draw_Timer", $iIDTimer) ConsoleWrite("Fallback, no time found :)" & @CRLF) EndIf ;~ GifDrawFrame($i) GifDrawFrame_Ctrl($i) $i += 1 Else _Timer_KillTimer($hWnd, $iIDTimer) EndIf EndFunc ;==>_Draw_Timer Func Quit() _Timer_KillAllTimers($hGUI) ;Tidy Up at end of each frame, otherwise memory use gets excessive in a short time. _GDIPlus_ImageDispose($hImage) _GDIPlus_Shutdown() HotKeySet("{Esc}") HotKeySet("{Left}") HotKeySet("{Right}") HotKeySet("{Pause}") Exit EndFunc ;==>Quit Func GifInit() _GDIPlus_Startup() ; Load your animated gif $hImage = _GDIPlus_ImageLoadFromFile($Gif) If @error Then _WinAPI_FatalAppExit("Image " & $Gif & " not found!" & _GDIPlus_Shutdown()) $ApW = _GDIPlus_ImageGetWidth($hImage) $ApH = _GDIPlus_ImageGetHeight($hImage) GUICtrlSetPos($IMG_Ctrl,Default,Default,$ApW,$ApH) ;Set Size of the Control :D ; 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) $GFC = $GFC[3] $FrameDelays = _GetFrameDelays($hImage, $GFC) $LoopCount = _GetGifLoopCount($hImage) EndFunc ;==>GifInit Func GifDrawFrame_Ctrl($i) ; 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) ; 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) _SetBitmapToCtrl($IMG_Ctrl,$hBitmap) _WinAPI_DeleteObject($hBitmap) EndFunc ;==>GifDrawFrame ; internal helper function, out of reources UDf from Zedna Func _SetBitmapToCtrl($CtrlId, $hBitmap) Local Const $STM_SETIMAGE = 0x0172 Local Const $IMAGE_BITMAP = 0 Local Const $SS_BITMAP = 0xE Local Const $GWL_STYLE = -16 Local Const $SS_REALSIZEIMAGE = 0x800 Local $hWnd = GUICtrlGetHandle($CtrlId) If $hWnd = 0 Then Return SetError(1, 0, 0) ; set SS_BITMAP style to control Local $oldStyle = DllCall("user32.dll", "long", "GetWindowLong", "hwnd", $hWnd, "int", $GWL_STYLE) If @error Then Return SetError(2, 0, 0) DllCall("user32.dll", "long", "SetWindowLong", "hwnd", $hWnd, "int", $GWL_STYLE, "long", BitOR($oldStyle[0], $SS_BITMAP,$SS_REALSIZEIMAGE)) If @error Then Return SetError(3, 0, 0) Local $oldBmp = DllCall("user32.dll", "hwnd", "SendMessage", "hwnd", $hWnd, "int", $STM_SETIMAGE, "int", $IMAGE_BITMAP, "int", $hBitmap) If @error Then Return SetError(4, 0, 0) If $oldBmp[0] <> 0 Then _WinAPI_DeleteObject($oldBmp[0]) Return 1 EndFunc ; move the window with animated GIF image 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 Func Left() If WinActive($hGUI) Then If Not $Pause Then Return $i -= 1 If $i = -1 Then $i = $GFC - 1 ;~ GifDrawFrame($i) GifDrawFrame_Ctrl($i) Else HotKeySet("{Left}") Send("{Left}") HotKeySet("{Left}", "Left") EndIf EndFunc ;==>Left Func Right() If WinActive($hGUI) Then If Not $Pause Then Return $i += 1 If $i = $GFC Then $i = 0 ;~ GifDrawFrame($i) GifDrawFrame_Ctrl($i) Else HotKeySet("{Right}") Send("{Right}") HotKeySet("{Right}", "Right") EndIf EndFunc ;==>Right Func Pause() If WinActive($hGUI) Then $Pause = Not $Pause if $Pause Then _Timer_KillTimer($hGUI,$GIF_TimerID) Else $GIF_TimerID = _Timer_SetTimer($hGUI, 100, "_Draw_Timer") ; Start Animation EndIf Else HotKeySet("{PAUSE}") Send("{PAUSE}") HotKeySet("{PAUSE}", "Pause") EndIf EndFunc ;==>Pause ; Author: Prog@ndy (converted from VB :) ) ; VB-Source: http://www.activevb.de/tipps/vb6tipps/tipp0675.html Func _GetFrameDelays(ByRef $hImage, $FrameCount) Local $lOutFrameDelay[$FrameCount] ;~ Dim lProp() As Byte ;~ Dim lPropCount As Long Local $lSize ;As Long ;~ Dim lPropSize As Long ;~ Dim tPropItem As PropertyItem Local $PropID = $PropertyTagFrameDelay If Not _CheckForProperty($hImage, $PropID) Then Return SetError(1, 0, 0) Local $PropertySize = DllCall($ghGDIPDll, "int", "GdipGetPropertyItemSize", "ptr", $hImage, "dword", $PropID, "uint*", 0) ;~ ' Datengröße vom EXIF-Tag ;~ ' "PropertyTagFrameDelay" ermitteln If $PropertySize[0] = 0 Then $tPropItem = DllStructCreate($tagPropertyItem & ";byte[" & $PropertySize[3] & "]"); Create Property-ItemStruct and save enough memory for its data Local $PropertyItem = DllCall($ghGDIPDll, "int", "GdipGetPropertyItem", "ptr", $hImage, "dword", $PropID, "dword", $PropertySize[3], "ptr", DllStructGetPtr($tPropItem)) If $PropertyItem[0] <> 0 Then Return SetError(1, 0, 0) $lSize = DllStructGetData($tPropItem, "length") ;~ ' PropertyTyp ermitteln Switch DllStructGetData($tPropItem, "Type") Case $PropertyTagTypeByte $lProp = DllStructCreate("byte[" & $lSize & "]", DllStructGetData($tPropItem, "value")) ;~ $lSize = "byte" ConsoleWrite("byte" & @CRLF) Case $PropertyTagTypeShort $lProp = DllStructCreate("short[" & Ceiling($lSize / 2) & "]", DllStructGetData($tPropItem, "value")) ;~ $lSize = "ushort" ConsoleWrite("short" & @CRLF) Case $PropertyTagTypeLong $lProp = DllStructCreate("long[" & Ceiling($lSize / 4) & "]", DllStructGetData($tPropItem, "value")) ;~ $lSize = "long" ConsoleWrite("long" & @CRLF) EndSwitch ;~ ' Pausenzeiten der einzelnen ;~ ' Bilder aus Bytearray kopieren For $lPropCount = 0 To $FrameCount - 1 $lOutFrameDelay[$lPropCount] = DllStructGetData($lProp, 1, $lPropCount + 1) * 10 Next EndIf ;~ _MemGlobalFree(DllStructGetData($tPropItem,"value")) ;~ _MemVirtualFree(DllStructGetData($tPropItem,"value"),$lSize,$MEM_RELEASE) Return $lOutFrameDelay EndFunc ;==>_GetFrameDelays ; Author: Prog@ndy (converted from VB :) ) ; VB-Source: http://www.activevb.de/tipps/vb6tipps/tipp0675.html ;~ '------------------------------------------------------ ;~ ' Funktion : GetGifLoopCount ;~ ' Beschreibung : Auslesen der Wiederholungen ;~ ' Übergabewert : lInBitmap = GDI+ Bitmapobjekt ;~ ' lOutLoopCount = Anzahl der Wiederholungen ;~ '------------------------------------------------------ Func _GetGifLoopCount(ByRef $hImage) Local $tPropItem Local $lProp Local $lSize ;~ ' ist der EXIF-Tag ;~ ' "PropertyTagLoopCount" vorhanden If _CheckForProperty($hImage, _ $PropertyTagLoopCount) = True Then ;~ ' Datengröße vom EXIF-Tag ;~ ' "PropertyTagLoopCount" ermitteln Local $PropertySize = DllCall($ghGDIPDll, "int", "GdipGetPropertyItemSize", "ptr", $hImage, "dword", $PropertyTagLoopCount, "uint*", 0) If $PropertySize[0] = 0 Then ;~ ' Daten auslesen $tPropItem = DllStructCreate($tagPropertyItem & ";byte[" & $PropertySize[3] & "]"); Create Property-ItemStruct and save enough memory for its data Local $PropertyItem = DllCall($ghGDIPDll, "int", "GdipGetPropertyItem", "ptr", $hImage, "dword", $PropertyTagLoopCount, "dword", $PropertySize[3], "ptr", DllStructGetPtr($tPropItem)) If $PropertyItem[0] <> 0 Then Return SetError(1, 0, 0) $lSize = DllStructGetData($tPropItem, "length") ;~ ' PropertyTyp ermitteln Switch DllStructGetData($tPropItem, "Type") Case $PropertyTagTypeByte $lProp = DllStructCreate("byte[" & $lSize & "]", DllStructGetData($tPropItem, "value")) ;~ $lSize = "byte" ConsoleWrite("byte" & @CRLF) Case $PropertyTagTypeShort $lProp = DllStructCreate("short[" & Ceiling($lSize / 2) & "]", DllStructGetData($tPropItem, "value")) ;~ $lSize = "ushort" ConsoleWrite("short" & @CRLF) Case $PropertyTagTypeLong $lProp = DllStructCreate("long[" & Ceiling($lSize / 4) & "]", DllStructGetData($tPropItem, "value")) ;~ $lSize = "long" ConsoleWrite("long" & @CRLF) EndSwitch Return DllStructGetData($lProp, 1, 1) EndIf Else ;~ ' wenn der EXIF-Tag ;~ ' "PropertyTagLoopCount" fehlt Return 0 EndIf EndFunc ;==>_GetGifLoopCount ; Author: Prog@ndy (converted from VB :) ) ; VB-Source: http://www.activevb.de/tipps/vb6tipps/tipp0675.html ;~ '------------------------------------------------------ ;~ ' Funktion : CheckLoopCount ;~ ' Beschreibung : Überprüft, ob der EXIF-Tag LoopCount ;~ ' vorhanden sind ;~ ' Übergabewert : lInBitmap = GDI+ Bitmapobjekt ;~ ' Rückgabewert : True = LoopCount vorhanden ;~ ' False = LoopCount nicht vorhanden ;~ '------------------------------------------------------ Func _CheckForProperty( _ ByRef $hImage, _ $PropertyID) Local $lPropItem Local $lPropList Local $bRet = False ;~ ' Anzahl der EXIF-Metatags ermitteln Local $PropertyCount = DllCall($ghGDIPDll, "int", "GdipGetPropertyCount", "ptr", $hImage, "long*", 0) If $PropertyCount[0] = 0 Then ;~ ' sind EXIF-Metatags vorhanden If ($PropertyCount[2] > 0) Then ;~ ' Array zur Aufnahme der ;~ ' EXIF-Metatags dimensionieren Local $lPropList = DllStructCreate("dword[" & $PropertyCount[2] & "]") ;~ ' Liste der EXIF-Metatags auslesen -> lPropList() Local $PropertyList = DllCall($ghGDIPDll, "int", "GdipGetPropertyIdList", "ptr", $hImage, "long", $PropertyCount[2], "ptr", DllStructGetPtr($lPropList)) If $PropertyList[0] = 0 Then ;~ ' Liste der EXIF-Metatags durchlaufen For $lPropItem = 1 To $PropertyCount[2] ;~ ' ist in der Liste der EXIF-Metatag ;~ ' PropertyID vorhanden If DllStructGetData($lPropList, $lPropItem) = $PropertyID Then ;~ ' wenn ja, dann Rückgabewert setzen und ;~ ' Schleife verlassen $bRet = True ExitLoop EndIf Next EndIf EndIf EndIf ;~ ' Rückgabewert ausgeben Return $bRet EndFunc ;==>_CheckForProperty *GERMAN* [note: you are not allowed to remove author / modified info from my UDFs]My UDFs:[_SetImageBinaryToCtrl] [_TaskDialog] [AutoItObject] [Animated GIF (GDI+)] [ClipPut for Image] [FreeImage] [GDI32 UDFs] [GDIPlus Progressbar] [Hotkey-Selector] [Multiline Inputbox] [MySQL without ODBC] [RichEdit UDFs] [SpeechAPI Example] [WinHTTP]UDFs included in AutoIt: FTP_Ex (as FTPEx), _WinAPI_SetLayeredWindowAttributes Link to comment Share on other sites More sharing options...
Zedna Posted July 31, 2008 Share Posted July 31, 2008 OK, I tried it with _SetBitmapToCtrl from Zednas Resource UDf -> It works. Also, I used a Timer for drawing new frames -> No blocking of other Functions or slower drawing then . The time for the Timer is set each time to the new value, so this should be OK, too.It's awesome!Just look at my previous last post - your little bug is not still corrected. Resources UDF ResourcesEx UDF AutoIt Forum Search Link to comment Share on other sites More sharing options...
ProgAndy Posted July 31, 2008 Share Posted July 31, 2008 In the one with timers, this bug doesn't exist And the other will be corrected in a minute *GERMAN* [note: you are not allowed to remove author / modified info from my UDFs]My UDFs:[_SetImageBinaryToCtrl] [_TaskDialog] [AutoItObject] [Animated GIF (GDI+)] [ClipPut for Image] [FreeImage] [GDI32 UDFs] [GDIPlus Progressbar] [Hotkey-Selector] [Multiline Inputbox] [MySQL without ODBC] [RichEdit UDFs] [SpeechAPI Example] [WinHTTP]UDFs included in AutoIt: FTP_Ex (as FTPEx), _WinAPI_SetLayeredWindowAttributes Link to comment Share on other sites More sharing options...
smashly Posted July 31, 2008 Author Share Posted July 31, 2008 (edited) So with a bit more work we'll hopefully soon get to see animated gif support in Zedna's Resources.au3 YaY Edit: Also forgot to mention with minimal code change you can use the same routine to display multi page tif files Edited July 31, 2008 by smashly Link to comment Share on other sites More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now