/*------------------------------------------------------------------------
*
* 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;
}