/* Copyright (C)2004 Landmark Graphics Corporation * Copyright (C)2005, 2006 Sun Microsystems, Inc. * Copyright (C)2009-2010 D. R. Commander * * This library is free software and may be redistributed and/or modified under * the terms of the wxWindows Library License, Version 3.1 or (at your option) * any later version. The full license is in the LICENSE.txt file included * with this distribution. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * wxWindows Library License for more details. */ #include #include #include #include #include #include "./bmp.h" #include "./rrutil.h" #include "./rrtimer.h" #include "./turbojpeg.h" #define _throw(op, err) { \ printf("ERROR in line %d while %s:\n%s\n", __LINE__, op, err); goto bailout;} #define _throwunix(m) _throw(m, strerror(errno)) #define _throwtj(m) _throw(m, tjGetErrorStr()) #define _throwbmp(m) _throw(m, bmpgeterr()) int forcemmx=0, forcesse=0, forcesse2=0, forcesse3=0, fastupsample=0, decomponly=0; const int _ps[BMPPIXELFORMATS]={3, 4, 3, 4, 4, 4}; const int _flags[BMPPIXELFORMATS]={0, 0, TJ_BGR, TJ_BGR, TJ_BGR|TJ_ALPHAFIRST, TJ_ALPHAFIRST}; const int _rindex[BMPPIXELFORMATS]={0, 0, 2, 2, 3, 1}; const int _gindex[BMPPIXELFORMATS]={1, 1, 1, 1, 2, 2}; const int _bindex[BMPPIXELFORMATS]={2, 2, 0, 0, 1, 3}; 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"}; void printsigfig(double val, int figs) { char format[80]; double _l=log10(val); int l; if(_l<0.) { l=(int)fabs(_l); sprintf(format, "%%%d.%df", figs+l+2, figs+l); } else { l=(int)_l+1; if(figs<=l) sprintf(format, "%%.0f"); else sprintf(format, "%%%d.%df", figs+1, figs-l); } printf(format, val); } void dotest(unsigned char *srcbuf, int w, int h, BMPPIXELFORMAT pf, int bu, int jpegsub, int qual, char *filename, int dotile, int useppm, int quiet) { char tempstr[1024]; FILE *outfile; tjhandle hnd; unsigned char **jpegbuf=NULL, *rgbbuf=NULL; rrtimer timer; double elapsed; int jpgbufsize=0, i, j, tilesizex, tilesizey, numtilesx, numtilesy, ITER; unsigned long *comptilesize=NULL; int flags=(forcemmx?TJ_FORCEMMX:0)|(forcesse?TJ_FORCESSE:0) |(forcesse2?TJ_FORCESSE2:0)|(forcesse3?TJ_FORCESSE3:0) |(fastupsample?TJ_FASTUPSAMPLE:0); int ps=_ps[pf]; int pitch=w*ps; flags |= _flags[pf]; if(bu) flags |= TJ_BOTTOMUP; if((rgbbuf=(unsigned char *)malloc(pitch*h)) == NULL) _throwunix("allocating image buffer"); if(!quiet) printf("\n>>>>> %s (%s) <--> JPEG %s Q%d <<<<<\n", _pfname[pf], bu?"Bottom-up":"Top-down", _subnamel[jpegsub], qual); if(dotile) {tilesizex=tilesizey=4;} else {tilesizex=w; tilesizey=h;} do { tilesizex*=2; if(tilesizex>w) tilesizex=w; tilesizey*=2; if(tilesizey>h) tilesizey=h; numtilesx=(w+tilesizex-1)/tilesizex; numtilesy=(h+tilesizey-1)/tilesizey; if((comptilesize=(unsigned long *)malloc(sizeof(unsigned long)*numtilesx*numtilesy)) == NULL || (jpegbuf=(unsigned char **)malloc(sizeof(unsigned char *)*numtilesx*numtilesy)) == NULL) _throwunix("allocating image buffers"); memset(jpegbuf, 0, sizeof(unsigned char *)*numtilesx*numtilesy); for(i=0; i Frame rate: %f fps\n", (double)ITER/elapsed); printf(" Output image size: %d bytes\n", jpgbufsize); printf(" Compression ratio: %f:1\n", (double)(w*h*ps)/(double)jpgbufsize); printf(" Source throughput: %f Megapixels/sec\n", (double)(w*h)/1000000.*(double)ITER/elapsed); printf(" Output bit stream: %f Megabits/sec\n", (double)jpgbufsize*8./1000000.*(double)ITER/elapsed); } if(tilesizex==w && tilesizey==h) { sprintf(tempstr, "%s_%sQ%d.jpg", filename, _subnames[jpegsub], qual); if((outfile=fopen(tempstr, "wb"))==NULL) _throwunix("opening reference image"); if(fwrite(jpegbuf[0], jpgbufsize, 1, outfile)!=1) _throwunix("writing reference image"); fclose(outfile); if(!quiet) printf("Reference image written to %s\n", tempstr); } // Decompression test memset(rgbbuf, 127, pitch*h); // Grey image means decompressor did nothing if((hnd=tjInitDecompress())==NULL) _throwtj("executing tjInitDecompress()"); if(tjDecompress(hnd, jpegbuf[0], jpgbufsize, rgbbuf, tilesizex, pitch, tilesizey, ps, flags)==-1) _throwtj("executing tjDecompress()"); ITER=0; timer.start(); do { int tilen=0; for(i=0; i Frame rate: %f fps\n", (double)ITER/elapsed); 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) { for(j=0; j255) 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>>>> JPEG --> %s (%s) <<<<<\n", _pfname[pf], bu?"Bottom-up":"Top-down"); printf("\nImage size: %d x %d\n", w, h); } memset(rgbbuf, 127, pitch*h); // Grey image means decompressor did nothing if(tjDecompress(hnd, jpegbuf, jpgbufsize, rgbbuf, w, pitch, h, ps, flags)==-1) _throwtj("executing tjDecompress()"); ITER=0; timer.start(); do { if(tjDecompress(hnd, jpegbuf, jpgbufsize, rgbbuf, w, pitch, h, ps, flags) ==-1) _throwtj("executing tjDecompress()"); ITER++; } while((elapsed=timer.elapsed())<5.); if(tjDestroy(hnd)==-1) _throwtj("executing tjDestroy()"); hnd=NULL; if(quiet) { printsigfig((double)(w*h)/1000000.*(double)ITER/elapsed, 4); printf("\n"); } else { printf("D--> Frame rate: %f fps\n", (double)ITER/elapsed); printf(" Dest. throughput: %f Megapixels/sec\n", (double)(w*h)/1000000.*(double)ITER/elapsed); } sprintf(tempstr, "%s_full.%s", filename, useppm?"ppm":"bmp"); if(savebmp(tempstr, rgbbuf, w, h, pf, pitch, bu)==-1) _throwbmp("saving bitmap"); bailout: if(jpegbuf) {free(jpegbuf); jpegbuf=NULL;} if(rgbbuf) {free(rgbbuf); rgbbuf=NULL;} if(hnd) {tjDestroy(hnd); hnd=NULL;} return; } void usage(char *progname) { printf("USAGE: %s <%% Quality>\n", progname); printf(" %s \n\n", progname); printf(" [-tile]\n"); printf(" Test performance of the codec when the image is encoded\n"); printf(" as separate tiles of varying sizes.\n\n"); printf(" [-forcemmx] [-forcesse] [-forcesse2] [-forcesse3]\n"); printf(" Force MMX, SSE, or SSE2 code paths in Intel codec\n\n"); printf(" [-rgb | -bgr | -rgba | -bgra | -abgr | -argb]\n"); printf(" Test the specified color conversion path in the codec (default: BGR)\n\n"); printf(" [-fastupsample]\n"); printf(" Use fast, inaccurate upsampling code to perform 4:2:2 and 4:2:0\n"); printf(" YUV decoding in libjpeg decompressor\n\n"); printf(" [-quiet]\n"); printf(" Output in tabular rather than verbose format\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); } int main(int argc, char *argv[]) { unsigned char *bmpbuf=NULL; int w, h, i, useppm=0; int qual, dotile=0, quiet=0, hiqual=-1; char *temp; BMPPIXELFORMAT pf=BMP_BGR; int bu=0, minarg=2; printf("\n"); if(argc100) { puts("ERROR: Quality must be between 1 and 100."); exit(1); } if((temp=strchr(argv[2], '-'))!=NULL && strlen(temp)>1 && sscanf(&temp[1], "%d", &hiqual)==1 && hiqual>qual && hiqual>=1 && hiqual<=100) {} else hiqual=qual; } if(argc>minarg) { for(i=minarg; i=qual; i--) dotest(bmpbuf, w, h, pf, bu, TJ_GRAYSCALE, i, argv[1], dotile, useppm, quiet); if(quiet) printf("\n"); for(i=hiqual; i>=qual; i--) dotest(bmpbuf, w, h, pf, bu, TJ_420, i, argv[1], dotile, useppm, quiet); if(quiet) printf("\n"); for(i=hiqual; i>=qual; i--) dotest(bmpbuf, w, h, pf, bu, TJ_422, i, argv[1], dotile, useppm, quiet); if(quiet) printf("\n"); for(i=hiqual; i>=qual; i--) dotest(bmpbuf, w, h, pf, bu, TJ_444, i, argv[1], dotile, useppm, quiet); bailout: if(bmpbuf) free(bmpbuf); return 0; }