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