/*
 * Copyright (C)2011, 2013-2014 D. R. Commander.  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;

/**
 * TurboJPEG lossless transformer
 */
public class TJTransformer extends TJDecompressor {

  /**
   * Create a TurboJPEG lossless transformer instance.
   */
  public TJTransformer() throws Exception {
    init();
  }

  /**
   * Create a TurboJPEG lossless transformer instance and associate the JPEG
   * 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)
   */
  public TJTransformer(byte[] jpegImage) throws Exception {
    init();
    setJPEGImage(jpegImage, jpegImage.length);
  }

  /**
   * Create a TurboJPEG lossless transformer instance and associate the JPEG
   * image of length <code>imageSize</code> bytes stored in
   * <code>jpegImage</code> with the newly created instance.
   *
   * @param jpegImage JPEG image buffer
   *
   * @param imageSize size of the JPEG image (in bytes)
   */
  public TJTransformer(byte[] jpegImage, int imageSize) throws Exception {
    init();
    setJPEGImage(jpegImage, imageSize);
  }

  /**
   * Losslessly transform the JPEG image associated with this transformer
   * instance into one or more JPEG images stored in the given destination
   * buffers.  Lossless transforms work by moving the raw coefficients from one
   * JPEG image structure to another without altering the values of the
   * coefficients.  While this is typically faster than decompressing the
   * image, transforming it, and re-compressing it, lossless transforms are not
   * free.  Each lossless transform requires reading and performing Huffman
   * decoding on all of the coefficients in the source image, regardless of the
   * size of the destination image.  Thus, this method provides a means of
   * generating multiple transformed images from the same source or of applying
   * multiple transformations simultaneously, in order to eliminate the need to
   * read the source coefficients multiple times.
   *
   * @param dstBufs an array of image buffers.  <code>dstbufs[i]</code> will
   * receive a JPEG image that has been transformed using the parameters in
   * <code>transforms[i]</code>.  Use {@link TJ#bufSize} to determine the
   * maximum size for each buffer based on the transformed or cropped width and
   * height and the level of subsampling used in the source image.
   *
   * @param transforms an array of {@link TJTransform} instances, each of
   * which specifies the transform parameters and/or cropping region for the
   * corresponding transformed output image
   *
   * @param flags the bitwise OR of one or more of
   * {@link TJ#FLAG_BOTTOMUP TJ.FLAG_*}
   */
  public void transform(byte[][] dstBufs, TJTransform[] transforms,
                        int flags) throws Exception {
    if (jpegBuf == null)
      throw new Exception("JPEG buffer not initialized");
    transformedSizes = transform(jpegBuf, jpegBufSize, dstBufs, transforms,
                                 flags);
  }

  /**
   * Losslessly transform the JPEG image associated with this transformer
   * instance and return an array of {@link TJDecompressor} instances, each of
   * which has a transformed JPEG image associated with it.
   *
   * @param transforms an array of {@link TJTransform} instances, each of
   * which specifies the transform parameters and/or cropping region for the
   * corresponding transformed output image
   *
   * @return an array of {@link TJDecompressor} instances, each of
   * which has a transformed JPEG image associated with it
   *
   * @param flags the bitwise OR of one or more of
   * {@link TJ#FLAG_BOTTOMUP TJ.FLAG_*}
   */
  public TJDecompressor[] transform(TJTransform[] transforms, int flags)
    throws Exception {
    byte[][] dstBufs = new byte[transforms.length][];
    if (jpegWidth < 1 || jpegHeight < 1)
      throw new Exception("JPEG buffer not initialized");
    for (int i = 0; i < transforms.length; i++) {
      int w = jpegWidth, h = jpegHeight;
      if ((transforms[i].options & TJTransform.OPT_CROP) != 0) {
        if (transforms[i].width != 0) w = transforms[i].width;
        if (transforms[i].height != 0) h = transforms[i].height;
      }
      dstBufs[i] = new byte[TJ.bufSize(w, h, jpegSubsamp)];
    }
    TJDecompressor[] tjd = new TJDecompressor[transforms.length];
    transform(dstBufs, transforms, flags);
    for (int i = 0; i < transforms.length; i++)
      tjd[i] = new TJDecompressor(dstBufs[i], transformedSizes[i]);
    return tjd;
  }

  /**
   * Returns an array containing the sizes of the transformed JPEG images
   * generated by the most recent transform operation.
   *
   * @return an array containing the sizes of the transformed JPEG images
   * generated by the most recent transform operation
   */
  public int[] getTransformedSizes() throws Exception {
    if (transformedSizes == null)
      throw new Exception("No image has been transformed yet");
    return transformedSizes;
  }

  private native void init() throws Exception;

  private native int[] transform(byte[] srcBuf, int srcSize, byte[][] dstBufs,
    TJTransform[] transforms, int flags) throws Exception;

  static {
    TJLoader.load();
  }

  private int[] transformedSizes = null;
};
