/*------------------------------------------------------------------------ * * Copyright (c) 1997-1998 by Cornell University. * * See the file "license.txt" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * * giftoppm.c * * Steve Weiss sweiss@cs.cornell.edu * * Usage : giftoppm inputGIF outPrefix * * Takes a GIF (possibly animated GIF) and output a sequence of PPM files. * outPrefix specifies the prefix of the PPM file. If outPrefix is foo, * and the GIF contains three image, then the GIF file will be decoded into * foo0.ppm foo1.ppm foo2.ppm. * *------------------------------------------------------------------------ */ #include <dvmbasic.h> #include <dvmimap.h> #include <dvmpnm.h> #include <dvmgif.h> int fsize(char *); void WritePPM(PnmHdr *, ByteImage *, ByteImage *, ByteImage *, char *); int main(int argc, char *argv[]) { GifSeqHdr *seqhdr; GifImgHdr *imgHdr; PnmHdr *pnmhdr; ByteImage *red, *green, *blue, *indices; BitParser *bp; BitStream *bs; FILE *inf; ImageMap *rmap, *gmap, *bmap, *lrmap, *lgmap, *lbmap; int i, ctsize; int status; char outname[256]; /* * Check the arguments. */ if (argc != 3) { fprintf(stderr, "usage : %s inputGIF outPrefix\n", argv[0]); exit(1); } /* * Open the input file and check for errors. */ #ifdef _WIN32_ inf = fopen(argv[1], "rb"); #else inf = fopen(argv[1], "r"); #endif if (!inf) { fprintf(stderr, "cannot open input GIF %s.\n", argv[1]); exit(1); } /* * Initialize BitStream and BitParser */ bp = BitParserNew(); bs = BitStreamNew(fsize(argv[1])); BitStreamFileRead(bs, inf, 0); BitParserWrap(bp, bs); /* * Initialize Image Maps */ rmap = ImageMapNew(); gmap = ImageMapNew(); bmap = ImageMapNew(); /* * Create a new header and initilaize the header with data from * BitStream. */ seqhdr = GifSeqHdrNew(); GifSeqHdrParse(bp, seqhdr); /* * Check if a color table exists. If it does, parse it from the * BitStream. */ if (GifSeqHdrGetCtFlag(seqhdr) == 1) { ctsize = GifSeqHdrGetCtSize(seqhdr); GifCtParse(bp, ctsize, rmap, gmap, bmap); } /* * Initialize data for the decoding loop below. imgHdr and pnmHdr * holds the GIF image header and output PPM header respectively. * i is the number of image (index to the output PPM). */ imgHdr = GifImgHdrNew(); pnmhdr = PnmHdrNew(); i = 0; /* * Now we find an image from the BitStream. While there is an image, * we decode the image and write it to an output PPM. */ status = GifImgFind(bp); while (status == DVM_GIF_OK) { /* * Here we parse an image, first the header then the body. * Since each image can be of different width and height, * we allocate the ByteImages separately for each image. * (We can actually just allocate it according to the width * and height from seqHdr, and clip it here. weitsang) * We also allocate a ByteImage for indices to the color table. */ int w, h; GifImgHdrParse(bp, imgHdr); w = GifImgHdrGetWidth(imgHdr); h = GifImgHdrGetHeight(imgHdr); red = ByteNew(w, h); green = ByteNew(w, h); blue = ByteNew(w, h); indices = ByteNew(w, h); if (GifImgHdrGetCtFlag(imgHdr) == 1) { /* * There is a local color table for this image. We * create new image maps to hold this color table, and * parse this color table. */ lrmap = ImageMapNew(); lgmap = ImageMapNew(); lbmap = ImageMapNew(); ctsize = GifImgHdrGetCtSize(imgHdr); GifCtParse(bp, ctsize, lrmap, lgmap, lbmap); /* * Next we parse the body of the image. Interlaced and * non-interlaced table are parsed differently. */ if (GifImgHdrGetInterlaced(imgHdr)) { GifImgInterlacedParse(bp, seqhdr, imgHdr, indices); } else { GifImgNonInterlacedParse(bp, seqhdr, imgHdr, indices); } /* * We map the color table to the indices to get the RGB plane * of the image. Finally we free the image maps. */ ImageMapApply(lrmap, indices, red); ImageMapApply(lgmap, indices, green); ImageMapApply(lbmap, indices, blue); ImageMapFree(lrmap); ImageMapFree(lgmap); ImageMapFree(lbmap); } else { /* * If there are no color table, we just parse the image and * apply the color map. */ if (GifImgHdrGetInterlaced(imgHdr)) { GifImgInterlacedParse(bp, seqhdr, imgHdr, indices); } else { GifImgNonInterlacedParse(bp, seqhdr, imgHdr, indices); } ImageMapApply(rmap, indices, red); ImageMapApply(gmap, indices, green); ImageMapApply(bmap, indices, blue); } /* * Output current RGB image to a PPM file. */ sprintf(outname, "%s%d.ppm", argv[2], i); WritePPM (pnmhdr, red, green, blue, outname); /* * Free the RGB ByteImages. */ ByteFree(red); ByteFree(green); ByteFree(blue); ByteFree(indices); /* * Try to find the next GIF image to decode. */ status = GifImgFind(bp); i++; } return 0; }