~ubuntu-branches/ubuntu/saucy/libjpeg-turbo/saucy-security

« back to all changes in this revision

Viewing changes to java/TJBench.java

  • Committer: Package Import Robot
  • Author(s): Fathi Boudra
  • Date: 2013-07-28 16:52:51 UTC
  • mfrom: (1.1.3) (9.1.1 saucy-proposed)
  • Revision ID: package-import@ubuntu.com-20130728165251-7vg6wszhm941kdej
Tags: 1.3.0-0ubuntu1
* New upstream release.
  - drop debian/patches/branch-updates.diff
  - refresh tjunittest.patch (now renamed to install-tjunittest.patch)
* Update debian/control:
  - add myself to Uploaders.
* Update debian/copyright:
  - add RSA Data Security copyright (md5).
* Update debian/libturbojpeg.install:
  - install libturbojpeg.so.0* (needed by tjunittest and tjbench).

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (C)2009-2012 D. R. Commander.  All Rights Reserved.
 
3
 *
 
4
 * Redistribution and use in source and binary forms, with or without
 
5
 * modification, are permitted provided that the following conditions are met:
 
6
 *
 
7
 * - Redistributions of source code must retain the above copyright notice,
 
8
 *   this list of conditions and the following disclaimer.
 
9
 * - Redistributions in binary form must reproduce the above copyright notice,
 
10
 *   this list of conditions and the following disclaimer in the documentation
 
11
 *   and/or other materials provided with the distribution.
 
12
 * - Neither the name of the libjpeg-turbo Project nor the names of its
 
13
 *   contributors may be used to endorse or promote products derived from this
 
14
 *   software without specific prior written permission.
 
15
 *
 
16
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS",
 
17
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 
18
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 
19
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
 
20
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 
21
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 
22
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 
23
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 
24
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 
25
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 
26
 * POSSIBILITY OF SUCH DAMAGE.
 
27
 */
 
28
 
 
29
import java.io.*;
 
30
import java.awt.image.*;
 
31
import javax.imageio.*;
 
32
import java.util.*;
 
33
import org.libjpegturbo.turbojpeg.*;
 
34
 
 
35
class TJBench {
 
36
 
 
37
  static final int YUVENCODE = 1;
 
38
  static final int YUVDECODE = 2;
 
39
 
 
40
  static int flags = 0, yuv = 0, quiet = 0, pf = TJ.PF_BGR;
 
41
  static boolean decompOnly, doTile;
 
42
 
 
43
  static final String[] pixFormatStr = {
 
44
    "RGB", "BGR", "RGBX", "BGRX", "XBGR", "XRGB", "GRAY"
 
45
  };
 
46
 
 
47
  static final String[] subNameLong = {
 
48
    "4:4:4", "4:2:2", "4:2:0", "GRAY", "4:4:0"
 
49
  };
 
50
 
 
51
  static final String[] subName = {
 
52
    "444", "422", "420", "GRAY", "440"
 
53
  };
 
54
 
 
55
  static TJScalingFactor sf;
 
56
  static int xformOp = TJTransform.OP_NONE, xformOpt = 0;
 
57
  static double benchTime = 5.0;
 
58
 
 
59
 
 
60
  static final double getTime() {
 
61
    return (double)System.nanoTime() / 1.0e9;
 
62
  }
 
63
 
 
64
 
 
65
  static String sigFig(double val, int figs) {
 
66
    String format;
 
67
    int digitsAfterDecimal = figs - (int)Math.ceil(Math.log10(Math.abs(val)));
 
68
    if (digitsAfterDecimal < 1)
 
69
      format = new String("%.0f");
 
70
    else
 
71
      format = new String("%." + digitsAfterDecimal + "f");
 
72
    return String.format(format, val);
 
73
  }
 
74
 
 
75
 
 
76
  static byte[] loadImage(String fileName, int[] w, int[] h, int pixelFormat)
 
77
                          throws Exception {
 
78
    BufferedImage img = ImageIO.read(new File(fileName));
 
79
    if (img == null)
 
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);
 
94
      dstPtr += ps;
 
95
      rgbPtr++;
 
96
    }
 
97
    return dstBuf;
 
