May 08, 2024, 12:04:02 PM

News:

Own IWBasic 2.x ? -----> Get your free upgrade to 3.x now.........


Mini GIF player

Started by sapero, April 09, 2009, 09:22:53 AM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

sapero

April 09, 2009, 09:22:53 AM Last Edit: April 09, 2009, 11:03:51 AM by sapero
This is a mini player for gif animations. It uses gdiplus to display frame by frame, and a timer for switching between frames.
On start, it downloads a image from the internet and 'plays' it. You can also load local image from the menu.
$include "windowssdk.inc"
$include "shlwapi.inc"
$include "gdiplus.inc"
autodefine "OFF"

type GIFDATA
' image
GpImage  image
' animation frame delays
pointer  delays ' PropertyItem *
BOOL     fTimerActive
int      nFrameCount
int      nCurrentFrame
endtype

INT_PTR g_gdiptoken
WINDOW d1
OpenWindow d1,0,0,295,230,@CAPTION|@MINBOX|@MAXBOX|@SIZE|@NOAUTODRAW,0,"GDI+ GIF Example",&handler
waituntil d1.hwnd = 0

sub handler
pointer temp
pointer pData = GetProp(d1.hwnd, "GIFDATA")
IStream stream

select @MESSAGE
case @IDCREATE
CENTERWINDOW d1
temp = new(GdiplusStartupInput, 1)
*<GdiplusStartupInput>temp.GdiplusVersion = 1
GdiplusStartup(&g_gdiptoken, temp, 0)
delete temp
pData = new(GIFDATA, 1)
SetProp(d1.hwnd, "GIFDATA", pData)

BEGINMENU d1
MENUTITLE "File"
MENUITEM "Open",0,100
ENDMENU

' download example image
if (URLOpenBlockingStream(0, "http://www.thegraphicgroove.com/oddBits/Butterfly2.gif", &stream, 0, 0) = 0)
gdiLoadImage(*pData, stream)
stream->Release()
endif

case @IDCLOSEWINDOW
CloseWindow d1


case @IDDESTROY
settype pData, GIFDATA
if (*pData.image) then GdipDisposeImage(*pData.image)
if (*pData.delays) then delete *pData.delays
delete pData
RemoveProp(d1.hwnd, "GIFDATA")
GdiplusShutdown(g_gdiptoken)

case @IDPAINT
if (*pData.image)
OnPaint(*pData.image)
endif

case @IDMENUPICK
if (@MENUNUM = 100)
temp = new(char, MAX_PATH)
*<STRING>temp = FILEREQUEST("Open GIF", d1, TRUE, "GIF Files|*.gif||", "gif", OFN_EXPLORER)
if (*<char>temp <> 0)
if (SHCreateStreamOnFile(temp, STGM_READ, &stream) = S_OK)
gdiLoadImage(*pData, stream)
stream->Release()
endif
endif
delete temp
endif

case @IDTIMER
if (@WPARAM = 1000)
' stop the timer
StopTimer d1, 1000
' next frame
*pData.nCurrentFrame++
if (*pData.nCurrentFrame >= *pData.nFrameCount) then *pData.nCurrentFrame = 0
' restart the timer
StartTimer d1, *pData.*<PropertyItem>delays.*<int>value[*pData.nCurrentFrame] * 10, 1000
' change animation frame
GdipImageSelectActiveFrame(*pData.image, FrameDimensionTime, *pData.nCurrentFrame)

OnPaint(*pData.image)
SetCaption d1, using("Frame # of #", *pData.nCurrentFrame+1, *pData.nFrameCount)
endif
endselect
endsub


sub gdiLoadImage(GIFDATA pData, IStream stream)

GpImage image
if (GdipLoadImageFromStream(stream, &image) = 0)

' stop animation
if (pData.fTimerActive)
StopTimer d1, 1000
pData.fTimerActive = FALSE
endif

' switch images
if (pData.image) then GdipDisposeImage(pData.image)
pData.image = image
pData.nCurrentFrame = 1

' grow client area if needed
int imgwidth, imgheight
GdipGetImageWidth(pData.image, &imgwidth)
GdipGetImageHeight(pData.image, &imgheight)
WINRECT rc
GetClientRect(d1.hwnd, &rc)
rc.right = __max(rc.right, imgwidth)
rc.bottom = __max(rc.bottom, imgheight)
AdjustWindowRect(&rc, GetWindowLong(d1.hwnd, GWL_STYLE), GetMenu(d1.hwnd))
SetWindowPos(d1.hwnd, 0, 0, 0, rc.right-rc.left, rc.bottom-rc.top, SWP_NOZORDER|SWP_NOMOVE)
CenterWindow d1 ' optional

' restart animation
if (TestForAnimatedGIF(pData))
StartTimer d1, pData.*<PropertyItem>delays.*<int>value[0] * 10, 1000
pData.fTimerActive = TRUE
endif

' invalidate the client area
InvalidateRect(d1.hwnd, NULL, TRUE)
OnPaint(pData.image)
endif
endsub


sub OnPaint(GpImage image)
GpGraphics graphics
HDC dc = GetHDC(d1)
if (GdipCreateFromHDC(dc, &graphics) = 0)
GdipDrawImageI(graphics, image, 0, 0)
GdipDeleteGraphics(graphics)
endif
ReleaseHDC(d1, dc)
endsub


sub TestForAnimatedGIF(GIFDATA pData),BOOL

pData.nFrameCount = 1
UINT count
if ((GdipImageGetFrameDimensionsCount(pData.image, &count) = 0) and count)

pointer pDimensionIDs = new(GUID, count)
if (pDimensionIDs)

' Get the list of frame dimensions from the Image object.
GdipImageGetFrameDimensionsList(pData.image, pDimensionIDs, count)

' Get the number of frames in the first dimension.
if ((GdipImageGetFrameCount(pData.image, pDimensionIDs, &pData.nFrameCount) = 0) and (pData.nFrameCount > 1))

' Assume that the image has a property item of type PropertyItemEquipMake.
' Get the size of that property item.
int nSize
GdipGetPropertyItemSize(pData.image, PropertyTagFrameDelay, &nSize)

if (pData.delays) then delete pData.delays
' Allocate a buffer to receive the property item.
pData.delays = new(byte, nSize)
if (pData.delays)
GdipGetPropertyItem(pData.image, PropertyTagFrameDelay, nSize, pData.delays)
else
pData.nFrameCount = 1
endif
endif
delete pDimensionIDs
endif
endif
return pData.nFrameCount > 1
endsub

Barney

Very useful. Thanks for sharing.  :)

Barney