[Solved] Need help converting autoit code, (Gdip Gif Animation)

Get help with using AutoHotkey and its commands and hotkeys
User avatar
Spawnova
Posts: 339
Joined: 08 Jul 2015, 00:12
Contact:

[Solved] Need help converting autoit code, (Gdip Gif Animation)

22 Feb 2016, 17:29

There is a script on the Autoit forums for looping through the frames of a .gif file using Gdip and I can't understand how to convert it to ahk
script - https://www.autoitscript.com/forum/topi ... using-gdi/

Here is what I've done so far but even the first dllcall doesn't seem to return correctly
commented code is the autoit stuff

Code: Select all

;$hImage = _GDIPlus_ImageLoadFromFile($Gif) ;seems to be loading bitmap
hImage := Gdip_CreateBitmapFromFile("imagetest.gif")
;$tDL = DllStructCreate($tagGUID) ;not sure the exact setup but I believe its varsetcapacity

;$pDimensionIDs = DllStructGetPtr($tDL) ;not sure

;$GFDC = DllCall($ghGDIPDll, "int", "GdipImageGetFrameDimensionsCount", "ptr", $hImage, "int*", 0)
GFDC := DllCall("gdiplus\GdipImageGetFrameDimensionsCount", "ptr", hImage, "int*", 0) ;returns 0
/* untested past this point since GdipImageGetFrameDimensionsCount returns 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])
DllCall("gdiplus\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)
 DllCall("gdiplus\GdipImageGetFrameDimensionsList", "ptr", hImage, "ptr", pDimensionIDs, "int", GFDC)
GFC := DllCall("gdiplus\GdipImageGetFrameCount", "ptr", hImage, "ptr", pDimensionIDs, "int*", 0) ;returns 7
 */
 
 ;Selecting frame
 ;DllCall($ghGDIPDll, "int", "GdipImageSelectActiveFrame", "ptr", $hImage, "ptr", $pDimensionIDs, "int", $i)
 INDEX := 5 ;example
  DllCall("gdiplus\GdipImageSelectActiveFrame", "ptr", hImage, "ptr", pDimensionIDs, "int*", INDEX)
I've tried just about everything I can think of but I'm stumped at this point, hopefully someone more knowledgeable can help me out.
Last edited by Spawnova on 24 Feb 2016, 18:29, edited 1 time in total.
tic
Posts: 92
Joined: 03 Nov 2014, 03:10

Re: Need help converting autoit code, (Gdip Gif Animation)

24 Feb 2016, 01:23

Here is an example of displaying an animated gif inside a standard window:

Code: Select all


#SingleInstance Force
;#include Gdip.ahk

pToken := Gdip_Startup()
OnExit, Exit

Gui, 1: Add, Picture, x10 y10 w80 h80 0xE hwndhwndGif1
Gui, 1: Add, Button, x+10 yp+0 w80 h80 gPlayPause hwndhwndPlayPause, Play 
Gui, 1: Show, AutoSize, Animated gif

gif1 := new Gif("mario_running.gif", hwndGif1)
return

;######################################################

PlayPause:
isPlaying := gif1.isPlaying
GuiControl,, % hwndPlayPause, % (isPlaying) ? "Play" : "Pause"
if (!isPlaying) {
	gif1.Play()
} else {
	gif1.Pause()
}
return

;######################################################

Exit:
Gdip_ShutDown(pToken)
ExitApp
return

;######################################################

class Gif
{	
	__New(file, hwnd)
	{
		this.file := file
		this.hwnd := hwnd
		this.pBitmap := Gdip_CreateBitmapFromFile(this.file)
		Gdip_GetImageDimensions(this.pBitmap, width, height)
		this.width := width, this.height := height
		this.isPlaying := false
		
		DllCall("Gdiplus\GdipImageGetFrameDimensionsCount", "ptr", this.pBitmap, "uptr*", frameDimensions)
		this.SetCapacity("dimensionIDs", 32)
		DllCall("Gdiplus\GdipImageGetFrameDimensionsList", "ptr", this.pBitmap, "uptr", this.GetAddress("dimensionIDs"), "int", frameDimensions)
		DllCall("Gdiplus\GdipImageGetFrameCount", "ptr", this.pBitmap, "uptr", this.GetAddress("dimensionIDs"), "int*", count)
		this.frameCount := count
		this.frameCurrent := -1
	}
	
	Play(interval=200)
	{
		this.isPlaying := true
		fn := this._Play.Bind(this)
		this._fn := fn
		SetTimer, % fn, % interval
	}
	
	Pause()
	{
		this.isPlaying := false
		fn := this._fn
		SetTimer, % fn, Delete
	}
	
	_Play()
	{
		this.frameCurrent := (this.frameCurrent = this.frameCount-1) ? 0 : this.frameCurrent + 1
		DllCall("Gdiplus\GdipImageSelectActiveFrame", "ptr", this.pBitmap, "uptr", this.GetAddress("dimensionIDs"), "int", this.frameCurrent)
		hBitmap := Gdip_CreateHBITMAPFromBitmap(this.pBitmap)
		SetImage(this.hwnd, hBitmap)
		DeleteObject(hBitmap)
	}
	
