BASIC

Author Topic: Loading GIF files/animations...  (Read 3473 times)

Offline dreamerman

  • Global Moderator
  • Dr. Type
  • *******
  • Posts: 288
    • View Profile
    • my personal website
Loading GIF files/animations...
« on: 2012-Aug-21 »
We can load jpg, png and bmp files, but whole gifs world was beyond our reach, until now.
From long time I was thinking about making gif importer, but LZW compression looked complicated, it still look strange ;d
But after long searches for most understandable code, I found some source in Java, and translation to GLB began..
Here it is, GIF loading code, with examples.

NOTE: I only 'converted' that module to GLBasic, real thanks should go to Jitsu Wan for his Java source.

GIF module:
Code: GLBasic [Select]
// --------------------------------- //
// Project: gif_loader

// No copyright asserted on this source code. May be used for
// any purpose, however, refer TO the Unisys LZW patent FOR any additional
// restrictions. I am NOT responsible IF something will not work properly.

// GLBasic GIF load port by dreamerman[at]wp.pl
// heavily based on gif loader for Java ME by Jitsu Wan with reference to work done by Kevin Weiner, FM Software; LZW decoder adapted from John Cristy's ImageMagick.
// includes c++ inline
// any other info in code
//
// --- HOW TO USE ---
// - first initialize gif vars by calling -
// Init_Gif_loader()
// - next load gif file as sprite -
// Load_gif_file("some.gif", sprite_id%, frame_count%, frame_width%, frame_height%)
// DrawSprite sprite_id%, 0, 0
// - or load directly as animation for use with DrawAnim ... -
// Load_gif_as_anim("some.gif", anim_id%, frame_count%, frame_width%, frame_height%)
// DrawAnim anim_id%, current_frame%, 0, 0
// - that's all... -

//ver: public 2
//Changelog:
//- public 2: added Redim's to clear image buffers



//two importants variables, set max sprite size - lower for compatibility with legacy gpu/mobile devices
GLOBAL gif_max_sprite_width% = 2048, gif_max_sprite_height% = 2048
//other gif loader variables
GLOBAL gif_curr_posx%, gif_curr_posy%, gif_currxlen%
GLOBAL gif_bytes%[], gif_file_size%, gif_error%, gif_rposition%, gif_tpixels%[], gif_framecount%
GLOBAL gif_width%, gif_height%, gif_gct_flag%, gif_gct_size%, gif_pixelaspect%, gif_bgindex%, gif_bgcolor%, gif_lastbgcolor%
GLOBAL gif_lctFlag%, gif_interlace%, gif_lct_size%, gif_islastimg%
GLOBAL gif_gctab%[], gif_lctab%[], gif_blockb%[], gif_block_size%
GLOBAL gif_delay%, gif_transparency%, gif_transIndex%, gif_dispose%, gif_lastDispose%
GLOBAL gif_MaxStackSize% = 4096, gif_prefix%[], gif_suffix%[], gif_pixelStack%[]
GLOBAL gif_ix%, gif_iy%, gif_iw%, gif_ih%, gif_done%, gif_loopcount%
GLOBAL gif_lastImage_id%, gif_lastRect%[], gif_image%[], gif_lastimage%[], gif_wholesprite%[]

//init function
FUNCTION Init_Gif_loader:

        DIM gif_bytes%[2]
        DIM gif_gctab%[256]
        DIM gif_lctab%[256]
        DIM gif_blockb%[256]
        DIM gif_tpixels%[256]
        DIM gif_prefix%[gif_MaxStackSize%]
        DIM gif_suffix%[gif_MaxStackSize%]
        DIM gif_pixelStack%[gif_MaxStackSize%+1]
        DIM gif_lastRect%[4]
        DIM gif_image%[256]
        DIM gif_lastimage%[256]
        DIM gif_wholesprite%[256]

ENDFUNCTION

//gif loading errors:
//1 - no such file
//2 - error with opening file
//3 - not a gif file - if it's bmp/jpg/png it will be loaded
//4 - ???
//5 - to small sprite size - to many gif frames
FUNCTION Load_gif_file: filename$, sprite_id%, BYREF frame_count%, BYREF frame_width%, BYREF frame_height%
        LOCAL i1%, i2%, i3%, wp%, czs1$

        gif_file_size% = GETFILESIZE(filename$); gif_error% = 0
        IF (gif_file_size% = 0)
                DEBUG "GIF load error: wrong file size\n"
                gif_error = 1; RETURN 0
        ENDIF   //no file size?
