OLD | NEW |
(Empty) | |
| 1 /* |
| 2 * Copyright (C)2011-2015 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 */ |
| 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 a
nd 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 } |
OLD | NEW |