7 typedef struct Entry Entry;
8 typedef struct Header Header;
38 static char readerr[] = "ReadGIF: read error: %r";
39 static char extreaderr[] = "ReadGIF: can't read extension: %r";
40 static char memerr[] = "ReadGIF: malloc failed: %r";
42 static Rawimage** readarray(Header*, int);
43 static Rawimage* readone(Header*);
44 static void readheader(Header*);
45 static void skipextension(Header*);
46 static uchar* readcmap(Header*, int);
47 static uchar* decode(Header*, Rawimage*, Entry*);
48 static void interlace(Header*, Rawimage*);
62 giffreeall(Header *h, int freeimage)
73 clear(&h->new->chans[0]);
76 clear(&h->globalcmap);
77 if(freeimage && h->array!=nil){
78 for(i=0; h->array[i]; i++){
79 clear(&h->array[i]->cmap);
80 clear(&h->array[i]->chans[0]);
88 giferror(Header *h, char *fmt, ...)
93 vseprint(h->err, h->err+sizeof h->err, fmt, arg);
96 werrstr("%s", h->err);
98 longjmp(h->errlab, 1);
103 readgif(int fd, int colorspace, int justone)
112 if(Binit(&b, fd, OREAD) < 0)
114 h = malloc(sizeof(Header));
119 memset(h, 0, sizeof(Header));
121 errstr(buf, sizeof buf); /* throw it away */
122 if(setjmp(h->errlab))
125 a = readarray(h, justone);
139 for(i=0; i<258; i++) {
147 readarray(Header *h, int justone)
150 Rawimage *new, **array;
158 h->globalcmap = readcmap(h, (h->fields&7)+1);
159 array = malloc(sizeof(Rawimage*));
167 switch(c = Bgetc(h->fd)){
171 case 0x21: /* Extension (ignored) */
175 case 0x2C: /* Image Descriptor */
178 if(new->fields & 0x80){
179 new->cmaplen = 3*(1<<((new->fields&7)+1));
180 new->cmap = readcmap(h, (new->fields&7)+1);
182 if(h->globalcmap == nil)
183 giferror(h, "ReadGIF: globalcmap missing");
184 new->cmaplen = 3*(1<<((h->fields&7)+1));
185 new->cmap = malloc(new->cmaplen);
188 memmove(new->cmap, h->globalcmap, new->cmaplen);
191 new->chans[0] = decode(h, new, tbl);
192 if(new->fields & 0x40)
194 new->gifflags = h->flags;
195 new->gifdelay = h->delay;
196 new->giftrindex = h->trindex;
197 new->gifloopcount = h->loopcount;
198 array = realloc(h->array, (nimages+2)*sizeof(Rawimage*));
201 array[nimages++] = new;
202 array[nimages] = nil;
209 case 0x3B: /* Trailer */
213 fprint(2, "ReadGIF: unknown block type: 0x%.2x\n", c);
219 if(array[0]==nil || array[0]->chans[0] == nil)
220 giferror(h, "ReadGIF: no picture in file");
227 readheader(Header *h)
229 if(Bread(h->fd, h->buf, 13) != 13)
230 giferror(h, "ReadGIF: can't read header: %r");
231 memmove(h->vers, h->buf, 6);
232 if(strcmp(h->vers, "GIF87a")!=0 && strcmp(h->vers, "GIF89a")!=0)
233 giferror(h, "ReadGIF: can't recognize format %s", h->vers);
234 h->screenw = h->buf[6]+(h->buf[7]<<8);
235 h->screenh = h->buf[8]+(h->buf[9]<<8);
236 h->fields = h->buf[10];
237 h->bgrnd = h->buf[11];
238 h->aspect = h->buf[12];
247 readcmap(Header *h, int size)
252 giferror(h, "ReadGIF: can't handles %d bits per pixel", size);
254 if(Bread(h->fd, h->buf, size) != size)
255 giferror(h, "ReadGIF: short read on color map");
259 memmove(map, h->buf, size);
268 int left, top, width, height;
270 if(Bread(h->fd, h->buf, 9) != 9)
271 giferror(h, "ReadGIF: can't read image descriptor: %r");
272 i = malloc(sizeof(Rawimage));
275 left = h->buf[0]+(h->buf[1]<<8);
276 top = h->buf[2]+(h->buf[3]<<8);
277 width = h->buf[4]+(h->buf[5]<<8);
278 height = h->buf[6]+(h->buf[7]<<8);
279 i->fields = h->buf[8];
282 i->r.max.x = left+width;
283 i->r.max.y = top+height;
286 memset(i->chans, 0, sizeof(i->chans));
293 readdata(Header *h, uchar *data)
297 nbytes = Bgetc(h->fd);
299 giferror(h, "ReadGIF: can't read data: %r");
302 n = Bread(h->fd, data, nbytes);
304 giferror(h, "ReadGIF: can't read data: %r");
306 fprint(2, "ReadGIF: short data subblock\n");
312 graphiccontrol(Header *h)
314 if(Bread(h->fd, h->buf, 5+1) != 5+1)
315 giferror(h, readerr);
316 h->flags = h->buf[1];
317 h->delay = h->buf[2]+(h->buf[3]<<8);
318 h->trindex = h->buf[4];
323 skipextension(Header *h)
325 int type, hsize, hasdata, n;
334 giferror(h, extreaderr);
336 case 0x01: /* Plain Text Extension */
340 case 0xF9: /* Graphic Control Extension */
343 case 0xFE: /* Comment Extension */
346 case 0xFF: /* Application Extension */
347 hsize = Bgetc(h->fd);
348 /* standard says this must be 11, but Adobe likes to put out 10-byte ones,
349 * so we pay attention to the field. */
353 giferror(h, "ReadGIF: unknown extension");
355 if(hsize>0 && Bread(h->fd, h->buf, hsize) != hsize)
356 giferror(h, extreaderr);
359 * This code used to check h->buf[hsize-1] != 0
360 * and giferror if so, but if !hasdata, hsize == 0.
365 /* loop counter: Application Extension with NETSCAPE2.0 as string and 1 <loop.count> in data */
366 if(type == 0xFF && hsize==11 && memcmp(h->buf, "NETSCAPE2.0", 11)==0){
367 n = readdata(h, data);
370 if(n==3 && data[0]==1)
371 h->loopcount = data[1] | (data[2]<<8);
373 while(readdata(h, data) != 0)
379 decode(Header *h, Rawimage *i, Entry *tbl)
381 int c, incode, codesize, CTM, EOD, pici, datai, stacki, nbits, sreg, fc, code, piclen;
382 int csize, nentry, maxentry, first, ocode, ndata, nb;
383 uchar clip, *p, *pic;
384 uchar stack[4096], data[256];
386 if(Bread(h->fd, h->buf, 1) != 1)
387 giferror(h, "ReadGIF: can't read data: %r");
388 codesize = h->buf[0];
389 if(codesize>8 || 0>codesize)
390 giferror(h, "ReadGIF: can't handle codesize %d", codesize);
395 piclen = (i->r.max.x-i->r.min.x)*(i->r.max.y-i->r.min.y);
397 pic = malloc(piclen);
412 maxentry = (1<<csize)-1;
416 for(;; ocode = incode) {
417 while(nbits < csize) {
419 ndata = readdata(h, data);
428 code = sreg & ((1<<csize) - 1);
433 ndata = readdata(h, data);
435 fprint(2, "ReadGIF: unexpected data past EOD\n");
442 stacki = (sizeof stack)-1;
446 /* special case for KwKwK */
448 stack[stacki--] = fc;
453 fprint(2, "ReadGIF: GIF invalid, code out of range, %x > %x\n", code, nentry);
456 for(c=code; stacki>0 && c>=0; c=tbl[c].prefix)
457 stack[stacki--] = tbl[c].exten;
459 nb = (sizeof stack)-(stacki+1);
460 if(pici+nb > piclen){
461 /* this common error is harmless
462 * we have to keep reading to keep the blocks in sync */
465 memmove(pic+pici, stack+stacki+1, sizeof stack - (stacki+1));
469 fc = stack[stacki+1];
475 #define early 0 /* peculiar tiff feature here for reference */
476 if(nentry == maxentry-early) {
480 maxentry = (1<<csize);
484 tbl[nentry].prefix = ocode;
485 tbl[nentry].exten = fc;
491 if(i->cmap!=nil && i->cmaplen!=3*256){
492 clip = (i->cmaplen/3)-1;
493 for(p = pic; p < pic+piclen; p++)
503 interlace(Header *h, Rawimage *image)
510 pic = image->chans[0];
512 dx = r.max.x-r.min.x;
513 ipic = malloc(dx*(r.max.y-r.min.y));
517 /* Group 1: every 8th row, starting with row 0 */
519 for(y=r.min.y; y<r.max.y; y+=8){
520 memmove(&ipic[(y-r.min.y)*dx], &pic[yy*dx], dx);
524 /* Group 2: every 8th row, starting with row 4 */
525 for(y=r.min.y+4; y<r.max.y; y+=8){
526 memmove(&ipic[(y-r.min.y)*dx], &pic[yy*dx], dx);
530 /* Group 3: every 4th row, starting with row 2 */
531 for(y=r.min.y+2; y<r.max.y; y+=4){
532 memmove(&ipic[(y-r.min.y)*dx], &pic[yy*dx], dx);
536 /* Group 4: every 2nd row, starting with row 1 */
537 for(y=r.min.y+1; y<r.max.y; y+=2){
538 memmove(&ipic[(y-r.min.y)*dx], &pic[yy*dx], dx);
542 free(image->chans[0]);
543 image->chans[0] = ipic;