//      DEBUG "reading start: " + GETTIMERALL() + "\n"
        wp% = GENFILE()
        IF (OPENFILE(wp%, filename$, 1))
                REDIM gif_bytes%[gif_file_size%]
                READSTR wp%, czs1$, gif_file_size%
                FOR i1% = 0 TO gif_file_size%-1
                        gif_bytes%[i1%] = ASC(MID$(czs1$, i1%, 1))
                NEXT
                CLOSEFILE wp%
                gif_rposition% = 6
        ELSE    //some error with loading file
                gif_error = 2; RETURN 0
        ENDIF

//      DEBUG "reading end: " + GETTIMERALL() + ", file size: " + gif_file_size% + "\n"

        gif_curr_posx% = 0; gif_curr_posy% = 0; gif_framecount% = 0
        czs1$ = CHR$(gif_bytes%[0]) + CHR$(gif_bytes%[1]) + CHR$(gif_bytes%[2]) + CHR$(gif_bytes%[3]) + CHR$(gif_bytes%[4]) + CHR$(gif_bytes%[5])
        IF (czs1$ = "GIF87a" OR czs1$ = "GIF89a")
//              DEBUG "it's a gif file..\n"
                //clear last image buffer
                REDIM gif_image%[0]; REDIM gif_wholesprite%[0]; REDIM gif_lastimage%[0]
                gif_readLSD()
                IF (gif_gct_flag%); gif_readColorTable(1); ENDIF
                //redim sprite array
                i1% = INTEGER(gif_max_sprite_width% / gif_width%)
                gif_currxlen% = i1% * gif_width%
                REDIM gif_wholesprite%[gif_currxlen% * gif_max_sprite_height%]

                gif_readContents()

//              DEBUG "loading end: " + GETTIMERALL() + "\n"
//              DEBUG "array x-size: " + gif_currxlen% + ", loop count: " + gif_loopcount% + ", delay: " + gif_delay% + " \n"
//              DEBUG "frame count: " + gif_framecount% + ", in-sprite pos: " + gif_curr_posx% + "x" + gif_curr_posy% + "\n"
                IF (gif_error% = 5); DEC gif_curr_posy%, gif_height%; DEC gif_framecount%; ENDIF
                REDIM gif_wholesprite%[gif_currxlen% * (gif_curr_posy%+gif_height%)]    //cut of unnecessary data
                //create sprite from array
                MEM2SPRITE(gif_wholesprite%[], sprite_id%, gif_currxlen%, gif_curr_posy%+gif_height%)

        ELSE    //check if it's bmp, jpg  or png for normal loading
                IF (gif_bytes%[0] = 66 AND gif_bytes%[1] = 77) OR (gif_bytes%[0] = 255 AND gif_bytes%[1] = 216) OR (gif_bytes%[0] = 137 AND gif_bytes%[1] = 80 AND gif_bytes%[2] = 78 AND gif_bytes%[3] = 71)
                        LOADSPRITE filename$, sprite_id%
                        GETSPRITESIZE sprite_id%, gif_width%, gif_height%
                        IF (gif_width% > 0 AND gif_height% > 0)
                                gif_framecount% = 1
                        ELSE
                                gif_error = 3; RETURN 0
                        ENDIF
                ELSE
                        gif_error = 3; RETURN 0
                ENDIF
        ENDIF
        frame_count% = gif_framecount%; frame_width% = gif_width%; frame_height% = gif_height%
        REDIM gif_bytes%[1]
        REDIM gif_wholesprite%[1]

        RETURN 1
ENDFUNCTION

//equivalent for LoadAnim
FUNCTION Load_gif_as_anim: filename$, anim_id%, BYREF frame_count%, BYREF frame_width%, BYREF frame_height%
        LOCAL ws% = GENSPRITE(), temp%, tcount%, twidth%, theight%
        temp% = Load_gif_file(filename$, anim_id%, tcount%, twidth%, theight%)
        SETSPRITEANIM anim_id%, twidth%, theight%
        frame_count% = tcount%; frame_width% = twidth%; frame_height% = theight%
        RETURN temp%
ENDFUNCTION

//main loop
FUNCTION gif_readContents:
        LOCAL i1%, code%, czs1$

        gif_done% = 0
        WHILE (gif_done% = 0)
                code% = gif_read()
                SELECT code%
                        CASE 44         //0x2C - image separator
                                gif_readImage()
