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