/*------------------------------------------------------------------------ * * 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. * * jpgtoppm * * Sugata sugata@cs.cornell.edu * * Usage : jpgtoppm inputJPG outputPPM * * Converts an input JPEG into a PPM file, quality = 50, using default * quantization table and huffman table. Only common sampling format * (420 and 422) and JPEG with single scan is supported. * *------------------------------------------------------------------------ */ #include "dvmbasic.h" #include "dvmjpeg.h" #include "dvmpnm.h" #include "dvmcolor.h" void WritePPM(PnmHdr *, ByteImage *, ByteImage *, ByteImage *, char *); int main(int argc, char *argv[]) { BitStream *bs; BitParser *bp; JpegHdr *hdr; JpegScanHdr *scanHdr; int nc, wi, hi, bw, bh, mbw, mbh, *xdec, *ydec, id, pw, ph; ByteImage *y, *u, *v, *r, *g, *b; int i; ScImage **sclist; PnmHdr* pnmHdr; /* * Check the arguments. */ if (argc < 3) { fprintf(stderr, "usage : %s input output\n", argv[0]); exit(1); } /* * Initialize bitstream and bitparser. */ bs = BitStreamMmapReadNew(argv[1]); bp = BitParserNew(); BitParserWrap(bp, bs); /* * First, we read off the JPEG header and scan header. */ hdr = JpegHdrNew(); JpegHdrParse(bp, hdr); scanHdr = JpegScanHdrNew(); JpegScanHdrParse(bp, hdr, scanHdr); /* * Find out the number of components, width and height of the image. * bw and bh are the dimension of the image in blocks. */ nc = JpegScanHdrGetNumOfComponents(scanHdr); wi = JpegHdrGetWidth(hdr); hi = JpegHdrGetHeight(hdr); bw = (wi+7)/8; bh = (hi+7)/8; mbw = JpegHdrGetMaxBlockWidth(hdr); mbh = JpegHdrGetMaxBlockHeight(hdr); xdec = (int *)malloc(sizeof(int)*nc); ydec = (int *)malloc(sizeof(int)*nc); sclist = (ScImage **)malloc(sizeof(ScImage *)*nc); for (i = 0; i < nc; i++) { id = JpegScanHdrGetScanId(scanHdr, i); xdec[i] = mbw/(JpegHdrGetBlockWidth(hdr, id)); ydec[i] = mbh/(JpegHdrGetBlockHeight(hdr, id)); sclist[i] = ScNew(bw/xdec[i], bh/ydec[i]); } /* * Finally, we parse the scan. */ JpegScanParse(bp, hdr, scanHdr, sclist, i); /* * Prepare to decode the image. */ pw = bw << 3; ph = bh << 3; y = ByteNew(pw/xdec[0], ph/ydec[0]); u = ByteNew(pw/xdec[1], ph/ydec[1]); v = ByteNew(pw/xdec[2], ph/ydec[2]); r = ByteNew(pw, ph); g = ByteNew(pw, ph); b = ByteNew(pw, ph); /* * Perform IDCT and dequantization on the image to get the raw image * in YUV color space. */ ScIToByte(sclist[0], y); ScIToByte(sclist[1], u); ScIToByte(sclist[2], v); /* * Perform color conversion from YUV to RGB color space. */ if (mbh == 1) { YuvToRgb422(y, u, v, r, g, b); } else { YuvToRgb420(y, u, v, r, g, b); } /* * Now output the PPM file. */ pnmHdr = PnmHdrNew(); PnmHdrSetWidth(pnmHdr, pw); PnmHdrSetHeight(pnmHdr, ph); PnmHdrSetMaxVal(pnmHdr, 255); PnmHdrSetType(pnmHdr, PPM_BIN); WritePPM (pnmHdr, r, g, b, argv[2]); /* * Clean up here. */ PnmHdrFree(pnmHdr); JpegScanHdrFree(scanHdr); JpegHdrFree(hdr); ByteFree(y); ByteFree(u); ByteFree(v); ByteFree(r); ByteFree(g); ByteFree(b); BitStreamMmapReadFree(bs); free(xdec); free(ydec); return 0; }