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