2
* Copyright (C)2009-2012 D. R. Commander. All Rights Reserved.
4
* Redistribution and use in source and binary forms, with or without
5
* modification, are permitted provided that the following conditions are met:
7
* - Redistributions of source code must retain the above copyright notice,
8
* this list of conditions and the following disclaimer.
9
* - Redistributions in binary form must reproduce the above copyright notice,
10
* this list of conditions and the following disclaimer in the documentation
11
* and/or other materials provided with the distribution.
12
* - Neither the name of the libjpeg-turbo Project nor the names of its
13
* contributors may be used to endorse or promote products derived from this
14
* software without specific prior written permission.
16
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS",
17
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
20
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26
* POSSIBILITY OF SUCH DAMAGE.
30
import java.awt.image.*;
31
import javax.imageio.*;
33
import org.libjpegturbo.turbojpeg.*;
37
static final int YUVENCODE = 1;
38
static final int YUVDECODE = 2;
40
static int flags = 0, yuv = 0, quiet = 0, pf = TJ.PF_BGR;
41
static boolean decompOnly, doTile;
43
static final String[] pixFormatStr = {
44
"RGB", "BGR", "RGBX", "BGRX", "XBGR", "XRGB", "GRAY"
47
static final String[] subNameLong = {
48
"4:4:4", "4:2:2", "4:2:0", "GRAY", "4:4:0"
51
static final String[] subName = {
52
"444", "422", "420", "GRAY", "440"
55
static TJScalingFactor sf;
56
static int xformOp = TJTransform.OP_NONE, xformOpt = 0;
57
static double benchTime = 5.0;
60
static final double getTime() {
61
return (double)System.nanoTime() / 1.0e9;
65
static String sigFig(double val, int figs) {
67
int digitsAfterDecimal = figs - (int)Math.ceil(Math.log10(Math.abs(val)));
68
if (digitsAfterDecimal < 1)
69
format = new String("%.0f");
71
format = new String("%." + digitsAfterDecimal + "f");
72
return String.format(format, val);
76
static byte[] loadImage(String fileName, int[] w, int[] h, int pixelFormat)
78
BufferedImage img = ImageIO.read(new File(fileName));
80
throw new Exception("Could not read " + fileName);
81
w[0] = img.getWidth();
82
h[0] = img.getHeight();
83
int[] rgb = img.getRGB(0, 0, w[0], h[0], null, 0, w[0]);
84
int ps = TJ.getPixelSize(pixelFormat);
85
int rindex = TJ.getRedOffset(pixelFormat);
86
int gindex = TJ.getGreenOffset(pixelFormat);
87
int bindex = TJ.getBlueOffset(pixelFormat);
88
byte[] dstBuf = new byte[w[0] * h[0] * ps];
89
int pixels = w[0] * h[0], dstPtr = 0, rgbPtr = 0;
90
while (pixels-- > 0) {
91
dstBuf[dstPtr + rindex] = (byte)((rgb[rgbPtr] >> 16) & 0xff);
92
dstBuf[dstPtr + gindex] = (byte)((rgb[rgbPtr] >> 8) & 0xff);
93
dstBuf[dstPtr + bindex] = (byte)(rgb[rgbPtr] & 0xff);
101
static void saveImage(String fileName, byte[] srcBuf, int w, int h,
102
int pixelFormat) throws Exception {
103
BufferedImage img = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
104
int pixels = w * h, srcPtr = 0;
105
int ps = TJ.getPixelSize(pixelFormat);
106
int rindex = TJ.getRedOffset(pixelFormat);
107
int gindex = TJ.getGreenOffset(pixelFormat);
108
int bindex = TJ.getBlueOffset(pixelFormat);
109
for (int y = 0; y < h; y++) {
110
for (int x = 0; x < w; x++, srcPtr += ps) {
111
int pixel = (srcBuf[srcPtr + rindex] & 0xff) << 16 |
112
(srcBuf[srcPtr + gindex] & 0xff) << 8 |
113
(srcBuf[srcPtr + bindex] & 0xff);
114
img.setRGB(x, y, pixel);
117
ImageIO.write(img, "bmp", new File(fileName));
121
/* Decompression test */
122
static void decompTest(byte[] srcBuf, byte[][] jpegBuf, int[] jpegSize,
123
byte[] dstBuf, int w, int h, int subsamp,
124
int jpegQual, String fileName, int tilew, int tileh)
126
String qualStr = new String(""), sizeStr, tempStr;
128
double start, elapsed;
129
int ps = TJ.getPixelSize(pf), i;
130
int yuvSize = TJ.bufSizeYUV(w, h, subsamp), bufsize;
131
int scaledw = (yuv == YUVDECODE) ? w : sf.getScaled(w);
132
int scaledh = (yuv == YUVDECODE) ? h : sf.getScaled(h);
133
int pitch = scaledw * ps;
136
qualStr = new String("_Q" + jpegQual);
138
tjd = new TJDecompressor();
140
int bufSize = (yuv == YUVDECODE ? yuvSize : pitch * scaledh);
142
dstBuf = new byte[bufSize];
144
/* Set the destination buffer to gray so we know whether the decompressor
145
attempted to write to it */
146
Arrays.fill(dstBuf, (byte)127);
148
/* Execute once to preload cache */
149
tjd.setJPEGImage(jpegBuf[0], jpegSize[0]);
150
if (yuv == YUVDECODE)
151
tjd.decompressToYUV(dstBuf, flags);
153
tjd.decompress(dstBuf, scaledw, pitch, scaledh, pf, flags);
156
for (i = 0, start = getTime(); (elapsed = getTime() - start) < benchTime;
159
if (yuv == YUVDECODE)
160
tjd.decompressToYUV(dstBuf, flags);
162
for (int y = 0; y < h; y += tileh) {
163
for (int x = 0; x < w; x += tilew, tile++) {
164
int width = doTile ? Math.min(tilew, w - x) : scaledw;
165
int height = doTile ? Math.min(tileh, h - y) : scaledh;
166
tjd.setJPEGImage(jpegBuf[tile], jpegSize[tile]);
167
tjd.decompress(dstBuf, x, y, width, pitch, height, pf, flags);
178
sigFig((double)(w * h) / 1000000. * (double)i / elapsed, 4));
180
System.out.format("D--> Frame rate: %f fps\n",
181
(double)i / elapsed);
182
System.out.format(" Dest. throughput: %f Megapixels/sec\n",
183
(double)(w * h) / 1000000. * (double)i / elapsed);
186
if (yuv == YUVDECODE) {
187
tempStr = fileName + "_" + subName[subsamp] + qualStr + ".yuv";
188
FileOutputStream fos = new FileOutputStream(tempStr);
189
fos.write(dstBuf, 0, yuvSize);
192
if (sf.getNum() != 1 || sf.getDenom() != 1)
193
sizeStr = new String(sf.getNum() + "_" + sf.getDenom());
194
else if (tilew != w || tileh != h)
195
sizeStr = new String(tilew + "x" + tileh);
197
sizeStr = new String("full");
199
tempStr = new String(fileName + "_" + sizeStr + ".bmp");
201
tempStr = new String(fileName + "_" + subName[subsamp] + qualStr +
202
"_" + sizeStr + ".bmp");
203
saveImage(tempStr, dstBuf, scaledw, scaledh, pf);
204
int ndx = tempStr.indexOf('.');
205
tempStr = new String(tempStr.substring(0, ndx) + "-err.bmp");
206
if (srcBuf != null && sf.getNum() == 1 && sf.getDenom() == 1) {
208
System.out.println("Compression error written to " + tempStr + ".");
209
if (subsamp == TJ.SAMP_GRAY) {
210
for (int y = 0, index = 0; y < h; y++, index += pitch) {
211
for (int x = 0, index2 = index; x < w; x++, index2 += ps) {
212
int rindex = index2 + TJ.getRedOffset(pf);
213
int gindex = index2 + TJ.getGreenOffset(pf);
214
int bindex = index2 + TJ.getBlueOffset(pf);
215
int lum = (int)((double)(srcBuf[rindex] & 0xff) * 0.299 +
216
(double)(srcBuf[gindex] & 0xff) * 0.587 +
217
(double)(srcBuf[bindex] & 0xff) * 0.114 + 0.5);
218
if (lum > 255) lum = 255;
219
if (lum < 0) lum = 0;
220
dstBuf[rindex] = (byte)Math.abs((dstBuf[rindex] & 0xff) - lum);
221
dstBuf[gindex] = (byte)Math.abs((dstBuf[gindex] & 0xff) - lum);
222
dstBuf[bindex] = (byte)Math.abs((dstBuf[bindex] & 0xff) - lum);
226
for (int y = 0; y < h; y++)
227
for (int x = 0; x < w * ps; x++)
228
dstBuf[pitch * y + x] =
229
(byte)Math.abs((dstBuf[pitch * y + x] & 0xff) -
230
(srcBuf[pitch * y + x] & 0xff));
232
saveImage(tempStr, dstBuf, w, h, pf);
238
static void doTestYUV(byte[] srcBuf, int w, int h, int subsamp,
239
String fileName) throws Exception {
242
double start, elapsed;
243
int ps = TJ.getPixelSize(pf), i;
246
yuvSize = TJ.bufSizeYUV(w, h, subsamp);
247
dstBuf = new byte[yuvSize];
250
System.out.format(">>>>> %s (%s) <--> YUV %s <<<<<\n",
252
(flags & TJ.FLAG_BOTTOMUP) != 0 ? "Bottom-up" : "Top-down",
253
subNameLong[subsamp]);
256
System.out.format("%s\t%s\t%s\tN/A\t", pixFormatStr[pf],
257
(flags & TJ.FLAG_BOTTOMUP) != 0 ? "BU" : "TD",
258
subNameLong[subsamp]);
260
tjc = new TJCompressor(srcBuf, w, 0, h, pf);
261
tjc.setSubsamp(subsamp);
263
/* Execute once to preload cache */
264
tjc.encodeYUV(dstBuf, flags);
267
for (i = 0, start = getTime();
268
(elapsed = getTime() - start) < benchTime; i++)
269
tjc.encodeYUV(dstBuf, flags);
272
System.out.format("%-4d %-4d\t", w, h);
274
System.out.format("%s%c%s%c",
275
sigFig((double)(w * h) / 1000000. * (double) i / elapsed, 4),
276
quiet == 2 ? '\n' : '\t',
277
sigFig((double)(w * h * ps) / (double)yuvSize, 4),
278
quiet == 2 ? '\n' : '\t');
280
System.out.format("\n%s size: %d x %d\n", "Image", w, h);
281
System.out.format("C--> Frame rate: %f fps\n",
282
(double)i / elapsed);
283
System.out.format(" Output image size: %d bytes\n", yuvSize);
284
System.out.format(" Compression ratio: %f:1\n",
285
(double)(w * h * ps) / (double)yuvSize);
286
System.out.format(" Source throughput: %f Megapixels/sec\n",
287
(double)(w * h) / 1000000. * (double)i / elapsed);
288
System.out.format(" Output bit stream: %f Megabits/sec\n",
289
(double)yuvSize * 8. / 1000000. * (double)i / elapsed);
291
String tempStr = fileName + "_" + subName[subsamp] + ".yuv";
292
FileOutputStream fos = new FileOutputStream(tempStr);
293
fos.write(dstBuf, 0, yuvSize);
296
System.out.println("Reference image written to " + tempStr);
300
static void doTest(byte[] srcBuf, int w, int h, int subsamp, int jpegQual,
301
String fileName) throws Exception {
306
double start, elapsed;
307
int totalJpegSize = 0, tilew, tileh, i;
308
int ps = TJ.getPixelSize(pf), ntilesw = 1, ntilesh = 1, pitch = w * ps;
310
if (yuv == YUVENCODE) {
311
doTestYUV(srcBuf, w, h, subsamp, fileName);
315
tmpBuf = new byte[pitch * h];
318
System.out.format(">>>>> %s (%s) <--> JPEG %s Q%d <<<<<\n",
320
(flags & TJ.FLAG_BOTTOMUP) != 0 ? "Bottom-up" : "Top-down",
321
subNameLong[subsamp], jpegQual);
323
tjc = new TJCompressor();
325
for (tilew = doTile ? 8 : w, tileh = doTile ? 8 : h; ;
326
tilew *= 2, tileh *= 2) {
331
ntilesw = (w + tilew - 1) / tilew;
332
ntilesh = (h + tileh - 1) / tileh;
334
jpegBuf = new byte[ntilesw * ntilesh][TJ.bufSize(tilew, tileh, subsamp)];
335
jpegSize = new int[ntilesw * ntilesh];
337
/* Compression test */
339
System.out.format("%s\t%s\t%s\t%d\t", pixFormatStr[pf],
340
(flags & TJ.FLAG_BOTTOMUP) != 0 ? "BU" : "TD",
341
subNameLong[subsamp], jpegQual);
342
for (i = 0; i < h; i++)
343
System.arraycopy(srcBuf, w * ps * i, tmpBuf, pitch * i, w * ps);
344
tjc.setSourceImage(srcBuf, tilew, pitch, tileh, pf);
345
tjc.setJPEGQuality(jpegQual);
346
tjc.setSubsamp(subsamp);
348
/* Execute once to preload cache */
349
tjc.compress(jpegBuf[0], flags);
352
for (i = 0, start = getTime();
353
(elapsed = getTime() - start) < benchTime; i++) {
356
for (int y = 0; y < h; y += tileh) {
357
for (int x = 0; x < w; x += tilew, tile++) {
358
int width = Math.min(tilew, w - x);
359
int height = Math.min(tileh, h - y);
360
tjc.setSourceImage(srcBuf, x, y, width, pitch, height, pf);
361
tjc.compress(jpegBuf[tile], flags);
362
jpegSize[tile] = tjc.getCompressedSize();
363
totalJpegSize += jpegSize[tile];
369
System.out.format("%-4d %-4d\t", tilew, tileh);
371
System.out.format("%s%c%s%c",
372
sigFig((double)(w * h) / 1000000. * (double) i / elapsed, 4),
373
quiet == 2 ? '\n' : '\t',
374
sigFig((double)(w * h * ps) / (double)totalJpegSize, 4),
375
quiet == 2 ? '\n' : '\t');
377
System.out.format("\n%s size: %d x %d\n", doTile ? "Tile" : "Image",
379
System.out.format("C--> Frame rate: %f fps\n",
380
(double)i / elapsed);
381
System.out.format(" Output image size: %d bytes\n",
383
System.out.format(" Compression ratio: %f:1\n",
384
(double)(w * h * ps) / (double)totalJpegSize);
385
System.out.format(" Source throughput: %f Megapixels/sec\n",
386
(double)(w * h) / 1000000. * (double)i / elapsed);
387
System.out.format(" Output bit stream: %f Megabits/sec\n",
388
(double)totalJpegSize * 8. / 1000000. * (double)i / elapsed);
390
if (tilew == w && tileh == h) {
391
String tempStr = fileName + "_" + subName[subsamp] + "_" + "Q" +
393
FileOutputStream fos = new FileOutputStream(tempStr);
394
fos.write(jpegBuf[0], 0, jpegSize[0]);
397
System.out.println("Reference image written to " + tempStr);
400
/* Decompression test */
401
decompTest(srcBuf, jpegBuf, jpegSize, tmpBuf, w, h, subsamp, jpegQual,
402
fileName, tilew, tileh);
404
for (i = 0; i < ntilesw * ntilesh; i++)
406
jpegBuf = null; jpegSize = null;
409
if (tilew == w && tileh == h) break;
414
static void doDecompTest(String fileName) throws Exception {
420
int w = 0, h = 0, subsamp = -1, _w, _h, _tilew, _tileh,
421
_ntilesw, _ntilesh, _subsamp, x, y;
422
int ntilesw = 1, ntilesh = 1;
423
double start, elapsed;
424
int ps = TJ.getPixelSize(pf), tile;
426
FileInputStream fis = new FileInputStream(fileName);
427
int srcSize = (int)fis.getChannel().size();
428
srcBuf = new byte[srcSize];
429
fis.read(srcBuf, 0, srcSize);
432
int index = fileName.indexOf('.');
434
fileName = new String(fileName.substring(0, index));
436
tjt = new TJTransformer();
438
tjt.setJPEGImage(srcBuf, srcSize);
441
subsamp = tjt.getSubsamp();
444
System.out.println("All performance values in Mpixels/sec\n");
445
System.out.format("Bitmap\tBitmap\tJPEG\t%s %s \tXform\tComp\tDecomp\n",
446
(doTile ? "Tile " : "Image"),
447
(doTile ? "Tile " : "Image"));
448
System.out.println("Format\tOrder\tSubsamp\tWidth Height\tPerf \tRatio\tPerf\n");
449
} else if (quiet == 0) {
450
System.out.format(">>>>> JPEG %s --> %s (%s) <<<<<",
451
subNameLong[subsamp], pixFormatStr[pf],
452
(flags & TJ.FLAG_BOTTOMUP) != 0 ? "Bottom-up" : "Top-down");
455
for (int tilew = doTile ? 16 : w, tileh = doTile ? 16 : h; ;
456
tilew *= 2, tileh *= 2) {
461
ntilesw = (w + tilew - 1) / tilew;
462
ntilesh = (h + tileh - 1) / tileh;
464
_w = w; _h = h; _tilew = tilew; _tileh = tileh;
466
System.out.format("\n%s size: %d x %d", (doTile ? "Tile" : "Image"),
468
if (sf.getNum() != 1 || sf.getDenom() != 1)
469
System.out.format(" --> %d x %d", sf.getScaled(_w),
471
System.out.println("");
472
} else if (quiet == 1) {
473
System.out.format("%s\t%s\t%s\t", pixFormatStr[pf],
474
(flags & TJ.FLAG_BOTTOMUP) != 0 ? "BU" : "TD",
475
subNameLong[subsamp]);
476
System.out.format("%-4d %-4d\t", tilew, tileh);
480
if (doTile || xformOp != TJTransform.OP_NONE || xformOpt != 0) {
481
if (xformOp == TJTransform.OP_TRANSPOSE ||
482
xformOp == TJTransform.OP_TRANSVERSE ||
483
xformOp == TJTransform.OP_ROT90 ||
484
xformOp == TJTransform.OP_ROT270) {
485
_w = h; _h = w; _tilew = tileh; _tileh = tilew;
488
if ((xformOpt & TJTransform.OPT_GRAY) != 0)
489
_subsamp = TJ.SAMP_GRAY;
490
if (xformOp == TJTransform.OP_HFLIP ||
491
xformOp == TJTransform.OP_ROT180)
492
_w = _w - (_w % TJ.getMCUWidth(_subsamp));
493
if (xformOp == TJTransform.OP_VFLIP ||
494
xformOp == TJTransform.OP_ROT180)
495
_h = _h - (_h % TJ.getMCUHeight(_subsamp));
496
if (xformOp == TJTransform.OP_TRANSVERSE ||
497
xformOp == TJTransform.OP_ROT90)
498
_w = _w - (_w % TJ.getMCUHeight(_subsamp));
499
if (xformOp == TJTransform.OP_TRANSVERSE ||
500
xformOp == TJTransform.OP_ROT270)
501
_h = _h - (_h % TJ.getMCUWidth(_subsamp));
502
_ntilesw = (_w + _tilew - 1) / _tilew;
503
_ntilesh = (_h + _tileh - 1) / _tileh;
505
TJTransform[] t = new TJTransform[_ntilesw * _ntilesh];
506
jpegBuf = new byte[_ntilesw * _ntilesh][TJ.bufSize(_tilew, _tileh, subsamp)];
508
for (y = 0, tile = 0; y < _h; y += _tileh) {
509
for (x = 0; x < _w; x += _tilew, tile++) {
510
t[tile] = new TJTransform();
511
t[tile].width = Math.min(_tilew, _w - x);
512
t[tile].height = Math.min(_tileh, _h - y);
515
t[tile].op = xformOp;
516
t[tile].options = xformOpt | TJTransform.OPT_TRIM;
517
if ((t[tile].options & TJTransform.OPT_NOOUTPUT) != 0 &&
518
jpegBuf[tile] != null)
519
jpegBuf[tile] = null;
524
tjt.transform(jpegBuf, t, flags);
525
jpegSize = tjt.getTransformedSizes();
526
elapsed = getTime() - start;
530
for (tile = 0, totalJpegSize = 0; tile < _ntilesw * _ntilesh; tile++)
531
totalJpegSize += jpegSize[tile];
534
System.out.format("%s%c%s%c",
535
sigFig((double)(w * h) / 1000000. / elapsed, 4),
536
quiet == 2 ? '\n' : '\t',
537
sigFig((double)(w * h * ps) / (double)totalJpegSize, 4),
538
quiet == 2 ? '\n' : '\t');
539
} else if (quiet == 0) {
540
System.out.format("X--> Frame rate: %f fps\n",
542
System.out.format(" Output image size: %lu bytes\n",
544
System.out.format(" Compression ratio: %f:1\n",
545
(double)(w * h * ps) / (double)totalJpegSize);
546
System.out.format(" Source throughput: %f Megapixels/sec\n",
547
(double)(w * h) / 1000000. / elapsed);
548
System.out.format(" Output bit stream: %f Megabits/sec\n",
549
(double)totalJpegSize * 8. / 1000000. / elapsed);
553
System.out.print("N/A\tN/A\t");
554
jpegBuf = new byte[1][TJ.bufSize(_tilew, _tileh, subsamp)];
555
jpegSize = new int[1];
556
jpegSize[0] = srcSize;
557
System.arraycopy(srcBuf, 0, jpegBuf[0], 0, srcSize);
564
if ((xformOpt & TJTransform.OPT_NOOUTPUT) == 0)
565
decompTest(null, jpegBuf, jpegSize, null, _w, _h, _subsamp, 0,
566
fileName, _tilew, _tileh);
568
System.out.println("N/A");
573
if (tilew == w && tileh == h) break;
578
static void usage() throws Exception {
580
TJScalingFactor[] scalingFactors = TJ.getScalingFactors();
581
int nsf = scalingFactors.length;
582
String className = new TJBench().getClass().getName();
584
System.out.println("\nUSAGE: java " + className);
585
System.out.println(" <Inputfile (BMP)> <Quality> [options]\n");
586
System.out.println(" java " + className);
587
System.out.println(" <Inputfile (JPG)> [options]\n");
588
System.out.println("Options:\n");
589
System.out.println("-alloc = Dynamically allocate JPEG image buffers");
590
System.out.println("-bottomup = Test bottom-up compression/decompression");
591
System.out.println("-tile = Test performance of the codec when the image is encoded as separate");
592
System.out.println(" tiles of varying sizes.");
593
System.out.println("-forcemmx, -forcesse, -forcesse2, -forcesse3 =");
594
System.out.println(" Force MMX, SSE, SSE2, or SSE3 code paths in the underlying codec");
595
System.out.println("-rgb, -bgr, -rgbx, -bgrx, -xbgr, -xrgb =");
596
System.out.println(" Test the specified color conversion path in the codec (default: BGR)");
597
System.out.println("-fastupsample = Use the fastest chrominance upsampling algorithm available in");
598
System.out.println(" the underlying codec");
599
System.out.println("-fastdct = Use the fastest DCT/IDCT algorithms available in the underlying");
600
System.out.println(" codec");
601
System.out.println("-accuratedct = Use the most accurate DCT/IDCT algorithms available in the");
602
System.out.println(" underlying codec");
603
System.out.println("-quiet = Output results in tabular rather than verbose format");
604
System.out.println("-yuvencode = Encode RGB input as planar YUV rather than compressing as JPEG");
605
System.out.println("-yuvdecode = Decode JPEG image to planar YUV rather than RGB");
606
System.out.println("-scale M/N = scale down the width/height of the decompressed JPEG image by a");
607
System.out.print (" factor of M/N (M/N = ");
608
for (i = 0; i < nsf; i++) {
609
System.out.format("%d/%d", scalingFactors[i].getNum(),
610
scalingFactors[i].getDenom());
611
if (nsf == 2 && i != nsf - 1)
612
System.out.print(" or ");
615
System.out.print(", ");
617
System.out.print("or ");
619
if (i % 8 == 0 && i != 0)
620
System.out.print("\n ");
622
System.out.println(")");
623
System.out.println("-hflip, -vflip, -transpose, -transverse, -rot90, -rot180, -rot270 =");
624
System.out.println(" Perform the corresponding lossless transform prior to");
625
System.out.println(" decompression (these options are mutually exclusive)");
626
System.out.println("-grayscale = Perform lossless grayscale conversion prior to decompression");
627
System.out.println(" test (can be combined with the other transforms above)");
628
System.out.println("-benchTime <t> = Run each benchmark for at least <t> seconds (default = 5.0)\n");
629
System.out.println("NOTE: If the quality is specified as a range (e.g. 90-100), a separate");
630
System.out.println("test will be performed for all quality values in the range.\n");
635
public static void main(String[] argv) {
636
byte[] srcBuf = null; int w = 0, h = 0;
637
int minQual = -1, maxQual = -1;
638
int minArg = 1; int retval = 0;
642
if (argv.length < minArg)
645
String tempStr = argv[0].toLowerCase();
646
if (tempStr.endsWith(".jpg") || tempStr.endsWith(".jpeg"))
649
System.out.println("");
651
if (argv.length > minArg) {
652
for (int i = minArg; i < argv.length; i++) {
653
if (argv[i].equalsIgnoreCase("-yuvencode")) {
654
System.out.println("Testing YUV planar encoding\n");
655
yuv = YUVENCODE; maxQual = minQual = 100;
657
if (argv[i].equalsIgnoreCase("-yuvdecode")) {
658
System.out.println("Testing YUV planar decoding\n");
664
if (!decompOnly && yuv != YUVENCODE) {
666
if (argv.length < minArg)
669
minQual = Integer.parseInt(argv[1]);
670
} catch (NumberFormatException e) {}
671
if (minQual < 1 || minQual > 100)
672
throw new Exception("Quality must be between 1 and 100.");
673
int dashIndex = argv[1].indexOf('-');
674
if (dashIndex > 0 && argv[1].length() > dashIndex + 1) {
676
maxQual = Integer.parseInt(argv[1].substring(dashIndex + 1));
677
} catch (NumberFormatException e) {}
679
if (maxQual < 1 || maxQual > 100)
683
if (argv.length > minArg) {
684
for (int i = minArg; i < argv.length; i++) {
685
if (argv[i].equalsIgnoreCase("-tile")) {
686
doTile = true; xformOpt |= TJTransform.OPT_CROP;
688
if (argv[i].equalsIgnoreCase("-forcesse3")) {
689
System.out.println("Forcing SSE3 code\n");
690
flags |= TJ.FLAG_FORCESSE3;
692
if (argv[i].equalsIgnoreCase("-forcesse2")) {
693
System.out.println("Forcing SSE2 code\n");
694
flags |= TJ.FLAG_FORCESSE2;
696
if (argv[i].equalsIgnoreCase("-forcesse")) {
697
System.out.println("Forcing SSE code\n");
698
flags |= TJ.FLAG_FORCESSE;
700
if (argv[i].equalsIgnoreCase("-forcemmx")) {
701
System.out.println("Forcing MMX code\n");
702
flags |= TJ.FLAG_FORCEMMX;
704
if (argv[i].equalsIgnoreCase("-fastupsample")) {
705
System.out.println("Using fast upsampling code\n");
706
flags |= TJ.FLAG_FASTUPSAMPLE;
708
if (argv[i].equalsIgnoreCase("-fastdct")) {
709
System.out.println("Using fastest DCT/IDCT algorithm\n");
710
flags |= TJ.FLAG_FASTDCT;
712
if (argv[i].equalsIgnoreCase("-accuratedct")) {
713
System.out.println("Using most accurate DCT/IDCT algorithm\n");
714
flags |= TJ.FLAG_ACCURATEDCT;
716
if (argv[i].equalsIgnoreCase("-rgb"))
718
if (argv[i].equalsIgnoreCase("-rgbx"))
720
if (argv[i].equalsIgnoreCase("-bgr"))
722
if (argv[i].equalsIgnoreCase("-bgrx"))
724
if (argv[i].equalsIgnoreCase("-xbgr"))
726
if (argv[i].equalsIgnoreCase("-xrgb"))
728
if (argv[i].equalsIgnoreCase("-bottomup"))
729
flags |= TJ.FLAG_BOTTOMUP;
730
if (argv[i].equalsIgnoreCase("-quiet"))
732
if (argv[i].equalsIgnoreCase("-qq"))
734
if (argv[i].equalsIgnoreCase("-scale") && i < argv.length - 1) {
735
int temp1 = 0, temp2 = 0;
736
boolean match = false, scanned = true;
737
Scanner scanner = new Scanner(argv[++i]).useDelimiter("/");
739
temp1 = scanner.nextInt();
740
temp2 = scanner.nextInt();
741
} catch(Exception e) {}
742
if (temp2 <= 0) temp2 = 1;
744
TJScalingFactor[] scalingFactors = TJ.getScalingFactors();
745
for (int j = 0; j < scalingFactors.length; j++) {
746
if ((double)temp1 / (double)temp2 ==
747
(double)scalingFactors[j].getNum() /
748
(double)scalingFactors[j].getDenom()) {
749
sf = scalingFactors[j];
757
if (argv[i].equalsIgnoreCase("-hflip"))
758
xformOp = TJTransform.OP_HFLIP;
759
if (argv[i].equalsIgnoreCase("-vflip"))
760
xformOp = TJTransform.OP_VFLIP;
761
if (argv[i].equalsIgnoreCase("-transpose"))
762
xformOp = TJTransform.OP_TRANSPOSE;
763
if (argv[i].equalsIgnoreCase("-transverse"))
764
xformOp = TJTransform.OP_TRANSVERSE;
765
if (argv[i].equalsIgnoreCase("-rot90"))
766
xformOp = TJTransform.OP_ROT90;
767
if (argv[i].equalsIgnoreCase("-rot180"))
768
xformOp = TJTransform.OP_ROT180;
769
if (argv[i].equalsIgnoreCase("-rot270"))
770
xformOp = TJTransform.OP_ROT270;
771
if (argv[i].equalsIgnoreCase("-grayscale"))
772
xformOpt |= TJTransform.OPT_GRAY;
773
if (argv[i].equalsIgnoreCase("-nooutput"))
774
xformOpt |= TJTransform.OPT_NOOUTPUT;
775
if (argv[i].equalsIgnoreCase("-benchtime") && i < argv.length - 1) {
778
temp = Double.parseDouble(argv[++i]);
779
} catch (NumberFormatException e) {}
785
if (argv[i].equalsIgnoreCase("-?"))
791
sf = new TJScalingFactor(1, 1);
793
if ((sf.getNum() != 1 || sf.getDenom() != 1) && doTile) {
794
System.out.println("Disabling tiled compression/decompression tests, because those tests do not");
795
System.out.println("work when scaled decompression is enabled.");
799
if (yuv != 0 && doTile) {
800
System.out.println("Disabling tiled compression/decompression tests, because those tests do not");
801
System.out.println("work when YUV encoding or decoding is enabled.\n");
806
int[] width = new int[1], height = new int[1];
807
srcBuf = loadImage(argv[0], width, height, pf);
808
w = width[0]; h = height[0];
810
if ((index = argv[0].indexOf('.')) >= 0)
811
argv[0] = argv[0].substring(0, index);
814
if (quiet == 1 && !decompOnly) {
815
System.out.println("All performance values in Mpixels/sec\n");
816
System.out.format("Bitmap\tBitmap\tJPEG\tJPEG\t%s %s \tComp\tComp\tDecomp\n",
817
(doTile ? "Tile " : "Image"), (doTile ? "Tile " : "Image"));
818
System.out.println("Format\tOrder\tSubsamp\tQual\tWidth Height\tPerf \tRatio\tPerf\n");
822
doDecompTest(argv[0]);
823
System.out.println("");
828
for (int i = maxQual; i >= minQual; i--)
829
doTest(srcBuf, w, h, TJ.SAMP_GRAY, i, argv[0]);
830
System.out.println("");
832
for (int i = maxQual; i >= minQual; i--)
833
doTest(srcBuf, w, h, TJ.SAMP_420, i, argv[0]);
834
System.out.println("");
836
for (int i = maxQual; i >= minQual; i--)
837
doTest(srcBuf, w, h, TJ.SAMP_422, i, argv[0]);
838
System.out.println("");
840
for (int i = maxQual; i >= minQual; i--)
841
doTest(srcBuf, w, h, TJ.SAMP_444, i, argv[0]);
842
System.out.println("");
844
} catch (Exception e) {
845
System.out.println("ERROR: " + e.getMessage());