shun-iwasawa 82a8f5
/*
shun-iwasawa 82a8f5
 * Copyright (C)2011-2018 D. R. Commander.  All Rights Reserved.
shun-iwasawa 82a8f5
 *
shun-iwasawa 82a8f5
 * Redistribution and use in source and binary forms, with or without
shun-iwasawa 82a8f5
 * modification, are permitted provided that the following conditions are met:
shun-iwasawa 82a8f5
 *
shun-iwasawa 82a8f5
 * - Redistributions of source code must retain the above copyright notice,
shun-iwasawa 82a8f5
 *   this list of conditions and the following disclaimer.
shun-iwasawa 82a8f5
 * - Redistributions in binary form must reproduce the above copyright notice,
shun-iwasawa 82a8f5
 *   this list of conditions and the following disclaimer in the documentation
shun-iwasawa 82a8f5
 *   and/or other materials provided with the distribution.
shun-iwasawa 82a8f5
 * - Neither the name of the libjpeg-turbo Project nor the names of its
shun-iwasawa 82a8f5
 *   contributors may be used to endorse or promote products derived from this
shun-iwasawa 82a8f5
 *   software without specific prior written permission.
shun-iwasawa 82a8f5
 *
shun-iwasawa 82a8f5
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS",
shun-iwasawa 82a8f5
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
shun-iwasawa 82a8f5
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
shun-iwasawa 82a8f5
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
shun-iwasawa 82a8f5
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
shun-iwasawa 82a8f5
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
shun-iwasawa 82a8f5
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
shun-iwasawa 82a8f5
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
shun-iwasawa 82a8f5
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
shun-iwasawa 82a8f5
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
shun-iwasawa 82a8f5
 * POSSIBILITY OF SUCH DAMAGE.
shun-iwasawa 82a8f5
 */
shun-iwasawa 82a8f5
shun-iwasawa 82a8f5
/*
shun-iwasawa 82a8f5
 * This program tests the various code paths in the TurboJPEG JNI Wrapper
shun-iwasawa 82a8f5
 */
