Changes in gif2png 0.7 (5 September 1999) ----------------------------------------- - modified to swap transparent palette entry with 0th entry to avoid large tRNS chunks (since many programs make *last* entry the transparent one) - modified for auto-interlace: make interlaced PNG only if GIF is interlaced - added -n option to disable interlacing (-i still forces interlacing) - added -q option for mostly quiet operation (-qq for totally quiet, aside from error messages) - inverted -p option so progress percentage only displayed if requested - added summary line ("converted N GIFs to M PNGs") - improved version info and usage screen - quieted some gcc warnings Note that the transparency-swapping fix has not been tested in conjunction with a background-color GIF; I don't have any (that I know of). In general it shouldn't be a problem. Greg Roelofs 12 September 1999 diff -c gif2png-0.6/Makefile gif2png-0.7/Makefile *** gif2png-0.6/Makefile Fri Nov 3 15:48:22 1995 --- gif2png-0.7/Makefile Sun Sep 5 12:30:00 1999 *************** *** 5,21 **** #COFF2EXE=coff2exe COFF2EXE=@echo >/dev/null ! PNGLIB=libpng-0.81 ! ZLIB=zlib-0.95 LIBS=$(PNGLIB)/libpng.a $(ZLIB)/libz.a - INCLUDE=-I$(PNGLIB) -I$(ZLIB) ! CFLAGS=$(INCLUDE) -g -O -Wall ! LDFLAGS=-g ! #CFLAGS=$(INCLUDE) -O -Wall ! #LDFLAGS=-s OBJS=gif2png.o gifread.o version.o 437_l1.o memory.o --- 5,28 ---- #COFF2EXE=coff2exe COFF2EXE=@echo >/dev/null ! #PNGINC=libpng-0.81 ! #PNGLIB=libpng-0.81 ! PNGINC=/usr/include ! PNGLIB=/usr/lib ! ! #ZINC=zlib-0.95 ! #ZLIB=zlib-0.95 ! ZINC=/usr/include ! ZLIB=/usr/lib + INCLUDE=-I$(PNGINC) -I$(ZINC) LIBS=$(PNGLIB)/libpng.a $(ZLIB)/libz.a ! #CFLAGS=$(INCLUDE) -g -O -Wall ! #LDFLAGS=-g ! CFLAGS=$(INCLUDE) -O3 -Wall ! LDFLAGS=-s OBJS=gif2png.o gifread.o version.o 437_l1.o memory.o *************** *** 31,37 **** gifread.o: gifread.c gif2png.h memory.o: memory.c gif2png.h ! version.o: version.c $(CC) $(CFLAGS) -c version.c -DPNGLIB=\"$(PNGLIB)\" -DZLIB=\"$(ZLIB)\" tags: .force --- 38,44 ---- gifread.o: gifread.c gif2png.h memory.o: memory.c gif2png.h ! version.o: version.c gif2png.c gifread.c memory.c 437_l1.c gif2png.h $(CC) $(CFLAGS) -c version.c -DPNGLIB=\"$(PNGLIB)\" -DZLIB=\"$(ZLIB)\" tags: .force diff -c gif2png-0.6/gif2png.c gif2png-0.7/gif2png.c *** gif2png-0.6/gif2png.c Fri Nov 3 17:52:44 1995 --- gif2png-0.7/gif2png.c Sun Sep 5 12:41:37 1999 *************** *** 1,24 **** /* * gif2png.c * Copyright (C) 1995 Alexander Lehmann * For conditions of distribution and use, see copyright notice in gif2png.h */ #include #include #include #define PNG_INTERNAL #include "gif2png.h" struct GIFelement first={NULL}; struct GIFelement *current; ! int delete; ! int histogram; ! int interlaced; ! int progress; ! int recover; ! int software_chunk; ! int skip_pte; /* return the actual line # used to store an interlaced line */ --- 1,30 ---- /* * gif2png.c * Copyright (C) 1995 Alexander Lehmann + * (Bug fixes and enhancements by Greg Roelofs, 5 September 1999) * For conditions of distribution and use, see copyright notice in gif2png.h */ #include #include #include + #include /* for isatty() */ + #define PNG_INTERNAL #include "gif2png.h" struct GIFelement first={NULL}; struct GIFelement *current; ! int delete = 0; ! int histogram = 0; ! int interlaced = -1; ! int progress = 0; ! int quiet = 0; ! int recover = 0; ! int software_chunk = 1; ! int skip_pte = 1; ! long numgifs = 0L; ! long numpngs = 0L; /* return the actual line # used to store an interlaced line */ *************** *** 67,77 **** except when the transparency color is also appearing as a visible color. In this case we write a paletted image, another solution would be gray+alpha, but that would probably increase the image size too much. ! If there are only few gray levels (<=16), we try to create a 4 or less bit grayscale file, but if the gray levels do not fit into the necessary grid, ! we write a paletted image, e.g. if the image contains black, white and 50% ! gray, the grayscale image would require 8 bit, but the paletted image only ! 2 bit. Even with filtering, the 8 bit file will be larger. */ int graycheck(png_color c) --- 73,83 ---- except when the transparency color is also appearing as a visible color. In this case we write a paletted image, another solution would be gray+alpha, but that would probably increase the image size too much. ! If there are only few gray levels (<=16), we try to create a 4-bit or less grayscale file, but if the gray levels do not fit into the necessary grid, ! we write a paletted image--e.g., if the image contains black, white and 50% ! gray, the grayscale image would require 8-bit, but the paletted image only ! 2-bit. Even with filtering, the 8-bit file will be larger. */ int graycheck(png_color c) *************** *** 88,101 **** struct GIFimagestruct *img=e->imagestruct; unsigned long *count=img->color_count; GifColor *colors=img->colors; ! int gray; ! int last_color=0, colors_used=0; byte remap[MAXCMSIZE]; ! int low_presc; png_struct *png_ptr = xalloc(sizeof (png_struct)); png_info *info_ptr = xalloc(sizeof (png_info)); int p; ! int bitdepth, gray_bitdepth; png_byte pal_trans[MAXCMSIZE]; png_color_16 color16trans, color16back; byte buffer[24]; /* used for gIFt and gIFg */ --- 94,107 ---- struct GIFimagestruct *img=e->imagestruct; unsigned long *count=img->color_count; GifColor *colors=img->colors; ! int colors_used=0; byte remap[MAXCMSIZE]; ! int low_prec; png_struct *png_ptr = xalloc(sizeof (png_struct)); png_info *info_ptr = xalloc(sizeof (png_info)); int p; ! int gray_bitdepth; ! png_color pal_rgb[MAXCMSIZE]; png_byte pal_trans[MAXCMSIZE]; png_color_16 color16trans, color16back; byte buffer[24]; /* used for gIFt and gIFg */ *************** *** 106,111 **** --- 112,124 ---- int passcount; png_text software; + /* these static declarations prevent gcc warnings ("variable might be + * clobbered by `longjmp' or `vfork'") */ + static int gray; + static int last_color=0; + static int remapping=0; + static int bitdepth; + if(img->trans!=-1 && !count[img->trans]) img->trans=-1; *************** *** 119,125 **** } if(gray) { ! fprintf(stderr, "image is grayscale\n"); /* zero out unused colors */ --- 132,139 ---- } if(gray) { ! if (!quiet) ! fprintf(stderr, "image is grayscale\n"); /* zero out unused colors */ *************** *** 132,138 **** for(i=0;itrans && colors[i].red==colors[img->trans].red) { gray=0; ! fprintf(stderr, "trans color is repeated in visible colors, using palette\n"); break; } } --- 146,154 ---- for(i=0;itrans && colors[i].red==colors[img->trans].red) { gray=0; ! if (!quiet) ! fprintf(stderr, ! "trans color is repeated in visible colors, using palette\n"); break; } } *************** *** 145,150 **** --- 161,167 ---- if(last_color<2) bitdepth=1; if(gray) { + remapping = 1; for(i=0;ijmpbuf)) { ! fprintf(stderr, "setjmp returns error condition\n"); ! free(png_ptr); free(info_ptr); - return 1; } --- 227,240 ---- } } ! if (!quiet) ! fprintf(stderr, "%d colors used, highest color %d, %s, bitdepth %d\n", ! colors_used, last_color, gray ? "gray":"palette", bitdepth); if(setjmp(png_ptr->jmpbuf)) { ! fprintf(stderr, "gif2png: libpng returns fatal error condition\n"); free(png_ptr); free(info_ptr); return 1; } *************** *** 228,234 **** info_ptr->height=current->imagestruct->height; info_ptr->bit_depth=bitdepth; info_ptr->color_type=gray ? PNG_COLOR_TYPE_GRAY : PNG_COLOR_TYPE_PALETTE; ! info_ptr->interlace_type=interlaced; if(GifScreen.AspectRatio!=0 && GifScreen.AspectRatio!=49) { info_ptr->x_pixels_per_unit=GifScreen.AspectRatio+15; --- 245,254 ---- info_ptr->height=current->imagestruct->height; info_ptr->bit_depth=bitdepth; info_ptr->color_type=gray ? PNG_COLOR_TYPE_GRAY : PNG_COLOR_TYPE_PALETTE; ! if (interlaced == -1) ! info_ptr->interlace_type = current->imagestruct->interlace; ! else ! info_ptr->interlace_type = interlaced; if(GifScreen.AspectRatio!=0 && GifScreen.AspectRatio!=49) { info_ptr->x_pixels_per_unit=GifScreen.AspectRatio+15; *************** *** 251,258 **** if(gray) { if(graycheck(GifScreen.ColorMap[GifScreen.Background])) { ! color16back.gray=remap[GifScreen.Background]; ! info_ptr->background=color16back; info_ptr->valid |= PNG_INFO_bKGD; } } else { --- 271,278 ---- if(gray) { if(graycheck(GifScreen.ColorMap[GifScreen.Background])) { ! color16back.gray = remap[GifScreen.Background]; ! info_ptr->background = color16back; info_ptr->valid |= PNG_INFO_bKGD; } } else { *************** *** 272,291 **** if(img->trans != -1) { if(gray) { ! color16trans.gray=remap[img->trans]; ! info_ptr->trans_values=color16trans; } else { ! for(i=0;itrans]=0; info_ptr->trans=pal_trans; info_ptr->num_trans=img->trans+1; } info_ptr->valid |= PNG_INFO_tRNS; } if(!gray) { ! info_ptr->palette=current->imagestruct->colors; ! info_ptr->num_palette=last_color+1; info_ptr->valid |= PNG_INFO_PLTE; } --- 292,333 ---- if(img->trans != -1) { if(gray) { ! color16trans.gray = remap[img->trans]; ! info_ptr->trans_values = color16trans; } else { ! #if 0 ! for(i=0;itrans]=0; info_ptr->trans=pal_trans; info_ptr->num_trans=img->trans+1; + #else + /* GRR NOTE: may be inconsistent with background-color logic (above) */ + remapping = 1; + for(i=0;itrans; + remap[img->trans] = 0; + pal_trans[0] = 0; + info_ptr->trans = pal_trans; + info_ptr->num_trans = 1; + #endif } info_ptr->valid |= PNG_INFO_tRNS; } if(!gray) { ! if (remapping) { ! for(i=0; i<=last_color; i++) { ! pal_rgb[i].red = current->imagestruct->colors[remap[i]].red; ! pal_rgb[i].green = current->imagestruct->colors[remap[i]].green; ! pal_rgb[i].blue = current->imagestruct->colors[remap[i]].blue; ! } ! info_ptr->palette = pal_rgb; ! } else { ! info_ptr->palette = current->imagestruct->colors; ! } ! info_ptr->num_palette = last_color+1; info_ptr->valid |= PNG_INFO_PLTE; } *************** *** 350,358 **** for(i=0;iimagestruct->height;i++) { if(progress) { if(passcount>1) ! printf("%d/%d ", p+1, passcount); ! printf("%2d%%\r", (int)(((long)i*100)/current->imagestruct->height)); ! fflush(stdout); } data=access_data(current, (long) (img->interlace ? interlace_line(current->imagestruct->height,i) : i) * --- 392,401 ---- for(i=0;iimagestruct->height;i++) { if(progress) { if(passcount>1) ! fprintf(stderr, "%d/%d ", p+1, passcount); ! fprintf(stderr, "%2d%%\r", ! (int)(((long)i*100)/current->imagestruct->height)); ! fflush(stderr); } data=access_data(current, (long) (img->interlace ? interlace_line(current->imagestruct->height,i) : i) * *************** *** 360,370 **** current->imagestruct->width); #ifndef TMPFILE /* if we store the image in memory, we have to remap once */ ! if(gray && p==0) { #else /* if we store the image in a file, we have to remap each time */ ! if(gray) { #endif for(j=0;jwidth;j++) { data[j]=remap[data[j]]; } --- 403,414 ---- current->imagestruct->width); #ifndef TMPFILE /* if we store the image in memory, we have to remap once */ ! if(remapping && p==0) #else /* if we store the image in a file, we have to remap each time */ ! if(remapping) #endif + { for(j=0;jwidth;j++) { data[j]=remap[data[j]]; } *************** *** 397,403 **** #if 0 case GIFplaintext: data=access_data(s, 0, s->size); ! /* gIFt is 12 bytes longer than GCE, due to 32 bit ints and rgb colors */ png_write_chunk_start(png_ptr, "gIFt", s->size+12); memset(buffer, 0, 24); --- 441,447 ---- #if 0 case GIFplaintext: data=access_data(s, 0, s->size); ! /* gIFt is 12 bytes longer than GCE, due to 32-bit ints and rgb colors */ png_write_chunk_start(png_ptr, "gIFt", s->size+12); memset(buffer, 0, 24); *************** *** 468,475 **** fclose(fp); ! if(num_pics>=0) ! printf("number of images %d\n", num_pics); if(num_pics<=0) return 1; --- 512,519 ---- fclose(fp); ! if(num_pics>=0 && !quiet) ! fprintf(stderr, "number of images %d\n", num_pics); if(num_pics<=0) return 1; *************** *** 508,513 **** --- 552,558 ---- } else { writefile(start, current, fp, i==num_pics); fclose(fp); + ++numpngs; start=NULL; sprintf(file_ext, ".p%02d", i); } *************** *** 544,550 **** char name[1025]; int ac; ! fprintf(stderr, "%s %s\n", version, compile_info); #ifdef TMPFILE if((tempfile=tmpfile())==NULL) { --- 589,596 ---- char name[1025]; int ac; ! if (quiet < 2) ! fprintf(stderr, "%s %s\n", version, compile_info); #ifdef TMPFILE if((tempfile=tmpfile())==NULL) { *************** *** 554,560 **** #endif software_chunk=1; - progress=1; ac=1; --- 600,605 ---- *************** *** 573,580 **** interlaced=1; break; case 'p': ! progress=0; break; case 'r': --- 618,633 ---- interlaced=1; break; + case 'n': + interlaced=0; + break; + case 'p': ! progress=1; ! break; ! ! case 'q': ! ++quiet; break; case 'r': *************** *** 586,616 **** break; case 't': ! skip_pte=1; break; default: ! fprintf(stderr, "unknown option char `%c'\n", argv[ac][i]); usage: fprintf(stderr, - "usage: gif2png [ -dhi ] [file[.gif]] ...\n" "\n" ! " -d delete source GIF files after successful conversion\n" ! " -i create interlaced PNG files\n" ! " -h create histogram chunks for color files\n" ! " -p do not display progress of PNG writing in %%\n" ! " -r try to recover corrupt GIF files\n" ! " -s do not write Software chunk\n" ! " -t ignore Plain Text Extensions\n" "\n" ! " if no source files are listed, stdin is converted to noname.png\n" ! " (may not work on systems that distinguish between text and binary mode)\n" "\n" ! " gif2png is Copyright 1995 by Alexander Lehmann \n" ! " For copyright, license, credits, etc. see the file README, which you\n" ! " should have received along with this program. If you didn't, you may be\n" ! " able to find gif2png on ftp://ftp.uu.net/graphics/png or on my\n" ! " WWW-page http://www.student.informatik.th-darmstadt.de/~alexlehm/\n" ); return 1; } --- 639,673 ---- break; case 't': ! skip_pte=0; break; default: ! fprintf(stderr, "unknown option `-%c'\n", argv[ac][i]); usage: fprintf(stderr, "\n" ! "usage: gif2png [ -dhinqprs ] [file[.gif]] ...\n" "\n" ! " -d delete source GIF files after successful conversion\n" ! " -h create histogram chunks for color files\n" ! " -i force interlaced PNG files (default = same as GIF image)\n" ! " -n force noninterlaced PNG files\n" ! " -p display progress of PNG writing in %%\n" ! " -q quiet mode (-qq very quiet)\n" ! " -r try to recover corrupted GIF files\n" ! " -s do not write Software text chunk\n" ! /* " -t convert Plain Text Extensions [not implemented]\n" */ "\n" ! " if no source files are listed, stdin is converted to noname.png\n" ! " (may not work on systems that distinguish between text and binary mode)\n" ! "\n" ! " gif2png is Copyright 1995 by Alexander Lehmann \n" ! " For copyright, license, credits, etc. see the file README, which you\n" ! " should have received along with this program. If you didn't, you may be\n" ! " able to find gif2png at http://www.cdrom.com/pub/png/pngcode.html ,\n" ! " ftp://ftp.uu.net/graphics/png/applications/ , or on my WWW page\n" ! " http://www.student.informatik.th-darmstadt.de/~alexlehm/ .\n" ); return 1; } *************** *** 620,626 **** if(input_is_terminal()) { goto usage; } ! printf("stdin:\n"); processfile("noname.gif", stdin); } else { for(i=ac;i 0) ; --- 291,298 ---- Gif89.inputFlag = -1; Gif89.disposal = 0; if(skip_pte) { ! if (!quiet) ! fprintf(stderr, "got a 'Plain Text Extension' extension (skipping)\n"); while (GetDataBlock(fd, (unsigned char*) buf) > 0) ; *************** *** 348,354 **** store_block(buf, size); } ! fprintf(stderr, "got a 'Comment Extension' extension\n"); current->GIFtype=label; --- 352,359 ---- store_block(buf, size); } ! if (!quiet) ! fprintf(stderr, "got a 'Comment Extension' extension\n"); current->GIFtype=label; *************** *** 380,386 **** goto copy_block; } default: ! fprintf(stderr, "skipping unknown extension 0x%02x\n", (unsigned char)label); while (GetDataBlock(fd, (unsigned char*) buf) > 0) ; --- 385,392 ---- goto copy_block; } default: ! if (!quiet) ! fprintf(stderr, "skipping unknown extension 0x%02x\n", (unsigned char)label); while (GetDataBlock(fd, (unsigned char*) buf) > 0) ; *************** *** 394,400 **** store_block(buf, size); } ! fprintf(stderr, "got a '%s' extension\n", str); current->GIFtype=label; --- 400,407 ---- store_block(buf, size); } ! if (!quiet) ! fprintf(stderr, "got a '%s' extension\n", str); current->GIFtype=label; *************** *** 561,567 **** ; if (count != 0) { ! fprintf(stderr, "missing EOD in data stream (common occurence)\n"); } return -2; } --- 568,574 ---- ; if (count != 0) { ! fprintf(stderr, "missing EOD in data stream (common occurrence)\n"); } return -2; } *************** *** 656,662 **** initLWZ(c); ! fprintf(stderr, "reading %d by %d%s GIF image\n", width, height, interlace ? " interlaced" : "" ); allocate_image(); --- 663,670 ---- initLWZ(c); ! if (!quiet) ! fprintf(stderr, "reading %d by %d%s GIF image\n", width, height, interlace ? " interlaced" : "" ); allocate_image(); diff -c gif2png-0.6/version.c gif2png-0.7/version.c *** gif2png-0.6/version.c Thu Nov 2 21:47:44 1995 --- gif2png-0.7/version.c Sun Sep 5 12:39:25 1999 *************** *** 5,22 **** */ #ifndef PNGLIB ! #define PNGLIB "pnglib (unknown version)" #endif #ifndef ZLIB ! #define ZLIB "zlib (unknown version)" #endif ! const char version[]="gif2png 0.6 (beta)"; const char compile_info[]= #ifdef TMPFILE ! "(TMPFILE) " #endif - "compiled " __DATE__ " with " PNGLIB " and " ZLIB; - --- 5,28 ---- */ + #include "zlib.h" + #include "png.h" + #ifndef PNGLIB ! # define PNGLIB "pnglib (unknown version)" #endif #ifndef ZLIB ! # define ZLIB "zlib (unknown version)" #endif ! const char version[]="gif2png 0.7,"; const char compile_info[]= #ifdef TMPFILE ! "(TMPFILE) " ! #endif ! #if defined(PNG_LIBPNG_VER_STRING) && defined(ZLIB_VERSION) ! "compiled " __DATE__ " with libpng " PNG_LIBPNG_VER_STRING " and zlib " ZLIB_VERSION "."; ! #else ! "compiled " __DATE__ " with " PNGLIB " and " ZLIB "."; #endif