lib/gifread.c

Go to the documentation of this file.
00001 /* gifread.c - The high level GIF reading routines.  See writegif for the
00002    write side.  Also gifdecode.c for lower level GIF reading code. */
00003 
00004 #include "common.h"
00005 #include "gifcodes.h"
00006 #include "memgfx.h"
00007 
00008 static char const rcsid[] = "$Id: gifread.c,v 1.4 2005/04/10 14:41:23 markd Exp $";
00009 
00010 static struct gif_header gif;
00011 static struct gif_image gim;
00012 static int gif_line;
00013 static char iphase;
00014 static WORD iy;
00015 static UBYTE gif_cmap[256*3];
00016 static FILE *gif_file;
00017 static struct memGfx *gif_mg;
00018 static int gif_width, gif_height;
00019 
00020 int gif_get_byte()
00021 /* Get next byte from file for decoder.
00022  * return -1 at end of file. */
00023 {
00024 return(fgetc(gif_file));
00025 }
00026 
00027 
00028 int gif_out_line(UBYTE *pixels, int linelen)
00029 /* Output a line of gif. */
00030 {
00031 int y;
00032 
00033 y = gif_line;
00034 if (gim.flags&ITLV_BIT)
00035     {
00036     y = iy;
00037     switch (iphase)
00038         {
00039         case 0:
00040         case 1:
00041             iy+=8;
00042             break;
00043         case 2:
00044             iy += 4;
00045             break;
00046         case 3:
00047             iy += 2;
00048             break;
00049         }
00050     if (iy >= gif_height)
00051         {
00052         switch (iphase)
00053             {
00054             case 0:
00055                 iy = 4;
00056                 break;
00057             case 1:
00058                 iy = 2;
00059                 break;
00060             case 2:
00061                 iy = 1;
00062                 break;
00063             }
00064         iphase++;
00065         }
00066     }
00067 gif_line++;
00068 memcpy(gif_mg->pixels + y*gif_mg->width, pixels, linelen);
00069 return(0);
00070 }
00071 
00072 
00073 
00074 struct memGfx *mgLoadGif(char *name)
00075 /* Create memory image based on gif file. 
00076  * Note this is based on a very old gif reader
00077  * that only handles the GIF87a version. 
00078  * This is the same that mgSaveGif creates at
00079  * least.  This version of gif was always
00080  * color mapped. */
00081 {
00082 int c;
00083 char type[7];
00084 int gif_colors = 0;
00085 
00086 gif_line = 0;
00087 iphase = 0;
00088 iy = 0;
00089 gif_mg = NULL;
00090 gif_file = mustOpen(name, "rb");
00091 if (fread(&gif, 1, sizeof(gif), gif_file) < sizeof(gif))
00092     {
00093     goto TRUNCOUT;
00094     }
00095 memcpy(type, gif.giftype, 6);
00096 type[6] = 0;
00097 if (!startsWith("GIF", type))
00098     {
00099     errAbort("Not a good GIF file");
00100     goto BADOUT;
00101     }
00102 if (!sameString("GIF87a", type))
00103     {
00104     errAbort("Gif is version %s, sadly load_gif only speaks version GIF87a", type);
00105     goto BADOUT;
00106     }
00107 gif_colors = (1<<((gif.colpix&PIXMASK)+1));
00108 if (gif.colpix&COLTAB)
00109     {
00110     int size = gif_colors*3;
00111     if (fread(gif_cmap, 1, size, gif_file) < size)
00112         goto TRUNCOUT;
00113     }
00114 for (;;)    /* skip over extension blocks and other junk til get ',' */
00115     {
00116     if ((c = fgetc(gif_file)) == READ_ERROR)
00117         goto TRUNCOUT;
00118     if (c == ',')
00119         break;
00120     if (c == ';')    /* semi-colon is end of piccie */
00121         goto TRUNCOUT;
00122     if (c == '!')    /* extension block */
00123         {
00124         if ((c = fgetc(gif_file)) == READ_ERROR)    /* skip extension type */
00125             goto TRUNCOUT;
00126         for (;;)
00127             {
00128             if ((c = fgetc(gif_file)) == READ_ERROR)
00129                 goto TRUNCOUT;
00130             if (c == 0)    /* zero 'count' means end of extension */
00131                 break;
00132             while (--c >= 0)
00133                 {
00134                 if (fgetc(gif_file) == READ_ERROR)
00135                     goto TRUNCOUT;
00136                 }
00137             }
00138         }
00139     }
00140 if (fread(&gim, 1, sizeof(gim), gif_file) < sizeof(gim))
00141     goto TRUNCOUT;
00142 gif_width = (gim.whi<<8) + gim.wlo;
00143 gif_height = (gim.hhi<<8) + gim.hlo;
00144 
00145 gif_mg = mgNew(gif_width, gif_height);
00146 
00147 /* Gif files can have color maps in two places.  Let
00148  * the gim color map overwrite the one in the gif header
00149  * here. */
00150 if (gim.flags&COLTAB)
00151     {
00152     int size;
00153     gif_colors = (1<<((gim.flags&PIXMASK)+1));
00154     size = gif_colors*3;
00155     if (fread(gif_cmap, 1, size, gif_file) < size)
00156         goto TRUNCOUT;
00157     }
00158 if (gif_colors > 0)
00159     {
00160     if (gif_colors > 256)
00161        errAbort("Too many colors in %s", name);
00162     memcpy(gif_mg->colorMap, gif_cmap, 3*gif_colors);
00163     }
00164 
00165 switch (gif_decoder(gif_width))
00166     {
00167     case READ_ERROR:
00168     case BAD_CODE_SIZE:
00169         goto TRUNCOUT;
00170     case OUT_OF_MEMORY:
00171         errAbort("out of memory");
00172         goto BADOUT;
00173     default:
00174         break;
00175     }
00176 carefulClose(&gif_file);
00177 return(gif_mg);
00178 
00179 TRUNCOUT:
00180 errAbort("%s is truncated", name);
00181 BADOUT:
00182 carefulClose(&gif_file);
00183 mgFree(&gif_mg);
00184 return(NULL);
00185 }
00186 
00187 

Generated on Tue Dec 25 18:39:31 2007 for blat by  doxygen 1.5.2