1/* 2 * Copyright (C)2009-2012 D. R. Commander. All Rights Reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are met: 6 * 7 * - Redistributions of source code must retain the above copyright notice, 8 * this list of conditions and the following disclaimer. 9 * - Redistributions in binary form must reproduce the above copyright notice, 10 * this list of conditions and the following disclaimer in the documentation 11 * and/or other materials provided with the distribution. 12 * - Neither the name of the libjpeg-turbo Project nor the names of its 13 * contributors may be used to endorse or promote products derived from this 14 * software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS", 17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE 20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29#include <stdio.h> 30#include <stdlib.h> 31#include <string.h> 32#include <math.h> 33#include <errno.h> 34#include "./bmp.h" 35#include "./tjutil.h" 36#include "./turbojpeg.h" 37 38 39#define _throw(op, err) { \ 40 printf("ERROR in line %d while %s:\n%s\n", __LINE__, op, err); \ 41 (void)retval; /* silence warning */ \ 42 retval=-1; goto bailout;} 43#define _throwunix(m) _throw(m, strerror(errno)) 44#define _throwtj(m) _throw(m, tjGetErrorStr()) 45#define _throwbmp(m) _throw(m, bmpgeterr()) 46 47int flags=0, decomponly=0, quiet=0, dotile=0, pf=TJPF_BGR; 48char *ext="ppm"; 49const char *pixFormatStr[TJ_NUMPF]= 50{ 51 "RGB", "BGR", "RGBX", "BGRX", "XBGR", "XRGB", "GRAY" 52}; 53const int bmpPF[TJ_NUMPF]= 54{ 55 BMP_RGB, BMP_BGR, BMP_RGBX, BMP_BGRX, BMP_XBGR, BMP_XRGB, -1 56}; 57const char *subNameLong[TJ_NUMSAMP]= 58{ 59 "4:4:4", "4:2:2", "4:2:0", "GRAY", "4:4:0" 60}; 61const char *subName[NUMSUBOPT]={"444", "422", "420", "GRAY", "440"}; 62tjscalingfactor *scalingfactors=NULL, sf={1, 1}; int nsf=0; 63double benchtime=5.0; 64 65 66char *sigfig(double val, int figs, char *buf, int len) 67{ 68 char format[80]; 69 int digitsafterdecimal=figs-(int)ceil(log10(fabs(val))); 70 if(digitsafterdecimal<1) snprintf(format, 80, "%%.0f"); 71 else snprintf(format, 80, "%%.%df", digitsafterdecimal); 72 snprintf(buf, len, format, val); 73 return buf; 74} 75 76 77/* Decompression test */ 78int decomptest(unsigned char *srcbuf, unsigned char **jpegbuf, 79 unsigned long *jpegsize, unsigned char *dstbuf, int w, int h, 80 int subsamp, int jpegqual, char *filename, int tilew, int tileh) 81{ 82 char tempstr[1024], sizestr[20]="\0", qualstr[6]="\0", *ptr; 83 FILE *file=NULL; tjhandle handle=NULL; 84 int row, col, i, dstbufalloc=0, retval=0; 85 double start, elapsed; 86 int ps=tjPixelSize[pf]; 87 int bufsize; 88 int scaledw=TJSCALED(w, sf); 89 int scaledh=TJSCALED(h, sf); 90 int pitch=scaledw*ps; 91 int ntilesw=(w+tilew-1)/tilew, ntilesh=(h+tileh-1)/tileh; 92 unsigned char *dstptr, *dstptr2; 93 94 if(jpegqual>0) 95 { 96 snprintf(qualstr, 6, "_Q%d", jpegqual); 97 qualstr[5]=0; 98 } 99 100 if((handle=tjInitDecompress())==NULL) 101 _throwtj("executing tjInitDecompress()"); 102 103 bufsize=pitch*scaledh; 104 if(dstbuf==NULL) 105 { 106 if((dstbuf=(unsigned char *)malloc(bufsize)) == NULL) 107 _throwunix("allocating image buffer"); 108 dstbufalloc=1; 109 } 110 /* Set the destination buffer to gray so we know whether the decompressor 111 attempted to write to it */ 112 memset(dstbuf, 127, bufsize); 113 114 /* Execute once to preload cache */ 115 if(tjDecompress2(handle, jpegbuf[0], jpegsize[0], dstbuf, scaledw, 116 pitch, scaledh, pf, flags)==-1) 117 _throwtj("executing tjDecompress2()"); 118 119 /* Benchmark */ 120 for(i=0, start=gettime(); (elapsed=gettime()-start)<benchtime; i++) 121 { 122 int tile=0; 123 for(row=0, dstptr=dstbuf; row<ntilesh; row++, dstptr+=pitch*tileh) 124 { 125 for(col=0, dstptr2=dstptr; col<ntilesw; col++, tile++, dstptr2+=ps*tilew) 126 { 127 int width=dotile? min(tilew, w-col*tilew):scaledw; 128 int height=dotile? min(tileh, h-row*tileh):scaledh; 129 if(tjDecompress2(handle, jpegbuf[tile], jpegsize[tile], dstptr2, width, 130 pitch, height, pf, flags)==-1) 131 _throwtj("executing tjDecompress2()"); 132 } 133 } 134 } 135 136 if(tjDestroy(handle)==-1) _throwtj("executing tjDestroy()"); 137 handle=NULL; 138 139 if(quiet) 140 { 141 printf("%s\n", 142 sigfig((double)(w*h)/1000000.*(double)i/elapsed, 4, tempstr, 1024)); 143 } 144 else 145 { 146 printf("D--> Frame rate: %f fps\n", (double)i/elapsed); 147 printf(" Dest. throughput: %f Megapixels/sec\n", 148 (double)(w*h)/1000000.*(double)i/elapsed); 149 } 150 if(sf.num!=1 || sf.denom!=1) 151 snprintf(sizestr, 20, "%d_%d", sf.num, sf.denom); 152 else if(tilew!=w || tileh!=h) 153 snprintf(sizestr, 20, "%dx%d", tilew, tileh); 154 else snprintf(sizestr, 20, "full"); 155 if(decomponly) 156 snprintf(tempstr, 1024, "%s_%s.%s", filename, sizestr, ext); 157 else 158 snprintf(tempstr, 1024, "%s_%s%s_%s.%s", filename, subName[subsamp], 159 qualstr, sizestr, ext); 160 if(savebmp(tempstr, dstbuf, scaledw, scaledh, bmpPF[pf], pitch, 161 (flags&TJFLAG_BOTTOMUP)!=0)==-1) 162 _throwbmp("saving bitmap"); 163 ptr=strrchr(tempstr, '.'); 164 snprintf(ptr, 1024-(ptr-tempstr), "-err.%s", ext); 165 if(srcbuf && sf.num==1 && sf.denom==1) 166 { 167 if(!quiet) printf("Compression error written to %s.\n", tempstr); 168 if(subsamp==TJ_GRAYSCALE) 169 { 170 int index, index2; 171 for(row=0, index=0; row<h; row++, index+=pitch) 172 { 173 for(col=0, index2=index; col<w; col++, index2+=ps) 174 { 175 int rindex=index2+tjRedOffset[pf]; 176 int gindex=index2+tjGreenOffset[pf]; 177 int bindex=index2+tjBlueOffset[pf]; 178 int y=(int)((double)srcbuf[rindex]*0.299 179 + (double)srcbuf[gindex]*0.587 180 + (double)srcbuf[bindex]*0.114 + 0.5); 181 if(y>255) y=255; if(y<0) y=0; 182 dstbuf[rindex]=abs(dstbuf[rindex]-y); 183 dstbuf[gindex]=abs(dstbuf[gindex]-y); 184 dstbuf[bindex]=abs(dstbuf[bindex]-y); 185 } 186 } 187 } 188 else 189 { 190 for(row=0; row<h; row++) 191 for(col=0; col<w*ps; col++) 192 dstbuf[pitch*row+col] 193 =abs(dstbuf[pitch*row+col]-srcbuf[pitch*row+col]); 194 } 195 if(savebmp(tempstr, dstbuf, w, h, bmpPF[pf], pitch, 196 (flags&TJFLAG_BOTTOMUP)!=0)==-1) 197 _throwbmp("saving bitmap"); 198 } 199 200 bailout: 201 if(file) {fclose(file); file=NULL;} 202 if(handle) {tjDestroy(handle); handle=NULL;} 203 if(dstbuf && dstbufalloc) {free(dstbuf); dstbuf=NULL;} 204 return retval; 205} 206 207 208void dotest(unsigned char *srcbuf, int w, int h, int subsamp, int jpegqual, 209 char *filename) 210{ 211 char tempstr[1024], tempstr2[80]; 212 FILE *file=NULL; tjhandle handle=NULL; 213 unsigned char **jpegbuf=NULL, *tmpbuf=NULL, *srcptr, *srcptr2; 214 double start, elapsed; 215 int totaljpegsize=0, row, col, i, tilew=w, tileh=h, retval=0; 216 unsigned long *jpegsize=NULL; 217 int ps=tjPixelSize[pf], ntilesw=1, ntilesh=1, pitch=w*ps; 218 219 if((tmpbuf=(unsigned char *)malloc(pitch*h)) == NULL) 220 _throwunix("allocating temporary image buffer"); 221 222 if(!quiet) 223 printf(">>>>> %s (%s) <--> JPEG %s Q%d <<<<<\n", pixFormatStr[pf], 224 (flags&TJFLAG_BOTTOMUP)? "Bottom-up":"Top-down", subNameLong[subsamp], 225 jpegqual); 226 227 for(tilew=dotile? 8:w, tileh=dotile? 8:h; ; tilew*=2, tileh*=2) 228 { 229 if(tilew>w) tilew=w; if(tileh>h) tileh=h; 230 ntilesw=(w+tilew-1)/tilew; ntilesh=(h+tileh-1)/tileh; 231 232 if((jpegbuf=(unsigned char **)malloc(sizeof(unsigned char *) 233 *ntilesw*ntilesh))==NULL) 234 _throwunix("allocating JPEG tile array"); 235 memset(jpegbuf, 0, sizeof(unsigned char *)*ntilesw*ntilesh); 236 if((jpegsize=(unsigned long *)malloc(sizeof(unsigned long) 237 *ntilesw*ntilesh))==NULL) 238 _throwunix("allocating JPEG size array"); 239 memset(jpegsize, 0, sizeof(unsigned long)*ntilesw*ntilesh); 240 241 for(i=0; i<ntilesw*ntilesh; i++) 242 { 243 if((jpegbuf[i]=(unsigned char *)malloc(tjBufSize(tilew, tileh, 244 subsamp)))==NULL) 245 _throwunix("allocating JPEG tiles"); 246 } 247 248 /* Compression test */ 249 if(quiet==1) 250 printf("%s\t%s\t%s\t%d\t", pixFormatStr[pf], 251 (flags&TJFLAG_BOTTOMUP)? "BU":"TD", subNameLong[subsamp], jpegqual); 252 for(i=0; i<h; i++) 253 memcpy(&tmpbuf[pitch*i], &srcbuf[w*ps*i], w*ps); 254 if((handle=tjInitCompress())==NULL) 255 _throwtj("executing tjInitCompress()"); 256 257 /* Execute once to preload cache */ 258 if(tjCompress2(handle, srcbuf, tilew, pitch, tileh, pf, &jpegbuf[0], 259 &jpegsize[0], subsamp, jpegqual, flags)==-1) 260 _throwtj("executing tjCompress2()"); 261 262 /* Benchmark */ 263 for(i=0, start=gettime(); (elapsed=gettime()-start)<benchtime; i++) 264 { 265 int tile=0; 266 totaljpegsize=0; 267 for(row=0, srcptr=srcbuf; row<ntilesh; row++, srcptr+=pitch*tileh) 268 { 269 for(col=0, srcptr2=srcptr; col<ntilesw; col++, tile++, 270 srcptr2+=ps*tilew) 271 { 272 int width=min(tilew, w-col*tilew); 273 int height=min(tileh, h-row*tileh); 274 if(tjCompress2(handle, srcptr2, width, pitch, height, pf, 275 &jpegbuf[tile], &jpegsize[tile], subsamp, jpegqual, flags)==-1) 276 _throwtj("executing tjCompress()2"); 277 totaljpegsize+=jpegsize[tile]; 278 } 279 } 280 } 281 282 if(tjDestroy(handle)==-1) _throwtj("executing tjDestroy()"); 283 handle=NULL; 284 285 if(quiet==1) printf("%-4d %-4d\t", tilew, tileh); 286 if(quiet) 287 { 288 printf("%s%c%s%c", 289 sigfig((double)(w*h)/1000000.*(double)i/elapsed, 4, tempstr, 1024), 290 quiet==2? '\n':'\t', 291 sigfig((double)(w*h*ps)/(double)totaljpegsize, 4, tempstr2, 80), 292 quiet==2? '\n':'\t'); 293 } 294 else 295 { 296 printf("\n%s size: %d x %d\n", dotile? "Tile":"Image", tilew, 297 tileh); 298 printf("C--> Frame rate: %f fps\n", (double)i/elapsed); 299 printf(" Output image size: %d bytes\n", totaljpegsize); 300 printf(" Compression ratio: %f:1\n", 301 (double)(w*h*ps)/(double)totaljpegsize); 302 printf(" Source throughput: %f Megapixels/sec\n", 303 (double)(w*h)/1000000.*(double)i/elapsed); 304 printf(" Output bit stream: %f Megabits/sec\n", 305 (double)totaljpegsize*8./1000000.*(double)i/elapsed); 306 } 307 if(tilew==w && tileh==h) 308 { 309 snprintf(tempstr, 1024, "%s_%s_Q%d.jpg", filename, subName[subsamp], 310 jpegqual); 311 if((file=fopen(tempstr, "wb"))==NULL) 312 _throwunix("opening reference image"); 313 if(fwrite(jpegbuf[0], jpegsize[0], 1, file)!=1) 314 _throwunix("writing reference image"); 315 fclose(file); file=NULL; 316 if(!quiet) printf("Reference image written to %s\n", tempstr); 317 } 318 319 /* Decompression test */ 320 if(decomptest(srcbuf, jpegbuf, jpegsize, tmpbuf, w, h, subsamp, jpegqual, 321 filename, tilew, tileh)==-1) 322 goto bailout; 323 324 for(i=0; i<ntilesw*ntilesh; i++) 325 { 326 if(jpegbuf[i]) free(jpegbuf[i]); jpegbuf[i]=NULL; 327 } 328 free(jpegbuf); jpegbuf=NULL; 329 free(jpegsize); jpegsize=NULL; 330 331 if(tilew==w && tileh==h) break; 332 } 333 334 bailout: 335 if(file) {fclose(file); file=NULL;} 336 if(jpegbuf) 337 { 338 for(i=0; i<ntilesw*ntilesh; i++) 339 { 340 if(jpegbuf[i]) free(jpegbuf[i]); jpegbuf[i]=NULL; 341 } 342 free(jpegbuf); jpegbuf=NULL; 343 } 344 if(jpegsize) {free(jpegsize); jpegsize=NULL;} 345 if(tmpbuf) {free(tmpbuf); tmpbuf=NULL;} 346 if(handle) {tjDestroy(handle); handle=NULL;} 347 return; 348} 349 350 351void dodecomptest(char *filename) 352{ 353 FILE *file=NULL; tjhandle handle=NULL; 354 unsigned char **jpegbuf=NULL, *srcbuf=NULL; 355 unsigned long *jpegsize=NULL, srcsize; 356 int w=0, h=0, subsamp=-1, _w, _h, _tilew, _tileh, _subsamp; 357 char *temp=NULL; 358 int i, tilew, tileh, ntilesw=1, ntilesh=1, retval=0; 359 360 if((file=fopen(filename, "rb"))==NULL) 361 _throwunix("opening file"); 362 if(fseek(file, 0, SEEK_END)<0 || (srcsize=ftell(file))<0) 363 _throwunix("determining file size"); 364 if((srcbuf=(unsigned char *)malloc(srcsize))==NULL) 365 _throwunix("allocating memory"); 366 if(fseek(file, 0, SEEK_SET)<0) 367 _throwunix("setting file position"); 368 if(fread(srcbuf, srcsize, 1, file)<1) 369 _throwunix("reading JPEG data"); 370 fclose(file); file=NULL; 371 372 temp=strrchr(filename, '.'); 373 if(temp!=NULL) *temp='\0'; 374 375 if((handle=tjInitDecompress())==NULL) 376 _throwtj("executing tjInitDecompress()"); 377 if(tjDecompressHeader2(handle, srcbuf, srcsize, &w, &h, &subsamp)==-1) 378 _throwtj("executing tjDecompressHeader2()"); 379 380 if(quiet==1) 381 { 382 printf("All performance values in Mpixels/sec\n\n"); 383 printf("Bitmap\tBitmap\tJPEG\t%s %s \tXform\tComp\tDecomp\n", 384 dotile? "Tile ":"Image", dotile? "Tile ":"Image"); 385 printf("Format\tOrder\tSubsamp\tWidth Height\tPerf \tRatio\tPerf\n\n"); 386 } 387 else if(!quiet) 388 { 389 printf(">>>>> JPEG %s --> %s (%s) <<<<<\n", subNameLong[subsamp], 390 pixFormatStr[pf], (flags&TJFLAG_BOTTOMUP)? "Bottom-up":"Top-down"); 391 } 392 393 for(tilew=dotile? 16:w, tileh=dotile? 16:h; ; tilew*=2, tileh*=2) 394 { 395 if(tilew>w) tilew=w; if(tileh>h) tileh=h; 396 ntilesw=(w+tilew-1)/tilew; ntilesh=(h+tileh-1)/tileh; 397 398 if((jpegbuf=(unsigned char **)malloc(sizeof(unsigned char *) 399 *ntilesw*ntilesh))==NULL) 400 _throwunix("allocating JPEG tile array"); 401 memset(jpegbuf, 0, sizeof(unsigned char *)*ntilesw*ntilesh); 402 if((jpegsize=(unsigned long *)malloc(sizeof(unsigned long) 403 *ntilesw*ntilesh))==NULL) 404 _throwunix("allocating JPEG size array"); 405 memset(jpegsize, 0, sizeof(unsigned long)*ntilesw*ntilesh); 406 407 for(i=0; i<ntilesw*ntilesh; i++) 408 { 409 if((jpegbuf[i]=(unsigned char *)malloc(tjBufSize(tilew, tileh, 410 subsamp)))==NULL) 411 _throwunix("allocating JPEG tiles"); 412 } 413 414 _w=w; _h=h; _tilew=tilew; _tileh=tileh; 415 if(!quiet) 416 { 417 printf("\n%s size: %d x %d", dotile? "Tile":"Image", _tilew, 418 _tileh); 419 if(sf.num!=1 || sf.denom!=1) 420 printf(" --> %d x %d", TJSCALED(_w, sf), TJSCALED(_h, sf)); 421 printf("\n"); 422 } 423 else if(quiet==1) 424 { 425 printf("%s\t%s\t%s\t", pixFormatStr[pf], 426 (flags&TJFLAG_BOTTOMUP)? "BU":"TD", subNameLong[subsamp]); 427 printf("%-4d %-4d\t", tilew, tileh); 428 } 429 430 _subsamp=subsamp; 431 if(quiet==1) printf("N/A\tN/A\t"); 432 jpegsize[0]=srcsize; 433 memcpy(jpegbuf[0], srcbuf, srcsize); 434 435 if(w==tilew) _tilew=_w; 436 if(h==tileh) _tileh=_h; 437 if(decomptest(NULL, jpegbuf, jpegsize, NULL, _w, _h, _subsamp, 0, 438 filename, _tilew, _tileh)==-1) 439 goto bailout; 440 else if(quiet==1) printf("N/A\n"); 441 442 for(i=0; i<ntilesw*ntilesh; i++) 443 { 444 free(jpegbuf[i]); jpegbuf[i]=NULL; 445 } 446 free(jpegbuf); jpegbuf=NULL; 447 if(jpegsize) {free(jpegsize); jpegsize=NULL;} 448 449 if(tilew==w && tileh==h) break; 450 } 451 452 bailout: 453 if(file) {fclose(file); file=NULL;} 454 if(jpegbuf) 455 { 456 for(i=0; i<ntilesw*ntilesh; i++) 457 { 458 if(jpegbuf[i]) free(jpegbuf[i]); jpegbuf[i]=NULL; 459 } 460 free(jpegbuf); jpegbuf=NULL; 461 } 462 if(jpegsize) {free(jpegsize); jpegsize=NULL;} 463 if(srcbuf) {free(srcbuf); srcbuf=NULL;} 464 if(handle) {tjDestroy(handle); handle=NULL;} 465 return; 466} 467 468 469void usage(char *progname) 470{ 471 int i; 472 printf("USAGE: %s\n", progname); 473 printf(" <Inputfile (BMP|PPM)> <%% Quality> [options]\n\n"); 474 printf(" %s\n", progname); 475 printf(" <Inputfile (JPG)> [options]\n\n"); 476 printf("Options:\n\n"); 477 printf("-bmp = Generate output images in Windows Bitmap format (default=PPM)\n"); 478 printf("-bottomup = Test bottom-up compression/decompression\n"); 479 printf("-tile = Test performance of the codec when the image is encoded as separate\n"); 480 printf(" tiles of varying sizes.\n"); 481 printf("-forcemmx, -forcesse, -forcesse2, -forcesse3 =\n"); 482 printf(" Force MMX, SSE, SSE2, or SSE3 code paths in the underlying codec\n"); 483 printf("-rgb, -bgr, -rgbx, -bgrx, -xbgr, -xrgb =\n"); 484 printf(" Test the specified color conversion path in the codec (default: BGR)\n"); 485 printf("-fastupsample = Use fast, inaccurate upsampling code to perform 4:2:2 and 4:2:0\n"); 486 printf(" YUV decoding\n"); 487 printf("-quiet = Output results in tabular rather than verbose format\n"); 488 printf("-scale M/N = scale down the width/height of the decompressed JPEG image by a\n"); 489 printf(" factor of M/N (M/N = "); 490 for(i=0; i<nsf; i++) 491 { 492 printf("%d/%d", scalingfactors[i].num, scalingfactors[i].denom); 493 if(nsf==2 && i!=nsf-1) printf(" or "); 494 else if(nsf>2) 495 { 496 if(i!=nsf-1) printf(", "); 497 if(i==nsf-2) printf("or "); 498 } 499 } 500 printf(")\n"); 501 printf("-benchtime <t> = Run each benchmark for at least <t> seconds (default = 5.0)\n\n"); 502 printf("NOTE: If the quality is specified as a range (e.g. 90-100), a separate\n"); 503 printf("test will be performed for all quality values in the range.\n\n"); 504 exit(1); 505} 506 507 508int main(int argc, char *argv[]) 509{ 510 unsigned char *srcbuf=NULL; int w, h, i, j; 511 int minqual=-1, maxqual=-1; char *temp; 512 int minarg=2; int retval=0; 513 514 if((scalingfactors=tjGetScalingFactors(&nsf))==NULL || nsf==0) 515 _throwtj("executing tjGetScalingFactors()"); 516 517 if(argc<minarg) usage(argv[0]); 518 519 temp=strrchr(argv[1], '.'); 520 if(temp!=NULL) 521 { 522 if(!strcasecmp(temp, ".bmp")) ext="bmp"; 523 if(!strcasecmp(temp, ".jpg") || !strcasecmp(temp, ".jpeg")) decomponly=1; 524 } 525 526 printf("\n"); 527 528 if(!decomponly) 529 { 530 minarg=3; 531 if(argc<minarg) usage(argv[0]); 532 if((minqual=atoi(argv[2]))<1 || minqual>100) 533 { 534 puts("ERROR: Quality must be between 1 and 100."); 535 exit(1); 536 } 537 if((temp=strchr(argv[2], '-'))!=NULL && strlen(temp)>1 538 && sscanf(&temp[1], "%d", &maxqual)==1 && maxqual>minqual && maxqual>=1 539 && maxqual<=100) {} 540 else maxqual=minqual; 541 } 542 543 if(argc>minarg) 544 { 545 for(i=minarg; i<argc; i++) 546 { 547 if(!strcasecmp(argv[i], "-tile")) 548 { 549 dotile=1; 550 } 551 if(!strcasecmp(argv[i], "-forcesse3")) 552 { 553 printf("Forcing SSE3 code\n\n"); 554 flags|=TJFLAG_FORCESSE3; 555 } 556 if(!strcasecmp(argv[i], "-forcesse2")) 557 { 558 printf("Forcing SSE2 code\n\n"); 559 flags|=TJFLAG_FORCESSE2; 560 } 561 if(!strcasecmp(argv[i], "-forcesse")) 562 { 563 printf("Forcing SSE code\n\n"); 564 flags|=TJFLAG_FORCESSE; 565 } 566 if(!strcasecmp(argv[i], "-forcemmx")) 567 { 568 printf("Forcing MMX code\n\n"); 569 flags|=TJFLAG_FORCEMMX; 570 } 571 if(!strcasecmp(argv[i], "-fastupsample")) 572 { 573 printf("Using fast upsampling code\n\n"); 574 flags|=TJFLAG_FASTUPSAMPLE; 575 } 576 if(!strcasecmp(argv[i], "-rgb")) pf=TJPF_RGB; 577 if(!strcasecmp(argv[i], "-rgbx")) pf=TJPF_RGBX; 578 if(!strcasecmp(argv[i], "-bgr")) pf=TJPF_BGR; 579 if(!strcasecmp(argv[i], "-bgrx")) pf=TJPF_BGRX; 580 if(!strcasecmp(argv[i], "-xbgr")) pf=TJPF_XBGR; 581 if(!strcasecmp(argv[i], "-xrgb")) pf=TJPF_XRGB; 582 if(!strcasecmp(argv[i], "-bottomup")) flags|=TJFLAG_BOTTOMUP; 583 if(!strcasecmp(argv[i], "-quiet")) quiet=1; 584 if(!strcasecmp(argv[i], "-qq")) quiet=2; 585 if(!strcasecmp(argv[i], "-scale") && i<argc-1) 586 { 587 int temp1=0, temp2=0, match=0; 588 if(sscanf(argv[++i], "%d/%d", &temp1, &temp2)==2) 589 { 590 for(j=0; j<nsf; j++) 591 { 592 if(temp1==scalingfactors[j].num && temp2==scalingfactors[j].denom) 593 { 594 sf=scalingfactors[j]; 595 match=1; break; 596 } 597 } 598 if(!match) usage(argv[0]); 599 } 600 else usage(argv[0]); 601 } 602 if(!strcasecmp(argv[i], "-benchtime") && i<argc-1) 603 { 604 double temp=atof(argv[++i]); 605 if(temp>0.0) benchtime=temp; 606 else usage(argv[0]); 607 } 608 if(!strcmp(argv[i], "-?")) usage(argv[0]); 609 if(!strcasecmp(argv[i], "-bmp")) ext="bmp"; 610 } 611 } 612 613 if((sf.num!=1 || sf.denom!=1) && dotile) 614 { 615 printf("Disabling tiled compression/decompression tests, because those tests do not\n"); 616 printf("work when scaled decompression is enabled.\n"); 617 dotile=0; 618 } 619 620 if(!decomponly) 621 { 622 if(loadbmp(argv[1], &srcbuf, &w, &h, bmpPF[pf], 1, 623 (flags&TJFLAG_BOTTOMUP)!=0)==-1) 624 _throwbmp("loading bitmap"); 625 temp=strrchr(argv[1], '.'); 626 if(temp!=NULL) *temp='\0'; 627 } 628 629 if(quiet==1 && !decomponly) 630 { 631 printf("All performance values in Mpixels/sec\n\n"); 632 printf("Bitmap\tBitmap\tJPEG\tJPEG\t%s %s \tComp\tComp\tDecomp\n", 633 dotile? "Tile ":"Image", dotile? "Tile ":"Image"); 634 printf("Format\tOrder\tSubsamp\tQual\tWidth Height\tPerf \tRatio\tPerf\n\n"); 635 } 636 637 if(decomponly) 638 { 639 dodecomptest(argv[1]); 640 printf("\n"); 641 goto bailout; 642 } 643 for(i=maxqual; i>=minqual; i--) 644 dotest(srcbuf, w, h, TJ_GRAYSCALE, i, argv[1]); 645 printf("\n"); 646 for(i=maxqual; i>=minqual; i--) 647 dotest(srcbuf, w, h, TJ_420, i, argv[1]); 648 printf("\n"); 649 for(i=maxqual; i>=minqual; i--) 650 dotest(srcbuf, w, h, TJ_422, i, argv[1]); 651 printf("\n"); 652 for(i=maxqual; i>=minqual; i--) 653 dotest(srcbuf, w, h, TJ_444, i, argv[1]); 654 printf("\n"); 655 656 bailout: 657 if(srcbuf) free(srcbuf); 658 return retval; 659} 660