98
  }
 
99
 
 
100
 
 
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);
 
115
      }
 
116
    }
 
117
    ImageIO.write(img, "bmp", new File(fileName));
 
118
  }
 
119
 
 
120
 
 
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)
 
125
                         throws Exception {
 
126
    String qualStr = new String(""), sizeStr, tempStr;
 
127
    TJDecompressor tjd;
 
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;
 
134
 
 
135
    if (jpegQual > 0)
 
136
      qualStr = new String("_Q" + jpegQual);
 
137
 
 
138
    tjd = new TJDecompressor();
 
139
 
 
140
    int bufSize = (yuv == YUVDECODE ? yuvSize : pitch * scaledh);
 
141
    if (dstBuf == null)
 
142
      dstBuf = new byte[bufSize];
 
143
 
 
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);
 
147
 
 
148
    /* Execute once to preload cache */
 
149
    tjd.setJPEGImage(jpegBuf[0], jpegSize[0]);
 
150
    if (yuv == YUVDECODE)
 
151
      tjd.decompressToYUV(dstBuf, flags);
 
152
    else
 
153
      tjd.decompress(dstBuf, scaledw, pitch, scaledh, pf, flags);
 
154
 
 
155
    /* Benchmark */
 
156
    for (i = 0, start = getTime(); (elapsed = getTime() - start) < benchTime;
 
157
         i++) {
 
158
      int tile = 0;
 
159
      if (yuv == YUVDECODE)
 
160
        tjd.decompressToYUV(dstBuf, flags);
 
161
      else {
 
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);
 
168
          }
 
169
        }
 
170
      }
 
171
    }
 
172
 
 
173
    tjd = null;
 
174
    System.gc();
 
175
 
 
176
    if (quiet != 0)
 
177
      System.out.println(
 
178
        sigFig((double)(w * h) / 1000000. * (double)i / elapsed, 4));
 
179
    else {
 
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);
 
184
    }
 
185
 
 
186
    if (yuv == YUVDECODE) {
 
187
      tempStr = fileName + "_" + subName[subsamp] + qualStr + ".yuv";
 
188
      FileOutputStream fos = new FileOutputStream(tempStr);
 
189
      fos.write(dstBuf, 0, yuvSize);
 
190
      fos.close();
 
191
    } else {
 
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);
 
196
      else
 
197
        sizeStr = new String("full");
 
198
      if (decompOnly)
 
199
        tempStr = new String(fileName + "_" + sizeStr + ".bmp");
 
200
      else
 
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) {
 
207
        if (quiet == 0)
 
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);
 
223
            }
 
224
          }
 
225
        } else {
 
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));
 
231
        }
 
232
        saveImage(tempStr, dstBuf, w, h, pf);
 
233
      }
 
234
    }
 
235
  }
 
236
 
 
237
 
 
238
  static void doTestYUV(byte[] srcBuf, int w, int h, int subsamp,
 
239
                        String fileName) throws Exception {
 
240
    TJCompressor tjc;
 
241
    byte[] dstBuf;
 
242
    double start, elapsed;
 
243
    int ps = TJ.getPixelSize(pf), i;
 
244
    int yuvSize = 0;
 
245
 
 
246
    yuvSize = TJ.bufSizeYUV(w, h, subsamp);
 
247
    dstBuf = new byte[yuvSize];
 
248
 
 
249
    if (quiet == 0)
 
250
      System.out.format(">>>>>  %s (%s) <--> YUV %s  <<<<<\n",
 
251
        pixFormatStr[pf],
 
252
        (flags & TJ.FLAG_BOTTOMUP) != 0 ? "Bottom-up" : "Top-down",
 
253
        subNameLong[subsamp]);
 
254
 
 
255
    if (quiet == 1)
 
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]);
 
259
 
 
260
    tjc = new TJCompressor(srcBuf, w, 0, h, pf);
 
261
    tjc.setSubsamp(subsamp);
 
262
 
 
263
    /* Execute once to preload cache */
 
264
    tjc.encodeYUV(dstBuf, flags);
 
265
 
 
266
    /* Benchmark */
 
267
    for (i = 0, start = getTime();
 
268
         (elapsed = getTime() - start) < benchTime; i++)
 