	__Delete()
	{
		Gdip_DisposeImage(this.pBitmap)
		Object.Delete("dimensionIDs")
	}
}

Download the gif from here
User avatar
Spawnova
Posts: 339
Joined: 08 Jul 2015, 00:12
Contact:

Re: Need help converting autoit code, (Gdip Gif Animation)

24 Feb 2016, 18:25

This is exactly what I was looking for! This will open up so many more options, I'm going to start working on stuff right away. =D

Thanks for the quick help Tic, It's extremely appreciated. =)
tmplinshi
Posts: 1540
Joined: 01 Oct 2013, 14:57

Re: [Solved] Need help converting autoit code, (Gdip Gif Animation)

08 Oct 2016, 01:05

Here is a modified version which supports retrieving the frames delay.

Code: Select all

#SingleInstance Force
;#include Gdip.ahk

pToken := Gdip_Startup()
OnExit, Exit

Gui, 1: Add, Picture, x10 y10 w80 h80 0xE hwndhwndGif1
Gui, 1: Add, Button, x+10 yp+0 w80 h80 gPlayPause hwndhwndPlayPause, Play 
Gui, 1: Show, AutoSize, Animated gif

gif1 := new Gif("mario_running.gif", hwndGif1)
return

;######################################################

PlayPause:
isPlaying := gif1.isPlaying
GuiControl,, % hwndPlayPause, % (isPlaying) ? "Play" : "Pause"
if (!isPlaying) {
	gif1.Play()
} else {
	gif1.Pause()
}
return

;######################################################

Exit:
Gdip_ShutDown(pToken)
ExitApp
return

;######################################################

class Gif
{	
	__New(file, hwnd)
	{
		this.file := file
		this.hwnd := hwnd
		this.pBitmap := Gdip_CreateBitmapFromFile(this.file)
		Gdip_GetImageDimensions(this.pBitmap, width, height)
		this.width := width, this.height := height
		this.isPlaying := false
		
		DllCall("Gdiplus\GdipImageGetFrameDimensionsCount", "ptr", this.pBitmap, "uptr*", frameDimensions)
		this.SetCapacity("dimensionIDs", 32)
		DllCall("Gdiplus\GdipImageGetFrameDimensionsList", "ptr", this.pBitmap, "uptr", this.GetAddress("dimensionIDs"), "int", frameDimensions)
		DllCall("Gdiplus\GdipImageGetFrameCount", "ptr", this.pBitmap, "uptr", this.GetAddress("dimensionIDs"), "int*", count)
		this.frameCount := count
		this.frameCurrent := -1
		this.frameDelay := this.GetFrameDelay(this.pBitmap)
	}

	; Return a zero-based array, containing the frames delay (in milliseconds)
	GetFrameDelay(pImage) {
		static PropertyTagFrameDelay := 0x5100

		DllCall("Gdiplus\GdipGetPropertyItemSize", "Ptr", pImage, "UInt", PropertyTagFrameDelay, "UInt*", ItemSize)
		VarSetCapacity(Item, ItemSize, 0)
		DllCall("Gdiplus\GdipGetPropertyItem"    , "Ptr", pImage, "UInt", PropertyTagFrameDelay, "UInt", ItemSize, "Ptr", &Item)

		PropLen := NumGet(Item, 4, "UInt")
		PropVal := NumGet(Item, 8 + A_PtrSize, "UPtr")

		outArray := []
		Loop, % PropLen//4 {
			if !n := NumGet(PropVal+0, (A_Index-1)*4, "UInt")
				n := 10
			outArray[A_Index-1] := n * 10
		}
		return outArray
	}
	
	Play()
	{
		this.isPlaying := true
		fn := this._Play.Bind(this)
		this._fn := fn
		SetTimer, % fn, -1
	}
	
	Pause()
	{
		this.isPlaying := false
		fn := this._fn
		SetTimer, % fn, Delete
	}
	
	_Play()
	{
		this.frameCurrent := (this.frameCurrent = this.frameCount-1) ? 0 : this.frameCurrent + 1
		DllCall("Gdiplus\GdipImageSelectActiveFrame", "ptr", this.pBitmap, "uptr", this.GetAddress("dimensionIDs"), "int", this.frameCurrent)
		hBitmap := Gdip_CreateHBITMAPFromBitmap(this.pBitmap)
		SetImage(this.hwnd, hBitmap)
		DeleteObject(hBitmap)

		fn := this._fn
		SetTimer, % fn, % -1 * this.frameDelay[this.frameCurrent]
	}
	
	__Delete()
	{
		Gdip_DisposeImage(this.pBitmap)
		Object.Delete("dimensionIDs")
	}
}

Return to “Ask For Help”

Who is online

Users browsing this forum: Albireo, pn4265 and 245 guests