Page 2 of 4

Re: UPDATED: Load Animated GIF frames

Posted: Tue Sep 28, 2010 11:55 am
by Niffo
Thank you "Divide By Zero", but what i was interested in is :
deano1987 wrote:This didnt load Animated GIF files correctly or set transparency... So I have been working hard to fix all the problems in the script and get it to load GIF images correctly, my script can now load 99% of GIF files correctly with the further 1% being just minimal display problems...

I'm hoping to release the code soon, it's taken me a huge amount of time so I hope everyone will appreciate my efforts :)
;)

Re: UPDATED: Load Animated GIF frames

Posted: Tue Sep 28, 2010 12:01 pm
by Divide By Zero
ahhh, my apologies, I must learn to read properly :) I just assumed that it was because it didn't run. I just read quoted the text which mentioned the syntax error. I didn't read the whole thread sorry. I should have realised that you knew more by your amount of posts :)

Re: UPDATED: Load Animated GIF frames

Posted: Wed Sep 29, 2010 1:16 pm
by deano1987
Hey Niffo, sorry started a new job a little over a month ago so I've been majorly distracted. I will get round to packaging it up for release as soon as possible though, I will try and reply in a week or two if I can :)

Re: UPDATED: Load Animated GIF frames

Posted: Sun Oct 24, 2010 12:23 pm
by c4s
deano1987 wrote:Hey Niffo, sorry started a new job a little over a month ago so I've been majorly distracted. I will get round to packaging it up for release as soon as possible though, I will try and reply in a week or two if I can :)
I still hope you will soon have enough time to post it. ;)

Re: UPDATED: Load Animated GIF frames

Posted: Wed Feb 01, 2012 8:11 am
by Niffo
@deano1987 : Please can you share your progress in the decoding algorythm ? ... even if it is not perfect or not "well packaged".

Re: UPDATED: Load Animated GIF frames

Posted: Wed Feb 15, 2012 6:13 pm
by deano1987
Hey Everyone, sorry it's been too long and I've kept wanting to work on this further and have not had the chance...

So anyway, reluctantly here is the code so far with my improvements/modifications. You will see GIF's are better but still not perfect!

