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