//                              DEBUG "new image: " + gif_framecount% + "\n"
                        CASE 33         //0x21 - extension
                                code% = gif_read()
//                              DEBUG "extension: " + "\n"
                                SELECT code%
                                        CASE 0xf9       //graphic control extension
                                                gif_readGraphicControlExt()
//                                              DEBUG "graphic ext: dispose: " + gif_dispose% + " \n"
                                        CASE 0xff       //application extension
                                                gif_readBlock()
//                                              DEBUG "netscape ext \n"
                                                czs1$ = ""
                                                FOR i1%=0 TO 10; INC czs1$, CHR$(gif_blockb%[i1%]); NEXT
                                                IF (czs1$ = "NETSCAPE2.0")
                                                        gif_readNetscapeExt()
                                                ELSE
                                                        gif_skipblock()
                                                ENDIF
                                        DEFAULT
                                                gif_skipblock()
                                ENDSELECT
                        CASE 59         //0x3b - terminator
                                gif_done% = 1
                        CASE 0          //0x00 - bad byte
                                //continue
                        DEFAULT
                                //raise error - format error?
                ENDSELECT
        WEND

ENDFUNCTION


// original comment
// Decodes LZW image data into pixel array.
// Adapted from John Cristy's ImageMagick.
FUNCTION gif_decodeImageData:
        LOCAL NullCode% = -1, npix% = gif_iw% * gif_ih%
        LOCAL available%, clear%, code_mask%, code_size%, end_of_information%, in_code%, old_code%, bits%, code%, count%, i%, datum%, data_size%, first%, top%, bi%, pi%

        IF (LEN(gif_tpixels%[]) < npix); REDIM gif_tpixels%[npix]; ENDIF

        data_size% = gif_read()         //  Initialize GIF data stream decoder.
        clear% = ASL(1, data_size%)
        end_of_information% = clear% + 1
        available% = clear% + 2
        old_code% = NullCode%
        code_size% = data_size% + 1
        code_mask% = ASL(1, code_size) - 1
        FOR code% = 0 TO clear%-1
                gif_prefix%[code%] = 0
                gif_suffix%[code%] = code%
        NEXT

INLINE
         //  Decode GIF pixel stream.
         datum = bits = count = first = top = pi = bi = 0;

         while (i < npix)
         {
             if (top == 0)
             {
                 if (bits < code_size)
                 {
                     //  Load bytes until there are enough bits for a code.
                     if (count == 0)
                     {
                         // Read a new data block.
                         count = gif_readBlock();
                         if (count <= 0) {
                                         break;
                                     }
                         bi = 0;
                     }
                     datum += ((gif_blockb(bi)) & 0xff) << bits;        //(((int) gif_blockb(bi)) & 0xff) << bits;
                     bits += 8;
                     bi++;
                     count--;
                     continue;
                 }

                 //  Get the next code.

                 code = datum & code_mask;
                 datum >>= code_size;
                 bits -= code_size;

                 //  Interpret the code

                 if ((code > available) || (code == end_of_information)) {
                     break;
                 }
                 if (code == clear)
                 {
                     //  Reset decoder.
                     code_size = data_size + 1;
                     code_mask = (1 << code_size) - 1;
                     available = clear + 2;
                     old_code = NullCode;
                     continue;
                 }
                 if (old_code == NullCode)
                 {
                     gif_pixelStack(top++) = gif_suffix(code);
                     old_code = code;
                     first = code;
                     continue;
                 }
                 in_code = code;
                 if (code == available)
                 {
                     gif_pixelStack(top++) = first;     //(byte) first
                     code = old_code;
                 }
                 while (code > clear)
                 {
                     gif_pixelStack(top++) = gif_suffix(code);
                     code = gif_prefix(code);
                 }
                 first = (gif_suffix(code)) & 0xff;     //((int) gif_suffix(code)) & 0xff;

                 //  Add a new string to the string table,

                 if (available >= gif_MaxStackSize) {
                     break;
                 }
                 gif_pixelStack(top++) = first; //(byte) first
                 gif_prefix(available) = old_code;      //(short) old_code
                 gif_suffix(available) = first; //(byte) first
                 available++;
                 if (((available & code_mask) == 0) && (available < gif_MaxStackSize))
                 {
                     code_size++;
                     code_mask += available;
                 }
                 old_code = in_code;
             }

             //  Pop a pixel off the pixel stack.

             top--;
             gif_tpixels(pi++) = gif_pixelStack(top);
             i++;
         }

         for (i = pi; i < npix; i++)
         {
             gif_tpixels(i) = 0; // clear missing pixels
         }
