/*------------------------------------------------------------------------ * * 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. * * ppmtogif * * Steve Weiss sweiss@cs.cornell.edu * * Usage : ppmtogif inputPPm outputGIF * * Reads a PPM file and encode it into a GIF file. * *------------------------------------------------------------------------ */ #include <dvmbasic.h> #include <dvmimap.h> #include <dvmpnm.h> #include <dvmgif.h> #include <dvmcolor.h> int fsize (char *); void ReadPPM (char *name, PnmHdr **, ByteImage **, ByteImage **, ByteImage **); int main (int argc, char *argv[]) { BitParser *bp; BitStream *bs; PnmHdr *pnmhdr; ImageMap *rmap, *gmap, *bmap; ByteImage *r, *g, *b, *indices; FILE *f; int w, h; GifSeqHdr *hdr; GifImgHdr *img; ColorHashTable *cht; VpTree tree; /* * Check arguments, and read in the input PPM. We create a BitStream * the same size as the PPM image, we assumes GIF is smaller than PPM * so this BitStream should be big enough to hold the output GIF. */ if (argc < 3) { fprintf (stderr, "usage: %s input output\n", argv[0]); exit (1); } bp = BitParserNew (); bs = BitStreamNew (fsize (argv[1])); f = fopen (argv[2], "wb"); if (f == NULL) { fprintf (stderr, "unable to open file %s for writing.\n", argv[2]); exit (1); } BitParserWrap (bp, bs); ReadPPM (argv[1], &pnmhdr, &r, &g, &b); /* * Allocates all the stuffs that we need : rmap, gmap and bmap for * the color table and indices for the color map indices. */ rmap = ImageMapNew (); gmap = ImageMapNew (); bmap = ImageMapNew (); w = ByteGetWidth (r); h = ByteGetHeight (r); indices = ByteNew (w, h); /* * Find 256 colors that best represents all the color in the input * image. */ cht = ColorHashTableNew (15); ColorHashTableClear (cht); RgbTo256 (r, g, b, cht, rmap, gmap, bmap); ColorHashTableFree (cht); /* * For each color in the input image, find the closest color * among the 256 colors. */ cht = ColorHashTableNew (16); ColorHashTableClear (cht); tree = VpTreeNew (); VpTreeInit (rmap, gmap, bmap, tree); RgbQuantWithVpTree (r, g, b, tree, cht, rmap, gmap, bmap, indices); ColorHashTableFree (cht); /* * Initialize a sequence header and encode it. */ hdr = GifSeqHdrNew (); GifSeqHdrSetWidth (hdr, w); GifSeqHdrSetHeight (hdr, h); GifSeqHdrSetCtFlag (hdr, 1); GifSeqHdrSetVersion (hdr, "87a"); GifSeqHdrSetCtSize (hdr, 256); GifSeqHdrSetCtSorted (hdr, 0); GifSeqHdrSetAspectRatio (hdr, 0); GifSeqHdrSetResolution (hdr, 3); GifSeqHdrEncode (hdr, bp); /* * Encode the color table. */ GifCtEncode (256, rmap, gmap, bmap, bp); /* * Initialize the image header and encode it. */ img = GifImgHdrNew (); GifImgHdrSetWidth (img, w); GifImgHdrSetHeight (img, h); GifImgHdrSetCtFlag (img, 0); GifImgHdrSetLeftPosition (img, 0); GifImgHdrSetTopPosition (img, 0); GifImgHdrSetInterlaced (img, 0); GifImgHdrSetGraphicControlFlag (img, 0); GifImgHdrEncode (img, bp); /* * Encode the image. */ GifImgEncode (hdr, img, indices, bp); /* * Encode the sequence trailer to indicate end of bitstream. * Write the bitstream out to a file. */ GifSeqTrailerEncode (bp); BitStreamFileWrite (bs, f, 0); /* * Clean up */ fclose (f); ByteFree (r); ByteFree (g); ByteFree (b); ByteFree (indices); ImageMapFree (rmap); ImageMapFree (gmap); ImageMapFree (bmap); return 0; }