NEURON
gifimage.cpp
Go to the documentation of this file.
1 #include <../../nrnconf.h>
2 #if HAVE_IV // to end of file
3 
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <string.h>
7 #include <InterViews/raster.h>
8 #include <InterViews/image.h>
9 #include "oc2iv.h"
10 
11 
12 #define byte unsigned char
13 #define True 1
14 #define False 0
15 #define DEBUG 0
16 #define Red pinfo_->r
17 #define Green pinfo_->g
18 #define Blue pinfo_->b
19 
20 typedef struct {
21  Raster* raster;
22  char* comment;
23  byte r[256];
24  byte g[256];
25  byte b[256];
26 } PICINFO;
27 
28 PICINFO* pinfo_;
29 
30 static int LoadGIF(const char* fname, PICINFO*);
31 
32 
33 Image* gif_image(const char* filename) {
34  Image* image{};
35  pinfo_ = new PICINFO;
36  if (LoadGIF(filename, pinfo_)) {
37  image = new Image(pinfo_->raster);
38  }
39  if (pinfo_->comment)
40  free(pinfo_->comment);
41  delete pinfo_;
42  return image;
43 }
44 
45 
46 /*
47  * xvgif.cpp - GIF loading code for 'xv'. Based strongly on...
48  *
49  * gif2ras.cpp - Converts from a Compuserve GIF (tm) image to a Sun Raster image.
50  *
51  * Copyright (c) 1988, 1989 by Patrick J. Naughton
52  *
53  * Author: Patrick J. Naughton
54  * naughton@wind.sun.com
55  *
56  * Permission to use, copy, modify, and distribute this software and its
57  * documentation for any purpose and without fee is hereby granted,
58  * provided that the above copyright notice appear in all copies and that
59  * both that copyright notice and this permission notice appear in
60  * supporting documentation.
61  *
62  * This file is provided AS IS with no warranties of any kind. The author
63  * shall have no liability with respect to the infringement of copyrights,
64  * trade secrets or any patents by this file or any part thereof. In no
65  * event will the author be liable for any lost revenue or profits or
66  * other special, indirect and consequential damages.
67  *
68  */
69 
70 
71 #define NEXTBYTE (*dataptr++)
72 #define NEXTBYTEa (dataptr++) /* avoid 'expression result unused' warnings */
73 #define EXTENSION 0x21
74 #define IMAGESEP 0x2c
75 #define TRAILER 0x3b
76 #define INTERLACEMASK 0x40
77 #define COLORMAPMASK 0x80
78 
79 #define ISTR_WARNING "LoadGif warning:"
80 #define ISTR_INFO "LoadGif info:"
81 #define SetISTR(a, f, c, d) fprintf(stderr, f, c, d)
82 
83 
84 static FILE* fp;
85 
86 static int BitOffset = 0, /* Bit Offset of next code */
87  XC = 0, YC = 0, /* Output X and Y coords of current pixel */
88  Pass = 0, /* Used by output routine if interlaced pic */
89  OutCount = 0, /* Decompressor output 'stack count' */
90  RWidth, RHeight, /* screen dimensions */
91  Width, Height, /* image dimensions */
92  LeftOfs, TopOfs, /* image offset */
93  BitsPerPixel, /* Bits per pixel, read from GIF header */
94  BytesPerScanline, /* bytes per scanline in output raster */
95  ColorMapSize, /* number of colors */
96  Background, /* background color */
97  CodeSize, /* Code size, read from GIF header */
98  InitCodeSize, /* Starting code size, used during Clear */
99  Code, /* Value returned by ReadCode */
100  MaxCode, /* limiting value for current code size */
101  ClearCode, /* GIF clear code */
102  EOFCode, /* GIF end-of-information code */
103  CurCode, OldCode, InCode, /* Decompressor variables */
104  FirstFree, /* First free code, generated per GIF spec */
105  FreeCode, /* Decompressor,next free slot in hash table */
106  FinChar, /* Decompressor variable */
107  BitMask, /* AND mask for data size */
108  ReadMask, /* Code AND mask for current code size */
109  Misc; /* miscellaneous bits (interlace, local cmap)*/
110 
111 
112 static bool Interlace, HasColormap;
113 
114 static byte* RawGIF; /* The heap array to hold it, raw */
115 static byte* GRaster; /* The raster data stream, unblocked */
116 static byte* pic8;
117 
118 /* The hash table used by the decompressor */
119 static int Prefix[4096];
120 static int Suffix[4096];
121 
122 /* An output array used by the decompressor */
123 static int OutCode[4097];
124 
125 static int gif89 = 0;
126 static const char* id87 = "GIF87a";
127 static const char* id89 = "GIF89a";
128 
129 static int EGApalette[16][3] = {{0, 0, 0},
130  {0, 0, 128},
131  {0, 128, 0},
132  {0, 128, 128},
133  {128, 0, 0},
134  {128, 0, 128},
135  {128, 128, 0},
136  {200, 200, 200},
137  {100, 100, 100},
138  {100, 100, 255},
139  {100, 255, 100},
140  {100, 255, 255},
141  {255, 100, 100},
142  {255, 100, 255},
143  {255, 255, 100},
144  {255, 255, 255}};
145 
146 
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*);
152 
153 static int filesize;
154 static const char* bname;
155 
156 static byte* dataptr;
157 
158 
159 /*****************************/
160 static int LoadGIF(const char* fname, PICINFO* pinfo)
161 /*****************************/
162 {
163  /* returns '1' if successful */
164 
165  byte ch, ch1, *origptr;
166  int i, block;
167  int aspect, gotimage;
168  float normaspect;
169 
170  /* initialize variables */
171  BitOffset = XC = YC = Pass = OutCount = gotimage = 0;
172  RawGIF = GRaster = pic8 = 0;
173  gif89 = 0;
174 
175  pinfo->raster = NULL;
176  pinfo->comment = NULL;
177 
178  bname = fname;
179  fp = fopen(fname, "rb");
180  if (!fp)
181  return (gifError(pinfo, "can't open file"));
182 
183 
184  /* find the size of the file */
185  fseek(fp, 0L, 2);
186  filesize = ftell(fp);
187  fseek(fp, 0L, 0);
188 
189  /* the +256's are so we can read truncated GIF files without fear of
190  segmentation violation */
191  if (!(dataptr = RawGIF = (byte*) calloc((size_t) filesize + 256, (size_t) 1)))
192  return (gifError(pinfo, "not enough memory to read gif file"));
193 
194  if (!(GRaster = (byte*) calloc((size_t) filesize + 256, (size_t) 1)))
195  return (gifError(pinfo, "not enough memory to read gif file"));
196 
197  if (fread(dataptr, (size_t) filesize, (size_t) 1, fp) != 1)
198  return (gifError(pinfo, "GIF data read failed"));
199 
200 
201  origptr = dataptr;
202 
203  if (strncmp((char*) dataptr, id87, (size_t) 6) == 0)
204  gif89 = 0;
205  else if (strncmp((char*) dataptr, id89, (size_t) 6) == 0)
206  gif89 = 1;
207  else
208  return (gifError(pinfo, "not a GIF file"));
209 
210  dataptr += 6;
211 
212  /* Get variables from the GIF screen descriptor */
213 
214  ch = NEXTBYTE;
215  RWidth = ch + 0x100 * NEXTBYTE; /* screen dimensions... not used. */
216  ch = NEXTBYTE;
217  RHeight = ch + 0x100 * NEXTBYTE;
218 
219  ch = NEXTBYTE;
220  HasColormap = ((ch & COLORMAPMASK) ? True : False);
221 
222  BitsPerPixel = (ch & 7) + 1;
223  ColorMapSize = 1 << BitsPerPixel;
224  BitMask = ColorMapSize - 1;
225 
226  Background = NEXTBYTE; /* background color... not used. */
227 
228  aspect = NEXTBYTE;
229  if (aspect) {
230  if (!gif89)
231  return (gifError(pinfo, "corrupt GIF file (screen descriptor)"));
232  else
233  normaspect = (float) (aspect + 15) / 64.0; /* gif89 aspect ratio */
234  if (DEBUG)
235  fprintf(stderr, "GIF89 aspect = %f\n", normaspect);
236  }
237 
238 
239  /* Read in global colormap. */
240 
241  if (HasColormap)
242  for (i = 0; i < ColorMapSize; i++) {
243  pinfo->r[i] = NEXTBYTE;
244  pinfo->g[i] = NEXTBYTE;
245  pinfo->b[i] = NEXTBYTE;
246  }
247  else { /* no colormap in GIF file */
248  /* put std EGA palette (repeated 16 times) into colormap, for lack of
249  anything better to do */
250 
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];
255  }
256  }
257 
258  /* possible things at this point are:
259  * an application extension block
260  * a comment extension block
261  * an (optional) graphic control extension block
262  * followed by either an image
263  * or a plaintext extension
264  */
265 
266  while (1) {
267  block = NEXTBYTE;
268 
269  if (DEBUG)
270  fprintf(stderr, "LoadGIF: ");
271 
272  if (block == EXTENSION) { /* parse extension blocks */
273  int i, fn, blocksize, aspnum, aspden;
274 
275  /* read extension block */
276  fn = NEXTBYTE;
277 
278  if (DEBUG)
279  fprintf(stderr, "GIF extension type 0x%02x\n", fn);
280 
281  if (fn == 'R') { /* GIF87 aspect extension */
282  int sbsize;
283 
284  blocksize = NEXTBYTE;
285  if (blocksize == 2) {
286  aspnum = NEXTBYTE;
287  aspden = NEXTBYTE;
288  if (aspden > 0 && aspnum > 0)
289  normaspect = (float) aspnum / (float) aspden;
290  else {
291  normaspect = 1.0;
292  aspnum = aspden = 1;
293  }
294 
295  if (DEBUG)
296  fprintf(stderr,
297  "GIF87 aspect extension: %d:%d = %f\n\n",
298  aspnum,
299  aspden,
300  normaspect);
301  } else {
302  for (i = 0; i < blocksize; i++)
303  NEXTBYTEa;
304  }
305 
306  while ((sbsize = NEXTBYTE) > 0) { /* eat any following data subblocks */
307  for (i = 0; i < sbsize; i++)
308  NEXTBYTEa;
309  }
310  }
311 
312 
313  else if (fn == 0xFE) { /* Comment Extension */
314  int ch, j, sbsize, cmtlen;
315  byte *ptr1, *cmt, *cmt1, *sp;
316 
317  cmtlen = 0;
318  ptr1 = dataptr; /* remember start of comments */
319 
320  /* figure out length of comment */
321  do {
322  sbsize = NEXTBYTE;
323  cmtlen += sbsize;
324  for (j = 0; j < sbsize; j++)
325  ch = NEXTBYTE;
326  } while (sbsize);
327 
328 
329  if (cmtlen > 0) { /* build into one un-blocked comment */
330  cmt = (byte*) malloc((size_t) (cmtlen + 1));
331  if (!cmt)
332  gifWarning("couldn't malloc space for comments\n");
333  else {
334  sp = cmt;
335  do {
336  sbsize = (*ptr1++);
337  for (j = 0; j < sbsize; j++, sp++, ptr1++)
338  *sp = *ptr1;
339  } while (sbsize);
340  *sp = '\0';
341 
342  if (pinfo->comment) { /* have to strcat onto old comments */
343  cmt1 = (byte*) malloc(strlen(pinfo->comment) + cmtlen + 2);
344  if (!cmt1) {
345  gifWarning("couldn't malloc space for comments\n");
346  free(cmt);
347  } else {
348  strcpy((char*) cmt1, (char*) pinfo->comment);
349  strcat((char*) cmt1, (char*) "\n");
350  strcat((char*) cmt1, (char*) cmt);
351  free(pinfo->comment);
352  free(cmt);
353  pinfo->comment = (char*) cmt1;
354  }
355  } else
356  pinfo->comment = (char*) cmt;
357  } /* if (cmt) */
358  } /* if cmtlen>0 */
359  }
360 
361 
362  else if (fn == 0x01) { /* PlainText Extension */
363  int j, sbsize, ch;
364  int tgLeft, tgTop, tgWidth, tgHeight, cWidth, cHeight, fg, bg;
365 
366  SetISTR(ISTR_INFO,
367  "%s: %s\n",
368  bname,
369  "PlainText extension found in GIF file. Ignored.");
370 
371  sbsize = NEXTBYTE;
372  tgLeft = NEXTBYTE;
373  tgLeft += (NEXTBYTE) << 8;
374  tgTop = NEXTBYTE;
375  tgTop += (NEXTBYTE) << 8;
376  tgWidth = NEXTBYTE;
377  tgWidth += (NEXTBYTE) << 8;
378  tgHeight = NEXTBYTE;
379  tgHeight += (NEXTBYTE) << 8;
380  cWidth = NEXTBYTE;
381  cHeight = NEXTBYTE;
382  fg = NEXTBYTE;
383  bg = NEXTBYTE;
384  i = 12;
385  for (; i < sbsize; i++)
386  NEXTBYTEa; /* read rest of first subblock */
387 
388  if (DEBUG)
389  fprintf(stderr,
390  "PlainText: tgrid=%d,%d %dx%d cell=%dx%d col=%d,%d\n",
391  tgLeft,
392  tgTop,
393  tgWidth,
394  tgHeight,
395  cWidth,
396  cHeight,
397  fg,
398  bg);
399 
400  /* read (and ignore) data sub-blocks */
401  do {
402  j = 0;
403  sbsize = NEXTBYTE;
404  while (j < sbsize) {
405  ch = NEXTBYTE;
406  j++;
407  if (DEBUG)
408  fprintf(stderr, "%c", ch);
409  }
410  } while (sbsize);
411  if (DEBUG)
412  fprintf(stderr, "\n\n");
413  }
414 
415 
416  else if (fn == 0xF9) { /* Graphic Control Extension */
417  int j, sbsize;
418 
419  if (DEBUG)
420  fprintf(stderr, "Graphic Control extension\n\n");
421 
422  SetISTR(ISTR_INFO,
423  "%s: %s\n",
424  bname,
425  "Graphic Control Extension in GIF file. Ignored.");
426 
427  /* read (and ignore) data sub-blocks */
428  do {
429  j = 0;
430  sbsize = NEXTBYTE;
431  while (j < sbsize) {
432  NEXTBYTEa;
433  j++;
434  }
435  } while (sbsize);
436  }
437 
438 
439  else if (fn == 0xFF) { /* Application Extension */
440  int j, sbsize;
441 
442  if (DEBUG)
443  fprintf(stderr, "Application extension\n\n");
444 
445  /* read (and ignore) data sub-blocks */
446  do {
447  j = 0;
448  sbsize = NEXTBYTE;
449  while (j < sbsize) {
450  NEXTBYTEa;
451  j++;
452  }
453  } while (sbsize);
454  }
455 
456 
457  else { /* unknown extension */
458  int j, sbsize;
459 
460  if (DEBUG)
461  fprintf(stderr, "unknown GIF extension 0x%02x\n\n", fn);
462 
463  SetISTR(ISTR_INFO,
464  "%s: Unknown extension 0x%02x in GIF file. Ignored.\n",
465  bname,
466  fn);
467 
468  /* read (and ignore) data sub-blocks */
469  do {
470  j = 0;
471  sbsize = NEXTBYTE;
472  while (j < sbsize) {
473  NEXTBYTEa;
474  j++;
475  }
476  } while (sbsize);
477  }
478  }
479 
480 
481  else if (block == IMAGESEP) {
482  if (DEBUG)
483  fprintf(stderr, "imagesep (got=%d) ", gotimage);
484  if (DEBUG)
485  fprintf(stderr, " at start: offset=%ld\n", dataptr - RawGIF);
486 
487  if (gotimage) { /* just skip over remaining images */
488  int i, misc, ch, ch1;
489 
490  /* skip image header */
491  NEXTBYTEa;
492  NEXTBYTEa; /* left position */
493  NEXTBYTEa;
494  NEXTBYTEa; /* top position */
495  NEXTBYTEa;
496  NEXTBYTEa; /* width */
497  NEXTBYTEa;
498  NEXTBYTEa; /* height */
499  misc = NEXTBYTE; /* misc. bits */
500 
501  if (misc & 0x80) { /* image has local colormap. skip it */
502  for (i = 0; i < 1 << ((misc & 7) + 1); i++) {
503  NEXTBYTEa;
504  NEXTBYTEa;
505  NEXTBYTEa;
506  }
507  }
508 
509  NEXTBYTEa; /* minimum code size */
510 
511  /* skip image data sub-blocks */
512  do {
513  ch = ch1 = NEXTBYTE;
514  while (ch--)
515  NEXTBYTEa;
516  if ((dataptr - RawGIF) > filesize)
517  break; /* EOF */
518  } while (ch1);
519  }
520 
521  else if (readImage(pinfo))
522  gotimage = 1;
523  if (DEBUG)
524  fprintf(stderr, " at end: dataptr=%ld\n", dataptr - RawGIF);
525  }
526 
527 
528  else if (block == TRAILER) { /* stop reading blocks */
529  if (DEBUG)
530  fprintf(stderr, "trailer");
531  break;
532  }
533 
534  else { /* unknown block type */
535  char str[128];
536 
537  if (DEBUG)
538  fprintf(stderr, "block type 0x%02x ", block);
539 
540  /* don't mention bad block if file was trunc'd, as it's all bogus */
541  if ((dataptr - origptr) < filesize) {
542  Sprintf(str,
543  "Unknown block type (0x%02x) at offset %ld",
544  block,
545  (dataptr - origptr) - 1);
546 
547  if (!gotimage)
548  return gifError(pinfo, str);
549  else
550  gifWarning(str);
551  }
552 
553  break;
554  }
555 
556  if (DEBUG)
557  fprintf(stderr, "\n");
558  }
559 
560  free(RawGIF);
561  RawGIF = 0;
562  free(GRaster);
563  GRaster = 0;
564 
565  if (!gotimage)
566  return (gifError(pinfo, "no image data found in GIF file"));
567 
568  return 1;
569 }
570 
571 
572 /********************************************/
573 static int readImage(PICINFO* pinfo) {
574  byte ch, ch1, *ptr1, *picptr;
575  int i, npixels, maxpixels;
576 
577  npixels = maxpixels = 0;
578 
579  /* read in values from the image descriptor */
580 
581  ch = NEXTBYTE;
582  LeftOfs = ch + 0x100 * NEXTBYTE;
583  ch = NEXTBYTE;
584  TopOfs = ch + 0x100 * NEXTBYTE;
585  ch = NEXTBYTE;
586  Width = ch + 0x100 * NEXTBYTE;
587  ch = NEXTBYTE;
588  Height = ch + 0x100 * NEXTBYTE;
589 
590  Misc = NEXTBYTE;
591  Interlace = ((Misc & INTERLACEMASK) ? True : False);
592 
593  if (!Interlace)
594  Pass = -1;
595 
596  if (Misc & 0x80) {
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;
601  }
602  }
603 
604 
605  if (!HasColormap && !(Misc & 0x80)) {
606  /* no global or local colormap */
607  SetISTR(ISTR_WARNING,
608  "%s: %s\n",
609  bname,
610  "No colormap in this GIF file. Assuming EGA colors.");
611  }
612 
613 
614  /* Start reading the raster data. First we get the intial code size
615  * and compute decompressor constant values, based on this code size.
616  */
617 
618  CodeSize = NEXTBYTE;
619 
620  ClearCode = (1 << CodeSize);
621  EOFCode = ClearCode + 1;
622  FreeCode = FirstFree = ClearCode + 2;
623 
624  /* The GIF spec has it that the code size is the code size used to
625  * compute the above values is the code size given in the file, but the
626  * code size used in compression/decompression is the code size given in
627  * the file plus one. (thus the ++).
628  */
629 
630  CodeSize++;
631  InitCodeSize = CodeSize;
632  MaxCode = (1 << CodeSize);
633  ReadMask = MaxCode - 1;
634 
635 
636  /* UNBLOCK:
637  * Read the raster data. Here we just transpose it from the GIF array
638  * to the Raster array, turning it from a series of blocks into one long
639  * data stream, which makes life much easier for readCode().
640  */
641 
642  ptr1 = GRaster;
643  do {
644  ch = ch1 = NEXTBYTE;
645  while (ch--) {
646  *ptr1 = NEXTBYTE;
647  ptr1++;
648  }
649  if ((dataptr - RawGIF) > filesize) {
650  SetISTR(ISTR_WARNING,
651  "%s: %s\n",
652  bname,
653  "This GIF file seems to be truncated. Winging it.");
654  break;
655  }
656  } while (ch1);
657 
658 
659  if (DEBUG) {
660  fprintf(stderr,
661  "xv: LoadGIF() - picture is %dx%d, %d bits, %sinterlaced\n",
662  Width,
663  Height,
664  BitsPerPixel,
665  Interlace ? "" : "non-");
666  }
667 
668 
669  /* Allocate the 'pic' */
670  maxpixels = Width * Height;
671  // picptr = pic8 = (byte *) malloc((size_t) maxpixels);
672  pinfo->raster = new Raster(Width, Height);
673  if (!pinfo->raster)
674  return (gifError(pinfo, "couldn't malloc 'pic8'"));
675 
676 
677  /* Decompress the file, continuing until you see the GIF EOF code.
678  * One obvious enhancement is to add checking for corrupt files here.
679  */
680 
681  Code = readCode();
682  while (Code != EOFCode) {
683  /* Clear code sets everything back to its initial value, then reads the
684  * immediately subsequent code as uncompressed data.
685  */
686 
687  if (Code == ClearCode) {
688  CodeSize = InitCodeSize;
689  MaxCode = (1 << CodeSize);
690  ReadMask = MaxCode - 1;
691  FreeCode = FirstFree;
692  Code = readCode();
693  CurCode = OldCode = Code;
694  FinChar = CurCode & BitMask;
695  doInterlace(FinChar);
696  npixels++;
697  } else {
698  /* If not a clear code, must be data: save same as CurCode and InCode */
699 
700  /* if we're at maxcode and didn't get a clear, stop loading */
701  if (FreeCode >= 4096) { /* printf("freecode blew up\n"); */
702  break;
703  }
704 
705  CurCode = InCode = Code;
706 
707  /* If greater or equal to FreeCode, not in the hash table yet;
708  * repeat the last character decoded
709  */
710 
711  if (CurCode >= FreeCode) {
712  CurCode = OldCode;
713  if (OutCount > 4096) { /* printf("outcount1 blew up\n"); */
714  break;
715  }
716  OutCode[OutCount++] = FinChar;
717  }
718 
719  /* Unless this code is raw data, pursue the chain pointed to by CurCode
720  * through the hash table to its end; each code in the chain puts its
721  * associated output code on the output queue.
722  */
723 
724  while (CurCode > BitMask) {
725  if (OutCount > 4096)
726  break; /* corrupt file */
727  OutCode[OutCount++] = Suffix[CurCode];
728  CurCode = Prefix[CurCode];
729  }
730 
731  if (OutCount > 4096) { /* printf("outcount blew up\n"); */
732  break;
733  }
734 
735  /* The last code in the chain is treated as raw data. */
736 
737  FinChar = CurCode & BitMask;
738  OutCode[OutCount++] = FinChar;
739 
740  /* Now we put the data out to the Output routine.
741  * It's been stacked LIFO, so deal with it that way...
742  */
743 
744  /* safety thing: prevent exceeding range of 'pic8' */
745  if (npixels + OutCount > maxpixels)
746  OutCount = maxpixels - npixels;
747 
748  npixels += OutCount;
749  for (i = OutCount - 1; i >= 0; i--)
750  doInterlace(OutCode[i]);
751  OutCount = 0;
752 
753  /* Build the hash table on-the-fly. No table is stored in the file. */
754 
755  Prefix[FreeCode] = OldCode;
756  Suffix[FreeCode] = FinChar;
757  OldCode = InCode;
758 
759  /* Point to the next slot in the table. If we exceed the current
760  * MaxCode value, increment the code size unless it's already 12. If it
761  * is, do nothing: the next code decompressed better be CLEAR
762  */
763 
764  FreeCode++;
765  if (FreeCode >= MaxCode) {
766  if (CodeSize < 12) {
767  CodeSize++;
768  MaxCode *= 2;
769  ReadMask = (1 << CodeSize) - 1;
770  }
771  }
772  }
773  Code = readCode();
774  if (npixels >= maxpixels)
775  break;
776  }
777 
778  if (npixels != maxpixels) {
779  SetISTR(ISTR_WARNING,
780  "%s: %s\n",
781  bname,
782  "This GIF file seems to be truncated. Winging it.");
783  // if (!Interlace) /* clear->EOBuffer */
784  // xvbzero((char *) pic8+npixels, (size_t) (maxpixels-npixels));
785  }
786 
787  fclose(fp);
788 
789  return 1;
790 }
791 
792 
793 /* Fetch the next code from the raster data stream. The codes can be
794  * any length from 3 to 12 bits, packed into 8-bit bytes, so we have to
795  * maintain our location in the Raster array as a BIT Offset. We compute
796  * the byte Offset into the raster array by dividing this by 8, pick up
797  * three bytes, compute the bit Offset into our 24-bit chunk, shift to
798  * bring the desired code to the bottom, then mask it off and return it.
799  */
800 
801 static int readCode() {
802  int RawCode, ByteOffset;
803 
804  ByteOffset = BitOffset / 8;
805  RawCode = GRaster[ByteOffset] + (GRaster[ByteOffset + 1] << 8);
806  if (CodeSize >= 8)
807  RawCode += (((int) GRaster[ByteOffset + 2]) << 16);
808  RawCode >>= (BitOffset % 8);
809  BitOffset += CodeSize;
810 
811  return (RawCode & ReadMask);
812 }
813 
814 
815 /***************************/
816 static void doInterlace(int Index) {
817  if (YC < Height)
818  pinfo_->raster->poke(
819  XC, Height - YC - 1, Red[Index] / 256., Green[Index] / 256., Blue[Index] / 256., 1.);
820 
821  /* Update the X-coordinate, and if it overflows, update the Y-coordinate */
822 
823  if (++XC == Width) {
824  /* deal with the interlace as described in the GIF
825  * spec. Put the decoded scan line out to the screen if we haven't gone
826  * past the bottom of it
827  */
828 
829  XC = 0;
830 
831  switch (Pass) {
832  case 0:
833  YC += 8;
834  if (YC >= Height) {
835  Pass++;
836  YC = 4;
837  }
838  break;
839 
840  case 1:
841  YC += 8;
842  if (YC >= Height) {
843  Pass++;
844  YC = 2;
845  }
846  break;
847 
848  case 2:
849  YC += 4;
850  if (YC >= Height) {
851  Pass++;
852  YC = 1;
853  }
854  break;
855 
856  case 3:
857  YC += 2;
858  break;
859 
860  default:
861  ++YC;
862  break;
863  }
864  }
865 }
866 
867 
868 /*****************************/
869 static int gifError(PICINFO* pinfo, const char* st) {
870  gifWarning(st);
871 
872  if (RawGIF != NULL)
873  free(RawGIF);
874  if (GRaster != NULL)
875  free(GRaster);
876 
877  if (pinfo->raster)
878  pinfo->raster->unref();
879  if (pinfo->comment)
880  free(pinfo->comment);
881 
882 
883  pinfo->raster = 0;
884  pinfo->comment = (char*) 0;
885 
886  return 0;
887 }
888 
889 
890 /*****************************/
891 static void gifWarning(const char* st) {
892  // SetISTR(ISTR_WARNING,"%s: %s\n", bname, st);
893  hoc_warning(bname, st);
894 }
895 
896 
897 #endif
#define Image
Definition: _defines.h:148
#define Background
Definition: _defines.h:41
#define Raster
Definition: _defines.h:217
static Frame * fp
Definition: code.cpp:96
#define i
Definition: md1redef.h:19
List * misc
Definition: init.cpp:9
#define DEBUG
Definition: list.cpp:37
void hoc_warning(const char *s1, const char *s2)
Definition: nrnoc_aux.cpp:44
int Sprintf(char(&buf)[N], const char *fmt, Args &&... args)
Redirect sprintf to snprintf if the buffer size can be deduced.
Definition: wrap_sprintf.h:14
size_t j
#define NULL
Definition: spdefs.h:105