/*
 * Copyright (C)2011-2015 D. R. Commander.  All Rights Reserved.
 * Copyright (C)2015 Viktor Szathmáry.  All Rights Reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * - Redistributions of source code must retain the above copyright notice,
 *   this list of conditions and the following disclaimer.
 * - Redistributions in binary form must reproduce the above copyright notice,
 *   this list of conditions and the following disclaimer in the documentation
 *   and/or other materials provided with the distribution.
 * - Neither the name of the libjpeg-turbo Project nor the names of its
 *   contributors may be used to endorse or promote products derived from this
 *   software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS",
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

package org.libjpegturbo.turbojpeg;

import java.awt.image.*;
import java.nio.*;
import java.io.*;

/**
 * TurboJPEG decompressor
 */
public class TJDecompressor implements Closeable {

  private static final String NO_ASSOC_ERROR =
    "No JPEG image is associated with this instance";

  /**
   * Create a TurboJPEG decompresssor instance.
   */
  public TJDecompressor() throws TJException {
    init();
  }

  /**
   * Create a TurboJPEG decompressor instance and associate the JPEG source
   * image stored in <code>jpegImage</code> with the newly created instance.
   *
   * @param jpegImage JPEG image buffer (size of the JPEG image is assumed to
   * be the length of the array.)  This buffer is not modified.
   */
  public TJDecompressor(byte[] jpegImage) throws TJException {
    init();
    setSourceImage(jpegImage, jpegImage.length);
  }

  /**
   * Create a TurboJPEG decompressor instance and associate the JPEG source
   * image of length <code>imageSize</code> bytes stored in
   * <code>jpegImage</code> with the newly created instance.
   *
   * @param jpegImage JPEG image buffer.  This buffer is not modified.
   *
   * @param imageSize size of the JPEG image (in bytes)
   */
  public TJDecompressor(byte[] jpegImage, int imageSize) throws TJException {
    init();
    setSourceImage(jpegImage, imageSize);
  }

  /**
   * Create a TurboJPEG decompressor instance and associate the YUV planar
   * source image stored in <code>yuvImage</code> with the newly created
   * instance.
   *
   * @param yuvImage {@link YUVImage} instance containing a YUV planar
   * image to be decoded.  This image is not modified.
   */
  public TJDecompressor(YUVImage yuvImage) throws TJException {
    init();
    setSourceImage(yuvImage);
  }

  /**
   * Associate the JPEG image of length <code>imageSize</code> bytes stored in
   * <code>jpegImage</code> with this decompressor instance.  This image will
   * be used as the source image for subsequent decompress operations.
   *
   * @param jpegImage JPEG image buffer.  This buffer is not modified.
   *
   * @param imageSize size of the JPEG image (in bytes)
   */
  public void setSourceImage(byte[] jpegImage, int imageSize)
                             throws TJException {
    if (jpegImage == null || imageSize < 1)
      throw new IllegalArgumentException("Invalid argument in setSourceImage()");
    jpegBuf = jpegImage;
    jpegBufSize = imageSize;
    decompressHeader(jpegBuf, jpegBufSize);
    yuvImage = null;
  }

  /**
   * @deprecated Use {@link #setSourceImage(byte[], int)} instead.
   */
  @Deprecated
  public void setJPEGImage(byte[] jpegImage, int imageSize)
                           throws TJException {
    setSourceImage(jpegImage, imageSize);
  }

  /**
   * Associate the specified YUV planar source image with this decompressor
   * instance.  Subsequent decompress operations will decode this image into an
   * RGB or grayscale destination image.
   *
   * @param srcImage {@link YUVImage} instance containing a YUV planar image to
   * be decoded.  This image is not modified.
   */
  public void setSourceImage(YUVImage srcImage) {
    if (srcImage == null)
      throw new IllegalArgumentException("Invalid argument in setSourceImage()");
    yuvImage = srcImage;
    jpegBuf = null;
    jpegBufSize = 0;
  }


  /**
   * Returns the width of the source image (JPEG or YUV) associated with this
   * decompressor instance.
   *
   * @return the width of the source image (JPEG or YUV) associated with this
   * decompressor instance.
   */
  public int getWidth() {
    if (yuvImage != null)
      return yuvImage.getWidth();
    if (jpegWidth < 1)
      throw new IllegalStateException(NO_ASSOC_ERROR);
    return jpegWidth;
  }

  /**
   * Returns the height of the source image (JPEG or YUV) associated with this
   * decompressor instance.
   *
   * @return the height of the source image (JPEG or YUV) associated with this
   * decompressor instance.
   */
  public int getHeight() {
    if (yuvImage != null)
      return yuvImage.getHeight();
    if (jpegHeight < 1)
      throw new IllegalStateException(NO_ASSOC_ERROR);
    return jpegHeight;
  }

