java/org/libjpegturbo/turbojpeg/TJCompressor.java (375 lines of code) (raw):

/* * Copyright (C)2011-2015, 2018, 2020, 2022-2024 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 compressor */ public class TJCompressor implements Closeable { /** * Create a TurboJPEG compressor instance. */ public TJCompressor() throws TJException { init(); } /** * Create a TurboJPEG compressor instance and associate the 8-bit-per-sample * packed-pixel source image stored in <code>srcImage</code> with the newly * created instance. * * @param srcImage see {@link #setSourceImage} for description * * @param x see {@link #setSourceImage} for description * * @param y see {@link #setSourceImage} for description * * @param width see {@link #setSourceImage} for description * * @param pitch see {@link #setSourceImage} for description * * @param height see {@link #setSourceImage} for description * * @param pixelFormat pixel format of the source image (one of * {@link TJ#PF_RGB TJ.PF_*}) */ public TJCompressor(byte[] srcImage, int x, int y, int width, int pitch, int height, int pixelFormat) throws TJException { setSourceImage(srcImage, x, y, width, pitch, height, pixelFormat); } /** * Create a TurboJPEG compressor instance and associate the 8-bit-per-sample * packed-pixel source image stored in <code>srcImage</code> with the newly * created instance. * * @param srcImage see * {@link #setSourceImage(BufferedImage, int, int, int, int)} for description * * @param x see * {@link #setSourceImage(BufferedImage, int, int, int, int)} for description * * @param y see * {@link #setSourceImage(BufferedImage, int, int, int, int)} for description * * @param width see * {@link #setSourceImage(BufferedImage, int, int, int, int)} for description * * @param height see * {@link #setSourceImage(BufferedImage, int, int, int, int)} for description */ public TJCompressor(BufferedImage srcImage, int x, int y, int width, int height) throws TJException { setSourceImage(srcImage, x, y, width, height); } /** * Associate an 8-bit-per-sample packed-pixel RGB, grayscale, or CMYK source * image with this compressor instance. * * @param srcImage buffer containing a packed-pixel RGB, grayscale, or CMYK * source image to be compressed or encoded. This buffer is not modified. * * @param x x offset (in pixels) of the region in the source image from which * the JPEG or YUV image should be compressed/encoded * * @param y y offset (in pixels) of the region in the source image from which * the JPEG or YUV image should be compressed/encoded * * @param width width (in pixels) of the region in the source image from * which the JPEG or YUV image should be compressed/encoded * * @param pitch bytes per row in the source image. Normally this should be * <code>width * {@link TJ#getPixelSize TJ.getPixelSize}(pixelFormat)</code>, * if the source image is unpadded. (Setting this parameter to 0 is the * equivalent of setting it to <code>width * * {@link TJ#getPixelSize TJ.getPixelSize}(pixelFormat)</code>.) However, * you can also use this parameter to specify the row alignment/padding of * the source image, to skip rows, or to compress/encode a JPEG or YUV image * from a specific region of a larger source image. * * @param height height (in pixels) of the region in the source image from * which the JPEG or YUV image should be compressed/encoded * * @param pixelFormat pixel format of the source image (one of * {@link TJ#PF_RGB TJ.PF_*}) */ public void setSourceImage(byte[] srcImage, int x, int y, int width, int pitch, int height, int pixelFormat) throws TJException { if (handle == 0) init(); if (srcImage == null || x < 0 || y < 0 || width < 1 || height < 1 || pitch < 0 || pixelFormat < 0 || pixelFormat >= TJ.NUMPF) throw new IllegalArgumentException("Invalid argument in setSourceImage()"); srcBuf8 = srcImage; srcWidth = width; if (pitch == 0) srcPitch = width * TJ.getPixelSize(pixelFormat); else srcPitch = pitch; srcHeight = height; srcPixelFormat = pixelFormat; srcX = x; srcY = y; srcBuf12 = null; srcBuf16 = null; srcBufInt = null; srcYUVImage = null; } /** * Associate a 12-bit-per-sample packed-pixel RGB, grayscale, or CMYK source * image with this compressor instance. Note that 12-bit-per-sample * packed-pixel source images can only be compressed into 12-bit-per-sample * JPEG images. * * @param srcImage buffer containing a packed-pixel RGB, grayscale, or CMYK * source image to be compressed. This buffer is not modified. * * @param x x offset (in pixels) of the region in the source image from which * the JPEG image should be compressed * * @param y y offset (in pixels) of the region in the source image from which * the JPEG image should be compressed * * @param width width (in pixels) of the region in the source image from * which the JPEG image should be compressed * * @param pitch samples per row in the source image. Normally this should be * <code>width * {@link TJ#getPixelSize TJ.getPixelSize}(pixelFormat)</code>, * if the source image is unpadded. (Setting this parameter to 0 is the * equivalent of setting it to <code>width * * {@link TJ#getPixelSize TJ.getPixelSize}(pixelFormat)</code>.) However, * you can also use this parameter to specify the row alignment/padding of * the source image, to skip rows, or to compress a JPEG image from a * specific region of a larger source image. * * @param height height (in pixels) of the region in the source image from * which the JPEG image should be compressed * * @param pixelFormat pixel format of the source image (one of * {@link TJ#PF_RGB TJ.PF_*}) */ public void setSourceImage12(short[] srcImage, int x, int y, int width, int pitch, int height, int pixelFormat) throws TJException { if (handle == 0) init(); if (srcImage == null || x < 0 || y < 0 || width < 1 || height < 1 || pitch < 0 || pixelFormat < 0 || pixelFormat >= TJ.NUMPF) throw new IllegalArgumentException("Invalid argument in setSourceImage()"); srcBuf12 = srcImage; srcWidth = width; if (pitch == 0) srcPitch = width * TJ.getPixelSize(pixelFormat); else srcPitch = pitch; srcHeight = height; srcPixelFormat = pixelFormat; srcX = x; srcY = y; srcBuf8 = null; srcBuf16 = null; srcBufInt = null; srcYUVImage = null; } /** * Associate a 16-bit-per-sample packed-pixel RGB, grayscale, or CMYK source * image with this compressor instance. Note that 16-bit-per-sample * packed-pixel source images can only be compressed into 16-bit-per-sample * lossless JPEG images. * * @param srcImage buffer containing a packed-pixel RGB, grayscale, or CMYK * source image to be compressed. This buffer is not modified. * * @param x x offset (in pixels) of the region in the source image from which * the JPEG image should be compressed * * @param y y offset (in pixels) of the region in the source image from which * the JPEG image should be compressed * * @param width width (in pixels) of the region in the source image from * which the JPEG image should be compressed * * @param pitch samples per row in the source image. Normally this should be * <code>width * {@link TJ#getPixelSize TJ.getPixelSize}(pixelFormat)</code>, * if the source image is unpadded. (Setting this parameter to 0 is the * equivalent of setting it to <code>width * * {@link TJ#getPixelSize TJ.getPixelSize}(pixelFormat)</code>.) However, * you can also use this parameter to specify the row alignment/padding of * the source image, to skip rows, or to compress a JPEG image from a * specific region of a larger source image. * * @param height height (in pixels) of the region in the source image from * which the JPEG image should be compressed * * @param pixelFormat pixel format of the source image (one of * {@link TJ#PF_RGB TJ.PF_*}) */ public void setSourceImage16(short[] srcImage, int x, int y, int width, int pitch, int height, int pixelFormat) throws TJException { if (handle == 0) init(); if (srcImage == null || x < 0 || y < 0 || width < 1 || height < 1 || pitch < 0 || pixelFormat < 0 || pixelFormat >= TJ.NUMPF) throw new IllegalArgumentException("Invalid argument in setSourceImage()"); srcBuf16 = srcImage; srcWidth = width; if (pitch == 0) srcPitch = width * TJ.getPixelSize(pixelFormat); else srcPitch = pitch; srcHeight = height; srcPixelFormat = pixelFormat; srcX = x; srcY = y; srcBuf8 = null; srcBuf12 = null; srcBufInt = null; srcYUVImage = null; } /** * Associate an 8-bit-per-sample packed-pixel RGB or grayscale source image * with this compressor instance. * * @param srcImage a <code>BufferedImage</code> instance containing a * packed-pixel RGB or grayscale source image to be compressed or encoded. * This image is not modified. * * @param x x offset (in pixels) of the region in the source image from which * the JPEG or YUV image should be compressed/encoded * * @param y y offset (in pixels) of the region in the source image from which * the JPEG or YUV image should be compressed/encoded * * @param width width (in pixels) of the region in the source image from * which the JPEG or YUV image should be compressed/encoded (0 = use the * width of the source image) * * @param height height (in pixels) of the region in the source image from * which the JPEG or YUV image should be compressed/encoded (0 = use the * height of the source image) */ public void setSourceImage(BufferedImage srcImage, int x, int y, int width, int height) throws TJException { if (handle == 0) init(); if (srcImage == null || x < 0 || y < 0 || width < 0 || height < 0) throw new IllegalArgumentException("Invalid argument in setSourceImage()"); srcX = x; srcY = y; srcWidth = (width == 0) ? srcImage.getWidth() : width; srcHeight = (height == 0) ? srcImage.getHeight() : height; if (x + width > srcImage.getWidth() || y + height > srcImage.getHeight()) throw new IllegalArgumentException("Compression region exceeds the bounds of the source image"); int pixelFormat; boolean intPixels = false; if (byteOrder == null) byteOrder = ByteOrder.nativeOrder(); switch (srcImage.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: case BufferedImage.TYPE_INT_ARGB: case BufferedImage.TYPE_INT_ARGB_PRE: if (byteOrder == ByteOrder.BIG_ENDIAN) pixelFormat = TJ.PF_XRGB; else pixelFormat = TJ.PF_BGRX; intPixels = true; break; default: throw new IllegalArgumentException("Unsupported BufferedImage format"); } srcPixelFormat = pixelFormat; WritableRaster wr = srcImage.getRaster(); if (intPixels) { SinglePixelPackedSampleModel sm = (SinglePixelPackedSampleModel)srcImage.getSampleModel(); srcStride = sm.getScanlineStride(); DataBufferInt db = (DataBufferInt)wr.getDataBuffer(); srcBufInt = db.getData(); srcBuf8 = null; srcBuf12 = null; srcBuf16 = null; } else { ComponentSampleModel sm = (ComponentSampleModel)srcImage.getSampleModel(); int pixelSize = sm.getPixelStride(); if (pixelSize != TJ.getPixelSize(pixelFormat)) throw new IllegalArgumentException("Inconsistency between pixel format and pixel size in BufferedImage"); srcPitch = sm.getScanlineStride(); DataBufferByte db = (DataBufferByte)wr.getDataBuffer(); srcBuf8 = db.getData(); srcBuf12 = null; srcBuf16 = null; srcBufInt = null; } srcYUVImage = null; } /** * Associate an 8-bit-per-sample planar YUV source image with this compressor * instance. This method sets {@link TJ#PARAM_SUBSAMP} to the chrominance * subsampling level of the source image. * * @param srcImage planar YUV source image to be compressed. This image is * not modified. */ public void setSourceImage(YUVImage srcImage) throws TJException { if (handle == 0) init(); if (srcImage == null) throw new IllegalArgumentException("Invalid argument in setSourceImage()"); srcYUVImage = srcImage; set(TJ.PARAM_SUBSAMP, srcImage.getSubsamp()); srcBuf8 = null; srcBuf12 = null; srcBuf16 = null; srcBufInt = null; } /** * Set the value of a compression parameter. * * @param param one of {@link TJ#PARAM_STOPONWARNING TJ.PARAM_*} * * @param value value of the compression parameter (refer to * {@link TJ#PARAM_STOPONWARNING parameter documentation}) */ public native void set(int param, int value); /** * Get the value of a compression parameter. * * @param param one of {@link TJ#PARAM_STOPONWARNING TJ.PARAM_*} * * @return the value of the specified compression parameter, or -1 if the * value is unknown. */ public native int get(int param); /** * @deprecated Use * <code>{@link #set set}({@link TJ#PARAM_SUBSAMP}, ...)</code> instead. */ @SuppressWarnings("checkstyle:JavadocMethod") @Deprecated public void setSubsamp(int subsamp) { if (subsamp < 0 || subsamp >= TJ.NUMSAMP) throw new IllegalArgumentException("Invalid argument in setSubsamp()"); set(TJ.PARAM_SUBSAMP, subsamp); } /** * @deprecated Use * <code>{@link #set set}({@link TJ#PARAM_QUALITY}, ...)</code> instead. */ @SuppressWarnings("checkstyle:JavadocMethod") @Deprecated public void setJPEGQuality(int quality) { if (quality < 1 || quality > 100) throw new IllegalArgumentException("Invalid argument in setJPEGQuality()"); set(TJ.PARAM_QUALITY, quality); } /** * Compress the packed-pixel or planar YUV source image associated with this * compressor instance and output a JPEG image to the given destination * buffer. * * @param dstBuf buffer that will receive the JPEG image. Use * {@link TJ#bufSize TJ.bufSize()} to determine the maximum size for this * buffer based on the source image's width and height and the desired level * of chrominance subsampling (see {@link TJ#PARAM_SUBSAMP}.) */ public void compress(byte[] dstBuf) throws TJException { if (dstBuf == null) throw new IllegalArgumentException("Invalid argument in compress()"); if (srcYUVImage != null) { checkSubsampling(); if (get(TJ.PARAM_SUBSAMP) != srcYUVImage.getSubsamp()) throw new IllegalStateException("TJ.PARAM_SUBSAMP must match subsampling level of YUV image"); compressedSize = compressFromYUV8(srcYUVImage.getPlanes(), srcYUVImage.getOffsets(), srcYUVImage.getWidth(), srcYUVImage.getStrides(), srcYUVImage.getHeight(), dstBuf); } else if (srcBuf8 != null) compressedSize = compress8(srcBuf8, srcX, srcY, srcWidth, srcPitch, srcHeight, srcPixelFormat, dstBuf); else if (srcBuf12 != null) compressedSize = compress12(srcBuf12, srcX, srcY, srcWidth, srcPitch, srcHeight, srcPixelFormat, dstBuf); else if (srcBuf16 != null) compressedSize = compress16(srcBuf16, srcX, srcY, srcWidth, srcPitch, srcHeight, srcPixelFormat, dstBuf); else if (srcBufInt != null) compressedSize = compress8(srcBufInt, srcX, srcY, srcWidth, srcStride, srcHeight, srcPixelFormat, dstBuf); else throw new IllegalStateException("No source image is associated with this instance"); } /** * @deprecated Use {@link #set set()} and {@link #compress(byte[])} instead. */ @SuppressWarnings("checkstyle:JavadocMethod") @Deprecated public void compress(byte[] dstBuf, int flags) throws TJException { if (flags < 0) throw new IllegalArgumentException("Invalid argument in compress()"); processFlags(flags); compress(dstBuf); } /** * Compress the packed-pixel or planar YUV source image associated with this * compressor instance and return a buffer containing a JPEG image. * * @return a buffer containing a JPEG image. The length of this buffer will * not be equal to the size of the JPEG image. Use * {@link #getCompressedSize} to obtain the size of the JPEG image. */ public byte[] compress() throws TJException { byte[] buf; if (srcYUVImage != null) { buf = new byte[TJ.bufSize(srcYUVImage.getWidth(), srcYUVImage.getHeight(), srcYUVImage.getSubsamp())]; } else { checkSubsampling(); int subsamp = get(TJ.PARAM_SUBSAMP); if (get(TJ.PARAM_LOSSLESS) == 1 && subsamp != TJ.SAMP_GRAY) subsamp = TJ.SAMP_444; buf = new byte[TJ.bufSize(srcWidth, srcHeight, subsamp)]; } compress(buf); return buf; } /** * @deprecated Use {@link #set set()} and {@link #compress()} instead. */ @SuppressWarnings("checkstyle:JavadocMethod") @Deprecated public byte[] compress(int flags) throws TJException { processFlags(flags); return compress(); } /** * Encode the 8-bit-per-sample packed-pixel source image associated with this * compressor instance into an 8-bit-per-sample planar YUV image and store it * in the given {@link YUVImage} instance. This method performs color * conversion (which is accelerated in the libjpeg-turbo implementation) but * does not execute any of the other steps in the JPEG compression process. * Encoding CMYK source images into YUV images is not supported. This method * sets {@link TJ#PARAM_SUBSAMP} to the chrominance subsampling level of the * destination image. * * @param dstImage {@link YUVImage} instance that will receive the planar YUV * image */ public void encodeYUV(YUVImage dstImage) throws TJException { if (dstImage == null) throw new IllegalArgumentException("Invalid argument in encodeYUV()"); if (srcBuf8 == null && srcBufInt == null) throw new IllegalStateException("No 8-bit-per-sample source image is associated with this instance"); if (srcYUVImage != null) throw new IllegalStateException("Source image is not correct type"); if (srcWidth != dstImage.getWidth() || srcHeight != dstImage.getHeight()) throw new IllegalStateException("Destination image is the wrong size"); set(TJ.PARAM_SUBSAMP, dstImage.getSubsamp()); if (srcBufInt != null) { encodeYUV8(srcBufInt, srcX, srcY, srcWidth, srcStride, srcHeight, srcPixelFormat, dstImage.getPlanes(), dstImage.getOffsets(), dstImage.getStrides()); } else { encodeYUV8(srcBuf8, srcX, srcY, srcWidth, srcPitch, srcHeight, srcPixelFormat, dstImage.getPlanes(), dstImage.getOffsets(), dstImage.getStrides()); } compressedSize = 0; } /** * @deprecated Use {@link #set set()} and {@link #encodeYUV(YUVImage)} * instead. */ @SuppressWarnings("checkstyle:JavadocMethod") @Deprecated public void encodeYUV(YUVImage dstImage, int flags) throws TJException { if (flags < 0) throw new IllegalArgumentException("Invalid argument in encodeYUV()"); processFlags(flags); encodeYUV(dstImage); } /** * Encode the 8-bit-per-sample packed-pixel source image associated with this * compressor instance into an 8-bit-per-sample unified planar YUV image and * return a {@link YUVImage} instance containing the encoded image. This * method performs color conversion (which is accelerated in the * libjpeg-turbo implementation) but does not execute any of the other steps * in the JPEG compression process. Encoding CMYK source images into YUV * images is not supported. * * @param align row alignment (in bytes) of the YUV image (must be a power of * 2.) Setting this parameter to n will cause each row in each plane of the * YUV image to be padded to the nearest multiple of n bytes (1 = unpadded.) * * @return a {@link YUVImage} instance containing the unified planar YUV * encoded image */ public YUVImage encodeYUV(int align) throws TJException { if (srcBuf8 == null && srcBufInt == null) throw new IllegalStateException("No 8-bit-per-sample source image is associated with this instance"); checkSubsampling(); if (align < 1 || ((align & (align - 1)) != 0)) throw new IllegalStateException("Invalid argument in encodeYUV()"); YUVImage dstYUVImage = new YUVImage(srcWidth, align, srcHeight, get(TJ.PARAM_SUBSAMP)); encodeYUV(dstYUVImage); return dstYUVImage; } /** * @deprecated Use {@link #set set()} and {@link #encodeYUV(int)} instead. */ @SuppressWarnings("checkstyle:JavadocMethod") @Deprecated public YUVImage encodeYUV(int align, int flags) throws TJException { processFlags(flags); return encodeYUV(align); } /** * Encode the 8-bit-per-sample packed-pixel source image associated with this * compressor instance into separate 8-bit-per-sample Y, U (Cb), and V (Cr) * image planes and return a {@link YUVImage} instance containing the encoded * image planes. This method performs color conversion (which is accelerated * in the libjpeg-turbo implementation) but does not execute any of the other * steps in the JPEG compression process. Encoding CMYK source images into * YUV images is not supported. * * @param strides an array of integers, each specifying the number of bytes * per row in the corresponding plane of the YUV source image. Setting the * stride for any plane to 0 is the same as setting it to the plane width * (see {@link YUVImage}.) If <code>strides</code> is null, then the strides * for all planes will be set to their respective plane widths. You can * adjust the strides in order to add an arbitrary amount of row padding to * each plane. * * @return a {@link YUVImage} instance containing the encoded image planes */ public YUVImage encodeYUV(int[] strides) throws TJException { if (srcBuf8 == null && srcBufInt == null) throw new IllegalStateException("No 8-bit-per-sample source image is associated with this instance"); checkSubsampling(); YUVImage dstYUVImage = new YUVImage(srcWidth, strides, srcHeight, get(TJ.PARAM_SUBSAMP)); encodeYUV(dstYUVImage); return dstYUVImage; } /** * @deprecated Use {@link #set set()} and {@link #encodeYUV(int[])} instead. */ @SuppressWarnings("checkstyle:JavadocMethod") @Deprecated public YUVImage encodeYUV(int[] strides, int flags) throws TJException { processFlags(flags); return encodeYUV(strides); } /** * Returns the size of the image (in bytes) generated by the most recent * compression operation. * * @return the size of the image (in bytes) generated by the most recent * compression operation. */ public int getCompressedSize() { return compressedSize; } /** * Free the native structures associated with this compressor instance. */ @Override public void close() throws TJException { if (handle != 0) destroy(); } @SuppressWarnings("checkstyle:DesignForExtension") @Override protected void finalize() throws Throwable { try { close(); } catch (TJException e) { } finally { super.finalize(); } }; @SuppressWarnings("deprecation") private void processFlags(int flags) { set(TJ.PARAM_BOTTOMUP, (flags & TJ.FLAG_BOTTOMUP) != 0 ? 1 : 0); if (get(TJ.PARAM_QUALITY) >= 96 || (flags & TJ.FLAG_ACCURATEDCT) != 0) set(TJ.PARAM_FASTDCT, 0); else set(TJ.PARAM_FASTDCT, 1); set(TJ.PARAM_STOPONWARNING, (flags & TJ.FLAG_STOPONWARNING) != 0 ? 1 : 0); set(TJ.PARAM_PROGRESSIVE, (flags & TJ.FLAG_PROGRESSIVE) != 0 ? 1 : 0); } private void checkSubsampling() { if (get(TJ.PARAM_SUBSAMP) == TJ.SAMP_UNKNOWN) throw new IllegalStateException("TJ.PARAM_SUBSAMP must be specified"); } private native void init() throws TJException; private native void destroy() throws TJException; // JPEG size in bytes is returned @SuppressWarnings("checkstyle:HiddenField") private native int compress8(byte[] srcBuf, int x, int y, int width, int pitch, int height, int pixelFormat, byte[] jpegBuf) throws TJException; @SuppressWarnings("checkstyle:HiddenField") private native int compress12(short[] srcBuf, int x, int y, int width, int pitch, int height, int pixelFormat, byte[] jpegBuf) throws TJException; @SuppressWarnings("checkstyle:HiddenField") private native int compress16(short[] srcBuf, int x, int y, int width, int pitch, int height, int pixelFormat, byte[] jpegBuf) throws TJException; @SuppressWarnings("checkstyle:HiddenField") private native int compress8(int[] srcBuf, int x, int y, int width, int stride, int height, int pixelFormat, byte[] jpegBuf) throws TJException; @SuppressWarnings("checkstyle:HiddenField") private native int compressFromYUV8(byte[][] srcPlanes, int[] srcOffsets, int width, int[] srcStrides, int height, byte[] jpegBuf) throws TJException; @SuppressWarnings("checkstyle:HiddenField") private native void encodeYUV8(byte[] srcBuf, int x, int y, int width, int pitch, int height, int pixelFormat, byte[][] dstPlanes, int[] dstOffsets, int[] dstStrides) throws TJException; @SuppressWarnings("checkstyle:HiddenField") private native void encodeYUV8(int[] srcBuf, int x, int y, int width, int srcStride, int height, int pixelFormat, byte[][] dstPlanes, int[] dstOffsets, int[] dstStrides) throws TJException; /** * @hidden * Ugly hack alert. It isn't straightforward to load 12-bit-per-sample and * 16-bit-per-sample images using the ImageIO and BufferedImage classes, and * ImageIO doesn't support PBMPLUS files anyhow. This method accesses * tj3LoadImage() through JNI and copies the pixel data between the C and * Java heaps. Currently it is undocumented and used only by TJBench. */ @SuppressWarnings("checkstyle:JavadocMethod") public native Object loadImage(int precision, String fileName, int[] width, int align, int[] height, int[] pixelFormat) throws TJException; static { TJLoader.load(); } private long handle = 0; private byte[] srcBuf8 = null; private short[] srcBuf12 = null; private short[] srcBuf16 = null; private int[] srcBufInt = null; private int srcWidth = 0; private int srcHeight = 0; private int srcX = -1; private int srcY = -1; private int srcPitch = 0; private int srcStride = 0; private int srcPixelFormat = -1; private YUVImage srcYUVImage = null; private int compressedSize = 0; private ByteOrder byteOrder = null; }