Exemplo n.º 1
0
void GifEncode(FILE *fout, UBYTE *pixels, int depth, int siz)
{
  GifTree *first = &GifRoot, *newNode, *curNode;
  UBYTE   *end;
  int     cc, eoi, next, tel=0;
  short   cLength;

  char    *pos, *buffer;

  empty[0] = NULL;
  need = 8;

  nodeArray = empty;
  memmove(++nodeArray, empty, 255*sizeof(GifTree **));
  if (( buffer = (char *)malloc((BUFLEN+1)*sizeof(char))) == NULL )
	 TheEnd1("No memory for writing");
  buffer++;


  pos = buffer;
  buffer[0] = 0x0;

  cc = (depth == 1) ? 0x4 : 1<<depth;
  fputc((depth == 1) ? 2 : depth, fout);
  eoi = cc+1;
  next = cc+2;

  cLength = (depth == 1) ? 3 : depth+1;

  if (( topNode = baseNode = (GifTree *)malloc(sizeof(GifTree)*4094)) == NULL )
	 TheEnd1("No memory for GIF-code tree");
  if (( nodeArray = first->node = (GifTree **)malloc(256*sizeof(GifTree *)*noOfArrays)) == NULL )
	 TheEnd1("No memory for search nodes");
  lastArray = nodeArray + ( 256*noOfArrays - cc);
  ClearTree(cc, first);

  pos = AddCodeToBuffer(cc, cLength, pos);

  end = pixels+siz;
  curNode = first;
  while(pixels < end) {

    if ( curNode->node[*pixels] != NULL ) {
      curNode = curNode->node[*pixels];
      tel++;
      pixels++;
      chainlen++;
      continue;
    } else if ( curNode->typ == SEARCH ) {
      newNode = curNode->nxt;
      while ( newNode->alt != NULL ) {
	if ( newNode->ix == *pixels ) break;
	newNode = newNode->alt;
      }
      if (newNode->ix == *pixels ) {
	tel++;
	pixels++;
	chainlen++;
	curNode = newNode;
	continue;
      }
    }

/* ******************************************************
 * If there is no more thread to follow, we create a new node.  If the
 * current node is terminating, it will become a SEARCH node.  If it is
 * a SEARCH node, and if we still have room, it will be converted to a
 * LOOKUP node.
*/
  newNode = ++topNode;
  switch (curNode->typ ) {
   case LOOKUP:
     newNode->nxt = NULL;
     newNode->alt = NULL,
     curNode->node[*pixels] = newNode;
   break;
   case SEARCH:
     if ( nodeArray != lastArray ) {
       nodeArray += cc;
       curNode->node = nodeArray;
       curNode->typ = LOOKUP;
       curNode->node[*pixels] = newNode;
       curNode->node[(curNode->nxt)->ix] = curNode->nxt;
       lookuptypes++;
       newNode->nxt = NULL;
       newNode->alt = NULL,
       curNode->nxt = NULL;
       break;
     }
/*   otherwise do as we do with a TERMIN node  */
   case TERMIN:
     newNode->alt = curNode->nxt;
     newNode->nxt = NULL,
     curNode->nxt = newNode;
     curNode->typ = SEARCH;
     break;
   default:
     fprintf(stderr, "Silly node type: %d\n", curNode->typ);
  }
  newNode->code = next;
  newNode->ix = *pixels;
  newNode->typ = TERMIN;
  newNode->node = empty;
  nodecount++;
/*
* End of node creation
* ******************************************************
*/
  if (debugFlag) {
    if (curNode == newNode) fprintf(stderr, "Wrong choice of node\n");
    if ( curNode->typ == LOOKUP && curNode->node[*pixels] != newNode ) fprintf(stderr, "Wrong pixel coding\n");
    if ( curNode->typ == TERMIN ) fprintf(stderr, "Wrong Type coding; frame no = %d; pixel# = %d; nodecount = %d\n", count, tel, nodecount);
  }
    pos = AddCodeToBuffer(curNode->code, cLength, pos);
    if ( chainlen > maxchainlen ) maxchainlen = chainlen;
    chainlen = 0;
    if(pos-buffer>BLOKLEN) {
      buffer[-1] = BLOKLEN;
      fwrite(buffer-1, 1, BLOKLEN+1, fout);
      buffer[0] = buffer[BLOKLEN];
      buffer[1] = buffer[BLOKLEN+1];
      buffer[2] = buffer[BLOKLEN+2];
      buffer[3] = buffer[BLOKLEN+3];
      pos -= BLOKLEN;
    }
    curNode = first;

    if(next == (1<<cLength)) cLength++;
    next++;

    if(next == 0xfff) {
      ClearTree(cc,first);
      pos = AddCodeToBuffer(cc, cLength, pos);
      if(pos-buffer>BLOKLEN) {
	buffer[-1] = BLOKLEN;
	fwrite(buffer-1, 1, BLOKLEN+1, fout);
	buffer[0] = buffer[BLOKLEN];
	buffer[1] = buffer[BLOKLEN+1];
	buffer[2] = buffer[BLOKLEN+2];
	buffer[3] = buffer[BLOKLEN+3];
	pos -= BLOKLEN;
      }
      next = cc+2;
      cLength = (depth == 1)?3:depth+1;
    }
  }

  pos = AddCodeToBuffer(curNode->code, cLength, pos);
  if(pos-buffer>BLOKLEN-3) {
    buffer[-1] = BLOKLEN-3;
    fwrite(buffer-1, 1, BLOKLEN-2, fout);
    buffer[0] = buffer[BLOKLEN-3];
    buffer[1] = buffer[BLOKLEN-2];
    buffer[2] = buffer[BLOKLEN-1];
    buffer[3] = buffer[BLOKLEN];
    buffer[4] = buffer[BLOKLEN+1];
    pos -= BLOKLEN-3;
  }
  pos = AddCodeToBuffer(eoi, cLength, pos);
  pos = AddCodeToBuffer(0x0, -1, pos);
  buffer[-1] = pos-buffer;

  fwrite(buffer-1, pos-buffer+1, 1, fout);
  free(buffer-1); free(first->node); free(baseNode);
  if (debugFlag) fprintf(stderr, "pixel count = %d; nodeCount = %d lookup nodes = %d\n", tel, nodecount, lookuptypes);
  return;

}
Exemplo n.º 2
0
void GifDecode(FILE *fp, UBYTE *pix, GifImageHdr gifimage)
{ UBYTE *chPos, firstCodeOut = 0, charBuff[256];
  ULONG CLEAR, EOI, bits = 0, code = 0, codeFeched, buffCount = 0;
  int need = 0;

  interlaced = gifimage.i;
  imgwidth = gifimage.width;
  imgheight = gifimage.height;
  imgsize = imgwidth * imgheight;
  picture = pix;
  pass = picI = 0;
  if ( debugFlag > 1 )
     fprintf(stderr, "(interlaced,imgwidth,imgheight,imgsize)=(%d,%d,%d,%d)\n",
		interlaced, imgwidth, imgheight, imgsize);

  rootCodeSize = Xgetc(fp);
  CLEAR = 1 << rootCodeSize;
  EOI = CLEAR + 1;

  GifClearTable();

  if ( (buffCount = Xgetc(fp)) == 0 ) {
    sprintf(charBuff, "End of image # %d before it began!\n", count);
    TheEnd1(charBuff);
  }

  while(buffCount > 0) {
    if ( fread(charBuff, 1, buffCount, fp) != buffCount ) { 
      sprintf(charBuff, "Premature end of file; Image # %d\n", count);
      TheEnd1(charBuff);
    }
    for(chPos = charBuff; buffCount-- > 0; chPos++) {
      need += (int) *chPos << bits;
      bits += 8;
      while (bits >= codeSize) {
	code = need & mask;
	need >>= codeSize;
	bits -= codeSize;
	if(code > expected)
	   TheEnd1("Neither LZW nor RunLength (new code != expected)\n");
	if (code == EOI) {
	  if (debugFlag > 1) fprintf(stderr, "Image # %d ends; buffCount=%d\n",
			count, buffCount);
	  goto skipRest;
	}

	if(code == CLEAR) {
	GifClearTable();
	continue;
	}
	if(old == MAXVAL) {  /* i.e. first code after clear table */
	  pix = GifSendData(pix, 1, &last[code]);
	  firstCodeOut = last[code];
	  old = code;
	  continue;
	}
	codeFeched = code;
	if(code == expected) {
	  *topGifBuff++ = firstCodeOut;
	  code = old;
	}
	while(code > CLEAR) {
	  *topGifBuff++ = last[code];
	  code = first[code];
	}

	*topGifBuff++ = firstCodeOut = last[code];
	first[expected] = old;
	last[expected] = firstCodeOut;
	if(expected < MAXVAL) expected++;
	if(((expected & mask) == 0) && (expected < MAXVAL)) {
	  codeSize++;
	  mask += expected;
	}
	old = codeFeched;
	pix = GifSendData(pix, topGifBuff - gifBuff, gifBuff);
	topGifBuff = gifBuff;

      }   /* end of extracting codes */
    }   /* end of reading a block of data */
    if ( (buffCount = Xgetc(fp)) == 0 ) {
      sprintf(charBuff, "End of image # %d without EOI\n", count);
      TheEnd1(charBuff);
    }
  }

skipRest: 
  if (debugFlag) fprintf(stderr, "Ending GifDecode, written: %d=%d\n",
	  interlaced && (pix-picture == 0) ? imgsize : pix - picture, imgsize);
  return ;
}
Exemplo n.º 3
0
/*
 * Read a Gif file.
 */