  /**
   * Returns the level of chrominance subsampling used in the source image
   * (JPEG or YUV) associated with this decompressor instance.  See
   * {@link TJ#SAMP_444 TJ.SAMP_*}.
   *
   * @return the level of chrominance subsampling used in the source image
   * (JPEG or YUV) associated with this decompressor instance.
   */
  public int getSubsamp() {
    if (yuvImage != null)
      return yuvImage.getSubsamp();
    if (jpegSubsamp < 0)
      throw new IllegalStateException(NO_ASSOC_ERROR);
    if (jpegSubsamp >= TJ.NUMSAMP)
      throw new IllegalStateException("JPEG header information is invalid");
    return jpegSubsamp;
  }

  /**
   * Returns the colorspace used in the source image (JPEG or YUV) associated
   * with this decompressor instance.  See {@link TJ#CS_RGB TJ.CS_*}.  If the
   * source image is YUV, then this always returns {@link TJ#CS_YCbCr}.
   *
   * @return the colorspace used in the source image (JPEG or YUV) associated
   * with this decompressor instance.
   */
  public int getColorspace() {
    if (yuvImage != null)
      return TJ.CS_YCbCr;
    if (jpegColorspace < 0)
      throw new IllegalStateException(NO_ASSOC_ERROR);
    if (jpegColorspace >= TJ.NUMCS)
      throw new IllegalStateException("JPEG header information is invalid");
    return jpegColorspace;
  }

  /**
   * Returns the JPEG image buffer associated with this decompressor instance.
   *
   * @return the JPEG image buffer associated with this decompressor instance.
   */
  public byte[] getJPEGBuf() {
    if (jpegBuf == null)
      throw new IllegalStateException(NO_ASSOC_ERROR);
    return jpegBuf;
  }

  /**
   * Returns the size of the JPEG image (in bytes) associated with this
   * decompressor instance.
   *
   * @return the size of the JPEG image (in bytes) associated with this
   * decompressor instance.
   */
  public int getJPEGSize() {
    if (jpegBufSize < 1)
      throw new IllegalStateException(NO_ASSOC_ERROR);
    return jpegBufSize;
  }

  /**
   * Returns the width of the largest scaled-down image that the TurboJPEG
   * decompressor can generate without exceeding the desired image width and
   * height.
   *
   * @param desiredWidth desired width (in pixels) of the decompressed image.
   * Setting this to 0 is the same as setting it to the width of the JPEG image
   * (in other words, the width will not be considered when determining the
   * scaled image size.)
   *
   * @param desiredHeight desired height (in pixels) of the decompressed image.
   * Setting this to 0 is the same as setting it to the height of the JPEG
   * image (in other words, the height will not be considered when determining
   * the scaled image size.)
   *
   * @return the width of the largest scaled-down image that the TurboJPEG
   * decompressor can generate without exceeding the desired image width and
   * height.
   */
  public int getScaledWidth(int desiredWidth, int desiredHeight) {
    if (jpegWidth < 1 || jpegHeight < 1)
      throw new IllegalStateException(NO_ASSOC_ERROR);
    if (desiredWidth < 0 || desiredHeight < 0)
      throw new IllegalArgumentException("Invalid argument in getScaledWidth()");
    TJScalingFactor[] sf = TJ.getScalingFactors();
    if (desiredWidth == 0)
      desiredWidth = jpegWidth;
    if (desiredHeight == 0)
      desiredHeight = jpegHeight;
    int scaledWidth = jpegWidth, scaledHeight = jpegHeight;
    for (int i = 0; i < sf.length; i++) {
      scaledWidth = sf[i].getScaled(jpegWidth);
      scaledHeight = sf[i].getScaled(jpegHeight);
      if (scaledWidth <= desiredWidth && scaledHeight <= desiredHeight)
        break;
    }
    if (scaledWidth > desiredWidth || scaledHeight > desiredHeight)
      throw new IllegalArgumentException("Could not scale down to desired image dimensions");
    return scaledWidth;
  }

  /**
   * Returns the height of the largest scaled-down image that the TurboJPEG
   * decompressor can generate without exceeding the desired image width and
   * height.
   *
   * @param desiredWidth desired width (in pixels) of the decompressed image.
   * Setting this to 0 is the same as setting it to the width of the JPEG image
   * (in other words, the width will not be considered when determining the
   * scaled image size.)
   *
   * @param desiredHeight desired height (in pixels) of the decompressed image.
   * Setting this to 0 is the same as setting it to the height of the JPEG
   * image (in other words, the height will not be considered when determining
   * the scaled image size.)
   *
   * @return the height of the largest scaled-down image that the TurboJPEG
   * decompressor can generate without exceeding the desired image width and
   * height.
   */
  public int getScaledHeight(int desiredWidth, int desiredHeight) {
    if (jpegWidth < 1 || jpegHeight < 1)
      throw new IllegalStateException(NO_ASSOC_ERROR);
    if (desiredWidth < 0 || desiredHeight < 0)
      throw new IllegalArgumentException("Invalid argument in getScaledHeight()");
    TJScalingFactor[] sf = TJ.getScalingFactors();
    if (desiredWidth == 0)
      desiredWidth = jpegWidth;
    if (desiredHeight == 0)
      desiredHeight = jpegHeight;
    int scaledWidth = jpegWidth, scaledHeight = jpegHeight;
    for (int i = 0; i < sf.length; i++) {
      scaledWidth = sf[i].getScaled(jpegWidth);
      scaledHeight = sf[i].getScaled(jpegHeight);
      if (scaledWidth <= desiredWidth && scaledHeight <= desiredHeight)
        break;
    }
    if (scaledWidth > desiredWidth || scaledHeight > desiredHeight)
      throw new IllegalArgumentException("Could not scale down to desired image dimensions");
    return scaledHeight;
  }

