1 #include <../../nrnconf.h> 2 #if HAVE_IV // to end of file 7 #include <InterViews/raster.h> 8 #include <InterViews/image.h> 12 #define byte unsigned char 17 #define Green pinfo_->g 18 #define Blue pinfo_->b 30 static int LoadGIF(
const char*
fname, PICINFO*);
33 Image* gif_image(
const char* filename) {
36 if (LoadGIF(filename, pinfo_)) {
37 image =
new Image(pinfo_->raster);
39 if (pinfo_->comment) free(pinfo_->comment);
70 #define NEXTBYTE (*dataptr++) 71 #define NEXTBYTEa (dataptr++) 72 #define EXTENSION 0x21 75 #define INTERLACEMASK 0x40 76 #define COLORMAPMASK 0x80 78 #define ISTR_WARNING "LoadGif warning:" 79 #define ISTR_INFO "LoadGif info:" 80 #define SetISTR(a,f,c,d) fprintf(stderr, f, c, d) 85 static int BitOffset = 0,
102 CurCode, OldCode, InCode,
111 static bool Interlace, HasColormap;
114 static byte *GRaster;
118 static int Prefix[4096];
119 static int Suffix[4096];
122 static int OutCode[4097];
124 static int gif89 = 0;
125 static const char *id87 =
"GIF87a";
126 static const char *id89 =
"GIF89a";
128 static int EGApalette[16][3] = {
129 {0,0,0}, {0,0,128}, {0,128,0}, {0,128,128},
130 {128,0,0}, {128,0,128}, {128,128,0}, {200,200,200},
131 {100,100,100}, {100,100,255}, {100,255,100}, {100,255,255},
132 {255,100,100}, {255,100,255}, {255,255,100}, {255,255,255} };
135 static int readImage(PICINFO*);
136 static int readCode();
137 static void doInterlace(
int);
138 static int gifError(PICINFO*,
const char *);
139 static void gifWarning(
const char *);
142 static const char *bname;
144 static byte *dataptr;
148 static int LoadGIF(
const char*
fname, PICINFO* pinfo)
153 byte ch, ch1, *origptr;
155 int aspect, gotimage;
159 BitOffset = XC = YC = Pass = OutCount = gotimage = 0;
160 RawGIF = GRaster = pic8 = 0;
163 pinfo->raster =
NULL;
164 pinfo->comment =
NULL;
167 fp =
fopen(fname,
"rb");
168 if (!fp)
return ( gifError(pinfo,
"can't open file") );
173 filesize = ftell(fp);
178 if (!(dataptr = RawGIF = (byte *) calloc((
size_t) filesize+256, (
size_t) 1)))
179 return( gifError(pinfo,
"not enough memory to read gif file") );
181 if (!(GRaster = (byte *) calloc((
size_t) filesize+256,(
size_t) 1)))
182 return( gifError(pinfo,
"not enough memory to read gif file") );
184 if (fread(dataptr, (
size_t) filesize, (
size_t) 1, fp) != 1)
185 return( gifError(pinfo,
"GIF data read failed") );
190 if (strncmp((
char *) dataptr, id87, (
size_t) 6)==0) gif89 = 0;
191 else if (strncmp((
char *) dataptr, id89, (
size_t) 6)==0) gif89 = 1;
192 else return( gifError(pinfo,
"not a GIF file"));
199 RWidth = ch + 0x100 * NEXTBYTE;
201 RHeight = ch + 0x100 * NEXTBYTE;
204 HasColormap = ((ch & COLORMAPMASK) ? True : False);
206 BitsPerPixel = (ch & 7) + 1;
207 ColorMapSize = 1 << BitsPerPixel;
208 BitMask = ColorMapSize - 1;
210 Background = NEXTBYTE;
214 if (!gif89)
return(gifError(pinfo,
"corrupt GIF file (screen descriptor)"));
215 else normaspect = (float) (aspect + 15) / 64.0;
216 if (
DEBUG)
fprintf(stderr,
"GIF89 aspect = %f\n", normaspect);
223 for (i=0; i<ColorMapSize; i++) {
224 pinfo->r[
i] = NEXTBYTE;
225 pinfo->g[
i] = NEXTBYTE;
226 pinfo->b[
i] = NEXTBYTE;
232 for (i=0; i<256; i++) {
233 pinfo->r[
i] = EGApalette[i&15][0];
234 pinfo->g[
i] = EGApalette[i&15][1];
235 pinfo->b[
i] = EGApalette[i&15][2];
252 if (block == EXTENSION) {
253 int i, fn, blocksize, aspnum, aspden;
258 if (
DEBUG)
fprintf(stderr,
"GIF extension type 0x%02x\n", fn);
263 blocksize = NEXTBYTE;
264 if (blocksize == 2) {
267 if (aspden>0 && aspnum>0)
268 normaspect = (float) aspnum / (
float) aspden;
269 else { normaspect = 1.0; aspnum = aspden = 1; }
271 if (
DEBUG)
fprintf(stderr,
"GIF87 aspect extension: %d:%d = %f\n\n",
272 aspnum, aspden,normaspect);
275 for (i=0; i<blocksize; i++) NEXTBYTEa;
278 while ((sbsize=NEXTBYTE)>0) {
279 for (i=0; i<sbsize; i++) NEXTBYTEa;
284 else if (fn == 0xFE) {
285 int ch,
j, sbsize, cmtlen;
286 byte *ptr1, *cmt, *cmt1, *sp;
295 for (j=0; j<sbsize; j++) ch = NEXTBYTE;
300 cmt = (byte *) malloc((
size_t) (cmtlen + 1));
301 if (!cmt) gifWarning(
"couldn't malloc space for comments\n");
306 for (j=0; j<sbsize; j++, sp++, ptr1++) *sp = *ptr1;
310 if (pinfo->comment) {
311 cmt1 = (byte *) malloc(strlen(pinfo->comment) + cmtlen + 2);
313 gifWarning(
"couldn't malloc space for comments\n");
317 strcpy((
char *) cmt1, (
char *) pinfo->comment);
318 strcat((
char *) cmt1, (
char *)
"\n");
319 strcat((
char *) cmt1, (
char *) cmt);
320 free(pinfo->comment);
322 pinfo->comment = (
char *) cmt1;
325 else pinfo->comment = (
char *) cmt;
331 else if (fn == 0x01) {
333 int tgLeft, tgTop, tgWidth, tgHeight, cWidth, cHeight, fg, bg;
335 SetISTR(ISTR_INFO,
"%s: %s\n", bname,
336 "PlainText extension found in GIF file. Ignored.");
339 tgLeft = NEXTBYTE; tgLeft += (NEXTBYTE)<<8;
340 tgTop = NEXTBYTE; tgTop += (NEXTBYTE)<<8;
341 tgWidth = NEXTBYTE; tgWidth += (NEXTBYTE)<<8;
342 tgHeight = NEXTBYTE; tgHeight += (NEXTBYTE)<<8;
348 for ( ; i<sbsize; i++) NEXTBYTEa;
351 "PlainText: tgrid=%d,%d %dx%d cell=%dx%d col=%d,%d\n",
352 tgLeft, tgTop, tgWidth, tgHeight, cWidth, cHeight, fg, bg);
367 else if (fn == 0xF9) {
370 if (
DEBUG)
fprintf(stderr,
"Graphic Control extension\n\n");
372 SetISTR(ISTR_INFO,
"%s: %s\n", bname,
373 "Graphic Control Extension in GIF file. Ignored.");
377 j = 0; sbsize = NEXTBYTE;
378 while (j<sbsize) { NEXTBYTEa; j++; }
383 else if (fn == 0xFF) {
390 j = 0; sbsize = NEXTBYTE;
391 while (j<sbsize) { NEXTBYTEa; j++; }
399 if (
DEBUG)
fprintf(stderr,
"unknown GIF extension 0x%02x\n\n", fn);
402 "%s: Unknown extension 0x%02x in GIF file. Ignored.\n",
407 j = 0; sbsize = NEXTBYTE;
408 while (j<sbsize) { NEXTBYTEa; j++; }
414 else if (block == IMAGESEP) {
415 if (
DEBUG)
fprintf(stderr,
"imagesep (got=%d) ",gotimage);
416 if (
DEBUG)
fprintf(stderr,
" at start: offset=%ld\n",dataptr-RawGIF);
422 NEXTBYTEa; NEXTBYTEa;
423 NEXTBYTEa; NEXTBYTEa;
424 NEXTBYTEa; NEXTBYTEa;
425 NEXTBYTEa; NEXTBYTEa;
429 for (i=0; i< 1 << ((misc&7)+1); i++) {
430 NEXTBYTEa; NEXTBYTEa; NEXTBYTEa;
439 while (ch--) NEXTBYTEa;
440 if ((dataptr - RawGIF) > filesize)
break;
444 else if (readImage(pinfo)) gotimage = 1;
445 if (
DEBUG)
fprintf(stderr,
" at end: dataptr=%ld\n",dataptr-RawGIF);
449 else if (block == TRAILER) {
460 if ((dataptr - origptr) < filesize) {
461 sprintf(str,
"Unknown block type (0x%02x) at offset %ld",
462 block, (dataptr - origptr) - 1);
464 if (!gotimage)
return gifError(pinfo, str);
465 else gifWarning(str);
474 free(RawGIF); RawGIF = 0;
475 free(GRaster); GRaster = 0;
478 return( gifError(pinfo,
"no image data found in GIF file") );
485 static int readImage(PICINFO* pinfo)
487 byte ch, ch1, *ptr1, *picptr;
488 int i, npixels, maxpixels;
490 npixels = maxpixels = 0;
495 LeftOfs = ch + 0x100 * NEXTBYTE;
497 TopOfs = ch + 0x100 * NEXTBYTE;
499 Width = ch + 0x100 * NEXTBYTE;
501 Height = ch + 0x100 * NEXTBYTE;
504 Interlace = ((Misc & INTERLACEMASK) ? True : False);
506 if (!Interlace) Pass = -1;
509 for (i=0; i< 1 << ((Misc&7)+1); i++) {
510 pinfo->r[
i] = NEXTBYTE;
511 pinfo->g[
i] = NEXTBYTE;
512 pinfo->b[
i] = NEXTBYTE;
517 if (!HasColormap && !(Misc&0x80)) {
519 SetISTR(ISTR_WARNING,
"%s: %s\n", bname,
520 "No colormap in this GIF file. Assuming EGA colors.");
531 ClearCode = (1 << CodeSize);
532 EOFCode = ClearCode + 1;
533 FreeCode = FirstFree = ClearCode + 2;
542 InitCodeSize = CodeSize;
543 MaxCode = (1 << CodeSize);
544 ReadMask = MaxCode - 1;
557 while (ch--) { *ptr1 = NEXTBYTE; ptr1++; }
558 if ((dataptr - RawGIF) > filesize) {
559 SetISTR(ISTR_WARNING,
"%s: %s\n", bname,
560 "This GIF file seems to be truncated. Winging it.");
569 fprintf(stderr,
"xv: LoadGIF() - picture is %dx%d, %d bits, %sinterlaced\n",
570 Width, Height, BitsPerPixel, Interlace ?
"" :
"non-");
575 maxpixels = Width*Height;
577 pinfo->raster =
new Raster(Width, Height);
578 if (!pinfo->raster)
return( gifError(pinfo,
"couldn't malloc 'pic8'") );
586 while (Code != EOFCode) {
591 if (Code == ClearCode) {
592 CodeSize = InitCodeSize;
593 MaxCode = (1 << CodeSize);
594 ReadMask = MaxCode - 1;
595 FreeCode = FirstFree;
597 CurCode = OldCode =
Code;
598 FinChar = CurCode & BitMask;
599 doInterlace(FinChar);
606 if (FreeCode>=4096) {
609 CurCode = InCode =
Code;
615 if (CurCode >= FreeCode) {
617 if (OutCount > 4096) {
break; }
618 OutCode[OutCount++] = FinChar;
626 while (CurCode > BitMask) {
627 if (OutCount > 4096)
break;
628 OutCode[OutCount++] = Suffix[CurCode];
629 CurCode = Prefix[CurCode];
632 if (OutCount > 4096) {
break; }
636 FinChar = CurCode & BitMask;
637 OutCode[OutCount++] = FinChar;
644 if (npixels + OutCount > maxpixels) OutCount = maxpixels-npixels;
647 for (i=OutCount-1; i>=0; i--) doInterlace(OutCode[i]);
652 Prefix[FreeCode] = OldCode;
653 Suffix[FreeCode] = FinChar;
662 if (FreeCode >= MaxCode) {
666 ReadMask = (1 << CodeSize) - 1;
671 if (npixels >= maxpixels)
break;
674 if (npixels != maxpixels) {
675 SetISTR(ISTR_WARNING,
"%s: %s\n", bname,
676 "This GIF file seems to be truncated. Winging it.");
690 pinfo->frmType = F_GIF;
691 pinfo->colType = F_FULLCOLOR;
693 pinfo->normw = pinfo->w; pinfo->normh = pinfo->h;
696 "GIF%s, %d bit%s per pixel, %sinterlaced. (%d bytes)",
697 (gif89) ?
"89" :
"87", BitsPerPixel,
698 (BitsPerPixel==1) ?
"" :
"s",
699 Interlace ?
"" :
"non-", filesize);
701 sprintf(pinfo->shrtInfo,
"%dx%d GIF%s.",Width,Height,(gif89) ?
"89" :
"87");
718 static int readCode()
720 int RawCode, ByteOffset;
722 ByteOffset = BitOffset / 8;
723 RawCode = GRaster[ByteOffset] + (GRaster[ByteOffset + 1] << 8);
725 RawCode += ( ((
int) GRaster[ByteOffset + 2]) << 16);
726 RawCode >>= (BitOffset % 8);
727 BitOffset += CodeSize;
729 return(RawCode & ReadMask);
734 static void doInterlace(
int Index)
738 pinfo_->raster->poke(XC, Height - YC - 1,
739 Red[Index]/256., Green[Index]/256., Blue[Index]/256.,
756 if (YC >= Height) { Pass++; YC = 4; }
761 if (YC >= Height) { Pass++; YC = 2; }
766 if (YC >= Height) { Pass++; YC = 1; }
782 static int gifError(PICINFO* pinfo,
const char* st)
786 if (RawGIF !=
NULL) free(RawGIF);
787 if (GRaster !=
NULL) free(GRaster);
789 if (pinfo->raster) pinfo->raster->unref();
790 if (pinfo->comment) free(pinfo->comment);
794 pinfo->comment = (
char *) 0;
801 static void gifWarning(
const char* st)
sprintf(buf," if (secondorder) {\ " int _i;\" " for(_i=0;_i< %d;++_i) {\" " _p[_slist%d[_i]]+=dt *_p[_dlist%d[_i]];\" " }}\", numeqn, listnum, listnum)
void hoc_warning(const char *, const char *)
static const char * fname(const char *name)
fprintf(stderr, "Don't know the location of params at %p\, pp)