269
      tjc.encodeYUV(dstBuf, flags);
 
270
 
 
271
    if (quiet == 1)
 
272
      System.out.format("%-4d  %-4d\t", w, h);
 
273
    if (quiet != 0) {
 
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');
 
279
    } else {
 
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);
 
290
    }
 
291
    String tempStr = fileName + "_" + subName[subsamp] + ".yuv";
 
292
    FileOutputStream fos = new FileOutputStream(tempStr);
 
293
    fos.write(dstBuf, 0, yuvSize);
 
294
    fos.close();
 
295
    if (quiet == 0)
 
296
      System.out.println("Reference image written to " + tempStr);
 
297
  }
 
298
 
 
299
 
 
300
  static void doTest(byte[] srcBuf, int w, int h, int subsamp, int jpegQual,
 
301
                     String fileName) throws Exception {
 
302
    TJCompressor tjc;
 
303
    byte[] tmpBuf;
 
304
    byte[][] jpegBuf;
 
305
    int[] jpegSize;
 
306
    double start, elapsed;
 
307
    int totalJpegSize = 0, tilew, tileh, i;
 
308
    int ps = TJ.getPixelSize(pf), ntilesw = 1, ntilesh = 1, pitch = w * ps;
 
309
 
 
310
    if (yuv == YUVENCODE) {
 
311
      doTestYUV(srcBuf, w, h, subsamp, fileName);
 
312
      return;
 
313
    }
 
314
 
 
315
    tmpBuf = new byte[pitch * h];
 
316
 
 
317
    if (quiet == 0)
 
318
      System.out.format(">>>>>  %s (%s) <--> JPEG %s Q%d  <<<<<\n",
 
319
        pixFormatStr[pf],
 
320
        (flags & TJ.FLAG_BOTTOMUP) != 0 ? "Bottom-up" : "Top-down",
 
321
        subNameLong[subsamp], jpegQual);
 
322
 
 
323
    tjc = new TJCompressor();
 
324
 
 
325
    for (tilew = doTile ? 8 : w, tileh = doTile ? 8 : h; ;
 
326
         tilew *= 2, tileh *= 2) {
 
327
      if (tilew > w)
 
328
        tilew = w;
 
329
      if (tileh > h)
 
330
        tileh = h;
 
331
      ntilesw = (w + tilew - 1) / tilew;
 
332
      ntilesh = (h + tileh - 1) / tileh;
 
333
 
 
334
      jpegBuf = new byte[ntilesw * ntilesh][TJ.bufSize(tilew, tileh, subsamp)];
 
335
      jpegSize = new int[ntilesw * ntilesh];
 
336
 
 
337
      /* Compression test */
 
338
      if (quiet == 1)
 
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);
 
347
 
 
348
      /* Execute once to preload cache */
 
349
      tjc.compress(jpegBuf[0], flags);
 
350
 
 
351
      /* Benchmark */
 
352
      for (i = 0, start = getTime();
 
353
           (elapsed = getTime() - start) < benchTime; i++) {
 
354
        int tile = 0;
 
355
        totalJpegSize = 0;
 
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];
 
364
          }
 
365
        }
 
366
      }
 
367
 
 
368
      if (quiet == 1)
 
369
        System.out.format("%-4d  %-4d\t", tilew, tileh);
 
370
      if (quiet != 0) {
 
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');
 
376
      } else {
 
377
        System.out.format("\n%s size: %d x %d\n", doTile ? "Tile" : "Image",
 
378
                          tilew, tileh);
 
379
        System.out.format("C--> Frame rate:           %f fps\n",
 
380
                          (double)i / elapsed);
 
381
        System.out.format("     Output image size:    %d bytes\n",
 
382
                          totalJpegSize);
 
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);
 
389
      }
 
390
      if (tilew == w && tileh == h) {
 
391
        String tempStr = fileName + "_" + subName[subsamp] + "_" + "Q" +
 
392
                         jpegQual + ".jpg";
 
393
        FileOutputStream fos = new FileOutputStream(tempStr);
 
394
        fos.write(jpegBuf[0], 0, jpegSize[0]);
 
395
        fos.close();
 
396
        if (quiet == 0)
 
397
          System.out.println("Reference image written to " + tempStr);
 
398
      }
 