  /**
   * Decompress the JPEG source image or decode the YUV source image associated
   * with this decompressor instance and output a grayscale, RGB, or CMYK image
   * to the given destination buffer.
   *
   * @param dstBuf buffer that will receive the decompressed/decoded image.
   * If the source image is a JPEG image, then this buffer should normally be
   * <code>pitch * scaledHeight</code> bytes in size, where
   * <code>scaledHeight</code> can be determined by calling <code>
   * scalingFactor.{@link TJScalingFactor#getScaled getScaled}(jpegHeight)
   * </code> with one of the scaling factors returned from {@link
   * TJ#getScalingFactors} or by calling {@link #getScaledHeight}.  If the
   * source image is a YUV image, then this buffer should normally be
   * <code>pitch * height</code> bytes in size, where <code>height</code> is
   * the height of the YUV image.  However, the buffer may also be larger than
   * the dimensions of the source image, in which case the <code>x</code>,
   * <code>y</code>, and <code>pitch</code> parameters can be used to specify
   * the region into which the source image should be decompressed/decoded.
   *
   * @param x x offset (in pixels) of the region in the destination image into
   * which the source image should be decompressed/decoded
   *
   * @param y y offset (in pixels) of the region in the destination image into
   * which the source image should be decompressed/decoded
   *
   * @param desiredWidth If the source image is a JPEG image, then this
   * specifies the desired width (in pixels) of the decompressed image (or
   * image region.)  If the desired destination image dimensions are different
   * than the source image dimensions, then TurboJPEG will use scaling in the
   * JPEG decompressor to generate the largest possible image that will fit
   * within the desired dimensions.  Setting this to 0 is the same as setting
   * it to the width of the JPEG image (in other words, the width will not be
   * considered when determining the scaled image size.)  This parameter is
   * ignored if the source image is a YUV image.
   *
   * @param pitch bytes per line of the destination image.  Normally, this
   * should be set to <code>scaledWidth * TJ.pixelSize(pixelFormat)</code> if
   * the destination image is unpadded, but you can use this to, for instance,
   * pad each line of the destination image to a 4-byte boundary or to
   * decompress/decode the source image into a region of a larger image.  NOTE:
   * if the source image is a JPEG image, then <code>scaledWidth</code> can be
   * determined by calling <code>
   * scalingFactor.{@link TJScalingFactor#getScaled getScaled}(jpegWidth)
   * </code> or by calling {@link #getScaledWidth}.  If the source image is a
   * YUV image, then <code>scaledWidth</code> is the width of the YUV image.
   * Setting this parameter to 0 is the equivalent of setting it to
   * <code>scaledWidth * TJ.pixelSize(pixelFormat)</code>.
   *
   * @param desiredHeight If the source image is a JPEG image, then this
   * specifies the desired height (in pixels) of the decompressed image (or
   * image region.)  If the desired destination image dimensions are different
   * than the source image dimensions, then TurboJPEG will use scaling in the
   * JPEG decompressor to generate the largest possible image that will fit
   * within the desired dimensions.  Setting this to 0 is the same as setting
   * it to the height of the JPEG image (in other words, the height will not be
   * considered when determining the scaled image size.)  This parameter is
   * ignored if the source image is a YUV image.
   *
   * @param pixelFormat pixel format of the decompressed/decoded image (one of
   * {@link TJ#PF_RGB TJ.PF_*})
   *
   * @param flags the bitwise OR of one or more of
   * {@link TJ#FLAG_BOTTOMUP TJ.FLAG_*}
   */
  public void decompress(byte[] dstBuf, int x, int y, int desiredWidth,
                         int pitch, int desiredHeight, int pixelFormat,
                         int flags) throws TJException {
    if (jpegBuf == null && yuvImage == null)
      throw new IllegalStateException(NO_ASSOC_ERROR);
    if (dstBuf == null || x < 0 || y < 0 || pitch < 0 ||
        (yuvImage != null && (desiredWidth < 0 || desiredHeight < 0)) ||
        pixelFormat < 0 || pixelFormat >= TJ.NUMPF || flags < 0)
      throw new IllegalArgumentException("Invalid argument in decompress()");
    if (yuvImage != null)
      decodeYUV(yuvImage.getPlanes(), yuvImage.getOffsets(),
                yuvImage.getStrides(), yuvImage.getSubsamp(), dstBuf, x, y,
                yuvImage.getWidth(), pitch, yuvImage.getHeight(), pixelFormat,
                flags);
    else {
      if (x > 0 || y > 0)
        decompress(jpegBuf, jpegBufSize, dstBuf, x, y, desiredWidth, pitch,
                   desiredHeight, pixelFormat, flags);
      else
        decompress(jpegBuf, jpegBufSize, dstBuf, desiredWidth, pitch,
                   desiredHeight, pixelFormat, flags);
    }
  }

  /**
   * @deprecated Use
   * {@link #decompress(byte[], int, int, int, int, int, int, int)} instead.
   */
  @Deprecated
  public void decompress(byte[] dstBuf, int desiredWidth, int pitch,
                         int desiredHeight, int pixelFormat, int flags)
                         throws TJException {
    decompress(dstBuf, 0, 0, desiredWidth, pitch, desiredHeight, pixelFormat,
               flags);
  }

  /**
   * Decompress the JPEG source image associated with this decompressor
   * instance and return a buffer containing the decompressed image.
   *
   * @param desiredWidth see
   * {@link #decompress(byte[], int, int, int, int, int, int, int)}
   * for description
   *
   * @param pitch see
   * {@link #decompress(byte[], int, int, int, int, int, int, int)}
   * for description
   *
   * @param desiredHeight see
   * {@link #decompress(byte[], int, int, int, int, int, int, int)}
   * for description
   *
   * @param pixelFormat pixel format of the decompressed image (one of
   * {@link TJ#PF_RGB TJ.PF_*})
   *
   * @param flags the bitwise OR of one or more of
   * {@link TJ#FLAG_BOTTOMUP TJ.FLAG_*}
   *
   * @return a buffer containing the decompressed image.
   */
  public byte[] decompress(int desiredWidth, int pitch, int desiredHeight,
                           int pixelFormat, int flags) throws TJException {
    if (pitch < 0 ||
        (yuvImage == null && (desiredWidth < 0 || desiredHeight < 0)) ||
        pixelFormat < 0 || pixelFormat >= TJ.NUMPF || flags < 0)
      throw new IllegalArgumentException("Invalid argument in decompress()");
    int pixelSize = TJ.getPixelSize(pixelFormat);
    int scaledWidth = getScaledWidth(desiredWidth, desiredHeight);
    int scaledHeight = getScaledHeight(desiredWidth, desiredHeight);
    if (pitch == 0)
      pitch = scaledWidth * pixelSize;
    byte[] buf = new byte[pitch * scaledHeight];
    decompress(buf, desiredWidth, pitch, desiredHeight, pixelFormat, flags);
    return buf;
  }

  /**
   * Decompress the JPEG source image associated with this decompressor
   * instance into a YUV planar image and store it in the given
   * <code>YUVImage</code> instance.  This method performs JPEG decompression
   * but leaves out the color conversion step, so a planar YUV image is
   * generated instead of an RGB or grayscale image.  This method cannot be
   * used to decompress JPEG source images with the CMYK or YCCK colorspace.
   *
   * @param dstImage {@link YUVImage} instance that will receive the YUV planar
   * image.  The level of subsampling specified in this <code>YUVImage</code>
   * instance must match that of the JPEG image, and the width and height
   * specified in the <code>YUVImage</code> instance must match one of the
   * scaled image sizes that TurboJPEG is capable of generating from the JPEG
   * source image.
   *
   * @param flags the bitwise OR of one or more of
   * {@link TJ#FLAG_BOTTOMUP TJ.FLAG_*}
   */
  public void decompressToYUV(YUVImage dstImage, int flags)
                              throws TJException {
    if (jpegBuf == null)
      throw new IllegalStateException(NO_ASSOC_ERROR);
    if (dstImage == null || flags < 0)
      throw new IllegalArgumentException("Invalid argument in decompressToYUV()");
    int scaledWidth = getScaledWidth(dstImage.getWidth(),
                                     dstImage.getHeight());
    int scaledHeight = getScaledHeight(dstImage.getWidth(),
                                       dstImage.getHeight());
    if (scaledWidth != dstImage.getWidth() ||
        scaledHeight != dstImage.getHeight())
      throw new IllegalArgumentException("YUVImage dimensions do not match one of the scaled image sizes that TurboJPEG is capable of generating.");
    if (jpegSubsamp != dstImage.getSubsamp())
      throw new IllegalArgumentException("YUVImage subsampling level does not match that of the JPEG image");

    decompressToYUV(jpegBuf, jpegBufSize, dstImage.getPlanes(),
                    dstImage.getOffsets(), dstImage.getWidth(),
                    dstImage.getStrides(), dstImage.getHeight(), flags);
  }

  /**
   * @deprecated Use {@link #decompressToYUV(YUVImage, int)} instead.
   */
  @Deprecated
  public void decompressToYUV(byte[] dstBuf, int flags) throws TJException {
    YUVImage dstImage = new YUVImage(dstBuf, jpegWidth, 4, jpegHeight,
                                     jpegSubsamp);
    decompressToYUV(dstImage, flags);
  }

  /**
   * Decompress the JPEG source image associated with this decompressor
   * instance into a set of Y, U (Cb), and V (Cr) image planes and return a
   * <code>YUVImage</code> instance containing the decompressed image planes.
   * This method performs JPEG decompression but leaves out the color
   * conversion step, so a planar YUV image is generated instead of an RGB or
   * grayscale image.  This method cannot be used to decompress JPEG source
   * images with the CMYK or YCCK colorspace.
   *
   * @param desiredWidth desired width (in pixels) of the YUV image.  If the
   * desired image dimensions are different than the dimensions of the JPEG
   * image being decompressed, then TurboJPEG will use scaling in the JPEG
   * decompressor to generate the largest possible image that will fit within
   * the desired dimensions.  Setting this to 0 is the same as setting it to
   * the width of the JPEG image (in other words, the width will not be
   * considered when determining the scaled image size.)
   *
   * @param strides an array of integers, each specifying the number of bytes
   * per line in the corresponding plane of the output image.  Setting the
   * stride for any plane to 0 is the same as setting it to the scaled
   * component width of the plane.  If <tt>strides</tt> is NULL, then the
   * strides for all planes will be set to their respective scaled component
   * widths.  You can adjust the strides in order to add an arbitrary amount of
   * line padding to each plane.
   *
   * @param desiredHeight desired height (in pixels) of the YUV image.  If the
   * desired image dimensions are different than the dimensions of the JPEG
   * image being decompressed, then TurboJPEG will use scaling in the JPEG
   * decompressor to generate the largest possible image that will fit within
   * the desired dimensions.  Setting this to 0 is the same as setting it to
   * the height of the JPEG image (in other words, the height will not be
   * considered when determining the scaled image size.)
   *
   * @param flags the bitwise OR of one or more of
   * {@link TJ#FLAG_BOTTOMUP TJ.FLAG_*}
   *
   * @return a YUV planar image.
   */
  public YUVImage decompressToYUV(int desiredWidth, int[] strides,
                                  int desiredHeight,
                                  int flags) throws TJException {
    if (flags < 0)
      throw new IllegalArgumentException("Invalid argument in decompressToYUV()");
    if (jpegWidth < 1 || jpegHeight < 1 || jpegSubsamp < 0)
      throw new IllegalStateException(NO_ASSOC_ERROR);
    if (jpegSubsamp >= TJ.NUMSAMP)
      throw new IllegalStateException("JPEG header information is invalid");
    if (yuvImage != null)
      throw new IllegalStateException("Source image is the wrong type");

    int scaledWidth = getScaledWidth(desiredWidth, desiredHeight);
    int scaledHeight = getScaledHeight(desiredWidth, desiredHeight);
    YUVImage yuvImage = new YUVImage(scaledWidth, null, scaledHeight,
                                     jpegSubsamp);
    decompressToYUV(yuvImage, flags);
    return yuvImage;
  }

  /**
   * Decompress the JPEG source image associated with this decompressor
   * instance into a unified YUV planar image buffer and return a
   * <code>YUVImage</code> instance containing the decompressed image.  This
   * method performs JPEG decompression but leaves out the color conversion
   * step, so a planar YUV image is generated instead of an RGB or grayscale
   * image.  This method cannot be used to decompress JPEG source images with
   * the CMYK or YCCK colorspace.
   *
   * @param desiredWidth desired width (in pixels) of the YUV image.  If the
   * desired image dimensions are different than the dimensions of the JPEG
   * image being decompressed, then TurboJPEG will use scaling in the JPEG
   * decompressor to generate the largest possible image that will fit within
   * the desired dimensions.  Setting this to 0 is the same as setting it to
   * the width of the JPEG image (in other words, the width will not be
   * considered when determining the scaled image size.)
   *
   * @param pad the width of each line in each plane of the YUV image will be
   * padded to the nearest multiple of this number of bytes (must be a power of
   * 2.)
   *
   * @param desiredHeight desired height (in pixels) of the YUV image.  If the
   * desired image dimensions are different than the dimensions of the JPEG
   * image being decompressed, then TurboJPEG will use scaling in the JPEG
   * decompressor to generate the largest possible image that will fit within
   * the desired dimensions.  Setting this to 0 is the same as setting it to
   * the height of the JPEG image (in other words, the height will not be
   * considered when determining the scaled image size.)
   *
   * @param flags the bitwise OR of one or more of
   * {@link TJ#FLAG_BOTTOMUP TJ.FLAG_*}
   *
   * @return a YUV planar image.
   */
  public YUVImage decompressToYUV(int desiredWidth, int pad, int desiredHeight,
                                  int flags) throws TJException {
    if (flags < 0)
      throw new IllegalArgumentException("Invalid argument in decompressToYUV()");
    if (jpegWidth < 1 || jpegHeight < 1 || jpegSubsamp < 0)
      throw new IllegalStateException(NO_ASSOC_ERROR);
    if (jpegSubsamp >= TJ.NUMSAMP)
      throw new IllegalStateException("JPEG header information is invalid");
    if (yuvImage != null)
      throw new IllegalStateException("Source image is the wrong type");

    int scaledWidth = getScaledWidth(desiredWidth, desiredHeight);
    int scaledHeight = getScaledHeight(desiredWidth, desiredHeight);
    YUVImage yuvImage = new YUVImage(scaledWidth, pad, scaledHeight,
                                     jpegSubsamp);
    decompressToYUV(yuvImage, flags);
    return yuvImage;
  }

  /**
   * @deprecated Use {@link #decompressToYUV(int, int, int, int)} instead.
   */
  @Deprecated
  public byte[] decompressToYUV(int flags) throws TJException {
    YUVImage dstImage = new YUVImage(jpegWidth, 4, jpegHeight, jpegSubsamp);
    decompressToYUV(dstImage, flags);
    return dstImage.getBuf();
  }

  /**
   * Decompress the JPEG source image or decode the YUV source image associated
   * with this decompressor instance and output a grayscale, RGB, or CMYK image
   * to the given destination buffer.
   *
   * @param dstBuf buffer that will receive the decompressed/decoded image.
   * If the source image is a JPEG image, then this buffer should normally be
   * <code>stride * scaledHeight</code> pixels in size, where
   * <code>scaledHeight</code> can be determined by calling <code>
   * scalingFactor.{@link TJScalingFactor#getScaled getScaled}(jpegHeight)
   * </code> with one of the scaling factors returned from {@link
   * TJ#getScalingFactors} or by calling {@link #getScaledHeight}.  If the
   * source image is a YUV image, then this buffer should normally be
   * <code>stride * height</code> pixels in size, where <code>height</code> is
   * the height of the YUV image.  However, the buffer may also be larger than
   * the dimensions of the JPEG image, in which case the <code>x</code>,
   * <code>y</code>, and <code>stride</code> parameters can be used to specify
   * the region into which the source image should be decompressed.
   *
   * @param x x offset (in pixels) of the region in the destination image into
   * which the source image should be decompressed/decoded
   *
   * @param y y offset (in pixels) of the region in the destination image into
   * which the source image should be decompressed/decoded
   *
   * @param desiredWidth If the source image is a JPEG image, then this
   * specifies the desired width (in pixels) of the decompressed image (or
   * image region.)  If the desired destination image dimensions are different
   * than the source image dimensions, then TurboJPEG will use scaling in the
   * JPEG decompressor to generate the largest possible image that will fit
   * within the desired dimensions.  Setting this to 0 is the same as setting
   * it to the width of the JPEG image (in other words, the width will not be
   * considered when determining the scaled image size.)  This parameter is
   * ignored if the source image is a YUV image.
   *
   * @param stride pixels per line of the destination image.  Normally, this
   * should be set to <code>scaledWidth</code>, but you can use this to, for
   * instance, decompress the JPEG image into a region of a larger image.
   * NOTE: if the source image is a JPEG image, then <code>scaledWidth</code>
   * can be determined by calling <code>
   * scalingFactor.{@link TJScalingFactor#getScaled getScaled}(jpegWidth)
   * </code> or by calling {@link #getScaledWidth}.  If the source image is a
   * YUV image, then <code>scaledWidth</code> is the width of the YUV image.
   * Setting this parameter to 0 is the equivalent of setting it to
   * <code>scaledWidth</code>.
   *
   * @param desiredHeight If the source image is a JPEG image, then this
   * specifies the desired height (in pixels) of the decompressed image (or
   * image region.)  If the desired destination image dimensions are different
   * than the source image dimensions, then TurboJPEG will use scaling in the
   * JPEG decompressor to generate the largest possible image that will fit
   * within the desired dimensions.  Setting this to 0 is the same as setting
   * it to the height of the JPEG image (in other words, the height will not be
   * considered when determining the scaled image size.)  This parameter is
   * ignored if the source image is a YUV image.
   *
   * @param pixelFormat pixel format of the decompressed image (one of
   * {@link TJ#PF_RGB TJ.PF_*})
   *
   * @param flags the bitwise OR of one or more of
   * {@link TJ#FLAG_BOTTOMUP TJ.FLAG_*}
   */
  public void decompress(int[] dstBuf, int x, int y, int desiredWidth,
                         int stride, int desiredHeight, int pixelFormat,
                         int flags) throws TJException {
    if (jpegBuf == null && yuvImage == null)
      throw new IllegalStateException(NO_ASSOC_ERROR);
    if (dstBuf == null || x < 0 || y < 0 || stride < 0 ||
        (yuvImage != null && (desiredWidth < 0 || desiredHeight < 0)) ||
        pixelFormat < 0 || pixelFormat >= TJ.NUMPF || flags < 0)
      throw new IllegalArgumentException("Invalid argument in decompress()");
    if (yuvImage != null)
      decodeYUV(yuvImage.getPlanes(), yuvImage.getOffsets(),
                yuvImage.getStrides(), yuvImage.getSubsamp(), dstBuf, x, y,
                yuvImage.getWidth(), stride, yuvImage.getHeight(), pixelFormat,
                flags);
    else
      decompress(jpegBuf, jpegBufSize, dstBuf, x, y, desiredWidth, stride,
                 desiredHeight, pixelFormat, flags);
  }

  /**
   * Decompress the JPEG source image or decode the YUV source image associated
   * with this decompressor instance and output a decompressed/decoded image to
   * the given <code>BufferedImage</code> instance.
   *
   * @param dstImage a <code>BufferedImage</code> instance that will receive
   * the decompressed/decoded image.  If the source image is a JPEG image, then
   * the width and height of the <code>BufferedImage</code> instance must match
   * one of the scaled image sizes that TurboJPEG is capable of generating from
   * the JPEG image.  If the source image is a YUV image, then the width and
   * height of the <code>BufferedImage</code> instance must match the width and
   * height of the YUV image.
   *
   * @param flags the bitwise OR of one or more of
   * {@link TJ#FLAG_BOTTOMUP TJ.FLAG_*}
   */
  public void decompress(BufferedImage dstImage, int flags)
                         throws TJException {
    if (dstImage == null || flags < 0)
      throw new IllegalArgumentException("Invalid argument in decompress()");
    int desiredWidth = dstImage.getWidth();
    int desiredHeight = dstImage.getHeight();
    int scaledWidth, scaledHeight;

    if (yuvImage != null) {
      if (desiredWidth != yuvImage.getWidth() ||
          desiredHeight != yuvImage.getHeight())
        throw new IllegalArgumentException("BufferedImage dimensions do not match the dimensions of the source image.");
      scaledWidth = yuvImage.getWidth();
      scaledHeight = yuvImage.getHeight();
    } else {
      scaledWidth = getScaledWidth(desiredWidth, desiredHeight);
      scaledHeight = getScaledHeight(desiredWidth, desiredHeight);
      if (scaledWidth != desiredWidth || scaledHeight != desiredHeight)
        throw new IllegalArgumentException("BufferedImage dimensions do not match one of the scaled image sizes that TurboJPEG is capable of generating.");
    }
    int pixelFormat;  boolean intPixels = false;
    if (byteOrder == null)
      byteOrder = ByteOrder.nativeOrder();
    switch(dstImage.getType()) {
      case BufferedImage.TYPE_3BYTE_BGR:
        pixelFormat = TJ.PF_BGR;  break;
      case BufferedImage.TYPE_4BYTE_ABGR:
      case BufferedImage.TYPE_4BYTE_ABGR_PRE:
        pixelFormat = TJ.PF_XBGR;  break;
      case BufferedImage.TYPE_BYTE_GRAY:
        pixelFormat = TJ.PF_GRAY;  break;
      case BufferedImage.TYPE_INT_BGR:
        if (byteOrder == ByteOrder.BIG_ENDIAN)
          pixelFormat = TJ.PF_XBGR;
        else
          pixelFormat = TJ.PF_RGBX;
        intPixels = true;  break;
      case BufferedImage.TYPE_INT_RGB:
        if (byteOrder == ByteOrder.BIG_ENDIAN)
          pixelFormat = TJ.PF_XRGB;
        else
          pixelFormat = TJ.PF_BGRX;
        intPixels = true;  break;
      case BufferedImage.TYPE_INT_ARGB:
      case BufferedImage.TYPE_INT_ARGB_PRE:
        if (byteOrder == ByteOrder.BIG_ENDIAN)
          pixelFormat = TJ.PF_ARGB;
        else
          pixelFormat = TJ.PF_BGRA;
        intPixels = true;  break;
      default:
        throw new IllegalArgumentException("Unsupported BufferedImage format");
    }
    WritableRaster wr = dstImage.getRaster();
    if (intPixels) {
      SinglePixelPackedSampleModel sm =
        (SinglePixelPackedSampleModel)dstImage.getSampleModel();
      int stride = sm.getScanlineStride();
      DataBufferInt db = (DataBufferInt)wr.getDataBuffer();
      int[] buf = db.getData();
      if (yuvImage != null)
        decodeYUV(yuvImage.getPlanes(), yuvImage.getOffsets(),
                  yuvImage.getStrides(), yuvImage.getSubsamp(), buf, 0, 0,
                  yuvImage.getWidth(), stride, yuvImage.getHeight(),
                  pixelFormat, flags);
      else {
        if (jpegBuf == null)
          throw new IllegalStateException(NO_ASSOC_ERROR);
        decompress(jpegBuf, jpegBufSize, buf, 0, 0, scaledWidth, stride,
                   scaledHeight, pixelFormat, flags);
      }
    } else {
      ComponentSampleModel sm =
        (ComponentSampleModel)dstImage.getSampleModel();
      int pixelSize = sm.getPixelStride();
      if (pixelSize != TJ.getPixelSize(pixelFormat))
        throw new IllegalArgumentException("Inconsistency between pixel format and pixel size in BufferedImage");
      int pitch = sm.getScanlineStride();
      DataBufferByte db = (DataBufferByte)wr.getDataBuffer();
      byte[] buf = db.getData();
      decompress(buf, 0, 0, scaledWidth, pitch, scaledHeight, pixelFormat,
                 flags);
    }
  }

