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