Example #1
0
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;
}
Example #2
0
/* 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);
}
ANIMATION* CreateAnimationFromGIF89a (HDC hdc, MG_RWops* area)
{
    unsigned char c;
    int ok = 0;
    MYBITMAP mybmp;
    GIFSCREEN GifScreen;
    IMAGEDESC ImageDesc;

    ANIMATION* anim;
    ANIMATIONFRAME* frame, *current = NULL;
    
    anim = calloc (1, sizeof (ANIMATION));
    if (anim == NULL)
        return NULL;

    anim->time_unit = 1;

    if (ReadGIFGlobal (area, &GifScreen) < 0)
        goto error;

    anim->width = GifScreen.Width;
    anim->height = GifScreen.Height;
    if (GifScreen.Background >= 0) {
        anim->bk = GifScreen.ColorMap [GifScreen.Background];
        anim->bk.a = 1;
    }
    else {
        anim->bk.r = anim->bk.g = anim->bk.b = 255;
        anim->bk.a = 0;
    }

    _MG_PRINTF ("EX_CTRL>GIF89a: Background: %d, %d, %d.\n",
                anim->bk.r, anim->bk.g, anim->bk.b);

    if ((ok = ReadOK (area, &c, 1)) == 0) {
        _MG_PRINTF ("EX_CTRL>GIF89a: EOF on image data\n");
        goto error;
    }

    while (c != ';' && ok > 0) {
        switch (c) {
        case '!':
            if ( (ok = ReadOK (area, &c, 1)) == 0) {
                _MG_PRINTF ("EX_CTRL>GIF89a: EOF on image data\n");
                goto error;
            }
            DoExtension (area, c, &GifScreen);
            _MG_PRINTF ("EX_CTRL>GIF89a: Extension info: %d, %d, %d, %d, %d, %d\n",
                        GifScreen.Width, GifScreen.Height, 
                        GifScreen.AspectRatio, GifScreen.delayTime,
                        GifScreen.disposal, GifScreen.transparent);
            break;

        case ',':
            if (ReadImageDesc (area, &ImageDesc, &GifScreen) < 0) {
                goto error;
            }
            else {
                if (ReadImage (area, &mybmp, &ImageDesc, &GifScreen, 0) < 0)
                    goto error;
            }
            _MG_PRINTF ("EX_CTRL>GIF89a: Image Descriptor: %d, %d, %d, %d, %d\n",
                        ImageDesc.Top, ImageDesc.Left,
                        ImageDesc.Width, ImageDesc.Height,
                        ImageDesc.haveColorMap);

            frame = (ANIMATIONFRAME*) calloc (1, sizeof (ANIMATIONFRAME));
            if (!frame)
                goto error;
            else {
                frame->next = NULL;
                frame->disposal = GifScreen.disposal;
                frame->off_y = ImageDesc.Left;
                frame->off_x = ImageDesc.Top;
                frame->width = mybmp.w;
                frame->height = mybmp.h;
                frame->delay_time = (GifScreen.delayTime>10)?GifScreen.delayTime:10;
                _MG_PRINTF ("EX_CTRL>GIF89a: frame info: %d, %d, %d, %d\n", 
                        frame->off_x, frame->off_y, frame->delay_time, 
                        GifScreen.transparent);

                if ((frame->mem_dc = CreateMemDCFromMyBitmap (&mybmp, ImageDesc.ColorMap)) == 0) {
                    free (mybmp.bits);
                    free (frame);
                    _MG_PRINTF ("EX_CTRL>GIF89a: Error when expand frame bitmap.\n");
                    goto error;
                }
                frame->bits = mybmp.bits;
                
                if (anim->frames == NULL) {
                    anim->frames = frame;
                    current = frame;
                    current->prev = NULL;
                }
                else {
                    frame->prev = current;
                    current->next = frame;
                    current = current->next;
                }

                anim->nr_frames++ ;
            }
            break;
        }

        ok = ReadOK (area, &c, 1);
    }

    return anim;

error:
    DestroyAnimation (anim, TRUE);
    return NULL;
}
Example #4
0
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;
}
Example #5
0
/*****
* 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 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;
}
Example #7
0
/*--------------------------------------------------------------------------*/
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;
}