예제 #1
0
파일: mparith1.c 프로젝트: hfeeki/go
int
Fconv(Fmt *fp)
{
	char buf[500];
	Mpflt *fvp, fv;
	double d;

	fvp = va_arg(fp->args, Mpflt*);
	if(fp->flags & FmtSharp) {
		// alternate form - decimal for error messages.
		// for well in range, convert to double and use print's %g
		if(-900 < fvp->exp && fvp->exp < 900) {
			d = mpgetflt(fvp);
			if(d >= 0 && (fp->flags & FmtSign))
				fmtprint(fp, "+");
			return fmtprint(fp, "%g", d);
		}
		// TODO(rsc): for well out of range, print
		// an approximation like 1.234e1000
	}

	if(sigfig(fvp) == 0) {
		snprint(buf, sizeof(buf), "0p+0");
		goto out;
	}
	fv = *fvp;

	while(fv.val.a[0] == 0) {
		mpshiftfix(&fv.val, -Mpscale);
		fv.exp += Mpscale;
	}
	while((fv.val.a[0]&1) == 0) {
		mpshiftfix(&fv.val, -1);
		fv.exp += 1;
	}

	if(fv.exp >= 0) {
		snprint(buf, sizeof(buf), "%#Bp+%d", &fv.val, fv.exp);
		goto out;
	}
	snprint(buf, sizeof(buf), "%#Bp-%d", &fv.val, -fv.exp);

out:
	return fmtstrcpy(fp, buf);
}
예제 #2
0
int
Fconv(Fmt *fp)
{
	char buf[500];
	Mpflt *fvp, fv;
	double d, dexp;
	int exp;

	fvp = va_arg(fp->args, Mpflt*);
	if(fp->flags & FmtSharp) {
		// alternate form - decimal for error messages.
		// for well in range, convert to double and use print's %g
		exp = fvp->exp + sigfig(fvp)*Mpscale;
		if(-900 < exp && exp < 900) {
			d = mpgetflt(fvp);
			if(d >= 0 && (fp->flags & FmtSign))
				fmtprint(fp, "+");
			return fmtprint(fp, "%g", d, exp, fvp);
		}
		
		// very out of range. compute decimal approximation by hand.
		// decimal exponent
		dexp = fvp->exp * 0.301029995663981195; // log_10(2)
		exp = (int)dexp;
		// decimal mantissa
		fv = *fvp;
		fv.val.neg = 0;
		fv.exp = 0;
		d = mpgetflt(&fv);
		d *= pow(10, dexp-exp);
		while(d >= 9.99995) {
			d /= 10;
			exp++;
		}
		if(fvp->val.neg)
			fmtprint(fp, "-");
		else if(fp->flags & FmtSign)
			fmtprint(fp, "+");
		return fmtprint(fp, "%.5fe+%d", d, exp);
	}

	if(sigfig(fvp) == 0) {
		snprint(buf, sizeof(buf), "0p+0");
		goto out;
	}
	fv = *fvp;

	while(fv.val.a[0] == 0) {
		mpshiftfix(&fv.val, -Mpscale);
		fv.exp += Mpscale;
	}
	while((fv.val.a[0]&1) == 0) {
		mpshiftfix(&fv.val, -1);
		fv.exp += 1;
	}

	if(fv.exp >= 0) {
		snprint(buf, sizeof(buf), "%#Bp+%d", &fv.val, fv.exp);
		goto out;
	}
	snprint(buf, sizeof(buf), "%#Bp-%d", &fv.val, -fv.exp);

out:
	return fmtstrcpy(fp, buf);
}
예제 #3
0
void dodecomptest(char *filename)
{
	FILE *file=NULL;  tjhandle handle=NULL;
	unsigned char **jpegbuf=NULL, *srcbuf=NULL;
	unsigned long *jpegsize=NULL, srcsize, totaljpegsize;
	tjtransform *t=NULL;
	int w=0, h=0, subsamp=-1, _w, _h, _tilew, _tileh,
		_ntilesw, _ntilesh, _subsamp;
	char *temp=NULL, tempstr[80], tempstr2[80];
	int row, col, i, tilew, tileh, ntilesw, ntilesh, retval=0;
	double start, elapsed;
	int ps=tjPixelSize[pf], tile;

	if((file=fopen(filename, "rb"))==NULL)
		_throwunix("opening file");
	if(fseek(file, 0, SEEK_END)<0 || (srcsize=ftell(file))<0)
		_throwunix("determining file size");
	if((srcbuf=(unsigned char *)malloc(srcsize))==NULL)
		_throwunix("allocating memory");
	if(fseek(file, 0, SEEK_SET)<0)
		_throwunix("setting file position");
	if(fread(srcbuf, srcsize, 1, file)<1)
		_throwunix("reading JPEG data");
	fclose(file);  file=NULL;

	temp=strrchr(filename, '.');
	if(temp!=NULL) *temp='\0';

	if((handle=tjInitTransform())==NULL)
		_throwtj("executing tjInitTransform()");
	if(tjDecompressHeader2(handle, srcbuf, srcsize, &w, &h, &subsamp)==-1)
		_throwtj("executing tjDecompressHeader2()");

	if(quiet==1)
	{
		printf("All performance values in Mpixels/sec\n\n");
		printf("Bitmap\tBitmap\tJPEG\t%s %s \tXform\tComp\tDecomp\n",
			dotile? "Tile ":"Image", dotile? "Tile ":"Image");
		printf("Format\tOrder\tSubsamp\tWidth Height\tPerf \tRatio\tPerf\n\n");
	}
	else if(!quiet)
	{
		printf(">>>>>  JPEG %s --> %s (%s)  <<<<<\n", subNameLong[subsamp],
			pixFormatStr[pf], (flags&TJFLAG_BOTTOMUP)? "Bottom-up":"Top-down");
	}

	for(tilew=dotile? 16:w, tileh=dotile? 16:h; ; tilew*=2, tileh*=2)
	{
		if(tilew>w) tilew=w;  if(tileh>h) tileh=h;
		ntilesw=(w+tilew-1)/tilew;  ntilesh=(h+tileh-1)/tileh;

		if((jpegbuf=(unsigned char **)malloc(sizeof(unsigned char *)
			*ntilesw*ntilesh))==NULL)
			_throwunix("allocating JPEG tile array");
		memset(jpegbuf, 0, sizeof(unsigned char *)*ntilesw*ntilesh);
		if((jpegsize=(unsigned long *)malloc(sizeof(unsigned long)
			*ntilesw*ntilesh))==NULL)
			_throwunix("allocating JPEG size array");
		memset(jpegsize, 0, sizeof(unsigned long)*ntilesw*ntilesh);

		if((flags&TJFLAG_NOREALLOC)!=0)
			for(i=0; i<ntilesw*ntilesh; i++)
			{
				if((jpegbuf[i]=(unsigned char *)malloc(tjBufSize(tilew, tileh,
					subsamp)))==NULL)
					_throwunix("allocating JPEG tiles");
			}

		_w=w;  _h=h;  _tilew=tilew;  _tileh=tileh;
		if(!quiet)
		{
			printf("\n%s size: %d x %d", dotile? "Tile":"Image", _tilew,
				_tileh);
			if(sf.num!=1 || sf.denom!=1)
				printf(" --> %d x %d", TJSCALED(_w, sf), TJSCALED(_h, sf));
			printf("\n");
		}
		else if(quiet==1)
		{
			printf("%s\t%s\t%s\t", pixFormatStr[pf],
				(flags&TJFLAG_BOTTOMUP)? "BU":"TD", subNameLong[subsamp]);
			printf("%-4d  %-4d\t", tilew, tileh);
		}

		_subsamp=subsamp;
		if(dotile || xformop!=TJXOP_NONE || xformopt!=0)
		{
			if((t=(tjtransform *)malloc(sizeof(tjtransform)*ntilesw*ntilesh))
				==NULL)
				_throwunix("allocating image transform array");

			if(xformop==TJXOP_TRANSPOSE || xformop==TJXOP_TRANSVERSE
				|| xformop==TJXOP_ROT90 || xformop==TJXOP_ROT270)
			{
				_w=h;  _h=w;  _tilew=tileh;  _tileh=tilew;
			}

			if(xformopt&TJXOPT_GRAY) _subsamp=TJ_GRAYSCALE;
			if(xformop==TJXOP_HFLIP || xformop==TJXOP_ROT180)
				_w=_w-(_w%tjMCUWidth[_subsamp]);
			if(xformop==TJXOP_VFLIP || xformop==TJXOP_ROT180)
				_h=_h-(_h%tjMCUHeight[_subsamp]);
			if(xformop==TJXOP_TRANSVERSE || xformop==TJXOP_ROT90)
				_w=_w-(_w%tjMCUHeight[_subsamp]);
			if(xformop==TJXOP_TRANSVERSE || xformop==TJXOP_ROT270)
				_h=_h-(_h%tjMCUWidth[_subsamp]);
			_ntilesw=(_w+_tilew-1)/_tilew;
			_ntilesh=(_h+_tileh-1)/_tileh;

			for(row=0, tile=0; row<_ntilesh; row++)
			{
				for(col=0; col<_ntilesw; col++, tile++)
				{
					t[tile].r.w=min(_tilew, _w-col*_tilew);
					t[tile].r.h=min(_tileh, _h-row*_tileh);
					t[tile].r.x=col*_tilew;
					t[tile].r.y=row*_tileh;
					t[tile].op=xformop;
					t[tile].options=xformopt|TJXOPT_TRIM;
				}
			}

			start=gettime();
			if(tjTransform(handle, srcbuf, srcsize, _ntilesw*_ntilesh, jpegbuf,
				jpegsize, t, flags)==-1)
				_throwtj("executing tjTransform()");
			elapsed=gettime()-start;

			free(t);  t=NULL;

			for(tile=0, totaljpegsize=0; tile<_ntilesw*_ntilesh; tile++)
				totaljpegsize+=jpegsize[tile];

			if(quiet)
			{
				printf("%s%c%s%c",
					sigfig((double)(w*h)/1000000./elapsed, 4, tempstr, 80),
					quiet==2? '\n':'\t',
					sigfig((double)(w*h*ps)/(double)totaljpegsize, 4, tempstr2, 80),
					quiet==2? '\n':'\t');
			}
			else if(!quiet)
			{
				printf("X--> Frame rate:           %f fps\n", 1.0/elapsed);
				printf("     Output image size:    %lu bytes\n", totaljpegsize);
				printf("     Compression ratio:    %f:1\n",
					(double)(w*h*ps)/(double)totaljpegsize);
				printf("     Source throughput:    %f Megapixels/sec\n",
					(double)(w*h)/1000000./elapsed);
				printf("     Output bit stream:    %f Megabits/sec\n",
					(double)totaljpegsize*8./1000000./elapsed);
			}
		}
		else
		{
			if(quiet==1) printf("N/A\tN/A\t");
			jpegsize[0]=srcsize;
			memcpy(jpegbuf[0], srcbuf, srcsize);
		}

		if(w==tilew) _tilew=_w;
		if(h==tileh) _tileh=_h;
		if(decomptest(NULL, jpegbuf, jpegsize, NULL, _w, _h, _subsamp, 0,
			filename, _tilew, _tileh)==-1)
			goto bailout;

		for(i=0; i<ntilesw*ntilesh; i++)
		{
			free(jpegbuf[i]);  jpegbuf[i]=NULL;
		}
		free(jpegbuf);  jpegbuf=NULL;
		if(jpegsize) {free(jpegsize);  jpegsize=NULL;}

		if(tilew==w && tileh==h) break;
	}

	bailout:
	if(file) {fclose(file);  file=NULL;}
	if(jpegbuf)
	{
		for(i=0; i<ntilesw*ntilesh; i++)
		{
			if(jpegbuf[i]) free(jpegbuf[i]);  jpegbuf[i]=NULL;
		}
		free(jpegbuf);  jpegbuf=NULL;
	}
	if(jpegsize) {free(jpegsize);  jpegsize=NULL;}
	if(srcbuf) {free(srcbuf);  srcbuf=NULL;}
	if(t) {free(t);  t=NULL;}
	if(handle) {tjDestroy(handle);  handle=NULL;}
	return;
}
예제 #4
0
/* Decompression test */
int decomptest(unsigned char *srcbuf, unsigned char **jpegbuf,
	unsigned long *jpegsize, unsigned char *dstbuf, int w, int h,
	int subsamp, int jpegqual, char *filename, int tilew, int tileh)
{
	char tempstr[1024], sizestr[20]="\0", qualstr[6]="\0", *ptr;
	FILE *file=NULL;  tjhandle handle=NULL;
	int row, col, i, dstbufalloc=0, retval=0;
	double start, elapsed;
	int ps=tjPixelSize[pf];
	int yuvsize=tjBufSizeYUV(w, h, subsamp), bufsize;
	int scaledw=(yuv==YUVDECODE)? w : TJSCALED(w, sf);
	int scaledh=(yuv==YUVDECODE)? h : TJSCALED(h, sf);
	int pitch=scaledw*ps;
	int ntilesw=(w+tilew-1)/tilew, ntilesh=(h+tileh-1)/tileh;
	unsigned char *dstptr, *dstptr2;

	if(jpegqual>0)
	{
		snprintf(qualstr, 6, "_Q%d", jpegqual);
		qualstr[5]=0;
	}

	if((handle=tjInitDecompress())==NULL)
		_throwtj("executing tjInitDecompress()");

	bufsize=(yuv==YUVDECODE? yuvsize:pitch*h);
	if(dstbuf==NULL)
	{
		if((dstbuf=(unsigned char *)malloc(bufsize)) == NULL)
			_throwunix("allocating image buffer");
		dstbufalloc=1;
	}
	/* Set the destination buffer to gray so we know whether the decompressor
	   attempted to write to it */
	memset(dstbuf, 127, bufsize);

	/* Execute once to preload cache */
	if(yuv==YUVDECODE)
	{
		if(tjDecompressToYUV(handle, jpegbuf[0], jpegsize[0], dstbuf, flags)==-1)
			_throwtj("executing tjDecompressToYUV()");
	}
	else if(tjDecompress2(handle, jpegbuf[0], jpegsize[0], dstbuf, scaledw,
		pitch, scaledh, pf, flags)==-1)
		_throwtj("executing tjDecompress2()");

	/* Benchmark */
	for(i=0, start=gettime(); (elapsed=gettime()-start)<benchtime; i++)
	{
		int tile=0;
		if(yuv==YUVDECODE)
		{
			if(tjDecompressToYUV(handle, jpegbuf[0], jpegsize[0], dstbuf, flags)==-1)
			_throwtj("executing tjDecompressToYUV()");
		}
		else for(row=0, dstptr=dstbuf; row<ntilesh; row++, dstptr+=pitch*tileh)
		{
			for(col=0, dstptr2=dstptr; col<ntilesw; col++, tile++, dstptr2+=ps*tilew)
			{
				int width=dotile? min(tilew, w-col*tilew):scaledw;
				int height=dotile? min(tileh, h-row*tileh):scaledh;
				if(tjDecompress2(handle, jpegbuf[tile], jpegsize[tile], dstptr2, width,
					pitch, height, pf, flags)==-1)
					_throwtj("executing tjDecompress2()");
			}
		}
	}

	if(tjDestroy(handle)==-1) _throwtj("executing tjDestroy()");
	handle=NULL;

	if(quiet)
	{
		printf("%s\n",
			sigfig((double)(w*h)/1000000.*(double)i/elapsed, 4, tempstr, 1024));
	}
	else
	{
		printf("D--> Frame rate:           %f fps\n", (double)i/elapsed);
		printf("     Dest. throughput:     %f Megapixels/sec\n",
			(double)(w*h)/1000000.*(double)i/elapsed);
	}
	if(yuv==YUVDECODE)
	{
		snprintf(tempstr, 1024, "%s_%s%s.yuv", filename, subName[subsamp],
			qualstr);
		if((file=fopen(tempstr, "wb"))==NULL)
			_throwunix("opening YUV image for output");
		if(fwrite(dstbuf, yuvsize, 1, file)!=1)
			_throwunix("writing YUV image");
		fclose(file);  file=NULL;
	}
	else
	{
		if(sf.num!=1 || sf.denom!=1)
			snprintf(sizestr, 20, "%d_%d", sf.num, sf.denom);
		else if(tilew!=w || tileh!=h)
			snprintf(sizestr, 20, "%dx%d", tilew, tileh);
		else snprintf(sizestr, 20, "full");
		if(decomponly)
			snprintf(tempstr, 1024, "%s_%s.%s", filename, sizestr, ext);
		else
			snprintf(tempstr, 1024, "%s_%s%s_%s.%s", filename, subName[subsamp],
				qualstr, sizestr, ext);
		if(savebmp(tempstr, dstbuf, scaledw, scaledh, pf,
			(flags&TJFLAG_BOTTOMUP)!=0)==-1)
			_throwbmp("saving bitmap");
		ptr=strrchr(tempstr, '.');
		snprintf(ptr, 1024-(ptr-tempstr), "-err.%s", ext);
		if(srcbuf && sf.num==1 && sf.denom==1)
		{
			if(!quiet) printf("Compression error written to %s.\n", tempstr);
			if(subsamp==TJ_GRAYSCALE)
			{
				int index, index2;
				for(row=0, index=0; row<h; row++, index+=pitch)
				{
					for(col=0, index2=index; col<w; col++, index2+=ps)
					{
						int rindex=index2+tjRedOffset[pf];
						int gindex=index2+tjGreenOffset[pf];
						int bindex=index2+tjBlueOffset[pf];
						int y=(int)((double)srcbuf[rindex]*0.299
							+ (double)srcbuf[gindex]*0.587
							+ (double)srcbuf[bindex]*0.114 + 0.5);
						if(y>255) y=255;  if(y<0) y=0;
						dstbuf[rindex]=abs(dstbuf[rindex]-y);
						dstbuf[gindex]=abs(dstbuf[gindex]-y);
						dstbuf[bindex]=abs(dstbuf[bindex]-y);
					}
				}
			}		
			else
			{
				for(row=0; row<h; row++)
					for(col=0; col<w*ps; col++)
						dstbuf[pitch*row+col]
							=abs(dstbuf[pitch*row+col]-srcbuf[pitch*row+col]);
			}
			if(savebmp(tempstr, dstbuf, w, h, pf,
				(flags&TJFLAG_BOTTOMUP)!=0)==-1)
				_throwbmp("saving bitmap");
		}
	}

	bailout:
	if(file) {fclose(file);  file=NULL;}
	if(handle) {tjDestroy(handle);  handle=NULL;}
	if(dstbuf && dstbufalloc) {free(dstbuf);  dstbuf=NULL;}
	return retval;
}
예제 #5
0
void dotest(unsigned char *srcbuf, int w, int h, int subsamp, int jpegqual,
	char *filename)
{
	char tempstr[1024], tempstr2[80];
	FILE *file=NULL;  tjhandle handle=NULL;
	unsigned char **jpegbuf=NULL, *tmpbuf=NULL, *srcptr, *srcptr2;
	double start, elapsed;
	int totaljpegsize=0, row, col, i, tilew=w, tileh=h, retval=0;
	unsigned long *jpegsize=NULL;
	int ps=tjPixelSize[pf], ntilesw=1, ntilesh=1, pitch=w*ps;

	if(yuv==YUVENCODE) {dotestyuv(srcbuf, w, h, subsamp, filename);  return;}

	if((tmpbuf=(unsigned char *)malloc(pitch*h)) == NULL)
		_throwunix("allocating temporary image buffer");

	if(!quiet)
		printf(">>>>>  %s (%s) <--> JPEG %s Q%d  <<<<<\n", pixFormatStr[pf],
			(flags&TJFLAG_BOTTOMUP)? "Bottom-up":"Top-down", subNameLong[subsamp],
			jpegqual);

	for(tilew=dotile? 8:w, tileh=dotile? 8:h; ; tilew*=2, tileh*=2)
	{
		if(tilew>w) tilew=w;  if(tileh>h) tileh=h;
		ntilesw=(w+tilew-1)/tilew;  ntilesh=(h+tileh-1)/tileh;

		if((jpegbuf=(unsigned char **)malloc(sizeof(unsigned char *)
			*ntilesw*ntilesh))==NULL)
			_throwunix("allocating JPEG tile array");
		memset(jpegbuf, 0, sizeof(unsigned char *)*ntilesw*ntilesh);
		if((jpegsize=(unsigned long *)malloc(sizeof(unsigned long)
			*ntilesw*ntilesh))==NULL)
			_throwunix("allocating JPEG size array");
		memset(jpegsize, 0, sizeof(unsigned long)*ntilesw*ntilesh);

		if((flags&TJFLAG_NOREALLOC)!=0)
			for(i=0; i<ntilesw*ntilesh; i++)
			{
				if((jpegbuf[i]=(unsigned char *)malloc(tjBufSize(tilew, tileh,
					subsamp)))==NULL)
					_throwunix("allocating JPEG tiles");
			}

		/* Compression test */
		if(quiet==1)
			printf("%s\t%s\t%s\t%d\t", pixFormatStr[pf],
				(flags&TJFLAG_BOTTOMUP)? "BU":"TD", subNameLong[subsamp], jpegqual);
		for(i=0; i<h; i++)
			memcpy(&tmpbuf[pitch*i], &srcbuf[w*ps*i], w*ps);
		if((handle=tjInitCompress())==NULL)
			_throwtj("executing tjInitCompress()");

		/* Execute once to preload cache */
		if(tjCompress2(handle, srcbuf, tilew, pitch, tileh, pf, &jpegbuf[0],
			&jpegsize[0], subsamp, jpegqual, flags)==-1)
			_throwtj("executing tjCompress2()");

		/* Benchmark */
		for(i=0, start=gettime(); (elapsed=gettime()-start)<benchtime; i++)
		{
			int tile=0;
			totaljpegsize=0;
			for(row=0, srcptr=srcbuf; row<ntilesh; row++, srcptr+=pitch*tileh)
			{
				for(col=0, srcptr2=srcptr; col<ntilesw; col++, tile++,
					srcptr2+=ps*tilew)
				{
					int width=min(tilew, w-col*tilew);
					int height=min(tileh, h-row*tileh);
					if(tjCompress2(handle, srcptr2, width, pitch, height, pf,
						&jpegbuf[tile], &jpegsize[tile], subsamp, jpegqual, flags)==-1)
						_throwtj("executing tjCompress()2");
					totaljpegsize+=jpegsize[tile];
				}
			}
		}

		if(tjDestroy(handle)==-1) _throwtj("executing tjDestroy()");
		handle=NULL;

		if(quiet==1) printf("%-4d  %-4d\t", tilew, tileh);
		if(quiet)
		{
			printf("%s%c%s%c",
				sigfig((double)(w*h)/1000000.*(double)i/elapsed, 4, tempstr, 1024),
				quiet==2? '\n':'\t',
				sigfig((double)(w*h*ps)/(double)totaljpegsize, 4, tempstr2, 80),
				quiet==2? '\n':'\t');
		}
		else
		{
			printf("\n%s size: %d x %d\n", dotile? "Tile":"Image", tilew,
				tileh);
			printf("C--> Frame rate:           %f fps\n", (double)i/elapsed);
			printf("     Output image size:    %d bytes\n", totaljpegsize);
			printf("     Compression ratio:    %f:1\n",
				(double)(w*h*ps)/(double)totaljpegsize);
			printf("     Source throughput:    %f Megapixels/sec\n",
				(double)(w*h)/1000000.*(double)i/elapsed);
			printf("     Output bit stream:    %f Megabits/sec\n",
				(double)totaljpegsize*8./1000000.*(double)i/elapsed);
		}
		if(tilew==w && tileh==h)
		{
			snprintf(tempstr, 1024, "%s_%s_Q%d.jpg", filename, subName[subsamp],
				jpegqual);
			if((file=fopen(tempstr, "wb"))==NULL)
				_throwunix("opening reference image");
			if(fwrite(jpegbuf[0], jpegsize[0], 1, file)!=1)
				_throwunix("writing reference image");
			fclose(file);  file=NULL;
			if(!quiet) printf("Reference image written to %s\n", tempstr);
		}

		/* Decompression test */
		if(decomptest(srcbuf, jpegbuf, jpegsize, tmpbuf, w, h, subsamp, jpegqual,
			filename, tilew, tileh)==-1)
			goto bailout;

		for(i=0; i<ntilesw*ntilesh; i++)
		{
			if(jpegbuf[i]) free(jpegbuf[i]);  jpegbuf[i]=NULL;
		}
		free(jpegbuf);  jpegbuf=NULL;
		free(jpegsize);  jpegsize=NULL;

		if(tilew==w && tileh==h) break;
	}

	bailout:
	if(file) {fclose(file);  file=NULL;}
	if(jpegbuf)
	{
		for(i=0; i<ntilesw*ntilesh; i++)
		{
			if(jpegbuf[i]) free(jpegbuf[i]);  jpegbuf[i]=NULL;
		}
		free(jpegbuf);  jpegbuf=NULL;
	}
	if(jpegsize) {free(jpegsize);  jpegsize=NULL;}
	if(tmpbuf) {free(tmpbuf);  tmpbuf=NULL;}
	if(handle) {tjDestroy(handle);  handle=NULL;}
	return;
}
예제 #6
0
void dotestyuv(unsigned char *srcbuf, int w, int h, int subsamp,
	char *filename)
{
	char tempstr[1024], tempstr2[80];
	FILE *file=NULL;  tjhandle handle=NULL;
	unsigned char *dstbuf=NULL;
	double start, elapsed;
	int i, retval=0, ps=tjPixelSize[pf];
	int yuvsize=0;

	yuvsize=tjBufSizeYUV(w, h, subsamp);
	if((dstbuf=(unsigned char *)malloc(yuvsize)) == NULL)
		_throwunix("allocating image buffer");

	if(!quiet)
		printf(">>>>>  %s (%s) <--> YUV %s  <<<<<\n", pixFormatStr[pf],
			(flags&TJFLAG_BOTTOMUP)? "Bottom-up":"Top-down", subNameLong[subsamp]);

	if(quiet==1)
		printf("%s\t%s\t%s\tN/A\t", pixFormatStr[pf],
			(flags&TJFLAG_BOTTOMUP)? "BU":"TD", subNameLong[subsamp]);

	if((handle=tjInitCompress())==NULL)
		_throwtj("executing tjInitCompress()");

	/* Execute once to preload cache */
	if(tjEncodeYUV2(handle, srcbuf, w, 0, h, pf, dstbuf, subsamp, flags)==-1)
		_throwtj("executing tjEncodeYUV2()");

	/* Benchmark */
	for(i=0, start=gettime(); (elapsed=gettime()-start)<benchtime; i++)
	{
		if(tjEncodeYUV2(handle, srcbuf, w, 0, h, pf, dstbuf, subsamp, flags)==-1)
			_throwtj("executing tjEncodeYUV2()");
	}

	if(tjDestroy(handle)==-1) _throwtj("executing tjDestroy()");
	handle=NULL;

	if(quiet==1) printf("%-4d  %-4d\t", w, h);
	if(quiet)
	{
		printf("%s%c%s%c",
			sigfig((double)(w*h)/1000000.*(double)i/elapsed, 4, tempstr, 1024),
			quiet==2? '\n':'\t',
			sigfig((double)(w*h*ps)/(double)yuvsize, 4, tempstr2, 80),
			quiet==2? '\n':'\t');
	}
	else
	{
		printf("\n%s size: %d x %d\n", "Image", w, h);
		printf("C--> Frame rate:           %f fps\n", (double)i/elapsed);
		printf("     Output image size:    %d bytes\n", yuvsize);
		printf("     Compression ratio:    %f:1\n",
			(double)(w*h*ps)/(double)yuvsize);
		printf("     Source throughput:    %f Megapixels/sec\n",
			(double)(w*h)/1000000.*(double)i/elapsed);
		printf("     Output bit stream:    %f Megabits/sec\n",
			(double)yuvsize*8./1000000.*(double)i/elapsed);
	}
	snprintf(tempstr, 1024, "%s_%s.yuv", filename, subName[subsamp]);
	if((file=fopen(tempstr, "wb"))==NULL)
		_throwunix("opening reference image");
	if(fwrite(dstbuf, yuvsize, 1, file)!=1)
		_throwunix("writing reference image");
	fclose(file);  file=NULL;
	if(!quiet) printf("Reference image written to %s\n", tempstr);

	bailout:
	if(file) {fclose(file);  file=NULL;}
	if(dstbuf) {free(dstbuf);  dstbuf=NULL;}
	if(handle) {tjDestroy(handle);  handle=NULL;}
	return;
}
예제 #7
0
int decompTest(char *filename)
{
	FILE *file=NULL;  tjhandle handle=NULL;
	unsigned char **jpegbuf=NULL, *srcbuf=NULL;
	unsigned long *jpegsize=NULL, srcsize, totaljpegsize;
	tjtransform *t=NULL;
	int w=0, h=0, subsamp=-1, cs=-1, _w, _h, _tilew, _tileh,
		_ntilesw, _ntilesh, _subsamp;
	char *temp=NULL, tempstr[80], tempstr2[80];
	int row, col, i, iter, tilew, tileh, ntilesw=1, ntilesh=1, retval=0;
	double start, elapsed;
	int ps=tjPixelSize[pf], tile;

	if((file=fopen(filename, "rb"))==NULL)
		_throwunix("opening file");
	if(fseek(file, 0, SEEK_END)<0 || (srcsize=ftell(file))==(unsigned long)-1)
		_throwunix("determining file size");
	if((srcbuf=(unsigned char *)malloc(srcsize))==NULL)
		_throwunix("allocating memory");
	if(fseek(file, 0, SEEK_SET)<0)
		_throwunix("setting file position");
	if(fread(srcbuf, srcsize, 1, file)<1)
		_throwunix("reading JPEG data");
	fclose(file);  file=NULL;

	temp=strrchr(filename, '.');
	if(temp!=NULL) *temp='\0';

	if((handle=tjInitTransform())==NULL)
		_throwtj("executing tjInitTransform()");
	if(tjDecompressHeader3(handle, srcbuf, srcsize, &w, &h, &subsamp, &cs)==-1)
		_throwtj("executing tjDecompressHeader3()");
	if(cs==TJCS_YCCK || cs==TJCS_CMYK)
	{
		pf=TJPF_CMYK;  ps=tjPixelSize[pf];
	}

	if(quiet==1)
	{
		printf("All performance values in Mpixels/sec\n\n");
		printf("Bitmap     JPEG   JPEG     %s  %s   Xform   Comp    Decomp  ",
			dotile? "Tile ":"Image", dotile? "Tile ":"Image");
		if(doyuv) printf("Decode");
		printf("\n");
		printf("Format     CS     Subsamp  Width  Height  Perf    Ratio   Perf    ");
		if(doyuv) printf("Perf");
		printf("\n\n");
	}
	else if(!quiet)
		printf(">>>>>  JPEG %s --> %s (%s)  <<<<<\n",
			formatName(subsamp, cs, tempstr), pixFormatStr[pf],
			(flags&TJFLAG_BOTTOMUP)? "Bottom-up":"Top-down");

	for(tilew=dotile? 16:w, tileh=dotile? 16:h; ; tilew*=2, tileh*=2)
	{
		if(tilew>w) tilew=w;  if(tileh>h) tileh=h;
		ntilesw=(w+tilew-1)/tilew;  ntilesh=(h+tileh-1)/tileh;

		if((jpegbuf=(unsigned char **)malloc(sizeof(unsigned char *)
			*ntilesw*ntilesh))==NULL)
			_throwunix("allocating JPEG tile array");
		memset(jpegbuf, 0, sizeof(unsigned char *)*ntilesw*ntilesh);
		if((jpegsize=(unsigned long *)malloc(sizeof(unsigned long)
			*ntilesw*ntilesh))==NULL)
			_throwunix("allocating JPEG size array");
		memset(jpegsize, 0, sizeof(unsigned long)*ntilesw*ntilesh);

		if((flags&TJFLAG_NOREALLOC)!=0 || !dotile)
			for(i=0; i<ntilesw*ntilesh; i++)
			{
				if((jpegbuf[i]=(unsigned char *)tjAlloc(tjBufSize(tilew, tileh,
					subsamp)))==NULL)
					_throwunix("allocating JPEG tiles");
			}

		_w=w;  _h=h;  _tilew=tilew;  _tileh=tileh;
		if(!quiet)
		{
			printf("\n%s size: %d x %d", dotile? "Tile":"Image", _tilew,
				_tileh);
			if(sf.num!=1 || sf.denom!=1)
				printf(" --> %d x %d", TJSCALED(_w, sf), TJSCALED(_h, sf));
			printf("\n");
		}
		else if(quiet==1)
		{
			printf("%-4s (%s)  %-5s  %-5s    ", pixFormatStr[pf],
				(flags&TJFLAG_BOTTOMUP)? "BU":"TD", csName[cs], subNameLong[subsamp]);
			printf("%-5d  %-5d   ", tilew, tileh);
		}

		_subsamp=subsamp;
		if(dotile || xformop!=TJXOP_NONE || xformopt!=0 || customFilter)
		{
			if((t=(tjtransform *)malloc(sizeof(tjtransform)*ntilesw*ntilesh))
				==NULL)
				_throwunix("allocating image transform array");

			if(xformop==TJXOP_TRANSPOSE || xformop==TJXOP_TRANSVERSE
				|| xformop==TJXOP_ROT90 || xformop==TJXOP_ROT270)
			{
				_w=h;  _h=w;  _tilew=tileh;  _tileh=tilew;
			}

			if(xformopt&TJXOPT_GRAY) _subsamp=TJ_GRAYSCALE;
			if(xformop==TJXOP_HFLIP || xformop==TJXOP_ROT180)
				_w=_w-(_w%tjMCUWidth[_subsamp]);
			if(xformop==TJXOP_VFLIP || xformop==TJXOP_ROT180)
				_h=_h-(_h%tjMCUHeight[_subsamp]);
			if(xformop==TJXOP_TRANSVERSE || xformop==TJXOP_ROT90)
				_w=_w-(_w%tjMCUHeight[_subsamp]);
			if(xformop==TJXOP_TRANSVERSE || xformop==TJXOP_ROT270)
				_h=_h-(_h%tjMCUWidth[_subsamp]);
			_ntilesw=(_w+_tilew-1)/_tilew;
			_ntilesh=(_h+_tileh-1)/_tileh;

			if(xformop==TJXOP_TRANSPOSE || xformop==TJXOP_TRANSVERSE
				|| xformop==TJXOP_ROT90 || xformop==TJXOP_ROT270)
			{
				if(_subsamp==TJSAMP_422) _subsamp=TJSAMP_440;
				else if(_subsamp==TJSAMP_440) _subsamp=TJSAMP_422;
			}

			for(row=0, tile=0; row<_ntilesh; row++)
			{
				for(col=0; col<_ntilesw; col++, tile++)
				{
					t[tile].r.w=min(_tilew, _w-col*_tilew);
					t[tile].r.h=min(_tileh, _h-row*_tileh);
					t[tile].r.x=col*_tilew;
					t[tile].r.y=row*_tileh;
					t[tile].op=xformop;
					t[tile].options=xformopt|TJXOPT_TRIM;
					t[tile].customFilter=customFilter;
					if(t[tile].options&TJXOPT_NOOUTPUT && jpegbuf[tile])
					{
						tjFree(jpegbuf[tile]);  jpegbuf[tile]=NULL;
					}
				}
			}

			iter=-warmup;
			elapsed=0.;
			while(1)
			{
				start=gettime();
				if(tjTransform(handle, srcbuf, srcsize, _ntilesw*_ntilesh, jpegbuf,
					jpegsize, t, flags)==-1)
					_throwtj("executing tjTransform()");
				iter++;
				if(iter>=1)
				{
					elapsed+=gettime()-start;
					if(elapsed>=benchtime) break;
				}
			}

			free(t);  t=NULL;

			for(tile=0, totaljpegsize=0; tile<_ntilesw*_ntilesh; tile++)
				totaljpegsize+=jpegsize[tile];

			if(quiet)
			{
				printf("%-6s%s%-6s%s",
					sigfig((double)(w*h)/1000000./elapsed, 4, tempstr, 80),
					quiet==2? "\n":"  ",
					sigfig((double)(w*h*ps)/(double)totaljpegsize, 4, tempstr2, 80),
					quiet==2? "\n":"  ");
			}
			else if(!quiet)
			{
				printf("Transform     --> Frame rate:         %f fps\n", 1.0/elapsed);
				printf("                  Output image size:  %lu bytes\n", totaljpegsize);
				printf("                  Compression ratio:  %f:1\n",
					(double)(w*h*ps)/(double)totaljpegsize);
				printf("                  Throughput:         %f Megapixels/sec\n",
					(double)(w*h)/1000000./elapsed);
				printf("                  Output bit stream:  %f Megabits/sec\n",
					(double)totaljpegsize*8./1000000./elapsed);
			}
		}
		else
		{
			if(quiet==1) printf("N/A     N/A     ");
			jpegsize[0]=srcsize;
			memcpy(jpegbuf[0], srcbuf, srcsize);
		}

		if(w==tilew) _tilew=_w;
		if(h==tileh) _tileh=_h;
		if(!(xformopt&TJXOPT_NOOUTPUT))
		{
			if(decomp(NULL, jpegbuf, jpegsize, NULL, _w, _h, _subsamp, 0,
				filename, _tilew, _tileh)==-1)
				goto bailout;
		}
		else if(quiet==1) printf("N/A\n");

		for(i=0; i<ntilesw*ntilesh; i++)
		{
			tjFree(jpegbuf[i]);  jpegbuf[i]=NULL;
		}
		free(jpegbuf);  jpegbuf=NULL;
		if(jpegsize) {free(jpegsize);  jpegsize=NULL;}

		if(tilew==w && tileh==h) break;
	}

	bailout:
	if(file) {fclose(file);  file=NULL;}
	if(jpegbuf)
	{
		for(i=0; i<ntilesw*ntilesh; i++)
		{
			if(jpegbuf[i]) tjFree(jpegbuf[i]);  jpegbuf[i]=NULL;
		}
		free(jpegbuf);  jpegbuf=NULL;
	}
	if(jpegsize) {free(jpegsize);  jpegsize=NULL;}
	if(srcbuf) {free(srcbuf);  srcbuf=NULL;}
	if(t) {free(t);  t=NULL;}
	if(handle) {tjDestroy(handle);  handle=NULL;}
	return retval;
}
예제 #8
0
int fullTest(unsigned char *srcbuf, int w, int h, int subsamp, int jpegqual,
	char *filename)
{
	char tempstr[1024], tempstr2[80];
	FILE *file=NULL;  tjhandle handle=NULL;
	unsigned char **jpegbuf=NULL, *yuvbuf=NULL, *tmpbuf=NULL, *srcptr, *srcptr2;
	double start, elapsed, elapsedEncode;
	int totaljpegsize=0, row, col, i, tilew=w, tileh=h, retval=0;
	int iter, yuvsize=0;
	unsigned long *jpegsize=NULL;
	int ps=tjPixelSize[pf];
	int ntilesw=1, ntilesh=1, pitch=w*ps;
	const char *pfStr=pixFormatStr[pf];

	if((tmpbuf=(unsigned char *)malloc(pitch*h)) == NULL)
		_throwunix("allocating temporary image buffer");

	if(!quiet)
		printf(">>>>>  %s (%s) <--> JPEG %s Q%d  <<<<<\n", pfStr,
			(flags&TJFLAG_BOTTOMUP)? "Bottom-up":"Top-down", subNameLong[subsamp],
			jpegqual);

	for(tilew=dotile? 8:w, tileh=dotile? 8:h; ; tilew*=2, tileh*=2)
	{
		if(tilew>w) tilew=w;  if(tileh>h) tileh=h;
		ntilesw=(w+tilew-1)/tilew;  ntilesh=(h+tileh-1)/tileh;

		if((jpegbuf=(unsigned char **)malloc(sizeof(unsigned char *)
			*ntilesw*ntilesh))==NULL)
			_throwunix("allocating JPEG tile array");
		memset(jpegbuf, 0, sizeof(unsigned char *)*ntilesw*ntilesh);
		if((jpegsize=(unsigned long *)malloc(sizeof(unsigned long)
			*ntilesw*ntilesh))==NULL)
			_throwunix("allocating JPEG size array");
		memset(jpegsize, 0, sizeof(unsigned long)*ntilesw*ntilesh);

		if((flags&TJFLAG_NOREALLOC)!=0)
			for(i=0; i<ntilesw*ntilesh; i++)
			{
				if((jpegbuf[i]=(unsigned char *)tjAlloc(tjBufSize(tilew, tileh,
					subsamp)))==NULL)
					_throwunix("allocating JPEG tiles");
			}

		/* Compression test */
		if(quiet==1)
			printf("%-4s (%s)  %-5s    %-3d   ", pfStr,
				(flags&TJFLAG_BOTTOMUP)? "BU":"TD", subNameLong[subsamp], jpegqual);
		for(i=0; i<h; i++)
			memcpy(&tmpbuf[pitch*i], &srcbuf[w*ps*i], w*ps);
		if((handle=tjInitCompress())==NULL)
			_throwtj("executing tjInitCompress()");

		if(doyuv)
		{
			yuvsize=tjBufSizeYUV2(tilew, yuvpad, tileh, subsamp);
			if((yuvbuf=(unsigned char *)malloc(yuvsize))==NULL)
				_throwunix("allocating YUV buffer");
			memset(yuvbuf, 127, yuvsize);
		}

		/* Benchmark */
		iter=-warmup;
		elapsed=elapsedEncode=0.;
		while(1)
		{
			int tile=0;
			totaljpegsize=0;
			start=gettime();
			for(row=0, srcptr=srcbuf; row<ntilesh; row++, srcptr+=pitch*tileh)
			{
				for(col=0, srcptr2=srcptr; col<ntilesw; col++, tile++,
					srcptr2+=ps*tilew)
				{
					int width=min(tilew, w-col*tilew);
					int height=min(tileh, h-row*tileh);
					if(doyuv)
					{
						double startEncode=gettime();
						if(tjEncodeYUV3(handle, srcptr2, width, pitch, height, pf, yuvbuf,
							yuvpad, subsamp, flags)==-1)
							_throwtj("executing tjEncodeYUV3()");
						if(iter>=0) elapsedEncode+=gettime()-startEncode;
						if(tjCompressFromYUV(handle, yuvbuf, width, yuvpad, height,
							subsamp, &jpegbuf[tile], &jpegsize[tile], jpegqual, flags)==-1)
							_throwtj("executing tjCompressFromYUV()");
					}
					else
					{
						if(tjCompress2(handle, srcptr2, width, pitch, height, pf,
							&jpegbuf[tile], &jpegsize[tile], subsamp, jpegqual, flags)==-1)
							_throwtj("executing tjCompress2()");
					}
					totaljpegsize+=jpegsize[tile];
				}
			}
			iter++;
			if(iter>=1)
			{
				elapsed+=gettime()-start;
				if(elapsed>=benchtime) break;
			}
		}
		if(doyuv) elapsed-=elapsedEncode;

		if(tjDestroy(handle)==-1) _throwtj("executing tjDestroy()");
		handle=NULL;

		if(quiet==1) printf("%-5d  %-5d   ", tilew, tileh);
		if(quiet)
		{
			if(doyuv)
				printf("%-6s%s",
					sigfig((double)(w*h)/1000000.*(double)iter/elapsedEncode, 4, tempstr,
						1024), quiet==2? "\n":"  ");
			printf("%-6s%s",
				sigfig((double)(w*h)/1000000.*(double)iter/elapsed, 4,	tempstr, 1024),
				quiet==2? "\n":"  ");
			printf("%-6s%s",
				sigfig((double)(w*h*ps)/(double)totaljpegsize, 4, tempstr2, 80),
				quiet==2? "\n":"  ");
		}
		else
		{
			printf("\n%s size: %d x %d\n", dotile? "Tile":"Image", tilew,
				tileh);
			if(doyuv)
			{
				printf("Encode YUV    --> Frame rate:         %f fps\n",
					(double)iter/elapsedEncode);
				printf("                  Output image size:  %d bytes\n", yuvsize);
				printf("                  Compression ratio:  %f:1\n",
					(double)(w*h*ps)/(double)yuvsize);
				printf("                  Throughput:         %f Megapixels/sec\n",
					(double)(w*h)/1000000.*(double)iter/elapsedEncode);
				printf("                  Output bit stream:  %f Megabits/sec\n",
					(double)yuvsize*8./1000000.*(double)iter/elapsedEncode);
			}
			printf("%s --> Frame rate:         %f fps\n",
				doyuv? "Comp from YUV":"Compress     ", (double)iter/elapsed);
			printf("                  Output image size:  %d bytes\n",
				totaljpegsize);
			printf("                  Compression ratio:  %f:1\n",
				(double)(w*h*ps)/(double)totaljpegsize);
			printf("                  Throughput:         %f Megapixels/sec\n",
				(double)(w*h)/1000000.*(double)iter/elapsed);
			printf("                  Output bit stream:  %f Megabits/sec\n",
				(double)totaljpegsize*8./1000000.*(double)iter/elapsed);
		}
		if(tilew==w && tileh==h)
		{
			snprintf(tempstr, 1024, "%s_%s_Q%d.jpg", filename, subName[subsamp],
				jpegqual);
			if((file=fopen(tempstr, "wb"))==NULL)
				_throwunix("opening reference image");
			if(fwrite(jpegbuf[0], jpegsize[0], 1, file)!=1)
				_throwunix("writing reference image");
			fclose(file);  file=NULL;
			if(!quiet) printf("Reference image written to %s\n", tempstr);
		}

		/* Decompression test */
		if(!componly)
		{
			if(decomp(srcbuf, jpegbuf, jpegsize, tmpbuf, w, h, subsamp, jpegqual,
				filename, tilew, tileh)==-1)
				goto bailout;
		}

		for(i=0; i<ntilesw*ntilesh; i++)
		{
			if(jpegbuf[i]) tjFree(jpegbuf[i]);  jpegbuf[i]=NULL;
		}
		free(jpegbuf);  jpegbuf=NULL;
		free(jpegsize);  jpegsize=NULL;
		if(doyuv)
		{
			free(yuvbuf);  yuvbuf=NULL;
		}

		if(tilew==w && tileh==h) break;
	}

	bailout:
	if(file) {fclose(file);  file=NULL;}
	if(jpegbuf)
	{
		for(i=0; i<ntilesw*ntilesh; i++)
		{
			if(jpegbuf[i]) tjFree(jpegbuf[i]);  jpegbuf[i]=NULL;
		}
		free(jpegbuf);  jpegbuf=NULL;
	}
	if(yuvbuf) {free(yuvbuf);  yuvbuf=NULL;}
	if(jpegsize) {free(jpegsize);  jpegsize=NULL;}
	if(tmpbuf) {free(tmpbuf);  tmpbuf=NULL;}
	if(handle) {tjDestroy(handle);  handle=NULL;}
	return retval;
}
예제 #9
0
/* Decompression test */
int decomp(unsigned char *srcbuf, unsigned char **jpegbuf,
	unsigned long *jpegsize, unsigned char *dstbuf, int w, int h,
	int subsamp, int jpegqual, char *filename, int tilew, int tileh)
{
	char tempstr[1024], sizestr[20]="\0", qualstr[6]="\0", *ptr;
	FILE *file=NULL;  tjhandle handle=NULL;
	int row, col, iter=0, dstbufalloc=0, retval=0;
	double elapsed, elapsedDecode;
	int ps=tjPixelSize[pf];
	int scaledw=TJSCALED(w, sf);
	int scaledh=TJSCALED(h, sf);
	int pitch=scaledw*ps;
	int ntilesw=(w+tilew-1)/tilew, ntilesh=(h+tileh-1)/tileh;
	unsigned char *dstptr, *dstptr2, *yuvbuf=NULL;

	if(jpegqual>0)
	{
		snprintf(qualstr, 6, "_Q%d", jpegqual);
		qualstr[5]=0;
	}

	if((handle=tjInitDecompress())==NULL)
		_throwtj("executing tjInitDecompress()");

	if(dstbuf==NULL)
	{
		if((dstbuf=(unsigned char *)malloc(pitch*scaledh))==NULL)
			_throwunix("allocating destination buffer");
		dstbufalloc=1;
	}
	/* Set the destination buffer to gray so we know whether the decompressor
	   attempted to write to it */
	memset(dstbuf, 127, pitch*scaledh);

	if(doyuv)
	{
		int width=dotile? tilew:scaledw;
		int height=dotile? tileh:scaledh;
		int yuvsize=tjBufSizeYUV2(width, yuvpad, height, subsamp);
		if((yuvbuf=(unsigned char *)malloc(yuvsize))==NULL)
			_throwunix("allocating YUV buffer");
		memset(yuvbuf, 127, yuvsize);
	}

	/* Benchmark */
	iter=-warmup;
	elapsed=elapsedDecode=0.;
	while(1)
	{
		int tile=0;
		double start=gettime();
		for(row=0, dstptr=dstbuf; row<ntilesh; row++, dstptr+=pitch*tileh)
		{
			for(col=0, dstptr2=dstptr; col<ntilesw; col++, tile++, dstptr2+=ps*tilew)
			{
				int width=dotile? min(tilew, w-col*tilew):scaledw;
				int height=dotile? min(tileh, h-row*tileh):scaledh;
				if(doyuv)
				{
					double startDecode;
					if(tjDecompressToYUV2(handle, jpegbuf[tile], jpegsize[tile], yuvbuf,
						width, yuvpad, height, flags)==-1)
						_throwtj("executing tjDecompressToYUV2()");
					startDecode=gettime();
					if(tjDecodeYUV(handle, yuvbuf, yuvpad, subsamp, dstptr2, width,
						pitch, height, pf, flags)==-1)
						_throwtj("executing tjDecodeYUV()");
					if(iter>=0) elapsedDecode+=gettime()-startDecode;
				}
				else
					if(tjDecompress2(handle, jpegbuf[tile], jpegsize[tile], dstptr2,
						width, pitch, height, pf, flags)==-1)
						_throwtj("executing tjDecompress2()");
			}
		}
		iter++;
		if(iter>=1)
		{
			elapsed+=gettime()-start;
			if(elapsed>=benchtime) break;
		}
	}
	if(doyuv) elapsed-=elapsedDecode;

	if(tjDestroy(handle)==-1) _throwtj("executing tjDestroy()");
	handle=NULL;

	if(quiet)
	{
		printf("%-6s%s",
			sigfig((double)(w*h)/1000000.*(double)iter/elapsed, 4, tempstr, 1024),
			quiet==2? "\n":"  ");
		if(doyuv)
			printf("%s\n",
				sigfig((double)(w*h)/1000000.*(double)iter/elapsedDecode, 4, tempstr,
					1024));
		else if(quiet!=2) printf("\n");
	}
	else
	{
		printf("%s --> Frame rate:         %f fps\n",
			doyuv? "Decomp to YUV":"Decompress   ", (double)iter/elapsed);
		printf("                  Throughput:         %f Megapixels/sec\n",
			(double)(w*h)/1000000.*(double)iter/elapsed);
		if(doyuv)
		{
			printf("YUV Decode    --> Frame rate:         %f fps\n",
				(double)iter/elapsedDecode);
			printf("                  Throughput:         %f Megapixels/sec\n",
				(double)(w*h)/1000000.*(double)iter/elapsedDecode);
		}
	}
	if(sf.num!=1 || sf.denom!=1)
		snprintf(sizestr, 20, "%d_%d", sf.num, sf.denom);
	else if(tilew!=w || tileh!=h)
		snprintf(sizestr, 20, "%dx%d", tilew, tileh);
	else snprintf(sizestr, 20, "full");
	if(decomponly)
		snprintf(tempstr, 1024, "%s_%s.%s", filename, sizestr, ext);
	else
		snprintf(tempstr, 1024, "%s_%s%s_%s.%s", filename, subName[subsamp],
			qualstr, sizestr, ext);

	if(savebmp(tempstr, dstbuf, scaledw, scaledh, pf,
		(flags&TJFLAG_BOTTOMUP)!=0)==-1)
		_throwbmp("saving bitmap");
	ptr=strrchr(tempstr, '.');
	snprintf(ptr, 1024-(ptr-tempstr), "-err.%s", ext);
	if(srcbuf && sf.num==1 && sf.denom==1)
	{
		if(!quiet) printf("Compression error written to %s.\n", tempstr);
		if(subsamp==TJ_GRAYSCALE)
		{
			int index, index2;
			for(row=0, index=0; row<h; row++, index+=pitch)
			{
				for(col=0, index2=index; col<w; col++, index2+=ps)
				{
					int rindex=index2+tjRedOffset[pf];
					int gindex=index2+tjGreenOffset[pf];
					int bindex=index2+tjBlueOffset[pf];
					int y=(int)((double)srcbuf[rindex]*0.299
						+ (double)srcbuf[gindex]*0.587
						+ (double)srcbuf[bindex]*0.114 + 0.5);
					if(y>255) y=255;  if(y<0) y=0;
					dstbuf[rindex]=abs(dstbuf[rindex]-y);
					dstbuf[gindex]=abs(dstbuf[gindex]-y);
					dstbuf[bindex]=abs(dstbuf[bindex]-y);
				}
			}
		}
		else
		{
			for(row=0; row<h; row++)
				for(col=0; col<w*ps; col++)
					dstbuf[pitch*row+col]
						=abs(dstbuf[pitch*row+col]-srcbuf[pitch*row+col]);
		}
		if(savebmp(tempstr, dstbuf, w, h, pf,
			(flags&TJFLAG_BOTTOMUP)!=0)==-1)
			_throwbmp("saving bitmap");
	}

	bailout:
	if(file) fclose(file);
	if(handle) tjDestroy(handle);
	if(dstbuf && dstbufalloc) free(dstbuf);
	if(yuvbuf) free(yuvbuf);
	return retval;
}