Module: Get raw frame delays from gif
Posted: Thu Feb 23, 2017 10:48 pm
In case Fred doesn't change the ImageFrameDelay() return values, here's something you can use to get the real ones:
[edit] Only 6 hours old and it's already obsolete, as Fred is changing the PB command to return the same. I don't mind though, I figured it would happen and I really only wrote this for fun. It should find life after retirement as a resource for those looking to learn how to traverse a gif file and find other information which may not be supplied natively. So it's going out to stud, let's say.
And a small test program (note the array has one element to begin with)
[edit] Only 6 hours old and it's already obsolete, as Fred is changing the PB command to return the same. I don't mind though, I figured it would happen and I really only wrote this for fun. It should find life after retirement as a resource for those looking to learn how to traverse a gif file and find other information which may not be supplied natively. So it's going out to stud, let's say.
Code: Select all
; Project: Return Raw Frame Delays from Gif (in milliseconds)
; Author: Lloyd Gallant (netmaestro)
; Birth Date: February 23, 2017
; Obsolete Date: February 23, 2017
; License: Free to modify, sell, share, reverse-engineer or obliterate with a drone
DeclareModule FrameDelays
Structure GIF_HEADER_AND_LOGICAL_SCREEN_DESCRIPTOR
HeaderBytes.a[6]
Width.u
Height.u
PackedByte.a
BackgroundColorIndex.a
PixelAspectRatio.a
EndStructure
Structure GRAPHICS_CONTROL_EXTENSION
Introducer.a
Label.a
BlockSize.a
PackedByte.a
DelayTime.u
TransparentColorIndex.a
BlockTerminator.a
EndStructure
Structure IMAGE_DESCRIPTOR
Separator.a
ImageLeft.w
ImageTop.w
ImageWidth.w
ImageHeight.w
PackedByte.a
EndStructure
#GIFHEADER89a = $613938464947
#GIFHEADER87a = $613738464947
#GIFHEADERMASK = $FFFFFFFFFFFF
#COLORTABLE_EXISTS = $80
Declare IsLocalColorTable(*buffer)
Declare IsGlobalColorTable(*buffer)
Declare ProcessGifData(*buffer, buffersize, Array FrameDelays(1))
Declare FrameDelaysFromBuffer(*buffer, size, Array FrameDelays(1))
Declare FrameDelaysFromFile(filename$, Array FrameDelays(1))
EndDeclareModule
Module FrameDelays
Procedure IsLocalColorTable(*buffer)
Protected *ptr.IMAGE_DESCRIPTOR = *buffer
If *ptr\PackedByte & #COLORTABLE_EXISTS
ProcedureReturn 2 << (*ptr\PackedByte & 7) *3
Else
ProcedureReturn 0
EndIf
EndProcedure
Procedure IsGlobalColorTable(*gifdata)
Protected *ptr.GIF_HEADER_AND_LOGICAL_SCREEN_DESCRIPTOR = *gifdata
If *ptr\PackedByte & #COLORTABLE_EXISTS
ProcedureReturn 2 << (*ptr\PackedByte & 7) * 3
Else
ProcedureReturn 0
EndIf
EndProcedure
Procedure ProcessGifData(*buffer, buffersize, Array FrameDelays(1))
Protected *readptr, *gcereader.GRAPHICS_CONTROL_EXTENSION
Protected *idreader.IMAGE_DESCRIPTOR
Protected.i index, bytes_colortable, extension_label
Protected.i morebytes, result, nextblock, FrameCount=0
Protected.u delaytime
If PeekQ(*buffer) & #GIFHEADERMASK <> #GIFHEADER89a And PeekQ(*buffer) & #GIFHEADERMASK <> #GIFHEADER87a
ProcedureReturn 0
EndIf
*readptr = *buffer + 13
bytes_colortable = IsGlobalColorTable(*buffer)
If bytes_colortable
*readptr + bytes_colortable
EndIf
Repeat
Select PeekA(*readptr)
Case $21
extension_label = PeekA(*readptr + 1)
Select extension_label
Case $F9
*gcereader.GRAPHICS_CONTROL_EXTENSION = *readptr
delaytime.u = *gcereader\DelayTime * 10
FrameDelays(ArraySize(FrameDelays())-1) = delaytime
ReDim FrameDelays(ArraySize(FrameDelays())+1)
*readptr + SizeOf(GRAPHICS_CONTROL_EXTENSION)
Case $FE, $01
*readptr+2
While PeekA(*readptr)
*readptr+1
If *readptr >= *buffer+buffersize
Break
EndIf
Wend
*readptr+1
Case $FF
*readptr + 2
morebytes = PeekA(*readptr)
*readptr + morebytes + 1
morebytes = PeekA(*readptr)
repeats = PeekU(*readptr+2)
*readptr + morebytes+1
morebytes = PeekA(*readptr)
While morebytes
*readptr+morebytes+1
morebytes = PeekA(*readptr)
Wend
*readptr+1
Default
Break
EndSelect
Case $3B
Break
Case $2C
FrameCount+1
*idreader.IMAGE_DESCRIPTOR = *readptr
*readptr + SizeOf(IMAGE_DESCRIPTOR)
result = IsLocalColorTable(*idreader)
If result
bytes_colortable = result
*readptr + bytes_colortable
EndIf
*readptr+1
nextblock = PeekA(*readptr)
While nextblock
*readptr + 1
*readptr+nextblock
totalcodebytes+nextblock
nextblock = PeekA(*readptr)
Wend
*readptr+1
Default
Break
EndSelect
ForEver
ReDim FrameDelays(FrameCount-1)
EndProcedure
Procedure.i FrameDelaysFromFile(file$, Array FrameDelays(1))
Protected.i buffersize, *buffer, result
If ReadFile(0, file$)
buffersize = Lof(0)
*buffer = AllocateMemory(buffersize)
ReadData(0, *buffer, buffersize)
CloseFile(0)
result = ProcessGifData(*buffer, buffersize, FrameDelays())
FreeMemory(*buffer)
ProcedureReturn result
Else
ProcedureReturn 0
EndIf
EndProcedure
Procedure.i FrameDelaysFromBuffer(*buffer, buffersize, Array FrameDelays(1))
ProcedureReturn ProcessGifData(*buffer, buffersize, FrameDelays())
EndProcedure
EndModule
Code: Select all
UseModule FrameDelays
Dim FrameDelays.i(1)
file$ = #PB_Compiler_Home + "Examples\Sources\Data\PureBasicLogo.gif"
FrameDelaysFromFile(file$, FrameDelays())
For i=1 To ArraySize(FrameDelays())
Debug Str(i)+" "+Str(framedelays(i))
Next