ENDINLINE

ENDFUNCTION


FUNCTION gif_readImage:

        gif_ix% = gif_readShort()
        gif_iy% = gif_readShort()
        gif_iw% = gif_readShort()
        gif_ih% = gif_readShort()

        LOCAL packed% = gif_read(), save%
        gif_lctFlag% = BAND(packed%, 0x80)              //1 - local color table flag
        gif_interlace% = BAND(packed%, 0x40)    //2 - interlace flag
                                                                                        //3 - sort flag, 4-5 - reserved
        gif_lct_size% = ASL(2, BAND(packed%, 7))        //6-8 - local color table size
        IF (gif_lctFlag%)       //use local table
                gif_readColorTable(0)
        ELSE
                FOR i1% = 0 TO gif_gct_size%-1
                        gif_lctab%[i1%] = gif_gctab%[i1%]
                NEXT
                IF (gif_bgindex% = gif_transIndex%); gif_bgcolor% = 0; ENDIF
        ENDIF

        IF (gif_transparency%)
                save% = gif_lctab%[gif_transIndex%]
                gif_lctab%[gif_transIndex%] = 0
        ENDIF

        gif_decodeImageData()
        gif_skipblock()

        INC gif_framecount%
        //check for space
        IF (gif_curr_posy% + gif_height% >= gif_max_sprite_height%)
                gif_error% = 5; gif_done% = 1
        ENDIF
        IF (gif_error% = 0)
                gif_setPixels()         // transfer pixel data to image
                IF (gif_transparency%); gif_lctab%[gif_transIndex%] = save%; ENDIF
                gif_resetFrame()
        ENDIF

        //calculate new position in our sprite
        INC gif_curr_posx%, gif_width%
        IF (gif_curr_posx% >= gif_currxlen%)
                gif_curr_posx% = 0
                INC gif_curr_posy%, gif_height%
                IF (gif_curr_posy% >= gif_max_sprite_height%)
                        gif_error% = 5
                        gif_done% = 1
                ENDIF
        ENDIF
//      DEBUG "new position in sprite: " + gif_curr_posx% + "x" + gif_curr_posy% + "\n"

ENDFUNCTION


FUNCTION gif_setPixels:
LOCAL n%, i1%, i2%, i3%, i4%, i5%, i6%, dlug% = gif_width% * gif_height%, ccolor%

IF (gif_lastDispose% > 0)
        IF (gif_lastDispose% = 3)
                n% = gif_framecount% - 2        //use image before last
                IF (n% > 0)
                        i1% = (n - 1) * gif_width%; i2% = 0             //x & y pos of that frame on sprite array
                        WHILE (i1% > gif_currxlen%)
                                DEC i1%, gif_currxlen%; INC i2%, gif_height%
                        WEND

                        FOR i4% = i2% TO i2% + gif_height%
                                i5% = gif_height% * i4%
                                FOR i3% = i1% TO i1% + gif_width%
                                        gif_image%[i6%] = gif_wholesprite%[i5% + i3%]
                                        INC i6%
                                NEXT
                        NEXT
                ENDIF
        ELSEIF (gif_lastDispose% = 2)
                IF (gif_transparency%)
                        ccolor% = INTEGER(0x00000000)
                ELSE
                        ccolor% = gif_lastbgcolor%
                ENDIF
                FOR i1% = 0 TO dlug%-1
                        gif_image%[i1%] = ccolor%
                NEXT
                //should be: g.fillRect(lastRect[0],lastRect[1],lastRect[2],lastRect[3]);
        ELSE
                FOR i1% = 0 TO dlug% - 1
                        gif_image%[i1%] = gif_lastimage%[i1%]
                NEXT
        ENDIF
ENDIF


INLINE
         // copy each source line to the appropriate place in the destination
         int pass = 1;
         int incr = 8;
         int iline = 0;
         for (int i = 0; i < gif_ih; i++) {
             int line = i;
             if (gif_interlace) {
                 if (iline >= gif_ih) {
                     pass++;
                     switch (pass) {
                         case 2 :
                             iline = 4;
                             break;
                         case 3 :
                             iline = 2;
                             incr = 4;
                             break;
                         case 4 :
                             iline = 1;
                             incr = 2;
                     }
                 }
                 line = iline;
                 iline += incr;
             }
             line += gif_iy;
             if (line < gif_height) {
                 int k = line * gif_width;
                 int dx = k + gif_ix; // start of line in dest
                 int dlim = dx + gif_iw; // end of dest line
                 if ((k + gif_width) < dlim) {
                     dlim = k + gif_width; // past dest edge
                 }
                 int sx = i * gif_iw; // start of line in source
                 while (dx < dlim) {
                     // map color and insert in destination
                     int index = (gif_tpixels(sx++)) & 0xff;
                     int c = gif_lctab(index);
                     if (c != 0) {
                         gif_image(dx) = c;
                     }
                     dx++;
                 }
             }
         }