399
 
 
400
      /* Decompression test */
 
401
      decompTest(srcBuf, jpegBuf, jpegSize, tmpBuf, w, h, subsamp, jpegQual,
 
402
                 fileName, tilew, tileh);
 
403
 
 
404
      for (i = 0; i < ntilesw * ntilesh; i++)
 
405
        jpegBuf[i] = null;
 
406
      jpegBuf = null;  jpegSize = null;
 
407
      System.gc();
 
408
 
 
409
      if (tilew == w && tileh == h) break;
 
410
    }
 
411
  }
 
412
 
 
413
 
 
414
  static void doDecompTest(String fileName) throws Exception {
 
415
    TJTransformer tjt;
 
416
    byte[][] jpegBuf;
 
417
    byte[] srcBuf;
 
418
    int[] jpegSize;
 
419
    int totalJpegSize;
 
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;
 
425
 
 
426
    FileInputStream fis = new FileInputStream(fileName);
 
427
    int srcSize = (int)fis.getChannel().size();
 
428
    srcBuf = new byte[srcSize];
 
429
    fis.read(srcBuf, 0, srcSize);
 
430
    fis.close();
 
431
 
 
432
    int index = fileName.indexOf('.');
 
433
    if (index >= 0)
 
434
      fileName = new String(fileName.substring(0, index));
 
435
 
 
436
    tjt = new TJTransformer();
 
437
 
 
438
    tjt.setJPEGImage(srcBuf, srcSize);
 
439
    w = tjt.getWidth();
 
440
    h = tjt.getHeight();
 
441
    subsamp = tjt.getSubsamp();
 
442
 
 
443
    if (quiet == 1) {
 
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");
 
453
    }
 
454
 
 
455
    for (int tilew = doTile ? 16 : w, tileh = doTile ? 16 : h; ;
 
456
         tilew *= 2, tileh *= 2) {
 
457
      if (tilew > w)
 
458
        tilew = w;
 
459
      if (tileh > h)
 
460
        tileh = h;
 
461
      ntilesw = (w + tilew - 1) / tilew;
 
462
      ntilesh = (h + tileh - 1) / tileh;
 
463
 
 
464
      _w = w;  _h = h;  _tilew = tilew;  _tileh = tileh;
 
465
      if (quiet == 0) {
 
466
        System.out.format("\n%s size: %d x %d", (doTile ? "Tile" : "Image"),
 
467
                          _tilew, _tileh);
 
468
        if (sf.getNum() != 1 || sf.getDenom() != 1)
 
469
          System.out.format(" --> %d x %d", sf.getScaled(_w),
 
470
                            sf.getScaled(_h));
 
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);
 
477
      }
 
478
 
 
479
      _subsamp = subsamp;
 
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;
 
486
        }
 
487
 
 
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;
 
504
 
 
505
        TJTransform[] t = new TJTransform[_ntilesw * _ntilesh];
 
506
        jpegBuf = new byte[_ntilesw * _ntilesh][TJ.bufSize(_tilew, _tileh, subsamp)];
 
507
 
 
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);
 
513
            t[tile].x = x;
 
514
            t[tile].y = 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;
 
520
          }
 
521
        }
 
522
 
 
523
        start = getTime();
 
524
        tjt.transform(jpegBuf, t, flags);
 
525
        jpegSize = tjt.getTransformedSizes();
 
526
        elapsed = getTime() - start;
 
527
 
 
528
        t = null;
 
529
 
 
530
        for (tile = 0, totalJpegSize = 0; tile < _ntilesw * _ntilesh; tile++)
 
531
          totalJpegSize += jpegSize[tile];
 
532
 
 
533
        if (quiet != 0) {
 
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",
 
541
                            1.0 / elapsed);
 
542
          System.out.format("     Output image size:    %lu bytes\n",
 
543
                            totalJpegSize);
 
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);
 
550
        }
 
551
      } else {
 
552
        if (quiet == 1)
 
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);
 
558
      }
 
559
 
 
560
      if (w == tilew)
 
