const int _hsf[NUMSUBOPT]={1, 2, 2, 1};
const int _vsf[NUMSUBOPT]={1, 1, 2, 1};
+enum {YUVENCODE=1, YUVDECODE};
int yuv=0;
int exitstatus=0;
#define PAD(v, p) ((v+(p)-1)&(~((p)-1)))
int checkbufyuv(unsigned char *buf, unsigned long size, int w, int h,
- int subsamp)
+ int subsamp, int decode)
{
int i, j;
int hsf=_hsf[subsamp], vsf=_vsf[subsamp];
int pw=PAD(w, hsf), ph=PAD(h, vsf);
- int cw=pw/hsf, ch=ph/vsf;
- int ypitch=PAD(pw, 4), uvpitch=PAD(cw, 4);
+ int cw=PAD(pw/hsf, decode? 8:1), ch=PAD(ph/vsf, decode? 8:1);
+ int ypitch=PAD(pw, decode? 8:4), uvpitch=PAD(cw, decode? 8:4);
int retval=1;
unsigned long correctsize=ypitch*ph + (subsamp==TJ_GRAYSCALE? 0:uvpitch*ch*2);
char tempstr[1024]; unsigned char *bmpbuf=NULL;
const char *pixformat; double t;
- if(yuv) flags|=TJ_YUV;
+ if(yuv==YUVENCODE) flags|=TJ_YUV;
if(flags&TJ_BGR)
{
else {if(flags&TJ_ALPHAFIRST) pixformat="ARGB"; else pixformat="RGBA";}
}
if(ps==1) pixformat="Grayscale";
- if(yuv)
+ if(yuv==YUVENCODE)
printf("%s %s -> %s YUV ... ", pixformat,
(flags&TJ_BOTTOMUP)?"Bottom-Up":"Top-Down ", _subnamel[subsamp]);
else
_catch(tjCompress(hnd, bmpbuf, w, 0, h, ps, jpegbuf, size, subsamp, qual, flags));
t=rrtime()-t;
- if(yuv)
+ if(yuv==YUVENCODE)
sprintf(tempstr, "%s_enc_%s_%s_%s.yuv", basefilename, pixformat,
(flags&TJ_BOTTOMUP)? "BU":"TD", _subnames[subsamp]);
else
sprintf(tempstr, "%s_enc_%s_%s_%sQ%d.jpg", basefilename, pixformat,
(flags&TJ_BOTTOMUP)? "BU":"TD", _subnames[subsamp], qual);
writejpeg(jpegbuf, *size, tempstr);
- if(yuv)
+ if(yuv==YUVENCODE)
{
- if(checkbufyuv(jpegbuf, *size, w, h, subsamp)) printf("Passed.");
+ if(checkbufyuv(jpegbuf, *size, w, h, subsamp, 0)) printf("Passed.");
else printf("FAILED!");
}
else printf("Done.");
}
void gentestbmp(tjhandle hnd, unsigned char *jpegbuf, unsigned long jpegsize,
- int w, int h, int ps, char *basefilename, int subsamp, int qual, int flags)
+ int w, int h, int ps, char *basefilename, int subsamp, int flags)
{
unsigned char *bmpbuf=NULL;
const char *pixformat; int _w=0, _h=0; double t;
+ unsigned long size=0;
+ int hsf=_hsf[subsamp], vsf=_vsf[subsamp];
+ int pw=PAD(w, 8), ph=PAD(h, 8), cw=PAD(pw/hsf, 8), ch=PAD(ph/vsf, 8);
- if(yuv) return;
+ if(yuv==YUVDECODE) flags|=TJ_YUV;
+ else if(yuv==YUVENCODE) return;
if(flags&TJ_BGR)
{
else {if(flags&TJ_ALPHAFIRST) pixformat="ARGB"; else pixformat="RGBA";}
}
if(ps==1) pixformat="Grayscale";
- printf("JPEG -> %s %s ... ", pixformat, (flags&TJ_BOTTOMUP)?"Bottom-Up":"Top-Down ");
+ if(yuv==YUVDECODE)
+ printf("JPEG -> YUV %s ... ", _subnames[subsamp]);
+ else
+ printf("JPEG -> %s %s ... ", pixformat,
+ (flags&TJ_BOTTOMUP)?"Bottom-Up":"Top-Down ");
_catch(tjDecompressHeader(hnd, jpegbuf, jpegsize, &_w, &_h));
if(_w!=w || _h!=h)
printf("Incorrect JPEG header\n"); bailout();
}
- if((bmpbuf=(unsigned char *)malloc(w*h*ps+1))==NULL)
+ if(yuv==YUVDECODE)
+ size=pw*ph + (subsamp==TJ_GRAYSCALE? 0:cw*ch*(ps-1));
+ else
+ size=w*h*ps;
+ if((bmpbuf=(unsigned char *)malloc(size+1))==NULL)
{
printf("ERROR: Could not allocate buffer\n"); bailout();
}
- memset(bmpbuf, 0, w*ps*h);
+ memset(bmpbuf, 0, size+1);
t=rrtime();
_catch(tjDecompress(hnd, jpegbuf, jpegsize, bmpbuf, w, w*ps, h, ps, flags));
t=rrtime()-t;
- if(checkbuf(bmpbuf, w, h, ps, subsamp, flags)) printf("Passed.");
- else {printf("FAILED!"); dumpbuf(bmpbuf, w, h, ps, flags);}
-
+ if(yuv==YUVDECODE)
+ {
+ if(checkbufyuv(bmpbuf, size, pw, ph, subsamp, 1))
+ printf("Passed.");
+ else printf("FAILED!");
+ }
+ else
+ {
+ if(checkbuf(bmpbuf, w, h, ps, subsamp, flags)) printf("Passed.");
+ else {printf("FAILED!"); dumpbuf(bmpbuf, w, h, ps, flags);}
+ }
printf(" %f ms\n\n", t*1000.);
finally:
{printf("Error in tjInitDecompress():\n%s\n", tjGetErrorStr()); bailout();}
gentestjpeg(hnd, jpegbuf, &size, w, h, ps, basefilename, subsamp, 100, 0);
- gentestbmp(dhnd, jpegbuf, size, w, h, ps, basefilename, subsamp, 100, 0);
+ gentestbmp(dhnd, jpegbuf, size, w, h, ps, basefilename, subsamp, 0);
- if(ps==1) goto finally;
+ if(ps==1 || yuv==YUVDECODE) goto finally;
gentestjpeg(hnd, jpegbuf, &size, w, h, ps, basefilename, subsamp, 100, TJ_BGR);
- gentestbmp(dhnd, jpegbuf, size, w, h, ps, basefilename, subsamp, 100, TJ_BGR);
+ gentestbmp(dhnd, jpegbuf, size, w, h, ps, basefilename, subsamp, TJ_BGR);
gentestjpeg(hnd, jpegbuf, &size, w, h, ps, basefilename, subsamp, 100, TJ_BOTTOMUP);
- gentestbmp(dhnd, jpegbuf, size, w, h, ps, basefilename, subsamp, 100, TJ_BOTTOMUP);
+ gentestbmp(dhnd, jpegbuf, size, w, h, ps, basefilename, subsamp, TJ_BOTTOMUP);
gentestjpeg(hnd, jpegbuf, &size, w, h, ps, basefilename, subsamp, 100, TJ_BGR|TJ_BOTTOMUP);
- gentestbmp(dhnd, jpegbuf, size, w, h, ps, basefilename, subsamp, 100, TJ_BGR|TJ_BOTTOMUP);
+ gentestbmp(dhnd, jpegbuf, size, w, h, ps, basefilename, subsamp, TJ_BGR|TJ_BOTTOMUP);
if(ps==4)
{
gentestjpeg(hnd, jpegbuf, &size, w, h, ps, basefilename, subsamp, 100, TJ_ALPHAFIRST);
- gentestbmp(dhnd, jpegbuf, size, w, h, ps, basefilename, subsamp, 100, TJ_ALPHAFIRST);
+ gentestbmp(dhnd, jpegbuf, size, w, h, ps, basefilename, subsamp, TJ_ALPHAFIRST);
gentestjpeg(hnd, jpegbuf, &size, w, h, ps, basefilename, subsamp, 100, TJ_ALPHAFIRST|TJ_BGR);
- gentestbmp(dhnd, jpegbuf, size, w, h, ps, basefilename, subsamp, 100, TJ_ALPHAFIRST|TJ_BGR);
+ gentestbmp(dhnd, jpegbuf, size, w, h, ps, basefilename, subsamp, TJ_ALPHAFIRST|TJ_BGR);
gentestjpeg(hnd, jpegbuf, &size, w, h, ps, basefilename, subsamp, 100, TJ_ALPHAFIRST|TJ_BOTTOMUP);
- gentestbmp(dhnd, jpegbuf, size, w, h, ps, basefilename, subsamp, 100, TJ_ALPHAFIRST|TJ_BOTTOMUP);
+ gentestbmp(dhnd, jpegbuf, size, w, h, ps, basefilename, subsamp, TJ_ALPHAFIRST|TJ_BOTTOMUP);
gentestjpeg(hnd, jpegbuf, &size, w, h, ps, basefilename, subsamp, 100, TJ_ALPHAFIRST|TJ_BGR|TJ_BOTTOMUP);
- gentestbmp(dhnd, jpegbuf, size, w, h, ps, basefilename, subsamp, 100, TJ_ALPHAFIRST|TJ_BGR|TJ_BOTTOMUP);
+ gentestbmp(dhnd, jpegbuf, size, w, h, ps, basefilename, subsamp, TJ_ALPHAFIRST|TJ_BGR|TJ_BOTTOMUP);
}
finally:
int main(int argc, char *argv[])
{
- if(argc>1 && !stricmp(argv[1], "-yuv")) yuv=1;
- dotest(35, 41, 3, TJ_444, "test");
- dotest(35, 41, 4, TJ_444, "test");
- if(yuv)
+ int doyuv=0;
+ if(argc>1 && !stricmp(argv[1], "-yuv")) doyuv=1;
+ if(doyuv) yuv=YUVENCODE;
+ dotest(35, 39, 3, TJ_444, "test");
+ dotest(39, 41, 4, TJ_444, "test");
+ if(doyuv)
+ {
+ dotest(41, 35, 3, TJ_422, "test");
+ dotest(35, 39, 4, TJ_422, "test");
+ dotest(39, 41, 3, TJ_420, "test");
+ dotest(41, 35, 4, TJ_420, "test");
+ }
+ dotest(35, 39, 1, TJ_GRAYSCALE, "test");
+ dotest(39, 41, 3, TJ_GRAYSCALE, "test");
+ dotest(41, 35, 4, TJ_GRAYSCALE, "test");
+ if(!doyuv) dotest1();
+ if(doyuv)
{
- dotest(35, 41, 3, TJ_422, "test");
- dotest(35, 41, 4, TJ_422, "test");
- dotest(35, 41, 3, TJ_420, "test");
- dotest(35, 41, 4, TJ_420, "test");
+ yuv=YUVDECODE;
+ dotest(35, 39, 3, TJ_444, "test");
+ dotest(39, 41, 1, TJ_GRAYSCALE, "test");
}
- dotest(35, 41, 1, TJ_GRAYSCALE, "test");
- dotest(35, 41, 3, TJ_GRAYSCALE, "test");
- dotest(35, 41, 4, TJ_GRAYSCALE, "test");
- dotest1();
return exitstatus;
}
#define _throwtj(m) _throw(m, tjGetErrorStr())
#define _throwbmp(m) _throw(m, bmpgeterr())
+#define PAD(v, p) ((v+(p)-1)&(~((p)-1)))
+
+enum {YUVENCODE=1, YUVDECODE};
int forcemmx=0, forcesse=0, forcesse2=0, forcesse3=0, fastupsample=0,
decomponly=0, yuv=0;
const int _ps[BMPPIXELFORMATS]={3, 4, 3, 4, 4, 4};
const char *_pfname[]={"RGB", "RGBA", "BGR", "BGRA", "ABGR", "ARGB"};
const char *_subnamel[NUMSUBOPT]={"4:4:4", "4:2:2", "4:2:0", "GRAY"};
const char *_subnames[NUMSUBOPT]={"444", "422", "420", "GRAY"};
+const int _hsf[NUMSUBOPT]={1, 2, 2, 1};
+const int _vsf[NUMSUBOPT]={1, 1, 2, 1};
void printsigfig(double val, int figs)
{
int jpegsub, int qual, char *filename, int dotile, int useppm, int quiet)
{
char tempstr[1024];
- FILE *outfile; tjhandle hnd;
+ FILE *outfile=NULL; tjhandle hnd;
unsigned char **jpegbuf=NULL, *rgbbuf=NULL;
rrtimer timer; double elapsed;
int jpgbufsize=0, i, j, tilesizex, tilesizey, numtilesx, numtilesy, ITER;
|(forcesse2?TJ_FORCESSE2:0)|(forcesse3?TJ_FORCESSE3:0)
|(fastupsample?TJ_FASTUPSAMPLE:0);
int ps=_ps[pf];
- int pitch=w*ps;
+ int pitch=w*ps, yuvsize;
+ int hsf=_hsf[jpegsub], vsf=_vsf[jpegsub];
+ int pw=PAD(w, 8), ph=PAD(h, 8), cw=PAD(pw/hsf, 8), ch=PAD(ph/vsf, 8);
flags |= _flags[pf];
if(bu) flags |= TJ_BOTTOMUP;
- if(yuv) flags |= TJ_YUV;
+ if(yuv==YUVENCODE) flags |= TJ_YUV;
- if((rgbbuf=(unsigned char *)malloc(pitch*h)) == NULL)
+ yuvsize=pw*ph + (jpegsub==TJ_GRAYSCALE? 0:cw*ch*2);
+ if((rgbbuf=(unsigned char *)malloc(max(yuvsize, pitch*h))) == NULL)
_throwunix("allocating image buffer");
if(!quiet)
{
- if(yuv)
+ if(yuv==YUVENCODE)
printf("\n>>>>> %s (%s) <--> YUV %s <<<<<\n", _pfname[pf],
bu?"Bottom-up":"Top-down", _subnamel[jpegsub]);
else
printf("\n>>>>> %s (%s) <--> JPEG %s Q%d <<<<<\n", _pfname[pf],
bu?"Bottom-up":"Top-down", _subnamel[jpegsub], qual);
}
+ if(yuv==YUVDECODE) dotile=0;
if(dotile) {tilesizex=tilesizey=4;} else {tilesizex=w; tilesizey=h;}
do
}
if(tilesizex==w && tilesizey==h)
{
- if(yuv)
+ if(yuv==YUVENCODE)
sprintf(tempstr, "%s_%s.yuv", filename, _subnames[jpegsub]);
else
sprintf(tempstr, "%s_%sQ%d.jpg", filename, _subnames[jpegsub], qual);
_throwunix("opening reference image");
if(fwrite(jpegbuf[0], jpgbufsize, 1, outfile)!=1)
_throwunix("writing reference image");
- fclose(outfile);
+ fclose(outfile); outfile=NULL;
if(!quiet) printf("Reference image written to %s\n", tempstr);
}
- if(yuv) goto bailout;
+ if(yuv==YUVENCODE) goto bailout;
// Decompression test
- memset(rgbbuf, 127, pitch*h); // Grey image means decompressor did nothing
+ if(yuv==YUVDECODE) flags |= TJ_YUV;
+ memset(rgbbuf, 127, max(yuvsize, pitch*h)); // Grey image means decompressor did nothing
if((hnd=tjInitDecompress())==NULL)
_throwtj("executing tjInitDecompress()");
if(tjDecompress(hnd, jpegbuf[0], jpgbufsize, rgbbuf, tilesizex, pitch,
printf(" Dest. throughput: %f Megapixels/sec\n",
(double)(w*h)/1000000.*(double)ITER/elapsed);
}
- if(tilesizex==w && tilesizey==h)
- sprintf(tempstr, "%s_%sQ%d_full.%s", filename, _subnames[jpegsub], qual,
- useppm?"ppm":"bmp");
- else sprintf(tempstr, "%s_%sQ%d_%dx%d.%s", filename, _subnames[jpegsub],
- qual, tilesizex, tilesizey, useppm?"ppm":"bmp");
- if(savebmp(tempstr, rgbbuf, w, h, pf, pitch, bu)==-1)
- _throwbmp("saving bitmap");
- sprintf(strrchr(tempstr, '.'), "-err.%s", useppm?"ppm":"bmp");
- if(!quiet)
- printf("Computing compression error and saving to %s.\n", tempstr);
- if(jpegsub==TJ_GRAYSCALE)
+ if(yuv==YUVDECODE)
+ {
+ sprintf(tempstr, "%s_%sQ%d.yuv", filename, _subnames[jpegsub], qual);
+ if((outfile=fopen(tempstr, "wb"))==NULL)
+ _throwunix("opening YUV image for output");
+ if(fwrite(rgbbuf, yuvsize, 1, outfile)!=1)
+ _throwunix("writing YUV image");
+ fclose(outfile); outfile=NULL;
+ }
+ else
{
- for(j=0; j<h; j++)
+ if(tilesizex==w && tilesizey==h)
+ sprintf(tempstr, "%s_%sQ%d_full.%s", filename, _subnames[jpegsub], qual,
+ useppm?"ppm":"bmp");
+ else sprintf(tempstr, "%s_%sQ%d_%dx%d.%s", filename, _subnames[jpegsub],
+ qual, tilesizex, tilesizey, useppm?"ppm":"bmp");
+ if(savebmp(tempstr, rgbbuf, w, h, pf, pitch, bu)==-1)
+ _throwbmp("saving bitmap");
+ sprintf(strrchr(tempstr, '.'), "-err.%s", useppm?"ppm":"bmp");
+ if(!quiet)
+ printf("Computing compression error and saving to %s.\n", tempstr);
+ if(jpegsub==TJ_GRAYSCALE)
{
- for(i=0; i<w*ps; i+=ps)
+ for(j=0; j<h; j++)
{
- int y=(int)((double)srcbuf[w*ps*j+i+_rindex[pf]]*0.299
- + (double)srcbuf[w*ps*j+i+_gindex[pf]]*0.587
- + (double)srcbuf[w*ps*j+i+_bindex[pf]]*0.114 + 0.5);
- if(y>255) y=255; if(y<0) y=0;
- rgbbuf[pitch*j+i+_rindex[pf]]=abs(rgbbuf[pitch*j+i+_rindex[pf]]-y);
- rgbbuf[pitch*j+i+_gindex[pf]]=abs(rgbbuf[pitch*j+i+_gindex[pf]]-y);
- rgbbuf[pitch*j+i+_bindex[pf]]=abs(rgbbuf[pitch*j+i+_bindex[pf]]-y);
+ for(i=0; i<w*ps; i+=ps)
+ {
+ int y=(int)((double)srcbuf[w*ps*j+i+_rindex[pf]]*0.299
+ + (double)srcbuf[w*ps*j+i+_gindex[pf]]*0.587
+ + (double)srcbuf[w*ps*j+i+_bindex[pf]]*0.114 + 0.5);
+ if(y>255) y=255; if(y<0) y=0;
+ rgbbuf[pitch*j+i+_rindex[pf]]=abs(rgbbuf[pitch*j+i+_rindex[pf]]-y);
+ rgbbuf[pitch*j+i+_gindex[pf]]=abs(rgbbuf[pitch*j+i+_gindex[pf]]-y);
+ rgbbuf[pitch*j+i+_bindex[pf]]=abs(rgbbuf[pitch*j+i+_bindex[pf]]-y);
+ }
}
+ }
+ else
+ {
+ for(j=0; j<h; j++) for(i=0; i<w*ps; i++)
+ rgbbuf[pitch*j+i]=abs(rgbbuf[pitch*j+i]-srcbuf[w*ps*j+i]);
}
- }
- else
- {
- for(j=0; j<h; j++) for(i=0; i<w*ps; i++)
- rgbbuf[pitch*j+i]=abs(rgbbuf[pitch*j+i]-srcbuf[w*ps*j+i]);
+ if(savebmp(tempstr, rgbbuf, w, h, pf, pitch, bu)==-1)
+ _throwbmp("saving bitmap");
}
- if(savebmp(tempstr, rgbbuf, w, h, pf, pitch, bu)==-1)
- _throwbmp("saving bitmap");
// Cleanup
+ if(outfile) {fclose(outfile); outfile=NULL;}
if(jpegbuf)
{
for(i=0; i<numtilesx*numtilesy; i++)
return;
bailout:
+ if(outfile) {fclose(outfile); outfile=NULL;}
if(jpegbuf)
{
for(i=0; i<numtilesx*numtilesy; i++)
printf(" YUV decoding in libjpeg decompressor\n\n");
printf(" [-quiet]\n");
printf(" Output in tabular rather than verbose format\n\n");
- printf(" [-yuv]\n");
+ printf(" [-yuvencode]\n");
printf(" Encode RGB input as planar YUV rather than compressing as JPEG\n\n");
+ printf(" [-yuvdecode]\n");
+ printf(" Decode JPEG image to planar YUV rather than RGB\n\n");
printf(" NOTE: If the quality is specified as a range, i.e. 90-100, a separate\n");
printf(" test will be performed for all quality values in the range.\n");
exit(1);
{
for(i=minarg; i<argc; i++)
{
- if(!stricmp(argv[i], "-yuv"))
+ if(!stricmp(argv[i], "-yuvencode"))
{
printf("Testing YUV planar encoding\n");
- yuv=1; hiqual=qual=100;
+ yuv=YUVENCODE; hiqual=qual=100;
+ }
+ if(!stricmp(argv[i], "-yuvdecode"))
+ {
+ printf("Testing YUV planar decoding\n");
+ yuv=YUVDECODE;
}
}
}
- if(!decomponly && !yuv)
+ if(!decomponly && yuv!=YUVENCODE)
{
minarg=3;
if(argc<minarg) usage(argv[0]);
if(setjmp(j->jerr.jb))
{ // this will execute if LIBJPEG has an error
free(j); return NULL;
- }
+ }
jpeg_create_decompress(&j->dinfo);
j->dinfo.src=&j->jsms;
unsigned char *dstbuf, int width, int pitch, int height, int ps,
int flags)
{
- int i; JSAMPROW *row_pointer=NULL;
+ int i, row; JSAMPROW *row_pointer=NULL, *outbuf[MAX_COMPONENTS];
+ int cw[MAX_COMPONENTS], ch[MAX_COMPONENTS];
checkhandle(h);
+ for(i=0; i<MAX_COMPONENTS; i++) outbuf[i]=NULL;
+
if(srcbuf==NULL || size<=0
|| dstbuf==NULL || width<=0 || pitch<0 || height<=0)
_throw("Invalid argument in tjDecompress()");
if(setjmp(j->jerr.jb))
{ // this will execute if LIBJPEG has an error
+ for(i=0; i<MAX_COMPONENTS; i++)
+ if(outbuf[i]!=NULL) free(outbuf[i]);
if(row_pointer) free(row_pointer);
return -1;
- }
+ }
j->jsms.bytes_in_buffer = size;
j->jsms.next_input_byte = srcbuf;
jpeg_read_header(&j->dinfo, TRUE);
- if((row_pointer=(JSAMPROW *)malloc(sizeof(JSAMPROW)*height))==NULL)
- _throw("Memory allocation failed in tjInitDecompress()");
- for(i=0; i<height; i++)
+ if(flags&TJ_YUV)
+ {
+ j_decompress_ptr dinfo=&j->dinfo;
+ JSAMPLE *ptr=dstbuf;
+
+ for(i=0; i<dinfo->num_components; i++)
+ {
+ jpeg_component_info *compptr=&dinfo->comp_info[i];
+ cw[i]=compptr->width_in_blocks*DCTSIZE;
+ ch[i]=compptr->height_in_blocks*DCTSIZE;
+ if((outbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*ch[i]))==NULL)
+ _throw("Memory allocation failed in tjInitDecompress()");
+ for(row=0; row<ch[i]; row++)
+ {
+ outbuf[i][row]=ptr;
+ ptr+=cw[i];
+ }
+ }
+ }
+ else
{
- if(flags&TJ_BOTTOMUP) row_pointer[i]= &dstbuf[(height-i-1)*pitch];
- else row_pointer[i]= &dstbuf[i*pitch];
+ if((row_pointer=(JSAMPROW *)malloc(sizeof(JSAMPROW)*height))==NULL)
+ _throw("Memory allocation failed in tjInitDecompress()");
+ for(i=0; i<height; i++)
+ {
+ if(flags&TJ_BOTTOMUP) row_pointer[i]= &dstbuf[(height-i-1)*pitch];
+ else row_pointer[i]= &dstbuf[i*pitch];
+ }
}
if(ps==1) j->dinfo.out_color_space = JCS_GRAYSCALE;
#endif
if(flags&TJ_FASTUPSAMPLE) j->dinfo.do_fancy_upsampling=FALSE;
+ if(flags&TJ_YUV) j->dinfo.raw_data_out=TRUE;
jpeg_start_decompress(&j->dinfo);
- while(j->dinfo.output_scanline<j->dinfo.output_height)
+ if(flags&TJ_YUV)
+ {
+ for(row=0; row<j->dinfo.output_height;
+ row+=j->dinfo.max_v_samp_factor*DCTSIZE)
+ {
+ JSAMPARRAY yuvptr[MAX_COMPONENTS];
+ for(i=0; i<j->dinfo.num_components; i++)
+ {
+ jpeg_component_info *compptr=&j->dinfo.comp_info[i];
+ yuvptr[i]=&outbuf[i][row*compptr->v_samp_factor/j->dinfo.max_v_samp_factor];
+ }
+ jpeg_read_raw_data(&j->dinfo, yuvptr, j->dinfo.max_v_samp_factor*DCTSIZE);
+ }
+ }
+ else
{
- jpeg_read_scanlines(&j->dinfo, &row_pointer[j->dinfo.output_scanline],
- j->dinfo.output_height-j->dinfo.output_scanline);
+ while(j->dinfo.output_scanline<j->dinfo.output_height)
+ {
+ jpeg_read_scanlines(&j->dinfo, &row_pointer[j->dinfo.output_scanline],
+ j->dinfo.output_height-j->dinfo.output_scanline);
+ }
}
jpeg_finish_decompress(&j->dinfo);
+ for(i=0; i<MAX_COMPONENTS; i++)
+ if(outbuf[i]) free(outbuf[i]);
if(row_pointer) free(row_pointer);
return 0;
}