Home | History | Annotate | Download | only in turbojpeg
      1 /*
      2  * Copyright (C)2011-2015 D. R. Commander.  All Rights Reserved.
      3  * Copyright (C)2015 Viktor Szathmry.  All Rights Reserved.
      4  *
      5  * Redistribution and use in source and binary forms, with or without
      6  * modification, are permitted provided that the following conditions are met:
      7  *
      8  * - Redistributions of source code must retain the above copyright notice,
      9  *   this list of conditions and the following disclaimer.
     10  * - Redistributions in binary form must reproduce the above copyright notice,
     11  *   this list of conditions and the following disclaimer in the documentation
     12  *   and/or other materials provided with the distribution.
     13  * - Neither the name of the libjpeg-turbo Project nor the names of its
     14  *   contributors may be used to endorse or promote products derived from this
     15  *   software without specific prior written permission.
     16  *
     17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS",
     18  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
     21  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     22  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     23  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     24  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     25  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     26  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     27  * POSSIBILITY OF SUCH DAMAGE.
     28  */
     29 
     30 package org.libjpegturbo.turbojpeg;
     31 
     32 import java.awt.image.*;
     33 import java.nio.*;
     34 import java.io.*;
     35 
     36 /**
     37  * TurboJPEG compressor
     38  */
     39 public class TJCompressor implements Closeable {
     40 
     41   private static final String NO_ASSOC_ERROR =
     42     "No source image is associated with this instance";
     43 
     44   /**
     45    * Create a TurboJPEG compressor instance.
     46    */
     47   public TJCompressor() throws TJException {
     48     init();
     49   }
     50 
     51   /**
     52    * Create a TurboJPEG compressor instance and associate the uncompressed
     53    * source image stored in <code>srcImage</code> with the newly created
     54    * instance.
     55    *
     56    * @param srcImage see {@link #setSourceImage} for description
     57    *
     58    * @param x see {@link #setSourceImage} for description
     59    *
     60    * @param y see {@link #setSourceImage} for description
     61    *
     62    * @param width see {@link #setSourceImage} for description
     63    *
     64    * @param pitch see {@link #setSourceImage} for description
     65    *
     66    * @param height see {@link #setSourceImage} for description
     67    *
     68    * @param pixelFormat pixel format of the source image (one of
     69    * {@link TJ#PF_RGB TJ.PF_*})
     70    */
     71   public TJCompressor(byte[] srcImage, int x, int y, int width, int pitch,
     72                       int height, int pixelFormat) throws TJException {
     73     setSourceImage(srcImage, x, y, width, pitch, height, pixelFormat);
     74   }
     75 
     76   /**
     77    * @deprecated Use
     78    * {@link #TJCompressor(byte[], int, int, int, int, int, int)} instead.
     79    */
     80   @Deprecated
     81   public TJCompressor(byte[] srcImage, int width, int pitch, int height,
     82                       int pixelFormat) throws TJException {
     83     setSourceImage(srcImage, width, pitch, height, pixelFormat);
     84   }
     85 
     86   /**
     87    * Create a TurboJPEG compressor instance and associate the uncompressed
     88    * source image stored in <code>srcImage</code> with the newly created
     89    * instance.
     90    *
     91    * @param srcImage see
     92    * {@link #setSourceImage(BufferedImage, int, int, int, int)} for description
     93    *
     94    * @param x see
     95    * {@link #setSourceImage(BufferedImage, int, int, int, int)} for description
     96    *
     97    * @param y see
     98    * {@link #setSourceImage(BufferedImage, int, int, int, int)} for description
     99    *
    100    * @param width see
    101    * {@link #setSourceImage(BufferedImage, int, int, int, int)} for description
    102    *
    103    * @param height see
    104    * {@link #setSourceImage(BufferedImage, int, int, int, int)} for description
    105    */
    106   public TJCompressor(BufferedImage srcImage, int x, int y, int width,
    107                       int height) throws TJException {
    108     setSourceImage(srcImage, x, y, width, height);
    109   }
    110 
    111   /**
    112    * Associate an uncompressed RGB, grayscale, or CMYK source image with this
    113    * compressor instance.
    114    *
    115    * @param srcImage image buffer containing RGB, grayscale, or CMYK pixels to
    116    * be compressed or encoded.  This buffer is not modified.
    117    *
    118    * @param x x offset (in pixels) of the region in the source image from which
    119    * the JPEG or YUV image should be compressed/encoded
    120    *
    121    * @param y y offset (in pixels) of the region in the source image from which
    122    * the JPEG or YUV image should be compressed/encoded
    123    *
    124    * @param width width (in pixels) of the region in the source image from
    125    * which the JPEG or YUV image should be compressed/encoded
    126    *
    127    * @param pitch bytes per line of the source image.  Normally, this should be
    128    * <code>width * TJ.pixelSize(pixelFormat)</code> if the source image is
    129    * unpadded, but you can use this parameter to, for instance, specify that
    130    * the scanlines in the source image are padded to a 4-byte boundary or to
    131    * compress/encode a JPEG or YUV image from a region of a larger source
    132    * image.  You can also be clever and use this parameter to skip lines, etc.
    133    * Setting this parameter to 0 is the equivalent of setting it to
    134    * <code>width * TJ.pixelSize(pixelFormat)</code>.
    135    *
    136    * @param height height (in pixels) of the region in the source image from
    137    * which the JPEG or YUV image should be compressed/encoded
    138    *
    139    * @param pixelFormat pixel format of the source image (one of
    140    * {@link TJ#PF_RGB TJ.PF_*})
    141    */
    142   public void setSourceImage(byte[] srcImage, int x, int y, int width,
    143                              int pitch, int height, int pixelFormat)
    144                              throws TJException {
    145     if (handle == 0) init();
    146     if (srcImage == null || x < 0 || y < 0 || width < 1 || height < 1 ||
    147         pitch < 0 || pixelFormat < 0 || pixelFormat >= TJ.NUMPF)
    148       throw new IllegalArgumentException("Invalid argument in setSourceImage()");
    149     srcBuf = srcImage;
    150     srcWidth = width;
    151     if (pitch == 0)
    152       srcPitch = width * TJ.getPixelSize(pixelFormat);
    153     else
    154       srcPitch = pitch;
    155     srcHeight = height;
    156     srcPixelFormat = pixelFormat;
    157     srcX = x;
    158     srcY = y;
    159     srcBufInt = null;
    160     srcYUVImage = null;
    161   }
    162 
    163   /**
    164    * @deprecated Use
    165    * {@link #setSourceImage(byte[], int, int, int, int, int, int)} instead.
    166    */
    167   @Deprecated
    168   public void setSourceImage(byte[] srcImage, int width, int pitch,
    169                              int height, int pixelFormat) throws TJException {
    170     setSourceImage(srcImage, 0, 0, width, pitch, height, pixelFormat);
    171     srcX = srcY = -1;
    172   }
    173 
    174   /**
    175    * Associate an uncompressed RGB or grayscale source image with this
    176    * compressor instance.
    177    *
    178    * @param srcImage a <code>BufferedImage</code> instance containing RGB or
    179    * grayscale pixels to be compressed or encoded.  This image is not modified.
    180    *
    181    * @param x x offset (in pixels) of the region in the source image from which
    182    * the JPEG or YUV image should be compressed/encoded
    183    *
    184    * @param y y offset (in pixels) of the region in the source image from which
    185    * the JPEG or YUV image should be compressed/encoded
    186    *
    187    * @param width width (in pixels) of the region in the source image from
    188    * which the JPEG or YUV image should be compressed/encoded (0 = use the
    189    * width of the source image)
    190    *
    191    * @param height height (in pixels) of the region in the source image from
    192    * which the JPEG or YUV image should be compressed/encoded (0 = use the
    193    * height of the source image)
    194    */
    195   public void setSourceImage(BufferedImage srcImage, int x, int y, int width,
    196                              int height) throws TJException {
    197     if (handle == 0) init();
    198     if (srcImage == null || x < 0 || y < 0 || width < 0 || height < 0)
    199       throw new IllegalArgumentException("Invalid argument in setSourceImage()");
    200     srcX = x;
    201     srcY = y;
    202     srcWidth = (width == 0) ? srcImage.getWidth(): width;
    203     srcHeight = (height == 0) ? srcImage.getHeight() : height;
    204     if (x + width > srcImage.getWidth() || y + height > srcImage.getHeight())
    205       throw new IllegalArgumentException("Compression region exceeds the bounds of the source image");
    206 
    207     int pixelFormat;
    208     boolean intPixels = false;
    209     if (byteOrder == null)
    210       byteOrder = ByteOrder.nativeOrder();
    211     switch(srcImage.getType()) {
    212       case BufferedImage.TYPE_3BYTE_BGR:
    213         pixelFormat = TJ.PF_BGR;  break;
    214       case BufferedImage.TYPE_4BYTE_ABGR:
    215       case BufferedImage.TYPE_4BYTE_ABGR_PRE:
    216         pixelFormat = TJ.PF_XBGR;  break;
    217       case BufferedImage.TYPE_BYTE_GRAY:
    218         pixelFormat = TJ.PF_GRAY;  break;
    219       case BufferedImage.TYPE_INT_BGR:
    220         if (byteOrder == ByteOrder.BIG_ENDIAN)
    221           pixelFormat = TJ.PF_XBGR;
    222         else
    223           pixelFormat = TJ.PF_RGBX;
    224         intPixels = true;  break;
    225       case BufferedImage.TYPE_INT_RGB:
    226       case BufferedImage.TYPE_INT_ARGB:
    227       case BufferedImage.TYPE_INT_ARGB_PRE:
    228         if (byteOrder == ByteOrder.BIG_ENDIAN)
    229           pixelFormat = TJ.PF_XRGB;
    230         else
    231           pixelFormat = TJ.PF_BGRX;
    232         intPixels = true;  break;
    233       default:
    234         throw new IllegalArgumentException("Unsupported BufferedImage format");
    235     }
    236     srcPixelFormat = pixelFormat;
    237 
    238     WritableRaster wr = srcImage.getRaster();
    239     if (intPixels) {
    240       SinglePixelPackedSampleModel sm =
    241         (SinglePixelPackedSampleModel)srcImage.getSampleModel();
    242       srcStride = sm.getScanlineStride();
    243       DataBufferInt db = (DataBufferInt)wr.getDataBuffer();
    244       srcBufInt = db.getData();
    245       srcBuf = null;
    246     } else {
    247       ComponentSampleModel sm =
    248         (ComponentSampleModel)srcImage.getSampleModel();
    249       int pixelSize = sm.getPixelStride();
    250       if (pixelSize != TJ.getPixelSize(pixelFormat))
    251         throw new IllegalArgumentException("Inconsistency between pixel format and pixel size in BufferedImage");
    252       srcPitch = sm.getScanlineStride();
    253       DataBufferByte db = (DataBufferByte)wr.getDataBuffer();
    254       srcBuf = db.getData();
    255       srcBufInt = null;
    256     }
    257     srcYUVImage = null;
    258   }
    259 
    260   /**
    261    * Associate an uncompressed YUV planar source image with this compressor
    262    * instance.
    263    *
    264    * @param srcImage YUV planar image to be compressed.  This image is not
    265    * modified.
    266    */
    267   public void setSourceImage(YUVImage srcImage) throws TJException {
    268     if (handle == 0) init();
    269     if (srcImage == null)
    270       throw new IllegalArgumentException("Invalid argument in setSourceImage()");
    271     srcYUVImage = srcImage;
    272     srcBuf = null;
    273     srcBufInt = null;
    274   }
    275 
    276   /**
    277    * Set the level of chrominance subsampling for subsequent compress/encode
    278    * operations.  When pixels are converted from RGB to YCbCr (see
    279    * {@link TJ#CS_YCbCr}) or from CMYK to YCCK (see {@link TJ#CS_YCCK}) as part
    280    * of the JPEG compression process, some of the Cb and Cr (chrominance)
    281    * components can be discarded or averaged together to produce a smaller
    282    * image with little perceptible loss of image clarity (the human eye is more
    283    * sensitive to small changes in brightness than to small changes in color.)
    284    * This is called "chrominance subsampling".
    285    * <p>
    286    * NOTE: This method has no effect when compressing a JPEG image from a YUV
    287    * planar source.  In that case, the level of chrominance subsampling in
    288    * the JPEG image is determined by the source.  Further, this method has no
    289    * effect when encoding to a pre-allocated {@link YUVImage} instance.  In
    290    * that case, the level of chrominance subsampling is determined by the
    291    * destination.
    292    *
    293    * @param newSubsamp the level of chrominance subsampling to use in
    294    * subsequent compress/encode oeprations (one of
    295    * {@link TJ#SAMP_444 TJ.SAMP_*})
    296    */
    297   public void setSubsamp(int newSubsamp) {
    298     if (newSubsamp < 0 || newSubsamp >= TJ.NUMSAMP)
    299       throw new IllegalArgumentException("Invalid argument in setSubsamp()");
    300     subsamp = newSubsamp;
    301   }
    302 
    303   /**
    304    * Set the JPEG image quality level for subsequent compress operations.
    305    *
    306    * @param quality the new JPEG image quality level (1 to 100, 1 = worst,
    307    * 100 = best)
    308    */
    309   public void setJPEGQuality(int quality) {
    310     if (quality < 1 || quality > 100)
    311       throw new IllegalArgumentException("Invalid argument in setJPEGQuality()");
    312     jpegQuality = quality;
    313   }
    314 
    315   /**
    316    * Compress the uncompressed source image associated with this compressor
    317    * instance and output a JPEG image to the given destination buffer.
    318    *
    319    * @param dstBuf buffer that will receive the JPEG image.  Use
    320    * {@link TJ#bufSize} to determine the maximum size for this buffer based on
    321    * the source image's width and height and the desired level of chrominance
    322    * subsampling.
    323    *
    324    * @param flags the bitwise OR of one or more of
    325    * {@link TJ#FLAG_BOTTOMUP TJ.FLAG_*}
    326    */
    327   public void compress(byte[] dstBuf, int flags) throws TJException {
    328     if (dstBuf == null || flags < 0)
    329       throw new IllegalArgumentException("Invalid argument in compress()");
    330     if (srcBuf == null && srcBufInt == null && srcYUVImage == null)
    331       throw new IllegalStateException(NO_ASSOC_ERROR);
    332     if (jpegQuality < 0)
    333       throw new IllegalStateException("JPEG Quality not set");
    334     if (subsamp < 0 && srcYUVImage == null)
    335       throw new IllegalStateException("Subsampling level not set");
    336 
    337     if (srcYUVImage != null)
    338       compressedSize = compressFromYUV(srcYUVImage.getPlanes(),
    339                                        srcYUVImage.getOffsets(),
    340                                        srcYUVImage.getWidth(),
    341                                        srcYUVImage.getStrides(),
    342                                        srcYUVImage.getHeight(),
    343                                        srcYUVImage.getSubsamp(),
    344                                        dstBuf, jpegQuality, flags);
    345     else if (srcBuf != null) {
    346       if (srcX >= 0 && srcY >= 0)
    347         compressedSize = compress(srcBuf, srcX, srcY, srcWidth, srcPitch,
    348                                   srcHeight, srcPixelFormat, dstBuf, subsamp,
    349                                   jpegQuality, flags);
    350       else
    351         compressedSize = compress(srcBuf, srcWidth, srcPitch, srcHeight,
    352                                   srcPixelFormat, dstBuf, subsamp, jpegQuality,
    353                                   flags);
    354     } else if (srcBufInt != null) {
    355       if (srcX >= 0 && srcY >= 0)
    356         compressedSize = compress(srcBufInt, srcX, srcY, srcWidth, srcStride,
    357                                   srcHeight, srcPixelFormat, dstBuf, subsamp,
    358                                   jpegQuality, flags);
    359       else
    360         compressedSize = compress(srcBufInt, srcWidth, srcStride, srcHeight,
    361                                   srcPixelFormat, dstBuf, subsamp, jpegQuality,
    362                                   flags);
    363     }
    364   }
    365 
    366   /**
    367    * Compress the uncompressed source image associated with this compressor
    368    * instance and return a buffer containing a JPEG image.
    369    *
    370    * @param flags the bitwise OR of one or more of
    371    * {@link TJ#FLAG_BOTTOMUP TJ.FLAG_*}
    372    *
    373    * @return a buffer containing a JPEG image.  The length of this buffer will
    374    * not be equal to the size of the JPEG image.  Use {@link
    375    * #getCompressedSize} to obtain the size of the JPEG image.
    376    */
    377   public byte[] compress(int flags) throws TJException {
    378     checkSourceImage();
    379     byte[] buf = new byte[TJ.bufSize(srcWidth, srcHeight, subsamp)];
    380     compress(buf, flags);
    381     return buf;
    382   }
    383 
    384   /**
    385    * @deprecated Use
    386    * {@link #setSourceImage(BufferedImage, int, int, int, int)} and
    387    * {@link #compress(byte[], int)} instead.
    388    */
    389   @Deprecated
    390   public void compress(BufferedImage srcImage, byte[] dstBuf, int flags)
    391                        throws TJException {
    392     setSourceImage(srcImage, 0, 0, 0, 0);
    393     compress(dstBuf, flags);
    394   }
    395 
    396   /**
    397    * @deprecated Use
    398    * {@link #setSourceImage(BufferedImage, int, int, int, int)} and
    399    * {@link #compress(int)} instead.
    400    */
    401   @Deprecated
    402   public byte[] compress(BufferedImage srcImage, int flags)
    403                          throws TJException {
    404     setSourceImage(srcImage, 0, 0, 0, 0);
    405     return compress(flags);
    406   }
    407 
    408   /**
    409    * Encode the uncompressed source image associated with this compressor
    410    * instance into a YUV planar image and store it in the given
    411    * <code>YUVImage</code> instance.   This method uses the accelerated color
    412    * conversion routines in TurboJPEG's underlying codec but does not execute
    413    * any of the other steps in the JPEG compression process.  Encoding
    414    * CMYK source images to YUV is not supported.
    415    *
    416    * @param dstImage {@link YUVImage} instance that will receive the YUV planar
    417    * image
    418    *
    419    * @param flags the bitwise OR of one or more of
    420    * {@link TJ#FLAG_BOTTOMUP TJ.FLAG_*}
    421    */
    422   public void encodeYUV(YUVImage dstImage, int flags) throws TJException {
    423     if (dstImage == null || flags < 0)
    424       throw new IllegalArgumentException("Invalid argument in encodeYUV()");
    425     if (srcBuf == null && srcBufInt == null)
    426       throw new IllegalStateException(NO_ASSOC_ERROR);
    427     if (srcYUVImage != null)
    428       throw new IllegalStateException("Source image is not correct type");
    429     checkSubsampling();
    430     if (srcWidth != dstImage.getWidth() || srcHeight != dstImage.getHeight())
    431       throw new IllegalStateException("Destination image is the wrong size");
    432 
    433     if (srcBufInt != null) {
    434       encodeYUV(srcBufInt, srcX, srcY, srcWidth, srcStride, srcHeight,
    435                 srcPixelFormat, dstImage.getPlanes(), dstImage.getOffsets(),
    436                 dstImage.getStrides(), dstImage.getSubsamp(), flags);
    437     } else {
    438       encodeYUV(srcBuf, srcX, srcY, srcWidth, srcPitch, srcHeight,
    439                 srcPixelFormat, dstImage.getPlanes(), dstImage.getOffsets(),
    440                 dstImage.getStrides(), dstImage.getSubsamp(), flags);
    441     }
    442     compressedSize = 0;
    443   }
    444 
    445   /**
    446    * @deprecated Use {@link #encodeYUV(YUVImage, int)} instead.
    447    */
    448   @Deprecated
    449   public void encodeYUV(byte[] dstBuf, int flags) throws TJException {
    450     if(dstBuf == null)
    451       throw new IllegalArgumentException("Invalid argument in encodeYUV()");
    452     checkSourceImage();
    453     checkSubsampling();
    454     YUVImage yuvImage = new YUVImage(dstBuf, srcWidth, 4, srcHeight, subsamp);
    455     encodeYUV(yuvImage, flags);
    456   }
    457 
    458   /**
    459    * Encode the uncompressed source image associated with this compressor
    460    * instance into a unified YUV planar image buffer and return a
    461    * <code>YUVImage</code> instance containing the encoded image.  This method
    462    * uses the accelerated color conversion routines in TurboJPEG's underlying
    463    * codec but does not execute any of the other steps in the JPEG compression
    464    * process.  Encoding CMYK source images to YUV is not supported.
    465    *
    466    * @param pad the width of each line in each plane of the YUV image will be
    467    * padded to the nearest multiple of this number of bytes (must be a power of
    468    * 2.)
    469    *
    470    * @param flags the bitwise OR of one or more of
    471    * {@link TJ#FLAG_BOTTOMUP TJ.FLAG_*}
    472    *
    473    * @return a YUV planar image.
    474    */
    475   public YUVImage encodeYUV(int pad, int flags) throws TJException {
    476     checkSourceImage();
    477     checkSubsampling();
    478     if(pad < 1 || ((pad & (pad - 1)) != 0))
    479       throw new IllegalStateException("Invalid argument in encodeYUV()");
    480     YUVImage yuvImage = new YUVImage(srcWidth, pad, srcHeight, subsamp);
    481     encodeYUV(yuvImage, flags);
    482     return yuvImage;
    483   }
    484 
    485   /**
    486    * Encode the uncompressed source image associated with this compressor
    487    * instance into separate Y, U (Cb), and V (Cr) image planes and return a
    488    * <code>YUVImage</code> instance containing the encoded image planes.  This
    489    * method uses the accelerated color conversion routines in TurboJPEG's
    490    * underlying codec but does not execute any of the other steps in the JPEG
    491    * compression process.  Encoding CMYK source images to YUV is not supported.
    492    *
    493    * @param strides an array of integers, each specifying the number of bytes
    494    * per line in the corresponding plane of the output image.  Setting the
    495    * stride for any plane to 0 is the same as setting it to the component width
    496    * of the plane.  If <code>strides</code> is null, then the strides for all
    497    * planes will be set to their respective component widths.  You can adjust
    498    * the strides in order to add an arbitrary amount of line padding to each
    499    * plane.
    500    *
    501    * @param flags the bitwise OR of one or more of
    502    * {@link TJ#FLAG_BOTTOMUP TJ.FLAG_*}
    503    *
    504    * @return a YUV planar image.
    505    */
    506   public YUVImage encodeYUV(int[] strides, int flags) throws TJException {
    507     checkSourceImage();
    508     checkSubsampling();
    509     YUVImage yuvImage = new YUVImage(srcWidth, strides, srcHeight, subsamp);
    510     encodeYUV(yuvImage, flags);
    511     return yuvImage;
    512   }
    513 
    514   /**
    515    * @deprecated Use {@link #encodeYUV(int, int)} instead.
    516    */
    517   @Deprecated
    518   public byte[] encodeYUV(int flags) throws TJException {
    519     checkSourceImage();
    520     checkSubsampling();
    521     YUVImage yuvImage = new YUVImage(srcWidth, 4, srcHeight, subsamp);
    522     encodeYUV(yuvImage, flags);
    523     return yuvImage.getBuf();
    524   }
    525 
    526   /**
    527    * @deprecated Use
    528    * {@link #setSourceImage(BufferedImage, int, int, int, int)} and
    529    * {@link #encodeYUV(byte[], int)} instead.
    530    */
    531   @Deprecated
    532   public void encodeYUV(BufferedImage srcImage, byte[] dstBuf, int flags)
    533                         throws TJException {
    534     setSourceImage(srcImage, 0, 0, 0, 0);
    535     encodeYUV(dstBuf, flags);
    536   }
    537 
    538   /**
    539    * @deprecated Use
    540    * {@link #setSourceImage(BufferedImage, int, int, int, int)} and
    541    * {@link #encodeYUV(int, int)} instead.
    542    */
    543   @Deprecated
    544   public byte[] encodeYUV(BufferedImage srcImage, int flags)
    545                           throws TJException {
    546     setSourceImage(srcImage, 0, 0, 0, 0);
    547     return encodeYUV(flags);
    548   }
    549 
    550   /**
    551    * Returns the size of the image (in bytes) generated by the most recent
    552    * compress operation.
    553    *
    554    * @return the size of the image (in bytes) generated by the most recent
    555    * compress operation.
    556    */
    557   public int getCompressedSize() {
    558     return compressedSize;
    559   }
    560 
    561   /**
    562    * Free the native structures associated with this compressor instance.
    563    */
    564   @Override
    565   public void close() throws TJException {
    566     if (handle != 0)
    567       destroy();
    568   }
    569 
    570   @Override
    571   protected void finalize() throws Throwable {
    572     try {
    573       close();
    574     } catch(TJException e) {
    575     } finally {
    576       super.finalize();
    577     }
    578   };
    579 
    580   private native void init() throws TJException;
    581 
    582   private native void destroy() throws TJException;
    583 
    584   // JPEG size in bytes is returned
    585   @Deprecated
    586   private native int compress(byte[] srcBuf, int width, int pitch,
    587     int height, int pixelFormat, byte[] dstBuf, int jpegSubsamp, int jpegQual,
    588     int flags) throws TJException;
    589 
    590   private native int compress(byte[] srcBuf, int x, int y, int width,
    591     int pitch, int height, int pixelFormat, byte[] dstBuf, int jpegSubsamp,
    592     int jpegQual, int flags) throws TJException;
    593 
    594   @Deprecated
    595   private native int compress(int[] srcBuf, int width, int stride,
    596     int height, int pixelFormat, byte[] dstBuf, int jpegSubsamp, int jpegQual,
    597     int flags) throws TJException;
    598 
    599   private native int compress(int[] srcBuf, int x, int y, int width,
    600     int stride, int height, int pixelFormat, byte[] dstBuf, int jpegSubsamp,
    601     int jpegQual, int flags) throws TJException;
    602 
    603   private native int compressFromYUV(byte[][] srcPlanes, int[] srcOffsets,
    604     int width, int[] srcStrides, int height, int subsamp, byte[] dstBuf,
    605     int jpegQual, int flags)
    606     throws TJException;
    607 
    608   @Deprecated
    609   private native void encodeYUV(byte[] srcBuf, int width, int pitch,
    610     int height, int pixelFormat, byte[] dstBuf, int subsamp, int flags)
    611     throws TJException;
    612 
    613   private native void encodeYUV(byte[] srcBuf, int x, int y, int width,
    614     int pitch, int height, int pixelFormat, byte[][] dstPlanes,
    615     int[] dstOffsets, int[] dstStrides, int subsamp, int flags)
    616     throws TJException;
    617 
    618   @Deprecated
    619   private native void encodeYUV(int[] srcBuf, int width, int stride,
    620     int height, int pixelFormat, byte[] dstBuf, int subsamp, int flags)
    621     throws TJException;
    622 
    623   private native void encodeYUV(int[] srcBuf, int x, int y, int width,
    624     int srcStride, int height, int pixelFormat, byte[][] dstPlanes,
    625     int[] dstOffsets, int[] dstStrides, int subsamp, int flags)
    626     throws TJException;
    627 
    628   static {
    629     TJLoader.load();
    630   }
    631 
    632   private void checkSourceImage() {
    633     if (srcWidth < 1 || srcHeight < 1)
    634       throw new IllegalStateException(NO_ASSOC_ERROR);
    635   }
    636 
    637   private void checkSubsampling() {
    638     if (subsamp < 0)
    639       throw new IllegalStateException("Subsampling level not set");
    640   }
    641 
    642   private long handle = 0;
    643   private byte[] srcBuf = null;
    644   private int[] srcBufInt = null;
    645   private int srcWidth = 0;
    646   private int srcHeight = 0;
    647   private int srcX = -1;
    648   private int srcY = -1;
    649   private int srcPitch = 0;
    650   private int srcStride = 0;
    651   private int srcPixelFormat = -1;
    652   private YUVImage srcYUVImage = null;
    653   private int subsamp = -1;
    654   private int jpegQuality = -1;
    655   private int compressedSize = 0;
    656   private int yuvPad = 4;
    657   private ByteOrder byteOrder = null;
    658 }
    659