It is currently Fri May 24, 2013 11:44 pm

All times are UTC + 1 hour




Post new topic Reply to topic  [ 53 posts ]  Go to page Previous  1, 2, 3, 4  Next
Author Message
 Post subject: Re: UPDATED: Load Animated GIF frames
PostPosted: Thu Mar 15, 2012 7:15 pm 
Offline
Enthusiast
Enthusiast
User avatar

Joined: Tue Jan 31, 2006 9:43 am
Posts: 323
Location: France
Here is a version with some improvements :

- No more APIs (multi-platform)
- Corrects colors artefacts (transparency based on index in palette and not on resulting color)
- Full alphachannel support
- Unicode compliant
- Respects interframe delay

Code:
; Original PB code by "hagibaba" (Purebasic.fr forums) based on "loadgif.c" for ImageShop32 by John Findlay
; Gif Anim support by localmotion34 (Purebasic.fr forums)
; Updated & Extended by Dean Williams - resplace.net
; APIs free, alpha channel support and bug fixes by Niffo (Purebasic.fr forums)

; Please help development and report any problems or improvements/bug fixes you may have on
; if we all work together we can have some really nice GIF support in PureBasic!
; http://www.purebasic.fr/english/viewtopic.php?f=12&t=27575

EnableExplicit

;{ - Structures

CompilerIf Defined(BITMAPINFOHEADER, #PB_Structure)
CompilerElse
   Structure BITMAPINFOHEADER
      biSize.l
      biWidth.l
      biHeight.l
      biPlanes.w
      biBitCount.w
      biCompression.l
      biSizeImage.l
      biXPelsPerMeter.l
      biYPelsPerMeter.l
      biClrUsed.l
      biClrImportant.l
   EndStructure
   
   #BI_RGB = 0
   
   Structure RGBQUAD
      rgbBlue.a
      rgbGreen.a
      rgbRed.a
      rgbReserved.a
   EndStructure
CompilerEndIf
 
Structure GIF_Frame
   Image.l
   DelayTime.w
EndStructure
 
Structure GIFHEADER ;Header
   ghSig.b[6] ;Signature & Version
   ghWidth.w ;Logical Screen Width
   ghHeight.w ;Logical Screen Height
   ghPkFields.b ;Global Color Table Flag
   ghBkColIndex.b ;Background Color Index
   ghAspRatio.b ;Pixel Aspect Ratio
EndStructure

Structure GIFIMAGE ;Image Descriptor
   imSep.b ;Image Separator
   imLeft.w ;Image Left Position
   imTop.w ;Image Top Position
   imWidth.w ;Image Width
   imHeight.w ;Image Height
   impkFields.b ;Local Color Table Flag
EndStructure

Structure GIFCLASS ;This is instead of using globals
   *lpBytes.Byte ;Pointer to next byte in block
   Pass.l ;First pass for interlaced images in OutLineGIF()
   Line.l ;Offset for addressing the bits in OutLineGIF()
   lpBits.l ;Scanline for bits
   pitch.l ;Bytes are rounded up for image lines
   CurrCodeSize.l ;The current code size
   BitsLeft.l ;Used in NextCodeGIF()
   BytesLeft.l ;Used in NextCodeGIF()
   CurrByte.l ;Current byte
   bUseGlobalColMap.b ;Is the color table global
   GlobColRes.l ;Color Resolution, bits '6' '5' '4'
   bImInterLace.b ;Is the image interlaced
   ImgColRes.l ;Color Resolution
EndStructure
   
;}

Procedure GIF_OutLine(lpPixels.l,LineLen.l,height.l,*cl.GIFCLASS)
   ;Outputs the pixel color index data to the DIB
   ;lpPixels -> Memory block that holds the color index value
   ;LineLen -> Length of the line of pixels
   ;Height -> im\imHeight
   ;Gif images are 2, 16 or 256 colors, poking the values into memory
   ;requires a different method for each case. If gif is interlaced,
   ;that is dealt with here.
 
   Protected ib.l,pixel.l,byte.l,BitCnt.l,CntBk.l,ColRes.l,Bits.l
 
   Bits=*cl\lpBits-(*cl\Line * *cl\pitch) ;Pointer to bits
 
   If *cl\bUseGlobalColMap
     ColRes=*cl\GlobColRes
   Else
     ColRes=*cl\ImgColRes
   EndIf
 
   Select ColRes
   
     Case 1
       byte=0
       For pixel=0 To LineLen-1 Step 8
         ib=0
         CntBk=7
         For BitCnt=0 To 8-1
           If PeekB(lpPixels+BitCnt+pixel)
             ib=ib | (1 << CntBk)
           EndIf
           CntBk-1
         Next
         PokeB(Bits+byte,ib)
         byte+1
       Next
     
     Case 4
       byte=0
       For pixel=0 To LineLen-1 Step 2
         ib=((PeekB(lpPixels+pixel) & 255) << 4)
         ib | (PeekB(lpPixels+pixel+1) & 255)
         PokeB(Bits+byte,ib)
         byte+1
       Next
     
     Case 8
       For pixel=0 To LineLen-1
         ib=PeekB(lpPixels+pixel) & 255
         PokeB(Bits+pixel,ib)
       Next
     
   EndSelect
 
   If *cl\bImInterLace ;Set Line for different passes when Interlaced
   
     Select *cl\Pass
     
       Case 0 ;Pass 1
         If *cl\Line<height-8
           *cl\Line+8
         Else
           *cl\Line=4 : *cl\Pass+1 ;Set Line for second pass
         EndIf
       
       Case 1 ;Pass 2
         If *cl\Line<height-8
           *cl\Line+8
         Else
           *cl\Line=2 : *cl\Pass+1 ;Set Line for third pass
         EndIf
       
       Case 2 ;Pass 3
         If *cl\Line<height-4
           *cl\Line+4
         Else
           *cl\Line=1 : *cl\Pass+1 ;Set Line for fourth pass
         EndIf
       
       Case 3 ;Pass 4
         If *cl\Line<height-2
           *cl\Line+2
         EndIf
       
     EndSelect
   
   Else ;When not Interlaced increment Line
   
     *cl\Line+1
   
   EndIf
 
EndProcedure

Procedure.l GIF_NextCode(file.l,Array CharBuff.b(1),Array CodeMask.l(1),*cl.GIFCLASS)
   ;Reads the next code from the data stream
   ;Returns the LZW CODE or ERROR
 
   Protected count.l,Char.l,ret.l
 
   If *cl\BitsLeft=0 ;Any bits left in byte?
   
     If *cl\BytesLeft<=0 ;If not get another block
     
       *cl\lpBytes=@CharBuff(0) ;Set byte pointer
       *cl\BytesLeft=ReadByte(file) & 255
     
       If *cl\BytesLeft<0
         ProcedureReturn *cl\BytesLeft ;Return if error
       ElseIf *cl\BytesLeft
         For count=0 To *cl\BytesLeft-1
           Char=ReadByte(file) & 255
           If Char<0 : ProcedureReturn Char : EndIf
           CharBuff(count)=Char ;Fill the char buffer with the new block
         Next
       EndIf
     
     EndIf
   
     *cl\CurrByte=*cl\lpBytes\b & 255 ;Get a byte
     *cl\lpBytes+1 ;Increment index pointer
     *cl\BitsLeft=8 ;Set bits left in the byte
     *cl\BytesLeft-1 ;Decrement the bytes left counter
   
   EndIf
 
   ;Shift off any previously used bits
   ret=*cl\CurrByte >> (8-*cl\BitsLeft)
 
   While *cl\CurrCodeSize>*cl\BitsLeft
   
     If *cl\BytesLeft<=0
     
       ;Out of bytes in current block
       *cl\lpBytes=@CharBuff(0) ;Set byte pointer
       *cl\BytesLeft=ReadByte(file) & 255
     
       If *cl\BytesLeft<0
         ProcedureReturn *cl\BytesLeft ;Return if error
       ElseIf *cl\BytesLeft
         For count=0 To *cl\BytesLeft-1
           Char=ReadByte(file) & 255
           If Char<0 : ProcedureReturn Char : EndIf
           CharBuff(count)=Char ;Fill the char buffer with the current block
         Next
       EndIf
     
     EndIf
   
     *cl\CurrByte=*cl\lpBytes\b & 255 ;Get a byte
     *cl\lpBytes+1 ;Increment index pointer
     ret | (*cl\CurrByte << *cl\BitsLeft) ;Add remaining bits to return
     *cl\BitsLeft+8 ;Set bit counter
     *cl\BytesLeft-1 ;Decrement bytesleft counter
   
   Wend
 
   *cl\BitsLeft-*cl\CurrCodeSize ;Subtract the code size from bitsleft
   ret & CodeMask(*cl\CurrCodeSize) ;Mask off the right number of bits
   ProcedureReturn ret
 
EndProcedure

Procedure GIF_CreateDIImage(Image.l, *dib.BITMAPINFOHEADER, TransColIndex.w)
   Define *Bits = *dib+*dib\biSize+(*dib\biClrUsed*4)
   Define.l Image = CreateImage(#PB_Any, *dib\biWidth, *dib\biHeight, 32)
   Define.l X, Y, RGBA, Col
   Define *Pal = *dib + *dib\biSize
   Define.a ColInd, Alpha
   Define.l dibPitch = *dib\biSizeImage/*dib\biHeight

   StartDrawing(ImageOutput(Image))
   DrawingMode(#PB_2DDrawing_AllChannels)

;   Define *BufAddr = DrawingBuffer()
;   Define.l BufPitch = DrawingBufferPitch()
   For Y = 0 To *dib\biHeight - 1
      For X = 0 To *dib\biWidth - 1
         
         Select *dib\biBitCount
            Case 8
               ColInd = PeekA(*Bits + Y*dibPitch+X)
            Case 4
               ;If X % 2
               ;   ColInd = PeekA(*Bits + Y*dibPitch+X) & $F
               ;Else
               ;   ColInd = PeekA(*Bits + Y*dibPitch+X) >> 4
               ;EndIf
               ColInd = PeekA(*Bits + Y*dibPitch+X/2) >> (4*(1-X%2)) & $F
         EndSelect         

         If ColInd = TransColIndex : Alpha = 0 : Else : Alpha = 255 : EndIf
         Col = PeekL(*Pal+ColInd*4)

         ; Plot
         RGBA = RGBA(Blue(Col), Green(Col), Red(Col), Alpha)
         Plot(X, *dib\biHeight-1-Y, RGBA)

;          ; Direct Buffer Write (not faster !?)
;          If DrawingBufferPixelFormat() & #PB_PixelFormat_32Bits_RGB
;             RGBA = RGBA(Blue(Col), Green(Col), Red(Col), Alpha)
;          ElseIf DrawingBufferPixelFormat() & #PB_PixelFormat_32Bits_BGR
;             RGBA = RGBA(Red(Col), Green(Col), Blue(Col), Alpha)
;          EndIf
;          If DrawingBufferPixelFormat() & #PB_PixelFormat_ReversedY
;             PokeL(*BufAddr + (Y*BufPitch+X*4), RGBA)
;          Else
;             PokeL(*BufAddr + ((*dib\biHeight-1-Y)*BufPitch+X*4), RGBA)
;          EndIf
         
      Next X
   Next Y

   StopDrawing()

   ProcedureReturn Image

EndProcedure

Procedure.l GIF_LoadFrames(filename.s,Array GIF_Frames.GIF_Frame(1))
   ;From "loadgif.c" for ImageShop32 by John Findlay
   ;Loads LZW Graphics Interchange Format files
   ;Uses NextCodeGIF() and OutLineGIF()
 
   Protected Dim stack.b(4096) ;Stack for storing pixels
   Protected Dim suffix.b(4096) ;Suffix table, max number of LZW codes
   Protected Dim prefix.l(4096) ;Prefix linked list (these are longs)
   Protected Dim CharBuff.b(279) ;Current block
   Protected Dim GlobalCols.l(256) ;Global colors of gif
   Protected Dim localCols.l(256) ;Local image colors of gif
   Protected Dim CodeMask.l(16) ;Masks for LZW compression algorithm
   Protected gh.GIFHEADER
   Protected im.GIFIMAGE
   Protected cl.GIFCLASS
   Protected bi.BITMAPINFOHEADER
   Protected *pal.RGBQUAD
   Protected *lpSP.Byte ;Pointer to stack
   Protected *lpBuffPtr.Byte ;Pointer to buffer
   Protected bGlobColsSorted.b ;Sort Flag  bit '3' (this is unused)
   Protected file.l,sig.s,PkFields.l,bGlobColTable.b,GlobColBytes.l
   Protected GlobColors.l,count.l,Red.l,Green.l,Blue.l
   Protected width.l,height.l,impkFields.l,bImColsSorted.b
   Protected bImColTable.b,ImgColBytes.l,LZWCodeSize.l,TopSlot.l
   Protected ClearCode.l,ImgColors.l,EndingCode.l,NewCodes.l,Slot.l
   Protected lpBUFF.l,TempOldCode.l,OldCode.l,BufCnt.l,bitcount.l
   Protected ncolors.l,Len.l,hDIB.l,cc.l,code.l
   Protected *dib.BITMAPINFOHEADER
 
   CodeMask( 0)=$0000 : CodeMask( 1)=$0001
   CodeMask( 2)=$0003 : CodeMask( 3)=$0007
   CodeMask( 4)=$000F : CodeMask( 5)=$001F
   CodeMask( 6)=$003F : CodeMask( 7)=$007F
   CodeMask( 8)=$00FF : CodeMask( 9)=$01FF
   CodeMask(10)=$03FF : CodeMask(11)=$07FF
   CodeMask(12)=$0FFF : CodeMask(13)=$1FFF
   CodeMask(14)=$3FFF : CodeMask(15)=$7FFF
 
   ;Open the file
   file=ReadFile(#PB_Any,filename)
   If file=0
     MessageRequester("GIF Load Error!" , "Could not open the GIF image file for reading.")
     ProcedureReturn #False
   EndIf
 
   ;Read the file header and logical screen descriptor
   ReadData(file,gh,SizeOf(gh))
 
   sig=PeekS(@gh\ghSig,6,#PB_Ascii) ;Get the header version string
   If sig<>"GIF89a" And sig<>"GIF87a"
     CloseFile(file)
     MessageRequester("GIF Load Error!" , "File was not a valid GIF image file")
     ProcedureReturn #False ;NOT_VALID
   EndIf
 
   Define.l realwidth=gh\ghWidth
   Define.l realheight=gh\ghHeight
 
   ;Store gh\ghPkFields for bit manipulation
   PkFields=gh\ghPkFields & 255
 
   ;Global Color Table Flag bit '7'
   bGlobColTable=(PkFields & (1 << 7)) >> 7
 
   If bGlobColTable
     cl\bUseGlobalColMap=#True
   
     GlobColBytes=3*(1 << ((PkFields & $07)+1)) ;Table size in bytes
     GlobColors=GlobColBytes/3 ;Number of colors
   
     ;Some gif encoders do not follow the gif spec very well,
     ;so make cl\GlobColRes from GlobColors.
     ;Also gif's are used on different platforms, which do
     ;have different bits per pixel. i.e. 32 colors is 5 bits/pixel.
     If GlobColors<=2
       cl\GlobColRes=1
     ElseIf GlobColors<=16
       cl\GlobColRes=4
     Else
       cl\GlobColRes=8
     EndIf
   
     For count=0 To GlobColors-1 ;Get the global screen colors
       Red=ReadByte(file) & 255
       Green=ReadByte(file) & 255
       Blue=ReadByte(file) & 255
       GlobalCols(count)=RGB(Red,Green,Blue)
     Next
   EndIf

   Define.w TransColorIndex = -1
   count=0
   While count<>$2C ;Search for im\imSep
     count=ReadByte(file) & 255
     If count = $F9
       ReadByte(file)
       Define.b tflag = ReadByte(file) & 1
       Define.w delaytime = ReadWord(file)
       Define.a transparent = ReadByte(file)
       If tflag : TransColorIndex = transparent : EndIf
     EndIf
   Wend
   FileSeek(file,Loc(file)-1) ;Seek to im\imSep
 
   ReadData(file,im,SizeOf(im)) ;Read the image descriptor
 
   ;Store im\imPkFields for bit manipulation
   impkFields=im\impkFields & 255
 
   ;Is the image interlaced
   cl\bImInterLace=(impkFields & (1 << 6)) >> 6
 
   ;Is the local color table sorted
   bImColsSorted=(impkFields & (1 << 5)) >> 5
 
   ;Is there a local color table
   bImColTable=(impkFields & (1 << 7)) >> 7
 
   If bImColTable
     cl\bUseGlobalColMap=#False
   
     ImgColBytes=3*(1 << ((impkFields & $07)+1)) ;Table size in bytes
     ImgColors=ImgColBytes/3 ;Number of colors
   
     If ImgColors<=2 ;Make sure image bit depth is 1, 4 or 8
       cl\ImgColRes=1
     ElseIf ImgColors<=16
       cl\ImgColRes=4
     Else
       cl\ImgColRes=8
     EndIf
   
     For count=0 To ImgColors-1 ;Get the local image colors
       Red=ReadByte(file) & 255
       Green=ReadByte(file) & 255
       Blue=ReadByte(file) & 255
       localCols(count)=RGB(Red,Green,Blue)
     Next
     ;transcolor=LocalCols(TByte)
   Else ;No local color table
     If cl\bUseGlobalColMap=#False ;No global color table
       CloseFile(file)
       MessageRequester("GIF Load Error!" , "The GIF image does not contain a valid color table.")
       ProcedureReturn #False ;NO_COLORTABLE
     EndIf
   EndIf
 
   width=im\imWidth & $FFFF ;Image width
   height=im\imHeight & $FFFF ;Image height
 
   ;Get the first byte of the new block of image data.
   ;Should be the bit size
   LZWCodeSize=ReadByte(file) & 255
 
   ;Bit size is normally the same as the color resolution.
   ;i.e. 8 for 256 colors
   If LZWCodeSize<2 Or LZWCodeSize>8
     CloseFile(file)
     MessageRequester("GIF Load Error!" , "LZW code size is not valid!")
     ProcedureReturn #False ;BAD_CODE_SIZE
   EndIf
 
   ;Initialise the variables for the decoder for reading a new image.
   cl\CurrCodeSize=LZWCodeSize+1
   TopSlot=1 << cl\CurrCodeSize ;Highest code for current size
   ClearCode=1 << LZWCodeSize ;Value for a clear code
   EndingCode=ClearCode+1 ;Value for an ending code
   NewCodes=ClearCode+2 ;First available code
   Slot=NewCodes ;Last read code
   cl\BitsLeft=0
   cl\BytesLeft=0
 
   ;Just in case...
   TempOldCode=0 : OldCode=0
 
   ;Allocate space for the decode buffer
   lpBUFF=AllocateMemory(width+8) ;+8 just in case
 
   ;Set up the stack pointer, decode buffer pointer and line counter
   *lpSP=@stack(0)
   *lpBuffPtr=lpBUFF
   BufCnt=width ;Count for pixel line length
 
   ;Start creating the DIB
   If cl\bUseGlobalColMap ;Global color table
     bitcount=cl\GlobColRes
   Else ;Local color table
     bitcount=cl\ImgColRes
   EndIf
 
   bi\biSize=SizeOf(bi)
   bi\biWidth=width
   bi\biHeight=height
   bi\biPlanes=1
   bi\biBitCount=bitcount ;BitCount will be 1, 4 or 8
   bi\biCompression=#BI_RGB
   bi\biSizeImage=0
   bi\biXPelsPerMeter=0
   bi\biYPelsPerMeter=0
   If cl\bUseGlobalColMap ;Global color table
     bi\biClrUsed=GlobColors
   Else ;Local color table
     bi\biClrUsed=ImgColors
   EndIf
   bi\biClrImportant=0
 
   ;With the BITMAPINFO format headers, the size of the palette is
   ;in biClrUsed, whereas in the BITMAPCORE - style headers, it is
   ;dependent on the Bits per pixel (2 to the power of bitsperpixel).
   If bi\biClrUsed<>0
     ncolors=bi\biClrUsed
   Else ;We don't have an optimal palette
     ncolors=1 << bi\biBitCount
   EndIf
 
   cl\pitch=(((bitcount*width)+31) >> 5) << 2 ;Bytes per line
   Len=bi\biSize+(ncolors*4)+(cl\pitch*height) ;Size of DIB
 
   bi\biSizeImage=cl\pitch*height ;Fill in biSizeImage
 
   ;Allocate memory block to store our DIB
   hDIB=AllocateMemory(Len)
   If hDIB=0
     FreeMemory(lpBUFF)
     ;CloseFile(file)
     MessageRequester("GIF Load Error!" , "Memory allocation failed!")
     ProcedureReturn #False ;NO_DIB
   EndIf
 
   ;Fill first part of DIB with the BITMAPINFOHEADER
   CopyMemory(bi,hDIB,SizeOf(bi))
 
   ;Set the colors in the DIB (or masks for the new DIB formats)
   *pal=hDIB+SizeOf(bi)
   If cl\bUseGlobalColMap
     For count=0 To bi\biClrUsed-1
       *pal\rgbBlue=Blue(GlobalCols(count))
       *pal\rgbGreen=Green(GlobalCols(count))
       *pal\rgbRed=Red(GlobalCols(count))
       *pal+4
     Next
   Else
     For count=0 To bi\biClrUsed-1
       *pal\rgbBlue=Blue(localCols(count))
       *pal\rgbGreen=Green(localCols(count))
       *pal\rgbRed=Red(localCols(count))
       *pal+4
     Next
   EndIf
 
   cl\Line=0 ;Set address offset for OutLineGIF()
   cl\Pass=0 ;For interlaced images in OutLineGIF()
 
   ;Image data bits of DIB
   cl\lpBits=hDIB+bi\biSize+(ncolors*4)+(cl\pitch*(height-1))
 
   ;This is the main loop. For each code we get we pass through the
   ;linked list of prefix codes, pushing the corresponding "character"
   ;for each code onto the stack. When the list reaches a single
   ;"character" we push that on the stack too, and then start
   ;unstacking each character for output in the correct order.
   ;Special handling is included for the clear code, and the whole
   ;thing ends when we get an ending code.
   While cc<>EndingCode
   
     cc=GIF_NextCode(file,CharBuff(),CodeMask(),cl)
   
     If cc<0 ;If a file error, return without completing the decode
       FreeMemory(lpBUFF)
       ;CloseFile(file)
       MessageRequester("GIF Load Error!" , "LZW code size is not valid!")
       ProcedureReturn #False ;FILE_ERROR
     EndIf
   
     ;If the code is a clear code, re-initialise all necessary items.
     If cc=ClearCode
     
       cl\CurrCodeSize=LZWCodeSize+1
       Slot=NewCodes
       TopSlot=1 << cl\CurrCodeSize
     
       ;Continue reading codes until we get a non-clear code
       ;(another unlikely, but possible case...)
       While cc=ClearCode
         cc=GIF_NextCode(file,CharBuff(),CodeMask(),cl)
       Wend
     
       ;If we get an ending code immediately after a clear code
       ;(yet another unlikely case), then break out of the loop.
       If cc=EndingCode
         Break ;end loop
       EndIf
     
       ;Finally, if the code is beyond the range of already set codes,
       ;(This one had better not happen, I have no idea what will
       ;result from this, but I doubt it will look good)
       ;then set it to color zero.
       If cc>=Slot
         cc=0
       EndIf
     
       OldCode=cc
       TempOldCode=OldCode
     
       ;And let us not forget to put the char into the buffer, and if,
       ;on the off chance, we were exactly one pixel from the end of
       ;the line, we have to send the buffer to the OutLineGIF() routine
       *lpBuffPtr\b=cc
       *lpBuffPtr+1
       BufCnt-1
     
       If BufCnt=0
         GIF_OutLine(lpBUFF,width,height,cl)
         *lpBuffPtr=lpBUFF
         BufCnt=width
       EndIf
     
     Else
     
       ;In this case, it's not a clear code or an ending code, so it
       ;must be a code code. So we can now decode the code into a
       ;stack of character codes (Clear as mud, right?).
       code=cc
     
       If code=Slot
         code=TempOldCode
         *lpSP\b=OldCode
         *lpSP+1
       EndIf
     
       ;Here we scan back along the linked list of prefixes, pushing
       ;helpless characters (i.e. suffixes) onto the stack as we do so.
       While code>=NewCodes
         *lpSP\b=suffix(code)
         *lpSP+1
         code=prefix(code)
       Wend
     
       ;Push the last character on the stack, and set up the new
       ;prefix and suffix, and if the required slot number is greater
       ;than that allowed by the current bit size, increase the bit
       ;size. (Note - if we are all full, we *don't* save the new
       ;suffix and prefix. I'm not certain if this is correct,
       ;it might be more proper to overwrite the last code.
       *lpSP\b=code
       *lpSP+1
     
       If Slot<TopSlot
         OldCode=code
         suffix(Slot)=OldCode
         prefix(Slot)=TempOldCode
         Slot+1
         TempOldCode=cc
       EndIf
     
       If Slot>=TopSlot
         If cl\CurrCodeSize<12
           TopSlot=TopSlot << 1
           cl\CurrCodeSize+1
         EndIf
       EndIf
     
       ;Now that we've pushed the decoded string (in reverse order)
       ;onto the stack, lets pop it off and put it into our decode
       ;buffer, and when the decode buffer is full, write another line.
       While *lpSP>@stack(0)
         *lpSP-1
         *lpBuffPtr\b=*lpSP\b
         *lpBuffPtr+1
         BufCnt-1
       
         If BufCnt=0
           GIF_OutLine(lpBUFF,width,height,cl)
           *lpBuffPtr=lpBUFF
           BufCnt=width
         EndIf
       Wend
     
     EndIf
   Wend
 
   If BufCnt<>width ;If there are any left, output the bytes
     GIF_OutLine(lpBUFF,width-BufCnt-1,height,cl)
   EndIf
   *dib=hDIB
   If *dib=0 ;Avoid errors
     ProcedureReturn #False
   EndIf
 
   Define.l Bits=*dib+*dib\biSize+(*dib\biClrUsed*4) ;Pointer to bits
 
   ;Create the DDB bitmap
   Define.l hImage=GIF_CreateDIImage(#PB_Any, *dib, TransColorIndex)
   Define.l pbimage=CreateImage(#PB_Any,realwidth,realheight, 32 | #PB_Image_Transparent) ; Create initial "screen"
   StartDrawing(ImageOutput(pbimage))
   DrawingMode(#PB_2DDrawing_AlphaBlend)
   ;Box(0,0,realwidth,realheight,$FFFFFF)
   DrawImage(ImageID(hImage),im\imLeft,im\imTop,im\imWidth,im\imHeight)
   StopDrawing()
   FreeImage(hImage)
   FreeMemory(hDIB)
   ;imageArray(0)=ImageID(pbimage)
   GIF_Frames(0)\Image = pbimage
   GIF_Frames(0)\DelayTime = delaytime
   Define.l numberimages=1
 
   ;===========================
   ;- continue to other frames
   ;===========================
 
   ; Read through the various image blocks
   Define.l NotatEnd=1
   While NotatEnd=1
     Define.w TransColorIndex = -1
     Define.l n
     While n<>$2C
       n=ReadByte(file) & 255
       If n=$3B
         NotatEnd=0
         CloseFile(file)
         FreeMemory(lpBUFF)
         ProcedureReturn numberimages
       ElseIf n=$F9
         ;Graphics control extension
         n=ReadByte(file) & 255
         Define.l Size = n
         n=ReadByte(file) ;& 255 ; packedfields
         ;Define.b packedfields = n &$FF
         Define.l disposalmethod = (n & %00011100) >>2
         tflag = n & %00000001
         delaytime = ReadWord(file)
         Define.a transparent = ReadByte(file)
         If tflag : TransColorIndex = transparent : EndIf
       ElseIf n=$FF
         ;application extension
       ElseIf n=$FE
         ;comment extention
         n=ReadByte(file) & 255
         FileSeek(file,Loc(file)+n)
       ElseIf n= $01
         ;"plain text extention"
         ;Debug "text"
         ; n=ReadByte(file) & 255
         ;FileSeek(file,Loc(file)+n& $FF)
       ElseIf n =$21
         ;"A Extension_block
       EndIf
     Wend
     n=0
   
     ; done with reading the image blocks for this frame
   FileSeek(file,Loc(file)-1)
   count=0
   While count<>$2C ;Search for im\imSep
     count=ReadByte(file) & 255
   Wend
   FileSeek(file,Loc(file)-1) ;Seek to im\imSep
 
   ReadData(file,im,SizeOf(im)) ;Read the image descriptor
 
   ;Store im\imPkFields for bit manipulation
   impkFields=im\impkFields & 255
 
   ;Is the image interlaced
   cl\bImInterLace=(impkFields & (1 << 6)) >> 6
 
   ;Is the local color table sorted
   bImColsSorted=(impkFields & (1 << 5)) >> 5
 
   ;Is there a local color table
   bImColTable=(impkFields & (1 << 7)) >> 7
 
   If bImColTable
     cl\bUseGlobalColMap=#False
   
     ImgColBytes=3*(1 << ((impkFields & $07)+1)) ;Table size in bytes
     ImgColors=ImgColBytes/3 ;Number of colors
   
     If ImgColors<=2 ;Make sure image bit depth is 1, 4 or 8
       cl\ImgColRes=1
     ElseIf ImgColors<=16
       cl\ImgColRes=4
     Else
       cl\ImgColRes=8
     EndIf
   
     For count=0 To ImgColors-1 ;Get the local image colors
       Red=ReadByte(file) & 255
       Green=ReadByte(file) & 255
       Blue=ReadByte(file) & 255
       localCols(count)=RGB(Red,Green,Blue)
     Next
     ;loctranscolor=localCols(transparent& $FF)
     ;transcolor=localCols(transparent& $FF)
   Else ;No local color table
     If cl\bUseGlobalColMap=#False ;No global color table
       CloseFile(file)
       MessageRequester("GIF Load Error!" , "The GIF image does not contain a valid color table.")
       ProcedureReturn #False ;NO_COLORTABLE
     EndIf
     ;transcolor=GlobalCols(transparent& $FF)
   EndIf
 
   width=im\imWidth & $FFFF ;Image width
   height=im\imHeight & $FFFF ;Image height
 
   ;Get the first byte of the new block of image data.
   ;Should be the bit size
   LZWCodeSize=ReadByte(file) & 255
 
   ;Bit size is normally the same as the color resolution.
   ;i.e. 8 for 256 colors
   If LZWCodeSize<2 Or LZWCodeSize>8
     CloseFile(file)
     MessageRequester("GIF Load Error!" , "LZW code size is not valid!")
     ProcedureReturn #False ;BAD_CODE_SIZE
   EndIf
 
   ;Initialise the variables for the decoder for reading a new image.
   cl\CurrCodeSize=LZWCodeSize+1
   TopSlot=1 << cl\CurrCodeSize ;Highest code for current size
   ClearCode=1 << LZWCodeSize ;Value for a clear code
   EndingCode=ClearCode+1 ;Value for an ending code
   NewCodes=ClearCode+2 ;First available code
   Slot=NewCodes ;Last read code
   cl\BitsLeft=0
   cl\BytesLeft=0
 
   ;Just in case...
   TempOldCode=0 : OldCode=0
 
   ;Allocate space for the decode buffer
   lpBUFF=AllocateMemory(width+8) ;+8 just in case
 
   ;Set up the stack pointer, decode buffer pointer and line counter
   *lpSP=@stack(0)
   *lpBuffPtr=lpBUFF
   BufCnt=width ;Count for pixel line length
 
   ;Start creating the DIB
   If cl\bUseGlobalColMap ;Global color table
     bitcount=cl\GlobColRes
   Else ;Local color table
     bitcount=cl\ImgColRes
   EndIf
 
   bi\biSize=SizeOf(bi)
   bi\biWidth=width
   bi\biHeight=height
   bi\biPlanes=1
   bi\biBitCount=bitcount ;BitCount will be 1, 4 or 8
   bi\biCompression=#BI_RGB
   bi\biSizeImage=0
   bi\biXPelsPerMeter=0
   bi\biYPelsPerMeter=0
   If cl\bUseGlobalColMap ;Global color table
     bi\biClrUsed=GlobColors
   Else ;Local color table
     bi\biClrUsed=ImgColors
   EndIf
   bi\biClrImportant=0
 
   ;With the BITMAPINFO format headers, the size of the palette is
   ;in biClrUsed, whereas in the BITMAPCORE - style headers, it is
   ;dependent on the Bits per pixel (2 to the power of bitsperpixel).
   If bi\biClrUsed<>0
     ncolors=bi\biClrUsed
   Else ;We don't have an optimal palette
     ncolors=1 << bi\biBitCount
   EndIf
 
   cl\pitch=(((bitcount*width)+31) >> 5) << 2 ;Bytes per line
   Len=bi\biSize+(ncolors*4)+(cl\pitch*height) ;Size of DIB
 
   bi\biSizeImage=cl\pitch*height ;Fill in biSizeImage
 
   ;Allocate memory block to store our DIB
   hDIB=AllocateMemory(Len)
   If hDIB=0
     FreeMemory(lpBUFF)
     CloseFile(file)
     MessageRequester("GIF Load Error!" , "Memory allocation failed!")
     ProcedureReturn #False ;NO_DIB
   EndIf
 
   ;Fill first part of DIB with the BITMAPINFOHEADER
   CopyMemory(bi,hDIB,SizeOf(bi))
 
   ;Set the colors in the DIB (or masks for the new DIB formats)
   *pal=hDIB+SizeOf(bi)
   If cl\bUseGlobalColMap
     For count=0 To bi\biClrUsed-1
       *pal\rgbBlue=Blue(GlobalCols(count))
       *pal\rgbGreen=Green(GlobalCols(count))
       *pal\rgbRed=Red(GlobalCols(count))
       *pal+4
     Next
   Else
     For count=0 To bi\biClrUsed-1
       *pal\rgbBlue=Blue(localCols(count))
       *pal\rgbGreen=Green(localCols(count))
       *pal\rgbRed=Red(localCols(count))
       *pal+4
     Next
   EndIf
 
   cl\Line=0 ;Set address offset for OutLineGIF()
   cl\Pass=0 ;For interlaced images in OutLineGIF()
 
   ;Image data bits of DIB
   cl\lpBits=hDIB+bi\biSize+(ncolors*4)+(cl\pitch*(height-1))
 
   ;This is the main loop. For each code we get we pass through the
   ;linked list of prefix codes, pushing the corresponding "character"
   ;for each code onto the stack. When the list reaches a single
   ;"character" we push that on the stack too, and then start
   ;unstacking each character for output in the correct order.
   ;Special handling is included for the clear code, and the whole
   ;thing ends when we get an ending code.
   cc=0
 
   While cc<>EndingCode
   
     cc=GIF_NextCode(file,CharBuff(),CodeMask(),cl)
   
     If cc<0 ;If a file error, return without completing the decode
       FreeMemory(lpBUFF)
       CloseFile(file)
       MessageRequester("GIF Load Error!", "GIF image contained an in-valid LZW code.")
       ProcedureReturn #False ;FILE_ERROR
     EndIf
   
     ;If the code is a clear code, re-initialise all necessary items.
     If cc=ClearCode
     
       cl\CurrCodeSize=LZWCodeSize+1
       Slot=NewCodes
       TopSlot=1 << cl\CurrCodeSize
     
       ;Continue reading codes until we get a non-clear code
       ;(another unlikely, but possible case...)
       While cc=ClearCode
         cc=GIF_NextCode(file,CharBuff(),CodeMask(),cl)
       Wend
     
       ;If we get an ending code immediately after a clear code
       ;(yet another unlikely case), then break out of the loop.
       If cc=EndingCode
         Break ;end loop
       EndIf
     
       ;Finally, if the code is beyond the range of already set codes,
       ;(This one had better not happen, I have no idea what will
       ;result from this, but I doubt it will look good)
       ;then set it to color zero.
       If cc>=Slot
         cc=0
       EndIf
     
       OldCode=cc
       TempOldCode=OldCode
     
       ;And let us not forget to put the char into the buffer, and if,
       ;on the off chance, we were exactly one pixel from the end of
       ;the line, we have to send the buffer to the OutLineGIF() routine
       *lpBuffPtr\b=cc
       *lpBuffPtr+1
       BufCnt-1
     
       If BufCnt=0
         GIF_OutLine(lpBUFF,width,height,cl)
         *lpBuffPtr=lpBUFF
         BufCnt=width
       EndIf
     
     Else
     
       ;In this case, it's not a clear code or an ending code, so it
       ;must be a code code. So we can now decode the code into a
       ;stack of character codes (Clear as mud, right?).
       code=cc
     
       If code=Slot
         code=TempOldCode
         *lpSP\b=OldCode
         *lpSP+1
       EndIf
     
       ;Here we scan back along the linked list of prefixes, pushing
       ;helpless characters (i.e. suffixes) onto the stack as we do so.
       While code>=NewCodes
         *lpSP\b=suffix(code)
         *lpSP+1
         code=prefix(code)
       Wend
     
       ;Push the last character on the stack, and set up the new
       ;prefix and suffix, and if the required slot number is greater
       ;than that allowed by the current bit size, increase the bit
       ;size. (Note - if we are all full, we *don't* save the new
       ;suffix and prefix. I'm not certain if this is correct,
       ;it might be more proper to overwrite the last code.
       *lpSP\b=code
       *lpSP+1
     
       If Slot<TopSlot
         OldCode=code
         suffix(Slot)=OldCode
         prefix(Slot)=TempOldCode
         Slot+1
         TempOldCode=cc
       EndIf
     
       If Slot>=TopSlot
         If cl\CurrCodeSize<12
           TopSlot=TopSlot << 1
           cl\CurrCodeSize+1
         EndIf
       EndIf
     
       ;Now that we've pushed the decoded string (in reverse order)
       ;onto the stack, lets pop it off and put it into our decode
       ;buffer, and when the decode buffer is full, write another line.
       While *lpSP>@stack(0)
         *lpSP-1
         *lpBuffPtr\b=*lpSP\b
         *lpBuffPtr+1
         BufCnt-1
       
         If BufCnt=0
           GIF_OutLine(lpBUFF,width,height,cl)
           *lpBuffPtr=lpBUFF
           BufCnt=width
         EndIf
       Wend
     
     EndIf
   
   Wend
 
   If BufCnt<>width ;If there are any left, output the bytes
     GIF_OutLine(lpBUFF,width-BufCnt-1,height,cl)
   EndIf
 
   ;Create the DDB bitmap
   *dib=hDIB
   If *dib=0 ;Avoid errors
     ProcedureReturn #False
   EndIf
 
   Bits=*dib+*dib\biSize+(*dib\biClrUsed*4) ;Pointer to bits
 
   ;- create the bitmap
   ;Create the DDB bitmap
   Define.l hImage = GIF_CreateDIImage(#PB_Any, *dib, TransColorIndex)
   pbimage=CreateImage(#PB_Any,realwidth,realheight, 32 | #PB_Image_Transparent)
   StartDrawing(ImageOutput(pbimage))
   DrawingMode(#PB_2DDrawing_AlphaBlend)
   ; For some retarded reason, we have to draw and redraw the GIF frames over the previous image imagenumber-1
 
 ;   If bUseGlobalColMap ; if a local color table, then draw previous image in array, and then dray new hbitmap with transparency
 ;     Box(0,0,realwidth,realheight,$FFFFFF)
 ;     DrawImage(imageArray(numberimages-1),0,0)
 ;     If tflag=1
 ;       ;loc
 ;       DrawTransparentImage(drawdc,hBitmap,im\imLeft,im\imTop,im\imWidth,im\imHeight,transcolor)
 ;     Else
 ;       DrawImage(hBitmap,im\imLeft,im\imTop,im\imWidth,im\imHeight)
 ;     EndIf
 ;   Else
   
     If disposalmethod = 1
       ;Box(0,0,realwidth,realheight,$FFFFFF)
       DrawImage(ImageID(GIF_Frames(numberimages-1)\Image),0,0)
       DrawImage(ImageID(hImage),im\imLeft,im\imTop,im\imWidth,im\imHeight)
     ElseIf disposalmethod = 2
       ;Box(0,0,realwidth,realheight,$FFFFFF)
       ;DrawImage(ImageID(GIF_Frames(1)),0,0)
       DrawImage(ImageID(hImage),im\imLeft,im\imTop,im\imWidth,im\imHeight)
     Else
       ;Box(0,0,realwidth,realheight,$FFFFFF)
       DrawImage(ImageID(GIF_Frames(numberimages-1)\Image),0,0)
       ;DrawImage(hBitmap,im\imLeft,im\imTop)
       DrawImage(ImageID(hImage),im\imLeft,im\imTop,im\imWidth,im\imHeight)
     EndIf
 ;   EndIf
   StopDrawing()
   FreeImage(hImage)
   FreeMemory(hDIB) ;Free the DIB
   ReDim GIF_Frames(numberimages)
   GIF_Frames(numberimages)\Image = pbimage
   GIF_Frames(numberimages)\DelayTime = delaytime
   numberimages + 1
 Wend
 ProcedureReturn numberimages
EndProcedure

#Gif_Test = #True
CompilerIf #Gif_Test ;{

Define.w a
Dim Frames.GIF_Frame(0)

OpenWindow(0, 0, 0, 800, 600, "Gif_Test", #PB_Window_SystemMenu|#PB_Window_ScreenCentered|#PB_Window_SizeGadget|#PB_Window_MaximizeGadget)
ButtonGadget(0,10,10,80,20,"Open File")
ImageGadget(1,50,50,0,0,0, #PB_Image_Border)

AddWindowTimer(0, 0, 100)

Repeat
   Select WaitWindowEvent()
     Case #PB_Event_Gadget
       Select EventGadget()
         Case 0
           Define.s Pattern="All Supported Formats|*.gif"
           Define.s filename=OpenFileRequester("Choose An Image File To Open","",Pattern,0)
           If filename
             If GIF_LoadFrames(filename,Frames())
               ResizeGadget(1, #PB_Ignore, #PB_Ignore, ImageWidth(Frames(0)\Image), ImageHeight(Frames(0)\Image))
               ;SetGadgetState(0, ImageID(Frames(0)\Image))
             EndIf
           EndIf
       EndSelect

     Case #PB_Event_CloseWindow
       Break
   
     Case #PB_Event_Timer
         RemoveWindowTimer(0, 0)
         If a > ArraySize(Frames()) : a = 0 : EndIf
         If IsImage(Frames(a)\Image)
            SetGadgetState(1, ImageID(Frames(a)\Image))
            AddWindowTimer(0, 0, Frames(a)\DelayTime * 10)
         Else
            AddWindowTimer(0, 0, 100)
         EndIf
         a + 1   
   EndSelect

ForEver

CompilerEndIf ;}

_________________
Niffo


Last edited by Niffo on Thu Mar 15, 2012 9:11 pm, edited 1 time in total.

Top
 Profile  
 
 Post subject: Re: UPDATED: Load Animated GIF frames
PostPosted: Thu Mar 15, 2012 8:25 pm 
Offline
Addict
Addict
User avatar

Joined: Thu Jun 24, 2004 2:44 pm
Posts: 4715
Location: Berlin - Germany
Image
This is great :D
The first version in this thread, that is working for me.

Many thanks

_________________
PureBasic 5.11 | Windows 7 SP1 (x64) | Mageia 3 (x64) | RealSource

The use of EnableExplicit is free of charge and avoids errors.


Top
 Profile  
 
 Post subject: Re: UPDATED: Load Animated GIF frames
PostPosted: Thu Mar 15, 2012 9:07 pm 
Offline
Enthusiast
Enthusiast
User avatar

Joined: Tue Jan 31, 2006 9:43 am
Posts: 323
Location: France
Before to have the obligation to have a code who works on MacOS, i also used GDI+ ;-) (viewtopic.php?f=12&t=49437&p=376400)

_________________
Niffo


Top
 Profile  
 
 Post subject: Re: UPDATED: Load Animated GIF frames
PostPosted: Fri Mar 16, 2012 3:32 am 
Offline
Addict
Addict
User avatar

Joined: Thu Jun 24, 2004 2:44 pm
Posts: 4715
Location: Berlin - Germany
Here is a version with some improvements :
Quote:
; + added Catch-Support
; + added reading of complete giffile into memory, this should be faster ;-)
; + optimized Variabletypes for better support 64-Bit Programs
; + changed Syntax of GIF_LoadFrames() to:
; GIF_LoadFrames(Array GIF_Frames.GIF_Frame(1), filename.s = "", *memory = 0, memsize = 0)

[GIFanimation.pbi]
Code:
; Original PB code by "hagibaba" (Purebasic.fr forums) based on "loadgif.c" for ImageShop32 by John Findlay
; Gif Anim support by localmotion34 (Purebasic.fr forums)
; Updated & Extended by Dean Williams - resplace.net
; APIs free, alpha channel support and bug fixes by Niffo (Purebasic.fr forums)

; #######################################
; enhanced and optimized by Thomas <ts-soft> Schulz (www.realsource.de)
; + added Catch-Support
; + added reading of complete giffile into memory, this should be faster ;-)
; + optimized Variabletypes for better support 64-Bit Programs
; + changed Syntax of GIF_LoadFrames() to:
; GIF_LoadFrames(Array GIF_Frames.GIF_Frame(1), filename.s = "", *memory = 0, memsize = 0)
; changed MessageRequester to Debug.
; #######################################
; Please help development and report any problems or improvements/bug fixes you may have on
; if we all work together we can have some really nice GIF support in PureBasic!
; http://www.purebasic.fr/english/viewtopic.php?f=12&t=27575

;{ - Structures

CompilerIf Defined(BITMAPINFOHEADER, #PB_Structure)
CompilerElse
Structure BITMAPINFOHEADER
  biSize.l
  biWidth.l
  biHeight.l
  biPlanes.w
  biBitCount.w
  biCompression.l
  biSizeImage.l
  biXPelsPerMeter.l
  biYPelsPerMeter.l
  biClrUsed.l
  biClrImportant.l
EndStructure

#BI_RGB = 0

Structure RGBQUAD
  rgbBlue.a
  rgbGreen.a
  rgbRed.a
  rgbReserved.a
EndStructure
CompilerEndIf

Structure GIF_Frame
  Image.i
  DelayTime.w
EndStructure

Structure GIFHEADER ;Header
  ghSig.b[6] ;Signature & Version
  ghWidth.w ;Logical Screen Width
  ghHeight.w ;Logical Screen Height
  ghPkFields.b ;Global Color Table Flag
  ghBkColIndex.b ;Background Color Index
  ghAspRatio.b ;Pixel Aspect Ratio
EndStructure

Structure GIFIMAGE ;Image Descriptor
  imSep.b ;Image Separator
  imLeft.w ;Image Left Position
  imTop.w ;Image Top Position
  imWidth.w ;Image Width
  imHeight.w ;Image Height
  impkFields.b ;Local Color Table Flag
EndStructure

Structure GIFCLASS ;This is instead of using globals
  *lpBytes.Byte ;Pointer to next byte in block
  Pass.l ;First pass for interlaced images in OutLineGIF()
  Line.l ;Offset for addressing the bits in OutLineGIF()
  lpBits.l ;Scanline for bits
  pitch.l ;Bytes are rounded up for image lines
  CurrCodeSize.l ;The current code size
  BitsLeft.l ;Used in NextCodeGIF()
  BytesLeft.l ;Used in NextCodeGIF()
  CurrByte.l ;Current byte
  bUseGlobalColMap.b ;Is the color table global
  GlobColRes.l ;Color Resolution, bits '6' '5' '4'
  bImInterLace.b ;Is the image interlaced
  ImgColRes.l ;Color Resolution
EndStructure

;}

Procedure GIF_OutLine(lpPixels.l,LineLen.l,height.l,*cl.GIFCLASS)
  ;Outputs the pixel color index data to the DIB
  ;lpPixels -> Memory block that holds the color index value
  ;LineLen -> Length of the line of pixels
  ;Height -> im\imHeight
  ;Gif images are 2, 16 or 256 colors, poking the values into memory
  ;requires a different method for each case. If gif is interlaced,
  ;that is dealt with here.
 
  Protected ib.l,pixel.l,byte.l,BitCnt.l,CntBk.l,ColRes.l,Bits.l
 
  Bits=*cl\lpBits-(*cl\Line * *cl\pitch) ;Pointer to bits
 
  If *cl\bUseGlobalColMap
    ColRes=*cl\GlobColRes
  Else
    ColRes=*cl\ImgColRes
  EndIf
 
  Select ColRes
     
    Case 1
      byte=0
      For pixel=0 To LineLen-1 Step 8
        ib=0
        CntBk=7
        For BitCnt=0 To 8-1
          If PeekB(lpPixels+BitCnt+pixel)
            ib=ib | (1 << CntBk)
          EndIf
          CntBk-1
        Next
        PokeB(Bits+byte,ib)
        byte+1
      Next
     
    Case 4
      byte=0
      For pixel=0 To LineLen-1 Step 2
        ib=((PeekB(lpPixels+pixel) & 255) << 4)
        ib | (PeekB(lpPixels+pixel+1) & 255)
        PokeB(Bits+byte,ib)
        byte+1
      Next
     
    Case 8
      For pixel=0 To LineLen-1
        ib=PeekB(lpPixels+pixel) & 255
        PokeB(Bits+pixel,ib)
      Next
     
  EndSelect
 
  If *cl\bImInterLace ;Set Line for different passes when Interlaced
   
    Select *cl\Pass
       
      Case 0 ;Pass 1
        If *cl\Line<height-8
          *cl\Line+8
        Else
          *cl\Line=4 : *cl\Pass+1 ;Set Line for second pass
        EndIf
       
      Case 1 ;Pass 2
        If *cl\Line<height-8
          *cl\Line+8
        Else
          *cl\Line=2 : *cl\Pass+1 ;Set Line for third pass
        EndIf
       
      Case 2 ;Pass 3
        If *cl\Line<height-4
          *cl\Line+4
        Else
          *cl\Line=1 : *cl\Pass+1 ;Set Line for fourth pass
        EndIf
       
      Case 3 ;Pass 4
        If *cl\Line<height-2
          *cl\Line+2
        EndIf
       
    EndSelect
   
  Else ;When not Interlaced increment Line
   
    *cl\Line+1
   
  EndIf
 
EndProcedure

Procedure.l GIF_NextCode(*mem, mempos, *pos.long, Array CharBuff.b(1),Array CodeMask.l(1),*cl.GIFCLASS)
  ;Reads the next code from the data stream
  ;Returns the LZW CODE or ERROR
 
  Protected count.l,Char.l,ret.l
 
  If *cl\BitsLeft=0 ;Any bits left in byte?
   
    If *cl\BytesLeft<=0 ;If not get another block
     
      *cl\lpBytes=@CharBuff(0) ;Set byte pointer
      *cl\BytesLeft = PeekA(*mem + mempos) : mempos + SizeOf(Byte)
     
      If *cl\BytesLeft<0
        *pos\l = mempos
        ProcedureReturn *cl\BytesLeft ;Return if error
      ElseIf *cl\BytesLeft
        For count=0 To *cl\BytesLeft-1
          Char = PeekA(*mem + mempos) : mempos + SizeOf(Byte)
          *pos\l = mempos
          If Char<0 : ProcedureReturn Char : EndIf
          CharBuff(count)=Char ;Fill the char buffer with the new block
        Next
      EndIf
     
    EndIf
   
    *cl\CurrByte=*cl\lpBytes\b & 255 ;Get a byte
    *cl\lpBytes+1 ;Increment index pointer
    *cl\BitsLeft=8 ;Set bits left in the byte
    *cl\BytesLeft-1 ;Decrement the bytes left counter
   
  EndIf
 
  ;Shift off any previously used bits
  ret=*cl\CurrByte >> (8-*cl\BitsLeft)
 
  While *cl\CurrCodeSize>*cl\BitsLeft
   
    If *cl\BytesLeft<=0
     
      ;Out of bytes in current block
      *cl\lpBytes=@CharBuff(0) ;Set byte pointer
      *cl\BytesLeft = PeekA(*mem + mempos) : mempos + SizeOf(Byte)
     
      If *cl\BytesLeft<0
        *pos\l = mempos
        ProcedureReturn *cl\BytesLeft ;Return if error
      ElseIf *cl\BytesLeft
        For count=0 To *cl\BytesLeft-1
          Char = PeekA(*mem + mempos) : mempos + SizeOf(Byte)
          *pos\l = mempos
          If Char<0 : ProcedureReturn Char : EndIf
          CharBuff(count)=Char ;Fill the char buffer with the current block
        Next
      EndIf
     
    EndIf
   
    *cl\CurrByte=*cl\lpBytes\b & 255 ;Get a byte
    *cl\lpBytes+1 ;Increment index pointer
    ret | (*cl\CurrByte << *cl\BitsLeft) ;Add remaining bits to return
    *cl\BitsLeft+8 ;Set bit counter
    *cl\BytesLeft-1 ;Decrement bytesleft counter
   
  Wend
 
  *cl\BitsLeft-*cl\CurrCodeSize ;Subtract the code size from bitsleft
  ret & CodeMask(*cl\CurrCodeSize) ;Mask off the right number of bits
  *pos\l = mempos
  ProcedureReturn ret
 
EndProcedure

Procedure GIF_CreateDIImage(*dib.BITMAPINFOHEADER, TransColIndex.w)
  Protected *Bits = *dib+*dib\biSize+(*dib\biClrUsed*4)
  Protected Image = CreateImage(#PB_Any, *dib\biWidth, *dib\biHeight, 32)
  Protected.l X, Y, RGBA, Col
  Protected *Pal = *dib + *dib\biSize
  Protected.a ColInd, Alpha
  Protected.l dibPitch = *dib\biSizeImage/*dib\biHeight
 
  StartDrawing(ImageOutput(Image))
  DrawingMode(#PB_2DDrawing_AllChannels)
 
  ;   Define *BufAddr = DrawingBuffer()
  ;   Define.l BufPitch = DrawingBufferPitch()
  For Y = 0 To *dib\biHeight - 1
    For X = 0 To *dib\biWidth - 1
     
      Select *dib\biBitCount
        Case 8
          ColInd = PeekA(*Bits + Y*dibPitch+X)
        Case 4
          ;If X % 2
          ;   ColInd = PeekA(*Bits + Y*dibPitch+X) & $F
          ;Else
          ;   ColInd = PeekA(*Bits + Y*dibPitch+X) >> 4
          ;EndIf
          ColInd = PeekA(*Bits + Y*dibPitch+X/2) >> (4*(1-X%2)) & $F
      EndSelect         
     
      If ColInd = TransColIndex : Alpha = 0 : Else : Alpha = 255 : EndIf
      Col = PeekL(*Pal+ColInd*4)
     
      ; Plot
      RGBA = RGBA(Blue(Col), Green(Col), Red(Col), Alpha)
      Plot(X, *dib\biHeight-1-Y, RGBA)
     
      ;          ; Direct Buffer Write (not faster !?)
      ;          If DrawingBufferPixelFormat() & #PB_PixelFormat_32Bits_RGB
      ;             RGBA = RGBA(Blue(Col), Green(Col), Red(Col), Alpha)
      ;          ElseIf DrawingBufferPixelFormat() & #PB_PixelFormat_32Bits_BGR
      ;             RGBA = RGBA(Red(Col), Green(Col), Blue(Col), Alpha)
      ;          EndIf
      ;          If DrawingBufferPixelFormat() & #PB_PixelFormat_ReversedY
      ;             PokeL(*BufAddr + (Y*BufPitch+X*4), RGBA)
      ;          Else
      ;             PokeL(*BufAddr + ((*dib\biHeight-1-Y)*BufPitch+X*4), RGBA)
      ;          EndIf
     
    Next X
  Next Y
 
  StopDrawing()
 
  ProcedureReturn Image
 
EndProcedure

Procedure.i GIF_LoadFrames(Array GIF_Frames.GIF_Frame(1), filename.s = "", *memory = 0, memsize = 0)
  ;From "loadgif.c" for ImageShop32 by John Findlay
  ;Loads LZW Graphics Interchange Format files
  ;Uses NextCodeGIF() and OutLineGIF()
 
  Protected Dim stack.b(4096) ;Stack for storing pixels
  Protected Dim suffix.b(4096) ;Suffix table, max number of LZW codes
  Protected Dim prefix.l(4096) ;Prefix linked list (these are longs)
  Protected Dim CharBuff.b(279) ;Current block
  Protected Dim GlobalCols.l(256) ;Global colors of gif
  Protected Dim localCols.l(256) ;Local image colors of gif
  Protected Dim CodeMask.l(16) ;Masks for LZW compression algorithm
  Protected gh.GIFHEADER
  Protected im.GIFIMAGE
  Protected cl.GIFCLASS
  Protected bi.BITMAPINFOHEADER
  Protected *pal.RGBQUAD
  Protected *lpSP.Byte ;Pointer to stack
  Protected *lpBuffPtr.Byte ;Pointer to buffer
  Protected bGlobColsSorted.b ;Sort Flag  bit '3' (this is unused)
  Protected file.l,sig.s,PkFields.l,bGlobColTable.b,GlobColBytes.l
  Protected GlobColors.l,count.l,Red.l,Green.l,Blue.l
  Protected width.l,height.l,impkFields.l,bImColsSorted.b
  Protected bImColTable.b,ImgColBytes.l,LZWCodeSize.l,TopSlot.l
  Protected ClearCode.l,ImgColors.l,EndingCode.l,NewCodes.l,Slot.l
  Protected lpBUFF.l,TempOldCode.l,OldCode.l,BufCnt.l,bitcount.l
  Protected ncolors.l,Len.l,hDIB.l,cc.l,code.l
  Protected *dib.BITMAPINFOHEADER
 
  CodeMask( 0)=$0000 : CodeMask( 1)=$0001
  CodeMask( 2)=$0003 : CodeMask( 3)=$0007
  CodeMask( 4)=$000F : CodeMask( 5)=$001F
  CodeMask( 6)=$003F : CodeMask( 7)=$007F
  CodeMask( 8)=$00FF : CodeMask( 9)=$01FF
  CodeMask(10)=$03FF : CodeMask(11)=$07FF
  CodeMask(12)=$0FFF : CodeMask(13)=$1FFF
  CodeMask(14)=$3FFF : CodeMask(15)=$7FFF
 
  Protected mempos, newpos, *mem
  If filename <> ""
    ;Open the file
    file=ReadFile(#PB_Any,filename)
    If file=0
      Debug "GIF Load Error! Could not open the GIF image file for reading."
      ProcedureReturn #False
    EndIf
    ;Read the file header and logical screen descriptor
    memsize = Lof(file)
    *mem = AllocateMemory(memsize)
    If *mem = 0
      Debug "GIF Load Error! Could not allocate Memory for GIF image."
      ProcedureReturn #False
    EndIf
    ReadData(file, *mem, memsize)
    CloseFile(file)
  ElseIf *memory
    *mem = AllocateMemory(memsize)
    If *mem
      CopyMemory(*memory, *mem, memsize)
    EndIf
  EndIf
  If *mem = 0
    Debug "GIF Load Error! Could not find Memory for GIF image."
    ProcedureReturn #False   
  EndIf
  CopyMemory(*mem, gh, SizeOf(gh))
  mempos + SizeOf(gh)
  sig=PeekS(@gh\ghSig,6,#PB_Ascii) ;Get the header version string
 
  If sig<>"GIF89a" And sig<>"GIF87a"
    FreeMemory(*mem)
    Debug "GIF Load Error! File was not a valid GIF image file"
    ProcedureReturn #False ;NOT_VALID
  EndIf
  Protected.l realwidth=gh\ghWidth
  Protected.l realheight=gh\ghHeight
 
  ;Store gh\ghPkFields for bit manipulation
  PkFields=gh\ghPkFields & 255
 
  ;Global Color Table Flag bit '7'
  bGlobColTable=(PkFields & (1 << 7)) >> 7
 
  If bGlobColTable
    cl\bUseGlobalColMap=#True
   
    GlobColBytes=3*(1 << ((PkFields & $07)+1)) ;Table size in bytes
    GlobColors=GlobColBytes/3 ;Number of colors
   
    ;Some gif encoders do not follow the gif spec very well,
    ;so make cl\GlobColRes from GlobColors.
    ;Also gif's are used on different platforms, which do
    ;have different bits per pixel. i.e. 32 colors is 5 bits/pixel.
    If GlobColors<=2
      cl\GlobColRes=1
    ElseIf GlobColors<=16
      cl\GlobColRes=4
    Else
      cl\GlobColRes=8
    EndIf
   
    For count=0 To GlobColors-1 ;Get the global screen colors
      Red = PeekA(*mem + mempos) : mempos + SizeOf(Byte)
      Green = PeekA(*mem + mempos) : mempos + SizeOf(Byte)
      Blue = PeekA(*mem + mempos) : mempos + SizeOf(Byte)
      GlobalCols(count)=RGB(Red,Green,Blue)
    Next
  EndIf
 
  Protected.w TransColorIndex = -1
  count=0
  While count<>$2C ;Search for im\imSep
    count = PeekA(*mem + mempos) : mempos + SizeOf(Byte)
    If count = $F9
      mempos + SizeOf(Byte)
      Protected.b tflag = PeekB(*mem + mempos) & 1 : mempos + SizeOf(Byte)
      Protected.w delaytime = PeekW(*mem + mempos) : mempos + SizeOf(Word)
      Protected.a transparent = PeekB(*mem + mempos) : mempos + SizeOf(Byte)
      If tflag : TransColorIndex = transparent : EndIf
    EndIf
  Wend
  mempos - SizeOf(byte);Seek to im\imSep
  CopyMemory(*mem + mempos, im, SizeOf(im)) ;Read the image descriptor
  mempos + SizeOf(im)
  ;Store im\imPkFields for bit manipulation
  impkFields=im\impkFields & 255
 
  ;Is the image interlaced
  cl\bImInterLace=(impkFields & (1 << 6)) >> 6
 
  ;Is the local color table sorted
  bImColsSorted=(impkFields & (1 << 5)) >> 5
 
  ;Is there a local color table
  bImColTable=(impkFields & (1 << 7)) >> 7
 
  If bImColTable
    cl\bUseGlobalColMap=#False
   
    ImgColBytes=3*(1 << ((impkFields & $07)+1)) ;Table size in bytes
    ImgColors=ImgColBytes/3 ;Number of colors
   
    If ImgColors<=2 ;Make sure image bit depth is 1, 4 or 8
      cl\ImgColRes=1
    ElseIf ImgColors<=16
      cl\ImgColRes=4
    Else
      cl\ImgColRes=8
    EndIf
   
    For count=0 To ImgColors-1 ;Get the local image colors
      Red = PeekA(*mem + mempos) : mempos + SizeOf(Byte)
      Green = PeekA(*mem + mempos) : mempos + SizeOf(Byte)
      Blue = PeekA(*mem + mempos) : mempos + SizeOf(Byte)
      localCols(count)=RGB(Red,Green,Blue)
    Next
    ;transcolor=LocalCols(TByte)
  Else ;No local color table
    If cl\bUseGlobalColMap=#False ;No global color table
      FreeMemory(*mem)
      Debug "GIF Load Error! The GIF image does not contain a valid color table."
      ProcedureReturn #False ;NO_COLORTABLE
    EndIf
  EndIf
 
  width=im\imWidth & $FFFF ;Image width
  height=im\imHeight & $FFFF ;Image height
 
  ;Get the first byte of the new block of image data.
  ;Should be the bit size
  LZWCodeSize = PeekA(*mem + mempos) : mempos + SizeOf(Byte)
  ;Bit size is normally the same as the color resolution.
  ;i.e. 8 for 256 colors
  If LZWCodeSize<2 Or LZWCodeSize>8
    FreeMemory(*mem)
    Debug "GIF Load Error! LZW code size is not valid!"
    ProcedureReturn #False ;BAD_CODE_SIZE
  EndIf
 
  ;Initialise the variables for the decoder for reading a new image.
  cl\CurrCodeSize=LZWCodeSize+1
  TopSlot=1 << cl\CurrCodeSize ;Highest code for current size
  ClearCode=1 << LZWCodeSize ;Value for a clear code
  EndingCode=ClearCode+1 ;Value for an ending code
  NewCodes=ClearCode+2 ;First available code
  Slot=NewCodes ;Last read code
  cl\BitsLeft=0
  cl\BytesLeft=0
 
  ;Just in case...
  TempOldCode=0 : OldCode=0
 
  ;Allocate space for the decode buffer
  lpBUFF=AllocateMemory(width+8) ;+8 just in case
 
  ;Set up the stack pointer, decode buffer pointer and line counter
  *lpSP=@stack(0)
  *lpBuffPtr=lpBUFF
  BufCnt=width ;Count for pixel line length
 
  ;Start creating the DIB
  If cl\bUseGlobalColMap ;Global color table
    bitcount=cl\GlobColRes
  Else ;Local color table
    bitcount=cl\ImgColRes
  EndIf
 
  bi\biSize=SizeOf(bi)
  bi\biWidth=width
  bi\biHeight=height
  bi\biPlanes=1
  bi\biBitCount=bitcount ;BitCount will be 1, 4 or 8
  bi\biCompression=#BI_RGB
  bi\biSizeImage=0
  bi\biXPelsPerMeter=0
  bi\biYPelsPerMeter=0
  If cl\bUseGlobalColMap ;Global color table
    bi\biClrUsed=GlobColors
  Else ;Local color table
    bi\biClrUsed=ImgColors
  EndIf
  bi\biClrImportant=0
 
  ;With the BITMAPINFO format headers, the size of the palette is
  ;in biClrUsed, whereas in the BITMAPCORE - style headers, it is
  ;dependent on the Bits per pixel (2 to the power of bitsperpixel).
  If bi\biClrUsed<>0
    ncolors=bi\biClrUsed
  Else ;We don't have an optimal palette
    ncolors=1 << bi\biBitCount
  EndIf
 
  cl\pitch=(((bitcount*width)+31) >> 5) << 2 ;Bytes per line
  Len=bi\biSize+(ncolors*4)+(cl\pitch*height) ;Size of DIB
 
  bi\biSizeImage=cl\pitch*height ;Fill in biSizeImage
 
  ;Allocate memory block to store our DIB
  hDIB=AllocateMemory(Len)
  If hDIB=0
    FreeMemory(lpBUFF)
    FreeMemory(*mem)
    Debug "GIF Load Error! Memory allocation failed!"
    ProcedureReturn #False ;NO_DIB
  EndIf
 
  ;Fill first part of DIB with the BITMAPINFOHEADER
  CopyMemory(bi,hDIB,SizeOf(bi))

  ;Set the colors in the DIB (or masks for the new DIB formats)
  *pal=hDIB+SizeOf(bi)
  If cl\bUseGlobalColMap
    For count=0 To bi\biClrUsed-1
      *pal\rgbBlue=Blue(GlobalCols(count))
      *pal\rgbGreen=Green(GlobalCols(count))
      *pal\rgbRed=Red(GlobalCols(count))
      *pal+4
    Next
  Else
    For count=0 To bi\biClrUsed-1
      *pal\rgbBlue=Blue(localCols(count))
      *pal\rgbGreen=Green(localCols(count))
      *pal\rgbRed=Red(localCols(count))
      *pal+4
    Next
  EndIf
 
  cl\Line=0 ;Set address offset for OutLineGIF()
  cl\Pass=0 ;For interlaced images in OutLineGIF()
 
  ;Image data bits of DIB
  cl\lpBits=hDIB+bi\biSize+(ncolors*4)+(cl\pitch*(height-1))
 
  ;This is the main loop. For each code we get we pass through the
  ;linked list of prefix codes, pushing the corresponding "character"
  ;for each code onto the stack. When the list reaches a single
  ;"character" we push that on the stack too, and then start
  ;unstacking each character for output in the correct order.
  ;Special handling is included for the clear code, and the whole
  ;thing ends when we get an ending code.
  While cc<>EndingCode
   
    cc=GIF_NextCode(*mem, mempos, @newpos, CharBuff(),CodeMask(),cl)
    mempos = newpos
    If cc<0 ;If a file error, return without completing the decode
      FreeMemory(lpBUFF)
      FreeMemory(*mem)
      Debug "GIF Load Error! LZW code size is Not valid!"
      ProcedureReturn #False ;FILE_ERROR
    EndIf
   
    ;If the code is a clear code, re-initialise all necessary items.
    If cc=ClearCode
     
      cl\CurrCodeSize=LZWCodeSize+1
      Slot=NewCodes
      TopSlot=1 << cl\CurrCodeSize
     
      ;Continue reading codes until we get a non-clear code
      ;(another unlikely, but possible case...)
      While cc=ClearCode
        cc=GIF_NextCode(*mem, mempos, @newpos,CharBuff(),CodeMask(),cl)
         mempos = newpos
      Wend
     
      ;If we get an ending code immediately after a clear code
      ;(yet another unlikely case), then break out of the loop.
      If cc=EndingCode
        Break ;end loop
      EndIf
     
      ;Finally, if the code is beyond the range of already set codes,
      ;(This one had better not happen, I have no idea what will
      ;result from this, but I doubt it will look good)
      ;then set it to color zero.
      If cc>=Slot
        cc=0
      EndIf
     
      OldCode=cc
      TempOldCode=OldCode
     
      ;And let us not forget to put the char into the buffer, and if,
      ;on the off chance, we were exactly one pixel from the end of
      ;the line, we have to send the buffer to the OutLineGIF() routine
      *lpBuffPtr\b=cc
      *lpBuffPtr+1
      BufCnt-1
     
      If BufCnt=0
        GIF_OutLine(lpBUFF,width,height,cl)
        *lpBuffPtr=lpBUFF
        BufCnt=width
      EndIf
     
    Else
     
      ;In this case, it's not a clear code or an ending code, so it
      ;must be a code code. So we can now decode the code into a
      ;stack of character codes (Clear as mud, right?).
      code=cc
     
      If code=Slot
        code=TempOldCode
        *lpSP\b=OldCode
        *lpSP+1
      EndIf
     
      ;Here we scan back along the linked list of prefixes, pushing
      ;helpless characters (i.e. suffixes) onto the stack as we do so.
      While code>=NewCodes
        *lpSP\b=suffix(code)
        *lpSP+1
        code=prefix(code)
      Wend
     
      ;Push the last character on the stack, and set up the new
      ;prefix and suffix, and if the required slot number is greater
      ;than that allowed by the current bit size, increase the bit
      ;size. (Note - if we are all full, we *don't* save the new
      ;suffix and prefix. I'm not certain if this is correct,
      ;it might be more proper to overwrite the last code.
      *lpSP\b=code
      *lpSP+1
     
      If Slot<TopSlot
        OldCode=code
        suffix(Slot)=OldCode
        prefix(Slot)=TempOldCode
        Slot+1
        TempOldCode=cc
      EndIf
     
      If Slot>=TopSlot
        If cl\CurrCodeSize<12
          TopSlot=TopSlot << 1
          cl\CurrCodeSize+1
        EndIf
      EndIf
     
      ;Now that we've pushed the decoded string (in reverse order)
      ;onto the stack, lets pop it off and put it into our decode
      ;buffer, and when the decode buffer is full, write another line.
      While *lpSP>@stack(0)
        *lpSP-1
        *lpBuffPtr\b=*lpSP\b
        *lpBuffPtr+1
        BufCnt-1
       
        If BufCnt=0
          GIF_OutLine(lpBUFF,width,height,cl)
          *lpBuffPtr=lpBUFF
          BufCnt=width
        EndIf
      Wend
     
    EndIf
  Wend
 
  If BufCnt<>width ;If there are any left, output the bytes
    GIF_OutLine(lpBUFF,width-BufCnt-1,height,cl)
  EndIf
  *dib=hDIB
  If *dib=0 ;Avoid errors
    ProcedureReturn #False
  EndIf
 
  Protected.i Bits=*dib+*dib\biSize+(*dib\biClrUsed*4) ;Pointer to bits
 
  ;Create the DDB bitmap
  Protected.i hImage=GIF_CreateDIImage(*dib, TransColorIndex)
  Protected.i pbimage=CreateImage(#PB_Any,realwidth,realheight, 32 | #PB_Image_Transparent) ; Create initial "screen"
  StartDrawing(ImageOutput(pbimage))
  DrawingMode(#PB_2DDrawing_AlphaBlend)
  ;Box(0,0,realwidth,realheight,$FFFFFF)
  DrawImage(ImageID(hImage),im\imLeft,im\imTop,im\imWidth,im\imHeight)
  StopDrawing()
  FreeImage(hImage)
  FreeMemory(hDIB)
  ;imageArray(0)=ImageID(pbimage)
  GIF_Frames(0)\Image = pbimage
  GIF_Frames(0)\DelayTime = delaytime
  Protected.l numberimages=1
 
  ;===========================
  ;- continue to other frames
  ;===========================
 
  ; Read through the various image blocks
  Protected NotatEnd=1
  While NotatEnd=1
    TransColorIndex = -1
    Protected.i n
    While n<>$2C
      n=PeekA(*mem + mempos) : mempos + SizeOf(Byte)
      If n=$3B
        NotatEnd=0
        FreeMemory(*mem)
        FreeMemory(lpBUFF)
        ProcedureReturn numberimages
      ElseIf n=$F9
        ;Graphics control extension
        n=PeekA(*mem + mempos) : mempos + SizeOf(Byte)
        Protected.l Size = n
        n=PeekA(*mem + mempos) : mempos + SizeOf(Byte)
        ;Define.b packedfields = n &$FF
        Protected.l disposalmethod = (n & %00011100) >>2
        tflag = n & %00000001
        delaytime = PeekW(*mem + mempos) : mempos + SizeOf(Word)
        transparent = PeekB(*mem + mempos) : mempos + SizeOf(Byte)
        If tflag : TransColorIndex = transparent : EndIf
      ElseIf n=$FF
        ;application extension
      ElseIf n=$FE
        ;comment extention
        n=PeekA(*mem + mempos) : mempos + SizeOf(Byte)
        mempos + n
      ElseIf n= $01
        ;"plain text extention"
        ;Debug "text"
        ; n=ReadByte(file) & 255
        ;FileSeek(file,Loc(file)+n& $FF)
      ElseIf n =$21
        ;"A Extension_block
      EndIf
    Wend
    n=0
   
    ; done with reading the image blocks for this frame
    mempos - SizeOf(Byte)
    count=0
    While count<>$2C ;Search for im\imSep
      count = PeekA(*mem + mempos) : mempos + SizeOf(Byte)
    Wend
    mempos - SizeOf(Byte) ;Seek to im\imSep
    CopyMemory(*mem + mempos, im, SizeOf(im)) ;Read the image descriptor
    mempos + SizeOf(im)
    ;Store im\imPkFields for bit manipulation
    impkFields=im\impkFields & 255
   
    ;Is the image interlaced
    cl\bImInterLace=(impkFields & (1 << 6)) >> 6
   
    ;Is the local color table sorted
    bImColsSorted=(impkFields & (1 << 5)) >> 5
   
    ;Is there a local color table
    bImColTable=(impkFields & (1 << 7)) >> 7
   
    If bImColTable
      cl\bUseGlobalColMap=#False
     
      ImgColBytes=3*(1 << ((impkFields & $07)+1)) ;Table size in bytes
      ImgColors=ImgColBytes/3 ;Number of colors
     
      If ImgColors<=2 ;Make sure image bit depth is 1, 4 or 8
        cl\ImgColRes=1
      ElseIf ImgColors<=16
        cl\ImgColRes=4
      Else
        cl\ImgColRes=8
      EndIf
     
      For count=0 To ImgColors-1 ;Get the local image colors
        Red = PeekA(*mem + mempos) : mempos + SizeOf(Byte)
        Green = PeekA(*mem + mempos) : mempos + SizeOf(Byte)
        Blue = PeekA(*mem + mempos) : mempos + SizeOf(Byte)
        localCols(count)=RGB(Red,Green,Blue)
      Next
      ;loctranscolor=localCols(transparent& $FF)
      ;transcolor=localCols(transparent& $FF)
    Else ;No local color table
      If cl\bUseGlobalColMap=#False ;No global color table
        FreeMemory(*mem)
        Debug "GIF Load Error! The GIF image does not contain a valid color table."
        ProcedureReturn #False ;NO_COLORTABLE
      EndIf
      ;transcolor=GlobalCols(transparent& $FF)
    EndIf
   
    width=im\imWidth & $FFFF ;Image width
    height=im\imHeight & $FFFF ;Image height
   
    ;Get the first byte of the new block of image data.
    ;Should be the bit size
    LZWCodeSize = PeekA(*mem + mempos) : mempos + SizeOf(Byte)
   
    ;Bit size is normally the same as the color resolution.
    ;i.e. 8 for 256 colors
    If LZWCodeSize<2 Or LZWCodeSize>8
      FreeMemory(*mem)
      Debug "GIF Load Error! LZW code size is Not valid!"
      ProcedureReturn #False ;BAD_CODE_SIZE
    EndIf
   
    ;Initialise the variables for the decoder for reading a new image.
    cl\CurrCodeSize=LZWCodeSize+1
    TopSlot=1 << cl\CurrCodeSize ;Highest code for current size
    ClearCode=1 << LZWCodeSize ;Value for a clear code
    EndingCode=ClearCode+1 ;Value for an ending code
    NewCodes=ClearCode+2 ;First available code
    Slot=NewCodes ;Last read code
    cl\BitsLeft=0
    cl\BytesLeft=0
   
    ;Just in case...
    TempOldCode=0 : OldCode=0
   
    ;Allocate space for the decode buffer
    lpBUFF=AllocateMemory(width+8) ;+8 just in case
   
    ;Set up the stack pointer, decode buffer pointer and line counter
    *lpSP=@stack(0)
    *lpBuffPtr=lpBUFF
    BufCnt=width ;Count for pixel line length
   
    ;Start creating the DIB
    If cl\bUseGlobalColMap ;Global color table
      bitcount=cl\GlobColRes
    Else ;Local color table
      bitcount=cl\ImgColRes
    EndIf
   
    bi\biSize=SizeOf(bi)
    bi\biWidth=width
    bi\biHeight=height
    bi\biPlanes=1
    bi\biBitCount=bitcount ;BitCount will be 1, 4 or 8
    bi\biCompression=#BI_RGB
    bi\biSizeImage=0
    bi\biXPelsPerMeter=0
    bi\biYPelsPerMeter=0
    If cl\bUseGlobalColMap ;Global color table
      bi\biClrUsed=GlobColors
    Else ;Local color table
      bi\biClrUsed=ImgColors
    EndIf
    bi\biClrImportant=0
   
    ;With the BITMAPINFO format headers, the size of the palette is
    ;in biClrUsed, whereas in the BITMAPCORE - style headers, it is
    ;dependent on the Bits per pixel (2 to the power of bitsperpixel).
    If bi\biClrUsed<>0
      ncolors=bi\biClrUsed
    Else ;We don't have an optimal palette
      ncolors=1 << bi\biBitCount
    EndIf
   
    cl\pitch=(((bitcount*width)+31) >> 5) << 2 ;Bytes per line
    Len=bi\biSize+(ncolors*4)+(cl\pitch*height) ;Size of DIB
   
    bi\biSizeImage=cl\pitch*height ;Fill in biSizeImage
   
    ;Allocate memory block to store our DIB
    hDIB=AllocateMemory(Len)
    If hDIB=0
      FreeMemory(lpBUFF)
      FreeMemory(*mem)
      Debug "GIF Load Error! Memory allocation failed!"
      ProcedureReturn #False ;NO_DIB
    EndIf
   
    ;Fill first part of DIB with the BITMAPINFOHEADER
    CopyMemory(bi,hDIB,SizeOf(bi))
    ;Set the colors in the DIB (or masks for the new DIB formats)
    *pal=hDIB+SizeOf(bi)
    If cl\bUseGlobalColMap
      For count=0 To bi\biClrUsed-1
        *pal\rgbBlue=Blue(GlobalCols(count))
        *pal\rgbGreen=Green(GlobalCols(count))
        *pal\rgbRed=Red(GlobalCols(count))
        *pal+4
      Next
    Else
      For count=0 To bi\biClrUsed-1
        *pal\rgbBlue=Blue(localCols(count))
        *pal\rgbGreen=Green(localCols(count))
        *pal\rgbRed=Red(localCols(count))
        *pal+4
      Next
    EndIf
   
    cl\Line=0 ;Set address offset for OutLineGIF()
    cl\Pass=0 ;For interlaced images in OutLineGIF()
   
    ;Image data bits of DIB
    cl\lpBits=hDIB+bi\biSize+(ncolors*4)+(cl\pitch*(height-1))
   
    ;This is the main loop. For each code we get we pass through the
    ;linked list of prefix codes, pushing the corresponding "character"
    ;for each code onto the stack. When the list reaches a single
    ;"character" we push that on the stack too, and then start
    ;unstacking each character for output in the correct order.
    ;Special handling is included for the clear code, and the whole
    ;thing ends when we get an ending code.
    cc=0
   
    While cc<>EndingCode
     
      cc=GIF_NextCode(*mem, mempos, @newpos,CharBuff(),CodeMask(),cl)
      mempos = newpos
      If cc<0 ;If a file error, return without completing the decode
        FreeMemory(lpBUFF)
        FreeMemory(*mem)
        Debug "GIF Load Error!GIF image contained an in-valid LZW code."
        ProcedureReturn #False ;FILE_ERROR
      EndIf
     
      ;If the code is a clear code, re-initialise all necessary items.
      If cc=ClearCode
       
        cl\CurrCodeSize=LZWCodeSize+1
        Slot=NewCodes
        TopSlot=1 << cl\CurrCodeSize
       
        ;Continue reading codes until we get a non-clear code
        ;(another unlikely, but possible case...)
        While cc=ClearCode
          cc=GIF_NextCode(*mem, mempos, @newpos, CharBuff(), CodeMask(),cl)
          mempos = newpos
        Wend
       
        ;If we get an ending code immediately after a clear code
        ;(yet another unlikely case), then break out of the loop.
        If cc=EndingCode
          Break ;end loop
        EndIf
       
        ;Finally, if the code is beyond the range of already set codes,
        ;(This one had better not happen, I have no idea what will
        ;result from this, but I doubt it will look good)
        ;then set it to color zero.
        If cc>=Slot
          cc=0
        EndIf
       
        OldCode=cc
        TempOldCode=OldCode
       
        ;And let us not forget to put the char into the buffer, and if,
        ;on the off chance, we were exactly one pixel from the end of
        ;the line, we have to send the buffer to the OutLineGIF() routine
        *lpBuffPtr\b=cc
        *lpBuffPtr+1
        BufCnt-1
       
        If BufCnt=0
          GIF_OutLine(lpBUFF,width,height,cl)
          *lpBuffPtr=lpBUFF
          BufCnt=width
        EndIf
       
      Else
       
        ;In this case, it's not a clear code or an ending code, so it
        ;must be a code code. So we can now decode the code into a
        ;stack of character codes (Clear as mud, right?).
        code=cc
       
        If code=Slot
          code=TempOldCode
          *lpSP\b=OldCode
          *lpSP+1
        EndIf
       
        ;Here we scan back along the linked list of prefixes, pushing
        ;helpless characters (i.e. suffixes) onto the stack as we do so.
        While code>=NewCodes
          *lpSP\b=suffix(code)
          *lpSP+1
          code=prefix(code)
        Wend
       
        ;Push the last character on the stack, and set up the new
        ;prefix and suffix, and if the required slot number is greater
        ;than that allowed by the current bit size, increase the bit
        ;size. (Note - if we are all full, we *don't* save the new
        ;suffix and prefix. I'm not certain if this is correct,
        ;it might be more proper to overwrite the last code.
        *lpSP\b=code
        *lpSP+1
       
        If Slot<TopSlot
          OldCode=code
          suffix(Slot)=OldCode
          prefix(Slot)=TempOldCode
          Slot+1
          TempOldCode=cc
        EndIf
       
        If Slot>=TopSlot
          If cl\CurrCodeSize<12
            TopSlot=TopSlot << 1
            cl\CurrCodeSize+1
          EndIf
        EndIf
       
        ;Now that we've pushed the decoded string (in reverse order)
        ;onto the stack, lets pop it off and put it into our decode
        ;buffer, and when the decode buffer is full, write another line.
        While *lpSP>@stack(0)
          *lpSP-1
          *lpBuffPtr\b=*lpSP\b
          *lpBuffPtr+1
          BufCnt-1
         
          If BufCnt=0
            GIF_OutLine(lpBUFF,width,height,cl)
            *lpBuffPtr=lpBUFF
            BufCnt=width
          EndIf
        Wend
       
      EndIf
     
    Wend
   
    If BufCnt<>width ;If there are any left, output the bytes
      GIF_OutLine(lpBUFF,width-BufCnt-1,height,cl)
    EndIf
   
    ;Create the DDB bitmap
    *dib=hDIB
    If *dib=0 ;Avoid errors
      ProcedureReturn #False
    EndIf
   
    Bits=*dib+*dib\biSize+(*dib\biClrUsed*4) ;Pointer to bits
   
    ;- create the bitmap
    ;Create the DDB bitmap
    hImage = GIF_CreateDIImage(*dib, TransColorIndex)
    pbimage=CreateImage(#PB_Any,realwidth,realheight, 32 | #PB_Image_Transparent)
    StartDrawing(ImageOutput(pbimage))
    DrawingMode(#PB_2DDrawing_AlphaBlend)
    ; For some retarded reason, we have to draw and redraw the GIF frames over the previous image imagenumber-1
   
    ;   If bUseGlobalColMap ; if a local color table, then draw previous image in array, and then dray new hbitmap with transparency
    ;     Box(0,0,realwidth,realheight,$FFFFFF)
    ;     DrawImage(imageArray(numberimages-1),0,0)
    ;     If tflag=1
    ;       ;loc
    ;       DrawTransparentImage(drawdc,hBitmap,im\imLeft,im\imTop,im\imWidth,im\imHeight,transcolor)
    ;     Else
    ;       DrawImage(hBitmap,im\imLeft,im\imTop,im\imWidth,im\imHeight)
    ;     EndIf
    ;   Else
   
    If disposalmethod = 1
      ;Box(0,0,realwidth,realheight,$FFFFFF)
      DrawImage(ImageID(GIF_Frames(numberimages-1)\Image),0,0)
      DrawImage(ImageID(hImage),im\imLeft,im\imTop,im\imWidth,im\imHeight)
    ElseIf disposalmethod = 2
      ;Box(0,0,realwidth,realheight,$FFFFFF)
      ;DrawImage(ImageID(GIF_Frames(1)),0,0)
      DrawImage(ImageID(hImage),im\imLeft,im\imTop,im\imWidth,im\imHeight)
    Else
      ;Box(0,0,realwidth,realheight,$FFFFFF)
      DrawImage(ImageID(GIF_Frames(numberimages-1)\Image),0,0)
      ;DrawImage(hBitmap,im\imLeft,im\imTop)
      DrawImage(ImageID(hImage),im\imLeft,im\imTop,im\imWidth,im\imHeight)
    EndIf
    ;   EndIf
    StopDrawing()
    FreeImage(hImage)
    FreeMemory(hDIB) ;Free the DIB
    ReDim GIF_Frames(numberimages)
    GIF_Frames(numberimages)\Image = pbimage
    GIF_Frames(numberimages)\DelayTime = delaytime
    numberimages + 1
  Wend
  FreeMemory(*mem)
  ProcedureReturn numberimages
EndProcedure

[example1.pb]
Code:
EnableExplicit
XIncludeFile "GIFanimation.pbi"

Define.w a
Dim Frames.GIF_Frame(0)

OpenWindow(0, 0, 0, 800, 600, "Gif_Test", #PB_Window_SystemMenu|#PB_Window_ScreenCentered|#PB_Window_SizeGadget|#PB_Window_MaximizeGadget)
ButtonGadget(0,10,10,80,20,"Open File")
ImageGadget(1,50,50,0,0,0, #PB_Image_Border)

AddWindowTimer(0, 0, 100)

Repeat
  Select WaitWindowEvent()
    Case #PB_Event_Gadget
      Select EventGadget()
        Case 0
          Define.s Pattern="All Supported Formats|*.gif"
          Define.s filename=OpenFileRequester("Choose An Image File To Open","",Pattern,0)
          If filename
            If GIF_LoadFrames(Frames(), filename)
              ResizeGadget(1, #PB_Ignore, #PB_Ignore, ImageWidth(Frames(0)\Image), ImageHeight(Frames(0)\Image))
              ;SetGadgetState(0, ImageID(Frames(0)\Image))
            EndIf
          EndIf
      EndSelect
     
    Case #PB_Event_CloseWindow
      Break
     
    Case #PB_Event_Timer
      RemoveWindowTimer(0, 0)
      If a > ArraySize(Frames()) : a = 0 : EndIf
      If IsImage(Frames(a)\Image)
        SetGadgetState(1, ImageID(Frames(a)\Image))
        AddWindowTimer(0, 0, Frames(a)\DelayTime * 10)
      Else
        AddWindowTimer(0, 0, 100)
      EndIf
      a + 1   
  EndSelect
 
ForEver

[example2.pb] catches from memory
Code:
EnableExplicit
XIncludeFile "GIFanimation.pbi"

Dim Frames.GIF_Frame(0)
Define i, count

If GIF_LoadFrames(Frames(), "", ?Loading2_gif_start, 7998)
  count = ArraySize(Frames())
  OpenWindow(0, #PB_Ignore, #PB_Ignore, ImageWidth(Frames(0)\Image) + 20, ImageHeight(Frames(0)\Image) + 20, "")
  ImageGadget(0, 10, 10, ImageWidth(Frames(0)\Image), ImageHeight(Frames(0)\Image), ImageID(Frames(0)\Image))
  AddWindowTimer(0, 1, Frames(0)\DelayTime * 10)
 
  i = 0
  Repeat
    Select WaitWindowEvent()
      Case #PB_Event_CloseWindow
        Break
       
      Case #PB_Event_Timer
        Select EventTimer()
          Case 1
            SetGadgetState(0, ImageID(Frames(i)\Image))
            i + 1
            If i > count : i = 0 : EndIf
        EndSelect
    EndSelect
  ForEver 
EndIf

DataSection
  Loading2_gif_start:
    ; size : 7998 bytes
    Data.q $00A0613938464947,$7C7E7C0000F20014,$8A8CACAAACECEAEC,$F4848684FCFEFC8C,$04F9218C8E8CF4F2
    Data.q $0BFF210004000709,$455041435354454E,$0000000103302E32,$1400A0000000002C,$FEDCBA48FE030000
    Data.q $CDEB38BDAB49CA30,$9E69648E2860FFBB,$2C70BEEB6CAEAA68,$364860871C219BCF,$0213D22EDCB7F3AE
    Data.q $95320C47F148437D,$812350752963E4CE,$EC90020C0000A001,$43F05EB96B0DFBB6,$1D83B564CFAF2E8C
    Data.q $C741BCB6F6D38F37,$00845D020E6EEFBF,$8B8A888685831002,$82928D8F8785890F,$9A84900D958A8C94
    Data.q $0E8EA00B9E5D9C0C,$0FA95CA710036370,$B368B1AC77AA5EAB,$B8A6B9B5B7B0B2AE,$0CC2AF0DBFBBBDAD
    Data.q $C985CAC8B1058A5A,$BDCE84CCCDCFCBB7,$D55DD3D4D1D2D6D0,$5C5C890AA263DD9B,$DFA5E598E1E404E2
    Data.q $9FEDEF93EAEBE663,$73F8E9E7ECF3F0E0,$CFF3E205087F75C7,$B81188190342BF8F,$3C02160B84C16147
    Data.q $08AD1380C54ED0C8,$1D8D94C9E0343018,$92C6A3D1C1B034AB,$4B6504090C901922,$26450984C65C4D96
    Data.q $B3C9DCEA73389B8D,$4A1D0A83409FCFA7,$0000121AA3D1A8B4,$001300070904F921,$1400A0000000002C
    Data.q $8486840402048400,$AAACDCDADC4C4A4C,$F46C6A6C343234AC,$B4B2B45C5E5CF4F2,$E6E48C8E8C141614
    Data.q $548C8A8C3C3E3CE4,$343634ACAEAC5452,$62640000007C7E7C,$EC1C1A1CB4B6B464,$000000000000ECEA
    Data.q $0000000000000000,$0000000000000000,$648E24E0FE050000,$BEEB6CAEAA689E69,$AE78DF6D74CF2C70
    Data.q $62214315D3EF7CEF,$00506DA4C88EFCA8,$8EAD4A728B8F9F38,$BF5818A016A78A06,$900E9C2DAB735E60
    Data.q $776CD5A1507082C5,$1D7872E9BD4EDD7A,$7B807C7EE7DB8F75,$2509646409268367,$27520E018F120E17
    Data.q $9095269391128F8D,$9C8E949D979B2892,$989F24A5A0A38C99,$0823AF96A2ACA79E,$0496900425085B89
    Data.q $BC8FBABDBB97B928,$C412C2C5C001BE27,$D1B8CCCACDC8C626,$115AB50D25C3BFC1,$E08FDE280E96A725
    Data.q $DDE8E626E412E227,$EBF0EFE3EDE1DF96,$4EDAD9F4EDF2EA24,$0A5D8EF790B1F5DC,$05850681BFDCB008
    Data.q $AD0985C1DD308820,$007DAD04B0A87441,$8DB498F025C8916E,$C9193228EB059712,$422942EA387D238F
    Data.q $B91C7A5C13962FE5,$3042308812CBE692,$8A7CE74F88D52F85,$BF3CA2B7934A1A00,$3D56D36974409D09
    Data.q $131996A631352AA1,$88A9604070380807,$EBD5CAD1BABB5BAC,$568B3586C765B004,$3B65C0F96EB21DAC
    Data.q $DDE8C25D5A9604F7,$0AF80C011909834B,$100502820202EC1E,$90C7E3B1B8CC24EC,$10DF32B94C9E4B23
    Data.q $1D00070904F92100,$00A0000000002C00,$8684040204840014,$2CDCDADC4C4A4C84,$6C6A6CACAAAC2C2E
    Data.q $3A3C141614F4F2F4,$B45C5E5C8C8E8C3C,$E4E6E40C0E0CB4B2,$0604FCFAFC343634,$345452548C8A8C04
    Data.q $7C7E7CACAEAC3432,$92943C3E3C1C1A1C,$ECB4B6B464626494,$000000000000ECEA,$8E2760FE05000000
    Data.q $EB6CAEAA689E6964,$78DF6D74CF2C70BE,$818DA5FFEF7CEFAE,$0472A4C8806C30F2,$1A72064C112260C9
    Data.q $7AECB384ECD80050,$0694714B166B8E6F,$2CDFBAF83118F188,$3A624750259D4108,$07051914543A7096
    Data.q $83817F8482807E2A,$8D288B86888A8529,$2491969294898C87,$639D0C2319597A19,$1216A816121C250C
    Data.q $AE26ACAAA9A6275C,$A7ADB5A8B328ABA9,$B724BDB8BBA5B1B4,$00A21825C4BFB6B0,$05250B58CA0B2309
    Data.q $27D6D4D32805A8AF,$D2DEA9DC26DAAFD8,$E4D7D5E024E216D4,$11CA1126E5E823E6,$A801A7250FCFC923
    Data.q $59FCAAFBF92812FA,$FB057F89E03037D0,$0E7E412050982C1D,$7889621081342A01,$891EE0067BD01AA2
    Data.q $6192281C02050F5F,$A93C8E17B2219280,$4896492F7DCA24D2,$9DA2CF670763CCA0,$D53D70089D8FA57B
    Data.q $43A2BBE78DBA0AA5,$A55003B3EA337E8F,$8893EA24E3B292E3,$164B9862F82ACF50,$35F61582095BAEC2
    Data.q $0B408ACD625708D8,$231ED81DB55718AC,$F144734D0113A721,$E005090480A07131,$80BF213037FBE88A
    Data.q $C56170F89C207705,$6512592C42330D8C,$048660218EF20EB8,$025D1E88E06C4E9A,$A339DC14097A8282
    Data.q $66CB63A4CE808B39,$CEB40B0A05016151,$83C0DFEFB7BBCDDE,$21000847BC4E1F0B,$2C001400070904F9
    Data.q $001400A000000000,$4484868404020485,$2C2E2CD4D2D44442,$6264ACAAACECEAEC,$F43C3A3C14121464
    Data.q $5452548C8E8CF4F6,$7A7CB4B2B4E4E6E4,$34DCDADC0C0E0C7C,$0000001C1A1C3436,$4A4C8C8A8C040604
    Data.q $F4343234D4D6D44C,$6C6A6CACAEACF4F2,$FAFC3C3E3C141614,$B45C5E5C949294FC,$0000007C7E7CB4B6
    Data.q $0000000000000000,$0000000000000000,$0000000000000000,$0000000000000000,$0000000000000000
    Data.q $0000000000000000,$0000000000000000,$0000000000000000,$0000000000000000,$0000000000000000
    Data.q $2C48708A40FE0600,$3A6CC972A4C88F1A,$AF5AAD4A74A8D09F,$55BF7AEDCB76ACD8,$74E8C088E1232711
    Data.q $454A82407E598236,$CF7E8019231CFA00,$7A08204C80FFA828,$047A7B790D481608,$111D8B8B1D11450D
    Data.q $0200920214979681,$8A43768C9B041F46,$200B1B1A470400A1,$ABB0AEACAA4A1A06,$B7B2B4B6B149AFAD
    Data.q $1646C0B5B8B3B948,$43207AA6204487A6,$231605450E7BCA0E,$D7D6D3477E1623D5,$D5E048D8D6DB46D9
    Data.q $E5E8D2DEE1D4DAE2,$08A18447DDE444EA,$7ACF214309CF1E45,$024019AADC064521,$341DB90523C0E030
    Data.q $3C47017FC2DAD092,$291388C12050D224,$1567854869567844,$00B508A127E3DC86,$CB650236231E50D5
    Data.q $E6447984A64E486B,$53A98CDE5F2695CB,$24711F3E974FE125,$9400FC91041951F2,$533C9683C02EC224
    Data.q $4EAAD4E5B5100D3E,$A956EA9596B4D6A1,$A6DE645AF582595A,$1F614A5B3C1244A3,$A428CD39B9147F3F
    Data.q $60A5D01F5C8BDCE1,$9606FB7BA95E2F57,$248A0F5303C8D7EB,$D61B7E33884CC653,$276FB9B26E778D59
    Data.q $CCBBF3759C965E9F,$675B6437765B3194,$41409495A83E14D2,$4A021EB808A64F91,$30B0580C1A232A19
    Data.q $EEEF7CBDDE6E952C,$0787B922F137FB8D,$0245E5F1961CAE2F,$8BDA8348B64083CC,$EFA623AF448A3D1A
    Data.q $826460B3700C067F,$11C023DF611FB305,$2191086CA7F0F7F8,$CFDFEBF3F1688843,$A0280600FFFFBFBF
    Data.q $0904F9210000411A,$0000002C00140007,$020485001400A000,$D444424484868404,$ECEAEC2C2E2CD4D2
    Data.q $1214646264ACAAAC,$8CF4F6F43C3A3C14,$E4E6E45452548C8E,$0E0C7C7A7CB4B2B4,$1C343634DCDADC0C
    Data.q $0406040000001C1A,$D6D44C4A4C8C8A8C,$ACF4F2F4343234D4,$1416146C6A6CACAE,$9294FCFAFC3C3E3C
    Data.q $7CB4B6B45C5E5C94,$0000000000007C7E,$0000000000000000,$0000000000000000,$0000000000000000
    Data.q $0000000000000000,$0000000000000000,$0000000000000000,$0000000000000000,$0000000000000000
    Data.q $0000000000000000,$FE06000000000000,$C88F1A2C48708A40,$A8D09F3A6CC972A4,$76ACD8AF5AAD4A74
    Data.q $9388A2E0BF7AEDCB,$C11ADAB4E1447091,$7D0022A541203F2C,$D61467CF600C918E,$16087B0820498180
    Data.q $450D047B7C7A0D48,$9782111D8C8C1D11,$491A06200B1B1A58,$A2041F4602009302,$470400A88B43778D
    Data.q $499F9DB14A9E9C9A,$BABCB4B69BB8B3B5,$C723160547B7B948,$4488AD16467F1623,$7CD20E43207BAD20
    Data.q $DB46CBC9C8C5450E,$C6C4E2C7E048CAC8,$E444EAE5E8DADEE1,$854706C7DC0648DD,$214309D71E4508A8
    Data.q $BD9E8F322884F6D7,$D91092341DB90523,$B0D2243C46F48242,$700B18871388BC9E,$1A59AE112233E38C
    Data.q $4A02FC21855AE152,$472D243263B1B228,$359647E5D3298478,$91E2E6731224DE6B,$A640F00B227F2F9E
    Data.q $0D29290A46D29091,$5A1CF2560080CA02,$CCCAAF558ECD0034,$32BF5BAED1AB142A,$F0148CD522162AA3
    Data.q $14A935C1244A7289,$B4511B91481C0600,$562F9678BDDE1A14,$DC782BB6001F7ABC,$A0F5683C8AE6A2C6
    Data.q $B80B5884D4693448,$3BC68996C4D85D61,$BF319A6D90DDD977,$3444D1691BF9BC3B,$6E0F91580160B018
    Data.q $022A14FAF0502527,$6A88CAF56ED887B4,$D60C3D6EAF7DAED6,$BC75A7137E45E0F0,$07C004ABCEE070B8
    Data.q $8238F9BB0691EAC1,$0CD5E04C529F2924,$720B04CA4166F018,$F0F0A3C047BECA43,$1086432210D94FE3
    Data.q $FFBFBFCFDFEBE4D9,$045380E0280600FF,$00070904F9210001,$A0000000002C0014,$8404020485001400
    Data.q $D4D2D44442448486,$AAACECEAEC2C2E2C,$3C141214646264AC,$8C8E8CF4F6F43C3A,$B2B4E4E6E4545254
    Data.q $DC0C0E0C7C7A7CB4,$1C1A1C343634DCDA,$8A8C040604000000,$34D4D6D44C4A4C8C,$ACAEACF4F2F43432
    Data.q $3E3C1416146C6A6C,$5C949294FCFAFC3C,$7C7E7CB4B6B45C5E,$0000000000000000,$0000000000000000
    Data.q $0000000000000000,$0000000000000000,$0000000000000000,$0000000000000000,$0000000000000000
    Data.q $0000000000000000,$0000000000000000,$0000000000000000,$8A40FE0600000000,$72A4C88F1A2C4870
    Data.q $4A74A8D09F3A6CC9,$EDCB76ACD8AF5AAD,$70919388AAE0BF7A,$3F2CC11ADAB4E144,$918E7D0022A54120
    Data.q $8180D61467CF600C,$0D4816087B082049,$1D11450D047B7C7A,$1A489782111D8C8C,$9C9A4A1A06200B1B
    Data.q $1F4602009302499E,$00AC8B43778DA604,$A3B5499F9DA14704,$BF99BABCA0B69BB8,$1623C723160547B7
    Data.q $B11647CAC8C6C47F,$0E43207BB1204488,$CBC9C8C5450E7CD6,$CFC7CDDEE2CEDF46,$0648E1E8E3EAE0CC
    Data.q $46F523F3F106C7E0,$8609DB1E4508AC85,$F379114427B6D884,$7BC1E14E084119F2,$44C871164430890E
    Data.q $9A71B638058C487A,$CDB08919931C8D11,$47F90C2ADB0A90D2,$8C663A2390114250,$126D349A4BE3D219
    Data.q $1F9ECEDE1A132981,$A247267310780591,$841AD28224964601,$A91429DCB8010495,$15AA2D1E7D5698D1
    Data.q $38991E935BA0D72B,$33EECC0FB210A2B4,$0C29536D824894F5,$AAF6B2B822506824,$47BCDF6F7680A59A
    Data.q $76E11D6F0A1B7EF7,$359AA4507AC41E44,$2BCE70DC11B4426C,$B9921E5E89832262,$1CD46B30E6CB3BB0
    Data.q $A3002C160306889A,$4EDE1F22B0F55A85,$6A04562AF600A04A,$A9D391966B1DB90F,$D77008BC2D6EFF57
    Data.q $A0397C1E1EBF88A0,$3780D2358820FB00,$A98933F12490471F,$99602CDE03019AFB,$7808F7D6486E8160
    Data.q $64421B29FBBDBDE4,$F3F8FBFBDBA210C8,$00FFFFBFBFCFDFEB,$0904F9210004110E,$0000002C00140007
    Data.q $020485001400A000,$D444424484868404,$ECEAEC2C2E2CD4D2,$1214646264ACAAAC,$8CF4F6F43C3A3C14
    Data.q $E4E6E45452548C8E,$0E0C7C7A7CB4B2B4,$1C343634DCDADC0C,$0406040000001C1A,$D6D44C4A4C8C8A8C
    Data.q $ACF4F2F4343234D4,$1416146C6A6CACAE,$9294FCFAFC3C3E3C,$7CB4B6B45C5E5C94,$0000000000007C7E
    Data.q $0000000000000000,$0000000000000000,$0000000000000000,$0000000000000000,$0000000000000000
    Data.q $0000000000000000,$0000000000000000,$0000000000000000,$0000000000000000,$FE06000000000000
    Data.q $C88F1A2C48708A40,$A8D09F3A6CC972A4,$76ACD8AF5AAD4A74,$C45130E0BF7AEDCB,$8D3D7AB1223848C9
    Data.q $801152A0901F9660,$0A33EFC00648C73E,$087C08204682816C,$0D047C7D7B0D4816,$83111D8D8D1D1145
    Data.q $4A1A06200B1B1A5F,$489F9D9BA09E9C9A,$AA041F4602009402,$470400B08C43788E,$A3B948A7A2A4A6A1
    Data.q $C723160546BDBF49,$CBC9C8C547801623,$89B51647CAC8C6C4,$DB0E43207CB52044,$D2E3D0D3CD450E7D
    Data.q $E9E448CFE8CCD4C7,$F34806C7CE0644E6,$8645FACEF847F6F4,$90C12E00F11410B0,$990FC22884F8E010
    Data.q $7117943C46F4863F,$700B1890F58690E2,$D3263B1B2336238C,$5DC09191C9638238,$130421855C01521A
    Data.q $279A47E4F212284A,$C8E2A771E934926D,$6492507805D0449B,$246A44968C01A247,$998041B72D224A82
    Data.q $AD1686C8A0CCC010,$76415BA3D7299596,$870D2145ABB10B0D,$AA8059C1F690A59E,$84052AEE004912A6
    Data.q $DA99CF7B34521709,$236EEB75F9F77CBE,$18A75BB696D17551,$B6D1141EB5079131,$6B9C37096F909BAD
    Data.q $7C898EAD33486F1C,$0CB8C5E8C859DC3E,$C3D66A97CC00B058,$BA07C8BADD78688C,$81160AFDB0281294
    Data.q $769B25BAD77A43DD,$FCAE2ED757B322EC,$00094531B0E49138,$79F7840D23D24210,$8BC3D295C0526914
    Data.q $16099882CE003019,$E248008F9DA48F00,$0C864421B287CBE3,$FFBFBFCFDFCDC421,$046180E0280600FF
    Data.q $00070904F9210001,$A0000000002C0014,$8404020485001400,$D4D2D44442448486,$AAACECEAEC2C2E2C
    Data.q $3C141214646264AC,$8C8E8CF4F6F43C3A,$B2B4E4E6E4545254,$DC0C0E0C7C7A7CB4,$1C1A1C343634DCDA
    Data.q $8A8C040604000000,$34D4D6D44C4A4C8C,$ACAEACF4F2F43432,$3E3C1416146C6A6C,$5C949294FCFAFC3C
    Data.q $7C7E7CB4B6B45C5E,$0000000000000000,$0000000000000000,$0000000000000000,$0000000000000000
    Data.q $0000000000000000,$0000000000000000,$0000000000000000,$0000000000000000,$0000000000000000
    Data.q $0000000000000000,$8A40FE0600000000,$72A4C88F1A2C4870,$4A74A8D09F3A6CC9,$EDCB76ACD8AF5AAD
    Data.q $48C9C45530E0BF7A,$96608D3D7AB12238,$C73E801152A0901F,$816C0A33EFC00648,$4816087C08204682
    Data.q $11450D047C7D7B0D,$1A4F83111D8D8D1D,$9C9A4A1A06200B1B,$A6A1499F9D9BA09E,$041F460200940249
    Data.q $0400B38C43788EAD,$BC48BDA5A8A3A947,$1623C723160547A7,$C8C548CAC8C6C480,$1644D4CED146CBC9
    Data.q $43207CB8204489B8,$CFC7D6450E7DDF0E,$44D8E9CDD5EAD2CC,$F6F4F34806C7D206,$FCC8FC46FAD2F847
    Data.q $E40F11410B343111,$22884F8E41090C12,$3CA04237A3DDEB00,$238C700B1887168A,$721243263B1B2337
    Data.q $121C7E4526924784,$1855C81521A5DC81,$1E4F252284A1B082,$2B94CADF677239C9,$8ECA24C0F00B21B3
    Data.q $51297499351C0345,$020DF989125C91A3,$150A450A6E0086CD,$27DD2AB93EA6D0E4,$FC4ECD002146688D
    Data.q $B6096707DA42967A,$1814AD3901244AB2,$6DA45AED91787C36,$8DB9DDB4F68DB6DF,$10DE389C21130D45
    Data.q $88A0F5C03C8ED3C6,$E1B86B8C84E16FB7,$02163B0AEBC8D330,$00582C060D113159,$B355AD61EAF52BB6
    Data.q $EC1F226C365A8236,$045C2C48A0A04A52,$D76D174DF5910F7A,$6DF90A0D7ED48BB3,$48D6308410025C4C
    Data.q $F0549A451E8DE203,$B3800C0662EFF425,$EF6123C2058266A0,$6CA1F0F7F8120023,$F3F1730843219108
    Data.q $00FFFFBFBFCFDFEB,$04F9210010451806,$00002C0014000709,$0485001400A00000,$4442448486840402
    Data.q $EAEC2C2E2CD4D2D4,$14646264ACAAACEC,$F4F6F43C3A3C1412,$E6E45452548C8E8C,$0C7C7A7CB4B2B4E4
    Data.q $343634DCDADC0C0E,$06040000001C1A1C,$D44C4A4C8C8A8C04,$F4F2F4343234D4D6,$16146C6A6CACAEAC
    Data.q $94FCFAFC3C3E3C14,$B4B6B45C5E5C9492,$00000000007C7E7C,$0000000000000000,$0000000000000000
    Data.q $0000000000000000,$0000000000000000,$0000000000000000,$0000000000000000,$0000000000000000
    Data.q $0000000000000000,$0000000000000000,$0600000000000000,$8F1A2C48708A40FE,$D09F3A6CC972A4C8
    Data.q $ACD8AF5AAD4A74A8,$58B0E0BF7AEDCB76,$CD78D11C2464E228,$A950480FCB304686,$FBE80324639F4008
    Data.q $08204383826D0519,$7D7E7C0D4816087D,$1D8E8E1D11450D04,$1A06200B1B1A8211,$9F9D9BA09E9C9A4A
    Data.q $0247A7A2A4A6A149,$8FB0041F46020095,$A9470400B68D4379,$23160547C0A5A8A3,$CAC8C6C4811623C7
    Data.q $CED146CBC9C8C548,$BB1646CFC7D645D4,$0E43207DBB20448A,$44D8DBCDD90E7EE3,$F206C7D20648D3DA
    Data.q $46FAF4F347F623F4,$E04C880115FCD2FC,$2E80F11410B64390,$881884FAE81090C1,$0B1890F58210E0CF
    Data.q $8638236EB8238C70,$36458FC8E471A64C,$112349E544792476,$21855D01521A61D0,$E263D269484A230C
    Data.q $20F00B225B3E9149,$990D1C03458EC964,$25429142A3512974,$41C735214CDC7312,$9EEC224EC01119C0
    Data.q $0FA1C52A74CA8D2A,$B6052D5448210A2C,$422D570B75A1EF69,$0295F74024895B58,$D48B95D4891388C4
    Data.q $9A2C6DAADCA7B46D,$63C716EFC6D95D78,$141EBB07909DD8F6,$371173909CAE3711,$A5C661C8596C4638
    Data.q $5F30C2C160306885,$91B5FADD82B75DAC,$C87B6D8EDF67B5D5,$6B4228281295BD87,$B5EB8D6A43E18117
    Data.q $174909BADE28373B,$281A46B184210012,$A75784A512490477,$39059C406032FF8B,$011FBB692E402C13
    Data.q $884364DF9FCBC691,$BFBFCFA3A842190C,$F480E0280600FFFF,$070904F921000105,$000000002C001400
    Data.q $04020485001400A0,$D2D4444244848684,$ACECEAEC2C2E2CD4,$141214646264ACAA,$8E8CF4F6F43C3A3C
    Data.q $B4E4E6E45452548C,$0C0E0C7C7A7CB4B2,$1A1C343634DCDADC,$8C0406040000001C,$D4D6D44C4A4C8C8A
    Data.q $AEACF4F2F4343234,$3C1416146C6A6CAC,$949294FCFAFC3C3E,$7E7CB4B6B45C5E5C,$000000000000007C
    Data.q $0000000000000000,$0000000000000000,$0000000000000000,$0000000000000000,$0000000000000000
    Data.q $0000000000000000,$0000000000000000,$0000000000000000,$0000000000000000,$40FE060000000000
    Data.q $A4C88F1A2C48708A,$74A8D09F3A6CC972,$CB76ACD8AF5AAD4A,$E22A58B0E0BF7AED,$4686CD78D11C2464
    Data.q $4008A950480FCB30,$0519FBE80324639F,$087D08204383826D,$0D047D7E7C0D4816,$57111D8E8E1D1145
    Data.q $9A4A1A06200B1B1A,$A1499F9D9BA09E9C,$48A3A948A7A2A4A6,$B3041F4602009502,$470400B98D43798F
    Data.q $23C723160546ADAF,$C4CBC9C8C5478116,$45D0D3CD48CAC8C6,$43D8DBD2CCD4C7D6,$207DBE20448ABE16
    Data.q $CFDED90E7EE70E43,$23F4F206C7CE0648,$CEFC46FAF4F347F6,$8211204C880115FC,$0788A085CA1C8EF5
    Data.q $C427D76084860976,$8C70088DC3067C40,$864C6E38C6233923,$FC8E4C4792476424,$1A572392C7A54458
    Data.q $2AEC0A90D30EC089,$98CBDF425148790C,$CC2360F00B22532F,$297498DD1C03458E,$B43905429142A351
    Data.q $B0839E70449AA4A9,$553DBC449F002293,$9E08428CD119CFBA,$DC0FB5052D1557BD,$5C5F42AE366B95C2
    Data.q $8A44C29607602489,$B729ECDB75D60F16,$1DF87C4B75E34C68,$444C6D170A437063,$62283D7C0F22E2B2
    Data.q $706E28EB213A5CEE,$582C060D10F2186C,$504661EAF52AE580,$B6D8ED35CC1D66AB,$BD87C91AFD911761
    Data.q $8117CB7228281295,$B67B86039D7043E1,$81085804A3D0426E,$4492411DCA0691AC,$180CC1E0E8CDA189
    Data.q $4B900B04CF016710,$E3F0F0A44047EECA,$EE1086432210D937,$FFFFBFBFCFDFEBE4,$F921001046080600
    Data.q $002C001400070904,$85001400A0000000,$4244848684040204,$EC2C2E2CD4D2D444,$646264ACAAACECEA
    Data.q $F6F43C3A3C141214,$E45452548C8E8CF4,$7C7A7CB4B2B4E4E6,$3634DCDADC0C0E0C,$040000001C1A1C34
    Data.q $4C4A4C8C8A8C0406,$F2F4343234D4D6D4,$146C6A6CACAEACF4,$FCFAFC3C3E3C1416,$B6B45C5E5C949294
    Data.q $000000007C7E7CB4,$0000000000000000,$0000000000000000,$0000000000000000,$0000000000000000
    Data.q $0000000000000000,$0000000000000000,$0000000000000000,$0000000000000000,$0000000000000000
    Data.q $0000000000000000,$1A2C48708A40FE06,$9F3A6CC972A4C88F,$D8AF5AAD4A74A8D0,$B0E0BF7AEDCB76AC
    Data.q $78D11C2464E22C58,$50480FCB304686CD,$E80324639F4008A9,$204383826D0519FB,$7E7C0D4816087D08
    Data.q $8E8E1D11450D047D,$06200B1B1A47111D,$9D9BA09E9C9A4A1A,$48A7A2A4A6A1499F,$950247B0A5A8A3A9
    Data.q $798FB6041F460200,$1605460400BC8D43,$C8C547811623C723,$CD48CAC8C6C4CBC9,$D2CCD4C7D645D0D3
    Data.q $C11647CFDA44D8DB,$0E43207DC120448A,$06C7CE06450E7EEA,$FACEF847F6F4F348,$4237A3C9FCC8FC46
    Data.q $283411EEF5801120,$4BBC3C45042F10E4,$188A213EBBC42430,$3B1B2339E38C700B,$2692478472124326
    Data.q $224AE53298D47E45,$844893296B924F25,$8861577854869877,$607C7658128BC4E2,$30068F33A2D0E512
    Data.q $82914DA4D2E8926A,$8752AAD329C01644,$10754EC8539754DC,$AAB3A0F410045E7C,$83EA90AB4400850C
    Data.q $AE143B6DBED614B4,$2B68711AE767BB5C,$78B052CAEF04912C,$8B45B9448DB86331,$8318DD71E21B38AA
    Data.q $AB92C3E36B0CD21B,$4507B041E42CBE3D,$0DC5DDC42763A9D2,$A6566160B0183446,$353AED66BD5BADD5
    Data.q $7B6D96D35445DAEC,$5C007C87BCDBA837,$381182BA22828129,$4908BE023A97643E,$1A46A78421C0130F
    Data.q $5D87A51249047738,$059C406032FF8BA7,$1FBB692E602C133F,$4364DF9FCBC69101,$BFCFA3C442190C88
    Data.q $80E0280600FFFFBF,$0904F92100010450,$0000002C000E0007,$020484001400A000,$44D4D2D484868404
    Data.q $2C2E2CECEAEC4442,$0E0CF4F6F4ACAAAC,$3CE4E6E48C8E8C0C,$7C7A7CDCDADC3C3A,$8A8C040604000000
    Data.q $34F4F2F4D4D6D48C,$141214FCFAFC3432,$7E7C3C3E3C949294,$000000000000007C,$0000000000000000
    Data.q $FE05000000000000,$AA689E69648E23A0,$74CF2C70BEEB6CAE,$FFEF7CEFAE78DF6D,$8C851A2C4870A0C0
    Data.q $0B031E3C19628AC8,$A000152CC6AD48E5,$A0A030DA26294102,$3AA2418B090C4940,$CF729D9AB46DD7A7
    Data.q $F5F3AF0E59BA6FE3,$035A6203277D7627,$2553056186051426,$2804101893181004,$9694992797959491
    Data.q $A0939E269C9F9298,$A19BAA90A4A7A29D,$245D5A8C1025A89A,$011806261661B516,$18BFC0BE2806C093
    Data.q $C7C7C4C8C1C527C3,$CAD4C6CEC2CFBDC9,$B55925DAD6D8CDD3,$AE260B5ABA172515,$27E99AEA95E828A7
    Data.q $F2F4F0ECEEE7B7EB,$E40C22F8EEEDF7B3,$0981F00078901800,$80308142FC1ABF63,$A2785C39290C00C2
    Data.q $A894562EC188C3E1,$1C82331E8A4720F1,$C9A60411C09C8FF1,$C512B461D1369021,$9A4266224978361E
    Data.q $08A71326ACBA6C23,$C4D3BA14DE79339D,$A138002C492B4637,$4A8C655AB2872894,$A0369F55565413C2
    Data.q $72B55DAC56EAC23A,$1D60B283AC75E115,$BC722E44A0D5D034,$0320506100819C4C,$DED0175BC5CAED74
    Data.q $70071BEDCC4B7EBC,$D4B0A09F0C7EC261,$002AE914250382D0,$437C0225CBE58AD9,$60C886458284F100
    Data.q $C6092580805A4D1E,$B0D7E932A0905801,$DBEDB6BB4D9ECB63,$F921000108B373B8,$002C000B00070904
    Data.q $84001400A0000000,$D2D4848684040204,$F4444244ECEAECD4,$3C3E3CACAAACF4F6,$7A7CDCDADC8C8E8C
    Data.q $8C1412140000007C,$F4F2F4D4D6D48C8A,$00007C7E7CFCFAFC,$0000000000000000,$0000000000000000
    Data.q $0000000000000000,$0000000000000000,$0000000000000000,$9E69648E22E0FE05,$2C70BEEB6CAEAA68
    Data.q $7CEFAE78DF6D74CF,$1A2C4870A0C0FFEF,$11066CC90384AB8F,$080C3D50D180000C,$6BA9B96AC561E184
    Data.q $596FE251831DDB76,$44FBF5E6DB92F61D,$0911A0D40401DA90,$807E7C7A030D2244,$8A83817F7D7B2782
    Data.q $878B84888C858D86,$9095982596918926,$06265577770D269D,$A9A8A6280611A77F,$B2AAA8AC27AEADAB
    Data.q $25B8ADAFB7A5B5B0,$22C17FBF24BDA7B3,$A48A94270C52A251,$28D1CC25CE7E8EA0,$D2DACBD8D0D680D4
    Data.q $D585D9E023DED724,$01ADCF0977C80925,$F4F0DCEEA8EFEDD9,$F9F6F7ECF3A7F1F2,$65274BA046FA7FF8
    Data.q $262828020A802F9D,$4C38170C85429582,$50FAB68AC3D770B8,$3D1F8DC5A211388C,$10063218F0C8BC66
    Data.q $C2254928D1F12E73,$112249842A569B96,$C239A02A65354D4B,$E114F2753D9C4CE6,$202A8F42A2502773
    Data.q $9CE60D06818D00A8,$CF51AA09AA5502B8,$57AD554BB59A7D4C,$B2892C75812D5AB9,$01C2022B4D8AC960
    Data.q $05974B993AD80764,$B759480418C70084,$4C1DFC040216DFAF,$5E2B1388C3E1B0B8
    Data.b $CC,$D8,$70,$08,$00,$3B
  Loading2_gif_end:
EndDataSection

_________________
PureBasic 5.11 | Windows 7 SP1 (x64) | Mageia 3 (x64) | RealSource

The use of EnableExplicit is free of charge and avoids errors.


Top
 Profile  
 
 Post subject: Re: UPDATED: Load Animated GIF frames
PostPosted: Mon Mar 19, 2012 12:41 pm 
Offline
Enthusiast
Enthusiast
User avatar

Joined: Tue Jan 31, 2006 9:43 am
Posts: 323
Location: France
Nice improvements ! :D

_________________
Niffo


Top
 Profile  
 
 Post subject: Re: UPDATED: Load Animated GIF frames
PostPosted: Mon Mar 19, 2012 9:59 pm 
Offline
Addict
Addict
User avatar

Joined: Thu Jun 24, 2004 2:44 pm
Posts: 4715
Location: Berlin - Germany
Thanks, :D

but we have to optimize the speed. A GIF with over 300 KB loads in 2 seconds, this is to slow.

_________________
PureBasic 5.11 | Windows 7 SP1 (x64) | Mageia 3 (x64) | RealSource

The use of EnableExplicit is free of charge and avoids errors.


Top
 Profile  
 
 Post subject: Re: UPDATED: Load Animated GIF frames
PostPosted: Tue Mar 20, 2012 9:46 am 
Offline
Enthusiast
Enthusiast
User avatar

Joined: Tue Jan 31, 2006 9:43 am
Posts: 323
Location: France
Even with debugger deactivated ?

_________________
Niffo


Top
 Profile  
 
 Post subject: Re: UPDATED: Load Animated GIF frames
PostPosted: Tue Mar 20, 2012 9:20 pm 
Offline
Addict
Addict

Joined: Sun Sep 07, 2008 12:45 pm
Posts: 1447
Location: Germany
The killer GIF for the program:

http://www.biologie.uni-hamburg.de/b-on ... movie2.gif

Bernd


Top
 Profile  
 
 Post subject: Re: UPDATED: Load Animated GIF frames
PostPosted: Tue Mar 20, 2012 9:37 pm 
Offline
Addict
Addict

Joined: Sun Sep 07, 2008 12:45 pm
Posts: 1447
Location: Germany
A fast try:
Code:
EnableExplicit
XIncludeFile "GIFanimation.pbi"

Define.w a
Dim Frames.GIF_Frame(0)

InitSprite()

OpenWindow(0, 0, 0, 800, 600, "Gif_Test", #PB_Window_SystemMenu|#PB_Window_ScreenCentered|#PB_Window_SizeGadget|#PB_Window_MaximizeGadget)
ButtonGadget(0,10,10,80,20,"Open File")

AddWindowTimer(0, 0, 100)

Repeat
  Select WaitWindowEvent()
    Case #PB_Event_Gadget
      Select EventGadget()
        Case 0
          Define.s Pattern="All Supported Formats|*.gif"
          Define.s filename=OpenFileRequester("Choose An Image File To Open","",Pattern,0)
          If filename
            If GIF_LoadFrames(Frames(), filename)
              OpenWindowedScreen(WindowID(0), 50, 50, ImageWidth(Frames(0)\Image), ImageHeight(Frames(0)\Image), 0, 0, 0)
            EndIf
          EndIf
      EndSelect
     
    Case #PB_Event_CloseWindow
      Break
     
    Case #PB_Event_Timer
      RemoveWindowTimer(0, 0)
      If a > ArraySize(Frames()) : a = 0 : EndIf
      If IsImage(Frames(a)\Image)
        StartDrawing(ScreenOutput())
        DrawImage(ImageID(Frames(a)\Image), 0, 0)
        StopDrawing()
        FlipBuffers()
        AddWindowTimer(0, 0, Frames(a)\DelayTime * 10)
      Else
        AddWindowTimer(0, 0, 100)
      EndIf
      a + 1
  EndSelect
 
ForEver
I'm not an expert with FlipBuffers() and so on.
So please look above that code.

Bernd


Top
 Profile  
 
 Post subject: Re: UPDATED: Load Animated GIF frames
PostPosted: Wed Mar 21, 2012 9:33 am 
Offline
Enthusiast
Enthusiast
User avatar

Joined: Tue Jan 31, 2006 9:43 am
Posts: 323
Location: France
For information, this 1,2 MB Gif takes 1,244 seconds to load with debugger disabled on my 2.8Ghz Core Duo.

_________________
Niffo


Last edited by Niffo on Thu May 03, 2012 2:24 pm, edited 1 time in total.

Top
 Profile  
 
 Post subject: Re: UPDATED: Load Animated GIF frames
PostPosted: Thu May 03, 2012 8:08 am 
Offline
User
User

Joined: Wed Feb 01, 2012 5:30 pm
Posts: 19
Hi to all. How I can implement a GIF animation, during a hard operation? Scanning, for example.

GIF animation function updates window by timer event. How I can use it, if my main program cycle starts by gadget event? GIF animation condition stops checking timer event, when base program cycle starts to work.

Code:
Repeat
  Select WaitWindowEvent()
    Case #PB_Event_Gadget
      Select EventGadget()
        Case 0 ; button gadget pressed
          ImageGadget() ;creating area for animation
          AddWindowTimer(0,0,Frames(0)\DelayTime*5)
          ; And then program does some hard and long operations... here animation doesn't work
      EndSelect

    Case #PB_Event_CloseWindow
      Break

    Case #PB_Event_Timer
       ;GIF processing routine
  EndSelect
 
ForEver


Top
 Profile  
 
 Post subject: Re: UPDATED: Load Animated GIF frames
PostPosted: Thu May 03, 2012 2:25 pm 
Offline
User
User
User avatar

Joined: Tue Aug 10, 2010 3:17 pm
Posts: 82
In the Pb help you will find that timer event are not the priority : in Window : AddWindowTimer()

Try to do it with a thread ?
(After Reading through the topic, I didn't see the thread aspect so I don't know if it's thread safe. Just try)

_________________
_________________________________________________
My Website : CeriseCode (Warning : perpetual changes & not completed ;))


Top
 Profile  
 
 Post subject: Re: UPDATED: Load Animated GIF frames
PostPosted: Thu May 03, 2012 2:29 pm 
Offline
Enthusiast
Enthusiast
User avatar

Joined: Tue Jan 31, 2006 9:43 am
Posts: 323
Location: France
You can try API timers (timeSetEvent() on Windows, viewtopic.php?f=19&t=37698), or Threads ...

_________________
Niffo


Top
 Profile  
 
 Post subject: Re: UPDATED: Load Animated GIF frames
PostPosted: Thu May 03, 2012 2:42 pm 
Offline
Addict
Addict
User avatar

Joined: Thu Jun 24, 2004 2:44 pm
Posts: 4715
Location: Berlin - Germany
You can load the GIF to a array, but better not in a thread.
You can Display the Animation in a thread, but enable Threadsafe,
is required for the ImageLib!

_________________
PureBasic 5.11 | Windows 7 SP1 (x64) | Mageia 3 (x64) | RealSource

The use of EnableExplicit is free of charge and avoids errors.


Top
 Profile  
 
 Post subject: Re: UPDATED: Load Animated GIF frames
PostPosted: Fri May 04, 2012 2:38 am 
Offline
User
User

Joined: Wed Feb 01, 2012 5:30 pm
Posts: 19
Quote:
but enable Threadsafe, is required for the ImageLib!

Works without threadsafe mode.
Quote:
You can Display the Animation in a thread

Look at the next code.
Code:
Procedure Animation(param)
 Repeat
    Select event ;event var declared as global
      Case #PB_Event_Timer
       ; GIF updating routine. All vars declared as global.
    EndSelect
ForEver
EndProcedure

CreateThread(@Animation(), param)

Repeat
    event=WaitWindowEvent(10);

    Repeat
      x+1 ; here window hangs bacause of hard repeating process. Thread works correctly without this cycle.
    ForEver

Until event=#PB_Event_CloseWindow

I suppose, I need to close my cycle into thread too. Or I did a mistake in my logic?

Edited. My program logic structure:

1. Declaring vars, arrays
2. Loading GIF
3. Enumerating constants
4. Several procedures, including Animation() proc:
Code:
Procedure Animation(param)
  Repeat
    Select event
      Case #PB_Event_Timer
        SetGadgetState(#Img_Scan,ImageID(Frames(i)\Image))
        i+1
        If i>count: i=0: EndIf
    EndSelect
  ForEver
EndProcedure

5. Drawing main window, initialization
6. Callback declared
7. Some short "If" conditions
8. Main program loop:
Code:
Repeat
   all following code
Until event=#PB_Event_CloseWindow

8.1. Some "Select event - Case" procedures
8.2. Our turn. GIF animation launched by pressing button:
Code:
ImageGadget(#Img_Scan,85,220,ImageWidth(Frames(0)\Image), ImageHeight(Frames(0)\Image),ImageID(Frames(0)\Image))
AddWindowTimer(#Window_Main,1,Frames(0)\DelayTime*5)
thread_anim=CreateThread(@Animation(),param)

8.2.1. All rest target code is long working with filesystem objects (dirs, folders..). And here animation is not working again :(

If all my work code replace by empty loop code:
Code:
Repeat
Until event=#PB_Event_CloseWindow

Animation works!


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 53 posts ]  Go to page Previous  1, 2, 3, 4  Next

All times are UTC + 1 hour


Who is online

Users browsing this forum: No registered users and 0 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
Jump to:  

 


Powered by phpBB © 2008 phpBB Group
subSilver+ theme by Canver Software, sponsor Sanal Modifiye