📄 whirlgif.c
字号:
/* * whirlgif.c * * Copyright (c) 1997,1998,1999 by Hans Dinsen-Hansen (dino@danbbs.dk) * Copyright (c) 1995,1996 by Kevin Kadow (kadokev@msg.net) * Based on txtmerge.c * Copyright (c) 1990,1991,1992,1993 by Mark Podlipec (podlipec@BayNetworks.com). * All rights reserved. * * This software may be freely copied, modified and redistributed * without fee provided that above copyright notices are preserved * intact on all copies and modified copies. * * There is no warranty or other guarantee of fitness of this software. * It is provided solely "as is". The author(s) disclaim(s) all * responsibility and liability with respect to this software's usage * or its effect upon hardware or computer systems. * * The Graphics Interchange format (c) is the Copyright property of * Compuserve Incorporated. Gif(sm) is a Service Mark property of * Compuserve Incorporated. * *//* * Description: * * This program reads in a sequence of single-image Gif format files and * outputs a single multi-image Gif file, suitable for use as an animation. * * TODO: * * More options for dealing with the colormap * *//* * Rev 3.04 21Feb99 Hans Dinsen-Hansen * RunLength & Amiga. * Rev 3.03 02Feb99 Hans Dinsen-Hansen * Published as a patch. Better error messages. * Rev 3.02 01Oct98 Hans Dinsen-Hansen * Loop. Verbose -> DEBUG. Further minimizing. * Rev 3.01 Oct98 Hans Dinsen-Hansen * Never published. Various experiments with Windows versions. * Rev 3.00 29jul98 Hans Dinsen-Hansen * Gif-repacking; unification of color map; only output diff. * Rev 2.02 09Sep97 Hans Dinsen-Hansen * Gif89a input; use global colormap whenever possible; background index * Rev 2.01 31Aug96 Kevin Kadow * disposal * Rev 2.00 05Feb96 Kevin Kadow * transparency, gif comments, * Rev 1.10 29Jan96 Kevin Kadow * first release of whirlgif * * txtmerge: * Rev 1.01 08Jan92 Mark Podlipec * use all colormaps, not just 1st. * Rev 1.00 23Jul91 Mark Podlipec * creation * * */#include "whirlgif.h"/* * Set some defaults, these can be changed on the command line */unsigned int loop=DEFAULT_LOOP, loopcount=0, useColormap=DEFAULT_USE_COLORMAP, debugFlag=0, globmap=0, minimize=0;int imagex = 0, imagey = 0, imagec = 0, GifBgcolor=0, count=0;/* global settings for offset, transparency */Global global;GifColor gifGmap[256], gifCmap[256];GifScreenHdr globscrn, gifscrn;GifImageHdr gifimage, gifimageold;extern ULONG gifMask[];extern int picI;UBYTE *pixold=NULL;ULONG gifMask[16]={0,1,3,7,15,31,63,127,255,511,1023,2047,4095,8191,0,0}, obits;ULONG gifPtwo[16]={1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,0,0};char gifFileName[BIGSTRING];FILE *ff;long sq(UBYTE i,UBYTE j){ return((i-j)*(i-j));}void main(argc, argv) int argc; char *argv[];{ FILE * infile, *fout; char temp[BIGSTRING], *cmt; int i; fprintf(stderr, "whirlgif Rev %2.2f (c) 1997-1999 by %s\n%s\n%s\n", DA_REV,"Hans Dinsen-Hansen", " (c) 1995-1996 by Kevin Kadow", " (c) 1990-1993 by Mark Podlipec"); cmt = temp; /* if there is no comment option, let cmt point at the final message */ if (argc < 2) Usage(); /* set global values */ global.trans.type = TRANS_NONE; global.trans.valid = 0; global.time = DEFAULT_TIME; global.left = 0; global.top = 0; global.disposal = DEFAULT_DISPOSAL; fout = stdout; i = 1; while( i < argc) { char *p; p = argv[i]; if (debugFlag > 1) fprintf(stderr, "Option: %s\n", p); if ( (p[0] == '-') || (p[0] == '+') ) { ++p; /* strip off the - */ switch(p[0]) { case 'v': /* Give lots of information */ debugFlag++; i++; fprintf(stderr, "Verbose output; debug level: %d\n", debugFlag); break; case 'g': /* Use the global colormap throughout */ globmap++; i++; if ( debugFlag > 1) fprintf(stderr, "globmap\n"); break; case 'm': /* minimize output */ minimize++; globmap++; i++; if ( debugFlag > 1) fprintf(stderr, "minimize \n"); break; case 'd': /* disposal setting */ i++; p = argv[i++]; if(!strcmp("not", p)) global.disposal = DISP_NOT; else if(!strcmp("back", p)) global.disposal = DISP_BACK; else if(!strcmp("prev", p)) global.disposal = DISP_PREV; else if(!strcmp("none", p)) global.disposal = DISP_NONE; else global.disposal = DEFAULT_DISPOSAL; if(debugFlag) fprintf(stderr, "Disposal method set to %s = %d\n", p, global.disposal); break; case 'D': /* Debug setting */ i++; debugFlag = 2; fprintf(stderr, "DEBUG: Debug Level %d\n", debugFlag); break; case 'c': /* set comment pointer */ i++; cmt = argv[i++]; if(debugFlag) fprintf(stderr, "Comment: '%s'\n", cmt); break; case 'b': /* set Background color index */ i++; GifBgcolor = atoi(argv[i++]) | 0x100; if (debugFlag) fprintf(stderr, "BACKGROUND = %d\n", GifBgcolor & 0xff); break; case 'l': /* Enable looping */ loop = TRUE; i++; if(*argv[i] != '-') { /* a loop count was perhaps given */ loopcount = atoi(argv[i]); if(debugFlag) { fprintf(stderr, loopcount != 0 ? "Loop %d times\n" : "Loop forever, count = %d\n", loopcount); } if( (loopcount > 0) | ((loopcount == 0) & (*argv[i] == '0'))) i++; } else { /* default to infinite loop */ loopcount = 0; if(debugFlag) fprintf(stderr, "Looping enabled\n"); } break; case 't': /* either time or transparent */ i++; if(!strncmp("time", p, 2)) { /* Delay time in 1/100's of a second */ global.time = atoi(argv[i++]); } else if(!strncmp("trans", p, 2)) CalcTrans(argv[i++]); break; case 'o': /* Output file - send output to a given filename */ i++; if(!strncmp("off", p, 2)) SetOffset(argv[i]); else if(NULL == (fout = fopen(argv[i], WRIBIN))) { /* It must be 'output, so we do that */ fprintf(stderr, "Cannot open %s for output\n", argv[i]); exit(1); } i++; break; case 'i': /* input file - file with a list of images */ i++; if(NULL != (infile = fopen(argv[i], REATXT))) { while(fgets(gifFileName, BIGSTRING, infile)) { strtok(gifFileName, "\n"); GifReadFile(fout, gifFileName, count++ == 0); } fclose(infile); global.left = global.top = 0; } else fprintf(stderr, "Cannot read list file %s\n", argv[i]); i++; break; default: Usage(); exit(0); break; } continue; } /* Not an option, must be the name of an input file */ GifReadFile(fout, argv[i], count++ == 0); global.left = global.top = 0; i++; } /* We're done with all options and file names, finish up */ if(count >0) { sprintf(temp, "whirlgif %2.2f (c) %s\r\n%d %s", DA_REV, "dino@danbbs.dk", count, count == 1 ? "image" : "images"); /* Either output above std. mess. or a possible user defined comment */ GifComment(fout, cmt); } fputc(';', fout); /* End of Gif file */ fclose(fout); fprintf(stderr, "Processed %d files.\n", count); exit(0);}/* * Read a Gif file. */void GifReadFile(FILE *fout, char *fname, int firstImage){ FILE *fp; UBYTE *pix; int i, gifBlockSize; if ( (fp = fopen(fname, REABIN)) == 0) { fprintf(stderr, "Can't open %s for reading.\n", fname); TheEnd(); } 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, top, bot, 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;/* 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++ ) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -