1 /* 2 * Copyright (C)2011-2015, 2018, 2020 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 byte[] buf; 381 if (srcYUVImage != null) { 382 buf = new byte[TJ.bufSize(srcYUVImage.getWidth(), 383 srcYUVImage.getHeight(), 384 srcYUVImage.getSubsamp())]; 385 } else { 386 checkSourceImage(); 387 buf = new byte[TJ.bufSize(srcWidth, srcHeight, subsamp)]; 388 } 389 compress(buf, flags); 390 return buf; 391 } 392 393 /** 394 * @deprecated Use 395 * {@link #setSourceImage(BufferedImage, int, int, int, int)} and 396 * {@link #compress(byte[], int)} instead. 397 */ 398 @SuppressWarnings("checkstyle:JavadocMethod") 399 @Deprecated compress(BufferedImage srcImage, byte[] dstBuf, int flags)400 public void compress(BufferedImage srcImage, byte[] dstBuf, int flags) 401 throws TJException { 402 setSourceImage(srcImage, 0, 0, 0, 0); 403 compress(dstBuf, flags); 404 } 405 406 /** 407 * @deprecated Use 408 * {@link #setSourceImage(BufferedImage, int, int, int, int)} and 409 * {@link #compress(int)} instead. 410 */ 411 @SuppressWarnings("checkstyle:JavadocMethod") 412 @Deprecated compress(BufferedImage srcImage, int flags)413 public byte[] compress(BufferedImage srcImage, int flags) 414 throws TJException { 415 setSourceImage(srcImage, 0, 0, 0, 0); 416 return compress(flags); 417 } 418 419 /** 420 * Encode the uncompressed source image associated with this compressor 421 * instance into a YUV planar image and store it in the given 422 * <code>YUVImage</code> instance. This method uses the accelerated color 423 * conversion routines in TurboJPEG's underlying codec but does not execute 424 * any of the other steps in the JPEG compression process. Encoding 425 * CMYK source images to YUV is not supported. 426 * 427 * @param dstImage {@link YUVImage} instance that will receive the YUV planar 428 * image 429 * 430 * @param flags the bitwise OR of one or more of 431 * {@link TJ#FLAG_BOTTOMUP TJ.FLAG_*} 432 */ encodeYUV(YUVImage dstImage, int flags)433 public void encodeYUV(YUVImage dstImage, int flags) throws TJException { 434 if (dstImage == null || flags < 0) 435 throw new IllegalArgumentException("Invalid argument in encodeYUV()"); 436 if (srcBuf == null && srcBufInt == null) 437 throw new IllegalStateException(NO_ASSOC_ERROR); 438 if (srcYUVImage != null) 439 throw new IllegalStateException("Source image is not correct type"); 440 checkSubsampling(); 441 if (srcWidth != dstImage.getWidth() || srcHeight != dstImage.getHeight()) 442 throw new IllegalStateException("Destination image is the wrong size"); 443 444 if (srcBufInt != null) { 445 encodeYUV(srcBufInt, srcX, srcY, srcWidth, srcStride, srcHeight, 446 srcPixelFormat, dstImage.getPlanes(), dstImage.getOffsets(), 447 dstImage.getStrides(), dstImage.getSubsamp(), flags); 448 } else { 449 encodeYUV(srcBuf, srcX, srcY, srcWidth, srcPitch, srcHeight, 450 srcPixelFormat, dstImage.getPlanes(), dstImage.getOffsets(), 451 dstImage.getStrides(), dstImage.getSubsamp(), flags); 452 } 453 compressedSize = 0; 454 } 455 456 /** 457 * @deprecated Use {@link #encodeYUV(YUVImage, int)} instead. 458 */ 459 @SuppressWarnings("checkstyle:JavadocMethod") 460 @Deprecated encodeYUV(byte[] dstBuf, int flags)461 public void encodeYUV(byte[] dstBuf, int flags) throws TJException { 462 if (dstBuf == null) 463 throw new IllegalArgumentException("Invalid argument in encodeYUV()"); 464 checkSourceImage(); 465 checkSubsampling(); 466 YUVImage dstYUVImage = new YUVImage(dstBuf, srcWidth, 4, srcHeight, 467 subsamp); 468 encodeYUV(dstYUVImage, flags); 469 } 470 471 /** 472 * Encode the uncompressed source image associated with this compressor 473 * instance into a unified YUV planar image buffer and return a 474 * <code>YUVImage</code> instance containing the encoded image. This method 475 * uses the accelerated color conversion routines in TurboJPEG's underlying 476 * codec but does not execute any of the other steps in the JPEG compression 477 * process. Encoding CMYK source images to YUV is not supported. 478 * 479 * @param pad the width of each line in each plane of the YUV image will be 480 * padded to the nearest multiple of this number of bytes (must be a power of 481 * 2.) 482 * 483 * @param flags the bitwise OR of one or more of 484 * {@link TJ#FLAG_BOTTOMUP TJ.FLAG_*} 485 * 486 * @return a YUV planar image. 487 */ encodeYUV(int pad, int flags)488 public YUVImage encodeYUV(int pad, int flags) throws TJException { 489 checkSourceImage(); 490 checkSubsampling(); 491 if (pad < 1 || ((pad & (pad - 1)) != 0)) 492 throw new IllegalStateException("Invalid argument in encodeYUV()"); 493 YUVImage dstYUVImage = new YUVImage(srcWidth, pad, srcHeight, subsamp); 494 encodeYUV(dstYUVImage, flags); 495 return dstYUVImage; 496 } 497 498 /** 499 * Encode the uncompressed source image associated with this compressor 500 * instance into separate Y, U (Cb), and V (Cr) image planes and return a 501 * <code>YUVImage</code> instance containing the encoded image planes. This 502 * method uses the accelerated color conversion routines in TurboJPEG's 503 * underlying codec but does not execute any of the other steps in the JPEG 504 * compression process. Encoding CMYK source images to YUV is not supported. 505 * 506 * @param strides an array of integers, each specifying the number of bytes 507 * per line in the corresponding plane of the output image. Setting the 508 * stride for any plane to 0 is the same as setting it to the component width 509 * of the plane. If <code>strides</code> is null, then the strides for all 510 * planes will be set to their respective component widths. You can adjust 511 * the strides in order to add an arbitrary amount of line padding to each 512 * plane. 513 * 514 * @param flags the bitwise OR of one or more of 515 * {@link TJ#FLAG_BOTTOMUP TJ.FLAG_*} 516 * 517 * @return a YUV planar image. 518 */ encodeYUV(int[] strides, int flags)519 public YUVImage encodeYUV(int[] strides, int flags) throws TJException { 520 checkSourceImage(); 521 checkSubsampling(); 522 YUVImage dstYUVImage = new YUVImage(srcWidth, strides, srcHeight, subsamp); 523 encodeYUV(dstYUVImage, flags); 524 return dstYUVImage; 525 } 526 527 /** 528 * @deprecated Use {@link #encodeYUV(int, int)} instead. 529 */ 530 @SuppressWarnings("checkstyle:JavadocMethod") 531 @Deprecated encodeYUV(int flags)532 public byte[] encodeYUV(int flags) throws TJException { 533 checkSourceImage(); 534 checkSubsampling(); 535 YUVImage dstYUVImage = new YUVImage(srcWidth, 4, srcHeight, subsamp); 536 encodeYUV(dstYUVImage, flags); 537 return dstYUVImage.getBuf(); 538 } 539 540 /** 541 * @deprecated Use 542 * {@link #setSourceImage(BufferedImage, int, int, int, int)} and 543 * {@link #encodeYUV(byte[], int)} instead. 544 */ 545 @SuppressWarnings("checkstyle:JavadocMethod") 546 @Deprecated encodeYUV(BufferedImage srcImage, byte[] dstBuf, int flags)547 public void encodeYUV(BufferedImage srcImage, byte[] dstBuf, int flags) 548 throws TJException { 549 setSourceImage(srcImage, 0, 0, 0, 0); 550 encodeYUV(dstBuf, flags); 551 } 552 553 /** 554 * @deprecated Use 555 * {@link #setSourceImage(BufferedImage, int, int, int, int)} and 556 * {@link #encodeYUV(int, int)} instead. 557 */ 558 @SuppressWarnings("checkstyle:JavadocMethod") 559 @Deprecated encodeYUV(BufferedImage srcImage, int flags)560 public byte[] encodeYUV(BufferedImage srcImage, int flags) 561 throws TJException { 562 setSourceImage(srcImage, 0, 0, 0, 0); 563 return encodeYUV(flags); 564 } 565 566 /** 567 * Returns the size of the image (in bytes) generated by the most recent 568 * compress operation. 569 * 570 * @return the size of the image (in bytes) generated by the most recent 571 * compress operation. 572 */ getCompressedSize()573 public int getCompressedSize() { 574 return compressedSize; 575 } 576 577 /** 578 * Free the native structures associated with this compressor instance. 579 */ 580 @Override close()581 public void close() throws TJException { 582 if (handle != 0) 583 destroy(); 584 } 585 586 @SuppressWarnings("checkstyle:DesignForExtension") 587 @Override finalize()588 protected void finalize() throws Throwable { 589 try { 590 close(); 591 } catch (TJException e) { 592 } finally { 593 super.finalize(); 594 } 595 }; 596 init()597 private native void init() throws TJException; 598 destroy()599 private native void destroy() throws TJException; 600 601 // JPEG size in bytes is returned 602 @SuppressWarnings("checkstyle:HiddenField") 603 @Deprecated compress(byte[] srcBuf, int width, int pitch, int height, int pixelFormat, byte[] jpegBuf, int jpegSubsamp, int jpegQual, int flags)604 private native int compress(byte[] srcBuf, int width, int pitch, 605 int height, int pixelFormat, byte[] jpegBuf, int jpegSubsamp, int jpegQual, 606 int flags) throws TJException; 607 608 @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)609 private native int compress(byte[] srcBuf, int x, int y, int width, 610 int pitch, int height, int pixelFormat, byte[] jpegBuf, int jpegSubsamp, 611 int jpegQual, int flags) throws TJException; 612 613 @SuppressWarnings("checkstyle:HiddenField") 614 @Deprecated compress(int[] srcBuf, int width, int stride, int height, int pixelFormat, byte[] jpegBuf, int jpegSubsamp, int jpegQual, int flags)615 private native int compress(int[] srcBuf, int width, int stride, 616 int height, int pixelFormat, byte[] jpegBuf, int jpegSubsamp, int jpegQual, 617 int flags) throws TJException; 618 619 @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)620 private native int compress(int[] srcBuf, int x, int y, int width, 621 int stride, int height, int pixelFormat, byte[] jpegBuf, int jpegSubsamp, 622 int jpegQual, int flags) throws TJException; 623 624 @SuppressWarnings("checkstyle:HiddenField") compressFromYUV(byte[][] srcPlanes, int[] srcOffsets, int width, int[] srcStrides, int height, int subsamp, byte[] jpegBuf, int jpegQual, int flags)625 private native int compressFromYUV(byte[][] srcPlanes, int[] srcOffsets, 626 int width, int[] srcStrides, int height, int subsamp, byte[] jpegBuf, 627 int jpegQual, int flags) 628 throws TJException; 629 630 @SuppressWarnings("checkstyle:HiddenField") 631 @Deprecated encodeYUV(byte[] srcBuf, int width, int pitch, int height, int pixelFormat, byte[] dstBuf, int subsamp, int flags)632 private native void encodeYUV(byte[] srcBuf, int width, int pitch, 633 int height, int pixelFormat, byte[] dstBuf, int subsamp, int flags) 634 throws TJException; 635 636 @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)637 private native void encodeYUV(byte[] srcBuf, int x, int y, int width, 638 int pitch, int height, int pixelFormat, byte[][] dstPlanes, 639 int[] dstOffsets, int[] dstStrides, int subsamp, int flags) 640 throws TJException; 641 642 @SuppressWarnings("checkstyle:HiddenField") 643 @Deprecated encodeYUV(int[] srcBuf, int width, int stride, int height, int pixelFormat, byte[] dstBuf, int subsamp, int flags)644 private native void encodeYUV(int[] srcBuf, int width, int stride, 645 int height, int pixelFormat, byte[] dstBuf, int subsamp, int flags) 646 throws TJException; 647 648 @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)649 private native void encodeYUV(int[] srcBuf, int x, int y, int width, 650 int srcStride, int height, int pixelFormat, byte[][] dstPlanes, 651 int[] dstOffsets, int[] dstStrides, int subsamp, int flags) 652 throws TJException; 653 654 static { TJLoader.load()655 TJLoader.load(); 656 } 657 checkSourceImage()658 private void checkSourceImage() { 659 if (srcWidth < 1 || srcHeight < 1) 660 throw new IllegalStateException(NO_ASSOC_ERROR); 661 } 662 checkSubsampling()663 private void checkSubsampling() { 664 if (subsamp < 0) 665 throw new IllegalStateException("Subsampling level not set"); 666 } 667 668 private long handle = 0; 669 private byte[] srcBuf = null; 670 private int[] srcBufInt = null; 671 private int srcWidth = 0; 672 private int srcHeight = 0; 673 private int srcX = -1; 674 private int srcY = -1; 675 private int srcPitch = 0; 676 private int srcStride = 0; 677 private int srcPixelFormat = -1; 678 private YUVImage srcYUVImage = null; 679 private int subsamp = -1; 680 private int jpegQuality = -1; 681 private int compressedSize = 0; 682 private int yuvPad = 4; 683 private ByteOrder byteOrder = null; 684 } 685