  /**
   * Decompress the JPEG source image or decode the YUV source image associated
   * with this decompressor instance and return a <code>BufferedImage</code>
   * instance containing the decompressed/decoded image.
   *
   * @param desiredWidth see
   * {@link #decompress(byte[], int, int, int, int, int, int, int)} for
   * description
   *
   * @param desiredHeight see
   * {@link #decompress(byte[], int, int, int, int, int, int, int)} for
   * description
   *
   * @param bufferedImageType the image type of the <code>BufferedImage</code>
   * instance that will be created (for instance,
   * <code>BufferedImage.TYPE_INT_RGB</code>)
   *
   * @param flags the bitwise OR of one or more of
   * {@link TJ#FLAG_BOTTOMUP TJ.FLAG_*}
   *
   * @return a <code>BufferedImage</code> instance containing the
   * decompressed/decoded image.
   */
  public BufferedImage decompress(int desiredWidth, int desiredHeight,
                                  int bufferedImageType, int flags)
                                  throws TJException {
    if ((yuvImage == null && (desiredWidth < 0 || desiredHeight < 0)) ||
        flags < 0)
      throw new IllegalArgumentException("Invalid argument in decompress()");
    int scaledWidth = getScaledWidth(desiredWidth, desiredHeight);
    int scaledHeight = getScaledHeight(desiredWidth, desiredHeight);
    BufferedImage img = new BufferedImage(scaledWidth, scaledHeight,
                                          bufferedImageType);
    decompress(img, flags);
    return img;
  }

  /**
   * Free the native structures associated with this decompressor instance.
   */
  @Override
  public void close() throws TJException {
    if (handle != 0)
      destroy();
  }

  @Override
  protected void finalize() throws Throwable {
    try {
      close();
    } catch(TJException e) {
    } finally {
      super.finalize();
    }
  };

  private native void init() throws TJException;

  private native void destroy() throws TJException;

  private native void decompressHeader(byte[] srcBuf, int size)
    throws TJException;

  @Deprecated
  private native void decompress(byte[] srcBuf, int size, byte[] dstBuf,
    int desiredWidth, int pitch, int desiredHeight, int pixelFormat, int flags)
    throws TJException;

  private native void decompress(byte[] srcBuf, int size, byte[] dstBuf, int x,
    int y, int desiredWidth, int pitch, int desiredHeight, int pixelFormat,
    int flags) throws TJException;

  @Deprecated
  private native void decompress(byte[] srcBuf, int size, int[] dstBuf,
    int desiredWidth, int stride, int desiredHeight, int pixelFormat,
    int flags) throws TJException;

  private native void decompress(byte[] srcBuf, int size, int[] dstBuf, int x,
    int y, int desiredWidth, int stride, int desiredHeight, int pixelFormat,
    int flags) throws TJException;

  @Deprecated
  private native void decompressToYUV(byte[] srcBuf, int size, byte[] dstBuf,
    int flags) throws TJException;

  private native void decompressToYUV(byte[] srcBuf, int size,
    byte[][] dstPlanes, int[] dstOffsets, int desiredWidth, int[] dstStrides,
    int desiredheight, int flags) throws TJException;

  private native void decodeYUV(byte[][] srcPlanes, int[] srcOffsets,
    int[] srcStrides, int subsamp, byte[] dstBuf, int x, int y, int width,
    int pitch, int height, int pixelFormat, int flags) throws TJException;

  private native void decodeYUV(byte[][] srcPlanes, int[] srcOffsets,
    int[] srcStrides, int subsamp, int[] dstBuf, int x, int y, int width,
    int stride, int height, int pixelFormat, int flags) throws TJException;

  static {
    TJLoader.load();
  }

  protected long handle = 0;
  protected byte[] jpegBuf = null;
  protected int jpegBufSize = 0;
  protected YUVImage yuvImage = null;
  protected int jpegWidth = 0;
  protected int jpegHeight = 0;
  protected int jpegSubsamp = -1;
  protected int jpegColorspace = -1;
  private ByteOrder byteOrder = null;
}
