static int ReadImageDesc (MG_RWops *area, IMAGEDESC* ImageDesc, GIFSCREEN* GifScreen) { unsigned char buf[16]; if (!ReadOK (area, buf, 9)) { _MG_PRINTF ("EX_CTRL>GIF89a: bad image size\n"); return -1; } ImageDesc->Top = LM_to_uint (buf[0], buf[1]); ImageDesc->Left = LM_to_uint (buf[2], buf[3]); ImageDesc->Width = LM_to_uint (buf[4], buf[5]); ImageDesc->Height = LM_to_uint (buf[6], buf[7]); ImageDesc->haveColorMap = BitSet (buf[8], LOCALCOLORMAP); ImageDesc->bitPixel = 1 << ((buf[8] & 0x07) + 1); ImageDesc->interlace = BitSet(buf[8], INTERLACE); if (ImageDesc->haveColorMap) { _MG_PRINTF ("EX_CTRL>GIF89a: have local colormap\n"); if (ReadColorMap (area, ImageDesc->bitPixel, ImageDesc->ColorMap) < 0) { _MG_PRINTF ("EX_CTRL>GIF89a: bad local colormap\n"); return -1; } } else { memcpy (ImageDesc->ColorMap, GifScreen->ColorMap, MAXCOLORMAPSIZE*sizeof (RGB)); } return 0; }
static DFBResult GIFReadHeader( IDirectFBVideoProvider_GIF_data *data ) { DFBResult ret; u8 buf[7]; ret = FetchData( data->buffer, buf, 6 ); if (ret) { GIFERRORMSG("error reading header"); return ret; } if (memcmp( buf, "GIF", 3 )) { GIFERRORMSG("bad magic"); return DFB_UNSUPPORTED; } memcpy( data->Version, &buf[3], 3 ); data->Version[3] = '\0'; ret = FetchData( data->buffer, buf, 7 ); if (ret) { GIFERRORMSG("error reading screen descriptor"); return ret; } data->Width = LM_to_uint( buf[0], buf[1] ); data->Height = LM_to_uint( buf[2], buf[3] ); data->BitPixel = 2 << (buf[4] & 0x07); data->ColorResolution = (((buf[4] & 0x70) >> 3) + 1); data->Background = buf[5]; data->AspectRatio = buf[6]; if (data->AspectRatio) data->AspectRatio = ((data->AspectRatio + 15) << 8) >> 6; else
static int DoExtension (MG_RWops *area, int label, GIFSCREEN* GifScreen) { static unsigned char buf[256]; switch (label) { case 0x01: /* Plain Text Extension */ while (GetDataBlock (area, (unsigned char *) buf) != 0); break; case 0xff: /* Application Extension */ while (GetDataBlock (area, (unsigned char *) buf) != 0); break; case 0xfe: /* Comment Extension */ while (GetDataBlock (area, (unsigned char *) buf) != 0); return 0; case 0xf9: /* Graphic Control Extension */ GetDataBlock (area, (unsigned char *) buf); GifScreen->disposal = (buf[0] >> 2) & 0x7;//000 000 0 0 the middle 2 bit is disposal GifScreen->inputFlag = (buf[0] >> 1) & 0x1;//000 000 0 0 the secand last bit //is user input flag GifScreen->delayTime = LM_to_uint(buf[1], buf[2]); if ((buf[0] & 0x1) != 0)// 000 000 0 0 the last bit is transparent flag GifScreen->transparent = buf[3]; else GifScreen->transparent = -1; while (GetDataBlock (area, (unsigned char *) buf) != 0); return 0; default: while (GetDataBlock (area, (unsigned char *) buf) != 0); break; } return 0; }
/*--------------------------------------------------------------------------*/ static int DoExtension( gifdata* gd, int label ) { unsigned char buf[256]; switch ( label ) { case 0x01: /* Plain Text Extension */ break; case 0xff: /* Application Extension */ break; case 0xfe: /* Comment Extension */ while ( GetDataBlock(gd,buf) != 0 ) ; return FALSE; case 0xf9: /* Graphic Control Extension */ (void)GetDataBlock( gd, buf ); gd->g89.disposal = (buf[0] >> 2) & 0x7; gd->g89.inputFlag = (buf[0] >> 1) & 0x1; gd->g89.delayTime = LM_to_uint(buf[1],buf[2]); if ( (buf[0] & 0x1) != 0 ) gd->g89.transparent = buf[3]; while ( GetDataBlock(gd,buf) != 0 ) ; return FALSE; } while ( GetDataBlock(gd,buf) != 0 ) ; return FALSE; }
static int ReadGIFGlobal (MG_RWops *area, GIFSCREEN* GifScreen) { unsigned char buf[9]; unsigned char version[4]; if (!ReadOK (area, buf, 6)) return -1; /* not gif image*/ if (strncmp((char *) buf, "GIF", 3) != 0) return -1; strncpy ((char*)version, (char *) buf + 3, 3); version [3] = '\0'; if (strcmp ((const char*)version, "87a") != 0 && strcmp ((const char*)version, "89a") != 0) { _MG_PRINTF ("EX_CTRL>GIF89a: GIF version number not 87a or 89a.\n"); return -1; /* image loading error*/ } GifScreen->Background = -1; GifScreen->transparent = -1; GifScreen->delayTime = -1; GifScreen->inputFlag = -1; GifScreen->disposal = 0; if (!ReadOK (area, buf, 7)) { _MG_PRINTF ("EX_CTRL>GIF89a: bad screen descriptor\n"); return -1; /* image loading error*/ } GifScreen->Width = LM_to_uint (buf[0], buf[1]); GifScreen->Height = LM_to_uint (buf[2], buf[3]); GifScreen->BitPixel = 2 << (buf[4] & 0x07); GifScreen->ColorResolution = (((buf[4] & 0x70) >> 3) + 1); GifScreen->Background = buf[5]; GifScreen->AspectRatio = buf[6]; if (BitSet(buf[4], LOCALCOLORMAP)) { /* Global Colormap */ _MG_PRINTF ("EX_CTRL>GIF89a: have global colormap: %d\n", GifScreen->Background); if (ReadColorMap (area, GifScreen->BitPixel, GifScreen->ColorMap)) { _MG_PRINTF ("EX_CTRL>GIF89a: bad global colormap\n"); return -1; /* image loading error*/ } } return 0; }
static int DoExtension( IDirectFBVideoProvider_GIF_data *data, int label ) { unsigned char buf[256] = { 0 }; char *str; switch (label) { case 0x01: /* Plain Text Extension */ str = "Plain Text Extension"; break; case 0xff: /* Application Extension */ str = "Application Extension"; break; case 0xfe: /* Comment Extension */ str = "Comment Extension"; while (GetDataBlock( data->buffer, (u8*) buf ) != 0) GIFDEBUGMSG("gif comment: %s", buf); return false; case 0xf9: /* Graphic Control Extension */ str = "Graphic Control Extension"; (void) GetDataBlock( data->buffer, (u8*) buf ); data->disposal = (buf[0] >> 2) & 0x7; data->inputFlag = (buf[0] >> 1) & 0x1; if (LM_to_uint( buf[1], buf[2] )) data->delayTime = LM_to_uint( buf[1], buf[2] ) * 10000; if ((buf[0] & 0x1) != 0) data->transparent = buf[3]; else data->transparent = -1; while (GetDataBlock( data->buffer, (u8*) buf ) != 0) ; return false; default: str = (char*) buf; snprintf(str, 256, "UNKNOWN (0x%02x)", label); break; } GIFDEBUGMSG("got a '%s' extension", str ); while (GetDataBlock( data->buffer, (u8*) buf ) != 0); return 0; }
static int DoExtension(SDL_RWops *src, int label) { static unsigned char buf[256]; char *str; switch (label) { case 0x01: /* Plain Text Extension */ str = "Plain Text Extension"; break; case 0xff: /* Application Extension */ str = "Application Extension"; break; case 0xfe: /* Comment Extension */ str = "Comment Extension"; while (GetDataBlock(src, (unsigned char *) buf) != 0) ; return FALSE; case 0xf9: /* Graphic Control Extension */ str = "Graphic Control Extension"; (void) GetDataBlock(src, (unsigned char *) buf); Gif89.disposal = (buf[0] >> 2) & 0x7; Gif89.inputFlag = (buf[0] >> 1) & 0x1; Gif89.delayTime = LM_to_uint(buf[1], buf[2]); if ((buf[0] & 0x1) != 0) Gif89.transparent = buf[3]; while (GetDataBlock(src, (unsigned char *) buf) != 0) ; return FALSE; default: str = (char *)buf; SDL_snprintf(str, 256, "UNKNOWN (0x%02x)", label); break; } while (GetDataBlock(src, (unsigned char *) buf) != 0) ; return FALSE; }
static int DoExtension(GifFrame* frame, SDL_RWops *src, int label) { static unsigned char buf[256]; char *str; switch (label) { case 0x01: /* Plain Text Extension */ dbgout("Plain Text Extension\n"); break; case 0xff: /* Application Extension */ dbgout("Application Extension\n"); break; case 0xfe: /* Comment Extension */ dbgout("Comment Extension\n"); while (GetDataBlock(src, (unsigned char *) buf) != 0) ; return FALSE; case 0xf9: /* Graphic Control Extension */ dbgout("Graphic Control Extension\n"); (void) GetDataBlock(src, (unsigned char *) buf); frame->disposal = (buf[0] >> 2) & 0x7; frame->inputFlag = (buf[0] >> 1) & 0x1; frame->delayMs = LM_to_uint(buf[1], buf[2]); if ((buf[0] & 0x1) != 0) frame->transparent = buf[3]; while (GetDataBlock(src, (unsigned char *) buf) != 0) ; return FALSE; default: dbgout("Unknown Extension: %s (0x%02x)\n", (char*)buf, label); break; } while (GetDataBlock(src, (unsigned char *) buf) != 0) ; return FALSE; }
Image * IMG_LoadGIF_RW(SDL_RWops *src) { Sint64 start; unsigned char buf[16]; unsigned char c; unsigned char localColorMap[3][MAXCOLORMAPSIZE]; int grayScale; int useGlobalColormap; int bitPixel; int imageCount = 0; char version[4]; int imageNumber = 1; Image *image = NULL; if ( src == NULL ) { return NULL; } start = SDL_RWtell(src); if (!ReadOK(src, buf, 6)) { RWSetMsg("error reading magic number"); goto done; } if (SDL_strncmp((char *) buf, "GIF", 3) != 0) { RWSetMsg("not a GIF file"); goto done; } SDL_memcpy(version, (char *) buf + 3, 3); version[3] = '\0'; if ((SDL_strcmp(version, "87a") != 0) && (SDL_strcmp(version, "89a") != 0)) { RWSetMsg("bad version number, not '87a' or '89a'"); goto done; } Gif89.transparent = -1; Gif89.delayTime = -1; Gif89.inputFlag = -1; Gif89.disposal = 0; if (!ReadOK(src, buf, 7)) { RWSetMsg("failed to read screen descriptor"); goto done; } GifScreen.Width = LM_to_uint(buf[0], buf[1]); GifScreen.Height = LM_to_uint(buf[2], buf[3]); GifScreen.BitPixel = 2 << (buf[4] & 0x07); GifScreen.ColorResolution = (((buf[4] & 0x70) >> 3) + 1); GifScreen.Background = buf[5]; GifScreen.AspectRatio = buf[6]; if (BitSet(buf[4], LOCALCOLORMAP)) { /* Global Colormap */ if (ReadColorMap(src, GifScreen.BitPixel, GifScreen.ColorMap, &GifScreen.GrayScale)) { RWSetMsg("error reading global colormap"); goto done; } } do { if (!ReadOK(src, &c, 1)) { RWSetMsg("EOF / read error on image data"); goto done; } if (c == ';') { /* GIF terminator */ if (imageCount < imageNumber) { RWSetMsg("only %d image%s found in file", imageCount, imageCount > 1 ? "s" : ""); goto done; } } if (c == '!') { /* Extension */ if (!ReadOK(src, &c, 1)) { RWSetMsg("EOF / read error on extention function code"); goto done; } DoExtension(src, c); continue; } if (c != ',') { /* Not a valid start character */ continue; } ++imageCount; if (!ReadOK(src, buf, 9)) { RWSetMsg("couldn't read left/top/width/height"); goto done; } useGlobalColormap = !BitSet(buf[8], LOCALCOLORMAP); bitPixel = 1 << ((buf[8] & 0x07) + 1); if (!useGlobalColormap) { if (ReadColorMap(src, bitPixel, localColorMap, &grayScale)) { RWSetMsg("error reading local colormap"); goto done; } image = ReadImage(src, LM_to_uint(buf[4], buf[5]), LM_to_uint(buf[6], buf[7]), bitPixel, localColorMap, grayScale, BitSet(buf[8], INTERLACE), imageCount != imageNumber); } else { image = ReadImage(src, LM_to_uint(buf[4], buf[5]), LM_to_uint(buf[6], buf[7]), GifScreen.BitPixel, GifScreen.ColorMap, GifScreen.GrayScale, BitSet(buf[8], INTERLACE), imageCount != imageNumber); } } while (image == NULL); #ifdef USED_BY_SDL if ( Gif89.transparent >= 0 ) { SDL_SetColorKey(image, SDL_TRUE, Gif89.transparent); } #endif done: if ( image == NULL ) { SDL_RWseek(src, start, RW_SEEK_SET); } return image; }
void ReadGIFInfo(FILE *fd,int *width,int *height) { unsigned char buf[16]; unsigned char c; char version[4]; char *str; if (!ReadOK(fd,buf,6)){ strcpy(str,"error reading magic number"); pm_error(str); } if (strncmp((char*)buf,"GIF",3) != 0){ strcpy(str,"not a GIF file"); pm_error(str); } strncpy(version,(char*)buf+3,3); version[3] = '\0'; if ((strcmp(version,"87a") != 0) && (strcmp(version,"89a") != 0)){ strcpy(str,"bad version number, not '87a' or '89a'"); pm_error(str); } /*read logical screen*/ if (!ReadOK(fd,buf,7)){ strcpy(str,"failed to read screen descriptor"); pm_error(str); } GifScreen.Width = LM_to_uint(buf[0],buf[1]); GifScreen.Height = LM_to_uint(buf[2],buf[3]); GifScreen.BitPixel = 2<<(buf[4]&0x07); GifScreen.ColorResolution = (((buf[4]&0x70)>>3)+1); GifScreen.Background = buf[5]; GifScreen.AspectRatio = buf[6]; if (BitSet(buf[4],LOCALCOLORMAP)){ if (ReadColorMap(fd,GifScreen.BitPixel,GifScreen.ColorMap)){ strcpy(str,"error reading global color map"); pm_error(str); } } if (!ReadOK(fd,&c,1)){ strcpy(str,"EOF / read error on image data"); pm_error(str); } if (c == ';'){/*0x3B, GIF terminator*/ return; } if (c == '!'){/*0x21, Extension*/ if (!ReadOK(fd,&c,1)){ strcpy(str,"OF / read error on extension function code"); pm_error(str); } DoExtension(fd,c); } if (!ReadOK(fd,buf,8)){ strcpy(str,"couldn't read left/top/width/height"); pm_error(str); } *width = LM_to_uint(buf[4],buf[5]); *height = LM_to_uint(buf[6],buf[7]); return; }
/* TODO: (Chase) dump frames into frameset instead of combining into one frame */ int IMG_LoadGIF_RW(SDL_RWops *src, IMG_File* dst) { int start; unsigned char buf[16]; unsigned char c; unsigned char localColorMap[3][MAXCOLORMAPSIZE]; int grayScale; int useGlobalColormap; int bitPixel; int imageCount = 0; char version[4]; int imageNumber = 1; /*<-- I believe this is what we want to control in order to change what frame to grab*/ int successCount = 0; int w = 0; int i = 0; Uint32 color = 0; SDL_Surface*image = NULL; SDL_Surface*nextImage = NULL; GifFrame frame; GifFrame* frames; if ( src == NULL ) { return 0; } start = SDL_RWtell(src); if (!ReadOK(src, buf, 6)) { IMG_SetError("error reading magic number"); goto done; } if (strncmp((char *) buf, "GIF", 3) != 0) { IMG_SetError("not a GIF file"); goto done; } strncpy(version, (char *) buf + 3, 3); version[3] = '\0'; if ((strcmp(version, "87a") != 0) && (strcmp(version, "89a") != 0)) { IMG_SetError("bad version number, not '87a' or '89a'"); goto done; } frame.transparent = -1; frame.delayMs = -1; frame.inputFlag = -1; frame.disposal = 0; if (!ReadOK(src, buf, 7)) { IMG_SetError("failed to read screen descriptor"); goto done; } GifScreen.Width = LM_to_uint(buf[0], buf[1]); GifScreen.Height = LM_to_uint(buf[2], buf[3]); GifScreen.BitPixel = 2 << (buf[4] & 0x07); GifScreen.ColorResolution = (((buf[4] & 0x70) >> 3) + 1); GifScreen.Background = buf[5]; GifScreen.AspectRatio = buf[6]; if (BitSet(buf[4], LOCALCOLORMAP)) { /* Global Colormap */ if (ReadColorMap(src, GifScreen.BitPixel, GifScreen.ColorMap, &GifScreen.GrayScale)) { IMG_SetError("error reading global colormap"); goto done; } } dbgout("GLOBAL BG COLOR: Index:%i RGB:%i,%i,%i\n", GifScreen.Background, GifScreen.ColorMap[CM_RED][GifScreen.Background], GifScreen.ColorMap[CM_GREEN][GifScreen.Background], GifScreen.ColorMap[CM_BLUE][GifScreen.Background]); frames = (GifFrame*)malloc(sizeof(GifFrame)); if (!frames) { IMG_SetError("Malloc Failed"); goto done; } do { /* This loop goes through and reads every image and sends its data to ReadImage, if its the one we want (index 1) it'll output SDL_Surface*/ /* What this SHOULD do... METHOD 1 (Lazy): Read every image, output an SDL_Surface into a vector After loop, count vector images, make a new image which has a w equal to the vector.size() * image width Render each image from the vector onto the new image, each one with an x offset of image width * index Free all surfaces in the vector, return the new combined one. METHOD 2 (hardcore): Read every image, count the number of images we get. Create a surface with a w equal to count * width Go back and read every images data, writing their pixels, leftmost to images x * index GENERAL PROBLEM: We have no delay info. We'd have to manually set the frame delay... However, this isn't a problem. =3 Looks like we can have local layer color maps.. of course being able to do this in imageready is a whole other issue. But as far as we know.. maybe? */ if (!ReadOK(src, &c, 1)) { IMG_SetError("EOF / read error on image data"); goto done; } else dbgout("%c", c); if (c == ';') { /* GIF terminator -0x3b */ /*if (imageCount < imageNumber) { IMG_SetError("only %d image%s found in file", imageCount, imageCount > 1 ? "s" : ""); goto done; }*/ break; } if (c == '!') { /* Extension 0x21 */ if (!ReadOK(src, &c, 1)) { IMG_SetError("EOF / read error on extention function code"); goto done; } DoExtension(&frame, src, c); continue; } if (c != ',') { /* Image seperator - 0x2c */ continue; } ++imageCount; if (!ReadOK(src, buf, 9)) { IMG_SetError("couldn't read left/top/width/height"); goto done; } /* Offset Length Contents 0 1 byte Image Separator (0x2c) 1 2 bytes Image Left Position 3 2 bytes Image Top Position 5 2 bytes Image Width 7 2 bytes Image Height 8 1 byte bit 0: Local Color Table Flag (LCTF) bit 1: Interlace Flag bit 2: Sort Flag bit 2..3: Reserved bit 4..7: Size of Local Color Table: 2^(1+n) ? bytes Local Color Table(0..255 x 3 bytes) if LCTF is one 1 byte LZW Minimum Code Size [ // Blocks 1 byte Block Size (s) œSx (s)bytes Image Data ]* 1 byte Block Terminator(0x00) */ useGlobalColormap = !BitSet(buf[8], LOCALCOLORMAP); frame.x = LM_to_uint(buf[0], buf[1]); frame.y = LM_to_uint(buf[2], buf[3]); dbgout("X:%i, Y:%i\n", frame.x, frame.y); bitPixel = 1 << ((buf[8] & 0x07) + 1); dbgout("Checkpoint\n"); if (!useGlobalColormap) { if (ReadColorMap(src, bitPixel, localColorMap, &grayScale)) { IMG_SetError("error reading local colormap"); goto done; } image = ReadImage(src, LM_to_uint(buf[4], buf[5]), LM_to_uint(buf[6], buf[7]), bitPixel, localColorMap, grayScale, BitSet(buf[8], INTERLACE), 0); if (image) color = SDL_MapRGB(image->format, localColorMap[CM_RED][frame.transparent], localColorMap[CM_GREEN][frame.transparent], localColorMap[CM_BLUE][frame.transparent]); } else { image = ReadImage(src, LM_to_uint(buf[4], buf[5]), LM_to_uint(buf[6], buf[7]), GifScreen.BitPixel, GifScreen.ColorMap, GifScreen.GrayScale, BitSet(buf[8], INTERLACE), 0); if (image) color = SDL_MapRGB(image->format, GifScreen.ColorMap[CM_RED][frame.transparent], GifScreen.ColorMap[CM_GREEN][frame.transparent], GifScreen.ColorMap[CM_BLUE][frame.transparent]); } dbgout("Image: %p\n", image); if (image) { ++successCount; /*image = convertTo32bit(image); */ /* transform to a 32 bit surface because I HATE palettes*/ dbgout("Converted Image: %ix%i [%p]\n", image->w, image->h, image); if (image) { if ( frame.transparent >= 0 ) { SDL_SetColorKey(image, SDL_SRCCOLORKEY, frame.transparent); } /*if ( frame.transparent >= 0 ) { SDL_SetColorKey(image, SDL_SRCCOLORKEY, color); Uint8 r, g, b; SDL_GetRGB(color, image->format, &r, &g, &b); dbgout("Local Transparency: %i,%i,%i\n", r, g, b); }*/ /*Reallocate room for another image in the list*/ frames = (GifFrame*)realloc(frames, successCount * sizeof(GifFrame)); if (!frames) { /*realloc failed*/ IMG_SetError("Realloc Failed"); goto done; } frame.surf = image; /* Copy the current state of the GifFrame before the next read loop */ frames[successCount-1] = frame; /*int i = 0; while (i < successCount) { dbgout("Frames[%i]: %p\n", i, frames[i]); i++; }*/ image = NULL; } } } while (1); /*let the above ... goto's... handle it*/ SDL_Frame* framesArray; if (successCount > 0) { dbgout("Mallocing Frames %i\n", successCount);fflush(stdout); framesArray = IMG_MallocFrames(successCount); i = 0; //first frame image = SDL_CreateRGBSurface(SDL_SWSURFACE, GifScreen.Width, GifScreen.Height, 32, RMASK, GMASK, BMASK, 0); color = SDL_MapRGB(image->format, GifScreen.ColorMap[CM_RED][frames[0].transparent], GifScreen.ColorMap[CM_GREEN][frames[0].transparent], GifScreen.ColorMap[CM_BLUE][frames[0].transparent]); Uint8 r, g, b; SDL_GetRGB(color, image->format, &r, &g, &b); dbgout("Final Transparency: %i,%i,%i\n", r, g, b);fflush(stdout); if (color != 0) /* Ignore 0,0,0 as the transparent color */ { SDL_FillRect(image, NULL, color); SDL_SetColorKey(image, SDL_SRCCOLORKEY, color); /* use the first frames trans color */ } while (i < successCount) /* render our surfs and clear */ { if (image) { dbgout("Dimensions: %ix%i: %p\n", image->w, image->h, image);fflush(stdout); w = 0; SDL_Rect r2, r3; dbgout("Adding Frames[%i]: %p Disposal:%i TransIndex: %i Delay: %i Input:%i\n", i, frames[i].surf, frames[i].disposal, frames[i].transparent, frames[i].delayMs, frames[i].inputFlag); fflush(stdout); /* Print out the overlay at its offset coordinates */ r2.x = frames[i].x; r2.y = frames[i].y; r2.w = frames[i].surf->w; r2.h = frames[i].surf->h; dbgout("Drawing at: %i,%i\n", r2.x, r2.y);fflush(stdout); if (SDL_BlitSurface(frames[i].surf, NULL, image, &r2)) { /*something bad happened but ignore it for now. */ dbgout("Drawing Failed: %s\n", IMG_GetError());fflush(stdout); } dbgout("Setting Crap\n");fflush(stdout); //add image to our frames list framesArray[i].surf = image; framesArray[i].delay = frames[i].delayMs * 10; //HACK: All observed gifs have a delay of say.. 7, which means 70ms. framesArray[i].key = NULL; dbgout("i+1 crap\n");fflush(stdout); /*what to do in frame[i+1] before rendering*/ if (i + 1 < successCount) { //create next frame so we can do something to it nextImage = SDL_CreateRGBSurface(SDL_SWSURFACE, GifScreen.Width, GifScreen.Height, 32, RMASK, GMASK, BMASK, 0); color = SDL_MapRGB(nextImage->format, GifScreen.ColorMap[CM_RED][frames[0].transparent], GifScreen.ColorMap[CM_GREEN][frames[0].transparent], GifScreen.ColorMap[CM_BLUE][frames[0].transparent]); Uint8 r, g, b; SDL_GetRGB(color, nextImage->format, &r, &g, &b); dbgout("Final Transparency: %i,%i,%i\n", r, g, b);fflush(stdout); if (color != 0) /* Ignore 0,0,0 as the transparent color */ { SDL_FillRect(nextImage, NULL, color); SDL_SetColorKey(nextImage, SDL_SRCCOLORKEY, color); /* use the first frames trans color */ } dbgout("Disposal crap\n");fflush(stdout); switch (frames[i].disposal) { case DISPOSAL_PREVIOUSFRAME: /* 04h - Overwrite graphic with previous graphic */ dbgout("Doing previous frame\n");fflush(stdout); r2.x = 0; r2.y = 0; r2.w = GifScreen.Width; r2.h = GifScreen.Height; SDL_BlitSurface(frames[0].surf, NULL, nextImage, &r2); //Since I'm lazy, and haven't seen many gifs use this, it'll just render the original frame break; case DISPOSAL_UNSPECIFIED: /* DISPOSAL_UNSPECIFIED 00h - Let the viewer decide */ /*Drop down to donotdispose */ case DISPOSAL_DONOTDISPOSE: /* 01h - Leave graphic there */ dbgout("Doing nondispose\n");fflush(stdout); /*render a copy of the previous i-1 into i */ r2.w = GifScreen.Width; r2.h = GifScreen.Height; r2.x = 0; r2.y = 0; /* r3 = src, r2 = dst */ r3.w = GifScreen.Width; r3.h = GifScreen.Height; r3.x = 0; r3.y = 0; dbgout("r3:(%i,%i)%ix%i r2:(%i,%i)%ix%i\n", r3.x, r3.y, r3.w, r3.h, r2.x, r2.y, r2.w, r2.h);fflush(stdout); if (SDL_BlitSurface(image, &r3, nextImage, &r2)) { dbgout("Drawing Failed: %s\n", IMG_GetError());fflush(stdout); } break; default: /* This'll default to DISPOSAL_BGCOLORWIPE 02h - Overwrite graphic with background color do nothing, next rect is empty already*/ dbgout("Doing default %i\n", frames[i].disposal);fflush(stdout); break; } image = nextImage; } } i++; } i = 0; while (i < successCount) { SDL_FreeSurface(frames[i].surf); i++; } free(frames); frames = NULL; } else { image = NULL; } done: if (frames) { /* We didn't complete successfully, handle any leaks */ i = 0; while (i < successCount) { SDL_FreeSurface(frames[i].surf); i++; } free(frames); /*if (image) { SDL_FreeSurface(image); image = NULL; }*/ } /*if ( image == NULL ) { SDL_RWseek(src, start, SEEK_SET); } */ if (successCount > 0) { dst->frames = framesArray; dst->count = successCount; dst->format = IMG_FORMAT_GIF; return 1; } return 0; //return IMG_SurfaceToFrameset(image, sdlFrames, sdlFrameCount); }
/***** * Name: _PLC_GIF_Init * Return Type: void * Description: image initializer for GIF images * In: * plc: current PLC * Returns: * Nothing but PLC is updated. * Note: * As this routine must be fully re-entrant, it needs a lot of checks * to make sure we have the data we want fully available. * The drawback is that if we are being suspended while doing this * initialization, everything must be reset and repeated the next time * this routine is called. *****/ void _PLC_GIF_Init(PLC *plc) { Byte buf[16], c; PLCImageGIF *gif; gif = &(plc->object->plc_gif_image); _XmHTMLDebug(15, ("plc.c: _PLC_GIF_Init for %s\n", plc->url)); /* this plc is active */ plc->plc_status = PLC_ACTIVE; /***** * When this routine is called, the init method of this PLC has already * been called to determine the type of this PLC Image object. Therefore * we already have data available and we need to rewind the input buffer * back to the beginning. *****/ _PLCRewindInputBuffer(plc); /* we know this is a gif image, so skip magic */ gif->info->type = IMAGE_GIF; (void)_PLCReadOK(plc, buf, 6); /* read logical screen descriptor */ (void)_PLCReadOK(plc, buf, 7); /* image dimensions */ gif->width = LM_to_uint(buf[0],buf[1]); gif->height = LM_to_uint(buf[2],buf[3]); /* set colorspace and allocate a colormap */ gif->colorclass = XmIMAGE_COLORSPACE_INDEXED; gif->cmapsize = 2<<(buf[4]&0x07); /* * We may have been called before (but returned 'cause not enough data * was available). */ if(gif->cmap == NULL) gif->cmap = (XCOLOR*)calloc(gif->cmapsize, sizeof(XCOLOR)); /* image is initially fully opaque */ gif->transparency = XmNONE; gif->bg_pixel = -1; /* * Incoming data buffer. This is *way* too much as the incoming data * will be compressed (but it does make sure there is enough room) */ gif->buf_size = gif->width*gif->height; gif->buf_pos = 0; /* current pos in data received so far */ gif->byte_count = 0; /* size of data received so far */ if(gif->buffer == NULL) gif->buffer = (Byte*)calloc(gif->buf_size + 1, sizeof(Byte)); /* check if a global colormap is available */ if(BitSet(buf[4], LOCALCOLORMAP)) { if(!(ReadColormap(plc, gif))) { /* premature end of data. */ if(plc->plc_data_status == STREAM_END) { _XmHTMLWarning(__WFUNC__(gif->owner, "_PLC_GIF_Init"), XMHTML_MSG_106, plc->url, "global"); plc->plc_status = PLC_ABORT; } return; /* no global colormap! */ } } /* process all extensions */ c = 0; while(c != ',') { if(!_PLCReadOK(plc, &c, 1)) return; if (c == ';') /* GIF terminator */ { _XmHTMLWarning(__WFUNC__(gif->owner, "_PLC_GIF_Init"), XMHTML_MSG_107, plc->url, "pixel data"); plc->plc_status = PLC_ABORT; return; } if(c == '!') /* Extension */ { if(!_PLCReadOK(plc,&c,1)) { if(plc->plc_data_status == STREAM_END) { _XmHTMLWarning(__WFUNC__(gif->owner, "_PLC_GIF_Init"), XMHTML_MSG_107, plc->url, "extension block type"); plc->plc_status = PLC_ABORT; } return; } if(!(DoExtension(plc, c))) { if(plc->plc_data_status == STREAM_END) { _XmHTMLWarning(__WFUNC__(gif->owner, "_PLC_GIF_Init"), XMHTML_MSG_107, plc->url, "extension block"); plc->plc_status = PLC_ABORT; } return; } continue; } if (c != ',') continue; /* Not a valid start character */ } /* get image descriptor */ if(!_PLCReadOK(plc, buf, 9)) return; /* see if we are to use a local colormap */ if(BitSet(buf[8], LOCALCOLORMAP)) { /* local colormap size */ gif->ncolors = 1<<((buf[8]&0x07)+1); /* do we also have a glocal colormap? */ if(gif->cmap) free(gif->cmap); gif->cmapsize = gif->ncolors; gif->cmap = (XCOLOR*)calloc(gif->cmapsize, sizeof(XCOLOR)); if(!(ReadColormap(plc, gif))) { /* premature end of data. */ if(plc->plc_data_status == STREAM_END) { _XmHTMLWarning(__WFUNC__(gif->owner, "_PLC_GIF_Init"), XMHTML_MSG_106, plc->url, "local"); plc->plc_status = PLC_ABORT; } return; /* no global colormap! */ } } gif->ncolors = gif->cmapsize; /* sanity check: image *must* have a colormap */ if(gif->cmap == NULL) { _XmHTMLWarning(__WFUNC__(gif->owner, "_PLC_GIF_Init"), XMHTML_MSG_106, plc->url, "global or local"); plc->plc_status = PLC_ABORT; return; /* no global colormap! */ } /* image depth (= codeSize in GIF images, unused in GZF images) */ if(!(_PLCReadOK(plc, &c, 1))) return; gif->depth = (int)(c & 0xff); /* check interlacing */ if(BitSet(buf[8], INTERLACE)) { /* interlaced gifs require 4 passes and use an initial rowstride of 8 */ gif->npasses = 4; gif->stride = 8; } else { /* regular gif, 1 pass will get us the entire image */ gif->npasses = 1; gif->stride = 0; } gif->curr_pass = 0; gif->curr_scanline = 0; /***** * This routine is also used for GZF images, so before initializing * the LZWStream object we need to make sure we have been called for * a true GIF image. *****/ if(plc->object->type == plcGIF) { XmHTMLWidget html = plc->object->plc_any.owner; if(HTML_ATTR(gif_proc) != NULL) { gif->external_codec = True; gif->inflate = HTML_ATTR(gif_proc); if((gif->gstream = (XmHTMLGIFStream*)malloc(sizeof(XmHTMLGIFStream))) == NULL) { /* out of memory, too bad then */ _XmHTMLWarning(__WFUNC__(gif->owner, "_PLC_GIF_Init"), XMHTML_MSG_113, plc->url, sizeof(XmHTMLGIFStream)); plc->plc_status = PLC_ABORT; return; } /* initialize GIFStream object */ memset(gif->gstream, 0, sizeof(XmHTMLGIFStream)); gif->gstream->codesize = (int)c; gif->gstream->state = GIF_STREAM_INIT; gif->gstream->next_out = gif->buffer; gif->gstream->avail_out = gif->buf_size + 1; gif->gstream->is_progressive = True; /* * and call external decoder so it can initialize its own data * structures */ if((gif->inflate(gif->gstream)) != GIF_STREAM_OK) { if(gif->gstream->msg != NULL) { _XmHTMLWarning(__WFUNC__(gif->owner, "_PLC_GIF_Init"), XMHTML_MSG_109, plc->url, gif->gstream->msg ? gif->gstream->msg : "(unknown error)"); } /* external decoder initalization failed, abort and return */ plc->plc_status = PLC_ABORT; return; } gif->gstream->state = GIF_STREAM_OK; } else { /* initialize local data buffer */ gif->ib.file = plc->url; gif->ib.buffer = gif->buffer; gif->ib.size = 0; gif->ib.next = 0; gif->ib.type = IMAGE_GIF; gif->ib.depth = gif->depth; gif->ib.may_free = False; /* initialize LZWStream object */ if(gif->lstream == NULL) { if((gif->lstream = LZWStreamCreate(&(gif->ib), html->html.zCmd)) == NULL) { /* couldn't create stream, abort and return */ plc->plc_status = PLC_ABORT; return; } /* set read functions */ gif->lstream->readOK = _XmHTMLGifReadOK; gif->lstream->getData = _XmHTMLGifGetDataBlock; } /* first byte in buffer is gif codesize */ gif->ib.buffer[0] = c; gif->ib.size = 1; } /* allocate room for final image data */ if(gif->data == NULL) { gif->data = (Byte*)calloc(gif->buf_size + 1, sizeof(Byte)); /* don't allocate clipmask yet, it's done in the plc code */ } gif->data_size = gif->buf_size; gif->data_pos = 0; } /* object has been initialized */ plc->initialized = True; plc->curr_obj_func = 0; /* move to GIF scanline reader */ return; }
static gint DoExtension (FILE *fd, gint label) { static guchar buf[256]; gchar *str; switch (label) { case 0x01: /* Plain Text Extension */ str = "Plain Text Extension"; #ifdef notdef if (GetDataBlock (fd, (guchar *) buf) == 0) ; lpos = LM_to_uint (buf[0], buf[1]); tpos = LM_to_uint (buf[2], buf[3]); width = LM_to_uint (buf[4], buf[5]); height = LM_to_uint (buf[6], buf[7]); cellw = buf[8]; cellh = buf[9]; foreground = buf[10]; background = buf[11]; while (GetDataBlock (fd, (guchar *) buf) > 0) { PPM_ASSIGN (image[ypos][xpos], cmap[CM_RED][v], cmap[CM_GREEN][v], cmap[CM_BLUE][v]); ++index; } return FALSE; #else break; #endif case 0xff: /* Application Extension */ str = "Application Extension"; break; case 0xfe: /* Comment Extension */ str = "Comment Extension"; while (GetDataBlock (fd, (guchar *) buf) > 0) { gchar *comment = (gchar *) buf; if (! g_utf8_validate (comment, -1, NULL)) continue; if (comment_parasite) gimp_parasite_free (comment_parasite); comment_parasite = gimp_parasite_new ("gimp-comment", GIMP_PARASITE_PERSISTENT, strlen (comment) + 1, comment); } return TRUE; break; case 0xf9: /* Graphic Control Extension */ str = "Graphic Control Extension"; (void) GetDataBlock (fd, (guchar *) buf); Gif89.disposal = (buf[0] >> 2) & 0x7; Gif89.inputFlag = (buf[0] >> 1) & 0x1; Gif89.delayTime = LM_to_uint (buf[1], buf[2]); if ((buf[0] & 0x1) != 0) Gif89.transparent = buf[3]; else Gif89.transparent = -1; while (GetDataBlock (fd, (guchar *) buf) > 0); return FALSE; break; default: str = (gchar *)buf; sprintf ((gchar *)buf, "UNKNOWN (0x%02x)", label); break; } #ifdef GIFDEBUG g_print ("GIF: got a '%s'\n", str); #endif while (GetDataBlock (fd, (guchar *) buf) > 0); return FALSE; }
static gint32 load_image (const gchar *filename, gboolean thumbnail, GError **error) { FILE *fd; guchar buf[16]; guchar c; CMap localColorMap; gint grayScale; gboolean useGlobalColormap; gint bitPixel; gint imageCount = 0; gchar version[4]; gint32 image_ID = -1; fd = g_fopen (filename, "rb"); if (! fd) { g_set_error (error, G_FILE_ERROR, g_file_error_from_errno (errno), _("Could not open '%s' for reading: %s"), gimp_filename_to_utf8 (filename), g_strerror (errno)); return -1; } gimp_progress_init_printf (_("Opening '%s'"), gimp_filename_to_utf8 (filename)); if (! ReadOK (fd, buf, 6)) { g_message ("Error reading magic number"); return -1; } if (strncmp ((gchar *) buf, "GIF", 3) != 0) { g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED, "%s", _("This is not a GIF file")); return -1; } strncpy (version, (gchar *) buf + 3, 3); version[3] = '\0'; if ((strcmp (version, "87a") != 0) && (strcmp (version, "89a") != 0)) { g_message ("Bad version number, not '87a' or '89a'"); return -1; } if (! ReadOK (fd, buf, 7)) { g_message ("Failed to read screen descriptor"); return -1; } GifScreen.Width = LM_to_uint (buf[0], buf[1]); GifScreen.Height = LM_to_uint (buf[2], buf[3]); GifScreen.BitPixel = 2 << (buf[4] & 0x07); GifScreen.ColorResolution = (((buf[4] & 0x70) >> 3) + 1); GifScreen.Background = buf[5]; GifScreen.AspectRatio = buf[6]; if (BitSet (buf[4], LOCALCOLORMAP)) { /* Global Colormap */ if (! ReadColorMap (fd, GifScreen.BitPixel, GifScreen.ColorMap, &GifScreen.GrayScale)) { g_message ("Error reading global colormap"); return -1; } } if (GifScreen.AspectRatio != 0 && GifScreen.AspectRatio != 49) { g_message (_("Non-square pixels. Image might look squashed.")); } highest_used_index = 0; while (TRUE) { if (! ReadOK (fd, &c, 1)) { g_message ("EOF / read error on image data"); return image_ID; /* will be -1 if failed on first image! */ } if (c == ';') { /* GIF terminator */ return image_ID; } if (c == '!') { /* Extension */ if (! ReadOK (fd, &c, 1)) { g_message ("EOF / read error on extension function code"); return image_ID; /* will be -1 if failed on first image! */ } DoExtension (fd, c); continue; } if (c != ',') { /* Not a valid start character */ g_printerr ("GIF: bogus character 0x%02x, ignoring.\n", (int) c); continue; } ++imageCount; if (! ReadOK (fd, buf, 9)) { g_message ("Couldn't read left/top/width/height"); return image_ID; /* will be -1 if failed on first image! */ } useGlobalColormap = !BitSet (buf[8], LOCALCOLORMAP); bitPixel = 1 << ((buf[8] & 0x07) + 1); if (! useGlobalColormap) { if (! ReadColorMap (fd, bitPixel, localColorMap, &grayScale)) { g_message ("Error reading local colormap"); return image_ID; /* will be -1 if failed on first image! */ } image_ID = ReadImage (fd, filename, LM_to_uint (buf[4], buf[5]), LM_to_uint (buf[6], buf[7]), localColorMap, bitPixel, grayScale, BitSet (buf[8], INTERLACE), imageCount, (guint) LM_to_uint (buf[0], buf[1]), (guint) LM_to_uint (buf[2], buf[3]), GifScreen.Width, GifScreen.Height); } else { image_ID = ReadImage (fd, filename, LM_to_uint (buf[4], buf[5]), LM_to_uint (buf[6], buf[7]), GifScreen.ColorMap, GifScreen.BitPixel, GifScreen.GrayScale, BitSet (buf[8], INTERLACE), imageCount, (guint) LM_to_uint (buf[0], buf[1]), (guint) LM_to_uint (buf[2], buf[3]), GifScreen.Width, GifScreen.Height); } if (comment_parasite != NULL) { if (! thumbnail) gimp_image_attach_parasite (image_ID, comment_parasite); gimp_parasite_free (comment_parasite); comment_parasite = NULL; } /* If we are loading a thumbnail, we stop after the first frame. */ if (thumbnail) break; } return image_ID; }
/*--------------------------------------------------------------------------*/ int AG_LoadGIF_RW( SDL_RWops* src, AG_Frame* frames, int maxFrames ) { int start; unsigned char buf[16]; unsigned char c; int useGlobalColormap; int bitPixel; int iFrame = 0; char version[4]; SDL_Surface* image = NULL; gifdata* gd; if ( src == NULL ) return 0; gd = (gifdata *)malloc( sizeof(*gd) ); memset( gd, 0, sizeof(*gd) ); gd->src = src; start = SDL_RWtell( src ); if ( !SDL_RWread(src,buf,6,1) ) { SDL_SetError( "error reading magic number" ); goto done; } if ( strncmp((char*)buf,"GIF",3) != 0 ) { SDL_SetError( "not a GIF file" ); goto done; } strncpy( version, (char*)buf+3, 3 ); version[3] = '\0'; if ( (strcmp(version,"87a") != 0) && (strcmp(version,"89a") != 0) ) { SDL_SetError( "bad version number, not '87a' or '89a'" ); goto done; } gd->g89.transparent = -1; gd->g89.delayTime = -1; gd->g89.inputFlag = -1; gd->g89.disposal = AG_DISPOSE_NA; if ( !SDL_RWread(src,buf,7,1) ) { SDL_SetError( "failed to read screen descriptor" ); goto done; } gd->gs.Width = LM_to_uint(buf[0],buf[1]); gd->gs.Height = LM_to_uint(buf[2],buf[3]); gd->gs.BitPixel = 2 << (buf[4] & 0x07); gd->gs.ColorResolution = (((buf[4] & 0x70) >> 3) + 1); gd->gs.Background = buf[5]; gd->gs.AspectRatio = buf[6]; if ( BitSet(buf[4],LOCALCOLORMAP) ) /* Global Colormap */ { if ( ReadColorMap(gd,gd->gs.BitPixel,gd->gs.ColorMap) ) { SDL_SetError( "error reading global colormap" ); goto done; } } do { if ( !SDL_RWread(src,&c,1,1) ) { SDL_SetError( "EOF / read error on image data" ); goto done; } if ( c == ';' ) /* GIF terminator */ goto done; if ( c == '!' ) /* Extension */ { if ( !SDL_RWread(src,&c,1,1) ) { SDL_SetError( "EOF / read error on extention function code" ); goto done; } DoExtension( gd, c ); continue; } if ( c != ',' ) /* Not a valid start character */ continue; if ( !SDL_RWread(src,buf,9,1) ) { SDL_SetError( "couldn't read left/top/width/height" ); goto done; } useGlobalColormap = !BitSet(buf[8],LOCALCOLORMAP); bitPixel = 1 << ((buf[8] & 0x07) + 1); if ( !useGlobalColormap ) { if ( ReadColorMap(gd,bitPixel,gd->localColorMap) ) { SDL_SetError( "error reading local colormap" ); goto done; } 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) ); } else { 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) ); } if ( frames ) { if ( image == NULL ) goto done; if ( gd->g89.transparent >= 0 ) SDL_SetColorKey( image, SDL_SRCCOLORKEY, gd->g89.transparent ); frames[iFrame].surface = image; frames[iFrame].x = LM_to_uint(buf[0], buf[1]); frames[iFrame].y = LM_to_uint(buf[2], buf[3]); frames[iFrame].disposal = gd->g89.disposal; frames[iFrame].delay = gd->g89.delayTime*10; /* gd->g89.transparent = -1; ** Hmmm, not sure if this should be reset for each frame? */ } iFrame++; } while ( iFrame < maxFrames || frames == NULL ); done: if ( image == NULL ) SDL_RWseek( src, start, SEEK_SET ); free( gd ); return iFrame; }
static int DoExtension(byte **inbuf, int label, GifState *g) { char *str; char *buf = g->ext_buf; switch (label) { case 0x01: /* Plain Text Extension */ str = "Plain Text Extension"; #ifdef notdef if (GetDataBlock(inbuf, (unsigned char*) buf, g) == 0) ; lpos = LM_to_uint(buf[0], buf[1]); tpos = LM_to_uint(buf[2], buf[3]); width = LM_to_uint(buf[4], buf[5]); height = LM_to_uint(buf[6], buf[7]); cellw = buf[8]; cellh = buf[9]; foreground = buf[10]; background = buf[11]; while (GetDataBlock(inbuf, (unsigned char*) buf, g) != 0) { PPM_ASSIGN(image[ypos][xpos], cmap[CM_RED][v], cmap[CM_GREEN][v], cmap[CM_BLUE][v]); ++index; } return FALSE; #else break; #endif case 0xff: /* Application Extension */ str = "Application Extension"; break; case 0xfe: /* Comment Extension */ str = "Comment Extension"; while (GetDataBlock(inbuf, (unsigned char*) buf, g) != 0) { #ifdef DEBUG _gif_message("gif comment: %s", buf ); #endif } return FALSE; case 0xf9: /* Graphic Control Extension */ str = "Graphic Control Extension"; (void) GetDataBlock(inbuf, (unsigned char*) buf, g); g->Gif89.disposal = (buf[0] >> 2) & 0x7; g->Gif89.inputFlag = (buf[0] >> 1) & 0x1; g->Gif89.delayTime = LM_to_uint(buf[1], buf[2]); if ((buf[0] & 0x1) != 0) g->Gif89.transparent = buf[3]; while (GetDataBlock(inbuf, (unsigned char*) buf, g) != 0) ; return FALSE; default: str = buf; sprintf(buf, "UNKNOWN (0x%02x)", label); break; } #ifdef DEBUG _gif_message("got a '%s' extension", str ); #endif while (GetDataBlock(inbuf, (unsigned char*) buf, g) != 0) ; return FALSE; }
static int gif_get_extension(GifContext *context) { int retval; int empty_block = false; if (context->extension_flag) { if (!context->extension_label && !gif_read(context, &context->extension_label , 1)) return -1; switch (context->extension_label) { case 0xf9: /* Graphic Control Extension */ retval = get_data_block(context, (euchar *)context->block_buf, NULL); if (retval != 0) return retval; if (context->frame == NULL) { context->gif89.disposal = (context->block_buf[0] >> 2) & 0x7; context->gif89.input_flag = (context->block_buf[0] >> 1) & 0x1; context->gif89.delay_time = LM_to_uint(context->block_buf[1], context->block_buf[2]); if ((context->block_buf[0] & 0x1) != 0) context->gif89.transparent = context->block_buf[3]; else context->gif89.transparent = -1; } /* Now we've successfully loaded this one, we continue on our way */ context->block_count = 0; context->extension_flag = false; break; case 0xff: /* application extension */ if (!context->in_loop_extension) { retval = get_data_block(context, (euchar *)context->block_buf, NULL); if (retval != 0) return retval; if (!e_strncmp(context->block_buf, _("NETSCAPE2.0"), 11) || !e_strncmp(context->block_buf, _("ANIMEXTS1.0"), 11)) { context->in_loop_extension = true; } context->block_count = 0; } if (context->in_loop_extension) { do { retval = get_data_block(context, (euchar *)context->block_buf, &empty_block); if (retval != 0) return retval; if (context->is_anim && context->block_buf[0] == 0x01) { context->anim->loop = context->block_buf[1] + (context->block_buf[2] << 8); if (context->anim->loop != 0) context->anim->loop++; } context->block_count = 0; } while (!empty_block); context->in_loop_extension = false; context->extension_flag = false; goto step; } break; default: break; } }
static int DoExtension(FILE *fd, int label){ static char buf[256]; char *str; switch (label) { case 0x01: /* Plain Text Extension */ strcpy(str,"Plain Text Extension"); #ifdef notdef if (GetDataBlock(fd, (unsigned char*) buf) == 0) ; lpos = LM_to_uint(buf[0], buf[1]); tpos = LM_to_uint(buf[2], buf[3]); width = LM_to_uint(buf[4], buf[5]); height = LM_to_uint(buf[6], buf[7]); cellw = buf[8]; cellh = buf[9]; foreground = buf[10]; background = buf[11]; while (GetDataBlock(fd, (unsigned char*) buf) != 0) { PPM_ASSIGN(image[ypos][xpos], cmap[CM_RED][v], cmap[CM_GREEN][v], cmap[CM_BLUE][v]); ++index; } return FALSE; #else break; #endif case 0xff: /* Application Extension */ strcpy(str,"Application Extension"); GetDataBlock(fd, (unsigned char*) buf); #if 0 if (showComment){ fprintf(stderr, "Application Extension: %c%c%c%c%c%c%c%c ", buf[0],buf[1],buf[2],buf[3],buf[4],buf[5],buf[6],buf[7]); fprintf(stderr, " Authentication Code=)%02x %02x %02x\n", buf[8], buf[9], buf[10]); } #endif break; case 0xfe: /* Comment Extension */ strcpy(str,"Comment Extension"); while (GetDataBlock(fd, (unsigned char*) buf) != 0) { #if 0 if (showComment) fprintf(stderr,"gif comment: %s\n", buf ); #endif } return FALSE; case 0xf9: /* Graphic Control Extension */ strcpy(str,"Graphic Control Extension"); (void) GetDataBlock(fd, (unsigned char*) buf); Gif89.disposal = (buf[0] >> 2) & 0x7; Gif89.inputFlag = (buf[0] >> 1) & 0x1; Gif89.delayTime = LM_to_uint(buf[1],buf[2]); if ((buf[0] & 0x1) != 0) Gif89.transparent = buf[3]; while (GetDataBlock(fd, (unsigned char*) buf) != 0) ; return FALSE; default: str = buf; sprintf(buf, "UNKNOWN (0x%02x)", label); break; } fprintf(stderr,"got a '%s' extension\n", str ); while (GetDataBlock(fd, (unsigned char*) buf) != 0) ; return FALSE; }
RageSurfaceUtils::OpenResult RageSurface_Load_GIF( const RString &sPath, RageSurface *&ret, bool bHeaderOnly, RString &error ) { unsigned char buf[256]; int imageCount = 0; int imageNumber = 1; RageFile f; if( !f.Open( sPath ) ) { error = f.GetError(); return RageSurfaceUtils::OPEN_FATAL_ERROR; } if( !ReadOK(f, buf, 6) ) { error = "error reading magic number"; return RageSurfaceUtils::OPEN_FATAL_ERROR; } if( strncmp((char *) buf, "GIF", 3) != 0 ) { error = "not a GIF file"; return RageSurfaceUtils::OPEN_UNKNOWN_FILE_FORMAT; } { char version[4]; strncpy(version, (char *) buf + 3, 3); version[3] = '\0'; if( (strcmp(version, "87a") != 0) && (strcmp(version, "89a") != 0) ) { error = "bad version number, not '87a' or '89a'"; return RageSurfaceUtils::OPEN_FATAL_ERROR; } } if( !ReadOK(f, buf, 7) ) { error = "failed to read screen descriptor"; return RageSurfaceUtils::OPEN_FATAL_ERROR; } RageSurfaceColor GlobalColorMap[MAXCOLORMAPSIZE]; unsigned int GlobalBitPixel = 0; GlobalBitPixel = 2 << (buf[4] & 0x07); if( BitSet(buf[4], LOCALCOLORMAP) ) { /* Global Colormap */ if( !ReadPalette(f, GlobalBitPixel, GlobalColorMap ) ) { error = "error reading global colormap"; return RageSurfaceUtils::OPEN_FATAL_ERROR; } } int transparency = -1; while(1) { unsigned char type; if( !ReadOK(f, &type, 1) ) { error = "EOF / read error on image data"; return RageSurfaceUtils::OPEN_FATAL_ERROR; } switch( type ) { case ';': { /* GIF terminator */ if( imageCount < imageNumber ) { error = ssprintf( "only %d image%s found in file", imageCount, imageCount > 1 ? "s" : ""); return RageSurfaceUtils::OPEN_FATAL_ERROR; } } case '!': { /* Extension */ unsigned char label; if( !ReadOK(f, &label, 1) ) { error = "EOF / read error on extention function code"; return RageSurfaceUtils::OPEN_FATAL_ERROR; } switch( label ) { case 0xf9: GetDataBlock( f, (unsigned char *) buf ); if( (buf[0] & 0x1) != 0 ) transparency = buf[3]; } while( GetDataBlock(f, (unsigned char *) buf) != 0 ) ; continue; } case ',': { ++imageCount; if( !ReadOK(f, buf, 9) ) { error = "couldn't read left/top/width/height"; return RageSurfaceUtils::OPEN_FATAL_ERROR; } int bitPixel = 1 << ((buf[8] & 0x07) + 1); RageSurfaceColor LocalColorMap[MAXCOLORMAPSIZE]; if( BitSet(buf[8], LOCALCOLORMAP) ) { if( !ReadPalette(f, bitPixel, LocalColorMap) ) { error = "error reading local colormap"; return RageSurfaceUtils::OPEN_FATAL_ERROR; } } else { bitPixel = GlobalBitPixel; memcpy( LocalColorMap, GlobalColorMap, sizeof(LocalColorMap) ); } ret = ReadImage( f, LM_to_uint(buf[4], buf[5]), LM_to_uint(buf[6], buf[7]), LocalColorMap, BitSet(buf[8], INTERLACE), imageCount != imageNumber ); if( !ret ) continue; if( transparency != -1 ) ret->format->palette->colors[ transparency ].a = 0; return RageSurfaceUtils::OPEN_OK; } default: continue; /* Not a valid start character */ } } return RageSurfaceUtils::OPEN_FATAL_ERROR; }