00001
00002
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
00022
00023 {
00024 return(fgetc(gif_file));
00025 }
00026
00027
00028 int gif_out_line(UBYTE *pixels, int linelen)
00029
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
00076
00077
00078
00079
00080
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 (;;)
00115 {
00116 if ((c = fgetc(gif_file)) == READ_ERROR)
00117 goto TRUNCOUT;
00118 if (c == ',')
00119 break;
00120 if (c == ';')
00121 goto TRUNCOUT;
00122 if (c == '!')
00123 {
00124 if ((c = fgetc(gif_file)) == READ_ERROR)
00125 goto TRUNCOUT;
00126 for (;;)
00127 {
00128 if ((c = fgetc(gif_file)) == READ_ERROR)
00129 goto TRUNCOUT;
00130 if (c == 0)
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
00148
00149
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