blob: 9cfc2aec3b9450771c7dfc780f2a7bd71cbdca82 [file] [log] [blame]
DRC2e7b76b2009-04-03 12:04:24 +00001/* Copyright (C)2004 Landmark Graphics Corporation
2 * Copyright (C)2005, 2006 Sun Microsystems, Inc.
DRC2e4d0442011-02-08 01:18:37 +00003 * Copyright (C)2009-2011 D. R. Commander
DRC2e7b76b2009-04-03 12:04:24 +00004 *
5 * This library is free software and may be redistributed and/or modified under
6 * the terms of the wxWindows Library License, Version 3.1 or (at your option)
7 * any later version. The full license is in the LICENSE.txt file included
8 * with this distribution.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * wxWindows Library License for more details.
14 */
15
16#include <stdio.h>
17#include <stdlib.h>
18#include <string.h>
19#include <math.h>
DRCe8ce2e02010-11-12 10:14:11 +000020#include <errno.h>
DRC2e7b76b2009-04-03 12:04:24 +000021#include "./bmp.h"
22#include "./rrutil.h"
23#include "./rrtimer.h"
24#include "./turbojpeg.h"
25
DRCe8ce2e02010-11-12 10:14:11 +000026#define _throw(op, err) { \
27 printf("ERROR in line %d while %s:\n%s\n", __LINE__, op, err); goto bailout;}
28#define _throwunix(m) _throw(m, strerror(errno))
29#define _throwtj(m) _throw(m, tjGetErrorStr())
30#define _throwbmp(m) _throw(m, bmpgeterr())
DRC2e7b76b2009-04-03 12:04:24 +000031
DRC9e17f7d2010-12-10 04:59:13 +000032#define PAD(v, p) ((v+(p)-1)&(~((p)-1)))
33
34enum {YUVENCODE=1, YUVDECODE};
DRCe8ce2e02010-11-12 10:14:11 +000035int forcemmx=0, forcesse=0, forcesse2=0, forcesse3=0, fastupsample=0,
DRC993bf0e2011-02-15 21:57:26 +000036 decomponly=0, yuv=0, quiet=0, dotile=0, pf=BMP_BGR, bu=0, useppm=0;
DRC2e7b76b2009-04-03 12:04:24 +000037const int _ps[BMPPIXELFORMATS]={3, 4, 3, 4, 4, 4};
38const int _flags[BMPPIXELFORMATS]={0, 0, TJ_BGR, TJ_BGR,
39 TJ_BGR|TJ_ALPHAFIRST, TJ_ALPHAFIRST};
40const int _rindex[BMPPIXELFORMATS]={0, 0, 2, 2, 3, 1};
41const int _gindex[BMPPIXELFORMATS]={1, 1, 1, 1, 2, 2};
42const int _bindex[BMPPIXELFORMATS]={2, 2, 0, 0, 1, 3};
43const char *_pfname[]={"RGB", "RGBA", "BGR", "BGRA", "ABGR", "ARGB"};
DRC61e51f92009-04-05 21:53:20 +000044const char *_subnamel[NUMSUBOPT]={"4:4:4", "4:2:2", "4:2:0", "GRAY"};
45const char *_subnames[NUMSUBOPT]={"444", "422", "420", "GRAY"};
DRC9e17f7d2010-12-10 04:59:13 +000046const int _hsf[NUMSUBOPT]={1, 2, 2, 1};
47const int _vsf[NUMSUBOPT]={1, 1, 2, 1};
DRC2e7b76b2009-04-03 12:04:24 +000048
49void printsigfig(double val, int figs)
50{
51 char format[80];
52 double _l=log10(val); int l;
53 if(_l<0.)
54 {
55 l=(int)fabs(_l);
56 sprintf(format, "%%%d.%df", figs+l+2, figs+l);
57 }
58 else
59 {
60 l=(int)_l+1;
61 if(figs<=l) sprintf(format, "%%.0f");
62 else sprintf(format, "%%%d.%df", figs+1, figs-l);
63 }
64 printf(format, val);
65}
66
DRC993bf0e2011-02-15 21:57:26 +000067// Decompression test
68int decomptest(unsigned char *srcbuf, unsigned char **jpegbuf,
69 unsigned long *comptilesize, unsigned char *rgbbuf, int w, int h,
70 int jpegsub, int qual, char *filename, int tilesizex, int tilesizey)
71{
72 char tempstr[1024], qualstr[5]="\0";
73 FILE *outfile=NULL; tjhandle hnd=NULL;
74 int flags=(forcemmx?TJ_FORCEMMX:0)|(forcesse?TJ_FORCESSE:0)
75 |(forcesse2?TJ_FORCESSE2:0)|(forcesse3?TJ_FORCESSE3:0)
76 |(fastupsample?TJ_FASTUPSAMPLE:0);
77 int i, j, ITER, rgbbufalloc=0;
78 double start, elapsed;
79 int ps=_ps[pf];
80 int pitch=w*ps;
81 int hsf=_hsf[jpegsub], vsf=_vsf[jpegsub];
82 int pw=PAD(w, hsf), ph=PAD(h, vsf);
83 int cw=pw/hsf, ch=ph/vsf;
84 int ypitch=PAD(pw, 4), uvpitch=PAD(cw, 4);
85 int yuvsize=ypitch*ph + (jpegsub==TJ_GRAYSCALE? 0:uvpitch*ch*2);
86
87 if(qual>0)
88 {
89 snprintf(qualstr, 5, "Q%d", qual);
90 qualstr[4]=0;
91 }
92
93 flags |= _flags[pf];
94 if(bu) flags |= TJ_BOTTOMUP;
95 if(yuv==YUVDECODE) flags |= TJ_YUV;
96 if((hnd=tjInitDecompress())==NULL)
97 _throwtj("executing tjInitDecompress()");
98
99 if(rgbbuf==NULL)
100 {
101 if((rgbbuf=(unsigned char *)malloc(max(yuvsize, pitch*h))) == NULL)
102 _throwunix("allocating image buffer");
103 rgbbufalloc=1;
104 }
105 memset(rgbbuf, 127, max(yuvsize, pitch*h)); // Grey image means decompressor did nothing
106
107 if(tjDecompress(hnd, jpegbuf[0], comptilesize[0], rgbbuf, tilesizex, pitch,
108 tilesizey, ps, flags)==-1)
109 _throwtj("executing tjDecompress()");
110 ITER=0;
111 start=rrtime();
112 do
113 {
114 int tilen=0;
115 for(i=0; i<h; i+=tilesizey)
116 {
117 for(j=0; j<w; j+=tilesizex)
118 {
119 int tempw=min(tilesizex, w-j), temph=min(tilesizey, h-i);
120 if(tjDecompress(hnd, jpegbuf[tilen], comptilesize[tilen],
121 &rgbbuf[pitch*i+ps*j], tempw, pitch, temph, ps, flags)==-1)
122 _throwtj("executing tjDecompress()");
123 tilen++;
124 }
125 }
126 ITER++;
127 } while((elapsed=rrtime()-start)<5.);
128 if(tjDestroy(hnd)==-1) _throwtj("executing tjDestroy()");
129 hnd=NULL;
130 if(quiet)
131 {
132 printsigfig((double)(w*h)/1000000.*(double)ITER/elapsed, 4);
133 printf("\n");
134 }
135 else
136 {
137 printf("D--> Frame rate: %f fps\n", (double)ITER/elapsed);
138 printf(" Dest. throughput: %f Megapixels/sec\n",
139 (double)(w*h)/1000000.*(double)ITER/elapsed);
140 }
141 if(yuv==YUVDECODE)
142 {
143 sprintf(tempstr, "%s_%s%s.yuv", filename, _subnames[jpegsub], qualstr);
144 if((outfile=fopen(tempstr, "wb"))==NULL)
145 _throwunix("opening YUV image for output");
146 if(fwrite(rgbbuf, yuvsize, 1, outfile)!=1)
147 _throwunix("writing YUV image");
148 fclose(outfile); outfile=NULL;
149 }
150 else
151 {
152 if(tilesizex==w && tilesizey==h)
DRCbc507f62011-02-16 01:23:48 +0000153 {
154 if(decomponly)
155 sprintf(tempstr, "%s_full.%s", filename, useppm?"ppm":"bmp");
156 else
157 sprintf(tempstr, "%s_%s%s_full.%s", filename, _subnames[jpegsub],
158 qualstr, useppm?"ppm":"bmp");
159 }
DRC993bf0e2011-02-15 21:57:26 +0000160 else sprintf(tempstr, "%s_%s%s_%dx%d.%s", filename, _subnames[jpegsub],
161 qualstr, tilesizex, tilesizey, useppm?"ppm":"bmp");
162 if(savebmp(tempstr, rgbbuf, w, h, pf, pitch, bu)==-1)
163 _throwbmp("saving bitmap");
164 sprintf(strrchr(tempstr, '.'), "-err.%s", useppm?"ppm":"bmp");
165 if(srcbuf)
166 {
167 if(!quiet)
168 printf("Computing compression error and saving to %s.\n", tempstr);
169 if(jpegsub==TJ_GRAYSCALE)
170 {
171 for(j=0; j<h; j++)
172 {
173 for(i=0; i<w*ps; i+=ps)
174 {
175 int y=(int)((double)srcbuf[w*ps*j+i+_rindex[pf]]*0.299
176 + (double)srcbuf[w*ps*j+i+_gindex[pf]]*0.587
177 + (double)srcbuf[w*ps*j+i+_bindex[pf]]*0.114 + 0.5);
178 if(y>255) y=255; if(y<0) y=0;
179 rgbbuf[pitch*j+i+_rindex[pf]]=abs(rgbbuf[pitch*j+i+_rindex[pf]]-y);
180 rgbbuf[pitch*j+i+_gindex[pf]]=abs(rgbbuf[pitch*j+i+_gindex[pf]]-y);
181 rgbbuf[pitch*j+i+_bindex[pf]]=abs(rgbbuf[pitch*j+i+_bindex[pf]]-y);
182 }
183 }
184 }
185 else
186 {
187 for(j=0; j<h; j++) for(i=0; i<w*ps; i++)
188 rgbbuf[pitch*j+i]=abs(rgbbuf[pitch*j+i]-srcbuf[w*ps*j+i]);
189 }
190 if(savebmp(tempstr, rgbbuf, w, h, pf, pitch, bu)==-1)
191 _throwbmp("saving bitmap");
192 }
193 }
194
195 if(hnd) {tjDestroy(hnd); hnd=NULL;}
196 if(rgbbuf && rgbbufalloc) {free(rgbbuf); rgbbuf=NULL;}
197 return 0;
198
199 bailout:
200 if(outfile) {fclose(outfile); outfile=NULL;}
201 if(hnd) {tjDestroy(hnd); hnd=NULL;}
202 if(rgbbuf && rgbbufalloc) {free(rgbbuf); rgbbuf=NULL;}
203 return -1;
204}
205
206void dotest(unsigned char *srcbuf, int w, int h, int jpegsub, int qual,
207 char *filename)
DRC2e7b76b2009-04-03 12:04:24 +0000208{
209 char tempstr[1024];
DRC9e17f7d2010-12-10 04:59:13 +0000210 FILE *outfile=NULL; tjhandle hnd;
DRC2e7b76b2009-04-03 12:04:24 +0000211 unsigned char **jpegbuf=NULL, *rgbbuf=NULL;
DRC2e4d0442011-02-08 01:18:37 +0000212 double start, elapsed;
DRC2e7b76b2009-04-03 12:04:24 +0000213 int jpgbufsize=0, i, j, tilesizex, tilesizey, numtilesx, numtilesy, ITER;
214 unsigned long *comptilesize=NULL;
215 int flags=(forcemmx?TJ_FORCEMMX:0)|(forcesse?TJ_FORCESSE:0)
DRC61e51f92009-04-05 21:53:20 +0000216 |(forcesse2?TJ_FORCESSE2:0)|(forcesse3?TJ_FORCESSE3:0)
217 |(fastupsample?TJ_FASTUPSAMPLE:0);
DRC2e4d0442011-02-08 01:18:37 +0000218 int ps=_ps[pf], tilen;
DRC9e17f7d2010-12-10 04:59:13 +0000219 int pitch=w*ps, yuvsize;
220 int hsf=_hsf[jpegsub], vsf=_vsf[jpegsub];
DRCf9cf5c72010-12-10 10:58:49 +0000221 int pw=PAD(w, hsf), ph=PAD(h, vsf);
222 int cw=pw/hsf, ch=ph/vsf;
223 int ypitch=PAD(pw, 4), uvpitch=PAD(cw, 4);
DRC2e7b76b2009-04-03 12:04:24 +0000224
225 flags |= _flags[pf];
226 if(bu) flags |= TJ_BOTTOMUP;
DRC9e17f7d2010-12-10 04:59:13 +0000227 if(yuv==YUVENCODE) flags |= TJ_YUV;
DRC2e7b76b2009-04-03 12:04:24 +0000228
DRCf9cf5c72010-12-10 10:58:49 +0000229 yuvsize=ypitch*ph + (jpegsub==TJ_GRAYSCALE? 0:uvpitch*ch*2);
DRC9e17f7d2010-12-10 04:59:13 +0000230 if((rgbbuf=(unsigned char *)malloc(max(yuvsize, pitch*h))) == NULL)
DRCe8ce2e02010-11-12 10:14:11 +0000231 _throwunix("allocating image buffer");
DRC2e7b76b2009-04-03 12:04:24 +0000232
DRCfbb67472010-11-24 04:02:37 +0000233 if(!quiet)
234 {
DRC9e17f7d2010-12-10 04:59:13 +0000235 if(yuv==YUVENCODE)
DRCfbb67472010-11-24 04:02:37 +0000236 printf("\n>>>>> %s (%s) <--> YUV %s <<<<<\n", _pfname[pf],
237 bu?"Bottom-up":"Top-down", _subnamel[jpegsub]);
238 else
239 printf("\n>>>>> %s (%s) <--> JPEG %s Q%d <<<<<\n", _pfname[pf],
240 bu?"Bottom-up":"Top-down", _subnamel[jpegsub], qual);
241 }
DRC9e17f7d2010-12-10 04:59:13 +0000242 if(yuv==YUVDECODE) dotile=0;
DRC2e7b76b2009-04-03 12:04:24 +0000243 if(dotile) {tilesizex=tilesizey=4;} else {tilesizex=w; tilesizey=h;}
244
245 do
246 {
247 tilesizex*=2; if(tilesizex>w) tilesizex=w;
248 tilesizey*=2; if(tilesizey>h) tilesizey=h;
249 numtilesx=(w+tilesizex-1)/tilesizex;
250 numtilesy=(h+tilesizey-1)/tilesizey;
251 if((comptilesize=(unsigned long *)malloc(sizeof(unsigned long)*numtilesx*numtilesy)) == NULL
252 || (jpegbuf=(unsigned char **)malloc(sizeof(unsigned char *)*numtilesx*numtilesy)) == NULL)
DRCe8ce2e02010-11-12 10:14:11 +0000253 _throwunix("allocating image buffers");
DRC2e7b76b2009-04-03 12:04:24 +0000254 memset(jpegbuf, 0, sizeof(unsigned char *)*numtilesx*numtilesy);
255 for(i=0; i<numtilesx*numtilesy; i++)
256 {
257 if((jpegbuf[i]=(unsigned char *)malloc(TJBUFSIZE(tilesizex, tilesizey))) == NULL)
DRCe8ce2e02010-11-12 10:14:11 +0000258 _throwunix("allocating image buffers");
DRC2e7b76b2009-04-03 12:04:24 +0000259 }
260
261 // Compression test
262 if(quiet) printf("%s\t%s\t%s\t%d\t", _pfname[pf], bu?"BU":"TD",
263 _subnamel[jpegsub], qual);
264 for(i=0; i<h; i++) memcpy(&rgbbuf[pitch*i], &srcbuf[w*ps*i], w*ps);
265 if((hnd=tjInitCompress())==NULL)
DRCe8ce2e02010-11-12 10:14:11 +0000266 _throwtj("executing tjInitCompress()");
267 if(tjCompress(hnd, rgbbuf, tilesizex, pitch, tilesizey, ps,
268 jpegbuf[0], &comptilesize[0], jpegsub, qual, flags)==-1)
269 _throwtj("executing tjCompress()");
DRC2e7b76b2009-04-03 12:04:24 +0000270 ITER=0;
DRC2e4d0442011-02-08 01:18:37 +0000271 start=rrtime();
DRC2e7b76b2009-04-03 12:04:24 +0000272 do
273 {
DRC2e4d0442011-02-08 01:18:37 +0000274 jpgbufsize=0; tilen=0;
DRC2e7b76b2009-04-03 12:04:24 +0000275 for(i=0; i<h; i+=tilesizey)
276 {
277 for(j=0; j<w; j+=tilesizex)
278 {
279 int tempw=min(tilesizex, w-j), temph=min(tilesizey, h-i);
DRCe8ce2e02010-11-12 10:14:11 +0000280 if(tjCompress(hnd, &rgbbuf[pitch*i+j*ps], tempw, pitch,
DRC2e7b76b2009-04-03 12:04:24 +0000281 temph, ps, jpegbuf[tilen], &comptilesize[tilen], jpegsub, qual,
DRCe8ce2e02010-11-12 10:14:11 +0000282 flags)==-1)
283 _throwtj("executing tjCompress()");
DRC2e7b76b2009-04-03 12:04:24 +0000284 jpgbufsize+=comptilesize[tilen];
285 tilen++;
286 }
287 }
288 ITER++;
DRC2e4d0442011-02-08 01:18:37 +0000289 } while((elapsed=rrtime()-start)<5.);
DRCe8ce2e02010-11-12 10:14:11 +0000290 if(tjDestroy(hnd)==-1) _throwtj("executing tjDestroy()");
291 hnd=NULL;
DRC2e7b76b2009-04-03 12:04:24 +0000292 if(quiet)
293 {
294 if(tilesizex==w && tilesizey==h) printf("Full \t");
295 else printf("%-4d %-4d\t", tilesizex, tilesizey);
296 printsigfig((double)(w*h)/1000000.*(double)ITER/elapsed, 4);
297 printf("\t");
298 printsigfig((double)(w*h*ps)/(double)jpgbufsize, 4);
299 printf("\t");
300 }
301 else
302 {
303 if(tilesizex==w && tilesizey==h) printf("\nFull image\n");
304 else printf("\nTile size: %d x %d\n", tilesizex, tilesizey);
305 printf("C--> Frame rate: %f fps\n", (double)ITER/elapsed);
306 printf(" Output image size: %d bytes\n", jpgbufsize);
307 printf(" Compression ratio: %f:1\n",
308 (double)(w*h*ps)/(double)jpgbufsize);
309 printf(" Source throughput: %f Megapixels/sec\n",
310 (double)(w*h)/1000000.*(double)ITER/elapsed);
311 printf(" Output bit stream: %f Megabits/sec\n",
312 (double)jpgbufsize*8./1000000.*(double)ITER/elapsed);
313 }
314 if(tilesizex==w && tilesizey==h)
315 {
DRC9e17f7d2010-12-10 04:59:13 +0000316 if(yuv==YUVENCODE)
DRCfbb67472010-11-24 04:02:37 +0000317 sprintf(tempstr, "%s_%s.yuv", filename, _subnames[jpegsub]);
318 else
319 sprintf(tempstr, "%s_%sQ%d.jpg", filename, _subnames[jpegsub], qual);
DRC2e7b76b2009-04-03 12:04:24 +0000320 if((outfile=fopen(tempstr, "wb"))==NULL)
DRCe8ce2e02010-11-12 10:14:11 +0000321 _throwunix("opening reference image");
DRC2e7b76b2009-04-03 12:04:24 +0000322 if(fwrite(jpegbuf[0], jpgbufsize, 1, outfile)!=1)
DRCe8ce2e02010-11-12 10:14:11 +0000323 _throwunix("writing reference image");
DRC9e17f7d2010-12-10 04:59:13 +0000324 fclose(outfile); outfile=NULL;
DRC2e7b76b2009-04-03 12:04:24 +0000325 if(!quiet) printf("Reference image written to %s\n", tempstr);
326 }
DRC9e17f7d2010-12-10 04:59:13 +0000327 if(yuv==YUVENCODE) goto bailout;
DRC2e7b76b2009-04-03 12:04:24 +0000328
329 // Decompression test
DRC993bf0e2011-02-15 21:57:26 +0000330 if(decomptest(srcbuf, jpegbuf, comptilesize, rgbbuf, w, h, jpegsub, qual,
331 filename, tilesizex, tilesizey)==-1)
332 goto bailout;
DRC2e7b76b2009-04-03 12:04:24 +0000333
334 // Cleanup
DRC9e17f7d2010-12-10 04:59:13 +0000335 if(outfile) {fclose(outfile); outfile=NULL;}
DRC2e7b76b2009-04-03 12:04:24 +0000336 if(jpegbuf)
337 {
338 for(i=0; i<numtilesx*numtilesy; i++)
339 {if(jpegbuf[i]) free(jpegbuf[i]); jpegbuf[i]=NULL;}
340 free(jpegbuf); jpegbuf=NULL;
341 }
342 if(comptilesize) {free(comptilesize); comptilesize=NULL;}
343 } while(tilesizex<w || tilesizey<h);
344
345 if(rgbbuf) {free(rgbbuf); rgbbuf=NULL;}
346 return;
347
348 bailout:
DRC9e17f7d2010-12-10 04:59:13 +0000349 if(outfile) {fclose(outfile); outfile=NULL;}
DRC2e7b76b2009-04-03 12:04:24 +0000350 if(jpegbuf)
351 {
352 for(i=0; i<numtilesx*numtilesy; i++)
353 {if(jpegbuf[i]) free(jpegbuf[i]); jpegbuf[i]=NULL;}
354 free(jpegbuf); jpegbuf=NULL;
355 }
356 if(comptilesize) {free(comptilesize); comptilesize=NULL;}
357 if(rgbbuf) {free(rgbbuf); rgbbuf=NULL;}
DRCe8ce2e02010-11-12 10:14:11 +0000358 if(hnd) {tjDestroy(hnd); hnd=NULL;}
DRC2e7b76b2009-04-03 12:04:24 +0000359 return;
360}
361
362
DRC993bf0e2011-02-15 21:57:26 +0000363void dodecomptest(char *filename)
DRCe8ce2e02010-11-12 10:14:11 +0000364{
DRC993bf0e2011-02-15 21:57:26 +0000365 FILE *file=NULL; tjhandle hnd=NULL;
366 unsigned char *jpegbuf=NULL;
367 int w=0, h=0, jpegsub=-1;
DRCe8ce2e02010-11-12 10:14:11 +0000368 unsigned long jpgbufsize=0;
DRC61c15bd2010-11-13 05:31:25 +0000369 char *temp=NULL;
DRCe8ce2e02010-11-12 10:14:11 +0000370
DRC993bf0e2011-02-15 21:57:26 +0000371 useppm=1;
DRCe8ce2e02010-11-12 10:14:11 +0000372
373 if((file=fopen(filename, "rb"))==NULL)
374 _throwunix("opening file");
DRC61c15bd2010-11-13 05:31:25 +0000375 if(fseek(file, 0, SEEK_END)<0 || (jpgbufsize=ftell(file))<0)
DRCe8ce2e02010-11-12 10:14:11 +0000376 _throwunix("determining file size");
DRC61c15bd2010-11-13 05:31:25 +0000377 if((jpegbuf=(unsigned char *)malloc(jpgbufsize))==NULL)
DRCe8ce2e02010-11-12 10:14:11 +0000378 _throwunix("allocating memory");
379 if(fseek(file, 0, SEEK_SET)<0)
380 _throwunix("setting file position");
DRC61c15bd2010-11-13 05:31:25 +0000381 if(fread(jpegbuf, jpgbufsize, 1, file)<1)
DRCe8ce2e02010-11-12 10:14:11 +0000382 _throwunix("reading JPEG data");
DRCcad1cfe2010-12-14 01:22:00 +0000383 fclose(file); file=NULL;
DRCe8ce2e02010-11-12 10:14:11 +0000384
385 temp=strrchr(filename, '.');
386 if(temp!=NULL) *temp='\0';
387
DRC72b0f2b2011-02-15 21:57:50 +0000388 if((hnd=tjInitDecompress())==NULL) _throwtj("executing tjInitDecompress()");
DRCcad1cfe2010-12-14 01:22:00 +0000389 if(tjDecompressHeader2(hnd, jpegbuf, jpgbufsize, &w, &h, &jpegsub)==-1)
390 _throwtj("executing tjDecompressHeader2()");
DRC993bf0e2011-02-15 21:57:26 +0000391 if(tjDestroy(hnd)==-1) _throwtj("executing tjDestroy()");
392 hnd=NULL;
DRCe8ce2e02010-11-12 10:14:11 +0000393
394 if(quiet)
395 {
396 printf("All performance values in Mpixels/sec\n\n");
DRC993bf0e2011-02-15 21:57:26 +0000397 printf("Bitmap\tBitmap\tJPEG\tImage Size\tDecomp\n"),
398 printf("Format\tOrder\tFormat\t X Y \tPerf\n\n");
399 printf("%s\t%s\t%s\t%-4d %-4d\t", _pfname[pf], bu?"BU":"TD",
400 _subnamel[jpegsub], w, h);
DRCe8ce2e02010-11-12 10:14:11 +0000401 }
DRC993bf0e2011-02-15 21:57:26 +0000402 else
DRCe8ce2e02010-11-12 10:14:11 +0000403 {
DRCcad1cfe2010-12-14 01:22:00 +0000404 if(yuv==YUVDECODE)
405 printf("\n>>>>> JPEG --> YUV %s <<<<<\n", _subnamel[jpegsub]);
406 else
407 printf("\n>>>>> JPEG --> %s (%s) <<<<<\n", _pfname[pf],
408 bu?"Bottom-up":"Top-down");
DRCe8ce2e02010-11-12 10:14:11 +0000409 printf("\nImage size: %d x %d\n", w, h);
410 }
411
DRC993bf0e2011-02-15 21:57:26 +0000412 decomptest(NULL, &jpegbuf, &jpgbufsize, NULL, w, h, jpegsub, 0, filename, w,
413 h);
DRCe8ce2e02010-11-12 10:14:11 +0000414
415 bailout:
DRCcad1cfe2010-12-14 01:22:00 +0000416 if(file) {fclose(file); file=NULL;}
DRCe8ce2e02010-11-12 10:14:11 +0000417 if(jpegbuf) {free(jpegbuf); jpegbuf=NULL;}
DRCe8ce2e02010-11-12 10:14:11 +0000418 if(hnd) {tjDestroy(hnd); hnd=NULL;}
419 return;
420}
421
422
423void usage(char *progname)
424{
DRCe89bbae2010-11-12 10:18:08 +0000425 printf("USAGE: %s <Inputfile (BMP|PPM))> <%% Quality>\n", progname);
426 printf(" %s <Inputfile (JPG))>\n\n", progname);
DRCe8ce2e02010-11-12 10:14:11 +0000427 printf(" [-tile]\n");
428 printf(" Test performance of the codec when the image is encoded\n");
429 printf(" as separate tiles of varying sizes.\n\n");
430 printf(" [-forcemmx] [-forcesse] [-forcesse2] [-forcesse3]\n");
431 printf(" Force MMX, SSE, or SSE2 code paths in Intel codec\n\n");
432 printf(" [-rgb | -bgr | -rgba | -bgra | -abgr | -argb]\n");
433 printf(" Test the specified color conversion path in the codec (default: BGR)\n\n");
434 printf(" [-fastupsample]\n");
435 printf(" Use fast, inaccurate upsampling code to perform 4:2:2 and 4:2:0\n");
436 printf(" YUV decoding in libjpeg decompressor\n\n");
437 printf(" [-quiet]\n");
DRCac08ef62010-12-09 10:01:57 +0000438 printf(" Output in tabular rather than verbose format\n\n");
DRC9e17f7d2010-12-10 04:59:13 +0000439 printf(" [-yuvencode]\n");
DRCfbb67472010-11-24 04:02:37 +0000440 printf(" Encode RGB input as planar YUV rather than compressing as JPEG\n\n");
DRC9e17f7d2010-12-10 04:59:13 +0000441 printf(" [-yuvdecode]\n");
442 printf(" Decode JPEG image to planar YUV rather than RGB\n\n");
DRCe8ce2e02010-11-12 10:14:11 +0000443 printf(" NOTE: If the quality is specified as a range, i.e. 90-100, a separate\n");
444 printf(" test will be performed for all quality values in the range.\n");
445 exit(1);
446}
447
448
DRC2e7b76b2009-04-03 12:04:24 +0000449int main(int argc, char *argv[])
450{
DRC993bf0e2011-02-15 21:57:26 +0000451 unsigned char *bmpbuf=NULL; int w, h, i;
452 int qual, hiqual=-1; char *temp;
453 int minarg=2;
DRC2e7b76b2009-04-03 12:04:24 +0000454
455 printf("\n");
456
DRCe8ce2e02010-11-12 10:14:11 +0000457 if(argc<minarg) usage(argv[0]);
DRC2e7b76b2009-04-03 12:04:24 +0000458
DRCe8ce2e02010-11-12 10:14:11 +0000459 temp=strrchr(argv[1], '.');
460 if(temp!=NULL)
DRC2e7b76b2009-04-03 12:04:24 +0000461 {
DRCe8ce2e02010-11-12 10:14:11 +0000462 if(!stricmp(temp, ".ppm")) useppm=1;
463 if(!stricmp(temp, ".jpg") || !stricmp(temp, ".jpeg")) decomponly=1;
464 }
465
DRCac08ef62010-12-09 10:01:57 +0000466 if(argc>minarg)
467 {
468 for(i=minarg; i<argc; i++)
469 {
DRC9e17f7d2010-12-10 04:59:13 +0000470 if(!stricmp(argv[i], "-yuvencode"))
DRCac08ef62010-12-09 10:01:57 +0000471 {
472 printf("Testing YUV planar encoding\n");
DRC9e17f7d2010-12-10 04:59:13 +0000473 yuv=YUVENCODE; hiqual=qual=100;
474 }
475 if(!stricmp(argv[i], "-yuvdecode"))
476 {
477 printf("Testing YUV planar decoding\n");
478 yuv=YUVDECODE;
DRCac08ef62010-12-09 10:01:57 +0000479 }
480 }
481 }
482
DRC9e17f7d2010-12-10 04:59:13 +0000483 if(!decomponly && yuv!=YUVENCODE)
DRCe8ce2e02010-11-12 10:14:11 +0000484 {
485 minarg=3;
486 if(argc<minarg) usage(argv[0]);
487 if((qual=atoi(argv[2]))<1 || qual>100)
488 {
489 puts("ERROR: Quality must be between 1 and 100.");
490 exit(1);
491 }
492 if((temp=strchr(argv[2], '-'))!=NULL && strlen(temp)>1
493 && sscanf(&temp[1], "%d", &hiqual)==1 && hiqual>qual && hiqual>=1
494 && hiqual<=100) {}
495 else hiqual=qual;
496 }
497
498 if(argc>minarg)
499 {
500 for(i=minarg; i<argc; i++)
DRC2e7b76b2009-04-03 12:04:24 +0000501 {
502 if(!stricmp(argv[i], "-tile")) dotile=1;
503 if(!stricmp(argv[i], "-forcesse3"))
504 {
DRC0c6a2712010-02-22 08:34:44 +0000505 printf("Using SSE3 code\n");
DRC2e7b76b2009-04-03 12:04:24 +0000506 forcesse3=1;
507 }
508 if(!stricmp(argv[i], "-forcesse2"))
509 {
DRC0c6a2712010-02-22 08:34:44 +0000510 printf("Using SSE2 code\n");
DRC2e7b76b2009-04-03 12:04:24 +0000511 forcesse2=1;
512 }
513 if(!stricmp(argv[i], "-forcesse"))
514 {
DRC0c6a2712010-02-22 08:34:44 +0000515 printf("Using SSE code\n");
DRC2e7b76b2009-04-03 12:04:24 +0000516 forcesse=1;
517 }
518 if(!stricmp(argv[i], "-forcemmx"))
519 {
DRC0c6a2712010-02-22 08:34:44 +0000520 printf("Using MMX code\n");
DRC2e7b76b2009-04-03 12:04:24 +0000521 forcemmx=1;
522 }
DRC61e51f92009-04-05 21:53:20 +0000523 if(!stricmp(argv[i], "-fastupsample"))
524 {
525 printf("Using fast upsampling code\n");
526 fastupsample=1;
527 }
DRC2e7b76b2009-04-03 12:04:24 +0000528 if(!stricmp(argv[i], "-rgb")) pf=BMP_RGB;
529 if(!stricmp(argv[i], "-rgba")) pf=BMP_RGBA;
530 if(!stricmp(argv[i], "-bgr")) pf=BMP_BGR;
531 if(!stricmp(argv[i], "-bgra")) pf=BMP_BGRA;
532 if(!stricmp(argv[i], "-abgr")) pf=BMP_ABGR;
533 if(!stricmp(argv[i], "-argb")) pf=BMP_ARGB;
534 if(!stricmp(argv[i], "-bottomup")) bu=1;
535 if(!stricmp(argv[i], "-quiet")) quiet=1;
536 }
537 }
538
DRCe8ce2e02010-11-12 10:14:11 +0000539 if(!decomponly)
DRC2e7b76b2009-04-03 12:04:24 +0000540 {
DRCe8ce2e02010-11-12 10:14:11 +0000541 if(loadbmp(argv[1], &bmpbuf, &w, &h, pf, 1, bu)==-1)
542 _throwbmp("loading bitmap");
543 temp=strrchr(argv[1], '.');
544 if(temp!=NULL) *temp='\0';
DRC2e7b76b2009-04-03 12:04:24 +0000545 }
546
DRCe8ce2e02010-11-12 10:14:11 +0000547 if(quiet && !decomponly)
DRC2e7b76b2009-04-03 12:04:24 +0000548 {
549 printf("All performance values in Mpixels/sec\n\n");
550 printf("Bitmap\tBitmap\tJPEG\tJPEG\tTile Size\tCompr\tCompr\tDecomp\n");
551 printf("Format\tOrder\tFormat\tQual\t X Y \tPerf \tRatio\tPerf\n\n");
552 }
553
DRCe8ce2e02010-11-12 10:14:11 +0000554 if(decomponly)
555 {
DRC993bf0e2011-02-15 21:57:26 +0000556 dodecomptest(argv[1]);
DRCe8ce2e02010-11-12 10:14:11 +0000557 goto bailout;
558 }
DRC2e7b76b2009-04-03 12:04:24 +0000559 for(i=hiqual; i>=qual; i--)
DRC993bf0e2011-02-15 21:57:26 +0000560 dotest(bmpbuf, w, h, TJ_GRAYSCALE, i, argv[1]);
DRC2e7b76b2009-04-03 12:04:24 +0000561 if(quiet) printf("\n");
562 for(i=hiqual; i>=qual; i--)
DRC993bf0e2011-02-15 21:57:26 +0000563 dotest(bmpbuf, w, h, TJ_420, i, argv[1]);
DRC2e7b76b2009-04-03 12:04:24 +0000564 if(quiet) printf("\n");
565 for(i=hiqual; i>=qual; i--)
DRC993bf0e2011-02-15 21:57:26 +0000566 dotest(bmpbuf, w, h, TJ_422, i, argv[1]);
DRC2e7b76b2009-04-03 12:04:24 +0000567 if(quiet) printf("\n");
568 for(i=hiqual; i>=qual; i--)
DRC993bf0e2011-02-15 21:57:26 +0000569 dotest(bmpbuf, w, h, TJ_444, i, argv[1]);
DRC2e7b76b2009-04-03 12:04:24 +0000570
DRCe8ce2e02010-11-12 10:14:11 +0000571 bailout:
DRC2e7b76b2009-04-03 12:04:24 +0000572 if(bmpbuf) free(bmpbuf);
573 return 0;
574}