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