(I think this is the most up to date file, I'll verify this later tonight sometime but im about 98% positive)... I'll continue working on this sometime soon, if anyone has any fix's please let me know and I will implement them into the code to release an updated package. (I will be making a google-code page soon with some small utilities showing how to use this code and also the code itself so we can all maintain it and get it working good!)

Code: Select all

; PureGif Library for PureBasic (By Dean Williams)

; Original Code By:         localmotion34 (Purebasic.fr forums)
; Updated & Extended By:    Dean Williams - resplace.net

; Please help development and report any problems or improvements/bug fixes you may have
; if we all work together we can have some really nice GIF support in PureBasic!
; Thanks to the original author for his work and I hope my improvements go a long way
; towards getting this to work correctly!

;- Structures

Structure ANGIF
  numberframes.l
  framenumber.l
  hBitmap.l[300]
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 OutLineGIF(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

#PB_LoadGifFIle=$6000

Procedure.l NextCodeGIF(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 DrawTransparentImage(DC, bitmap, x, y, width, height, TransparentColor)
 
  ; First, create some DC's. These are our gateways To associated
  ; bitmaps in RAM
  maskDC = CreateCompatibleDC_(DC)
  tempDC = CreateCompatibleDC_(DC)
 
  SourceDC = CreateCompatibleDC_(DC)
  SelectObject_(SourceDC, bitmap)
 
 
  ; Then, we need the bitmaps. Note that we create a monochrome
  ; bitmap here!
  ; This is a trick we use For creating a mask fast enough.
  hMaskBmp = CreateBitmap_(width, height, 1, 1, 0)
  hTempBmp = CreateCompatibleBitmap_(DC, width, height)
 
  ; Then we can assign the bitmaps to the DCs
  ;
  hMaskBmp = SelectObject_(maskDC, hMaskBmp)
  hTempBmp = SelectObject_(tempDC, hTempBmp)
 
  ; Now we can create a mask. First, we set the background color
  ; To the transparent color; then we copy the image into the
  ; monochrome bitmap.
  ; When we are done, we reset the background color of the
  ; original source.
  TransparentColor= SetBkColor_(SourceDC, TransparentColor)
  BitBlt_ (maskDC, 0, 0, width, height, SourceDC, 0, 0, #SRCCOPY)
  SetBkColor_(SourceDC, TransparentColor)
 
  ; The first we do with the mask is To MergePaint it into the
  ; destination.
  ; This will punch a WHITE hole in the background exactly were
  ; we want the graphics To be painted in.
  BitBlt_ (tempDC, 0, 0, width, height, maskDC, 0, 0, #SRCCOPY)
  BitBlt_ (DC, x, y, width, height, tempDC, 0, 0, #MERGEPAINT)
 
  ; Now we delete the transparent part of our source image. To do
  ; this, we must invert the mask And MergePaint it into the
  ; source image. The transparent area will now appear as WHITE.
  BitBlt_ (maskDC, 0, 0, width, height, maskDC, 0, 0, #NOTSRCCOPY)
  BitBlt_ (tempDC, 0, 0, width, height, SourceDC, 0, 0, #SRCCOPY)
  BitBlt_ (tempDC, 0, 0, width, height, maskDC, 0, 0, #MERGEPAINT)
 
  ; Both target And source are clean. All we have To do is To And
  ; them together!
  BitBlt_ (DC, x, y, width, height, tempDC, 0, 0, #SRCAND)
 
  ; Now all we have To do is To clean up after us And free system
  ; resources..
  DeleteObject_ (hMaskBmp)
  DeleteObject_ (hTempBmp)
  DeleteDC_ (maskDC)
  DeleteDC_ (tempDC)
  DeleteDC_ (SourceDC)
 
EndProcedure

Procedure.l LoadGIFframes(filename.s,Array imageArray.l(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
    ;LogError("GIF Load Error!" , "Could not open the GIF image file for reading." , "File Path = " + filename)
    ProcedureReturn #False
  EndIf
 
  ;Read the file header and logical screen descriptor
  ReadData(file,gh,SizeOf(gh))
 
  sig=PeekS(@gh\ghSig,6) ;Get the header version string
  If sig<>"GIF89a" And sig<>"GIF87a"
    CloseFile(file)
    ;LogError("GIF Load Error!" , "File was not a valid GIF image file" , "File Path = " + filename + Chr(23) + "File Signature = " + sig)
    ProcedureReturn #False ;NOT_VALID
  EndIf
 
  realwidth=gh\ghWidth
  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

  Debug "Image!"
   
  count=0
  While count<>$2C ;Search for im\imSep
    count=ReadByte(file) & 255
    If count = $F9
      ReadByte(file)
      trans = ReadByte(file) & 1
      Debug "MTrans: " + Str(trans)
      ReadWord(file)
      TByte = ReadByte(file)
      Debug "TByte: " + Str(TByte)
      If TByte >0 And TByte <255
        transcolor = GlobalCols(TByte)
        Debug "MTransCol: " + Str(trans)
      Else
        ;Disable transparency, we dont have a correct color
        trans=0
        transcolor=0
      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)
      ;LogError("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)
    ;LogError("GIF Load Error!" , "LZW code size is not valid!" , "LZW code size = "+ Str(LZWCodeSize))
    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)
    ;LogError("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=NextCodeGIF(file,CharBuff(),CodeMask(),cl)
   
    If cc<0 ;If a file error, return without completing the decode
      FreeMemory(lpBUFF)
      ;CloseFile(file)
      ;LogError("GIF Load Error!" , "LZW code size is not valid!" , "LZW code size = "+ Str(cc))
      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=NextCodeGIF(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
        OutLineGIF(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
          OutLineGIF(lpBUFF,width,height,cl)
          *lpBuffPtr=lpBUFF
          BufCnt=width
        EndIf
      Wend
     
    EndIf
  Wend
 
  If BufCnt<>width ;If there are any left, output the bytes
    OutLineGIF(lpBUFF,width-BufCnt-1,height,cl)
  EndIf
  *dib=hDIB
  If *dib=0 ;Avoid errors
    ProcedureReturn #False
  EndIf
 
  Bits=*dib+*dib\biSize+(*dib\biClrUsed*4) ;Pointer to bits
 
  ;Create the DDB bitmap
  hdc=GetDC_(#Null)
  hBitmap=CreateDIBitmap_(hdc,*dib,#CBM_INIT,Bits,*dib,#DIB_RGB_COLORS)
  pbimage=CreateImage(#PB_Any,realwidth,realheight)
  drawdc=StartDrawing(ImageOutput(pbimage))
  Box(0,0,realwidth,realheight,$FFFFFF)
  If trans=1
    DrawTransparentImage(drawdc,hBitmap,im\imLeft,im\imTop,im\imWidth,im\imHeight,transcolor)
  Else
   DrawImage(hBitmap,im\imLeft,im\imTop,im\imWidth,im\imHeight)
  EndIf
  StopDrawing()
  FreeMemory(hDIB)
  imageArray(0)=ImageID(pbimage) ;hBitmap
  numberimages=1
 
  ;- continue to other frames
  Macro GetBit(Value, bit)
    (Value&(1<<bit))>>bit  ;Translates as 'value' ANDed with 2^bit and shifted back to bitposition 0
  EndMacro
 
  ; Read through the various image blocks
  NotatEnd=1
  While NotatEnd=1
    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
        Size=n
        n=ReadByte(file) ;& 255
        packedfields.b=n &$FF
        ;Debug Bin(n&$FF)
        disposalmethod= (n & %00011100) >>2
        ;Debug disposalmethod
        tflag= GetBit(n,0) ;n& %00000001
        ;Debug tflag
        delaytime.w=ReadWord(file)
       
        ;Debug delaytime &  $FFFF
        transparent.b=ReadByte(file)
        
      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)
      ;LogError("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)
    ;LogError("GIF Load Error!" , "LZW code size is not valid!" , "LZW code size = "+ Str(LZWCodeSize))
    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)
    ;LogError("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=NextCodeGIF(file,CharBuff(),CodeMask(),cl)
   
    If cc<0 ;If a file error, return without completing the decode
      FreeMemory(lpBUFF)
      CloseFile(file)
      ;LogError("GIF Load Error!", "GIF image contained an in-valid LZW code." , "LZW Read = "+Str(cc))
      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=NextCodeGIF(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
        OutLineGIF(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
          OutLineGIF(lpBUFF,width,height,cl)
          *lpBuffPtr=lpBUFF
          BufCnt=width
        EndIf
      Wend
     
    EndIf
   
  Wend
 
  If BufCnt<>width ;If there are any left, output the bytes
    OutLineGIF(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
  hdc=GetDC_(#Null)
  hBitmap=CreateDIBitmap_(hdc,*dib,#CBM_INIT,Bits,*dib,#DIB_RGB_COLORS)
  pbimage=CreateImage(#PB_Any,realwidth,realheight)
  drawdc=StartDrawing(ImageOutput(pbimage))
  ; For some retarded reason, we have to draw and redraw the GIF frames over the previous image imagenumber-1
  Debug "TransFlag: "+Str(tflag)
  
;   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
    
    Debug "Disposal: "+Str(disposalmethod) 
    
    If disposalmethod =1
      Box(0,0,realwidth,realheight,$FFFFFF)
      DrawImage(imageArray(numberimages-1),0,0)
      If tflag=1
        ;glob
        DrawTransparentImage(drawdc,hBitmap,im\imLeft,im\imTop,im\imWidth,im\imHeight,transcolor)
      Else
        DrawImage(hBitmap,im\imLeft,im\imTop,im\imWidth,im\imHeight)
      EndIf
    ElseIf disposalmethod =2
      Box(0,0,realwidth,realheight,$FFFFFF)
      ;DrawImage(imageArray(0),0,0)
      If tflag=1
        ;glob
        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
      Box(0,0,realwidth,realheight,$FFFFFF)
      ;DrawImage(imageArray(numberimages-1),0,0)
      ;DrawImage(hBitmap,im\imLeft,im\imTop)
      If tflag=1
        ;glob
        DrawTransparentImage(drawdc,hBitmap,im\imLeft,im\imTop,im\imWidth,im\imHeight,transcolor)
      Else
        DrawImage(hBitmap,im\imLeft,im\imTop,im\imWidth,im\imHeight)
      EndIf
    EndIf
;   EndIf
  StopDrawing()
  FreeMemory(hDIB) ;Free the DIB
  imageArray(numberimages)=ImageID(pbimage)
  numberimages=numberimages+1
Wend
ProcedureReturn numberimages
EndProcedure


;Procedure TimerProc(hwnd,
Procedure GIFTimerProc(hwnd,msg,wParam,lParam)
  Select msg
    Case #PB_LoadGifFIle
      *GIFframe.ANGIF=GetProp_(hwnd,"frameinfo")
      If *GIFframe
        For d=0 To *GIFframe\numberframes-1
          DeleteObject_(*GIFframe\hBitmap[d])
        Next
        FreeMemory(*GIFframe)
      EndIf
      *frame.ANGIF=AllocateMemory(SizeOf(ANGIF))
      Dim GIFarray.l(600)
      string.s=PeekS(lParam)
      numberframes=LoadGIFframes(string.s,GIFarray())
      If numberframes <1
        ;obviously a problem here :o
        ;LogError("GIF Load Error!" , "File was not a valid GIF image file, returned 0 frames!" , "Frames = " + Str(numberframes))
        ProcedureReturn #False
      EndIf
      ReDim GIFarray.l(numberframes-1)
      SendMessage_(hwnd,#STM_SETIMAGE,#IMAGE_BITMAP,GIFarray(0))
      SetTimer_(hwnd,200,100,0)
      *frame\numberframes=numberframes
      *frame\framenumber=0
      For a=0 To numberframes-1
        *frame\hBitmap[a]=GIFarray(a)
      Next
      SetProp_(hwnd,"frameinfo",*frame.ANGIF)
     
    Case #WM_TIMER
      *GIFframe.ANGIF=GetProp_(hwnd,"frameinfo") ; get the image array pointer
      framenumber=*GIFframe\framenumber ; get the frame index
      KillTimer_(hwnd,200) ; stop the timer
      *GIFframe\framenumber=*GIFframe\framenumber+1; increase the frame count
      If *GIFframe\framenumber=*GIFframe\numberframes
        *GIFframe\framenumber=0
      EndIf
      hBitmap=*GIFframe\hBitmap[framenumber] ; get the bitmap
      ;delaytime=PeekW(*ptr+(frame*SizeOf(ANGIF))+4) ; get the delaytime
      SendMessage_(hwnd,#STM_SETIMAGE,#IMAGE_BITMAP,hBitmap); set the new bitmap
     
      SetTimer_(hwnd,200,100,0) ; set the new timer
      SetProp_(hwnd,"frameinfo",*GIFframe.ANGIF); reset the window props
      ;FreeMemory(*GIFframe)
  EndSelect
  ProcedureReturn CallWindowProc_(GetProp_(hwnd,"oldproc"),hwnd,msg,wParam,lParam)
EndProcedure

Procedure GifStaticControl(id.l,x.l,y.l,width.l,height.l)
  StaticCtl=ImageGadget(id,x.l,y.l,width.l,height,0,#PB_Image_Border)
  If id=#PB_Any
    PBreturn=StaticCtl
    hwnd=GadgetID(StaticCtl)
  Else
    PBreturn=GadgetID(id)
    hwnd=GadgetID(id)
  EndIf
  SetProp_(hwnd,"oldproc",SetWindowLong_(hwnd,#GWL_WNDPROC,@GIFTimerProc())) ; subclass
  ProcedureReturn PBreturn
EndProcedure
If OpenWindow(0, 0, 0, 800, 600, "MDIGadget", #PB_Window_SystemMenu|#PB_Window_ScreenCentered|#PB_Window_SizeGadget|#PB_Window_MaximizeGadget)
  If CreateGadgetList(WindowID(0)) And CreateMenu(0, WindowID(0))
    MenuTitle("File")
    MenuItem(0, "Open GIF")
    MenuItem(1, "Exit")
    MenuTitle("MDI windows menu")
    ;MDIGadget(0, 0, 0, 0, 0, 1, 2, #PB_MDI_AutoSize)
    ;GifStaticControl(50,100,100,200,200)
  EndIf
EndIf
Repeat
  Select WaitWindowEvent()
    Case #PB_Event_Gadget
      Select EventGadget()
        Case 0
         
      EndSelect
    Case #PB_Event_Menu
      Select EventMenu()
        Case 0
          Pattern.s="All Supported Formats|*.gif"
          filename.s=OpenFileRequester("Choose An Image File To Open","",Pattern,0)
          If filename
            ;SendMessage_(GadgetID(50),#PB_LoadGifFIle,0,filename)
            Dim myarray.l(800)
            numberGIFs=LoadGIFframes(filename,myarray())
            UseGadgetList(WindowID(0))
            GifStaticControl(50,100,100,200,200)
            For a=1 To numberGIFs
              AddGadgetItem(50,a,"GIF Frame " + Str(a))
              CreateGadgetList(WindowID(0))
              ImageGadget(a*10,0,50*a,0,0,0)
              SendMessage_(GadgetID(a*10),#STM_SETIMAGE,#IMAGE_BITMAP,myarray(a-1))
            Next
            
          EndIf
        Case 1
          End
      EndSelect
    Case #PB_Event_CloseWindow
      End
  EndSelect
ForEver

Re: UPDATED: Load Animated GIF frames

Posted: Thu Feb 16, 2012 9:22 am
by electrochrisso
Loads the images, but stacks them vertically, with no animation.
Unfortunately I don't think I have the ability to make it any better. :cry:

Re: UPDATED: Load Animated GIF frames

Posted: Thu Feb 16, 2012 10:23 am
by deano1987
Sorry yes this was my "frame testing" build, I have a solution which I will put in a ZIP and upload today. Watch this space...

Re: UPDATED: Load Animated GIF frames

Posted: Wed Feb 29, 2012 11:40 am
by Niffo
@deano1987 :
Many thanks for this code ! I am going to explore it ... :-)

Re: UPDATED: Load Animated GIF frames

Posted: Wed Feb 29, 2012 7:26 pm
by kvitaliy
A simple way to use GIF - use a small DLL

Re: UPDATED: Load Animated GIF frames

Posted: Wed Feb 29, 2012 7:30 pm
by Niffo
A DLL is Windows Only. I'am going to translate this code to a multi-platform one ...

Re: UPDATED: Load Animated GIF frames

Posted: Wed Feb 29, 2012 9:02 pm
by kvitaliy
Niffo wrote:A DLL is Windows Only. I'am going to translate this code to a multi-platform one ...
SelectObject_,BitBlt_ is Windows API Only :D

Re: UPDATED: Load Animated GIF frames

Posted: Wed Feb 29, 2012 10:40 pm
by Niffo
kvitaliy wrote:SelectObject_,BitBlt_ is Windows API Only :D
Niffo wrote:I'am going to translate this code to a multi-platform one ...
:)

Re: UPDATED: Load Animated GIF frames

Posted: Thu Mar 01, 2012 4:09 am
by electrochrisso
A simple way to use GIF - use a small DLL http://pbasic.spb.ru/phpBB2/download.php?id=1316
Thanks for the link kvitaliy. :)

Re: UPDATED: Load Animated GIF frames

Posted: Wed Mar 07, 2012 5:50 pm
by Niffo
deano1987 wrote:Hey Everyone, sorry it's been too long and I've kept wanting to work on this further and have not had the chance...

So anyway, reluctantly here is the code so far with my improvements/modifications. You will see GIF's are better but still not perfect!

(I think this is the most up to date file, I'll verify this later tonight sometime but im about 98% positive)... I'll continue working on this sometime soon, if anyone has any fix's please let me know and I will implement them into the code to release an updated package. (I will be making a google-code page soon with some small utilities showing how to use this code and also the code itself so we can all maintain it and get it working good!)
Sadly, your code can not load anymore correctly the gif in this post : http://www.purebasic.fr/english/viewtop ... 96#p199196 :(