1 #include <../../nrnconf.h>
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);
40 free(pinfo_->comment);
71 #define NEXTBYTE (*dataptr++)
72 #define NEXTBYTEa (dataptr++)
73 #define EXTENSION 0x21
76 #define INTERLACEMASK 0x40
77 #define COLORMAPMASK 0x80
79 #define ISTR_WARNING "LoadGif warning:"
80 #define ISTR_INFO "LoadGif info:"
81 #define SetISTR(a, f, c, d) fprintf(stderr, f, c, d)
86 static int BitOffset = 0,
103 CurCode, OldCode, InCode,
112 static bool Interlace, HasColormap;
115 static byte* GRaster;
119 static int Prefix[4096];
120 static int Suffix[4096];
123 static int OutCode[4097];
125 static int gif89 = 0;
126 static const char* id87 =
"GIF87a";
127 static const char* id89 =
"GIF89a";
129 static int EGApalette[16][3] = {{0, 0, 0},
147 static int readImage(PICINFO*);
148 static int readCode();
149 static void doInterlace(
int);
150 static int gifError(PICINFO*,
const char*);
151 static void gifWarning(
const char*);
154 static const char* bname;
156 static byte* dataptr;
160 static int LoadGIF(
const char* fname, PICINFO* pinfo)
165 byte ch, ch1, *origptr;
167 int aspect, gotimage;
171 BitOffset = XC = YC = Pass = OutCount = gotimage = 0;
172 RawGIF = GRaster = pic8 = 0;
175 pinfo->raster =
NULL;
176 pinfo->comment =
NULL;
179 fp = fopen(fname,
"rb");
181 return (gifError(pinfo,
"can't open file"));
186 filesize = ftell(
fp);
191 if (!(dataptr = RawGIF = (
byte*) calloc((
size_t) filesize + 256, (
size_t) 1)))
192 return (gifError(pinfo,
"not enough memory to read gif file"));
194 if (!(GRaster = (
byte*) calloc((
size_t) filesize + 256, (
size_t) 1)))
195 return (gifError(pinfo,
"not enough memory to read gif file"));
197 if (fread(dataptr, (
size_t) filesize, (
size_t) 1,
fp) != 1)
198 return (gifError(pinfo,
"GIF data read failed"));
203 if (strncmp((
char*) dataptr, id87, (
size_t) 6) == 0)
205 else if (strncmp((
char*) dataptr, id89, (
size_t) 6) == 0)
208 return (gifError(pinfo,
"not a GIF file"));
215 RWidth = ch + 0x100 * NEXTBYTE;
217 RHeight = ch + 0x100 * NEXTBYTE;
220 HasColormap = ((ch & COLORMAPMASK) ? True : False);
222 BitsPerPixel = (ch & 7) + 1;
223 ColorMapSize = 1 << BitsPerPixel;
224 BitMask = ColorMapSize - 1;
231 return (gifError(pinfo,
"corrupt GIF file (screen descriptor)"));
233 normaspect = (float) (aspect + 15) / 64.0;
235 fprintf(stderr,
"GIF89 aspect = %f\n", normaspect);
242 for (
i = 0;
i < ColorMapSize;
i++) {
243 pinfo->r[
i] = NEXTBYTE;
244 pinfo->g[
i] = NEXTBYTE;
245 pinfo->b[
i] = NEXTBYTE;
251 for (
i = 0;
i < 256;
i++) {
252 pinfo->r[
i] = EGApalette[
i & 15][0];
253 pinfo->g[
i] = EGApalette[
i & 15][1];
254 pinfo->b[
i] = EGApalette[
i & 15][2];
270 fprintf(stderr,
"LoadGIF: ");
272 if (block == EXTENSION) {
273 int i, fn, blocksize, aspnum, aspden;
279 fprintf(stderr,
"GIF extension type 0x%02x\n", fn);
284 blocksize = NEXTBYTE;
285 if (blocksize == 2) {
288 if (aspden > 0 && aspnum > 0)
289 normaspect = (float) aspnum / (
float) aspden;
297 "GIF87 aspect extension: %d:%d = %f\n\n",
302 for (
i = 0;
i < blocksize;
i++)
306 while ((sbsize = NEXTBYTE) > 0) {
307 for (
i = 0;
i < sbsize;
i++)
313 else if (fn == 0xFE) {
314 int ch,
j, sbsize, cmtlen;
315 byte *ptr1, *cmt, *cmt1, *sp;
324 for (
j = 0;
j < sbsize;
j++)
330 cmt = (
byte*) malloc((
size_t) (cmtlen + 1));
332 gifWarning(
"couldn't malloc space for comments\n");
337 for (
j = 0;
j < sbsize;
j++, sp++, ptr1++)
342 if (pinfo->comment) {
343 cmt1 = (
byte*) malloc(strlen(pinfo->comment) + cmtlen + 2);
345 gifWarning(
"couldn't malloc space for comments\n");
348 strcpy((
char*) cmt1, (
char*) pinfo->comment);
349 strcat((
char*) cmt1, (
char*)
"\n");
350 strcat((
char*) cmt1, (
char*) cmt);
351 free(pinfo->comment);
353 pinfo->comment = (
char*) cmt1;
356 pinfo->comment = (
char*) cmt;
362 else if (fn == 0x01) {
364 int tgLeft, tgTop, tgWidth, tgHeight, cWidth, cHeight, fg, bg;
369 "PlainText extension found in GIF file. Ignored.");
373 tgLeft += (NEXTBYTE) << 8;
375 tgTop += (NEXTBYTE) << 8;
377 tgWidth += (NEXTBYTE) << 8;
379 tgHeight += (NEXTBYTE) << 8;
385 for (;
i < sbsize;
i++)
390 "PlainText: tgrid=%d,%d %dx%d cell=%dx%d col=%d,%d\n",
408 fprintf(stderr,
"%c", ch);
412 fprintf(stderr,
"\n\n");
416 else if (fn == 0xF9) {
420 fprintf(stderr,
"Graphic Control extension\n\n");
425 "Graphic Control Extension in GIF file. Ignored.");
439 else if (fn == 0xFF) {
443 fprintf(stderr,
"Application extension\n\n");
461 fprintf(stderr,
"unknown GIF extension 0x%02x\n\n", fn);
464 "%s: Unknown extension 0x%02x in GIF file. Ignored.\n",
481 else if (block == IMAGESEP) {
483 fprintf(stderr,
"imagesep (got=%d) ", gotimage);
485 fprintf(stderr,
" at start: offset=%ld\n", dataptr - RawGIF);
488 int i,
misc, ch, ch1;
502 for (
i = 0;
i < 1 << ((
misc & 7) + 1);
i++) {
516 if ((dataptr - RawGIF) > filesize)
521 else if (readImage(pinfo))
524 fprintf(stderr,
" at end: dataptr=%ld\n", dataptr - RawGIF);
528 else if (block == TRAILER) {
530 fprintf(stderr,
"trailer");
538 fprintf(stderr,
"block type 0x%02x ", block);
541 if ((dataptr - origptr) < filesize) {
543 "Unknown block type (0x%02x) at offset %ld",
545 (dataptr - origptr) - 1);
548 return gifError(pinfo, str);
557 fprintf(stderr,
"\n");
566 return (gifError(pinfo,
"no image data found in GIF file"));
573 static int readImage(PICINFO* pinfo) {
574 byte ch, ch1, *ptr1, *picptr;
575 int i, npixels, maxpixels;
577 npixels = maxpixels = 0;
582 LeftOfs = ch + 0x100 * NEXTBYTE;
584 TopOfs = ch + 0x100 * NEXTBYTE;
586 Width = ch + 0x100 * NEXTBYTE;
588 Height = ch + 0x100 * NEXTBYTE;
591 Interlace = ((Misc & INTERLACEMASK) ? True : False);
597 for (
i = 0;
i < 1 << ((Misc & 7) + 1);
i++) {
598 pinfo->r[
i] = NEXTBYTE;
599 pinfo->g[
i] = NEXTBYTE;
600 pinfo->b[
i] = NEXTBYTE;
605 if (!HasColormap && !(Misc & 0x80)) {
607 SetISTR(ISTR_WARNING,
610 "No colormap in this GIF file. Assuming EGA colors.");
620 ClearCode = (1 << CodeSize);
621 EOFCode = ClearCode + 1;
622 FreeCode = FirstFree = ClearCode + 2;
631 InitCodeSize = CodeSize;
632 MaxCode = (1 << CodeSize);
633 ReadMask = MaxCode - 1;
649 if ((dataptr - RawGIF) > filesize) {
650 SetISTR(ISTR_WARNING,
653 "This GIF file seems to be truncated. Winging it.");
661 "xv: LoadGIF() - picture is %dx%d, %d bits, %sinterlaced\n",
665 Interlace ?
"" :
"non-");
670 maxpixels = Width * Height;
672 pinfo->raster =
new Raster(Width, Height);
674 return (gifError(pinfo,
"couldn't malloc 'pic8'"));
682 while (Code != EOFCode) {
687 if (Code == ClearCode) {
688 CodeSize = InitCodeSize;
689 MaxCode = (1 << CodeSize);
690 ReadMask = MaxCode - 1;
691 FreeCode = FirstFree;
693 CurCode = OldCode = Code;
694 FinChar = CurCode & BitMask;
695 doInterlace(FinChar);
701 if (FreeCode >= 4096) {
705 CurCode = InCode = Code;
711 if (CurCode >= FreeCode) {
713 if (OutCount > 4096) {
716 OutCode[OutCount++] = FinChar;
724 while (CurCode > BitMask) {
727 OutCode[OutCount++] = Suffix[CurCode];
728 CurCode = Prefix[CurCode];
731 if (OutCount > 4096) {
737 FinChar = CurCode & BitMask;
738 OutCode[OutCount++] = FinChar;
745 if (npixels + OutCount > maxpixels)
746 OutCount = maxpixels - npixels;
749 for (
i = OutCount - 1;
i >= 0;
i--)
750 doInterlace(OutCode[
i]);
755 Prefix[FreeCode] = OldCode;
756 Suffix[FreeCode] = FinChar;
765 if (FreeCode >= MaxCode) {
769 ReadMask = (1 << CodeSize) - 1;
774 if (npixels >= maxpixels)
778 if (npixels != maxpixels) {
779 SetISTR(ISTR_WARNING,
782 "This GIF file seems to be truncated. Winging it.");
801 static int readCode() {
802 int RawCode, ByteOffset;
804 ByteOffset = BitOffset / 8;
805 RawCode = GRaster[ByteOffset] + (GRaster[ByteOffset + 1] << 8);
807 RawCode += (((int) GRaster[ByteOffset + 2]) << 16);
808 RawCode >>= (BitOffset % 8);
809 BitOffset += CodeSize;
811 return (RawCode & ReadMask);
816 static void doInterlace(
int Index) {
818 pinfo_->raster->poke(
819 XC, Height - YC - 1, Red[Index] / 256., Green[Index] / 256., Blue[Index] / 256., 1.);
869 static int gifError(PICINFO* pinfo,
const char* st) {
878 pinfo->raster->unref();
880 free(pinfo->comment);
884 pinfo->comment = (
char*) 0;
891 static void gifWarning(
const char* st) {
void hoc_warning(const char *s1, const char *s2)
int Sprintf(char(&buf)[N], const char *fmt, Args &&... args)
Redirect sprintf to snprintf if the buffer size can be deduced.