Merge pull request #4735 from cg110/fix_web_server_mem_leak
[vuplus_xbmc] / tools / TexturePacker / SDL_anigif.cpp
1 /*
2     SDL_anigif:  An example animated GIF image loading library for use with SDL
3     SDL_image Copyright (C) 1997-2006 Sam Lantinga
4     Animated GIF "derived work" Copyright (C) 2006 Doug McFadyen
5
6     This library is free software; you can redistribute it and/or
7     modify it under the terms of the GNU Lesser General Public
8     License as published by the Free Software Foundation; either
9     version 2.1 of the License, or (at your option) any later version.
10
11     This library is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14     Lesser General Public License for more details.
15
16     You should have received a copy of the GNU Lesser General Public
17     License along with this library; if not, write to the Free Software
18     Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19 */
20
21 #include <stdio.h>
22 #include <string.h>
23 #include <stdlib.h>
24 #include "SDL_anigif.h"
25
26
27
28 /* Code from here to end of file has been adapted from XPaint:           */
29 /* +-------------------------------------------------------------------+ */
30 /* | Copyright 1990, 1991, 1993 David Koblas.                          | */
31 /* | Copyright 1996 Torsten Martinsen.                                 | */
32 /* |   Permission to use, copy, modify, and distribute this software   | */
33 /* |   and its documentation for any purpose and without fee is hereby | */
34 /* |   granted, provided that the above copyright notice appear in all | */
35 /* |   copies and that both that copyright notice and this permission  | */
36 /* |   notice appear in supporting documentation.  This software is    | */
37 /* |   provided "as is" without express or implied warranty.           | */
38 /* +-------------------------------------------------------------------+ */
39 /* Adapted for use in SDL by Sam Lantinga -- 7/20/98 */
40 /* Animated GIF support by Doug McFadyen -- 10/19/06 */
41
42 #define MAXCOLORMAPSIZE                 256
43
44 #define TRUE                                    1
45 #define FALSE                                   0
46
47 #define CM_RED                                  0
48 #define CM_GREEN                                1
49 #define CM_BLUE                                 2
50
51 #define MAX_LWZ_BITS                    12
52
53 #define INTERLACE                               0x40
54 #define LOCALCOLORMAP                   0x80
55 #define BitSet(byte,bit)                (((byte) & (bit)) == (bit))
56 #define LM_to_uint(a,b)                 (((b)<<8)|(a))
57
58 #define SDL_SetError(t)                 ((void)0)               /* We're not SDL so ignore error reporting */
59
60
61 typedef struct
62 {
63         unsigned int    Width;
64         unsigned int    Height;
65         unsigned char   ColorMap[3][MAXCOLORMAPSIZE];
66         unsigned int    BitPixel;
67         unsigned int    ColorResolution;
68         unsigned int    Background;
69         unsigned int    AspectRatio;
70 } gifscreen;
71
72 typedef struct
73 {
74         int                             transparent;
75         int                             delayTime;
76         int                             inputFlag;
77         int                             disposal;
78 } gif89;
79
80 typedef struct
81 {
82         /* global data */
83         SDL_RWops*              src;
84         gifscreen               gs;
85         gif89                   g89;
86         int                             zerodatablock;
87         /* AG_LoadGIF_RW data */
88         unsigned char   localColorMap[3][MAXCOLORMAPSIZE];
89         /* GetCode data */
90         unsigned char   buf[280];
91         int                             curbit, lastbit, done, lastbyte;
92         /* LWZReadByte data */
93         int                             fresh, code, incode;
94         int                             codesize, setcodesize;
95         int                             maxcode, maxcodesize;
96         int                             firstcode, oldcode;
97         int                             clearcode, endcode;
98         int                             table[2][(1 << MAX_LWZ_BITS)];
99         int                             stack[(1 << (MAX_LWZ_BITS))*2], *sp;
100 } gifdata;
101
102
103
104 static int                      ReadColorMap( gifdata* gd, int number, unsigned char buffer[3][MAXCOLORMAPSIZE] );
105 static int                      DoExtension( gifdata* gd, int label );
106 static int                      GetDataBlock( gifdata* gd, unsigned char* buf );
107 static int                      GetCode( gifdata* gd, int code_size, int flag );
108 static int                      LWZReadByte( gifdata* gd, int flag, int input_code_size );
109 static SDL_Surface*     ReadImage( gifdata* gd, int len, int height, int, unsigned char cmap[3][MAXCOLORMAPSIZE], int interlace, int ignore );
110
111
112
113 /*--------------------------------------------------------------------------*
114  *
115  *--------------------------------------------------------------------------*/
116 int AG_isGIF( SDL_RWops* src )
117 {
118         int isGIF = FALSE;
119
120         if ( src )
121         {
122                 int start = SDL_RWtell( src );
123                 char magic[6];
124
125                 if ( SDL_RWread(src,magic,sizeof(magic),1) )
126                 {
127                         if ( (strncmp(magic,"GIF",3) == 0) && ((memcmp(magic+3,"87a",3) == 0) || (memcmp(magic+3,"89a",3) == 0)) )
128                         {
129                                 isGIF = TRUE;
130                         }
131                 }
132
133                 SDL_RWseek( src, start, SEEK_SET );
134         }
135
136         return isGIF;
137 }
138
139
140
141 /*--------------------------------------------------------------------------*
142  *
143  *--------------------------------------------------------------------------*/
144 int AG_LoadGIF( const char* file, AG_Frame* frames, int size )
145 {
146         int n = 0;
147
148         SDL_RWops* src = SDL_RWFromFile( file, "rb" );
149
150         if ( src )
151         {
152                 n = AG_LoadGIF_RW( src, frames, size );
153                 SDL_RWclose( src );
154         }
155
156         return n;
157 }
158
159
160
161 /*--------------------------------------------------------------------------*
162  *
163  *--------------------------------------------------------------------------*/
164 void AG_FreeSurfaces( AG_Frame* frames, int nFrames )
165 {
166         int i;
167
168         if ( frames )
169         {
170                 for ( i = 0; i < nFrames; i++ )
171                 {
172                         if ( frames[i].surface )
173                         {
174                                 SDL_FreeSurface( frames[i].surface );
175                                 frames[i].surface = NULL;
176                         }
177                 }
178         }
179 }
180
181
182
183 /*--------------------------------------------------------------------------*
184  *
185  *--------------------------------------------------------------------------*/
186 int AG_ConvertSurfacesToDisplayFormat( AG_Frame* frames, int nFrames )
187 {
188         int i;
189         int n = 0;
190
191         if ( frames )
192         {
193                 for ( i = 0; i < nFrames; i++ )
194                 {
195                         if ( frames[i].surface )
196                         {
197                                 SDL_Surface* surface = (frames[i].surface->flags & SDL_SRCCOLORKEY) ? SDL_DisplayFormatAlpha(frames[i].surface) : SDL_DisplayFormat(frames[i].surface);
198
199                                 if ( surface )
200                                 {
201                                         SDL_FreeSurface( frames[i].surface );
202                                         frames[i].surface = surface;
203                                         n++;
204                                 }
205                         }
206                 }
207         }
208
209         return n;
210 }
211
212
213
214 /*--------------------------------------------------------------------------*
215  *
216  *--------------------------------------------------------------------------*/
217 int AG_NormalizeSurfacesToDisplayFormat( AG_Frame* frames, int nFrames )
218 {
219         int n = 0;
220
221         if ( nFrames > 0 && frames && frames[0].surface )
222         {
223                 SDL_Surface* mainSurface = (frames[0].surface->flags & SDL_SRCCOLORKEY) ? SDL_DisplayFormatAlpha(frames[0].surface) : SDL_DisplayFormat(frames[0].surface);
224                 const int newDispose = (frames[0].surface->flags & SDL_SRCCOLORKEY) ? AG_DISPOSE_RESTORE_BACKGROUND : AG_DISPOSE_NONE;
225
226                 if ( mainSurface )
227                 {
228                         int i;
229                         int lastDispose = AG_DISPOSE_NA;
230                         int iRestore = 0;
231                         const Uint8 alpha = (frames[0].disposal == AG_DISPOSE_NONE) ? SDL_ALPHA_OPAQUE : SDL_ALPHA_TRANSPARENT;
232
233                         SDL_FillRect( mainSurface, NULL, SDL_MapRGBA(mainSurface->format,0,0,0,alpha) );
234
235                         for ( i = 0; i < nFrames; i++ )
236                         {
237                                 if ( frames[i].surface )
238                                 {
239                                         SDL_Surface* surface = SDL_ConvertSurface( mainSurface, mainSurface->format, mainSurface->flags );
240
241                                         if ( surface )
242                                         {
243                                                 SDL_Rect r;
244
245                                                 if ( lastDispose == AG_DISPOSE_NONE )
246                                                         SDL_BlitSurface( frames[i-1].surface, NULL, surface, NULL );
247
248                                                 if ( lastDispose == AG_DISPOSE_RESTORE_PREVIOUS )
249                                                         SDL_BlitSurface( frames[iRestore].surface, NULL, surface, NULL );
250                                                 if ( frames[i].disposal != AG_DISPOSE_RESTORE_PREVIOUS )
251                                                         iRestore = i;
252
253                                                 r.x = (Sint16)frames[i].x;
254                                                 r.y = (Sint16)frames[i].y;
255                                                 SDL_BlitSurface( frames[i].surface, NULL, surface, &r );
256
257                                                 SDL_FreeSurface( frames[i].surface );
258                                                 frames[i].surface = surface;
259                                                 frames[i].x = frames[i].y = 0;
260                                                 lastDispose = frames[i].disposal;
261                                                 frames[i].disposal = newDispose;
262                                                 n++;
263                                         }
264                                 }
265                         }
266
267                         SDL_FreeSurface( mainSurface );
268                 }
269         }
270
271         return n;
272 }
273
274
275
276 /*--------------------------------------------------------------------------*
277  *
278  *--------------------------------------------------------------------------*/
279 int AG_LoadGIF_RW( SDL_RWops* src, AG_Frame* frames, int maxFrames )
280 {
281         int start;
282         unsigned char buf[16];
283         unsigned char c;
284         int useGlobalColormap;
285         int bitPixel;
286         int iFrame = 0;
287         char version[4];
288         SDL_Surface* image = NULL;
289         gifdata* gd;
290
291         if ( src == NULL )
292                 return 0;
293
294         gd = (gifdata*)malloc( sizeof(*gd) );
295         memset( gd, 0, sizeof(*gd) );
296         gd->src = src;
297
298         start = SDL_RWtell( src );
299
300         if ( !SDL_RWread(src,buf,6,1) )
301         {
302                 SDL_SetError( "error reading magic number" );
303                 goto done;
304         }
305
306         if ( strncmp((char*)buf,"GIF",3) != 0 )
307         {
308                 SDL_SetError( "not a GIF file" );
309                 goto done;
310         }
311
312         strncpy( version, (char*)buf+3, 3 );
313         version[3] = '\0';
314
315         if ( (strcmp(version,"87a") != 0) && (strcmp(version,"89a") != 0) )
316         {
317                 SDL_SetError( "bad version number, not '87a' or '89a'" );
318                 goto done;
319         }
320
321         gd->g89.transparent     = -1;
322         gd->g89.delayTime       = -1;
323         gd->g89.inputFlag       = -1;
324         gd->g89.disposal        = AG_DISPOSE_NA;
325
326         if ( !SDL_RWread(src,buf,7,1) )
327         {
328                 SDL_SetError( "failed to read screen descriptor" );
329                 goto done;
330         }
331
332         gd->gs.Width                    = LM_to_uint(buf[0],buf[1]);
333         gd->gs.Height                   = LM_to_uint(buf[2],buf[3]);
334         gd->gs.BitPixel                 = 2 << (buf[4] & 0x07);
335         gd->gs.ColorResolution  = (((buf[4] & 0x70) >> 3) + 1);
336         gd->gs.Background               = buf[5];
337         gd->gs.AspectRatio              = buf[6];
338
339         if ( BitSet(buf[4],LOCALCOLORMAP) )             /* Global Colormap */
340         {
341                 if ( ReadColorMap(gd,gd->gs.BitPixel,gd->gs.ColorMap) )
342                 {
343                         SDL_SetError( "error reading global colormap" );
344                         goto done;
345                 }
346         }
347
348         do
349         {
350                 if ( !SDL_RWread(src,&c,1,1) )
351                 {
352                         SDL_SetError( "EOF / read error on image data" );
353                         goto done;
354                 }
355
356                 if ( c == ';' )         /* GIF terminator */
357                         goto done;
358
359                 if ( c == '!' )         /* Extension */
360                 {
361                         if ( !SDL_RWread(src,&c,1,1) )
362                         {
363                                 SDL_SetError( "EOF / read error on extention function code" );
364                                 goto done;
365                         }
366                         DoExtension( gd, c );
367                         continue;
368                 }
369
370                 if ( c != ',' )         /* Not a valid start character */
371                         continue;
372
373                 if ( !SDL_RWread(src,buf,9,1) )
374                 {
375                         SDL_SetError( "couldn't read left/top/width/height" );
376                         goto done;
377                 }
378
379                 useGlobalColormap = !BitSet(buf[8],LOCALCOLORMAP);
380                 bitPixel = 1 << ((buf[8] & 0x07) + 1);
381
382                 if ( !useGlobalColormap )
383                 {
384                         if ( ReadColorMap(gd,bitPixel,gd->localColorMap) )
385                         {
386                                 SDL_SetError( "error reading local colormap" );
387                                 goto done;
388                         }
389                         image = ReadImage( gd, LM_to_uint(buf[4],buf[5]), LM_to_uint(buf[6],buf[7]), bitPixel, gd->localColorMap, BitSet(buf[8],INTERLACE), (frames==NULL) );
390                 }
391                 else
392                 {
393                         image = ReadImage( gd, LM_to_uint(buf[4],buf[5]), LM_to_uint(buf[6],buf[7]), gd->gs.BitPixel, gd->gs.ColorMap, BitSet(buf[8],INTERLACE), (frames==NULL) );
394                 }
395
396                 if ( frames )
397                 {
398                         if ( image == NULL )
399                                 goto done;
400
401                         if ( gd->g89.transparent >= 0 )
402                                 SDL_SetColorKey( image, SDL_SRCCOLORKEY, gd->g89.transparent );
403
404                         frames[iFrame].surface  = image;
405                         frames[iFrame].x                = LM_to_uint(buf[0], buf[1]);
406                         frames[iFrame].y                = LM_to_uint(buf[2], buf[3]);
407                         frames[iFrame].disposal = gd->g89.disposal;
408                         frames[iFrame].delay    = gd->g89.delayTime*10;
409 /*                      gd->g89.transparent             = -1;                   ** Hmmm, not sure if this should be reset for each frame? */
410                 }
411
412                 iFrame++;
413         } while ( iFrame < maxFrames || frames == NULL );
414
415 done:
416         if ( image == NULL )
417                 SDL_RWseek( src, start, SEEK_SET );
418
419         free( gd );
420
421         return iFrame;
422 }
423
424
425
426 /*--------------------------------------------------------------------------*
427  *
428  *--------------------------------------------------------------------------*/
429 static int ReadColorMap( gifdata* gd, int number, unsigned char buffer[3][MAXCOLORMAPSIZE] )
430 {
431         int i;
432         unsigned char rgb[3];
433         int flag;
434
435         flag = TRUE;
436
437         for ( i = 0; i < number; ++i )
438         {
439                 if ( !SDL_RWread(gd->src,rgb,sizeof(rgb),1) )
440                 {
441                         SDL_SetError( "bad colormap" );
442                         return 1;
443                 }
444
445                 buffer[CM_RED][i]       = rgb[0];
446                 buffer[CM_GREEN][i]     = rgb[1];
447                 buffer[CM_BLUE][i]      = rgb[2];
448                 flag &= (rgb[0] == rgb[1] && rgb[1] == rgb[2]);
449         }
450
451         return FALSE;
452 }
453
454
455
456 /*--------------------------------------------------------------------------*
457  *
458  *--------------------------------------------------------------------------*/
459 static int DoExtension( gifdata* gd, int label )
460 {
461         unsigned char buf[256];
462
463         switch ( label )
464         {
465           case 0x01:            /* Plain Text Extension */
466                 break;
467
468           case 0xff:            /* Application Extension */
469                 break;
470
471           case 0xfe:            /* Comment Extension */
472                 while ( GetDataBlock(gd,buf) != 0 )
473                         ;
474                 return FALSE;
475
476           case 0xf9:            /* Graphic Control Extension */
477                 (void)GetDataBlock( gd, buf );
478                 gd->g89.disposal        = (buf[0] >> 2) & 0x7;
479                 gd->g89.inputFlag       = (buf[0] >> 1) & 0x1;
480                 gd->g89.delayTime       = LM_to_uint(buf[1],buf[2]);
481                 if ( (buf[0] & 0x1) != 0 )
482                         gd->g89.transparent = buf[3];
483
484                 while ( GetDataBlock(gd,buf) != 0 )
485                         ;
486                 return FALSE;
487         }
488
489         while ( GetDataBlock(gd,buf) != 0 )
490                 ;
491
492         return FALSE;
493 }
494
495
496
497 /*--------------------------------------------------------------------------*
498  *
499  *--------------------------------------------------------------------------*/
500 static int GetDataBlock( gifdata* gd, unsigned char* buf )
501 {
502         unsigned char count;
503
504         if ( !SDL_RWread(gd->src,&count,1,1) )
505         {
506                 /* pm_message("error in getting DataBlock size" ); */
507                 return -1;
508         }
509
510         gd->zerodatablock = count == 0;
511
512         if ( (count != 0) && !SDL_RWread(gd->src,buf,count,1) )
513         {
514                 /* pm_message("error in reading DataBlock" ); */
515                 return -1;
516         }
517
518         return count;
519 }
520
521
522
523 /*--------------------------------------------------------------------------*
524  *
525  *--------------------------------------------------------------------------*/
526 static int GetCode( gifdata* gd, int code_size, int flag )
527 {
528         int i, j, ret;
529         int count;
530
531         if ( flag )
532         {
533                 gd->curbit = 0;
534                 gd->lastbit = 0;
535                 gd->done = FALSE;
536                 return 0;
537         }
538
539         if ( (gd->curbit + code_size) >= gd->lastbit )
540         {
541                 if ( gd->done )
542                 {
543                         if ( gd->curbit >= gd->lastbit )
544                         SDL_SetError( "ran off the end of my bits" );
545                         return -1;
546                 }
547
548                 gd->buf[0] = gd->buf[gd->lastbyte - 2];
549                 gd->buf[1] = gd->buf[gd->lastbyte - 1];
550
551                 if ( (count = GetDataBlock(gd, &gd->buf[2])) == 0 )
552                         gd->done = TRUE;
553
554                 gd->lastbyte = 2 + count;
555                 gd->curbit = (gd->curbit - gd->lastbit) + 16;
556                 gd->lastbit = (2 + count)*8;
557         }
558
559         ret = 0;
560         for ( i = gd->curbit, j = 0; j < code_size; ++i, ++j )
561                 ret |= ((gd->buf[i / 8] & (1 << (i % 8))) != 0) << j;
562
563         gd->curbit += code_size;
564
565         return ret;
566 }
567
568
569
570 /*--------------------------------------------------------------------------*
571  *
572  *--------------------------------------------------------------------------*/
573 static int LWZReadByte( gifdata* gd, int flag, int input_code_size )
574 {
575         int i, code, incode;
576
577         if ( flag )
578         {
579                 gd->setcodesize = input_code_size;
580                 gd->codesize    = gd->setcodesize + 1;
581                 gd->clearcode   = 1 << gd->setcodesize;
582                 gd->endcode             = gd->clearcode + 1;
583                 gd->maxcodesize = gd->clearcode*2;
584                 gd->maxcode             = gd->clearcode + 2;
585
586                 GetCode( gd, 0, TRUE );
587
588                 gd->fresh = TRUE;
589
590                 for ( i = 0; i < gd->clearcode; ++i )
591                 {
592                         gd->table[0][i] = 0;
593                         gd->table[1][i] = i;
594                 }
595
596                 for ( ; i < (1 << MAX_LWZ_BITS); ++i )
597                         gd->table[0][i] = gd->table[1][0] = 0;
598
599                 gd->sp = gd->stack;
600                 return 0;
601         }
602         else if ( gd->fresh )
603         {
604                 gd->fresh = FALSE;
605                 do
606                 {
607                         gd->firstcode = gd->oldcode = GetCode( gd, gd->codesize, FALSE );
608                 } while ( gd->firstcode == gd->clearcode );
609                 return gd->firstcode;
610         }
611
612         if ( gd->sp > gd->stack )
613                 return *--gd->sp;
614
615         while ( (code = GetCode(gd,gd->codesize,FALSE)) >= 0 )
616         {
617                 if ( code == gd->clearcode )
618                 {
619                         for ( i = 0; i < gd->clearcode; ++i )
620                         {
621                                 gd->table[0][i] = 0;
622                                 gd->table[1][i] = i;
623                         }
624
625                         for ( ; i < (1 << MAX_LWZ_BITS); ++i )
626                                 gd->table[0][i] = gd->table[1][i] = 0;
627
628                         gd->codesize    = gd->setcodesize + 1;
629                         gd->maxcodesize = gd->clearcode*2;
630                         gd->maxcode             = gd->clearcode + 2;
631                         gd->sp                  = gd->stack;
632                         gd->firstcode   = gd->oldcode = GetCode( gd, gd->codesize, FALSE );
633                         return gd->firstcode;
634                 }
635                 else if ( code == gd->endcode )
636                 {
637                         int count;
638                         unsigned char buf[260];
639
640                         if ( gd->zerodatablock )
641                                 return -2;
642
643                         while ( (count = GetDataBlock(gd,buf)) > 0 )
644                                 ;
645
646                         if ( count != 0 )
647                         {
648                                 /* pm_message("missing EOD in data stream (common occurence)"); */
649                         }
650                         return -2;
651                 }
652
653                 incode = code;
654
655                 if ( code >= gd->maxcode )
656                 {
657                         *gd->sp++ = gd->firstcode;
658                         code = gd->oldcode;
659                 }
660
661                 while ( code >= gd->clearcode )
662                 {
663                         *gd->sp++ = gd->table[1][code];
664                         if ( code == gd->table[0][code] )
665                                 SDL_SetError( "circular table entry BIG ERROR" );
666                         code = gd->table[0][code];
667                 }
668
669                 *gd->sp++ = gd->firstcode = gd->table[1][code];
670
671                 if ( (code = gd->maxcode) < (1 << MAX_LWZ_BITS) )
672                 {
673                         gd->table[0][code] = gd->oldcode;
674                         gd->table[1][code] = gd->firstcode;
675                         ++gd->maxcode;
676                         if ( (gd->maxcode >= gd->maxcodesize) && (gd->maxcodesize < (1 << MAX_LWZ_BITS)) )
677                         {
678                                 gd->maxcodesize *= 2;
679                                 ++gd->codesize;
680                         }
681                 }
682
683                 gd->oldcode = incode;
684
685                 if ( gd->sp > gd->stack )
686                         return *--gd->sp;
687         }
688
689         return code;
690 }
691
692
693
694 /*--------------------------------------------------------------------------*
695  *
696  *--------------------------------------------------------------------------*/
697 static SDL_Surface* ReadImage( gifdata* gd, int len, int height, int cmapSize, unsigned char cmap[3][MAXCOLORMAPSIZE], int interlace, int ignore )
698 {
699         SDL_Surface* image;
700         unsigned char c;
701         int i, v;
702         int xpos = 0, ypos = 0, pass = 0;
703
704         /* Initialize the compression routines */
705         if ( !SDL_RWread(gd->src,&c,1,1) )
706         {
707                 SDL_SetError( "EOF / read error on image data" );
708                 return NULL;
709         }
710
711         if ( LWZReadByte(gd,TRUE,c) < 0 )
712         {
713                 SDL_SetError( "error reading image" );
714                 return NULL;
715         }
716
717         /* If this is an "uninteresting picture" ignore it. */
718         if ( ignore )
719         {
720                 while ( LWZReadByte(gd,FALSE,c) >= 0 )
721                         ;
722                 return NULL;
723         }
724
725         image = SDL_AllocSurface( SDL_SWSURFACE, len, height, 8, 0, 0, 0, 0 );
726
727         for ( i = 0; i < cmapSize; i++ )
728         {
729                 image->format->palette->colors[i].r = cmap[CM_RED][i];
730                 image->format->palette->colors[i].g = cmap[CM_GREEN][i];
731                 image->format->palette->colors[i].b = cmap[CM_BLUE][i];
732         }
733
734         while ( (v = LWZReadByte(gd,FALSE,c)) >= 0 )
735         {
736                 ((Uint8*)image->pixels)[xpos + ypos*image->pitch] = (Uint8)v;
737                 ++xpos;
738
739                 if ( xpos == len )
740                 {
741                         xpos = 0;
742                         if ( interlace )
743                         {
744                                 switch ( pass )
745                                 {
746                                   case 0:
747                                   case 1:       ypos += 8;      break;
748                                   case 2:       ypos += 4;      break;
749                                   case 3:       ypos += 2;      break;
750                                 }
751
752                                 if ( ypos >= height )
753                                 {
754                                         ++pass;
755                                         switch ( pass )
756                                         {
757                                           case 1:       ypos = 4;       break;
758                                           case 2:       ypos = 2;       break;
759                                           case 3:       ypos = 1;       break;
760                                           default:      goto fini;
761                                         }
762                                 }
763                         }
764                         else
765                         {
766                                 ++ypos;
767                         }
768                 }
769
770                 if ( ypos >= height )
771                         break;
772         }
773
774 fini:
775         return image;
776 }
777