1 /* 2 * Copyright (C)2009-2014 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 /* 30 * This program tests the various code paths in the TurboJPEG C Wrapper 31 */ 32 33 #include <stdio.h> 34 #include <stdlib.h> 35 #include <string.h> 36 #include <errno.h> 37 #include "./tjutil.h" 38 #include "./turbojpeg.h" 39 #ifdef _WIN32 40 #include <time.h> 41 #define random() rand() 42 #endif 43 44 45 void usage(char *progName) 46 { 47 printf("\nUSAGE: %s [options]\n", progName); 48 printf("Options:\n"); 49 printf("-yuv = test YUV encoding/decoding support\n"); 50 printf("-noyuvpad = do not pad each line of each Y, U, and V plane to the nearest\n"); 51 printf(" 4-byte boundary\n"); 52 printf("-alloc = test automatic buffer allocation\n"); 53 exit(1); 54 } 55 56 57 #define _throwtj() {printf("TurboJPEG ERROR:\n%s\n", tjGetErrorStr()); \ 58 bailout();} 59 #define _tj(f) {if((f)==-1) _throwtj();} 60 #define _throw(m) {printf("ERROR: %s\n", m); bailout();} 61 62 const char *subNameLong[TJ_NUMSAMP]= 63 { 64 "4:4:4", "4:2:2", "4:2:0", "GRAY", "4:4:0", "4:1:1" 65 }; 66 const char *subName[TJ_NUMSAMP]={"444", "422", "420", "GRAY", "440", "411"}; 67 68 const char *pixFormatStr[TJ_NUMPF]= 69 { 70 "RGB", "BGR", "RGBX", "BGRX", "XBGR", "XRGB", "Grayscale", 71 "RGBA", "BGRA", "ABGR", "ARGB", "CMYK" 72 }; 73 74 const int alphaOffset[TJ_NUMPF] = {-1, -1, -1, -1, -1, -1, -1, 3, 3, 0, 0, -1}; 75 76 const int _3byteFormats[]={TJPF_RGB, TJPF_BGR}; 77 const int _4byteFormats[]={TJPF_RGBX, TJPF_BGRX, TJPF_XBGR, TJPF_XRGB, 78 TJPF_CMYK}; 79 const int _onlyGray[]={TJPF_GRAY}; 80 const int _onlyRGB[]={TJPF_RGB}; 81 82 int doyuv=0, alloc=0, pad=4; 83 84 int exitStatus=0; 85 #define bailout() {exitStatus=-1; goto bailout;} 86 87 88 void initBuf(unsigned char *buf, int w, int h, int pf, int flags) 89 { 90 int roffset=tjRedOffset[pf]; 91 int goffset=tjGreenOffset[pf]; 92 int boffset=tjBlueOffset[pf]; 93 int ps=tjPixelSize[pf]; 94 int index, row, col, halfway=16; 95 96 if(pf==TJPF_GRAY) 97 { 98 memset(buf, 0, w*h*ps); 99 for(row=0; row<h; row++) 100 { 101 for(col=0; col<w; col++) 102 { 103 if(flags&TJFLAG_BOTTOMUP) index=(h-row-1)*w+col; 104 else index=row*w+col; 105 if(((row/8)+(col/8))%2==0) buf[index]=(row<halfway)? 255:0; 106 else buf[index]=(row<halfway)? 76:226; 107 } 108 } 109 } 110 else if(pf==TJPF_CMYK) 111 { 112 memset(buf, 255, w*h*ps); 113 for(row=0; row<h; row++) 114 { 115 for(col=0; col<w; col++) 116 { 117 if(flags&TJFLAG_BOTTOMUP) index=(h-row-1)*w+col; 118 else index=row*w+col; 119 if(((row/8)+(col/8))%2==0) 120 { 121 if(row>=halfway) buf[index*ps+3]=0; 122 } 123 else 124 { 125 buf[index*ps+2]=0; 126 if(row<halfway) buf[index*ps+1]=0; 127 } 128 } 129 } 130 } 131 else 132 { 133 memset(buf, 0, w*h*ps); 134 for(row=0; row<h; row++) 135 { 136 for(col=0; col<w; col++) 137 { 138 if(flags&TJFLAG_BOTTOMUP) index=(h-row-1)*w+col; 139 else index=row*w+col; 140 if(((row/8)+(col/8))%2==0) 141 { 142 if(row<halfway) 143 { 144 buf[index*ps+roffset]=255; 145 buf[index*ps+goffset]=255; 146 buf[index*ps+boffset]=255; 147 } 148 } 149 else 150 { 151 buf[index*ps+roffset]=255; 152 if(row>=halfway) buf[index*ps+goffset]=255; 153 } 154 } 155 } 156 } 157 } 158 159 160 #define checkval(v, cv) { \ 161 if(v<cv-1 || v>cv+1) { \ 162 printf("\nComp. %s at %d,%d should be %d, not %d\n", \ 163 #v, row, col, cv, v); \ 164 retval=0; exitStatus=-1; goto bailout; \ 165 }} 166 167 #define checkval0(v) { \ 168 if(v>1) { \ 169 printf("\nComp. %s at %d,%d should be 0, not %d\n", #v, row, col, v); \ 170 retval=0; exitStatus=-1; goto bailout; \ 171 }} 172 173 #define checkval255(v) { \ 174 if(v<254) { \ 175 printf("\nComp. %s at %d,%d should be 255, not %d\n", #v, row, col, v); \ 176 retval=0; exitStatus=-1; goto bailout; \ 177 }} 178 179 180 int checkBuf(unsigned char *buf, int w, int h, int pf, int subsamp, 181 tjscalingfactor sf, int flags) 182 { 183 int roffset=tjRedOffset[pf]; 184 int goffset=tjGreenOffset[pf]; 185 int boffset=tjBlueOffset[pf]; 186 int aoffset=alphaOffset[pf]; 187 int ps=tjPixelSize[pf]; 188 int index, row, col, retval=1; 189 int halfway=16*sf.num/sf.denom; 190 int blocksize=8*sf.num/sf.denom; 191 192 if(pf==TJPF_CMYK) 193 { 194 for(row=0; row<h; row++) 195 { 196 for(col=0; col<w; col++) 197 { 198 unsigned char c, m, y, k; 199 if(flags&TJFLAG_BOTTOMUP) index=(h-row-1)*w+col; 200 else index=row*w+col; 201 c=buf[index*ps]; 202 m=buf[index*ps+1]; 203 y=buf[index*ps+2]; 204 k=buf[index*ps+3]; 205 if(((row/blocksize)+(col/blocksize))%2==0) 206 { 207 checkval255(c); checkval255(m); checkval255(y); 208 if(row<halfway) checkval255(k) 209 else checkval0(k) 210 } 211 else 212 { 213 checkval255(c); checkval0(y); checkval255(k); 214 if(row<halfway) checkval0(m) 215 else checkval255(m) 216 } 217 } 218 } 219 return 1; 220 } 221 222 for(row=0; row<h; row++) 223 { 224 for(col=0; col<w; col++) 225 { 226 unsigned char r, g, b, a; 227 if(flags&TJFLAG_BOTTOMUP) index=(h-row-1)*w+col; 228 else index=row*w+col; 229 r=buf[index*ps+roffset]; 230 g=buf[index*ps+goffset]; 231 b=buf[index*ps+boffset]; 232 a=aoffset>=0? buf[index*ps+aoffset]:0xFF; 233 if(((row/blocksize)+(col/blocksize))%2==0) 234 { 235 if(row<halfway) 236 { 237 checkval255(r); checkval255(g); checkval255(b); 238 } 239 else 240 { 241 checkval0(r); checkval0(g); checkval0(b); 242 } 243 } 244 else 245 { 246 if(subsamp==TJSAMP_GRAY) 247 { 248 if(row<halfway) 249 { 250 checkval(r, 76); checkval(g, 76); checkval(b, 76); 251 } 252 else 253 { 254 checkval(r, 226); checkval(g, 226); checkval(b, 226); 255 } 256 } 257 else 258 { 259 if(row<halfway) 260 { 261 checkval255(r); checkval0(g); checkval0(b); 262 } 263 else 264 { 265 checkval255(r); checkval255(g); checkval0(b); 266 } 267 } 268 } 269 checkval255(a); 270 } 271 } 272 273 bailout: 274 if(retval==0) 275 { 276 for(row=0; row<h; row++) 277 { 278 for(col=0; col<w; col++) 279 { 280 if(pf==TJPF_CMYK) 281 printf("%.3d/%.3d/%.3d/%.3d ", buf[(row*w+col)*ps], 282 buf[(row*w+col)*ps+1], buf[(row*w+col)*ps+2], 283 buf[(row*w+col)*ps+3]); 284 else 285 printf("%.3d/%.3d/%.3d ", buf[(row*w+col)*ps+roffset], 286 buf[(row*w+col)*ps+goffset], buf[(row*w+col)*ps+boffset]); 287 } 288 printf("\n"); 289 } 290 } 291 return retval; 292 } 293 294 295 #define PAD(v, p) ((v+(p)-1)&(~((p)-1))) 296 297 int checkBufYUV(unsigned char *buf, int w, int h, int subsamp, 298 tjscalingfactor sf) 299 { 300 int row, col; 301 int hsf=tjMCUWidth[subsamp]/8, vsf=tjMCUHeight[subsamp]/8; 302 int pw=PAD(w, hsf), ph=PAD(h, vsf); 303 int cw=pw/hsf, ch=ph/vsf; 304 int ypitch=PAD(pw, pad), uvpitch=PAD(cw, pad); 305 int retval=1; 306 int halfway=16*sf.num/sf.denom; 307 int blocksize=8*sf.num/sf.denom; 308 309 for(row=0; row<ph; row++) 310 { 311 for(col=0; col<pw; col++) 312 { 313 unsigned char y=buf[ypitch*row+col]; 314 if(((row/blocksize)+(col/blocksize))%2==0) 315 { 316 if(row<halfway) checkval255(y) else checkval0(y); 317 } 318 else 319 { 320 if(row<halfway) checkval(y, 76) else checkval(y, 226); 321 } 322 } 323 } 324 if(subsamp!=TJSAMP_GRAY) 325 { 326 int halfway=16/vsf*sf.num/sf.denom; 327 for(row=0; row<ch; row++) 328 { 329 for(col=0; col<cw; col++) 330 { 331 unsigned char u=buf[ypitch*ph + (uvpitch*row+col)], 332 v=buf[ypitch*ph + uvpitch*ch + (uvpitch*row+col)]; 333 if(((row*vsf/blocksize)+(col*hsf/blocksize))%2==0) 334 { 335 checkval(u, 128); checkval(v, 128); 336 } 337 else 338 { 339 if(row<halfway) 340 { 341 checkval(u, 85); checkval255(v); 342 } 343 else 344 { 345 checkval0(u); checkval(v, 149); 346 } 347 } 348 } 349 } 350 } 351 352 bailout: 353 if(retval==0) 354 { 355 for(row=0; row<ph; row++) 356 { 357 for(col=0; col<pw; col++) 358 printf("%.3d ", buf[ypitch*row+col]); 359 printf("\n"); 360 } 361 printf("\n"); 362 for(row=0; row<ch; row++) 363 { 364 for(col=0; col<cw; col++) 365 printf("%.3d ", buf[ypitch*ph + (uvpitch*row+col)]); 366 printf("\n"); 367 } 368 printf("\n"); 369 for(row=0; row<ch; row++) 370 { 371 for(col=0; col<cw; col++) 372 printf("%.3d ", buf[ypitch*ph + uvpitch*ch + (uvpitch*row+col)]); 373 printf("\n"); 374 } 375 } 376 377 return retval; 378 } 379 380 381 void writeJPEG(unsigned char *jpegBuf, unsigned long jpegSize, char *filename) 382 { 383 FILE *file=fopen(filename, "wb"); 384 if(!file || fwrite(jpegBuf, jpegSize, 1, file)!=1) 385 { 386 printf("ERROR: Could not write to %s.\n%s\n", filename, strerror(errno)); 387 bailout(); 388 } 389 390 bailout: 391 if(file) fclose(file); 392 } 393 394 395 void compTest(tjhandle handle, unsigned char **dstBuf, 396 unsigned long *dstSize, int w, int h, int pf, char *basename, 397 int subsamp, int jpegQual, int flags) 398 { 399 char tempStr[1024]; unsigned char *srcBuf=NULL, *yuvBuf=NULL; 400 const char *pfStr=pixFormatStr[pf]; 401 const char *buStrLong=(flags&TJFLAG_BOTTOMUP)? "Bottom-Up":"Top-Down "; 402 const char *buStr=(flags&TJFLAG_BOTTOMUP)? "BU":"TD"; 403 404 if((srcBuf=(unsigned char *)malloc(w*h*tjPixelSize[pf]))==NULL) 405 _throw("Memory allocation failure"); 406 initBuf(srcBuf, w, h, pf, flags); 407 408 if(*dstBuf && *dstSize>0) memset(*dstBuf, 0, *dstSize); 409 410 411 if(!alloc) flags|=TJFLAG_NOREALLOC; 412 if(doyuv) 413 { 414 unsigned long yuvSize=tjBufSizeYUV2(w, pad, h, subsamp); 415 tjscalingfactor sf={1, 1}; 416 tjhandle handle2=tjInitCompress(); 417 if(!handle2) _throwtj(); 418 419 if((yuvBuf=(unsigned char *)malloc(yuvSize))==NULL) 420 _throw("Memory allocation failure"); 421 memset(yuvBuf, 0, yuvSize); 422 423 printf("%s %s -> YUV %s ... ", pfStr, buStrLong, subNameLong[subsamp]); 424 _tj(tjEncodeYUV3(handle2, srcBuf, w, 0, h, pf, yuvBuf, pad, subsamp, 425 flags)); 426 tjDestroy(handle2); 427 if(checkBufYUV(yuvBuf, w, h, subsamp, sf)) printf("Passed.\n"); 428 else printf("FAILED!\n"); 429 430 printf("YUV %s %s -> JPEG Q%d ... ", subNameLong[subsamp], buStrLong, 431 jpegQual); 432 _tj(tjCompressFromYUV(handle, yuvBuf, w, pad, h, subsamp, dstBuf, 433 dstSize, jpegQual, flags)); 434 } 435 else 436 { 437 printf("%s %s -> %s Q%d ... ", pfStr, buStrLong, subNameLong[subsamp], 438 jpegQual); 439 _tj(tjCompress2(handle, srcBuf, w, 0, h, pf, dstBuf, dstSize, subsamp, 440 jpegQual, flags)); 441 } 442 443 snprintf(tempStr, 1024, "%s_enc_%s_%s_%s_Q%d.jpg", basename, pfStr, buStr, 444 subName[subsamp], jpegQual); 445 writeJPEG(*dstBuf, *dstSize, tempStr); 446 printf("Done.\n Result in %s\n", tempStr); 447 448 bailout: 449 if(yuvBuf) free(yuvBuf); 450 if(srcBuf) free(srcBuf); 451 } 452 453 454 void _decompTest(tjhandle handle, unsigned char *jpegBuf, 455 unsigned long jpegSize, int w, int h, int pf, char *basename, int subsamp, 456 int flags, tjscalingfactor sf) 457 { 458 unsigned char *dstBuf=NULL, *yuvBuf=NULL; 459 int _hdrw=0, _hdrh=0, _hdrsubsamp=-1; 460 int scaledWidth=TJSCALED(w, sf); 461 int scaledHeight=TJSCALED(h, sf); 462 unsigned long dstSize=0; 463 464 _tj(tjDecompressHeader2(handle, jpegBuf, jpegSize, &_hdrw, &_hdrh, 465 &_hdrsubsamp)); 466 if(_hdrw!=w || _hdrh!=h || _hdrsubsamp!=subsamp) 467 _throw("Incorrect JPEG header"); 468 469 dstSize=scaledWidth*scaledHeight*tjPixelSize[pf]; 470 if((dstBuf=(unsigned char *)malloc(dstSize))==NULL) 471 _throw("Memory allocation failure"); 472 memset(dstBuf, 0, dstSize); 473 474 if(doyuv) 475 { 476 unsigned long yuvSize=tjBufSizeYUV2(scaledWidth, pad, scaledHeight, 477 subsamp); 478 tjhandle handle2=tjInitDecompress(); 479 if(!handle2) _throwtj(); 480 481 if((yuvBuf=(unsigned char *)malloc(yuvSize))==NULL) 482 _throw("Memory allocation failure"); 483 memset(yuvBuf, 0, yuvSize); 484 485 printf("JPEG -> YUV %s ", subNameLong[subsamp]); 486 if(sf.num!=1 || sf.denom!=1) 487 printf("%d/%d ... ", sf.num, sf.denom); 488 else printf("... "); 489 _tj(tjDecompressToYUV2(handle, jpegBuf, jpegSize, yuvBuf, scaledWidth, 490 pad, scaledHeight, flags)); 491 if(checkBufYUV(yuvBuf, scaledWidth, scaledHeight, subsamp, sf)) 492 printf("Passed.\n"); 493 else printf("FAILED!\n"); 494 495 printf("YUV %s -> %s %s ... ", subNameLong[subsamp], pixFormatStr[pf], 496 (flags&TJFLAG_BOTTOMUP)? "Bottom-Up":"Top-Down "); 497 _tj(tjDecodeYUV(handle2, yuvBuf, pad, subsamp, dstBuf, scaledWidth, 0, 498 scaledHeight, pf, flags)); 499 tjDestroy(handle2); 500 } 501 else 502 { 503 printf("JPEG -> %s %s ", pixFormatStr[pf], 504 (flags&TJFLAG_BOTTOMUP)? "Bottom-Up":"Top-Down "); 505 if(sf.num!=1 || sf.denom!=1) 506 printf("%d/%d ... ", sf.num, sf.denom); 507 else printf("... "); 508 _tj(tjDecompress2(handle, jpegBuf, jpegSize, dstBuf, scaledWidth, 0, 509 scaledHeight, pf, flags)); 510 } 511 512 if(checkBuf(dstBuf, scaledWidth, scaledHeight, pf, subsamp, sf, flags)) 513 printf("Passed."); 514 else printf("FAILED!"); 515 printf("\n"); 516 517 bailout: 518 if(yuvBuf) free(yuvBuf); 519 if(dstBuf) free(dstBuf); 520 } 521 522 523 void decompTest(tjhandle handle, unsigned char *jpegBuf, 524 unsigned long jpegSize, int w, int h, int pf, char *basename, int subsamp, 525 int flags) 526 { 527 int i, n=0; 528 tjscalingfactor *sf=tjGetScalingFactors(&n); 529 if(!sf || !n) _throwtj(); 530 531 for(i=0; i<n; i++) 532 { 533 if(subsamp==TJSAMP_444 || subsamp==TJSAMP_GRAY || 534 (subsamp==TJSAMP_411 && sf[i].num==1 && 535 (sf[i].denom==2 || sf[i].denom==1)) || 536 (subsamp!=TJSAMP_411 && sf[i].num==1 && 537 (sf[i].denom==4 || sf[i].denom==2 || sf[i].denom==1))) 538 _decompTest(handle, jpegBuf, jpegSize, w, h, pf, basename, subsamp, 539 flags, sf[i]); 540 } 541 542 bailout: 543 return; 544 } 545 546 547 void doTest(int w, int h, const int *formats, int nformats, int subsamp, 548 char *basename) 549 { 550 tjhandle chandle=NULL, dhandle=NULL; 551 unsigned char *dstBuf=NULL; 552 unsigned long size=0; int pfi, pf, i; 553 554 if(!alloc) 555 size=tjBufSize(w, h, subsamp); 556 if(size!=0) 557 if((dstBuf=(unsigned char *)tjAlloc(size))==NULL) 558 _throw("Memory allocation failure."); 559 560 if((chandle=tjInitCompress())==NULL || (dhandle=tjInitDecompress())==NULL) 561 _throwtj(); 562 563 for(pfi=0; pfi<nformats; pfi++) 564 { 565 for(i=0; i<2; i++) 566 { 567 int flags=0; 568 if(subsamp==TJSAMP_422 || subsamp==TJSAMP_420 || subsamp==TJSAMP_440 || 569 subsamp==TJSAMP_411) 570 flags|=TJFLAG_FASTUPSAMPLE; 571 if(i==1) flags|=TJFLAG_BOTTOMUP; 572 pf=formats[pfi]; 573 compTest(chandle, &dstBuf, &size, w, h, pf, basename, subsamp, 100, 574 flags); 575 decompTest(dhandle, dstBuf, size, w, h, pf, basename, subsamp, 576 flags); 577 if(pf>=TJPF_RGBX && pf<=TJPF_XRGB) 578 { 579 printf("\n"); 580 decompTest(dhandle, dstBuf, size, w, h, pf+(TJPF_RGBA-TJPF_RGBX), 581 basename, subsamp, flags); 582 } 583 printf("\n"); 584 } 585 } 586 printf("--------------------\n\n"); 587 588 bailout: 589 if(chandle) tjDestroy(chandle); 590 if(dhandle) tjDestroy(dhandle); 591 592 if(dstBuf) tjFree(dstBuf); 593 } 594 595 596 void bufSizeTest(void) 597 { 598 int w, h, i, subsamp; 599 unsigned char *srcBuf=NULL, *dstBuf=NULL; 600 tjhandle handle=NULL; 601 unsigned long dstSize=0; 602 603 if((handle=tjInitCompress())==NULL) _throwtj(); 604 605 printf("Buffer size regression test\n"); 606 for(subsamp=0; subsamp<TJ_NUMSAMP; subsamp++) 607 { 608 for(w=1; w<48; w++) 609 { 610 int maxh=(w==1)? 2048:48; 611 for(h=1; h<maxh; h++) 612 { 613 if(h%100==0) printf("%.4d x %.4d\b\b\b\b\b\b\b\b\b\b\b", w, h); 614 if((srcBuf=(unsigned char *)malloc(w*h*4))==NULL) 615 _throw("Memory allocation failure"); 616 if(!alloc || doyuv) 617 { 618 if(doyuv) dstSize=tjBufSizeYUV2(w, pad, h, subsamp); 619 else dstSize=tjBufSize(w, h, subsamp); 620 if((dstBuf=(unsigned char *)tjAlloc(dstSize))==NULL) 621 _throw("Memory allocation failure"); 622 } 623 624 for(i=0; i<w*h*4; i++) 625 { 626 if(random()<RAND_MAX/2) srcBuf[i]=0; 627 else srcBuf[i]=255; 628 } 629 630 if(doyuv) 631 { 632 _tj(tjEncodeYUV3(handle, srcBuf, w, 0, h, TJPF_BGRX, dstBuf, pad, 633 subsamp, 0)); 634 } 635 else 636 { 637 _tj(tjCompress2(handle, srcBuf, w, 0, h, TJPF_BGRX, &dstBuf, 638 &dstSize, subsamp, 100, alloc? 0:TJFLAG_NOREALLOC)); 639 } 640 free(srcBuf); srcBuf=NULL; 641 if(!alloc || doyuv) 642 { 643 tjFree(dstBuf); dstBuf=NULL; 644 } 645 646 if((srcBuf=(unsigned char *)malloc(h*w*4))==NULL) 647 _throw("Memory allocation failure"); 648 if(!alloc || doyuv) 649 { 650 if(doyuv) dstSize=tjBufSizeYUV2(h, pad, w, subsamp); 651 else dstSize=tjBufSize(h, w, subsamp); 652 if((dstBuf=(unsigned char *)tjAlloc(dstSize))==NULL) 653 _throw("Memory allocation failure"); 654 } 655 656 for(i=0; i<h*w*4; i++) 657 { 658 if(random()<RAND_MAX/2) srcBuf[i]=0; 659 else srcBuf[i]=255; 660 } 661 662 if(doyuv) 663 { 664 _tj(tjEncodeYUV3(handle, srcBuf, h, 0, w, TJPF_BGRX, dstBuf, pad, 665 subsamp, 0)); 666 } 667 else 668 { 669 _tj(tjCompress2(handle, srcBuf, h, 0, w, TJPF_BGRX, &dstBuf, 670 &dstSize, subsamp, 100, alloc? 0:TJFLAG_NOREALLOC)); 671 } 672 free(srcBuf); srcBuf=NULL; 673 if(!alloc || doyuv) 674 { 675 tjFree(dstBuf); dstBuf=NULL; 676 } 677 } 678 } 679 } 680 printf("Done. \n"); 681 682 bailout: 683 if(srcBuf) free(srcBuf); 684 if(dstBuf) tjFree(dstBuf); 685 if(handle) tjDestroy(handle); 686 } 687 688 689 int main(int argc, char *argv[]) 690 { 691 int i, num4bf=5; 692 #ifdef _WIN32 693 srand((unsigned int)time(NULL)); 694 #endif 695 if(argc>1) 696 { 697 for(i=1; i<argc; i++) 698 { 699 if(!strcasecmp(argv[i], "-yuv")) doyuv=1; 700 if(!strcasecmp(argv[i], "-noyuvpad")) pad=1; 701 if(!strcasecmp(argv[i], "-alloc")) alloc=1; 702 if(!strncasecmp(argv[i], "-h", 2) || !strcasecmp(argv[i], "-?")) 703 usage(argv[0]); 704 } 705 } 706 if(alloc) printf("Testing automatic buffer allocation\n"); 707 if(doyuv) num4bf=4; 708 doTest(35, 39, _3byteFormats, 2, TJSAMP_444, "test"); 709 doTest(39, 41, _4byteFormats, num4bf, TJSAMP_444, "test"); 710 doTest(41, 35, _3byteFormats, 2, TJSAMP_422, "test"); 711 doTest(35, 39, _4byteFormats, num4bf, TJSAMP_422, "test"); 712 doTest(39, 41, _3byteFormats, 2, TJSAMP_420, "test"); 713 doTest(41, 35, _4byteFormats, num4bf, TJSAMP_420, "test"); 714 doTest(35, 39, _3byteFormats, 2, TJSAMP_440, "test"); 715 doTest(39, 41, _4byteFormats, num4bf, TJSAMP_440, "test"); 716 doTest(41, 35, _3byteFormats, 2, TJSAMP_411, "test"); 717 doTest(35, 39, _4byteFormats, num4bf, TJSAMP_411, "test"); 718 doTest(39, 41, _onlyGray, 1, TJSAMP_GRAY, "test"); 719 doTest(41, 35, _3byteFormats, 2, TJSAMP_GRAY, "test"); 720 doTest(35, 39, _4byteFormats, 4, TJSAMP_GRAY, "test"); 721 bufSizeTest(); 722 if(doyuv) 723 { 724 printf("\n--------------------\n\n"); 725 doTest(48, 48, _onlyRGB, 1, TJSAMP_444, "test_yuv0"); 726 doTest(48, 48, _onlyRGB, 1, TJSAMP_422, "test_yuv0"); 727 doTest(48, 48, _onlyRGB, 1, TJSAMP_420, "test_yuv0"); 728 doTest(48, 48, _onlyRGB, 1, TJSAMP_440, "test_yuv0"); 729 doTest(48, 48, _onlyRGB, 1, TJSAMP_411, "test_yuv0"); 730 doTest(48, 48, _onlyRGB, 1, TJSAMP_GRAY, "test_yuv0"); 731 doTest(48, 48, _onlyGray, 1, TJSAMP_GRAY, "test_yuv0"); 732 } 733 734 return exitStatus; 735 } 736