/*------------------------------------------------------------------------ * * 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 * * Sugata sugata@cs.cornell.edu * * Usage : ppmtojpg inputPPm outputJPG * * Reads a PPM file and encode it into a JPG file. * *------------------------------------------------------------------------ */ #include "dvmbasic.h" #include "dvmjpeg.h" #include "dvmcolor.h" #include "dvmpnm.h" #ifdef WIN32 #include "windows.h" #endif void ReadPPM(char *, PnmHdr **, ByteImage **, ByteImage **, ByteImage **); int main(int argc, char *argv[]) { #ifdef DO_TIMING LARGE_INTEGER curr; __int64 start, stop, f; #endif FILE *out; int i; PnmHdr *hdr; ByteImage *r, *g, *b, *y, *u, *v, *cr, *cg, *cb; ScImage *scy, *scu, *scv; int w, h, bw, bh; BitStream *outBs; BitParser *outBp; JpegHdr *jpegHdr; JpegScanHdr *scanHdr; JpegHuffTable *huffTable; /* * Check arguments and read in the input PPM. */ if (argc != 3) { fprintf(stderr, "usage : ppmtojpg <inputppm> <outputjpg>\n"); exit(1); } out = fopen(argv[2], "wb"); ReadPPM(argv[1], &hdr, &r, &g, &b); #ifdef DO_TIMING QueryPerformanceFrequency(&curr); f = curr.QuadPart; QueryPerformanceCounter(&curr); start = curr.QuadPart; #endif /* * Find the dimension of the input image. */ w = PnmHdrGetWidth(hdr); h = PnmHdrGetHeight(hdr); /* * Initialize the JPEG header. We uses the standard quantization * table and the standard Huffman table. We are encoding the image * using 4:2:0 sampling, so the block width and height are 2x2 for y * 1x1 for u, and 1x1 for v. We also make u and v plane share the same * quantization table. */ jpegHdr = JpegHdrNew(); JpegHdrSetWidth(jpegHdr, w); JpegHdrSetHeight(jpegHdr, h); JpegHdrSetNumOfComponents(jpegHdr, 3); JpegHdrSetRestartInterval(jpegHdr, 0); JpegHdrSetPrecision(jpegHdr, 8); JpegHdrSetBlockWidth(jpegHdr, 0, 2); JpegHdrSetBlockWidth(jpegHdr, 1, 1); JpegHdrSetBlockWidth(jpegHdr, 2, 1); JpegHdrSetMaxBlockWidth(jpegHdr, 2); JpegHdrSetBlockHeight(jpegHdr, 0, 2); JpegHdrSetBlockHeight(jpegHdr, 1, 1); JpegHdrSetBlockHeight(jpegHdr, 2, 1); JpegHdrSetMaxBlockHeight(jpegHdr, 2); JpegHdrSetQtId(jpegHdr, 0, 0); JpegHdrSetQtId(jpegHdr, 1, 1); JpegHdrSetQtId(jpegHdr, 2, 1); JpegHdrStdQtInit(jpegHdr); JpegHdrStdHtInit(jpegHdr); /* * Initialize the scan header. */ scanHdr = JpegScanHdrNew(); JpegScanHdrSetNumOfComponents(scanHdr, 3); JpegScanHdrSetScanId(scanHdr, 0, 0); JpegScanHdrSetScanId(scanHdr, 1, 1); JpegScanHdrSetScanId(scanHdr, 2, 2); JpegScanHdrSetDcId(scanHdr, 0, 0); JpegScanHdrSetDcId(scanHdr, 1, 1); JpegScanHdrSetDcId(scanHdr, 2, 1); JpegScanHdrSetAcId(scanHdr, 0, 0); JpegScanHdrSetAcId(scanHdr, 1, 1); JpegScanHdrSetAcId(scanHdr, 2, 1); /* * Creates and initialize a new huffman table for encoding. */ huffTable = JpegHuffTableNew(3); JpegHuffTableInit(jpegHdr, scanHdr, huffTable); /* * Creates a new bitstream. Assumes the the JPEG image is smaller * than the PPM, so a BitStream of size 3*w*h is enough for the output * JPEG. */ outBs = BitStreamNew(3*w*h); outBp = BitParserNew(); BitParserWrap(outBp, outBs); /* * Encodes the image start code, quantization table, huffman table, * header and scan header. */ JpegStartCodeEncode(outBp); i = JpegHdrQtEncode(jpegHdr, outBp); i = JpegHdrHtEncode(jpegHdr, outBp); i = JpegHdrEncode(jpegHdr, 1, outBp); i = JpegScanHdrEncode(jpegHdr, scanHdr, outBp); /* * We clip the input r, g, b into strips of size w x 16, and encodes * each strips. */ bw = w/8; scy = ScNew(bw, 2); scu = ScNew(bw/2, 1); scv = ScNew(bw/2, 1); y = ByteNew(w, 16); u = ByteNew(w/2, 8); v = ByteNew(w/2, 8); cr = ByteClip(r, 0, 0, 0, 0); cg = ByteClip(g, 0, 0, 0, 0); cb = ByteClip(b, 0, 0, 0, 0); JpegScanIncEncode420(jpegHdr, scanHdr, huffTable, NULL, scu, scv, outBp); bh = h >> 4; for (i = 0; i < bh; i++) { ByteReclip(r, 0, i<<4, w, 16, cr); ByteReclip(g, 0, i<<4, w, 16, cg); ByteReclip(b, 0, i<<4, w, 16, cb); RgbToYuv420(cr, cg, cb, y, u ,v); ByteToSc(y, scy); ByteToSc(u, scu); ByteToSc(v, scv); JpegScanIncEncode420(jpegHdr, scanHdr, huffTable, scy, scu, scv, outBp); } JpegScanIncEncode420(jpegHdr, scanHdr, huffTable, NULL, scu, scv, outBp); JpegEndCodeEncode(outBp); #ifdef DO_TIMING QueryPerformanceCounter(&curr); stop = curr.QuadPart; printf("TOTAL TIME : %f ms\n", (stop - start)/(double)f*1000.0); #endif BitStreamFileWriteSegment(outBs, out, 0, BitParserTell(outBp)); /* * Clean up. */ fclose(out); ByteFree(y); ByteFree(u); ByteFree(v); ByteFree(r); ByteFree(g); ByteFree(b); ScFree(scy); ScFree(scu); ScFree(scv); JpegHdrFree(jpegHdr); JpegScanHdrFree(scanHdr); JpegHuffTableFree(huffTable); return 0; }