shun-iwasawa 82a8f5
shun-iwasawa 82a8f5
import java.io.*;
shun-iwasawa 82a8f5
import java.util.*;
shun-iwasawa 82a8f5
import java.awt.image.*;
shun-iwasawa 82a8f5
import javax.imageio.*;
shun-iwasawa 82a8f5
import java.nio.*;
shun-iwasawa 82a8f5
import org.libjpegturbo.turbojpeg.*;
shun-iwasawa 82a8f5
shun-iwasawa 82a8f5
@SuppressWarnings("checkstyle:JavadocType")
shun-iwasawa 82a8f5
final class TJUnitTest {
shun-iwasawa 82a8f5
shun-iwasawa 82a8f5
  private TJUnitTest() {}
shun-iwasawa 82a8f5
shun-iwasawa 82a8f5
  static final String CLASS_NAME =
shun-iwasawa 82a8f5
    new TJUnitTest().getClass().getName();
shun-iwasawa 82a8f5
shun-iwasawa 82a8f5
  static void usage() {
shun-iwasawa 82a8f5
    System.out.println("\nUSAGE: java " + CLASS_NAME + " [options]\n");
shun-iwasawa 82a8f5
    System.out.println("Options:");
shun-iwasawa 82a8f5
    System.out.println("-yuv = test YUV encoding/decoding support");
shun-iwasawa 82a8f5
    System.out.println("-noyuvpad = do not pad each line of each Y, U, and V plane to the nearest");
shun-iwasawa 82a8f5
    System.out.println("            4-byte boundary");
shun-iwasawa 82a8f5
    System.out.println("-bi = test BufferedImage support\n");
shun-iwasawa 82a8f5
    System.exit(1);
shun-iwasawa 82a8f5
  }
shun-iwasawa 82a8f5
shun-iwasawa 82a8f5
  static final String[] SUBNAME_LONG = {
shun-iwasawa 82a8f5
    "4:4:4", "4:2:2", "4:2:0", "GRAY", "4:4:0", "4:1:1"
shun-iwasawa 82a8f5
  };
shun-iwasawa 82a8f5
  static final String[] SUBNAME = {
shun-iwasawa 82a8f5
    "444", "422", "420", "GRAY", "440", "411"
shun-iwasawa 82a8f5
  };
shun-iwasawa 82a8f5
shun-iwasawa 82a8f5
  static final String[] PIXFORMATSTR = {
shun-iwasawa 82a8f5
    "RGB", "BGR", "RGBX", "BGRX", "XBGR", "XRGB", "Grayscale",
shun-iwasawa 82a8f5
    "RGBA", "BGRA", "ABGR", "ARGB", "CMYK"
shun-iwasawa 82a8f5
  };
shun-iwasawa 82a8f5
shun-iwasawa 82a8f5
  static final int[] FORMATS_3BYTE = {
shun-iwasawa 82a8f5
    TJ.PF_RGB, TJ.PF_BGR
shun-iwasawa 82a8f5
  };
shun-iwasawa 82a8f5
  static final int[] FORMATS_3BYTEBI = {
shun-iwasawa 82a8f5
    BufferedImage.TYPE_3BYTE_BGR
shun-iwasawa 82a8f5
  };
shun-iwasawa 82a8f5
  static final int[] FORMATS_4BYTE = {
shun-iwasawa 82a8f5
    TJ.PF_RGBX, TJ.PF_BGRX, TJ.PF_XBGR, TJ.PF_XRGB, TJ.PF_CMYK
shun-iwasawa 82a8f5
  };
shun-iwasawa 82a8f5
  static final int[] FORMATS_4BYTEBI = {
shun-iwasawa 82a8f5
    BufferedImage.TYPE_INT_BGR, BufferedImage.TYPE_INT_RGB,
shun-iwasawa 82a8f5
    BufferedImage.TYPE_4BYTE_ABGR, BufferedImage.TYPE_4BYTE_ABGR_PRE,
shun-iwasawa 82a8f5
    BufferedImage.TYPE_INT_ARGB, BufferedImage.TYPE_INT_ARGB_PRE
shun-iwasawa 82a8f5
  };
shun-iwasawa 82a8f5
  static final int[] FORMATS_GRAY = {
shun-iwasawa 82a8f5
    TJ.PF_GRAY
shun-iwasawa 82a8f5
  };
shun-iwasawa 82a8f5
  static final int[] FORMATS_GRAYBI = {
shun-iwasawa 82a8f5
    BufferedImage.TYPE_BYTE_GRAY
shun-iwasawa 82a8f5
  };
shun-iwasawa 82a8f5
  static final int[] FORMATS_RGB = {
shun-iwasawa 82a8f5
    TJ.PF_RGB
shun-iwasawa 82a8f5
  };
shun-iwasawa 82a8f5
shun-iwasawa 82a8f5
  private static boolean doYUV = false;
shun-iwasawa 82a8f5
  private static int pad = 4;
shun-iwasawa 82a8f5
  private static boolean bi = false;
shun-iwasawa 82a8f5
shun-iwasawa 82a8f5
  private static int exitStatus = 0;
shun-iwasawa 82a8f5
shun-iwasawa 82a8f5
  static int biTypePF(int biType) {
shun-iwasawa 82a8f5
    ByteOrder byteOrder = ByteOrder.nativeOrder();
shun-iwasawa 82a8f5
    switch (biType) {
shun-iwasawa 82a8f5
    case BufferedImage.TYPE_3BYTE_BGR:
shun-iwasawa 82a8f5
      return TJ.PF_BGR;
shun-iwasawa 82a8f5
    case BufferedImage.TYPE_4BYTE_ABGR:
shun-iwasawa 82a8f5
    case BufferedImage.TYPE_4BYTE_ABGR_PRE:
shun-iwasawa 82a8f5
      return TJ.PF_ABGR;
shun-iwasawa 82a8f5
    case BufferedImage.TYPE_BYTE_GRAY:
shun-iwasawa 82a8f5
      return TJ.PF_GRAY;
shun-iwasawa 82a8f5
    case BufferedImage.TYPE_INT_BGR:
shun-iwasawa 82a8f5
      return TJ.PF_RGBX;
shun-iwasawa 82a8f5
    case BufferedImage.TYPE_INT_RGB:
shun-iwasawa 82a8f5
      return TJ.PF_BGRX;
shun-iwasawa 82a8f5
    case BufferedImage.TYPE_INT_ARGB:
shun-iwasawa 82a8f5
    case BufferedImage.TYPE_INT_ARGB_PRE:
shun-iwasawa 82a8f5
      return TJ.PF_BGRA;
shun-iwasawa 82a8f5
    default:
shun-iwasawa 82a8f5
      return 0;
shun-iwasawa 82a8f5
    }
shun-iwasawa 82a8f5
  }
shun-iwasawa 82a8f5
shun-iwasawa 82a8f5
  static String biTypeStr(int biType) {
shun-iwasawa 82a8f5
    switch (biType) {
shun-iwasawa 82a8f5
    case BufferedImage.TYPE_3BYTE_BGR:
shun-iwasawa 82a8f5
      return "3BYTE_BGR";
shun-iwasawa 82a8f5
    case BufferedImage.TYPE_4BYTE_ABGR:
shun-iwasawa 82a8f5
      return "4BYTE_ABGR";
shun-iwasawa 82a8f5
    case BufferedImage.TYPE_4BYTE_ABGR_PRE:
shun-iwasawa 82a8f5
      return "4BYTE_ABGR_PRE";
shun-iwasawa 82a8f5
    case BufferedImage.TYPE_BYTE_GRAY:
shun-iwasawa 82a8f5
      return "BYTE_GRAY";
shun-iwasawa 82a8f5
    case BufferedImage.TYPE_INT_BGR:
shun-iwasawa 82a8f5
      return "INT_BGR";
shun-iwasawa 82a8f5
    case BufferedImage.TYPE_INT_RGB:
shun-iwasawa 82a8f5
      return "INT_RGB";
shun-iwasawa 82a8f5
    case BufferedImage.TYPE_INT_ARGB:
shun-iwasawa 82a8f5
      return "INT_ARGB";
shun-iwasawa 82a8f5
    case BufferedImage.TYPE_INT_ARGB_PRE:
shun-iwasawa 82a8f5
      return "INT_ARGB_PRE";
shun-iwasawa 82a8f5
    default:
shun-iwasawa 82a8f5
      return "Unknown";
shun-iwasawa 82a8f5
    }
shun-iwasawa 82a8f5
  }
shun-iwasawa 82a8f5
shun-iwasawa 82a8f5
  static void initBuf(byte[] buf, int w, int pitch, int h, int pf, int flags)
shun-iwasawa 82a8f5
                      throws Exception {
shun-iwasawa 82a8f5
    int roffset = TJ.getRedOffset(pf);
shun-iwasawa 82a8f5
    int goffset = TJ.getGreenOffset(pf);
shun-iwasawa 82a8f5
    int boffset = TJ.getBlueOffset(pf);
shun-iwasawa 82a8f5
    int aoffset = TJ.getAlphaOffset(pf);
shun-iwasawa 82a8f5
    int ps = TJ.getPixelSize(pf);
shun-iwasawa 82a8f5
    int index, row, col, halfway = 16;
shun-iwasawa 82a8f5
shun-iwasawa 82a8f5
    if (pf == TJ.PF_GRAY) {
shun-iwasawa 82a8f5
      Arrays.fill(buf, (byte)0);
shun-iwasawa 82a8f5
      for (row = 0; row < h; row++) {
shun-iwasawa 82a8f5
        for (col = 0; col < w; col++) {
shun-iwasawa 82a8f5
          if ((flags & TJ.FLAG_BOTTOMUP) != 0)
shun-iwasawa 82a8f5
            index = pitch * (h - row - 1) + col;
shun-iwasawa 82a8f5
          else
shun-iwasawa 82a8f5
            index = pitch * row + col;
shun-iwasawa 82a8f5
          if (((row / 8) + (col / 8)) % 2 == 0)
shun-iwasawa 82a8f5
            buf[index] = (row < halfway) ? (byte)255 : 0;
shun-iwasawa 82a8f5
          else
shun-iwasawa 82a8f5
            buf[index] = (row < halfway) ? 76 : (byte)226;
shun-iwasawa 82a8f5
        }
shun-iwasawa 82a8f5
      }
shun-iwasawa 82a8f5
      return;
shun-iwasawa 82a8f5
    }
shun-iwasawa 82a8f5
    if (pf == TJ.PF_CMYK) {
shun-iwasawa 82a8f5
      Arrays.fill(buf, (byte)255);
shun-iwasawa 82a8f5
      for (row = 0; row < h; row++) {
shun-iwasawa 82a8f5
        for (col = 0; col < w; col++) {
shun-iwasawa 82a8f5
          if ((flags & TJ.FLAG_BOTTOMUP) != 0)
shun-iwasawa 82a8f5
            index = (h - row - 1) * w + col;
shun-iwasawa 82a8f5
          else
shun-iwasawa 82a8f5
            index = row * w + col;
shun-iwasawa 82a8f5
          if (((row / 8) + (col / 8)) % 2 == 0) {
shun-iwasawa 82a8f5
            if (row >= halfway) buf[index * ps + 3] = 0;
shun-iwasawa 82a8f5
          } else {
shun-iwasawa 82a8f5
            buf[index * ps + 2] = 0;
shun-iwasawa 82a8f5
            if (row < halfway)
shun-iwasawa 82a8f5
              buf[index * ps + 1] = 0;
shun-iwasawa 82a8f5
          }
shun-iwasawa 82a8f5
        }
shun-iwasawa 82a8f5
      }
shun-iwasawa 82a8f5
      return;
shun-iwasawa 82a8f5
    }
shun-iwasawa 82a8f5
shun-iwasawa 82a8f5
    Arrays.fill(buf, (byte)0);
shun-iwasawa 82a8f5
    for (row = 0; row < h; row++) {
shun-iwasawa 82a8f5
      for (col = 0; col < w; col++) {
shun-iwasawa 82a8f5
        if ((flags & TJ.FLAG_BOTTOMUP) != 0)
shun-iwasawa 82a8f5
          index = pitch * (h - row - 1) + col * ps;
shun-iwasawa 82a8f5
        else
shun-iwasawa 82a8f5
          index = pitch * row + col * ps;
shun-iwasawa 82a8f5
        if (((row / 8) + (col / 8)) % 2 == 0) {
shun-iwasawa 82a8f5
          if (row < halfway) {
shun-iwasawa 82a8f5
            buf[index + roffset] = (byte)255;
shun-iwasawa 82a8f5
            buf[index + goffset] = (byte)255;
shun-iwasawa 82a8f5
            buf[index + boffset] = (byte)255;
shun-iwasawa 82a8f5
          }
shun-iwasawa 82a8f5
        } else {
shun-iwasawa 82a8f5
          buf[index + roffset] = (byte)255;
shun-iwasawa 82a8f5
          if (row >= halfway)
shun-iwasawa 82a8f5
            buf[index + goffset] = (byte)255;
shun-iwasawa 82a8f5
        }
shun-iwasawa 82a8f5
        if (aoffset >= 0)
shun-iwasawa 82a8f5
          buf[index + aoffset] = (byte)255;
shun-iwasawa 82a8f5
      }
shun-iwasawa 82a8f5
    }
shun-iwasawa 82a8f5
  }
shun-iwasawa 82a8f5
shun-iwasawa 82a8f5
  static void initIntBuf(int[] buf, int w, int pitch, int h, int pf, int flags)
shun-iwasawa 82a8f5
                         throws Exception {
shun-iwasawa 82a8f5
    int rshift = TJ.getRedOffset(pf) * 8;
shun-iwasawa 82a8f5
    int gshift = TJ.getGreenOffset(pf) * 8;
shun-iwasawa 82a8f5
    int bshift = TJ.getBlueOffset(pf) * 8;
shun-iwasawa 82a8f5
    int ashift = TJ.getAlphaOffset(pf) * 8;
shun-iwasawa 82a8f5
    int index, row, col, halfway = 16;
shun-iwasawa 82a8f5
shun-iwasawa 82a8f5
    Arrays.fill(buf, 0);
shun-iwasawa 82a8f5
    for (row = 0; row < h; row++) {
shun-iwasawa 82a8f5
      for (col = 0; col < w; col++) {
shun-iwasawa 82a8f5
        if ((flags & TJ.FLAG_BOTTOMUP) != 0)
shun-iwasawa 82a8f5
          index = pitch * (h - row - 1) + col;
shun-iwasawa 82a8f5
        else
shun-iwasawa 82a8f5
          index = pitch * row + col;
shun-iwasawa 82a8f5
        if (((row / 8) + (col / 8)) % 2 == 0) {
shun-iwasawa 82a8f5
          if (row < halfway) {
shun-iwasawa 82a8f5
            buf[index] |= (255 << rshift);
shun-iwasawa 82a8f5
            buf[index] |= (255 << gshift);
shun-iwasawa 82a8f5
            buf[index] |= (255 << bshift);
shun-iwasawa 82a8f5
          }
shun-iwasawa 82a8f5
        } else {
shun-iwasawa 82a8f5
          buf[index] |= (255 << rshift);
shun-iwasawa 82a8f5
          if (row >= halfway)
shun-iwasawa 82a8f5
            buf[index] |= (255 << gshift);
shun-iwasawa 82a8f5
        }
shun-iwasawa 82a8f5
        if (ashift >= 0)
shun-iwasawa 82a8f5
          buf[index] |= (255 << ashift);
shun-iwasawa 82a8f5
      }
shun-iwasawa 82a8f5
    }
shun-iwasawa 82a8f5
  }
shun-iwasawa 82a8f5
shun-iwasawa 82a8f5
  static void initImg(BufferedImage img, int pf, int flags) throws Exception {
shun-iwasawa 82a8f5
    WritableRaster wr = img.getRaster();
shun-iwasawa 82a8f5
    int imgType = img.getType();
shun-iwasawa 82a8f5
shun-iwasawa 82a8f5
    if (imgType == BufferedImage.TYPE_INT_RGB ||
shun-iwasawa 82a8f5
        imgType == BufferedImage.TYPE_INT_BGR ||
shun-iwasawa 82a8f5
        imgType == BufferedImage.TYPE_INT_ARGB ||
shun-iwasawa 82a8f5
        imgType == BufferedImage.TYPE_INT_ARGB_PRE) {
shun-iwasawa 82a8f5
      SinglePixelPackedSampleModel sm =
shun-iwasawa 82a8f5
        (SinglePixelPackedSampleModel)img.getSampleModel();
shun-iwasawa 82a8f5
      int pitch = sm.getScanlineStride();
shun-iwasawa 82a8f5
      DataBufferInt db = (DataBufferInt)wr.getDataBuffer();
shun-iwasawa 82a8f5
      int[] buf = db.getData();
shun-iwasawa 82a8f5
      initIntBuf(buf, img.getWidth(), pitch, img.getHeight(), pf, flags);
shun-iwasawa 82a8f5
    } else {
shun-iwasawa 82a8f5
      ComponentSampleModel sm = (ComponentSampleModel)img.getSampleModel();
shun-iwasawa 82a8f5
      int pitch = sm.getScanlineStride();
shun-iwasawa 82a8f5
      DataBufferByte db = (DataBufferByte)wr.getDataBuffer();
shun-iwasawa 82a8f5
      byte[] buf = db.getData();
shun-iwasawa 82a8f5
      initBuf(buf, img.getWidth(), pitch, img.getHeight(), pf, flags);
shun-iwasawa 82a8f5
    }
shun-iwasawa 82a8f5
  }
shun-iwasawa 82a8f5
shun-iwasawa 82a8f5
  static void checkVal(int row, int col, int v, String vname, int cv)
shun-iwasawa 82a8f5
                       throws Exception {
shun-iwasawa 82a8f5
    v = (v < 0) ? v + 256 : v;
shun-iwasawa 82a8f5
    if (v < cv - 1 || v > cv + 1) {
shun-iwasawa 82a8f5
      throw new Exception("Comp. " + vname + " at " + row + "," + col +
shun-iwasawa 82a8f5
                          " should be " + cv + ", not " + v);
shun-iwasawa 82a8f5
    }
shun-iwasawa 82a8f5
  }
shun-iwasawa 82a8f5
shun-iwasawa 82a8f5
  static void checkVal0(int row, int col, int v, String vname)
shun-iwasawa 82a8f5
                        throws Exception {
shun-iwasawa 82a8f5
    v = (v < 0) ? v + 256 : v;
shun-iwasawa 82a8f5
    if (v > 1) {
shun-iwasawa 82a8f5
      throw new Exception("Comp. " + vname + " at " + row + "," + col +
shun-iwasawa 82a8f5
                          " should be 0, not " + v);
shun-iwasawa 82a8f5
    }
shun-iwasawa 82a8f5
  }
shun-iwasawa 82a8f5
shun-iwasawa 82a8f5
  static void checkVal255(int row, int col, int v, String vname)
shun-iwasawa 82a8f5
                          throws Exception {
shun-iwasawa 82a8f5
    v = (v < 0) ? v + 256 : v;
shun-iwasawa 82a8f5
    if (v < 254) {
shun-iwasawa 82a8f5
      throw new Exception("Comp. " + vname + " at " + row + "," + col +
shun-iwasawa 82a8f5
                          " should be 255, not " + v);
shun-iwasawa 82a8f5
    }
shun-iwasawa 82a8f5
  }
shun-iwasawa 82a8f5
shun-iwasawa 82a8f5
  static int checkBuf(byte[] buf, int w, int pitch, int h, int pf, int subsamp,
shun-iwasawa 82a8f5
                      TJScalingFactor sf, int flags) throws Exception {
shun-iwasawa 82a8f5
    int roffset = TJ.getRedOffset(pf);
shun-iwasawa 82a8f5
    int goffset = TJ.getGreenOffset(pf);
shun-iwasawa 82a8f5
    int boffset = TJ.getBlueOffset(pf);
shun-iwasawa 82a8f5
    int aoffset = TJ.getAlphaOffset(pf);
shun-iwasawa 82a8f5
    int ps = TJ.getPixelSize(pf);
shun-iwasawa 82a8f5
    int index, row, col, retval = 1;
shun-iwasawa 82a8f5
    int halfway = 16 * sf.getNum() / sf.getDenom();
shun-iwasawa 82a8f5
    int blockSize = 8 * sf.getNum() / sf.getDenom();
shun-iwasawa 82a8f5
shun-iwasawa 82a8f5
    try {
shun-iwasawa 82a8f5
shun-iwasawa 82a8f5
      if (pf == TJ.PF_GRAY)
shun-iwasawa 82a8f5
        roffset = goffset = boffset = 0;
shun-iwasawa 82a8f5
shun-iwasawa 82a8f5
      if (pf == TJ.PF_CMYK) {
shun-iwasawa 82a8f5
        for (row = 0; row < h; row++) {
shun-iwasawa 82a8f5
          for (col = 0; col < w; col++) {
shun-iwasawa 82a8f5
            if ((flags & TJ.FLAG_BOTTOMUP) != 0)
shun-iwasawa 82a8f5
              index = (h - row - 1) * w + col;
shun-iwasawa 82a8f5
            else
shun-iwasawa 82a8f5
              index = row * w + col;
shun-iwasawa 82a8f5
            byte c = buf[index * ps];
shun-iwasawa 82a8f5
            byte m = buf[index * ps + 1];
shun-iwasawa 82a8f5
            byte y = buf[index * ps + 2];
shun-iwasawa 82a8f5
            byte k = buf[index * ps + 3];
shun-iwasawa 82a8f5
            checkVal255(row, col, c, "C");
shun-iwasawa 82a8f5
            if (((row / blockSize) + (col / blockSize)) % 2 == 0) {
shun-iwasawa 82a8f5
              checkVal255(row, col, m, "M");
shun-iwasawa 82a8f5
              checkVal255(row, col, y, "Y");
shun-iwasawa 82a8f5
              if (row < halfway)
shun-iwasawa 82a8f5
                checkVal255(row, col, k, "K");
shun-iwasawa 82a8f5
              else
shun-iwasawa 82a8f5
                checkVal0(row, col, k, "K");
shun-iwasawa 82a8f5
            } else {
shun-iwasawa 82a8f5
              checkVal0(row, col, y, "Y");
shun-iwasawa 82a8f5
              checkVal255(row, col, k, "K");
shun-iwasawa 82a8f5
              if (row < halfway)
shun-iwasawa 82a8f5
                checkVal0(row, col, m, "M");
shun-iwasawa 82a8f5
              else
shun-iwasawa 82a8f5
                checkVal255(row, col, m, "M");
shun-iwasawa 82a8f5
            }
shun-iwasawa 82a8f5
          }
shun-iwasawa 82a8f5
        }
shun-iwasawa 82a8f5
        return 1;
shun-iwasawa 82a8f5
      }
shun-iwasawa 82a8f5
shun-iwasawa 82a8f5
      for (row = 0; row < halfway; row++) {
shun-iwasawa 82a8f5
        for (col = 0; col < w; col++) {
shun-iwasawa 82a8f5
          if ((flags & TJ.FLAG_BOTTOMUP) != 0)
shun-iwasawa 82a8f5
            index = pitch * (h - row - 1) + col * ps;
shun-iwasawa 82a8f5
          else
shun-iwasawa 82a8f5
            index = pitch * row + col * ps;
shun-iwasawa 82a8f5
          byte r = buf[index + roffset];
shun-iwasawa 82a8f5
          byte g = buf[index + goffset];
shun-iwasawa 82a8f5
          byte b = buf[index + boffset];
shun-iwasawa 82a8f5
          byte a = aoffset >= 0 ? buf[index + aoffset] : (byte)255;
shun-iwasawa 82a8f5
          if (((row / blockSize) + (col / blockSize)) % 2 == 0) {
shun-iwasawa 82a8f5
            if (row < halfway) {
shun-iwasawa 82a8f5
              checkVal255(row, col, r, "R");
shun-iwasawa 82a8f5
              checkVal255(row, col, g, "G");
shun-iwasawa 82a8f5
              checkVal255(row, col, b, "B");
shun-iwasawa 82a8f5
            } else {
shun-iwasawa 82a8f5
              checkVal0(row, col, r, "R");
shun-iwasawa 82a8f5
              checkVal0(row, col, g, "G");
shun-iwasawa 82a8f5
              checkVal0(row, col, b, "B");
shun-iwasawa 82a8f5
            }
shun-iwasawa 82a8f5
          } else {
shun-iwasawa 82a8f5
            if (subsamp == TJ.SAMP_GRAY) {
shun-iwasawa 82a8f5
              if (row < halfway) {
shun-iwasawa 82a8f5
                checkVal(row, col, r, "R", 76);
shun-iwasawa 82a8f5
                checkVal(row, col, g, "G", 76);
shun-iwasawa 82a8f5
                checkVal(row, col, b, "B", 76);
shun-iwasawa 82a8f5
              } else {
shun-iwasawa 82a8f5
                checkVal(row, col, r, "R", 226);
shun-iwasawa 82a8f5
                checkVal(row, col, g, "G", 226);
shun-iwasawa 82a8f5
                checkVal(row, col, b, "B", 226);
shun-iwasawa 82a8f5
              }
shun-iwasawa 82a8f5
            } else {
shun-iwasawa 82a8f5
              checkVal255(row, col, r, "R");
shun-iwasawa 82a8f5
              if (row < halfway) {
shun-iwasawa 82a8f5
                checkVal0(row, col, g, "G");
shun-iwasawa 82a8f5
              } else {
shun-iwasawa 82a8f5
                checkVal255(row, col, g, "G");
shun-iwasawa 82a8f5
              }
shun-iwasawa 82a8f5
              checkVal0(row, col, b, "B");
shun-iwasawa 82a8f5
            }
shun-iwasawa 82a8f5
          }
shun-iwasawa 82a8f5
          checkVal255(row, col, a, "A");
shun-iwasawa 82a8f5
        }
shun-iwasawa 82a8f5
      }
shun-iwasawa 82a8f5
    } catch (Exception e) {
shun-iwasawa 82a8f5
      System.out.println("\n" + e.getMessage());
shun-iwasawa 82a8f5
      retval = 0;
shun-iwasawa 82a8f5
    }
shun-iwasawa 82a8f5
shun-iwasawa 82a8f5
    if (retval == 0) {
shun-iwasawa 82a8f5
      for (row = 0; row < h; row++) {
shun-iwasawa 82a8f5
        for (col = 0; col < w; col++) {
shun-iwasawa 82a8f5
          if (pf == TJ.PF_CMYK) {
shun-iwasawa 82a8f5
            int c = buf[pitch * row + col * ps];
shun-iwasawa 82a8f5
            int m = buf[pitch * row + col * ps + 1];
shun-iwasawa 82a8f5
            int y = buf[pitch * row + col * ps + 2];
shun-iwasawa 82a8f5
            int k = buf[pitch * row + col * ps + 3];
shun-iwasawa 82a8f5
            if (c < 0) c += 256;
shun-iwasawa 82a8f5
            if (m < 0) m += 256;
shun-iwasawa 82a8f5
            if (y < 0) y += 256;
shun-iwasawa 82a8f5
            if (k < 0) k += 256;
shun-iwasawa 82a8f5
            System.out.format("%3d/%3d/%3d/%3d ", c, m, y, k);
shun-iwasawa 82a8f5
          } else {
shun-iwasawa 82a8f5
            int r = buf[pitch * row + col * ps + roffset];
shun-iwasawa 82a8f5
            int g = buf[pitch * row + col * ps + goffset];
shun-iwasawa 82a8f5
            int b = buf[pitch * row + col * ps + boffset];
shun-iwasawa 82a8f5
            if (r < 0) r += 256;
shun-iwasawa 82a8f5
            if (g < 0) g += 256;
shun-iwasawa 82a8f5
            if (b < 0) b += 256;
shun-iwasawa 82a8f5
            System.out.format("%3d/%3d/%3d ", r, g, b);
shun-iwasawa 82a8f5
          }
shun-iwasawa 82a8f5
        }
shun-iwasawa 82a8f5
        System.out.print("\n");
shun-iwasawa 82a8f5
      }
shun-iwasawa 82a8f5
    }
shun-iwasawa 82a8f5
    return retval;
shun-iwasawa 82a8f5
  }
shun-iwasawa 82a8f5
shun-iwasawa 82a8f5
  static int checkIntBuf(int[] buf, int w, int pitch, int h, int pf,
shun-iwasawa 82a8f5
                         int subsamp, TJScalingFactor sf, int flags)
shun-iwasawa 82a8f5
                         throws Exception {
shun-iwasawa 82a8f5
    int rshift = TJ.getRedOffset(pf) * 8;
shun-iwasawa 82a8f5
    int gshift = TJ.getGreenOffset(pf) * 8;
shun-iwasawa 82a8f5
    int bshift = TJ.getBlueOffset(pf) * 8;
shun-iwasawa 82a8f5
    int ashift = TJ.getAlphaOffset(pf) * 8;
shun-iwasawa 82a8f5
    int index, row, col, retval = 1;
shun-iwasawa 82a8f5
    int halfway = 16 * sf.getNum() / sf.getDenom();
shun-iwasawa 82a8f5
    int blockSize = 8 * sf.getNum() / sf.getDenom();
shun-iwasawa 82a8f5
shun-iwasawa 82a8f5
    try {
shun-iwasawa 82a8f5
      for (row = 0; row < halfway; row++) {
shun-iwasawa 82a8f5
        for (col = 0; col < w; col++) {
shun-iwasawa 82a8f5
          if ((flags & TJ.FLAG_BOTTOMUP) != 0)
shun-iwasawa 82a8f5
            index = pitch * (h - row - 1) + col;
shun-iwasawa 82a8f5
          else
shun-iwasawa 82a8f5
            index = pitch * row + col;
shun-iwasawa 82a8f5
          int r = (buf[index] >> rshift) & 0xFF;
shun-iwasawa 82a8f5
          int g = (buf[index] >> gshift) & 0xFF;
shun-iwasawa 82a8f5
          int b = (buf[index] >> bshift) & 0xFF;
shun-iwasawa 82a8f5
          int a = ashift >= 0 ? (buf[index] >> ashift) & 0xFF : 255;
shun-iwasawa 82a8f5
          if (((row / blockSize) + (col / blockSize)) % 2 == 0) {
shun-iwasawa 82a8f5
            if (row < halfway) {
shun-iwasawa 82a8f5
              checkVal255(row, col, r, "R");
shun-iwasawa 82a8f5
              checkVal255(row, col, g, "G");
shun-iwasawa 82a8f5
              checkVal255(row, col, b, "B");
shun-iwasawa 82a8f5
            } else {
shun-iwasawa 82a8f5
              checkVal0(row, col, r, "R");
shun-iwasawa 82a8f5
              checkVal0(row, col, g, "G");
shun-iwasawa 82a8f5
              checkVal0(row, col, b, "B");
shun-iwasawa 82a8f5
            }
shun-iwasawa 82a8f5
          } else {
shun-iwasawa 82a8f5
            if (subsamp == TJ.SAMP_GRAY) {
shun-iwasawa 82a8f5
              if (row < halfway) {
shun-iwasawa 82a8f5
                checkVal(row, col, r, "R", 76);
shun-iwasawa 82a8f5
                checkVal(row, col, g, "G", 76);
shun-iwasawa 82a8f5
                checkVal(row, col, b, "B", 76);
shun-iwasawa 82a8f5
              } else {
shun-iwasawa 82a8f5
                checkVal(row, col, r, "R", 226);
shun-iwasawa 82a8f5
                checkVal(row, col, g, "G", 226);
shun-iwasawa 82a8f5
                checkVal(row, col, b, "B", 226);
shun-iwasawa 82a8f5
              }
shun-iwasawa 82a8f5
            } else {
shun-iwasawa 82a8f5
              checkVal255(row, col, r, "R");
shun-iwasawa 82a8f5
              if (row < halfway) {
shun-iwasawa 82a8f5
                checkVal0(row, col, g, "G");
shun-iwasawa 82a8f5
              } else {
shun-iwasawa 82a8f5
                checkVal255(row, col, g, "G");
shun-iwasawa 82a8f5
              }
shun-iwasawa 82a8f5
              checkVal0(row, col, b, "B");
shun-iwasawa 82a8f5
            }
shun-iwasawa 82a8f5
          }
shun-iwasawa 82a8f5
          checkVal255(row, col, a, "A");
shun-iwasawa 82a8f5
        }
shun-iwasawa 82a8f5
      }
shun-iwasawa 82a8f5
    } catch (Exception e) {
shun-iwasawa 82a8f5
      System.out.println("\n" + e.getMessage());
shun-iwasawa 82a8f5
      retval = 0;
shun-iwasawa 82a8f5
    }
shun-iwasawa 82a8f5
shun-iwasawa 82a8f5
    if (retval == 0) {
shun-iwasawa 82a8f5
      for (row = 0; row < h; row++) {
shun-iwasawa 82a8f5
        for (col = 0; col < w; col++) {
shun-iwasawa 82a8f5
          int r = (buf[pitch * row + col] >> rshift) & 0xFF;
shun-iwasawa 82a8f5
          int g = (buf[pitch * row + col] >> gshift) & 0xFF;
shun-iwasawa 82a8f5
          int b = (buf[pitch * row + col] >> bshift) & 0xFF;
shun-iwasawa 82a8f5
          if (r < 0) r += 256;
shun-iwasawa 82a8f5
          if (g < 0) g += 256;
shun-iwasawa 82a8f5
          if (b < 0) b += 256;
shun-iwasawa 82a8f5
          System.out.format("%3d/%3d/%3d ", r, g, b);
shun-iwasawa 82a8f5
        }
shun-iwasawa 82a8f5
        System.out.print("\n");
shun-iwasawa 82a8f5
      }
shun-iwasawa 82a8f5
    }
shun-iwasawa 82a8f5
    return retval;
shun-iwasawa 82a8f5
  }
shun-iwasawa 82a8f5
shun-iwasawa 82a8f5
  static int checkImg(BufferedImage img, int pf, int subsamp,
shun-iwasawa 82a8f5
                      TJScalingFactor sf, int flags) throws Exception {
shun-iwasawa 82a8f5
    WritableRaster wr = img.getRaster();
shun-iwasawa 82a8f5
    int imgType = img.getType();
shun-iwasawa 82a8f5
    if (imgType == BufferedImage.TYPE_INT_RGB ||
shun-iwasawa 82a8f5
        imgType == BufferedImage.TYPE_INT_BGR ||
shun-iwasawa 82a8f5
        imgType == BufferedImage.TYPE_INT_ARGB ||
shun-iwasawa 82a8f5
        imgType == BufferedImage.TYPE_INT_ARGB_PRE) {
shun-iwasawa 82a8f5
      SinglePixelPackedSampleModel sm =
shun-iwasawa 82a8f5
        (SinglePixelPackedSampleModel)img.getSampleModel();
shun-iwasawa 82a8f5
      int pitch = sm.getScanlineStride();
shun-iwasawa 82a8f5
      DataBufferInt db = (DataBufferInt)wr.getDataBuffer();
shun-iwasawa 82a8f5
      int[] buf = db.getData();
shun-iwasawa 82a8f5
      return checkIntBuf(buf, img.getWidth(), pitch, img.getHeight(), pf,
shun-iwasawa 82a8f5
                         subsamp, sf, flags);
shun-iwasawa 82a8f5
    } else {
shun-iwasawa 82a8f5
      ComponentSampleModel sm = (ComponentSampleModel)img.getSampleModel();
shun-iwasawa 82a8f5
      int pitch = sm.getScanlineStride();
shun-iwasawa 82a8f5
      DataBufferByte db = (DataBufferByte)wr.getDataBuffer();
shun-iwasawa 82a8f5
      byte[] buf = db.getData();
shun-iwasawa 82a8f5
      return checkBuf(buf, img.getWidth(), pitch, img.getHeight(), pf, subsamp,
shun-iwasawa 82a8f5
                      sf, flags);
shun-iwasawa 82a8f5
    }
shun-iwasawa 82a8f5
  }
shun-iwasawa 82a8f5
shun-iwasawa 82a8f5
  static int pad(int v, int p) {
shun-iwasawa 82a8f5
    return ((v + (p) - 1) & (~((p) - 1)));
shun-iwasawa 82a8f5
  }
shun-iwasawa 82a8f5
shun-iwasawa 82a8f5
  static int checkBufYUV(byte[] buf, int size, int w, int h, int subsamp,
shun-iwasawa 82a8f5
                         TJScalingFactor sf) throws Exception {
shun-iwasawa 82a8f5
    int row, col;
shun-iwasawa 82a8f5
    int hsf = TJ.getMCUWidth(subsamp) / 8, vsf = TJ.getMCUHeight(subsamp) / 8;
shun-iwasawa 82a8f5
    int pw = pad(w, hsf), ph = pad(h, vsf);
shun-iwasawa 82a8f5
    int cw = pw / hsf, ch = ph / vsf;
shun-iwasawa 82a8f5
    int ypitch = pad(pw, pad), uvpitch = pad(cw, pad);
shun-iwasawa 82a8f5
    int retval = 1;
shun-iwasawa 82a8f5
    int correctsize = ypitch * ph +
shun-iwasawa 82a8f5
                      (subsamp == TJ.SAMP_GRAY ? 0 : uvpitch * ch * 2);
shun-iwasawa 82a8f5
    int halfway = 16 * sf.getNum() / sf.getDenom();
shun-iwasawa 82a8f5
    int blockSize = 8 * sf.getNum() / sf.getDenom();
shun-iwasawa 82a8f5
shun-iwasawa 82a8f5
    try {
shun-iwasawa 82a8f5
      if (size != correctsize)
shun-iwasawa 82a8f5
        throw new Exception("Incorrect size " + size + ".  Should be " +
shun-iwasawa 82a8f5
                            correctsize);
shun-iwasawa 82a8f5
shun-iwasawa 82a8f5
      for (row = 0; row < ph; row++) {
shun-iwasawa 82a8f5
        for (col = 0; col < pw; col++) {
shun-iwasawa 82a8f5
          byte y = buf[ypitch * row + col];
shun-iwasawa 82a8f5
          if (((row / blockSize) + (col / blockSize)) % 2 == 0) {
shun-iwasawa 82a8f5
            if (row < halfway)
shun-iwasawa 82a8f5
              checkVal255(row, col, y, "Y");
shun-iwasawa 82a8f5
            else
shun-iwasawa 82a8f5
              checkVal0(row, col, y, "Y");
shun-iwasawa 82a8f5
          } else {
shun-iwasawa 82a8f5
            if (row < halfway)
shun-iwasawa 82a8f5
              checkVal(row, col, y, "Y", 76);
shun-iwasawa 82a8f5
            else
shun-iwasawa 82a8f5
              checkVal(row, col, y, "Y", 226);
shun-iwasawa 82a8f5
          }
shun-iwasawa 82a8f5
        }
shun-iwasawa 82a8f5
      }
shun-iwasawa 82a8f5
      if (subsamp != TJ.SAMP_GRAY) {
shun-iwasawa 82a8f5
        halfway = 16 / vsf * sf.getNum() / sf.getDenom();
shun-iwasawa 82a8f5
        for (row = 0; row < ch; row++) {
shun-iwasawa 82a8f5
          for (col = 0; col < cw; col++) {
shun-iwasawa 82a8f5
            byte u = buf[ypitch * ph + (uvpitch * row + col)],
shun-iwasawa 82a8f5
                 v = buf[ypitch * ph + uvpitch * ch + (uvpitch * row + col)];
shun-iwasawa 82a8f5
            if (((row * vsf / blockSize) + (col * hsf / blockSize)) % 2 == 0) {
shun-iwasawa 82a8f5
              checkVal(row, col, u, "U", 128);
shun-iwasawa 82a8f5
              checkVal(row, col, v, "V", 128);
shun-iwasawa 82a8f5
            } else {
shun-iwasawa 82a8f5
              if (row < halfway) {
shun-iwasawa 82a8f5
                checkVal(row, col, u, "U", 85);
shun-iwasawa 82a8f5
                checkVal255(row, col, v, "V");
shun-iwasawa 82a8f5
              } else {
shun-iwasawa 82a8f5
                checkVal0(row, col, u, "U");
shun-iwasawa 82a8f5
                checkVal(row, col, v, "V", 149);
shun-iwasawa 82a8f5
              }
shun-iwasawa 82a8f5
            }
shun-iwasawa 82a8f5
          }
shun-iwasawa 82a8f5
        }
shun-iwasawa 82a8f5
      }
shun-iwasawa 82a8f5
    } catch (Exception e) {
shun-iwasawa 82a8f5
      System.out.println("\n" + e.getMessage());
shun-iwasawa 82a8f5
      retval = 0;
shun-iwasawa 82a8f5
    }
shun-iwasawa 82a8f5
shun-iwasawa 82a8f5
    if (retval == 0) {
shun-iwasawa 82a8f5
      for (row = 0; row < ph; row++) {
shun-iwasawa 82a8f5
        for (col = 0; col < pw; col++) {
shun-iwasawa 82a8f5
          int y = buf[ypitch * row + col];
shun-iwasawa 82a8f5
          if (y < 0) y += 256;
shun-iwasawa 82a8f5
          System.out.format("%3d ", y);
shun-iwasawa 82a8f5
        }
shun-iwasawa 82a8f5
        System.out.print("\n");
shun-iwasawa 82a8f5
      }
shun-iwasawa 82a8f5
      System.out.print("\n");
shun-iwasawa 82a8f5
      for (row = 0; row < ch; row++) {
shun-iwasawa 82a8f5
        for (col = 0; col < cw; col++) {
shun-iwasawa 82a8f5
          int u = buf[ypitch * ph + (uvpitch * row + col)];
shun-iwasawa 82a8f5
          if (u < 0) u += 256;
shun-iwasawa 82a8f5
          System.out.format("%3d ", u);
shun-iwasawa 82a8f5
        }
shun-iwasawa 82a8f5
        System.out.print("\n");
shun-iwasawa 82a8f5
      }
shun-iwasawa 82a8f5
      System.out.print("\n");
shun-iwasawa 82a8f5
      for (row = 0; row < ch; row++) {
shun-iwasawa 82a8f5
        for (col = 0; col < cw; col++) {
shun-iwasawa 82a8f5
          int v = buf[ypitch * ph + uvpitch * ch + (uvpitch * row + col)];
shun-iwasawa 82a8f5
          if (v < 0) v += 256;
shun-iwasawa 82a8f5
          System.out.format("%3d ", v);
shun-iwasawa 82a8f5
        }
shun-iwasawa 82a8f5
        System.out.print("\n");
shun-iwasawa 82a8f5
      }
shun-iwasawa 82a8f5
    }
shun-iwasawa 82a8f5
shun-iwasawa 82a8f5
    return retval;
shun-iwasawa 82a8f5
  }
shun-iwasawa 82a8f5
shun-iwasawa 82a8f5
  static void writeJPEG(byte[] jpegBuf, int jpegBufSize, String filename)
shun-iwasawa 82a8f5
                        throws Exception {
shun-iwasawa 82a8f5
    File file = new File(filename);
shun-iwasawa 82a8f5
    FileOutputStream fos = new FileOutputStream(file);
shun-iwasawa 82a8f5
    fos.write(jpegBuf, 0, jpegBufSize);
shun-iwasawa 82a8f5
    fos.close();
shun-iwasawa 82a8f5
  }
shun-iwasawa 82a8f5
shun-iwasawa 82a8f5
  static int compTest(TJCompressor tjc, byte[] dstBuf, int w, int h, int pf,
shun-iwasawa 82a8f5
                      String baseName, int subsamp, int jpegQual, int flags)
shun-iwasawa 82a8f5
                      throws Exception {
shun-iwasawa 82a8f5
    String tempStr;
shun-iwasawa 82a8f5
    byte[] srcBuf = null;
shun-iwasawa 82a8f5
    BufferedImage img = null;
shun-iwasawa 82a8f5
    String pfStr, pfStrLong;
shun-iwasawa 82a8f5
    String buStr = (flags & TJ.FLAG_BOTTOMUP) != 0 ? "BU" : "TD";
shun-iwasawa 82a8f5
    String buStrLong = (flags & TJ.FLAG_BOTTOMUP) != 0 ?
shun-iwasawa 82a8f5
                       "Bottom-Up" : "Top-Down ";
shun-iwasawa 82a8f5
    int size = 0, ps, imgType = pf;
shun-iwasawa 82a8f5
shun-iwasawa 82a8f5
    if (bi) {
shun-iwasawa 82a8f5
      pf = biTypePF(imgType);
shun-iwasawa 82a8f5
      pfStr = biTypeStr(imgType);
shun-iwasawa 82a8f5
      pfStrLong = pfStr + " (" + PIXFORMATSTR[pf] + ")";
shun-iwasawa 82a8f5
    } else {
shun-iwasawa 82a8f5
      pfStr = PIXFORMATSTR[pf];
shun-iwasawa 82a8f5
      pfStrLong = pfStr;
shun-iwasawa 82a8f5
    }
shun-iwasawa 82a8f5
    ps =  TJ.getPixelSize(pf);
shun-iwasawa 82a8f5
shun-iwasawa 82a8f5
    if (bi) {
shun-iwasawa 82a8f5
      img = new BufferedImage(w, h, imgType);
shun-iwasawa 82a8f5
      initImg(img, pf, flags);
shun-iwasawa 82a8f5
      tempStr = baseName + "_enc_" + pfStr + "_" + buStr + "_" +
shun-iwasawa 82a8f5
                SUBNAME[subsamp] + "_Q" + jpegQual + ".png";
shun-iwasawa 82a8f5
      File file = new File(tempStr);
shun-iwasawa 82a8f5
      ImageIO.write(img, "png", file);
shun-iwasawa 82a8f5
      tjc.setSourceImage(img, 0, 0, 0, 0);
shun-iwasawa 82a8f5
    } else {
shun-iwasawa 82a8f5
      srcBuf = new byte[w * h * ps + 1];
shun-iwasawa 82a8f5
      initBuf(srcBuf, w, w * ps, h, pf, flags);
shun-iwasawa 82a8f5
      tjc.setSourceImage(srcBuf, 0, 0, w, 0, h, pf);
shun-iwasawa 82a8f5
    }
shun-iwasawa 82a8f5
    Arrays.fill(dstBuf, (byte)0);
shun-iwasawa 82a8f5
shun-iwasawa 82a8f5
    tjc.setSubsamp(subsamp);
shun-iwasawa 82a8f5
    tjc.setJPEGQuality(jpegQual);
shun-iwasawa 82a8f5
    if (doYUV) {
shun-iwasawa 82a8f5
      System.out.format("%s %s -> YUV %s ... ", pfStrLong, buStrLong,
shun-iwasawa 82a8f5
                        SUBNAME_LONG[subsamp]);
shun-iwasawa 82a8f5
      YUVImage yuvImage = tjc.encodeYUV(pad, flags);
shun-iwasawa 82a8f5
      if (checkBufYUV(yuvImage.getBuf(), yuvImage.getSize(), w, h, subsamp,
shun-iwasawa 82a8f5
                      new TJScalingFactor(1, 1)) == 1)
shun-iwasawa 82a8f5
        System.out.print("Passed.\n");
shun-iwasawa 82a8f5
      else {
shun-iwasawa 82a8f5
        System.out.print("FAILED!\n");
shun-iwasawa 82a8f5
        exitStatus = -1;
shun-iwasawa 82a8f5
      }
shun-iwasawa 82a8f5
shun-iwasawa 82a8f5
      System.out.format("YUV %s %s -> JPEG Q%d ... ", SUBNAME_LONG[subsamp],
shun-iwasawa 82a8f5
                        buStrLong, jpegQual);
shun-iwasawa 82a8f5
      tjc.setSourceImage(yuvImage);
shun-iwasawa 82a8f5
    } else {
shun-iwasawa 82a8f5
      System.out.format("%s %s -> %s Q%d ... ", pfStrLong, buStrLong,
shun-iwasawa 82a8f5
                        SUBNAME_LONG[subsamp], jpegQual);
shun-iwasawa 82a8f5
    }
shun-iwasawa 82a8f5
    tjc.compress(dstBuf, flags);
shun-iwasawa 82a8f5
    size = tjc.getCompressedSize();
shun-iwasawa 82a8f5
shun-iwasawa 82a8f5
    tempStr = baseName + "_enc_" + pfStr + "_" + buStr + "_" +
shun-iwasawa 82a8f5
              SUBNAME[subsamp] + "_Q" + jpegQual + ".jpg";
shun-iwasawa 82a8f5
    writeJPEG(dstBuf, size, tempStr);
shun-iwasawa 82a8f5
    System.out.println("Done.\n  Result in " + tempStr);
shun-iwasawa 82a8f5
shun-iwasawa 82a8f5
    return size;
shun-iwasawa 82a8f5
  }
shun-iwasawa 82a8f5
shun-iwasawa 82a8f5
  static void decompTest(TJDecompressor tjd, byte[] jpegBuf, int jpegSize,
shun-iwasawa 82a8f5
                         int w, int h, int pf, String baseName, int subsamp,
shun-iwasawa 82a8f5
                         int flags, TJScalingFactor sf) throws Exception {
shun-iwasawa 82a8f5
    String pfStr, pfStrLong, tempStr;
shun-iwasawa 82a8f5
    String buStrLong = (flags & TJ.FLAG_BOTTOMUP) != 0 ?
shun-iwasawa 82a8f5
                       "Bottom-Up" : "Top-Down ";
shun-iwasawa 82a8f5
    int scaledWidth = sf.getScaled(w);
shun-iwasawa 82a8f5
    int scaledHeight = sf.getScaled(h);
shun-iwasawa 82a8f5
    int temp1, temp2, imgType = pf;
shun-iwasawa 82a8f5
    BufferedImage img = null;
shun-iwasawa 82a8f5
    byte[] dstBuf = null;
shun-iwasawa 82a8f5
shun-iwasawa 82a8f5
    if (bi) {
shun-iwasawa 82a8f5
      pf = biTypePF(imgType);
shun-iwasawa 82a8f5
      pfStr = biTypeStr(imgType);
shun-iwasawa 82a8f5
      pfStrLong = pfStr + " (" + PIXFORMATSTR[pf] + ")";
shun-iwasawa 82a8f5
    } else {
shun-iwasawa 82a8f5
      pfStr = PIXFORMATSTR[pf];
shun-iwasawa 82a8f5
      pfStrLong = pfStr;
shun-iwasawa 82a8f5
    }
shun-iwasawa 82a8f5
shun-iwasawa 82a8f5
    tjd.setSourceImage(jpegBuf, jpegSize);
shun-iwasawa 82a8f5
    if (tjd.getWidth() != w || tjd.getHeight() != h ||
shun-iwasawa 82a8f5
        tjd.getSubsamp() != subsamp)
shun-iwasawa 82a8f5
      throw new Exception("Incorrect JPEG header");
shun-iwasawa 82a8f5
shun-iwasawa 82a8f5
    temp1 = scaledWidth;
shun-iwasawa 82a8f5
    temp2 = scaledHeight;
shun-iwasawa 82a8f5
    temp1 = tjd.getScaledWidth(temp1, temp2);
shun-iwasawa 82a8f5
    temp2 = tjd.getScaledHeight(temp1, temp2);
shun-iwasawa 82a8f5
    if (temp1 != scaledWidth || temp2 != scaledHeight)
shun-iwasawa 82a8f5
      throw new Exception("Scaled size mismatch");
shun-iwasawa 82a8f5
shun-iwasawa 82a8f5
    if (doYUV) {
shun-iwasawa 82a8f5
      System.out.format("JPEG -> YUV %s ", SUBNAME_LONG[subsamp]);
shun-iwasawa 82a8f5
      if (!sf.isOne())
shun-iwasawa 82a8f5
        System.out.format("%d/%d ... ", sf.getNum(), sf.getDenom());
shun-iwasawa 82a8f5
      else System.out.print("... ");
shun-iwasawa 82a8f5
      YUVImage yuvImage = tjd.decompressToYUV(scaledWidth, pad, scaledHeight,
shun-iwasawa 82a8f5
                                              flags);
shun-iwasawa 82a8f5
      if (checkBufYUV(yuvImage.getBuf(), yuvImage.getSize(), scaledWidth,
shun-iwasawa 82a8f5
                      scaledHeight, subsamp, sf) == 1)
shun-iwasawa 82a8f5
        System.out.print("Passed.\n");
shun-iwasawa 82a8f5
      else {
shun-iwasawa 82a8f5
        System.out.print("FAILED!\n");  exitStatus = -1;
shun-iwasawa 82a8f5
      }
shun-iwasawa 82a8f5
shun-iwasawa 82a8f5
      System.out.format("YUV %s -> %s %s ... ", SUBNAME_LONG[subsamp],
shun-iwasawa 82a8f5
                        pfStrLong, buStrLong);
shun-iwasawa 82a8f5
      tjd.setSourceImage(yuvImage);
shun-iwasawa 82a8f5
    } else {
shun-iwasawa 82a8f5
      System.out.format("JPEG -> %s %s ", pfStrLong, buStrLong);
shun-iwasawa 82a8f5
      if (!sf.isOne())
shun-iwasawa 82a8f5
        System.out.format("%d/%d ... ", sf.getNum(), sf.getDenom());
shun-iwasawa 82a8f5
      else System.out.print("... ");
shun-iwasawa 82a8f5
    }
shun-iwasawa 82a8f5
    if (bi)
shun-iwasawa 82a8f5
      img = tjd.decompress(scaledWidth, scaledHeight, imgType, flags);
shun-iwasawa 82a8f5
    else
shun-iwasawa 82a8f5
      dstBuf = tjd.decompress(scaledWidth, 0, scaledHeight, pf, flags);
shun-iwasawa 82a8f5
shun-iwasawa 82a8f5
    if (bi) {
shun-iwasawa 82a8f5
      tempStr = baseName + "_dec_" + pfStr + "_" +
shun-iwasawa 82a8f5
                (((flags & TJ.FLAG_BOTTOMUP) != 0) ? "BU" : "TD") + "_" +
shun-iwasawa 82a8f5
                SUBNAME[subsamp] + "_" +
shun-iwasawa 82a8f5
                (double)sf.getNum() / (double)sf.getDenom() + "x" + ".png";
shun-iwasawa 82a8f5
      File file = new File(tempStr);
shun-iwasawa 82a8f5
      ImageIO.write(img, "png", file);
shun-iwasawa 82a8f5
    }
shun-iwasawa 82a8f5
shun-iwasawa 82a8f5
    if ((bi && checkImg(img, pf, subsamp, sf, flags) == 1) ||
shun-iwasawa 82a8f5
        (!bi && checkBuf(dstBuf, scaledWidth,
shun-iwasawa 82a8f5
                         scaledWidth * TJ.getPixelSize(pf), scaledHeight, pf,
shun-iwasawa 82a8f5
                         subsamp, sf, flags) == 1))
shun-iwasawa 82a8f5
      System.out.print("Passed.\n");
shun-iwasawa 82a8f5
    else {
shun-iwasawa 82a8f5
      System.out.print("FAILED!\n");
shun-iwasawa 82a8f5
      exitStatus = -1;
shun-iwasawa 82a8f5
    }
shun-iwasawa 82a8f5
  }
shun-iwasawa 82a8f5
shun-iwasawa 82a8f5
  static void decompTest(TJDecompressor tjd, byte[] jpegBuf, int jpegSize,
shun-iwasawa 82a8f5
                         int w, int h, int pf, String baseName, int subsamp,
shun-iwasawa 82a8f5
                         int flags) throws Exception {
shun-iwasawa 82a8f5
    int i;
shun-iwasawa 82a8f5
    TJScalingFactor[] sf = TJ.getScalingFactors();
shun-iwasawa 82a8f5
    for (i = 0; i < sf.length; i++) {
shun-iwasawa 82a8f5
      int num = sf[i].getNum();
shun-iwasawa 82a8f5
      int denom = sf[i].getDenom();
shun-iwasawa 82a8f5
      if (subsamp == TJ.SAMP_444 || subsamp == TJ.SAMP_GRAY ||
shun-iwasawa 82a8f5
          (subsamp == TJ.SAMP_411 && num == 1 &&
shun-iwasawa 82a8f5
           (denom == 2 || denom == 1)) ||
shun-iwasawa 82a8f5
          (subsamp != TJ.SAMP_411 && num == 1 &&
shun-iwasawa 82a8f5
           (denom == 4 || denom == 2 || denom == 1)))
shun-iwasawa 82a8f5
        decompTest(tjd, jpegBuf, jpegSize, w, h, pf, baseName, subsamp,
shun-iwasawa 82a8f5
                   flags, sf[i]);
shun-iwasawa 82a8f5
    }
shun-iwasawa 82a8f5
  }
shun-iwasawa 82a8f5
shun-iwasawa 82a8f5
  static void doTest(int w, int h, int[] formats, int subsamp, String baseName)
shun-iwasawa 82a8f5
                     throws Exception {
shun-iwasawa 82a8f5
    TJCompressor tjc = null;
shun-iwasawa 82a8f5
    TJDecompressor tjd = null;
shun-iwasawa 82a8f5
    int size;
shun-iwasawa 82a8f5
    byte[] dstBuf;
shun-iwasawa 82a8f5
shun-iwasawa 82a8f5
    dstBuf = new byte[TJ.bufSize(w, h, subsamp)];
shun-iwasawa 82a8f5
shun-iwasawa 82a8f5
    try {
shun-iwasawa 82a8f5
      tjc = new TJCompressor();
shun-iwasawa 82a8f5
      tjd = new TJDecompressor();
shun-iwasawa 82a8f5
shun-iwasawa 82a8f5
      for (int pf : formats) {
shun-iwasawa 82a8f5
        if (pf < 0) continue;
shun-iwasawa 82a8f5
        for (int i = 0; i < 2; i++) {
shun-iwasawa 82a8f5
          int flags = 0;
shun-iwasawa 82a8f5
          if (subsamp == TJ.SAMP_422 || subsamp == TJ.SAMP_420 ||
shun-iwasawa 82a8f5
              subsamp == TJ.SAMP_440 || subsamp == TJ.SAMP_411)
shun-iwasawa 82a8f5
            flags |= TJ.FLAG_FASTUPSAMPLE;
shun-iwasawa 82a8f5
          if (i == 1)
shun-iwasawa 82a8f5
            flags |= TJ.FLAG_BOTTOMUP;
shun-iwasawa 82a8f5
          size = compTest(tjc, dstBuf, w, h, pf, baseName, subsamp, 100,
shun-iwasawa 82a8f5
                          flags);
shun-iwasawa 82a8f5
          decompTest(tjd, dstBuf, size, w, h, pf, baseName, subsamp, flags);
shun-iwasawa 82a8f5
          if (pf >= TJ.PF_RGBX && pf <= TJ.PF_XRGB && !bi) {
shun-iwasawa 82a8f5
            System.out.print("\n");
shun-iwasawa 82a8f5
            decompTest(tjd, dstBuf, size, w, h, pf + (TJ.PF_RGBA - TJ.PF_RGBX),
shun-iwasawa 82a8f5
                       baseName, subsamp, flags);
shun-iwasawa 82a8f5
          }
shun-iwasawa 82a8f5
          System.out.print("\n");
shun-iwasawa 82a8f5
        }
shun-iwasawa 82a8f5
      }
shun-iwasawa 82a8f5
      System.out.print("--------------------\n\n");
shun-iwasawa 82a8f5
    } catch (Exception e) {
shun-iwasawa 82a8f5
      if (tjc != null) tjc.close();
shun-iwasawa 82a8f5
      if (tjd != null) tjd.close();
shun-iwasawa 82a8f5
      throw e;
shun-iwasawa 82a8f5
    }
shun-iwasawa 82a8f5
    if (tjc != null) tjc.close();
shun-iwasawa 82a8f5
    if (tjd != null) tjd.close();
shun-iwasawa 82a8f5
  }
shun-iwasawa 82a8f5
shun-iwasawa 82a8f5
  static void bufSizeTest() throws Exception {
shun-iwasawa 82a8f5
    int w, h, i, subsamp;
shun-iwasawa 82a8f5
    byte[] srcBuf, dstBuf = null;
shun-iwasawa 82a8f5
    YUVImage dstImage = null;
shun-iwasawa 82a8f5
    TJCompressor tjc = null;
shun-iwasawa 82a8f5
    Random r = new Random();
shun-iwasawa 82a8f5
shun-iwasawa 82a8f5
    try {
shun-iwasawa 82a8f5
      tjc = new TJCompressor();
shun-iwasawa 82a8f5
      System.out.println("Buffer size regression test");
shun-iwasawa 82a8f5
      for (subsamp = 0; subsamp < TJ.NUMSAMP; subsamp++) {
shun-iwasawa 82a8f5
        for (w = 1; w < 48; w++) {
shun-iwasawa 82a8f5
          int maxh = (w == 1) ? 2048 : 48;
shun-iwasawa 82a8f5
          for (h = 1; h < maxh; h++) {
shun-iwasawa 82a8f5
            if (h % 100 == 0)
shun-iwasawa 82a8f5
              System.out.format("%04d x %04d\b\b\b\b\b\b\b\b\b\b\b", w, h);
shun-iwasawa 82a8f5
            srcBuf = new byte[w * h * 4];
shun-iwasawa 82a8f5
            if (doYUV)
shun-iwasawa 82a8f5
              dstImage = new YUVImage(w, pad, h, subsamp);
shun-iwasawa 82a8f5
            else
shun-iwasawa 82a8f5
              dstBuf = new byte[TJ.bufSize(w, h, subsamp)];
shun-iwasawa 82a8f5
            for (i = 0; i < w * h * 4; i++) {
shun-iwasawa 82a8f5
              srcBuf[i] = (byte)(r.nextInt(2) * 255);
shun-iwasawa 82a8f5
            }
shun-iwasawa 82a8f5
            tjc.setSourceImage(srcBuf, 0, 0, w, 0, h, TJ.PF_BGRX);
shun-iwasawa 82a8f5
            tjc.setSubsamp(subsamp);
shun-iwasawa 82a8f5
            tjc.setJPEGQuality(100);
shun-iwasawa 82a8f5
            if (doYUV)
shun-iwasawa 82a8f5
              tjc.encodeYUV(dstImage, 0);
shun-iwasawa 82a8f5
            else
shun-iwasawa 82a8f5
              tjc.compress(dstBuf, 0);
shun-iwasawa 82a8f5
shun-iwasawa 82a8f5
            srcBuf = new byte[h * w * 4];
shun-iwasawa 82a8f5
            if (doYUV)
shun-iwasawa 82a8f5
              dstImage = new YUVImage(h, pad, w, subsamp);
shun-iwasawa 82a8f5
            else
shun-iwasawa 82a8f5
              dstBuf = new byte[TJ.bufSize(h, w, subsamp)];
shun-iwasawa 82a8f5
            for (i = 0; i < h * w * 4; i++) {
shun-iwasawa 82a8f5
              srcBuf[i] = (byte)(r.nextInt(2) * 255);
shun-iwasawa 82a8f5
            }
shun-iwasawa 82a8f5
            tjc.setSourceImage(srcBuf, 0, 0, h, 0, w, TJ.PF_BGRX);
shun-iwasawa 82a8f5
            if (doYUV)
shun-iwasawa 82a8f5
              tjc.encodeYUV(dstImage, 0);
shun-iwasawa 82a8f5
            else
shun-iwasawa 82a8f5
              tjc.compress(dstBuf, 0);
shun-iwasawa 82a8f5
          }
shun-iwasawa 82a8f5
          dstImage = null;
shun-iwasawa 82a8f5
          dstBuf = null;
shun-iwasawa 82a8f5
          System.gc();
shun-iwasawa 82a8f5
        }
shun-iwasawa 82a8f5
      }
shun-iwasawa 82a8f5
      System.out.println("Done.      ");
shun-iwasawa 82a8f5
    } catch (Exception e) {
shun-iwasawa 82a8f5
      if (tjc != null) tjc.close();
shun-iwasawa 82a8f5
      throw e;
shun-iwasawa 82a8f5
    }
shun-iwasawa 82a8f5
    if (tjc != null) tjc.close();
shun-iwasawa 82a8f5
  }
shun-iwasawa 82a8f5
shun-iwasawa 82a8f5
  public static void main(String[] argv) {
shun-iwasawa 82a8f5
    try {
shun-iwasawa 82a8f5
      String testName = "javatest";
shun-iwasawa 82a8f5
      for (int i = 0; i < argv.length; i++) {
shun-iwasawa 82a8f5
        if (argv[i].equalsIgnoreCase("-yuv"))
shun-iwasawa 82a8f5
          doYUV = true;
shun-iwasawa 82a8f5
        else if (argv[i].equalsIgnoreCase("-noyuvpad"))
shun-iwasawa 82a8f5
          pad = 1;
shun-iwasawa 82a8f5
        else if (argv[i].equalsIgnoreCase("-bi")) {
shun-iwasawa 82a8f5
          bi = true;
shun-iwasawa 82a8f5
          testName = "javabitest";
shun-iwasawa 82a8f5
        } else
shun-iwasawa 82a8f5
          usage();
shun-iwasawa 82a8f5
      }
shun-iwasawa 82a8f5
      if (doYUV)
shun-iwasawa 82a8f5
        FORMATS_4BYTE[4] = -1;
shun-iwasawa 82a8f5
      doTest(35, 39, bi ? FORMATS_3BYTEBI : FORMATS_3BYTE, TJ.SAMP_444,
shun-iwasawa 82a8f5
             testName);
shun-iwasawa 82a8f5
      doTest(39, 41, bi ? FORMATS_4BYTEBI : FORMATS_4BYTE, TJ.SAMP_444,
shun-iwasawa 82a8f5
             testName);
shun-iwasawa 82a8f5
      doTest(41, 35, bi ? FORMATS_3BYTEBI : FORMATS_3BYTE, TJ.SAMP_422,
shun-iwasawa 82a8f5
             testName);
shun-iwasawa 82a8f5
      doTest(35, 39, bi ? FORMATS_4BYTEBI : FORMATS_4BYTE, TJ.SAMP_422,
shun-iwasawa 82a8f5
             testName);
shun-iwasawa 82a8f5
      doTest(39, 41, bi ? FORMATS_3BYTEBI : FORMATS_3BYTE, TJ.SAMP_420,
shun-iwasawa 82a8f5
             testName);
shun-iwasawa 82a8f5
      doTest(41, 35, bi ? FORMATS_4BYTEBI : FORMATS_4BYTE, TJ.SAMP_420,
shun-iwasawa 82a8f5
             testName);
shun-iwasawa 82a8f5
      doTest(35, 39, bi ? FORMATS_3BYTEBI : FORMATS_3BYTE, TJ.SAMP_440,
shun-iwasawa 82a8f5
             testName);
shun-iwasawa 82a8f5
      doTest(39, 41, bi ? FORMATS_4BYTEBI : FORMATS_4BYTE, TJ.SAMP_440,
shun-iwasawa 82a8f5
             testName);
shun-iwasawa 82a8f5
      doTest(41, 35, bi ? FORMATS_3BYTEBI : FORMATS_3BYTE, TJ.SAMP_411,
shun-iwasawa 82a8f5
             testName);
shun-iwasawa 82a8f5
      doTest(35, 39, bi ? FORMATS_4BYTEBI : FORMATS_4BYTE, TJ.SAMP_411,
shun-iwasawa 82a8f5
             testName);
shun-iwasawa 82a8f5
      doTest(39, 41, bi ? FORMATS_GRAYBI : FORMATS_GRAY, TJ.SAMP_GRAY,
shun-iwasawa 82a8f5
             testName);
shun-iwasawa 82a8f5
      doTest(41, 35, bi ? FORMATS_3BYTEBI : FORMATS_3BYTE, TJ.SAMP_GRAY,
shun-iwasawa 82a8f5
             testName);
shun-iwasawa 82a8f5
      FORMATS_4BYTE[4] = -1;
shun-iwasawa 82a8f5
      doTest(35, 39, bi ? FORMATS_4BYTEBI : FORMATS_4BYTE, TJ.SAMP_GRAY,
shun-iwasawa 82a8f5
             testName);
shun-iwasawa 82a8f5
      if (!bi)
shun-iwasawa 82a8f5
        bufSizeTest();
shun-iwasawa 82a8f5
      if (doYUV && !bi) {
shun-iwasawa 82a8f5
        System.out.print("\n--------------------\n\n");
shun-iwasawa 82a8f5
        doTest(48, 48, FORMATS_RGB, TJ.SAMP_444, "javatest_yuv0");
shun-iwasawa 82a8f5
        doTest(48, 48, FORMATS_RGB, TJ.SAMP_422, "javatest_yuv0");
shun-iwasawa 82a8f5
        doTest(48, 48, FORMATS_RGB, TJ.SAMP_420, "javatest_yuv0");
shun-iwasawa 82a8f5
        doTest(48, 48, FORMATS_RGB, TJ.SAMP_440, "javatest_yuv0");
shun-iwasawa 82a8f5
        doTest(48, 48, FORMATS_RGB, TJ.SAMP_411, "javatest_yuv0");
shun-iwasawa 82a8f5
        doTest(48, 48, FORMATS_RGB, TJ.SAMP_GRAY, "javatest_yuv0");
shun-iwasawa 82a8f5
        doTest(48, 48, FORMATS_GRAY, TJ.SAMP_GRAY, "javatest_yuv0");
shun-iwasawa 82a8f5
      }
shun-iwasawa 82a8f5
    } catch (Exception e) {
shun-iwasawa 82a8f5
      e.printStackTrace();
shun-iwasawa 82a8f5
      exitStatus = -1;
shun-iwasawa 82a8f5
    }
shun-iwasawa 82a8f5
    System.exit(exitStatus);
shun-iwasawa 82a8f5
  }
shun-iwasawa 82a8f5
}