void animate_gif(FILE *fout,char *fname,int firstImage,int Xoff,int Yoff,
		 int delay_time,int loop_val) /* time in 100th of seconds */
{
  FILE *fp;
  UBYTE *pix;
  int i;
  if ( (fp = fopen(fname, REABIN)) == 0) {
    fprintf(stderr, "Can't open %s for reading.\n", fname);
    TheEnd();
  }
     global.trans.type = TRANS_NONE;
     global.trans.valid = 0;
     global.time = delay_time;

     global.disposal = DEFAULT_DISPOSAL;
    global.left = Xoff;
    global.top = Yoff;

    loop=loop_val;
     /*   loop = TRUE; */
           /* loopcount = 0; */
   
   
  /*global.left = global.top = 0;*/
   
   
   GifScreenHeader(fp, fout, firstImage);

   /* read until , separator */
  do {
    switch ( i = Xgetc(fp)) {
      case ',':
      case '\0':
	break;
      case '!':
	Xgetc(fp); /* the extension code */
	for ( i = Xgetc(fp); i > 0; i-- ) Xgetc(fp);
	while ( ( i = Xgetc(fp) ) > 0 ) {
	  for ( i = i ; i > 0; i-- ) Xgetc(fp);
	}
	break;
      default:
	fclose(fp);
	if ( feof(fp) || i == ';' )
	TheEnd1("GifReadHeader: Unexpected End of File\n");
	TheEnd1("GifReadHeader: Unknown block type\n");
     }
   } while(i != ',');

  if(firstImage) {
    globscrn.m = gifscrn.m;
    globscrn.pixbits = gifscrn.pixbits;
    globscrn.bc = gifscrn.bc;
    if ( globscrn.m ) {
      for (i = gifMask[1+globscrn.pixbits]; i >= 0; i--) {
	gifGmap[i].cmap.red   = gifCmap[i].cmap.red;
	gifGmap[i].cmap.green = gifCmap[i].cmap.green;
	gifGmap[i].cmap.blue  = gifCmap[i].cmap.blue;
      }
    }
    if(loop) GifLoop(fout, loopcount);
  }

  ReadImageHeader(fp);

 /*** ACTION for IMAGE */

  if ( ( gifimage.m != 0 && globmap !=0 ) || minimize !=0 ) {
    UBYTE translator[256], *p, *po;
    int left, right=0, top, bot=0, i, j, k, l, hi, wi;
    long dsquare, dsquare1;
    hi = gifimage.height;
    wi = gifimage.width;
    if (( pix = (UBYTE *)malloc(wi * hi * sizeof(UBYTE)) ) == NULL )
	 TheEnd1("No memory for image\n");
    if (debugFlag) fprintf(stderr, "  decoding picture no %d\n", count);
    GifDecode(fp, pix, gifimage);
    gifimage.i = 0;
    k = gifMask[1+globscrn.pixbits]; 
    l = gifMask[1+gifscrn.pixbits]; 
    for (j = 0; j <= l; j++) {
      dsquare = 256*256*3;
      for (i = 0; i <= k; i++) {
	dsquare1 = sq(gifGmap[i].cmap.red, gifCmap[j].cmap.red) +
		   sq(gifGmap[i].cmap.green, gifCmap[j].cmap.green) +
		   sq(gifGmap[i].cmap.blue,  gifCmap[j].cmap.blue);
	if ( dsquare1 < dsquare ) {
	  dsquare = dsquare1;
	  translator[j]=i;
	  if ( dsquare == 0 ) break;
	}
      }
    }
    gifimage.m = 0;
    gifscrn.pixbits = globscrn.pixbits;
    if (debugFlag) fprintf(stderr, "  translating picture no %d\n", count);
    for (i = wi * hi -1; i>=0; i--)
      pix[i]=translator[pix[i]];
    if ( minimize != 0 && pixold != NULL  && hi == gifimageold.height
	&& wi == gifimageold.width && gifimage.top == gifimageold.top
	&& gifimage.left == gifimageold.left ) {
      gifimageold = gifimage;
/* First test from left to right, top to bottom */
      p = pix; po = pixold;
      for (i = 0; i < hi; i++ ) {
	for (j = 0; j < wi; j++ ) {
	  if ( *p++ != *po++ ) {
	    left = j; top=i;
	    goto done;
	  }
	}
      }
      if (FALSE) { 
done: /* i.e. a preliminary left and top found */ ;
      }
      else goto alike; /* writes full image, should we drop it ? */
/* Then test from right to left, bottom to top */
      k=hi*wi-1; 
      p = &pix[k]; po = &pixold[k];
      for (i = hi-1; i >= top; i-- ) {
	for (j = wi -1; j >= 0; j-- ) {
	  if ( *p-- != *po-- ) {
	    right = j; bot=i;
	    goto botfound;
	  }
	}
      }
botfound:
/* The form of the differing area (not rectangle) may be slanted */
      if ( right < left ) {
	i = right; right = left; left = i;
      }
/* Now test between top and bottom at the left hand side */
      for (i = top+1; i <= bot; i++ ) {
	k= i * wi;
	p = &pix[k]; po = &pixold[k];
	for (j = 0; j < left; j++ ) {
	  if ( *p++ != *po++ ) {
	    left = j;
	    break;
	  }
	}
      }
/* Finally test between bottom and top at the right hand side */
      for (i = bot-1; i >= top; i-- ) {
	k= (i+1) * wi-1;
	p = &pix[k]; po = &pixold[k];
	for (j = wi-1; j > right; j-- ) {
	  if ( *p-- != *po-- ) {
	    right = j;
	    break;
	  }
	}
      }
      gifimage.left += left;
      gifimage.top += top;
      gifimage.width = right-left+1;
      gifimage.height = bot-top+1;
      WriteImageHeader(fout);
/* The rectangle containing diffs is transferred to the mem area of pixold */
      po = pixold;
      for (i = top; i <= bot; i++ ) {
	p = &pix[i * wi+left];
	for (j = left; j <= right; j++ ) {
	  *po++ = *p++;
	}
      }
      GifEncode(fout, pixold, gifscrn.pixbits+1, gifimage.height * gifimage.width);
      if (debugFlag)
	fprintf(stderr, "  encoded: width= %d, height = %d, left = %d, top = %d\n",
	   gifimage.width, gifimage.height, gifimage.left, gifimage.top);
    }
    else {
alike:
      WriteImageHeader(fout);
      gifimageold = gifimage;
      GifEncode(fout, pix, gifscrn.pixbits+1, gifimage.height * gifimage.width);
      if (debugFlag) fprintf(stderr, "  picture re-encoded\n");
    }
    free(pixold);
    pixold = pix;
    fputc(0, fout);    /* block count of zero */
  }
  else {
    WriteImageHeader(fout);
    i = Xgetc(fp); fputc(i, fout); /* the LZW code size */
    while ( ( gifBlockSize = Xgetc(fp) ) > 0 ) {
      fputc(gifBlockSize, fout);
      while ( gifBlockSize-- > 0 ) fputc(Xgetc(fp),fout);
    }
    if ( gifBlockSize == 0 ) fputc(gifBlockSize, fout);
    else TheEnd1("GifPassing: Unexpected End of File\n");
  }

  fclose(fp);
}