ENDINLINE

//paste current frame to our sprite
i2% = 0; i3% = gif_curr_posy% * gif_currxlen% + gif_curr_posx%
FOR i1% = 0 TO gif_height% * gif_width% - 1
        gif_wholesprite%[i3%+i2%] = gif_image%[i1%]
        INC i2%
        IF (i2%>=gif_width%); i2% = 0; INC i3%, gif_currxlen%; ENDIF
NEXT

ENDFUNCTION


FUNCTION gif_readGraphicControlExt:
        gif_read()      //block size
        LOCAL packed% = gif_read()      //packed fields
        gif_dispose% = ASR(BAND(packed%, 0x1c), 2)      //disposal method -> dispose = (packed & 0x1c) >> 2
        IF (gif_dispose% = 0); gif_dispose% = 1; ENDIF
        gif_transparency% = BAND(packed%, 1)    //transparency = (packed & 1) != 0;
        gif_delay% = gif_readShort() * 10       //delay in miliseconds
        gif_transIndex% = gif_read()            //transparent color index
        gif_read()      //block terminator
ENDFUNCTION

//how many loops/repeats - does we care about it? ;]
FUNCTION gif_readNetscapeExt:
        LOCAL b1%, b2%
        REPEAT
                gif_readBlock()
                IF (gif_blockb%[0] = 1)
                        b1% = BAND(gif_blockb%[1], 256)
                        b2% = BAND(gif_blockb%[2], 256)
                        gif_loopcount% = BOR(ASL(b2%, 8), b1%)
                ENDIF
        UNTIL (gif_block_size% = 0 OR gif_error% <> 0)
ENDFUNCTION

//read Logical Screen Descriptor
FUNCTION gif_readLSD:
        gif_width% = gif_readShort()
        gif_height% = gif_readShort()
        LOCAL packed% = gif_read(), dlug% = gif_width% * gif_height%
        gif_gct_flag% = BAND(packed%, 128)              // = (packed & 0x80) != 0
        gif_gct_size% = ASL(2, BAND(packed%, 7))
//bits:
// 1   : global color table flag
// 2-4 : color resolution
// 5   : gct sort flag
// 6-8 : gct size

        gif_bgindex% = gif_read()
        gif_pixelaspect% = gif_read()
        //redim our image tables
        REDIM gif_image%[dlug%]
        REDIM gif_lastimage%[dlug%]

//DEBUG "info: " + gif_width% + "x" + gif_height% + ", colors count: " + gif_gct_size% + "\n"

ENDFUNCTION

//read one byte from gif file array
FUNCTION gif_read:
        LOCAL i1% = 0
        i1% = gif_bytes%[gif_rposition]
        INC gif_rposition
        RETURN i1%
ENDFUNCTION

FUNCTION gif_readShort:
        RETURN gif_read() + ASL(gif_read(), 8)
ENDFUNCTION

//block reading
FUNCTION gif_readBlock:
        LOCAL i1%
        gif_block_size% = gif_read()
        IF (gif_block_size% > 0)
                LOCAL count% = 0
                FOR i2%=0 TO gif_block_size%-1
                        gif_blockb%[i2%] = gif_bytes%[gif_rposition+i2%]
                NEXT
                INC gif_rposition%, gif_block_size%
        ENDIF
        RETURN gif_block_size%
ENDFUNCTION

FUNCTION gif_skipblock:
        REPEAT
                gif_readBlock()
        UNTIL (gif_block_size%=0 OR gif_error%<>0)
ENDFUNCTION

