ftp.nice.ch/pub/next/unix/network/www/wwwcount.2.3.NIHS.bs.tar.gz#/wwwcount2.3/combine/readgif.c

This is readgif.c in view mode; [Download] [Up]

/*
 *	ReadGIFImage - reads a GIF Image
 *
 *	RCS:
 *		$Revision: 2.3 $
 *		$Date: 1996/05/03 02:21:34 $
 *
 *	Security:
 *		Unclassified
 *
 *	Description:
 *		Adapted mostly from ImageMagick 3.1
 *
 *	Input Parameters:
 *		type	identifier	description
 *
 *		text
 *
 *	Output Parameters:
 *		type	identifier	description
 *
 *		text
 *
 *	Return Values:
 *		value	description
 *
 *	Side Effects:
 *		text
 *
 *	Limitations and Comments:
 *		text
 *
 *	Development History:
 *		when	who		why
 *	6/28/94		muquit	first cut
 */

#include "combine.h"
#include "defines.h"
#include "errcds.h"


int ReadGIFImage (image)
Image
	*image;
{

#define BitSet(byte, bit) (((byte) & (bit)) == (bit))
#define LSBFirstOrder(x, y)	(((y) << 8) | (x))

	int
		rc = 0;

	int
		pass,
		x, y;
	
    short int
		transparency_index;

	register int
		i;

	register Runlength
		*q;
	
	register unsigned char
		*p;
	
	unsigned char
		c,
		*global_colormap,
		header[MaxTextLength],
		type[12];

	unsigned int
		global_colors,
		image_count,
		interlace,
		local_colormap;

	FILE
		*fp=(FILE *) NULL;
	
	Image
		*next_image = (Image *) NULL;

	fp = fopen (image->filename, "rb");

	if (fp == (FILE *) NULL)
	{
		fprintf (stderr, "could not open file: %s\n",image->filename);
		rc = OPEN_FAILED;
		goto ExitProcessing;
	}

	image->fp = fp;

	rc = Read_Data ((char *) type, 1, 6, fp);

	if ((rc == 1) || ((strncmp((char *) type, "GIF87", 5) != 0) &&
		(strncmp ((char *) type, "GIF89", 5) != 0)))
	{
		fprintf (stderr, "Not a GIF Image: [%s]\n",image->filename);
		rc = NOT_A_GIF_FILE;
		goto ExitProcessing;
	}

#ifdef DEBUG
	fprintf (stderr, " File Type: %s\n",type);
#endif
	rc = Read_Data ((char *) header, 1, 7, fp);

	if (rc == 1)
	{
		rc = FAILED_TO_READ_SCREEND;
		goto ExitProcessing;
	}

	global_colors = 0;
	global_colormap = (unsigned char *) NULL;

	if (BitSet(header[4], 0x80))
	{
		global_colors = 1 << ((header[4] & 0x07) + 1);

		global_colormap = (unsigned char *)
			malloc (3*global_colors*sizeof(unsigned char));

		if (global_colormap == (unsigned char *) NULL)
		{
			rc = MALLOC_FAILED;
			goto ExitProcessing;
		}

		(void) Read_Data ((char *) global_colormap, 3, (int) global_colors,
			fp);
	}

	transparency_index = (-1);
	image_count = 0;

	for ( ; ; )
	{
		rc = Read_Data ((char *) &c, 1, 1, fp);

		if (rc == 1)
		{
			rc = 0;
			break;
		}

		if (c == ';')	/* terminator */
			break;
		
		if (c == '!')	/* EXTENSION ! */
		{
			rc = Read_Data ((char *) &c, 1, 1, fp);

			if (rc == 1)
			{
				rc = READ_ERR_EXT_BLOCK;
				goto ExitProcessing;
			}

			switch (c)
			{
				case 0xf9:	/* Transperency */
				{
					while (ReadDataBlock ((char *) header, fp) !=0)
					if ((header[0] * 0x01) == 1)
					{
						transparency_index = header[3];
					}
					break;
				
				}
				case 0xfe:	/* comment extension */
				{
					int
						length;
					
					for ( ; ; )
					{
						length = ReadDataBlock ((char *) header, fp);
						if (length <= 0)
							break;

					if (image->comments != (char *) NULL)
					{
						image->comments=(char *) realloc((char *) 
							image->comments,
							(strlen(image->comments)+length+1)*
							sizeof(char));
					}
					else
					{
						image->comments = (char *) malloc ((length + 1)*
							sizeof(char));
						if (image->comments != (char *) NULL)
						{
							*image->comments = '\0';
						}
					}

					if (image->comments == (char *) NULL)
					{
						rc = MALLOC_FAILED;
						goto ExitProcessing;
					}
					header[length] = '\0';
					(void) strcat (image->comments, (char *) header);
#ifdef DEBUG
	fprintf (stderr, " GIF: comment: %s\n", image->comments);
#endif
					}
					break;
				}	

				default:
				{
					while (ReadDataBlock ((char *) header, fp) != 0);
					break;
				}
			}
		}


		if (c != ',')
			continue;


		if (image_count != 0)
		{
			if (next_image != (Image *) NULL)
				DestroyAnyImageStruct(&next_image);

			next_image = AllocateImageStruct();
			if (next_image == (Image *)NULL)
			{
				(void) fprintf (stderr,"Unable to Display GIF!\n");
				rc=MALLOC_FAILED;
				goto ExitProcessing;
			}
			(void) strcpy(next_image->filename, image->filename);
			next_image->fp = fp;

			if (image != (Image *) NULL)
				DestroyAnyImageStruct(&image);
			image=next_image;
		}
		image_count++;
		/*
		** can't handle multiple images in one file
		*/

		/*
		** read Header Now
		*/

		rc = Read_Data ((char *) header, 1, 9, fp);

		if (rc == 1)
		{
			rc = READ_ERR_WIDTH_HEIGHT;
			goto ExitProcessing;
		}

		interlace = BitSet (header[8], 0x40);
		local_colormap = BitSet (header[8], 0x80);
		image->columns = LSBFirstOrder (header[4], header[5]);
		image->rows = LSBFirstOrder (header[6], header[7]);
		image->packets = image->columns*image->rows;

		if (image->pixels != (Runlength *) NULL)
		{
			(void) free ((char *) image->pixels);
		}

		image->pixels = (Runlength *)
			malloc (image->packets*sizeof(Runlength));

		if (image->pixels == (Runlength *) NULL)
		{
			rc = MALLOC_FAILED;
			goto ExitProcessing;
		}
		
		image->class = PseudoClass;
		image->colors = 
			!local_colormap ? global_colors : 1 << ((header[8] & 0x07) + 1);
#ifdef DEBUG
	fprintf (stderr, " GIF: no of colors: %d\n", image->colors);
#endif

		image->colormap = (RGB *) malloc (image->colors*sizeof(RGB));

		if (image->colormap == (RGB *) NULL)
		{
			rc = MALLOC_FAILED;
			goto ExitProcessing;
		}

		if (!local_colormap)
		{
			p = global_colormap;

			for (i=0; i < image->colors; i++)
			{
				image->colormap[i].red = (*p++);
				image->colormap[i].green = (*p++);
				image->colormap[i].blue = (*p++);
			}
		}
		else
		{
			unsigned char
				*colormap;

			colormap = (unsigned char *)
				malloc (3*image->colors*sizeof(unsigned char));

			if (colormap == (unsigned char *) NULL)
			{
				rc = MALLOC_FAILED;
				goto ExitProcessing;
			}

			(void) Read_Data ((char *) colormap, 3, (int) image->colors, 
				fp);
			
			p = colormap;

			for (i=0; i < image->colors; i++)
			{
				image->colormap[i].red = (*p++);
				image->colormap[i].green = (*p++);
				image->colormap[i].blue = (*p++);
			}
			(void) free ((char *) colormap);
		}
		rc = LZWDecodeImage (image);
	    if (interlace)
       	{ 
        	Image
          		*interlaced_image;
        	register Runlength
           		*p;

			static int
			interlace_rate[4] = { 8, 8, 4, 2 },
			interlace_start[4] = { 0, 4, 2, 1 };
            
#ifdef DEBUG
    fprintf (stderr, " GIF: processing Interlaced image\n");
#endif
			interlaced_image = DuplicateImage (image, image->columns,
				image->rows, True);

			if (interlaced_image == (Image *) NULL)
			{
				rc = MALLOC_FAILED;
				/* destroy interlaced_image */
				goto ExitProcessing;
			} 
            
			p = interlaced_image->pixels;
			q = image->pixels;

			for (pass=0; pass < 4; pass++)
			{
				y = interlace_start[pass];
                
				while (y < image->rows)
				{
					q = image->pixels + (y*image->columns);
					for (x=0; x < image->columns; x++)
					{
						*q = (*p);
						p++;
						q++;
					}
					y+=interlace_rate[pass];
				}
			}
			DestroyAnyImageStruct (&interlaced_image);
		}/*if interlace*/

            /*
            ** handle transparency
            */

            if (transparency_index >= 0)
            {
                /*
                ** create alpha channel
                */
                q=image->pixels;
                for(i=0; i < image->packets; i++)
                {
                    if (q->index != (unsigned short) transparency_index)
                        q->index=Opaque;
                    else
                        q->index=Transparent;
                    q++;
                }
                transparency_index=(-1);
                image->class=DirectClass;
                image->alpha=True;
            }

			if (rc == 1)
			{
				rc = 0;
                (void) fprintf (stderr," Error\n");
				break;
			}

        break;
	}/* for (;;) */

		if (global_colormap != (unsigned char *) NULL)
		{
			(void) free ((char *) global_colormap);
		}

		if (image->pixels == (Runlength *) NULL)
		{
			rc = CORRUPT_GIF_IMAGE;
			goto ExitProcessing;
		}

        CompressColormap(image);
ExitProcessing:
	if (fp != (FILE *) NULL)
		(void) fclose ((FILE *) fp);
	return (rc);

}
	

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.