561
        _tilew = _w;
 
562
      if (h == tileh)
 
563
        _tileh = _h;
 
564
      if ((xformOpt & TJTransform.OPT_NOOUTPUT) == 0)
 
565
        decompTest(null, jpegBuf, jpegSize, null, _w, _h, _subsamp, 0,
 
566
                   fileName, _tilew, _tileh);
 
567
      else if (quiet == 1)
 
568
        System.out.println("N/A");
 
569
 
 
570
      jpegBuf = null;
 
571
      jpegSize = null;
 
572
 
 
573
      if (tilew == w && tileh == h) break;
 
574
    }
 
575
  }
 
576
 
 
577
 
 
578
  static void usage() throws Exception {
 
579
    int i;
 
580
    TJScalingFactor[] scalingFactors = TJ.getScalingFactors();
 
581
    int nsf = scalingFactors.length;
 
582
    String className = new TJBench().getClass().getName();
 
583
 
 
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 ");
 
613
      else if (nsf > 2) {
 
614
        if (i != nsf - 1)
 
615
          System.out.print(", ");
 
616
        if (i == nsf - 2)
 
617
          System.out.print("or ");
 
618
      }
 
619
      if (i % 8 == 0 && i != 0)
 
620
        System.out.print("\n     ");
 
621
    }
 
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");
 
631
    System.exit(1);
 
632
  }
 
633
 
 
634
 
 
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;
 
639
 
 
640
    try {
 
641
 
 
642
      if (argv.length < minArg)
 
643
        usage();
 
644
 
 
645
      String tempStr = argv[0].toLowerCase();
 
646
      if (tempStr.endsWith(".jpg") || tempStr.endsWith(".jpeg"))
 
647
        decompOnly = true;
 
648
 
 
649
      System.out.println("");
 
650
 
 
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;
 
656
          }
 
657
          if (argv[i].equalsIgnoreCase("-yuvdecode")) {
 
658
            System.out.println("Testing YUV planar decoding\n");
 
659
            yuv = YUVDECODE;
 
660
          }
 
661
        }
 
662
      }
 
663
 
 
664
      if (!decompOnly && yuv != YUVENCODE) {
 
665
        minArg = 2;
 
666
        if (argv.length < minArg)
 
667
          usage();
 
668
        try {
 
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) {
 
675
          try {
 
676
            maxQual = Integer.parseInt(argv[1].substring(dashIndex + 1));
 
677
          } catch (NumberFormatException e) {}
 
678
        }
 
679
        if (maxQual < 1 || maxQual > 100)
 
680
          maxQual = minQual;
 
681
      }
 
682
 
 
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;
 
687
          }
 
688
          if (argv[i].equalsIgnoreCase("-forcesse3")) {
 
689
            System.out.println("Forcing SSE3 code\n");
 
690
            flags |= TJ.FLAG_FORCESSE3;
 
691
          }
 
692
          if (argv[i].equalsIgnoreCase("-forcesse2")) {
 
693
            System.out.println("Forcing SSE2 code\n");
 
694
            flags |= TJ.FLAG_FORCESSE2;
 
695
          }
 
696
          if (argv[i].equalsIgnoreCase("-forcesse")) {
 
697
            System.out.println("Forcing SSE code\n");
 
698
            flags |= TJ.FLAG_FORCESSE;
 
699
          }
 
700
          if (argv[i].equalsIgnoreCase("-forcemmx")) {
 
701
            System.out.println("Forcing MMX code\n");
 
702
            flags |= TJ.FLAG_FORCEMMX;
 
703
          }
 
704
          if (argv[i].equalsIgnoreCase("-fastupsample")) {
 
705
            System.out.println("Using fast upsampling code\n");
 
706
            flags |= TJ.FLAG_FASTUPSAMPLE;
 
707
          }
 
708
          if (argv[i].equalsIgnoreCase("-fastdct")) {
 
709
            System.out.println("Using fastest DCT/IDCT algorithm\n");
 
710
            flags |= TJ.FLAG_FASTDCT;
 
711
          }
 
