Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(509)

Side by Side Diff: java/org/libjpegturbo/turbojpeg/TJDecompressor.java

Issue 1934113002: Update libjpeg_turbo to 1.4.90 from https://github.com/libjpeg-turbo/ (Closed) Base URL: https://chromium.googlesource.com/chromium/deps/libjpeg_turbo.git@master
Patch Set: Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(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 decompressor
38 */
39 public class TJDecompressor implements Closeable {
40
41 private static final String NO_ASSOC_ERROR =
42 "No JPEG image is associated with this instance";
43
44 /**
45 * Create a TurboJPEG decompresssor instance.
46 */
47 public TJDecompressor() throws TJException {
48 init();
49 }
50
51 /**
52 * Create a TurboJPEG decompressor instance and associate the JPEG source
53 * image stored in <code>jpegImage</code> with the newly created instance.
54 *
55 * @param jpegImage JPEG image buffer (size of the JPEG image is assumed to
56 * be the length of the array.) This buffer is not modified.
57 */
58 public TJDecompressor(byte[] jpegImage) throws TJException {
59 init();
60 setSourceImage(jpegImage, jpegImage.length);
61 }
62
63 /**
64 * Create a TurboJPEG decompressor instance and associate the JPEG source
65 * image of length <code>imageSize</code> bytes stored in
66 * <code>jpegImage</code> with the newly created instance.
67 *
68 * @param jpegImage JPEG image buffer. This buffer is not modified.
69 *
70 * @param imageSize size of the JPEG image (in bytes)
71 */
72 public TJDecompressor(byte[] jpegImage, int imageSize) throws TJException {
73 init();
74 setSourceImage(jpegImage, imageSize);
75 }
76
77 /**
78 * Create a TurboJPEG decompressor instance and associate the YUV planar
79 * source image stored in <code>yuvImage</code> with the newly created
80 * instance.
81 *
82 * @param yuvImage {@link YUVImage} instance containing a YUV planar
83 * image to be decoded. This image is not modified.
84 */
85 public TJDecompressor(YUVImage yuvImage) throws TJException {
86 init();
87 setSourceImage(yuvImage);
88 }
89
90 /**
91 * Associate the JPEG image of length <code>imageSize</code> bytes stored in
92 * <code>jpegImage</code> with this decompressor instance. This image will
93 * be used as the source image for subsequent decompress operations.
94 *
95 * @param jpegImage JPEG image buffer. This buffer is not modified.
96 *
97 * @param imageSize size of the JPEG image (in bytes)
98 */
99 public void setSourceImage(byte[] jpegImage, int imageSize)
100 throws TJException {
101 if (jpegImage == null || imageSize < 1)
102 throw new IllegalArgumentException("Invalid argument in setSourceImage()") ;
103 jpegBuf = jpegImage;
104 jpegBufSize = imageSize;
105 decompressHeader(jpegBuf, jpegBufSize);
106 yuvImage = null;
107 }
108
109 /**
110 * @deprecated Use {@link #setSourceImage(byte[], int)} instead.
111 */
112 @Deprecated
113 public void setJPEGImage(byte[] jpegImage, int imageSize)
114 throws TJException {
115 setSourceImage(jpegImage, imageSize);
116 }
117
118 /**
119 * Associate the specified YUV planar source image with this decompressor
120 * instance. Subsequent decompress operations will decode this image into an
121 * RGB or grayscale destination image.
122 *
123 * @param srcImage {@link YUVImage} instance containing a YUV planar image to
124 * be decoded. This image is not modified.
125 */
126 public void setSourceImage(YUVImage srcImage) {
127 if (srcImage == null)
128 throw new IllegalArgumentException("Invalid argument in setSourceImage()") ;
129 yuvImage = srcImage;
130 jpegBuf = null;
131 jpegBufSize = 0;
132 }
133
134
135 /**
136 * Returns the width of the source image (JPEG or YUV) associated with this
137 * decompressor instance.
138 *
139 * @return the width of the source image (JPEG or YUV) associated with this
140 * decompressor instance.
141 */
142 public int getWidth() {
143 if (yuvImage != null)
144 return yuvImage.getWidth();
145 if (jpegWidth < 1)
146 throw new IllegalStateException(NO_ASSOC_ERROR);
147 return jpegWidth;
148 }
149
150 /**
151 * Returns the height of the source image (JPEG or YUV) associated with this
152 * decompressor instance.
153 *
154 * @return the height of the source image (JPEG or YUV) associated with this
155 * decompressor instance.
156 */
157 public int getHeight() {
158 if (yuvImage != null)
159 return yuvImage.getHeight();
160 if (jpegHeight < 1)
161 throw new IllegalStateException(NO_ASSOC_ERROR);
162 return jpegHeight;
163 }
164
165 /**
166 * Returns the level of chrominance subsampling used in the source image
167 * (JPEG or YUV) associated with this decompressor instance. See
168 * {@link TJ#SAMP_444 TJ.SAMP_*}.
169 *
170 * @return the level of chrominance subsampling used in the source image
171 * (JPEG or YUV) associated with this decompressor instance.
172 */
173 public int getSubsamp() {
174 if (yuvImage != null)
175 return yuvImage.getSubsamp();
176 if (jpegSubsamp < 0)
177 throw new IllegalStateException(NO_ASSOC_ERROR);
178 if (jpegSubsamp >= TJ.NUMSAMP)
179 throw new IllegalStateException("JPEG header information is invalid");
180 return jpegSubsamp;
181 }
182
183 /**
184 * Returns the colorspace used in the source image (JPEG or YUV) associated
185 * with this decompressor instance. See {@link TJ#CS_RGB TJ.CS_*}. If the
186 * source image is YUV, then this always returns {@link TJ#CS_YCbCr}.
187 *
188 * @return the colorspace used in the source image (JPEG or YUV) associated
189 * with this decompressor instance.
190 */
191 public int getColorspace() {
192 if (yuvImage != null)
193 return TJ.CS_YCbCr;
194 if (jpegColorspace < 0)
195 throw new IllegalStateException(NO_ASSOC_ERROR);
196 if (jpegColorspace >= TJ.NUMCS)
197 throw new IllegalStateException("JPEG header information is invalid");
198 return jpegColorspace;
199 }
200
201 /**
202 * Returns the JPEG image buffer associated with this decompressor instance.
203 *
204 * @return the JPEG image buffer associated with this decompressor instance.
205 */
206 public byte[] getJPEGBuf() {
207 if (jpegBuf == null)
208 throw new IllegalStateException(NO_ASSOC_ERROR);
209 return jpegBuf;
210 }
211
212 /**
213 * Returns the size of the JPEG image (in bytes) associated with this
214 * decompressor instance.
215 *
216 * @return the size of the JPEG image (in bytes) associated with this
217 * decompressor instance.
218 */
219 public int getJPEGSize() {
220 if (jpegBufSize < 1)
221 throw new IllegalStateException(NO_ASSOC_ERROR);
222 return jpegBufSize;
223 }
224
225 /**
226 * Returns the width of the largest scaled-down image that the TurboJPEG
227 * decompressor can generate without exceeding the desired image width and
228 * height.
229 *
230 * @param desiredWidth desired width (in pixels) of the decompressed image.
231 * Setting this to 0 is the same as setting it to the width of the JPEG image
232 * (in other words, the width will not be considered when determining the
233 * scaled image size.)
234 *
235 * @param desiredHeight desired height (in pixels) of the decompressed image.
236 * Setting this to 0 is the same as setting it to the height of the JPEG
237 * image (in other words, the height will not be considered when determining
238 * the scaled image size.)
239 *
240 * @return the width of the largest scaled-down image that the TurboJPEG
241 * decompressor can generate without exceeding the desired image width and
242 * height.
243 */
244 public int getScaledWidth(int desiredWidth, int desiredHeight) {
245 if (jpegWidth < 1 || jpegHeight < 1)
246 throw new IllegalStateException(NO_ASSOC_ERROR);
247 if (desiredWidth < 0 || desiredHeight < 0)
248 throw new IllegalArgumentException("Invalid argument in getScaledWidth()") ;
249 TJScalingFactor[] sf = TJ.getScalingFactors();
250 if (desiredWidth == 0)
251 desiredWidth = jpegWidth;
252 if (desiredHeight == 0)
253 desiredHeight = jpegHeight;
254 int scaledWidth = jpegWidth, scaledHeight = jpegHeight;
255 for (int i = 0; i < sf.length; i++) {
256 scaledWidth = sf[i].getScaled(jpegWidth);
257 scaledHeight = sf[i].getScaled(jpegHeight);
258 if (scaledWidth <= desiredWidth && scaledHeight <= desiredHeight)
259 break;
260 }
261 if (scaledWidth > desiredWidth || scaledHeight > desiredHeight)
262 throw new IllegalArgumentException("Could not scale down to desired image dimensions");
263 return scaledWidth;
264 }
265
266 /**
267 * Returns the height of the largest scaled-down image that the TurboJPEG
268 * decompressor can generate without exceeding the desired image width and
269 * height.
270 *
271 * @param desiredWidth desired width (in pixels) of the decompressed image.
272 * Setting this to 0 is the same as setting it to the width of the JPEG image
273 * (in other words, the width will not be considered when determining the
274 * scaled image size.)
275 *
276 * @param desiredHeight desired height (in pixels) of the decompressed image.
277 * Setting this to 0 is the same as setting it to the height of the JPEG
278 * image (in other words, the height will not be considered when determining
279 * the scaled image size.)
280 *
281 * @return the height of the largest scaled-down image that the TurboJPEG
282 * decompressor can generate without exceeding the desired image width and
283 * height.
284 */
285 public int getScaledHeight(int desiredWidth, int desiredHeight) {
286 if (jpegWidth < 1 || jpegHeight < 1)
287 throw new IllegalStateException(NO_ASSOC_ERROR);
288 if (desiredWidth < 0 || desiredHeight < 0)
289 throw new IllegalArgumentException("Invalid argument in getScaledHeight()" );
290 TJScalingFactor[] sf = TJ.getScalingFactors();
291 if (desiredWidth == 0)
292 desiredWidth = jpegWidth;
293 if (desiredHeight == 0)
294 desiredHeight = jpegHeight;
295 int scaledWidth = jpegWidth, scaledHeight = jpegHeight;
296 for (int i = 0; i < sf.length; i++) {
297 scaledWidth = sf[i].getScaled(jpegWidth);
298 scaledHeight = sf[i].getScaled(jpegHeight);
299 if (scaledWidth <= desiredWidth && scaledHeight <= desiredHeight)
300 break;
301 }
302 if (scaledWidth > desiredWidth || scaledHeight > desiredHeight)
303 throw new IllegalArgumentException("Could not scale down to desired image dimensions");
304 return scaledHeight;
305 }
306
307 /**
308 * Decompress the JPEG source image or decode the YUV source image associated
309 * with this decompressor instance and output a grayscale, RGB, or CMYK image
310 * to the given destination buffer.
311 *
312 * @param dstBuf buffer that will receive the decompressed/decoded image.
313 * If the source image is a JPEG image, then this buffer should normally be
314 * <code>pitch * scaledHeight</code> bytes in size, where
315 * <code>scaledHeight</code> can be determined by calling <code>
316 * scalingFactor.{@link TJScalingFactor#getScaled getScaled}(jpegHeight)
317 * </code> with one of the scaling factors returned from {@link
318 * TJ#getScalingFactors} or by calling {@link #getScaledHeight}. If the
319 * source image is a YUV image, then this buffer should normally be
320 * <code>pitch * height</code> bytes in size, where <code>height</code> is
321 * the height of the YUV image. However, the buffer may also be larger than
322 * the dimensions of the source image, in which case the <code>x</code>,
323 * <code>y</code>, and <code>pitch</code> parameters can be used to specify
324 * the region into which the source image should be decompressed/decoded.
325 *
326 * @param x x offset (in pixels) of the region in the destination image into
327 * which the source image should be decompressed/decoded
328 *
329 * @param y y offset (in pixels) of the region in the destination image into
330 * which the source image should be decompressed/decoded
331 *
332 * @param desiredWidth If the source image is a JPEG image, then this
333 * specifies the desired width (in pixels) of the decompressed image (or
334 * image region.) If the desired destination image dimensions are different
335 * than the source image dimensions, then TurboJPEG will use scaling in the
336 * JPEG decompressor to generate the largest possible image that will fit
337 * within the desired dimensions. Setting this to 0 is the same as setting
338 * it to the width of the JPEG image (in other words, the width will not be
339 * considered when determining the scaled image size.) This parameter is
340 * ignored if the source image is a YUV image.
341 *
342 * @param pitch bytes per line of the destination image. Normally, this
343 * should be set to <code>scaledWidth * TJ.pixelSize(pixelFormat)</code> if
344 * the destination image is unpadded, but you can use this to, for instance,
345 * pad each line of the destination image to a 4-byte boundary or to
346 * decompress/decode the source image into a region of a larger image. NOTE:
347 * if the source image is a JPEG image, then <code>scaledWidth</code> can be
348 * determined by calling <code>
349 * scalingFactor.{@link TJScalingFactor#getScaled getScaled}(jpegWidth)
350 * </code> or by calling {@link #getScaledWidth}. If the source image is a
351 * YUV image, then <code>scaledWidth</code> is the width of the YUV image.
352 * Setting this parameter to 0 is the equivalent of setting it to
353 * <code>scaledWidth * TJ.pixelSize(pixelFormat)</code>.
354 *
355 * @param desiredHeight If the source image is a JPEG image, then this
356 * specifies the desired height (in pixels) of the decompressed image (or
357 * image region.) If the desired destination image dimensions are different
358 * than the source image dimensions, then TurboJPEG will use scaling in the
359 * JPEG decompressor to generate the largest possible image that will fit
360 * within the desired dimensions. Setting this to 0 is the same as setting
361 * it to the height of the JPEG image (in other words, the height will not be
362 * considered when determining the scaled image size.) This parameter is
363 * ignored if the source image is a YUV image.
364 *
365 * @param pixelFormat pixel format of the decompressed/decoded image (one of
366 * {@link TJ#PF_RGB TJ.PF_*})
367 *
368 * @param flags the bitwise OR of one or more of
369 * {@link TJ#FLAG_BOTTOMUP TJ.FLAG_*}
370 */
371 public void decompress(byte[] dstBuf, int x, int y, int desiredWidth,
372 int pitch, int desiredHeight, int pixelFormat,
373 int flags) throws TJException {
374 if (jpegBuf == null && yuvImage == null)
375 throw new IllegalStateException(NO_ASSOC_ERROR);
376 if (dstBuf == null || x < 0 || y < 0 || pitch < 0 ||
377 (yuvImage != null && (desiredWidth < 0 || desiredHeight < 0)) ||
378 pixelFormat < 0 || pixelFormat >= TJ.NUMPF || flags < 0)
379 throw new IllegalArgumentException("Invalid argument in decompress()");
380 if (yuvImage != null)
381 decodeYUV(yuvImage.getPlanes(), yuvImage.getOffsets(),
382 yuvImage.getStrides(), yuvImage.getSubsamp(), dstBuf, x, y,
383 yuvImage.getWidth(), pitch, yuvImage.getHeight(), pixelFormat,
384 flags);
385 else {
386 if (x > 0 || y > 0)
387 decompress(jpegBuf, jpegBufSize, dstBuf, x, y, desiredWidth, pitch,
388 desiredHeight, pixelFormat, flags);
389 else
390 decompress(jpegBuf, jpegBufSize, dstBuf, desiredWidth, pitch,
391 desiredHeight, pixelFormat, flags);
392 }
393 }
394
395 /**
396 * @deprecated Use
397 * {@link #decompress(byte[], int, int, int, int, int, int, int)} instead.
398 */
399 @Deprecated
400 public void decompress(byte[] dstBuf, int desiredWidth, int pitch,
401 int desiredHeight, int pixelFormat, int flags)
402 throws TJException {
403 decompress(dstBuf, 0, 0, desiredWidth, pitch, desiredHeight, pixelFormat,
404 flags);
405 }
406
407 /**
408 * Decompress the JPEG source image associated with this decompressor
409 * instance and return a buffer containing the decompressed image.
410 *
411 * @param desiredWidth see
412 * {@link #decompress(byte[], int, int, int, int, int, int, int)}
413 * for description
414 *
415 * @param pitch see
416 * {@link #decompress(byte[], int, int, int, int, int, int, int)}
417 * for description
418 *
419 * @param desiredHeight see
420 * {@link #decompress(byte[], int, int, int, int, int, int, int)}
421 * for description
422 *
423 * @param pixelFormat pixel format of the decompressed image (one of
424 * {@link TJ#PF_RGB TJ.PF_*})
425 *
426 * @param flags the bitwise OR of one or more of
427 * {@link TJ#FLAG_BOTTOMUP TJ.FLAG_*}
428 *
429 * @return a buffer containing the decompressed image.
430 */
431 public byte[] decompress(int desiredWidth, int pitch, int desiredHeight,
432 int pixelFormat, int flags) throws TJException {
433 if (pitch < 0 ||
434 (yuvImage == null && (desiredWidth < 0 || desiredHeight < 0)) ||
435 pixelFormat < 0 || pixelFormat >= TJ.NUMPF || flags < 0)
436 throw new IllegalArgumentException("Invalid argument in decompress()");
437 int pixelSize = TJ.getPixelSize(pixelFormat);
438 int scaledWidth = getScaledWidth(desiredWidth, desiredHeight);
439 int scaledHeight = getScaledHeight(desiredWidth, desiredHeight);
440 if (pitch == 0)
441 pitch = scaledWidth * pixelSize;
442 byte[] buf = new byte[pitch * scaledHeight];
443 decompress(buf, desiredWidth, pitch, desiredHeight, pixelFormat, flags);
444 return buf;
445 }
446
447 /**
448 * Decompress the JPEG source image associated with this decompressor
449 * instance into a YUV planar image and store it in the given
450 * <code>YUVImage</code> instance. This method performs JPEG decompression
451 * but leaves out the color conversion step, so a planar YUV image is
452 * generated instead of an RGB or grayscale image. This method cannot be
453 * used to decompress JPEG source images with the CMYK or YCCK colorspace.
454 *
455 * @param dstImage {@link YUVImage} instance that will receive the YUV planar
456 * image. The level of subsampling specified in this <code>YUVImage</code>
457 * instance must match that of the JPEG image, and the width and height
458 * specified in the <code>YUVImage</code> instance must match one of the
459 * scaled image sizes that TurboJPEG is capable of generating from the JPEG
460 * source image.
461 *
462 * @param flags the bitwise OR of one or more of
463 * {@link TJ#FLAG_BOTTOMUP TJ.FLAG_*}
464 */
465 public void decompressToYUV(YUVImage dstImage, int flags)
466 throws TJException {
467 if (jpegBuf == null)
468 throw new IllegalStateException(NO_ASSOC_ERROR);
469 if (dstImage == null || flags < 0)
470 throw new IllegalArgumentException("Invalid argument in decompressToYUV()" );
471 int scaledWidth = getScaledWidth(dstImage.getWidth(),
472 dstImage.getHeight());
473 int scaledHeight = getScaledHeight(dstImage.getWidth(),
474 dstImage.getHeight());
475 if (scaledWidth != dstImage.getWidth() ||
476 scaledHeight != dstImage.getHeight())
477 throw new IllegalArgumentException("YUVImage dimensions do not match one o f the scaled image sizes that TurboJPEG is capable of generating.");
478 if (jpegSubsamp != dstImage.getSubsamp())
479 throw new IllegalArgumentException("YUVImage subsampling level does not ma tch that of the JPEG image");
480
481 decompressToYUV(jpegBuf, jpegBufSize, dstImage.getPlanes(),
482 dstImage.getOffsets(), dstImage.getWidth(),
483 dstImage.getStrides(), dstImage.getHeight(), flags);
484 }
485
486 /**
487 * @deprecated Use {@link #decompressToYUV(YUVImage, int)} instead.
488 */
489 @Deprecated
490 public void decompressToYUV(byte[] dstBuf, int flags) throws TJException {
491 YUVImage dstImage = new YUVImage(dstBuf, jpegWidth, 4, jpegHeight,
492 jpegSubsamp);
493 decompressToYUV(dstImage, flags);
494 }
495
496 /**
497 * Decompress the JPEG source image associated with this decompressor
498 * instance into a set of Y, U (Cb), and V (Cr) image planes and return a
499 * <code>YUVImage</code> instance containing the decompressed image planes.
500 * This method performs JPEG decompression but leaves out the color
501 * conversion step, so a planar YUV image is generated instead of an RGB or
502 * grayscale image. This method cannot be used to decompress JPEG source
503 * images with the CMYK or YCCK colorspace.
504 *
505 * @param desiredWidth desired width (in pixels) of the YUV image. If the
506 * desired image dimensions are different than the dimensions of the JPEG
507 * image being decompressed, then TurboJPEG will use scaling in the JPEG
508 * decompressor to generate the largest possible image that will fit within
509 * the desired dimensions. Setting this to 0 is the same as setting it to
510 * the width of the JPEG image (in other words, the width will not be
511 * considered when determining the scaled image size.)
512 *
513 * @param strides an array of integers, each specifying the number of bytes
514 * per line in the corresponding plane of the output image. Setting the
515 * stride for any plane to 0 is the same as setting it to the scaled
516 * component width of the plane. If <tt>strides</tt> is NULL, then the
517 * strides for all planes will be set to their respective scaled component
518 * widths. You can adjust the strides in order to add an arbitrary amount of
519 * line padding to each plane.
520 *
521 * @param desiredHeight desired height (in pixels) of the YUV image. If the
522 * desired image dimensions are different than the dimensions of the JPEG
523 * image being decompressed, then TurboJPEG will use scaling in the JPEG
524 * decompressor to generate the largest possible image that will fit within
525 * the desired dimensions. Setting this to 0 is the same as setting it to
526 * the height of the JPEG image (in other words, the height will not be
527 * considered when determining the scaled image size.)
528 *
529 * @param flags the bitwise OR of one or more of
530 * {@link TJ#FLAG_BOTTOMUP TJ.FLAG_*}
531 *
532 * @return a YUV planar image.
533 */
534 public YUVImage decompressToYUV(int desiredWidth, int[] strides,
535 int desiredHeight,
536 int flags) throws TJException {
537 if (flags < 0)
538 throw new IllegalArgumentException("Invalid argument in decompressToYUV()" );
539 if (jpegWidth < 1 || jpegHeight < 1 || jpegSubsamp < 0)
540 throw new IllegalStateException(NO_ASSOC_ERROR);
541 if (jpegSubsamp >= TJ.NUMSAMP)
542 throw new IllegalStateException("JPEG header information is invalid");
543 if (yuvImage != null)
544 throw new IllegalStateException("Source image is the wrong type");
545
546 int scaledWidth = getScaledWidth(desiredWidth, desiredHeight);
547 int scaledHeight = getScaledHeight(desiredWidth, desiredHeight);
548 YUVImage yuvImage = new YUVImage(scaledWidth, null, scaledHeight,
549 jpegSubsamp);
550 decompressToYUV(yuvImage, flags);
551 return yuvImage;
552 }
553
554 /**
555 * Decompress the JPEG source image associated with this decompressor
556 * instance into a unified YUV planar image buffer and return a
557 * <code>YUVImage</code> instance containing the decompressed image. This
558 * method performs JPEG decompression but leaves out the color conversion
559 * step, so a planar YUV image is generated instead of an RGB or grayscale
560 * image. This method cannot be used to decompress JPEG source images with
561 * the CMYK or YCCK colorspace.
562 *
563 * @param desiredWidth desired width (in pixels) of the YUV image. If the
564 * desired image dimensions are different than the dimensions of the JPEG
565 * image being decompressed, then TurboJPEG will use scaling in the JPEG
566 * decompressor to generate the largest possible image that will fit within
567 * the desired dimensions. Setting this to 0 is the same as setting it to
568 * the width of the JPEG image (in other words, the width will not be
569 * considered when determining the scaled image size.)
570 *
571 * @param pad the width of each line in each plane of the YUV image will be
572 * padded to the nearest multiple of this number of bytes (must be a power of
573 * 2.)
574 *
575 * @param desiredHeight desired height (in pixels) of the YUV image. If the
576 * desired image dimensions are different than the dimensions of the JPEG
577 * image being decompressed, then TurboJPEG will use scaling in the JPEG
578 * decompressor to generate the largest possible image that will fit within
579 * the desired dimensions. Setting this to 0 is the same as setting it to
580 * the height of the JPEG image (in other words, the height will not be
581 * considered when determining the scaled image size.)
582 *
583 * @param flags the bitwise OR of one or more of
584 * {@link TJ#FLAG_BOTTOMUP TJ.FLAG_*}
585 *
586 * @return a YUV planar image.
587 */
588 public YUVImage decompressToYUV(int desiredWidth, int pad, int desiredHeight,
589 int flags) throws TJException {
590 if (flags < 0)
591 throw new IllegalArgumentException("Invalid argument in decompressToYUV()" );
592 if (jpegWidth < 1 || jpegHeight < 1 || jpegSubsamp < 0)
593 throw new IllegalStateException(NO_ASSOC_ERROR);
594 if (jpegSubsamp >= TJ.NUMSAMP)
595 throw new IllegalStateException("JPEG header information is invalid");
596 if (yuvImage != null)
597 throw new IllegalStateException("Source image is the wrong type");
598
599 int scaledWidth = getScaledWidth(desiredWidth, desiredHeight);
600 int scaledHeight = getScaledHeight(desiredWidth, desiredHeight);
601 YUVImage yuvImage = new YUVImage(scaledWidth, pad, scaledHeight,
602 jpegSubsamp);
603 decompressToYUV(yuvImage, flags);
604 return yuvImage;
605 }
606
607 /**
608 * @deprecated Use {@link #decompressToYUV(int, int, int, int)} instead.
609 */
610 @Deprecated
611 public byte[] decompressToYUV(int flags) throws TJException {
612 YUVImage dstImage = new YUVImage(jpegWidth, 4, jpegHeight, jpegSubsamp);
613 decompressToYUV(dstImage, flags);
614 return dstImage.getBuf();
615 }
616
617 /**
618 * Decompress the JPEG source image or decode the YUV source image associated
619 * with this decompressor instance and output a grayscale, RGB, or CMYK image
620 * to the given destination buffer.
621 *
622 * @param dstBuf buffer that will receive the decompressed/decoded image.
623 * If the source image is a JPEG image, then this buffer should normally be
624 * <code>stride * scaledHeight</code> pixels in size, where
625 * <code>scaledHeight</code> can be determined by calling <code>
626 * scalingFactor.{@link TJScalingFactor#getScaled getScaled}(jpegHeight)
627 * </code> with one of the scaling factors returned from {@link
628 * TJ#getScalingFactors} or by calling {@link #getScaledHeight}. If the
629 * source image is a YUV image, then this buffer should normally be
630 * <code>stride * height</code> pixels in size, where <code>height</code> is
631 * the height of the YUV image. However, the buffer may also be larger than
632 * the dimensions of the JPEG image, in which case the <code>x</code>,
633 * <code>y</code>, and <code>stride</code> parameters can be used to specify
634 * the region into which the source image should be decompressed.
635 *
636 * @param x x offset (in pixels) of the region in the destination image into
637 * which the source image should be decompressed/decoded
638 *
639 * @param y y offset (in pixels) of the region in the destination image into
640 * which the source image should be decompressed/decoded
641 *
642 * @param desiredWidth If the source image is a JPEG image, then this
643 * specifies the desired width (in pixels) of the decompressed image (or
644 * image region.) If the desired destination image dimensions are different
645 * than the source image dimensions, then TurboJPEG will use scaling in the
646 * JPEG decompressor to generate the largest possible image that will fit
647 * within the desired dimensions. Setting this to 0 is the same as setting
648 * it to the width of the JPEG image (in other words, the width will not be
649 * considered when determining the scaled image size.) This parameter is
650 * ignored if the source image is a YUV image.
651 *
652 * @param stride pixels per line of the destination image. Normally, this
653 * should be set to <code>scaledWidth</code>, but you can use this to, for
654 * instance, decompress the JPEG image into a region of a larger image.
655 * NOTE: if the source image is a JPEG image, then <code>scaledWidth</code>
656 * can be determined by calling <code>
657 * scalingFactor.{@link TJScalingFactor#getScaled getScaled}(jpegWidth)
658 * </code> or by calling {@link #getScaledWidth}. If the source image is a
659 * YUV image, then <code>scaledWidth</code> is the width of the YUV image.
660 * Setting this parameter to 0 is the equivalent of setting it to
661 * <code>scaledWidth</code>.
662 *
663 * @param desiredHeight If the source image is a JPEG image, then this
664 * specifies the desired height (in pixels) of the decompressed image (or
665 * image region.) If the desired destination image dimensions are different
666 * than the source image dimensions, then TurboJPEG will use scaling in the
667 * JPEG decompressor to generate the largest possible image that will fit
668 * within the desired dimensions. Setting this to 0 is the same as setting
669 * it to the height of the JPEG image (in other words, the height will not be
670 * considered when determining the scaled image size.) This parameter is
671 * ignored if the source image is a YUV image.
672 *
673 * @param pixelFormat pixel format of the decompressed image (one of
674 * {@link TJ#PF_RGB TJ.PF_*})
675 *
676 * @param flags the bitwise OR of one or more of
677 * {@link TJ#FLAG_BOTTOMUP TJ.FLAG_*}
678 */
679 public void decompress(int[] dstBuf, int x, int y, int desiredWidth,
680 int stride, int desiredHeight, int pixelFormat,
681 int flags) throws TJException {
682 if (jpegBuf == null && yuvImage == null)
683 throw new IllegalStateException(NO_ASSOC_ERROR);
684 if (dstBuf == null || x < 0 || y < 0 || stride < 0 ||
685 (yuvImage != null && (desiredWidth < 0 || desiredHeight < 0)) ||
686 pixelFormat < 0 || pixelFormat >= TJ.NUMPF || flags < 0)
687 throw new IllegalArgumentException("Invalid argument in decompress()");
688 if (yuvImage != null)
689 decodeYUV(yuvImage.getPlanes(), yuvImage.getOffsets(),
690 yuvImage.getStrides(), yuvImage.getSubsamp(), dstBuf, x, y,
691 yuvImage.getWidth(), stride, yuvImage.getHeight(), pixelFormat,
692 flags);
693 else
694 decompress(jpegBuf, jpegBufSize, dstBuf, x, y, desiredWidth, stride,
695 desiredHeight, pixelFormat, flags);
696 }
697
698 /**
699 * Decompress the JPEG source image or decode the YUV source image associated
700 * with this decompressor instance and output a decompressed/decoded image to
701 * the given <code>BufferedImage</code> instance.
702 *
703 * @param dstImage a <code>BufferedImage</code> instance that will receive
704 * the decompressed/decoded image. If the source image is a JPEG image, then
705 * the width and height of the <code>BufferedImage</code> instance must match
706 * one of the scaled image sizes that TurboJPEG is capable of generating from
707 * the JPEG image. If the source image is a YUV image, then the width and
708 * height of the <code>BufferedImage</code> instance must match the width and
709 * height of the YUV image.
710 *
711 * @param flags the bitwise OR of one or more of
712 * {@link TJ#FLAG_BOTTOMUP TJ.FLAG_*}
713 */
714 public void decompress(BufferedImage dstImage, int flags)
715 throws TJException {
716 if (dstImage == null || flags < 0)
717 throw new IllegalArgumentException("Invalid argument in decompress()");
718 int desiredWidth = dstImage.getWidth();
719 int desiredHeight = dstImage.getHeight();
720 int scaledWidth, scaledHeight;
721
722 if (yuvImage != null) {
723 if (desiredWidth != yuvImage.getWidth() ||
724 desiredHeight != yuvImage.getHeight())
725 throw new IllegalArgumentException("BufferedImage dimensions do not matc h the dimensions of the source image.");
726 scaledWidth = yuvImage.getWidth();
727 scaledHeight = yuvImage.getHeight();
728 } else {
729 scaledWidth = getScaledWidth(desiredWidth, desiredHeight);
730 scaledHeight = getScaledHeight(desiredWidth, desiredHeight);
731 if (scaledWidth != desiredWidth || scaledHeight != desiredHeight)
732 throw new IllegalArgumentException("BufferedImage dimensions do not matc h one of the scaled image sizes that TurboJPEG is capable of generating.");
733 }
734 int pixelFormat; boolean intPixels = false;
735 if (byteOrder == null)
736 byteOrder = ByteOrder.nativeOrder();
737 switch(dstImage.getType()) {
738 case BufferedImage.TYPE_3BYTE_BGR:
739 pixelFormat = TJ.PF_BGR; break;
740 case BufferedImage.TYPE_4BYTE_ABGR:
741 case BufferedImage.TYPE_4BYTE_ABGR_PRE:
742 pixelFormat = TJ.PF_XBGR; break;
743 case BufferedImage.TYPE_BYTE_GRAY:
744 pixelFormat = TJ.PF_GRAY; break;
745 case BufferedImage.TYPE_INT_BGR:
746 if (byteOrder == ByteOrder.BIG_ENDIAN)
747 pixelFormat = TJ.PF_XBGR;
748 else
749 pixelFormat = TJ.PF_RGBX;
750 intPixels = true; break;
751 case BufferedImage.TYPE_INT_RGB:
752 if (byteOrder == ByteOrder.BIG_ENDIAN)
753 pixelFormat = TJ.PF_XRGB;
754 else
755 pixelFormat = TJ.PF_BGRX;
756 intPixels = true; break;
757 case BufferedImage.TYPE_INT_ARGB:
758 case BufferedImage.TYPE_INT_ARGB_PRE:
759 if (byteOrder == ByteOrder.BIG_ENDIAN)
760 pixelFormat = TJ.PF_ARGB;
761 else
762 pixelFormat = TJ.PF_BGRA;
763 intPixels = true; break;
764 default:
765 throw new IllegalArgumentException("Unsupported BufferedImage format");
766 }
767 WritableRaster wr = dstImage.getRaster();
768 if (intPixels) {
769 SinglePixelPackedSampleModel sm =
770 (SinglePixelPackedSampleModel)dstImage.getSampleModel();
771 int stride = sm.getScanlineStride();
772 DataBufferInt db = (DataBufferInt)wr.getDataBuffer();
773 int[] buf = db.getData();
774 if (yuvImage != null)
775 decodeYUV(yuvImage.getPlanes(), yuvImage.getOffsets(),
776 yuvImage.getStrides(), yuvImage.getSubsamp(), buf, 0, 0,
777 yuvImage.getWidth(), stride, yuvImage.getHeight(),
778 pixelFormat, flags);
779 else {
780 if (jpegBuf == null)
781 throw new IllegalStateException(NO_ASSOC_ERROR);
782 decompress(jpegBuf, jpegBufSize, buf, 0, 0, scaledWidth, stride,
783 scaledHeight, pixelFormat, flags);
784 }
785 } else {
786 ComponentSampleModel sm =
787 (ComponentSampleModel)dstImage.getSampleModel();
788 int pixelSize = sm.getPixelStride();
789 if (pixelSize != TJ.getPixelSize(pixelFormat))
790 throw new IllegalArgumentException("Inconsistency between pixel format a nd pixel size in BufferedImage");
791 int pitch = sm.getScanlineStride();
792 DataBufferByte db = (DataBufferByte)wr.getDataBuffer();
793 byte[] buf = db.getData();
794 decompress(buf, 0, 0, scaledWidth, pitch, scaledHeight, pixelFormat,
795 flags);
796 }
797 }
798
799 /**
800 * Decompress the JPEG source image or decode the YUV source image associated
801 * with this decompressor instance and return a <code>BufferedImage</code>
802 * instance containing the decompressed/decoded image.
803 *
804 * @param desiredWidth see
805 * {@link #decompress(byte[], int, int, int, int, int, int, int)} for
806 * description
807 *
808 * @param desiredHeight see
809 * {@link #decompress(byte[], int, int, int, int, int, int, int)} for
810 * description
811 *
812 * @param bufferedImageType the image type of the <code>BufferedImage</code>
813 * instance that will be created (for instance,
814 * <code>BufferedImage.TYPE_INT_RGB</code>)
815 *
816 * @param flags the bitwise OR of one or more of
817 * {@link TJ#FLAG_BOTTOMUP TJ.FLAG_*}
818 *
819 * @return a <code>BufferedImage</code> instance containing the
820 * decompressed/decoded image.
821 */
822 public BufferedImage decompress(int desiredWidth, int desiredHeight,
823 int bufferedImageType, int flags)
824 throws TJException {
825 if ((yuvImage == null && (desiredWidth < 0 || desiredHeight < 0)) ||
826 flags < 0)
827 throw new IllegalArgumentException("Invalid argument in decompress()");
828 int scaledWidth = getScaledWidth(desiredWidth, desiredHeight);
829 int scaledHeight = getScaledHeight(desiredWidth, desiredHeight);
830 BufferedImage img = new BufferedImage(scaledWidth, scaledHeight,
831 bufferedImageType);
832 decompress(img, flags);
833 return img;
834 }
835
836 /**
837 * Free the native structures associated with this decompressor instance.
838 */
839 @Override
840 public void close() throws TJException {
841 if (handle != 0)
842 destroy();
843 }
844
845 @Override
846 protected void finalize() throws Throwable {
847 try {
848 close();
849 } catch(TJException e) {
850 } finally {
851 super.finalize();
852 }
853 };
854
855 private native void init() throws TJException;
856
857 private native void destroy() throws TJException;
858
859 private native void decompressHeader(byte[] srcBuf, int size)
860 throws TJException;
861
862 @Deprecated
863 private native void decompress(byte[] srcBuf, int size, byte[] dstBuf,
864 int desiredWidth, int pitch, int desiredHeight, int pixelFormat, int flags)
865 throws TJException;
866
867 private native void decompress(byte[] srcBuf, int size, byte[] dstBuf, int x,
868 int y, int desiredWidth, int pitch, int desiredHeight, int pixelFormat,
869 int flags) throws TJException;
870
871 @Deprecated
872 private native void decompress(byte[] srcBuf, int size, int[] dstBuf,
873 int desiredWidth, int stride, int desiredHeight, int pixelFormat,
874 int flags) throws TJException;
875
876 private native void decompress(byte[] srcBuf, int size, int[] dstBuf, int x,
877 int y, int desiredWidth, int stride, int desiredHeight, int pixelFormat,
878 int flags) throws TJException;
879
880 @Deprecated
881 private native void decompressToYUV(byte[] srcBuf, int size, byte[] dstBuf,
882 int flags) throws TJException;
883
884 private native void decompressToYUV(byte[] srcBuf, int size,
885 byte[][] dstPlanes, int[] dstOffsets, int desiredWidth, int[] dstStrides,
886 int desiredheight, int flags) throws TJException;
887
888 private native void decodeYUV(byte[][] srcPlanes, int[] srcOffsets,
889 int[] srcStrides, int subsamp, byte[] dstBuf, int x, int y, int width,
890 int pitch, int height, int pixelFormat, int flags) throws TJException;
891
892 private native void decodeYUV(byte[][] srcPlanes, int[] srcOffsets,
893 int[] srcStrides, int subsamp, int[] dstBuf, int x, int y, int width,
894 int stride, int height, int pixelFormat, int flags) throws TJException;
895
896 static {
897 TJLoader.load();
898 }
899
900 protected long handle = 0;
901 protected byte[] jpegBuf = null;
902 protected int jpegBufSize = 0;
903 protected YUVImage yuvImage = null;
904 protected int jpegWidth = 0;
905 protected int jpegHeight = 0;
906 protected int jpegSubsamp = -1;
907 protected int jpegColorspace = -1;
908 private ByteOrder byteOrder = null;
909 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698