TJTransformer.java revision 92549de2c2b139070294aec12ec39b7c86a56b52
1/*
2 * Copyright (C)2011 D. R. Commander.  All Rights Reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * - Redistributions of source code must retain the above copyright notice,
8 *   this list of conditions and the following disclaimer.
9 * - Redistributions in binary form must reproduce the above copyright notice,
10 *   this list of conditions and the following disclaimer in the documentation
11 *   and/or other materials provided with the distribution.
12 * - Neither the name of the libjpeg-turbo Project nor the names of its
13 *   contributors may be used to endorse or promote products derived from this
14 *   software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS",
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
27 */
28
29package org.libjpegturbo.turbojpeg;
30
31/**
32 * TurboJPEG lossless transformer
33 */
34public class TJTransformer extends TJDecompressor {
35
36  /**
37   * Create a TurboJPEG lossless transformer instance.
38   */
39  public TJTransformer() throws Exception {
40    init();
41  }
42
43  /**
44   * Create a TurboJPEG lossless transformer instance and associate the JPEG
45   * image stored in <code>jpegImage</code> with the newly-created instance.
46   *
47   * @param jpegImage JPEG image buffer (size of JPEG image is assumed to be
48   * the length of the buffer)
49   */
50  public TJTransformer(byte[] jpegImage) throws Exception {
51    init();
52    setJPEGBuffer(jpegImage, jpegImage.length);
53  }
54
55  /**
56   * Create a TurboJPEG lossless transformer instance and associate the JPEG
57   * image of length <code>imageSize</code> bytes stored in
58   * <code>jpegImage</code> with the newly-created instance.
59   *
60   * @param jpegImage JPEG image buffer
61   *
62   * @param imageSize size of JPEG image (in bytes)
63   */
64  public TJTransformer(byte[] jpegImage, int imageSize) throws Exception {
65    init();
66    setJPEGBuffer(jpegImage, imageSize);
67  }
68
69  /**
70   * Losslessly transform the JPEG image associated with this transformer
71   * instance into one or more JPEG images stored in the given destination
72   * buffers.  Lossless transforms work by moving the raw coefficients from one
73   * JPEG image structure to another without altering the values of the
74   * coefficients.  While this is typically faster than decompressing the
75   * image, transforming it, and re-compressing it, lossless transforms are not
76   * free.  Each lossless transform requires reading and Huffman decoding all
77   * of the coefficients in the source image, regardless of the size of the
78   * destination image.  Thus, this function provides a means of generating
79   * multiple transformed images from the same source or of applying multiple
80   * transformations simultaneously, in order to eliminate the need to read the
81   * source coefficients multiple times.
82   *
83   * @param dstBufs an array of n image buffers.  <code>dstbufs[i]</code> will
84   * receive a JPEG image that has been transformed using the parameters in
85   * <code>transforms[i]</code>.  Use {@link TJ#bufSizeYUV} to determine the
86   * maximum size for each buffer based on the cropped width and height.
87   *
88   * @param transforms an array of n {@link TJTransform} instances, each of
89   * which specifies the transform parameters and/or cropping region for the
90   * corresponding transformed output image
91   *
92   * @param flags the bitwise OR of one or more of the flags described in
93   * {@link TJ}
94   */
95  public void transform(byte[][] dstBufs, TJTransform[] transforms,
96    int flags) throws Exception {
97    if(jpegBuf == null) throw new Exception("JPEG buffer not initialized");
98    transformedSizes = transform(jpegBuf, jpegBufSize, dstBufs, transforms,
99      flags);
100  }
101
102  /**
103   * Losslessly transform the JPEG image associated with this transformer
104   * instance and return an array of {@link TJDecompressor} instances, each of
105   * which has a transformed JPEG image associated with it.
106   *
107   * @param transforms an array of n {@link TJTransform} instances, each of
108   * which specifies the transform parameters and/or cropping region for the
109   * corresponding transformed output image
110   *
111   * @return an array of {@link TJDecompressor} instances, each of
112   * which has a transformed JPEG image associated with it
113   *
114   * @param flags the bitwise OR of one or more of the flags described in
115   * {@link TJ}
116   */
117  public TJDecompressor[] transform(TJTransform[] transforms, int flags)
118    throws Exception {
119    byte[][] dstBufs = new byte[transforms.length][];
120    if(jpegWidth < 1 || jpegHeight < 1)
121      throw new Exception("JPEG buffer not initialized");
122    for(int i = 0; i < transforms.length; i++) {
123      int w = jpegWidth, h = jpegHeight;
124      if((transforms[i].options & TJTransform.OPT_CROP) != 0) {
125        if(transforms[i].width != 0) w = transforms[i].width;
126        if(transforms[i].height != 0) h = transforms[i].height;
127      }
128      dstBufs[i] = new byte[TJ.bufSize(w, h)];
129    }
130    TJDecompressor[] tjd = new TJDecompressor[transforms.length];
131    transform(dstBufs, transforms, flags);
132    for(int i = 0; i < transforms.length; i++)
133      tjd[i] = new TJDecompressor(dstBufs[i], transformedSizes[i]);
134    return tjd;
135  }
136
137  /**
138   * Returns an array containing the sizes of the transformed JPEG images from
139   * the most recent call to {@link #transform transform()}.
140   *
141   * @return an array containing the sizes of the transformed JPEG images from
142   * the most recent call to {@link #transform transform()}
143   */
144  public int[] getTransformedSizes() throws Exception {
145    if(transformedSizes == null)
146      throw new Exception("No image has been transformed yet");
147    return transformedSizes;
148  }
149
150  private native void init() throws Exception;
151
152  private native int[] transform(byte[] srcBuf, int srcSize, byte[][] dstBufs,
153    TJTransform[] transforms, int flags) throws Exception;
154
155  static {
156    System.loadLibrary("turbojpeg");
157  }
158
159  private int[] transformedSizes = null;
160};
161