712
          if (argv[i].equalsIgnoreCase("-accuratedct")) {
 
713
            System.out.println("Using most accurate DCT/IDCT algorithm\n");
 
714
            flags |= TJ.FLAG_ACCURATEDCT;
 
715
          }
 
716
          if (argv[i].equalsIgnoreCase("-rgb"))
 
717
            pf = TJ.PF_RGB;
 
718
          if (argv[i].equalsIgnoreCase("-rgbx"))
 
719
            pf = TJ.PF_RGBX;
 
720
          if (argv[i].equalsIgnoreCase("-bgr"))
 
721
            pf = TJ.PF_BGR;
 
722
          if (argv[i].equalsIgnoreCase("-bgrx"))
 
723
            pf = TJ.PF_BGRX;
 
724
          if (argv[i].equalsIgnoreCase("-xbgr"))
 
725
            pf = TJ.PF_XBGR;
 
726
          if (argv[i].equalsIgnoreCase("-xrgb"))
 
727
            pf = TJ.PF_XRGB;
 
728
          if (argv[i].equalsIgnoreCase("-bottomup"))
 
729
            flags |= TJ.FLAG_BOTTOMUP;
 
730
          if (argv[i].equalsIgnoreCase("-quiet"))
 
731
            quiet = 1;
 
732
          if (argv[i].equalsIgnoreCase("-qq"))
 
733
            quiet = 2;
 
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("/");
 
738
            try {
 
739
              temp1 = scanner.nextInt();
 
740
              temp2 = scanner.nextInt();
 
741
            } catch(Exception e) {}
 
742
            if (temp2 <= 0) temp2 = 1;
 
743
            if (temp1 > 0) {
 
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];
 
750
                  match = true;   break;
 
751
                }
 
752
              }
 
753
              if (!match) usage();
 
754
            } else
 
755
              usage();
 
756
          }
 
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) {
 
776
            double temp = -1;
 
777
            try {
 
778
              temp = Double.parseDouble(argv[++i]);
 
779
            } catch (NumberFormatException e) {}
 
780
            if (temp > 0.0)
 
781
              benchTime = temp;
 
782
            else
 
783
              usage();
 
784
          }
 
785
          if (argv[i].equalsIgnoreCase("-?"))
 
786
            usage();
 
787
        }
 
788
      }
 
789
 
 
790
      if (sf == null)
 
791
        sf = new TJScalingFactor(1, 1);
 
792
 
 
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.");
 
796
        doTile = false;
 
797
      }
 
798
 
 
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");
 
802
        doTile = false;
 
803
      }
 
804
 
 
805
      if (!decompOnly) {
 
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];
 
809
        int index = -1;
 
810
        if ((index = argv[0].indexOf('.')) >= 0)
 
811
          argv[0] = argv[0].substring(0, index);
 
812
      }
 
813
 
 
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");
 
819
      }
 
820
 
 
821
      if (decompOnly) {
 
822
        doDecompTest(argv[0]);
 
823
        System.out.println("");
 
824
        System.exit(retval);
 
825
      }
 
826
 
 
827
      System.gc();
 
828
      for (int i = maxQual; i >= minQual; i--)
 
829
        doTest(srcBuf, w, h, TJ.SAMP_GRAY, i, argv[0]);
 
830
      System.out.println("");
 
831
      System.gc();
 
832
      for (int i = maxQual; i >= minQual; i--)
 
833
        doTest(srcBuf, w, h, TJ.SAMP_420, i, argv[0]);
 
834
      System.out.println("");
 
835
      System.gc();
 
836
      for (int i = maxQual; i >= minQual; i--)
 
837
        doTest(srcBuf, w, h, TJ.SAMP_422, i, argv[0]);
 
838
      System.out.println("");
 
839
      System.gc();
 
840
      for (int i = maxQual; i >= minQual; i--)
 
841
        doTest(srcBuf, w, h, TJ.SAMP_444, i, argv[0]);
 
842
      System.out.println("");
 
843
 
 
844
    } catch (Exception e) {
 
845
      System.out.println("ERROR: " + e.getMessage());
 
846
      e.printStackTrace();
 
847
      retval = -1;
 
848
    }
 
849
 
 
850
    System.exit(retval);
 
851
  }
 
852
 
 
853
}