TJUnitTest.java revision f962fbb44ad4d7b8200679ad0ed9263e10252638
1/* 2 * Copyright (C)2011 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/* 30 * This program tests the various code paths in the TurboJPEG JNI Wrapper 31 */ 32 33import java.io.*; 34import java.util.*; 35import java.awt.image.*; 36import javax.imageio.*; 37import org.libjpegturbo.turbojpeg.*; 38 39public class TJUnitTest { 40 41 private static final String classname = 42 new TJUnitTest().getClass().getName(); 43 44 private static void usage() { 45 System.out.println("\nUSAGE: java " + classname + " [options]\n"); 46 System.out.println("Options:\n"); 47 System.out.println("-yuv = test YUV encoding/decoding support\n"); 48 System.out.println("-bi = test BufferedImage support\n"); 49 System.exit(1); 50 } 51 52 private final static String subNameLong[] = { 53 "4:4:4", "4:2:2", "4:2:0", "GRAY", "4:4:0" 54 }; 55 private final static String subName[] = { 56 "444", "422", "420", "GRAY", "440" 57 }; 58 59 private final static String pixFormatStr[] = { 60 "RGB", "BGR", "RGBX", "BGRX", "XBGR", "XRGB", "Grayscale" 61 }; 62 private final static int biType[] = { 63 0, BufferedImage.TYPE_3BYTE_BGR, BufferedImage.TYPE_INT_BGR, 64 BufferedImage.TYPE_INT_RGB, 0, 0, BufferedImage.TYPE_BYTE_GRAY 65 }; 66 67 private final static int _3byteFormats[] = { 68 TJ.PF_RGB, TJ.PF_BGR 69 }; 70 private final static int _3byteFormatsBI[] = { 71 TJ.PF_BGR 72 }; 73 private final static int _4byteFormats[] = { 74 TJ.PF_RGBX, TJ.PF_BGRX, TJ.PF_XBGR, TJ.PF_XRGB 75 }; 76 private final static int _4byteFormatsBI[] = { 77 TJ.PF_RGBX, TJ.PF_BGRX 78 }; 79 private final static int onlyGray[] = { 80 TJ.PF_GRAY 81 }; 82 private final static int onlyRGB[] = { 83 TJ.PF_RGB 84 }; 85 86 private final static int YUVENCODE = 1; 87 private final static int YUVDECODE = 2; 88 private static int yuv = 0; 89 private static boolean bi = false; 90 91 private static int exitStatus = 0; 92 93 private static double getTime() { 94 return (double)System.nanoTime() / 1.0e9; 95 } 96 97 private final static byte pixels[][] = { 98 {0, (byte)255, 0}, 99 {(byte)255, 0, (byte)255}, 100 {0, (byte)255, (byte)255}, 101 {(byte)255, 0, 0}, 102 {(byte)255, (byte)255, 0}, 103 {0, 0, (byte)255}, 104 {(byte)255, (byte)255, (byte)255}, 105 {0, 0, 0}, 106 {0, 0, (byte)255} 107 }; 108 109 private static void initBuf(byte[] buf, int w, int pitch, int h, int pf, 110 int flags) throws Exception { 111 int roffset = TJ.getRedOffset(pf); 112 int goffset = TJ.getGreenOffset(pf); 113 int boffset = TJ.getBlueOffset(pf); 114 int ps = TJ.getPixelSize(pf); 115 int index, row, col, halfway = 16; 116 117 Arrays.fill(buf, (byte)0); 118 if(pf == TJ.PF_GRAY) { 119 for(row = 0; row < h; row++) { 120 for(col = 0; col < w; col++) { 121 if((flags & TJ.FLAG_BOTTOMUP) != 0) 122 index = pitch * (h - row - 1) + col; 123 else index = pitch * row + col; 124 if(((row / 8) + (col / 8)) % 2 == 0) 125 buf[index] = (row < halfway) ? (byte)255 : 0; 126 else buf[index] = (row < halfway) ? 76 : (byte)226; 127 } 128 } 129 return; 130 } 131 for(row = 0; row < h; row++) { 132 for(col = 0; col < w; col++) { 133 if((flags & TJ.FLAG_BOTTOMUP) != 0) 134 index = pitch * (h - row - 1) + col * ps; 135 else index = pitch * row + col * ps; 136 if(((row / 8) + (col / 8)) % 2 == 0) { 137 if(row < halfway) { 138 buf[index + roffset] = (byte)255; 139 buf[index + goffset] = (byte)255; 140 buf[index + boffset] = (byte)255; 141 } 142 } 143 else { 144 buf[index + roffset] = (byte)255; 145 if(row >= halfway) buf[index + goffset] = (byte)255; 146 } 147 } 148 } 149 } 150 151 private static void initIntBuf(int[] buf, int w, int pitch, int h, int pf, 152 int flags) throws Exception { 153 int rshift = TJ.getRedOffset(pf) * 8; 154 int gshift = TJ.getGreenOffset(pf) * 8; 155 int bshift = TJ.getBlueOffset(pf) * 8; 156 int index, row, col, halfway = 16; 157 158 Arrays.fill(buf, 0); 159 for(row = 0; row < h; row++) { 160 for(col = 0; col < w; col++) { 161 if((flags & TJ.FLAG_BOTTOMUP) != 0) 162 index = pitch * (h - row - 1) + col; 163 else index = pitch * row + col; 164 if(((row / 8) + (col / 8)) % 2 == 0) { 165 if(row < halfway) { 166 buf[index] |= (255 << rshift); 167 buf[index] |= (255 << gshift); 168 buf[index] |= (255 << bshift); 169 } 170 } 171 else { 172 buf[index] |= (255 << rshift); 173 if(row >= halfway) buf[index] |= (255 << gshift); 174 } 175 } 176 } 177 } 178 179 private static void initImg(BufferedImage img, int pf, int flags) 180 throws Exception { 181 WritableRaster wr = img.getRaster(); 182 int imgtype = img.getType(); 183 if(imgtype == BufferedImage.TYPE_INT_RGB 184 || imgtype == BufferedImage.TYPE_INT_BGR) { 185 SinglePixelPackedSampleModel sm = 186 (SinglePixelPackedSampleModel)img.getSampleModel(); 187 int pitch = sm.getScanlineStride(); 188 DataBufferInt db = (DataBufferInt)wr.getDataBuffer(); 189 int[] buf = db.getData(); 190 initIntBuf(buf, img.getWidth(), pitch, img.getHeight(), pf, flags); 191 } 192 else { 193 ComponentSampleModel sm = (ComponentSampleModel)img.getSampleModel(); 194 int pitch = sm.getScanlineStride(); 195 DataBufferByte db = (DataBufferByte)wr.getDataBuffer(); 196 byte[] buf = db.getData(); 197 initBuf(buf, img.getWidth(), pitch, img.getHeight(), pf, flags); 198 } 199 } 200 201 private static void checkVal(int row, int col, int v, String vname, int cv) 202 throws Exception { 203 v = (v < 0) ? v + 256 : v; 204 if(v < cv - 1 || v > cv + 1) { 205 throw new Exception("\nComp. " + vname + " at " + row + "," + col 206 + " should be " + cv + ", not " + v + "\n"); 207 } 208 } 209 210 private static void checkVal0(int row, int col, int v, String vname) 211 throws Exception { 212 v = (v < 0) ? v + 256 : v; 213 if(v > 1) { 214 throw new Exception("\nComp. " + vname + " at " + row + "," + col 215 + " should be 0, not " + v + "\n"); 216 } 217 } 218 219 private static void checkVal255(int row, int col, int v, String vname) 220 throws Exception { 221 v = (v < 0) ? v + 256 : v; 222 if(v < 254) { 223 throw new Exception("\nComp. " + vname + " at " + row + "," + col 224 + " should be 255, not " + v + "\n"); 225 } 226 } 227 228 private static int checkBuf(byte[] buf, int w, int pitch, int h, int pf, 229 int subsamp, TJScalingFactor sf, int flags) throws Exception { 230 int roffset = TJ.getRedOffset(pf); 231 int goffset = TJ.getGreenOffset(pf); 232 int boffset = TJ.getBlueOffset(pf); 233 int ps = TJ.getPixelSize(pf); 234 int index, row, col, retval = 1; 235 int halfway = 16 * sf.getNum() / sf.getDenom(); 236 int blockSize = 8 * sf.getNum() / sf.getDenom(); 237 238 try { 239 for(row = 0; row < halfway; row++) { 240 for(col = 0; col < w; col++) { 241 if((flags & TJ.FLAG_BOTTOMUP) != 0) 242 index = pitch * (h - row - 1) + col * ps; 243 else index = pitch * row + col * ps; 244 byte r = buf[index + roffset]; 245 byte g = buf[index + goffset]; 246 byte b = buf[index + boffset]; 247 if(((row / blockSize) + (col / blockSize)) % 2 == 0) { 248 if(row < halfway) { 249 checkVal255(row, col, r, "R"); 250 checkVal255(row, col, g, "G"); 251 checkVal255(row, col, b, "B"); 252 } 253 else { 254 checkVal0(row, col, r, "R"); 255 checkVal0(row, col, g, "G"); 256 checkVal0(row, col, b, "B"); 257 } 258 } 259 else { 260 if(subsamp == TJ.SAMP_GRAY) { 261 if(row < halfway) { 262 checkVal(row, col, r, "R", 76); 263 checkVal(row, col, g, "G", 76); 264 checkVal(row, col, b, "B", 76); 265 } 266 else { 267 checkVal(row, col, r, "R", 226); 268 checkVal(row, col, g, "G", 226); 269 checkVal(row, col, b, "B", 226); 270 } 271 } 272 else { 273 checkVal255(row, col, r, "R"); 274 if(row < halfway) { 275 checkVal0(row, col, g, "G"); 276 } 277 else { 278 checkVal255(row, col, g, "G"); 279 } 280 checkVal0(row, col, b, "B"); 281 } 282 } 283 } 284 } 285 } 286 catch(Exception e) { 287 System.out.println(e); 288 retval = 0; 289 } 290 291 if(retval == 0) { 292 System.out.print("\n"); 293 for(row = 0; row < h; row++) { 294 for(col = 0; col < w; col++) { 295 int r = buf[pitch * row + col * ps + roffset]; 296 int g = buf[pitch * row + col * ps + goffset]; 297 int b = buf[pitch * row + col * ps + boffset]; 298 if(r < 0) r += 256; if(g < 0) g += 256; if(b < 0) b += 256; 299 System.out.format("%3d/%3d/%3d ", r, g, b); 300 } 301 System.out.print("\n"); 302 } 303 } 304 return retval; 305 } 306 307 private static int checkIntBuf(int[] buf, int w, int pitch, int h, int pf, 308 int subsamp, TJScalingFactor sf, int flags) throws Exception { 309 int rshift = TJ.getRedOffset(pf) * 8; 310 int gshift = TJ.getGreenOffset(pf) * 8; 311 int bshift = TJ.getBlueOffset(pf) * 8; 312 int index, row, col, retval = 1; 313 int halfway = 16 * sf.getNum() / sf.getDenom(); 314 int blockSize = 8 * sf.getNum() / sf.getDenom(); 315 316 try { 317 for(row = 0; row < halfway; row++) { 318 for(col = 0; col < w; col++) { 319 if((flags & TJ.FLAG_BOTTOMUP) != 0) 320 index = pitch * (h - row - 1) + col; 321 else index = pitch * row + col; 322 int r = (buf[index] >> rshift) & 0xFF; 323 int g = (buf[index] >> gshift) & 0xFF; 324 int b = (buf[index] >> bshift) & 0xFF; 325 if(((row / blockSize) + (col / blockSize)) % 2 == 0) { 326 if(row < halfway) { 327 checkVal255(row, col, r, "R"); 328 checkVal255(row, col, g, "G"); 329 checkVal255(row, col, b, "B"); 330 } 331 else { 332 checkVal0(row, col, r, "R"); 333 checkVal0(row, col, g, "G"); 334 checkVal0(row, col, b, "B"); 335 } 336 } 337 else { 338 if(subsamp == TJ.SAMP_GRAY) { 339 if(row < halfway) { 340 checkVal(row, col, r, "R", 76); 341 checkVal(row, col, g, "G", 76); 342 checkVal(row, col, b, "B", 76); 343 } 344 else { 345 checkVal(row, col, r, "R", 226); 346 checkVal(row, col, g, "G", 226); 347 checkVal(row, col, b, "B", 226); 348 } 349 } 350 else { 351 checkVal255(row, col, r, "R"); 352 if(row < halfway) { 353 checkVal0(row, col, g, "G"); 354 } 355 else { 356 checkVal255(row, col, g, "G"); 357 } 358 checkVal0(row, col, b, "B"); 359 } 360 } 361 } 362 } 363 } 364 catch(Exception e) { 365 System.out.println(e); 366 retval = 0; 367 } 368 369 if(retval == 0) { 370 System.out.print("\n"); 371 for(row = 0; row < h; row++) { 372 for(col = 0; col < w; col++) { 373 int r = (buf[pitch * row + col] >> rshift) & 0xFF; 374 int g = (buf[pitch * row + col] >> gshift) & 0xFF; 375 int b = (buf[pitch * row + col] >> bshift) & 0xFF; 376 if(r < 0) r += 256; if(g < 0) g += 256; if(b < 0) b += 256; 377 System.out.format("%3d/%3d/%3d ", r, g, b); 378 } 379 System.out.print("\n"); 380 } 381 } 382 return retval; 383 } 384 385 private static int checkImg(BufferedImage img, int pf, 386 int subsamp, TJScalingFactor sf, int flags) throws Exception { 387 WritableRaster wr = img.getRaster(); 388 int imgtype = img.getType(); 389 if(imgtype == BufferedImage.TYPE_INT_RGB 390 || imgtype == BufferedImage.TYPE_INT_BGR) { 391 SinglePixelPackedSampleModel sm = 392 (SinglePixelPackedSampleModel)img.getSampleModel(); 393 int pitch = sm.getScanlineStride(); 394 DataBufferInt db = (DataBufferInt)wr.getDataBuffer(); 395 int[] buf = db.getData(); 396 return checkIntBuf(buf, img.getWidth(), pitch, img.getHeight(), pf, 397 subsamp, sf, flags); 398 } 399 else { 400 ComponentSampleModel sm = (ComponentSampleModel)img.getSampleModel(); 401 int pitch = sm.getScanlineStride(); 402 DataBufferByte db = (DataBufferByte)wr.getDataBuffer(); 403 byte[] buf = db.getData(); 404 return checkBuf(buf, img.getWidth(), pitch, img.getHeight(), pf, subsamp, 405 sf, flags); 406 } 407 } 408 409 private static int PAD(int v, int p) { 410 return ((v + (p) - 1) & (~((p) - 1))); 411 } 412 413 private static int checkBufYUV(byte[] buf, int size, int w, int h, 414 int subsamp) throws Exception { 415 int i, j; 416 int hsf = TJ.getMCUWidth(subsamp)/8, vsf = TJ.getMCUHeight(subsamp)/8; 417 int pw = PAD(w, hsf), ph = PAD(h, vsf); 418 int cw = pw / hsf, ch = ph / vsf; 419 int ypitch = PAD(pw, 4), uvpitch = PAD(cw, 4); 420 int retval = 1; 421 int correctsize = ypitch * ph 422 + (subsamp == TJ.SAMP_GRAY ? 0 : uvpitch * ch * 2); 423 424 try { 425 if(size != correctsize) 426 throw new Exception("\nIncorrect size " + size + ". Should be " 427 + correctsize); 428 429 for(i = 0; i < 16; i++) { 430 for(j = 0; j < pw; j++) { 431 byte y = buf[ypitch * i + j]; 432 if(((i / 8) + (j / 8)) % 2 == 0) checkVal255(i, j, y, "Y"); 433 else checkVal(i, j, y, "Y", 76); 434 } 435 } 436 for(i = 16; i < ph; i++) { 437 for(j = 0; j < pw; j++) { 438 byte y = buf[ypitch * i + j]; 439 if(((i / 8) + (j / 8)) % 2 == 0) checkVal0(i, j, y, "Y"); 440 else checkVal(i, j, y, "Y", 226); 441 } 442 } 443 if(subsamp != TJ.SAMP_GRAY) { 444 for(i = 0; i < 16 / vsf; i++) { 445 for(j = 0; j < cw; j++) { 446 byte u = buf[ypitch * ph + (uvpitch * i + j)], 447 v = buf[ypitch * ph + uvpitch * ch + (uvpitch * i + j)]; 448 if(((i * vsf / 8) + (j * hsf / 8)) % 2 == 0) { 449 checkVal(i, j, u, "U", 128); checkVal(i, j, v, "V", 128); 450 } 451 else { 452 checkVal(i, j, u, "U", 85); checkVal255(i, j, v, "V"); 453 } 454 } 455 } 456 for(i = 16 / vsf; i < ch; i++) { 457 for(j = 0; j < cw; j++) { 458 byte u = buf[ypitch * ph + (uvpitch * i + j)], 459 v = buf[ypitch * ph + uvpitch * ch + (uvpitch * i + j)]; 460 if(((i * vsf / 8) + (j * hsf / 8)) % 2 == 0) { 461 checkVal(i, j, u, "U", 128); checkVal(i, j, v, "V", 128); 462 } 463 else { 464 checkVal0(i, j, u, "U"); checkVal(i, j, v, "V", 149); 465 } 466 } 467 } 468 } 469 } 470 catch(Exception e) { 471 System.out.println(e); 472 retval = 0; 473 } 474 475 if(retval == 0) { 476 for(i = 0; i < ph; i++) { 477 for(j = 0; j < pw; j++) { 478 int y = buf[ypitch * i + j]; 479 if(y < 0) y += 256; 480 System.out.format("%3d ", y); 481 } 482 System.out.print("\n"); 483 } 484 System.out.print("\n"); 485 for(i = 0; i < ch; i++) { 486 for(j = 0; j < cw; j++) { 487 int u = buf[ypitch * ph + (uvpitch * i + j)]; 488 if(u < 0) u += 256; 489 System.out.format("%3d ", u); 490 } 491 System.out.print("\n"); 492 } 493 System.out.print("\n"); 494 for(i = 0; i < ch; i++) { 495 for(j = 0; j < cw; j++) { 496 int v = buf[ypitch * ph + uvpitch * ch + (uvpitch * i + j)]; 497 if(v < 0) v += 256; 498 System.out.format("%3d ", v); 499 } 500 System.out.print("\n"); 501 } 502 System.out.print("\n"); 503 } 504 505 return retval; 506 } 507 508 private static void writeJPEG(byte[] jpegBuf, int jpegBufSize, 509 String filename) throws Exception { 510 File file = new File(filename); 511 FileOutputStream fos = new FileOutputStream(file); 512 fos.write(jpegBuf, 0, jpegBufSize); 513 fos.close(); 514 } 515 516 private static int compTest(TJCompressor tjc, byte[] dstBuf, int w, 517 int h, int pf, String baseName, int subsamp, int jpegQual, 518 int flags) throws Exception { 519 String tempstr; 520 byte[] srcBuf = null; 521 BufferedImage img = null; 522 String pfStr; 523 double t; 524 int size = 0, ps = TJ.getPixelSize(pf); 525 526 pfStr = pixFormatStr[pf]; 527 528 System.out.print(pfStr + " "); 529 if((flags & TJ.FLAG_BOTTOMUP) != 0) System.out.print("Bottom-Up"); 530 else System.out.print("Top-Down "); 531 System.out.print(" -> " + subNameLong[subsamp] + " "); 532 if(yuv == YUVENCODE) System.out.print("YUV ... "); 533 else System.out.print("Q" + jpegQual + " ... "); 534 535 if(bi) { 536 img = new BufferedImage(w, h, biType[pf]); 537 initImg(img, pf, flags); 538 tempstr = baseName + "_enc_" + pfStr + "_" 539 + (((flags & TJ.FLAG_BOTTOMUP) != 0) ? "BU" : "TD") + "_" 540 + subName[subsamp] + "_Q" + jpegQual + ".png"; 541 File file = new File(tempstr); 542 ImageIO.write(img, "png", file); 543 } 544 else { 545 srcBuf = new byte[w * h * ps + 1]; 546 initBuf(srcBuf, w, w * ps, h, pf, flags); 547 } 548 Arrays.fill(dstBuf, (byte)0); 549 550 t = getTime(); 551 tjc.setSubsamp(subsamp); 552 tjc.setJPEGQuality(jpegQual); 553 if(bi) { 554 if(yuv == YUVENCODE) tjc.encodeYUV(img, dstBuf, flags); 555 else tjc.compress(img, dstBuf, flags); 556 } 557 else { 558 tjc.setSourceImage(srcBuf, w, 0, h, pf); 559 if(yuv == YUVENCODE) tjc.encodeYUV(dstBuf, flags); 560 else tjc.compress(dstBuf, flags); 561 } 562 size = tjc.getCompressedSize(); 563 t = getTime() - t; 564 565 if(yuv == YUVENCODE) 566 tempstr = baseName + "_enc_" + pfStr + "_" 567 + (((flags & TJ.FLAG_BOTTOMUP) != 0) ? "BU" : "TD") + "_" 568 + subName[subsamp] + ".yuv"; 569 else 570 tempstr = baseName + "_enc_" + pfStr + "_" 571 + (((flags & TJ.FLAG_BOTTOMUP) != 0) ? "BU" : "TD") + "_" 572 + subName[subsamp] + "_Q" + jpegQual + ".jpg"; 573 writeJPEG(dstBuf, size, tempstr); 574 575 if(yuv == YUVENCODE) { 576 if(checkBufYUV(dstBuf, size, w, h, subsamp) == 1) 577 System.out.print("Passed."); 578 else { 579 System.out.print("FAILED!"); exitStatus = -1; 580 } 581 } 582 else System.out.print("Done."); 583 System.out.format(" %.6f ms\n", t * 1000.); 584 System.out.println(" Result in " + tempstr); 585 586 return size; 587 } 588 589 private static void decompTest(TJDecompressor tjd, byte[] jpegBuf, 590 int jpegSize, int w, int h, int pf, String baseName, int subsamp, 591 int flags, TJScalingFactor sf) throws Exception { 592 String pfStr, tempstr; 593 double t; 594 int scaledWidth = sf.getScaled(w); 595 int scaledHeight = sf.getScaled(h); 596 int temp1, temp2; 597 BufferedImage img = null; 598 byte[] dstBuf = null; 599 600 if(yuv == YUVENCODE) return; 601 602 pfStr = pixFormatStr[pf]; 603 System.out.print("JPEG -> "); 604 if(yuv == YUVDECODE) 605 System.out.print("YUV " + subName[subsamp] + " ... "); 606 else { 607 System.out.print(pfStr + " "); 608 if((flags & TJ.FLAG_BOTTOMUP) != 0) System.out.print("Bottom-Up "); 609 else System.out.print("Top-Down "); 610 if(!sf.isOne()) 611 System.out.print(sf.getNum() + "/" + sf.getDenom() + " ... "); 612 else System.out.print("... "); 613 } 614 615 t = getTime(); 616 tjd.setJPEGImage(jpegBuf, jpegSize); 617 if(tjd.getWidth() != w || tjd.getHeight() != h 618 || tjd.getSubsamp() != subsamp) 619 throw new Exception("Incorrect JPEG header"); 620 621 temp1 = scaledWidth; 622 temp2 = scaledHeight; 623 temp1 = tjd.getScaledWidth(temp1, temp2); 624 temp2 = tjd.getScaledHeight(temp1, temp2); 625 if(temp1 != scaledWidth || temp2 != scaledHeight) 626 throw new Exception("Scaled size mismatch"); 627 628 if(yuv == YUVDECODE) dstBuf = tjd.decompressToYUV(flags); 629 else { 630 if(bi) 631 img = tjd.decompress(scaledWidth, scaledHeight, biType[pf], flags); 632 else dstBuf = tjd.decompress(scaledWidth, 0, scaledHeight, pf, flags); 633 } 634 t = getTime() - t; 635 636 if(bi) { 637 tempstr = baseName + "_dec_" + pfStr + "_" 638 + (((flags & TJ.FLAG_BOTTOMUP) != 0) ? "BU" : "TD") + "_" 639 + subName[subsamp] + "_" + (double)sf.getNum() / (double)sf.getDenom() 640 + "x" + ".png"; 641 File file = new File(tempstr); 642 ImageIO.write(img, "png", file); 643 } 644 645 if(yuv == YUVDECODE) { 646 if(checkBufYUV(dstBuf, dstBuf.length, w, h, subsamp) == 1) 647 System.out.print("Passed."); 648 else { 649 System.out.print("FAILED!"); exitStatus = -1; 650 } 651 } 652 else { 653 if((bi && checkImg(img, pf, subsamp, sf, flags) == 1) 654 || (!bi && checkBuf(dstBuf, scaledWidth, scaledWidth 655 * TJ.getPixelSize(pf), scaledHeight, pf, subsamp, sf, flags) == 1)) 656 System.out.print("Passed."); 657 else { 658 System.out.print("FAILED!"); exitStatus = -1; 659 } 660 } 661 System.out.format(" %.6f ms\n", t * 1000.); 662 } 663 664 private static void decompTest(TJDecompressor tjd, byte[] jpegBuf, 665 int jpegSize, int w, int h, int pf, String baseName, int subsamp, 666 int flags) throws Exception { 667 int i; 668 if((subsamp == TJ.SAMP_444 || subsamp == TJ.SAMP_GRAY) && yuv == 0) { 669 TJScalingFactor sf[] = TJ.getScalingFactors(); 670 for(i = 0; i < sf.length; i++) 671 decompTest(tjd, jpegBuf, jpegSize, w, h, pf, baseName, subsamp, 672 flags, sf[i]); 673 } 674 else 675 decompTest(tjd, jpegBuf, jpegSize, w, h, pf, baseName, subsamp, 676 flags, new TJScalingFactor(1, 1)); 677 System.out.print("\n"); 678 } 679 680 private static void doTest(int w, int h, int[] formats, int subsamp, 681 String baseName) throws Exception { 682 TJCompressor tjc = null; 683 TJDecompressor tjd = null; 684 int size; 685 byte[] dstBuf; 686 687 if(yuv == YUVENCODE) dstBuf = new byte[TJ.bufSizeYUV(w, h, subsamp)]; 688 else dstBuf = new byte[TJ.bufSize(w, h)]; 689 690 try { 691 tjc = new TJCompressor(); 692 tjd = new TJDecompressor(); 693 694 for(int pf : formats) { 695 for(int i = 0; i < 2; i++) { 696 int flags = 0; 697 if(i == 1) { 698 if(yuv == YUVDECODE) { 699 tjc.close(); tjd.close(); return; 700 } 701 else flags |= TJ.FLAG_BOTTOMUP; 702 } 703 size = compTest(tjc, dstBuf, w, h, pf, baseName, subsamp, 100, 704 flags); 705 decompTest(tjd, dstBuf, size, w, h, pf, baseName, subsamp, flags); 706 } 707 } 708 } 709 catch(Exception e) { 710 if(tjc != null) tjc.close(); 711 if(tjd != null) tjd.close(); 712 throw e; 713 } 714 if(tjc != null) tjc.close(); 715 if(tjd != null) tjd.close(); 716 } 717 718 private static void doTest1() throws Exception { 719 int w, h, i; 720 byte[] srcBuf, jpegBuf; 721 TJCompressor tjc = null; 722 723 try { 724 tjc = new TJCompressor(); 725 System.out.println("Buffer size regression test"); 726 for(w = 1; w < 48; w++) { 727 int maxh = (w == 1) ? 2048 : 48; 728 for(h = 1; h < maxh; h++) { 729 if(h % 100 == 0) 730 System.out.format("%04d x %04d\b\b\b\b\b\b\b\b\b\b\b", w, h); 731 srcBuf = new byte[w * h * 4]; 732 jpegBuf = new byte[TJ.bufSize(w, h)]; 733 Arrays.fill(srcBuf, (byte)0); 734 for(i = 0; i < w * h; i++) { 735 srcBuf[i * 4] = pixels[i % 9][0]; 736 srcBuf[i * 4 + 1] = pixels[i % 9][1]; 737 srcBuf[i * 4 + 2] = pixels[i % 9][2]; 738 } 739 tjc.setSourceImage(srcBuf, w, 0, h, TJ.PF_BGRX); 740 tjc.setSubsamp(TJ.SAMP_444); 741 tjc.setJPEGQuality(100); 742 tjc.compress(jpegBuf, 0); 743 744 srcBuf = new byte[h * w * 4]; 745 jpegBuf = new byte[TJ.bufSize(h, w)]; 746 for(i = 0; i < h * w; i++) { 747 if(i % 2 == 0) srcBuf[i * 4] = 748 srcBuf[i * 4 + 1] = srcBuf[i * 4 + 2] = (byte)0xFF; 749 else srcBuf[i * 4] = srcBuf[i * 4 + 1] = srcBuf[i * 4 + 2] = 0; 750 } 751 tjc.setSourceImage(srcBuf, h, 0, w, TJ.PF_BGRX); 752 tjc.compress(jpegBuf, 0); 753 } 754 } 755 System.out.println("Done. "); 756 } 757 catch(Exception e) { 758 if(tjc != null) tjc.close(); 759 throw e; 760 } 761 if(tjc != null) tjc.close(); 762 } 763 764 public static void main(String argv[]) { 765 try { 766 String testName = "javatest"; 767 boolean doyuv = false; 768 for(int i = 0; i < argv.length; i++) { 769 if(argv[i].equalsIgnoreCase("-yuv")) doyuv = true; 770 if(argv[i].substring(0, 1).equalsIgnoreCase("-h") 771 || argv[i].equalsIgnoreCase("-?")) 772 usage(); 773 if(argv[i].equalsIgnoreCase("-bi")) { 774 bi = true; 775 testName = "javabitest"; 776 } 777 } 778 if(doyuv) yuv = YUVENCODE; 779 doTest(35, 39, bi ? _3byteFormatsBI : _3byteFormats, TJ.SAMP_444, testName); 780 doTest(39, 41, bi ? _4byteFormatsBI : _4byteFormats, TJ.SAMP_444, testName); 781 if(doyuv) { 782 doTest(41, 35, bi ? _3byteFormatsBI : _3byteFormats, TJ.SAMP_422, 783 testName); 784 doTest(35, 39, bi ? _4byteFormatsBI : _4byteFormats, TJ.SAMP_422, 785 testName); 786 doTest(39, 41, bi ? _3byteFormatsBI : _3byteFormats, TJ.SAMP_420, 787 testName); 788 doTest(41, 35, bi ? _4byteFormatsBI : _4byteFormats, TJ.SAMP_420, 789 testName); 790 doTest(35, 39, bi ? _3byteFormatsBI : _3byteFormats, TJ.SAMP_440, 791 testName); 792 doTest(39, 41, bi ? _4byteFormatsBI : _4byteFormats, TJ.SAMP_440, 793 testName); 794 } 795 doTest(35, 39, onlyGray, TJ.SAMP_GRAY, testName); 796 doTest(39, 41, bi ? _3byteFormatsBI : _3byteFormats, TJ.SAMP_GRAY, 797 testName); 798 doTest(41, 35, bi ? _4byteFormatsBI : _4byteFormats, TJ.SAMP_GRAY, 799 testName); 800 if(!doyuv && !bi) doTest1(); 801 if(doyuv && !bi) { 802 yuv = YUVDECODE; 803 doTest(48, 48, onlyRGB, TJ.SAMP_444, "javatest_yuv0"); 804 doTest(35, 39, onlyRGB, TJ.SAMP_444, "javatest_yuv1"); 805 doTest(48, 48, onlyRGB, TJ.SAMP_422, "javatest_yuv0"); 806 doTest(39, 41, onlyRGB, TJ.SAMP_422, "javatest_yuv1"); 807 doTest(48, 48, onlyRGB, TJ.SAMP_420, "javatest_yuv0"); 808 doTest(41, 35, onlyRGB, TJ.SAMP_420, "javatest_yuv1"); 809 doTest(48, 48, onlyRGB, TJ.SAMP_440, "javatest_yuv0"); 810 doTest(35, 39, onlyRGB, TJ.SAMP_440, "javatest_yuv1"); 811 doTest(48, 48, onlyRGB, TJ.SAMP_GRAY, "javatest_yuv0"); 812 doTest(35, 39, onlyRGB, TJ.SAMP_GRAY, "javatest_yuv1"); 813 doTest(48, 48, onlyGray, TJ.SAMP_GRAY, "javatest_yuv0"); 814 doTest(39, 41, onlyGray, TJ.SAMP_GRAY, "javatest_yuv1"); 815 } 816 } 817 catch(Exception e) { 818 e.printStackTrace(); 819 exitStatus = -1; 820 } 821 System.exit(exitStatus); 822 } 823} 824