nomainwin
MaxFrames = 1000
global MaxFrames
WindowWidth = 800
WindowHeight = 600
open "Animated GIFs" for graphics_nsb as #w
#w "trapclose quit"
hw = hwnd(#w)
calldll #user32, "GetDC", hw as ulong, hdc as ulong
do
filedialog "Select an animated GIF", "*.gif", GIFfile$
if GIFfile$ <> "" then call AnimatedGIF hdc, GIFfile$, 10
loop until GIFfile$ = ""
close #w
end
sub quit h$
close #h$
end
end sub
' specify a duration in seconds or zero to play the animation once
sub AnimatedGIF hDC, filename$, duration
open "gdiplus.dll" for dll as #gdiplus
struct tSI, GdiplusVersion as long, DebugEventCallback as ulong, _
SuppressBackgroundThread as long, SuppressExternalCodecs as long
tSI.GdiplusVersion.struct = 1
struct GDIP, l as struct
calldll #gdiplus, "GdiplusStartup", GDIP as struct, tSI as struct, 0 as long, r as void
struct graphics, p as ulong
calldll #gdiplus, "GdipCreateFromHDC", hDC as ulong, graphics as struct, r as void
calldll #gdiplus, "GdipSetSmoothingMode", graphics.p.struct as long, 2 as long, r as void
l = len(filename$) + 1
wide$ = space$(l * 2) + chr$(0)
calldll #kernel32, "MultiByteToWideChar", 0 as long, 0 as long, _
filename$ as ptr, -1 as long, wide$ as ptr, l as long, r as long
struct image, p as ulong
calldll #gdiplus, "GdipLoadImageFromFile", wide$ as ptr, image as struct, r as void
if image.p.struct = 0 then notice "Couldn't open ";filename$ : exit sub
struct dims, n as long
calldll #gdiplus, "GdipImageGetFrameDimensionsCount", image.p.struct as ulong, _
dims as struct, r as void
if dims.n.struct > MaxFrames then notice "Too many frames: increase MaxFrames" : exit sub
struct dimIDs(MaxFrames), a as long, b as long, c as long, d as long
calldll #gdiplus, "GdipImageGetFrameDimensionsList", image.p.struct as ulong, _
dimIDs(0) as struct, dims.n.struct as long, r as void
struct frames, n as long
calldll #gdiplus, "GdipImageGetFrameCount", image.p.struct as ulong, _
dimIDs(0) as struct, frames as struct, r as void
if frames.n.struct > MaxFrames then notice "Too many frames: increase MaxFrames" : exit sub
PropertyTagFrameDelay = hexdec("5100")
struct psize, n as long
calldll #gdiplus, "GdipGetPropertyItemSize", image.p.struct as ulong, _
PropertyTagFrameDelay as long, psize as struct, r as void
if (psize.n.struct / 4) > MaxFrames then notice "Too many frames: increase MaxFrames" : exit sub
struct PropItem(MaxFrames), delay as long
calldll #gdiplus, "GdipGetPropertyItem", image.p.struct as ulong, _
PropertyTagFrameDelay as long, psize.n.struct as long, _
PropItem(0) as struct, r as void
struct xs, n as long
struct ys, n as long
calldll #gdiplus, "GdipGetImageWidth", image.p.struct as ulong, xs as struct, r as void
calldll #gdiplus, "GdipGetImageHeight", image.p.struct as ulong, ys as struct, r as void
xsize = xs.n.struct
ysize = ys.n.struct
if xsize > WindowWidth then ysize *= WindowWidth / xsize : xsize = WindowWidth
IF ysize > WindowHeight then xsize *= WindowHeight / ysize : ysize = WindowHeight
xpos = (WindowWidth - xsize) / 2
ypos = (WindowHeight - ysize) / 2
endtime = time$("ms") + duration * 1000
do
for frame = 0 to frames.n.struct - 1
calldll #gdiplus, "GdipImageSelectActiveFrame", image.p.struct as ulong, _
dimIDs(0) as struct, frame as long, r as void
#w "cls"
calldll #gdiplus, "GdipDrawImageRectI", graphics.p.struct as ulong, _
image.p.struct as ulong, xpos as long, ypos as long, _
xsize as long, ysize as long, r as void
delay = PropItem(frame+4).delay.struct
if delay = 0 then delay = 8
timer delay * 10, [animate]
wait
[animate]
timer 0
scan
next frame
loop until time$("ms") >= endtime
calldll #gdiplus, "GdipDisposeImage", image.p.struct as ulong, r as void
calldll #gdiplus, "GdipDeleteGraphics", graphics.p.struct as ulong, r as void
calldll #gdiplus, "GdiplusShutdown", GDIP.l.struct as ulong, r as void
close #gdiplus
end sub