FUNCTION gif_readColorTable: is_global%
        LOCAL i1%
        IF (is_global% = 1)
                FOR i1%=0 TO gif_gct_size%-1
                        gif_gctab%[i1%] = 0xff000000 + ASL(gif_bytes%[gif_rposition+2], 16) + ASL(gif_bytes%[gif_rposition+1], 8) + gif_bytes%[gif_rposition]
                        INC gif_rposition, 3
                NEXT
        ELSE
                FOR i1%=0 TO gif_lct_size%-1
                        gif_lctab%[i1%] = 0xff000000 + ASL(gif_bytes%[gif_rposition+2], 16) + ASL(gif_bytes%[gif_rposition+1], 8) + gif_bytes%[gif_rposition]
                        INC gif_rposition, 3
                NEXT
        ENDIF
ENDFUNCTION

FUNCTION gif_resetFrame:
        gif_lastDispose% = gif_dispose%
        gif_lastRect%[0] = gif_ix%
        gif_lastRect%[1] = gif_iy%
        gif_lastRect%[2] = gif_iw%
        gif_lastRect%[3] = gif_ih%

        //lastImage = image
        LOCAL dlug% = LEN(gif_image%[]), i1%
        FOR i1% = 0 TO dlug%-1
                gif_lastimage%[i1%] = gif_image%[i1%]
        NEXT
        gif_islastimg% = 1

        gif_lastbgcolor% = gif_bgcolor%
        gif_dispose% = 0
        gif_transparency% = 0
        //gif_delay% = 0
        gif_lct_size% = 0

ENDFUNCTION
 

example - load as sprite:
Code: GLBasic [Select]
SETCURRENTDIR("Media") // go to media files
LOCAL t1%, t2%, t3%
Init_Gif_loader()
Load_gif_file("some_animation.gif", 1, t1%, t2%, t3%)
SAVESPRITE "test.png", 1
MOUSEWAIT
END
 

example - load as animation:
Code: GLBasic [Select]
SETCURRENTDIR("Media") // go to media files
LOCAL t1%, t2%, t3%, gif_cframe%, gif_frames%, done% = 1

Init_Gif_loader()
Load_gif_as_anim("earth.gif", 3, gif_frames%, t2%, t3%)

CLEARSCREEN RGB(100, 50, 50)
WHILE done%
        IF KEY(01); done% = 0; ENDIF
        INC gif_cframe%
        IF (gif_cframe% >= gif_frames%); gif_cframe% = 0; ENDIF
        SLEEP gif_delay% //var from gif loading module
        IF (gif_frames%>0); DRAWANIM 3, gif_cframe%, 10, 10; ENDIF
        SHOWSCREEN
WEND
END
 

:-)

Edit: little update, fixed issue with not clearing image buffers..
« Last Edit: 2012-Aug-23 by dreamerman »
Check my source code editor for GLBasic - link

Offline Ian Price

  • Administrator
  • Prof. Inline
  • *******
  • Posts: 4147
  • On the shoulders of giants.
    • View Profile
    • My Apps
Re: Loading GIF files/animations...
« Reply #1 on: 2012-Aug-21 »
Excellent news. Well done to all :)
I came. I saw. I played.

Offline mentalthink

  • Prof. Inline
  • *****
  • Posts: 3366
  • Integrated Brain
    • View Profile
Re: Loading GIF files/animations...
« Reply #2 on: 2012-Aug-21 »
Uhh this it´s very Important... thanks a lot  :nw: :nw: :nw:

Offline erico

  • Community Developer
  • Prof. Inline
  • ******
  • Posts: 4212
    • View Profile
    • Portfolio
Re: Loading GIF files/animations...
« Reply #3 on: 2012-Aug-21 »
I wonder about the final data size of a sprite based game using GIF. Does is compress(losslesly) to a good measure when compared to PNG? Holding sheets of sprite or movie strip on a lower source (gif 256 colors) could be great.

Its a widespread format, I should mark this page :-[

Offline Kitty Hello

  • code monkey
  • Administrator
  • Prof. Inline
  • *******
  • Posts: 10709
  • here on my island the sea says 'hello'
    • View Profile
    • http://www.glbasic.com
Loading GIF files/animations...
« Reply #4 on: 2012-Aug-21 »
Insane. That's so cool.

Offline Schranz0r

  • Premium User :)
  • Administrator
  • Prof. Inline
  • *******
  • Posts: 5020
  • O Rly?
    • View Profile
Re: Loading GIF files/animations...
« Reply #5 on: 2012-Aug-23 »
HAHAHA... love it!
I <3 DGArray's :D

PC:
AMD RYzen 7 1700 @3.9Ghz, 16GB HyperX Fury 2666Mhz Ram, ASUS ROG GTX 1060 STRIX 6GB, Windows 10 Pro 64Bit, MSi Tomahawk B350 Mainboard