1 /*
2 * Copyright (C)2011-2019 D. R. Commander. All Rights Reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * - Redistributions of source code must retain the above copyright notice,
8 * this list of conditions and the following disclaimer.
9 * - Redistributions in binary form must reproduce the above copyright notice,
10 * this list of conditions and the following disclaimer in the documentation
11 * and/or other materials provided with the distribution.
12 * - Neither the name of the libjpeg-turbo Project nor the names of its
13 * contributors may be used to endorse or promote products derived from this
14 * software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS",
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 #include <stdlib.h>
30 #include <string.h>
31 #include "turbojpeg.h"
32 #ifdef WIN32
33 #include "tjutil.h"
34 #endif
35 #include <jni.h>
36 #include "java/org_libjpegturbo_turbojpeg_TJCompressor.h"
37 #include "java/org_libjpegturbo_turbojpeg_TJDecompressor.h"
38 #include "java/org_libjpegturbo_turbojpeg_TJTransformer.h"
39 #include "java/org_libjpegturbo_turbojpeg_TJ.h"
40
41 #define BAILIF0(f) { \
42 if (!(f) || (*env)->ExceptionCheck(env)) { \
43 goto bailout; \
44 } \
45 }
46
47 #define THROW(msg, exceptionClass) { \
48 jclass _exccls = (*env)->FindClass(env, exceptionClass); \
49 \
50 BAILIF0(_exccls); \
51 (*env)->ThrowNew(env, _exccls, msg); \
52 goto bailout; \
53 }
54
55 #define THROW_TJ() { \
56 jclass _exccls; \
57 jmethodID _excid; \
58 jobject _excobj; \
59 jstring _errstr; \
60 \
61 BAILIF0(_errstr = (*env)->NewStringUTF(env, tjGetErrorStr2(handle))); \
62 BAILIF0(_exccls = (*env)->FindClass(env, \
63 "org/libjpegturbo/turbojpeg/TJException")); \
64 BAILIF0(_excid = (*env)->GetMethodID(env, _exccls, "<init>", \
65 "(Ljava/lang/String;I)V")); \
66 BAILIF0(_excobj = (*env)->NewObject(env, _exccls, _excid, _errstr, \
67 tjGetErrorCode(handle))); \
68 (*env)->Throw(env, _excobj); \
69 goto bailout; \
70 }
71
72 #define THROW_ARG(msg) THROW(msg, "java/lang/IllegalArgumentException")
73
74 #define THROW_MEM() \
75 THROW("Memory allocation failure", "java/lang/OutOfMemoryError");
76
77 #define GET_HANDLE() \
78 jclass _cls = (*env)->GetObjectClass(env, obj); \
79 jfieldID _fid; \
80 \
81 BAILIF0(_cls); \
82 BAILIF0(_fid = (*env)->GetFieldID(env, _cls, "handle", "J")); \
83 handle = (tjhandle)(size_t)(*env)->GetLongField(env, obj, _fid);
84
85 #ifdef _WIN32
86 #define setenv(envvar, value, dummy) _putenv_s(envvar, value)
87 #endif
88
89 #define PROP2ENV(property, envvar) { \
90 if ((jName = (*env)->NewStringUTF(env, property)) != NULL && \
91 (jValue = (*env)->CallStaticObjectMethod(env, cls, mid, \
92 jName)) != NULL) { \
93 if ((value = (*env)->GetStringUTFChars(env, jValue, 0)) != NULL) { \
94 setenv(envvar, value, 1); \
95 (*env)->ReleaseStringUTFChars(env, jValue, value); \
96 } \
97 } \
98 }
99
100 #define SAFE_RELEASE(javaArray, cArray) { \
101 if (javaArray && cArray) \
102 (*env)->ReleasePrimitiveArrayCritical(env, javaArray, (void *)cArray, 0); \
103 cArray = NULL; \
104 }
105
ProcessSystemProperties(JNIEnv * env)106 static int ProcessSystemProperties(JNIEnv *env)
107 {
108 jclass cls;
109 jmethodID mid;
110 jstring jName, jValue;
111 const char *value;
112
113 BAILIF0(cls = (*env)->FindClass(env, "java/lang/System"));
114 BAILIF0(mid = (*env)->GetStaticMethodID(env, cls, "getProperty",
115 "(Ljava/lang/String;)Ljava/lang/String;"));
116
117 PROP2ENV("turbojpeg.optimize", "TJ_OPTIMIZE");
118 PROP2ENV("turbojpeg.arithmetic", "TJ_ARITHMETIC");
119 PROP2ENV("turbojpeg.restart", "TJ_RESTART");
120 PROP2ENV("turbojpeg.progressive", "TJ_PROGRESSIVE");
121 return 0;
122
123 bailout:
124 return -1;
125 }
126
127 /* TurboJPEG 1.2.x: TJ::bufSize() */
Java_org_libjpegturbo_turbojpeg_TJ_bufSize(JNIEnv * env,jclass cls,jint width,jint height,jint jpegSubsamp)128 JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJ_bufSize
129 (JNIEnv *env, jclass cls, jint width, jint height, jint jpegSubsamp)
130 {
131 jint retval = (jint)tjBufSize(width, height, jpegSubsamp);
132
133 if (retval == -1) THROW_ARG(tjGetErrorStr());
134
135 bailout:
136 return retval;
137 }
138
139 /* TurboJPEG 1.4.x: TJ::bufSizeYUV() */
Java_org_libjpegturbo_turbojpeg_TJ_bufSizeYUV__IIII(JNIEnv * env,jclass cls,jint width,jint pad,jint height,jint subsamp)140 JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJ_bufSizeYUV__IIII
141 (JNIEnv *env, jclass cls, jint width, jint pad, jint height, jint subsamp)
142 {
143 jint retval = (jint)tjBufSizeYUV2(width, pad, height, subsamp);
144
145 if (retval == -1) THROW_ARG(tjGetErrorStr());
146
147 bailout:
148 return retval;
149 }
150
151 /* TurboJPEG 1.2.x: TJ::bufSizeYUV() */
Java_org_libjpegturbo_turbojpeg_TJ_bufSizeYUV__III(JNIEnv * env,jclass cls,jint width,jint height,jint subsamp)152 JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJ_bufSizeYUV__III
153 (JNIEnv *env, jclass cls, jint width, jint height, jint subsamp)
154 {
155 return Java_org_libjpegturbo_turbojpeg_TJ_bufSizeYUV__IIII(env, cls, width,
156 4, height,
157 subsamp);
158 }
159
160 /* TurboJPEG 1.4.x: TJ::planeSizeYUV() */
Java_org_libjpegturbo_turbojpeg_TJ_planeSizeYUV__IIIII(JNIEnv * env,jclass cls,jint componentID,jint width,jint stride,jint height,jint subsamp)161 JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJ_planeSizeYUV__IIIII
162 (JNIEnv *env, jclass cls, jint componentID, jint width, jint stride,
163 jint height, jint subsamp)
164 {
165 jint retval = (jint)tjPlaneSizeYUV(componentID, width, stride, height,
166 subsamp);
167
168 if (retval == -1) THROW_ARG(tjGetErrorStr());
169
170 bailout:
171 return retval;
172 }
173
174 /* TurboJPEG 1.4.x: TJ::planeWidth() */
Java_org_libjpegturbo_turbojpeg_TJ_planeWidth__III(JNIEnv * env,jclass cls,jint componentID,jint width,jint subsamp)175 JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJ_planeWidth__III
176 (JNIEnv *env, jclass cls, jint componentID, jint width, jint subsamp)
177 {
178 jint retval = (jint)tjPlaneWidth(componentID, width, subsamp);
179
180 if (retval == -1) THROW_ARG(tjGetErrorStr());
181
182 bailout:
183 return retval;
184 }
185
186 /* TurboJPEG 1.4.x: TJ::planeHeight() */
Java_org_libjpegturbo_turbojpeg_TJ_planeHeight__III(JNIEnv * env,jclass cls,jint componentID,jint height,jint subsamp)187 JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJ_planeHeight__III
188 (JNIEnv *env, jclass cls, jint componentID, jint height, jint subsamp)
189 {
190 jint retval = (jint)tjPlaneHeight(componentID, height, subsamp);
191
192 if (retval == -1) THROW_ARG(tjGetErrorStr());
193
194 bailout:
195 return retval;
196 }
197
198 /* TurboJPEG 1.2.x: TJCompressor::init() */
Java_org_libjpegturbo_turbojpeg_TJCompressor_init(JNIEnv * env,jobject obj)199 JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_init
200 (JNIEnv *env, jobject obj)
201 {
202 jclass cls;
203 jfieldID fid;
204 tjhandle handle;
205
206 if ((handle = tjInitCompress()) == NULL)
207 THROW(tjGetErrorStr(), "org/libjpegturbo/turbojpeg/TJException");
208
209 BAILIF0(cls = (*env)->GetObjectClass(env, obj));
210 BAILIF0(fid = (*env)->GetFieldID(env, cls, "handle", "J"));
211 (*env)->SetLongField(env, obj, fid, (size_t)handle);
212
213 bailout:
214 return;
215 }
216
TJCompressor_compress(JNIEnv * env,jobject obj,jarray src,jint srcElementSize,jint x,jint y,jint width,jint pitch,jint height,jint pf,jbyteArray dst,jint jpegSubsamp,jint jpegQual,jint flags)217 static jint TJCompressor_compress
218 (JNIEnv *env, jobject obj, jarray src, jint srcElementSize, jint x, jint y,
219 jint width, jint pitch, jint height, jint pf, jbyteArray dst,
220 jint jpegSubsamp, jint jpegQual, jint flags)
221 {
222 tjhandle handle = 0;
223 unsigned long jpegSize = 0;
224 jsize arraySize = 0, actualPitch;
225 unsigned char *srcBuf = NULL, *jpegBuf = NULL;
226
227 GET_HANDLE();
228
229 if (pf < 0 || pf >= org_libjpegturbo_turbojpeg_TJ_NUMPF || width < 1 ||
230 height < 1 || pitch < 0)
231 THROW_ARG("Invalid argument in compress()");
232 if (org_libjpegturbo_turbojpeg_TJ_NUMPF != TJ_NUMPF)
233 THROW_ARG("Mismatch between Java and C API");
234
235 actualPitch = (pitch == 0) ? width * tjPixelSize[pf] : pitch;
236 arraySize = (y + height - 1) * actualPitch + (x + width) * tjPixelSize[pf];
237 if ((*env)->GetArrayLength(env, src) * srcElementSize < arraySize)
238 THROW_ARG("Source buffer is not large enough");
239 jpegSize = tjBufSize(width, height, jpegSubsamp);
240 if ((*env)->GetArrayLength(env, dst) < (jsize)jpegSize)
241 THROW_ARG("Destination buffer is not large enough");
242
243 if (ProcessSystemProperties(env) < 0) goto bailout;
244
245 BAILIF0(srcBuf = (*env)->GetPrimitiveArrayCritical(env, src, 0));
246 BAILIF0(jpegBuf = (*env)->GetPrimitiveArrayCritical(env, dst, 0));
247
248 if (tjCompress2(handle, &srcBuf[y * actualPitch + x * tjPixelSize[pf]],
249 width, pitch, height, pf, &jpegBuf, &jpegSize, jpegSubsamp,
250 jpegQual, flags | TJFLAG_NOREALLOC) == -1) {
251 SAFE_RELEASE(dst, jpegBuf);
252 SAFE_RELEASE(src, srcBuf);
253 THROW_TJ();
254 }
255
256 bailout:
257 SAFE_RELEASE(dst, jpegBuf);
258 SAFE_RELEASE(src, srcBuf);
259 return (jint)jpegSize;
260 }
261
262 /* TurboJPEG 1.3.x: TJCompressor::compress() byte source */
Java_org_libjpegturbo_turbojpeg_TJCompressor_compress___3BIIIIII_3BIII(JNIEnv * env,jobject obj,jbyteArray src,jint x,jint y,jint width,jint pitch,jint height,jint pf,jbyteArray dst,jint jpegSubsamp,jint jpegQual,jint flags)263 JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_compress___3BIIIIII_3BIII
264 (JNIEnv *env, jobject obj, jbyteArray src, jint x, jint y, jint width,
265 jint pitch, jint height, jint pf, jbyteArray dst, jint jpegSubsamp,
266 jint jpegQual, jint flags)
267 {
268 return TJCompressor_compress(env, obj, src, 1, x, y, width, pitch, height,
269 pf, dst, jpegSubsamp, jpegQual, flags);
270 }
271
272 /* TurboJPEG 1.2.x: TJCompressor::compress() byte source */
Java_org_libjpegturbo_turbojpeg_TJCompressor_compress___3BIIII_3BIII(JNIEnv * env,jobject obj,jbyteArray src,jint width,jint pitch,jint height,jint pf,jbyteArray dst,jint jpegSubsamp,jint jpegQual,jint flags)273 JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_compress___3BIIII_3BIII
274 (JNIEnv *env, jobject obj, jbyteArray src, jint width, jint pitch,
275 jint height, jint pf, jbyteArray dst, jint jpegSubsamp, jint jpegQual,
276 jint flags)
277 {
278 return TJCompressor_compress(env, obj, src, 1, 0, 0, width, pitch, height,
279 pf, dst, jpegSubsamp, jpegQual, flags);
280 }
281
282 /* TurboJPEG 1.3.x: TJCompressor::compress() int source */
Java_org_libjpegturbo_turbojpeg_TJCompressor_compress___3IIIIIII_3BIII(JNIEnv * env,jobject obj,jintArray src,jint x,jint y,jint width,jint stride,jint height,jint pf,jbyteArray dst,jint jpegSubsamp,jint jpegQual,jint flags)283 JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_compress___3IIIIIII_3BIII
284 (JNIEnv *env, jobject obj, jintArray src, jint x, jint y, jint width,
285 jint stride, jint height, jint pf, jbyteArray dst, jint jpegSubsamp,
286 jint jpegQual, jint flags)
287 {
288 if (pf < 0 || pf >= org_libjpegturbo_turbojpeg_TJ_NUMPF)
289 THROW_ARG("Invalid argument in compress()");
290 if (tjPixelSize[pf] != sizeof(jint))
291 THROW_ARG("Pixel format must be 32-bit when compressing from an integer buffer.");
292
293 return TJCompressor_compress(env, obj, src, sizeof(jint), x, y, width,
294 stride * sizeof(jint), height, pf, dst,
295 jpegSubsamp, jpegQual, flags);
296
297 bailout:
298 return 0;
299 }
300
301 /* TurboJPEG 1.2.x: TJCompressor::compress() int source */
Java_org_libjpegturbo_turbojpeg_TJCompressor_compress___3IIIII_3BIII(JNIEnv * env,jobject obj,jintArray src,jint width,jint stride,jint height,jint pf,jbyteArray dst,jint jpegSubsamp,jint jpegQual,jint flags)302 JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_compress___3IIIII_3BIII
303 (JNIEnv *env, jobject obj, jintArray src, jint width, jint stride,
304 jint height, jint pf, jbyteArray dst, jint jpegSubsamp, jint jpegQual,
305 jint flags)
306 {
307 if (pf < 0 || pf >= org_libjpegturbo_turbojpeg_TJ_NUMPF)
308 THROW_ARG("Invalid argument in compress()");
309 if (tjPixelSize[pf] != sizeof(jint))
310 THROW_ARG("Pixel format must be 32-bit when compressing from an integer buffer.");
311
312 return TJCompressor_compress(env, obj, src, sizeof(jint), 0, 0, width,
313 stride * sizeof(jint), height, pf, dst,
314 jpegSubsamp, jpegQual, flags);
315
316 bailout:
317 return 0;
318 }
319
320 /* TurboJPEG 1.4.x: TJCompressor::compressFromYUV() */
Java_org_libjpegturbo_turbojpeg_TJCompressor_compressFromYUV___3_3B_3II_3III_3BII(JNIEnv * env,jobject obj,jobjectArray srcobjs,jintArray jSrcOffsets,jint width,jintArray jSrcStrides,jint height,jint subsamp,jbyteArray dst,jint jpegQual,jint flags)321 JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_compressFromYUV___3_3B_3II_3III_3BII
322 (JNIEnv *env, jobject obj, jobjectArray srcobjs, jintArray jSrcOffsets,
323 jint width, jintArray jSrcStrides, jint height, jint subsamp,
324 jbyteArray dst, jint jpegQual, jint flags)
325 {
326 tjhandle handle = 0;
327 unsigned long jpegSize = 0;
328 jbyteArray jSrcPlanes[3] = { NULL, NULL, NULL };
329 const unsigned char *srcPlanes[3];
330 unsigned char *jpegBuf = NULL;
331 int *srcOffsets = NULL, *srcStrides = NULL;
332 int nc = (subsamp == org_libjpegturbo_turbojpeg_TJ_SAMP_GRAY ? 1 : 3), i;
333
334 GET_HANDLE();
335
336 if (subsamp < 0 || subsamp >= org_libjpegturbo_turbojpeg_TJ_NUMSAMP)
337 THROW_ARG("Invalid argument in compressFromYUV()");
338 if (org_libjpegturbo_turbojpeg_TJ_NUMSAMP != TJ_NUMSAMP)
339 THROW_ARG("Mismatch between Java and C API");
340
341 if ((*env)->GetArrayLength(env, srcobjs) < nc)
342 THROW_ARG("Planes array is too small for the subsampling type");
343 if ((*env)->GetArrayLength(env, jSrcOffsets) < nc)
344 THROW_ARG("Offsets array is too small for the subsampling type");
345 if ((*env)->GetArrayLength(env, jSrcStrides) < nc)
346 THROW_ARG("Strides array is too small for the subsampling type");
347
348 jpegSize = tjBufSize(width, height, subsamp);
349 if ((*env)->GetArrayLength(env, dst) < (jsize)jpegSize)
350 THROW_ARG("Destination buffer is not large enough");
351
352 if (ProcessSystemProperties(env) < 0) goto bailout;
353
354 #define RELEASE_ARRAYS_COMPRESSFROMYUV() { \
355 SAFE_RELEASE(dst, jpegBuf); \
356 for (i = 0; i < nc; i++) \
357 SAFE_RELEASE(jSrcPlanes[i], srcPlanes[i]); \
358 SAFE_RELEASE(jSrcStrides, srcStrides); \
359 SAFE_RELEASE(jSrcOffsets, srcOffsets); \
360 }
361
362 BAILIF0(srcOffsets = (*env)->GetPrimitiveArrayCritical(env, jSrcOffsets, 0));
363 BAILIF0(srcStrides = (*env)->GetPrimitiveArrayCritical(env, jSrcStrides, 0));
364 for (i = 0; i < nc; i++) {
365 int planeSize = tjPlaneSizeYUV(i, width, srcStrides[i], height, subsamp);
366 int pw = tjPlaneWidth(i, width, subsamp);
367
368 if (planeSize < 0 || pw < 0) {
369 RELEASE_ARRAYS_COMPRESSFROMYUV();
370 THROW_ARG(tjGetErrorStr());
371 }
372
373 if (srcOffsets[i] < 0) {
374 RELEASE_ARRAYS_COMPRESSFROMYUV();
375 THROW_ARG("Invalid argument in compressFromYUV()");
376 }
377 if (srcStrides[i] < 0 && srcOffsets[i] - planeSize + pw < 0) {
378 RELEASE_ARRAYS_COMPRESSFROMYUV();
379 THROW_ARG("Negative plane stride would cause memory to be accessed below plane boundary");
380 }
381
382 BAILIF0(jSrcPlanes[i] = (*env)->GetObjectArrayElement(env, srcobjs, i));
383 if ((*env)->GetArrayLength(env, jSrcPlanes[i]) <
384 srcOffsets[i] + planeSize) {
385 RELEASE_ARRAYS_COMPRESSFROMYUV();
386 THROW_ARG("Source plane is not large enough");
387 }
388
389 BAILIF0(srcPlanes[i] =
390 (*env)->GetPrimitiveArrayCritical(env, jSrcPlanes[i], 0));
391 srcPlanes[i] = &srcPlanes[i][srcOffsets[i]];
392 }
393 BAILIF0(jpegBuf = (*env)->GetPrimitiveArrayCritical(env, dst, 0));
394
395 if (tjCompressFromYUVPlanes(handle, srcPlanes, width, srcStrides, height,
396 subsamp, &jpegBuf, &jpegSize, jpegQual,
397 flags | TJFLAG_NOREALLOC) == -1) {
398 RELEASE_ARRAYS_COMPRESSFROMYUV();
399 THROW_TJ();
400 }
401
402 bailout:
403 RELEASE_ARRAYS_COMPRESSFROMYUV();
404 return (jint)jpegSize;
405 }
406
TJCompressor_encodeYUV(JNIEnv * env,jobject obj,jarray src,jint srcElementSize,jint x,jint y,jint width,jint pitch,jint height,jint pf,jobjectArray dstobjs,jintArray jDstOffsets,jintArray jDstStrides,jint subsamp,jint flags)407 static void TJCompressor_encodeYUV
408 (JNIEnv *env, jobject obj, jarray src, jint srcElementSize, jint x, jint y,
409 jint width, jint pitch, jint height, jint pf, jobjectArray dstobjs,
410 jintArray jDstOffsets, jintArray jDstStrides, jint subsamp, jint flags)
411 {
412 tjhandle handle = 0;
413 jsize arraySize = 0, actualPitch;
414 jbyteArray jDstPlanes[3] = { NULL, NULL, NULL };
415 unsigned char *srcBuf = NULL, *dstPlanes[3];
416 int *dstOffsets = NULL, *dstStrides = NULL;
417 int nc = (subsamp == org_libjpegturbo_turbojpeg_TJ_SAMP_GRAY ? 1 : 3), i;
418
419 GET_HANDLE();
420
421 if (pf < 0 || pf >= org_libjpegturbo_turbojpeg_TJ_NUMPF || width < 1 ||
422 height < 1 || pitch < 0 || subsamp < 0 ||
423 subsamp >= org_libjpegturbo_turbojpeg_TJ_NUMSAMP)
424 THROW_ARG("Invalid argument in encodeYUV()");
425 if (org_libjpegturbo_turbojpeg_TJ_NUMPF != TJ_NUMPF ||
426 org_libjpegturbo_turbojpeg_TJ_NUMSAMP != TJ_NUMSAMP)
427 THROW_ARG("Mismatch between Java and C API");
428
429 if ((*env)->GetArrayLength(env, dstobjs) < nc)
430 THROW_ARG("Planes array is too small for the subsampling type");
431 if ((*env)->GetArrayLength(env, jDstOffsets) < nc)
432 THROW_ARG("Offsets array is too small for the subsampling type");
433 if ((*env)->GetArrayLength(env, jDstStrides) < nc)
434 THROW_ARG("Strides array is too small for the subsampling type");
435
436 actualPitch = (pitch == 0) ? width * tjPixelSize[pf] : pitch;
437 arraySize = (y + height - 1) * actualPitch + (x + width) * tjPixelSize[pf];
438 if ((*env)->GetArrayLength(env, src) * srcElementSize < arraySize)
439 THROW_ARG("Source buffer is not large enough");
440
441 #define RELEASE_ARRAYS_ENCODEYUV() { \
442 SAFE_RELEASE(src, srcBuf); \
443 for (i = 0; i < nc; i++) \
444 SAFE_RELEASE(jDstPlanes[i], dstPlanes[i]); \
445 SAFE_RELEASE(jDstStrides, dstStrides); \
446 SAFE_RELEASE(jDstOffsets, dstOffsets); \
447 }
448
449 BAILIF0(dstOffsets = (*env)->GetPrimitiveArrayCritical(env, jDstOffsets, 0));
450 BAILIF0(dstStrides = (*env)->GetPrimitiveArrayCritical(env, jDstStrides, 0));
451 for (i = 0; i < nc; i++) {
452 int planeSize = tjPlaneSizeYUV(i, width, dstStrides[i], height, subsamp);
453 int pw = tjPlaneWidth(i, width, subsamp);
454
455 if (planeSize < 0 || pw < 0) {
456 RELEASE_ARRAYS_ENCODEYUV();
457 THROW_ARG(tjGetErrorStr());
458 }
459
460 if (dstOffsets[i] < 0) {
461 RELEASE_ARRAYS_ENCODEYUV();
462 THROW_ARG("Invalid argument in encodeYUV()");
463 }
464 if (dstStrides[i] < 0 && dstOffsets[i] - planeSize + pw < 0) {
465 RELEASE_ARRAYS_ENCODEYUV();
466 THROW_ARG("Negative plane stride would cause memory to be accessed below plane boundary");
467 }
468
469 BAILIF0(jDstPlanes[i] = (*env)->GetObjectArrayElement(env, dstobjs, i));
470 if ((*env)->GetArrayLength(env, jDstPlanes[i]) <
471 dstOffsets[i] + planeSize) {
472 RELEASE_ARRAYS_ENCODEYUV();
473 THROW_ARG("Destination plane is not large enough");
474 }
475
476 BAILIF0(dstPlanes[i] =
477 (*env)->GetPrimitiveArrayCritical(env, jDstPlanes[i], 0));
478 dstPlanes[i] = &dstPlanes[i][dstOffsets[i]];
479 }
480 BAILIF0(srcBuf = (*env)->GetPrimitiveArrayCritical(env, src, 0));
481
482 if (tjEncodeYUVPlanes(handle, &srcBuf[y * actualPitch + x * tjPixelSize[pf]],
483 width, pitch, height, pf, dstPlanes, dstStrides,
484 subsamp, flags) == -1) {
485 RELEASE_ARRAYS_ENCODEYUV();
486 THROW_TJ();
487 }
488
489 bailout:
490 RELEASE_ARRAYS_ENCODEYUV();
491 }
492
493 /* TurboJPEG 1.4.x: TJCompressor::encodeYUV() byte source */
Java_org_libjpegturbo_turbojpeg_TJCompressor_encodeYUV___3BIIIIII_3_3B_3I_3III(JNIEnv * env,jobject obj,jbyteArray src,jint x,jint y,jint width,jint pitch,jint height,jint pf,jobjectArray dstobjs,jintArray jDstOffsets,jintArray jDstStrides,jint subsamp,jint flags)494 JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_encodeYUV___3BIIIIII_3_3B_3I_3III
495 (JNIEnv *env, jobject obj, jbyteArray src, jint x, jint y, jint width,
496 jint pitch, jint height, jint pf, jobjectArray dstobjs,
497 jintArray jDstOffsets, jintArray jDstStrides, jint subsamp, jint flags)
498 {
499 TJCompressor_encodeYUV(env, obj, src, 1, x, y, width, pitch, height, pf,
500 dstobjs, jDstOffsets, jDstStrides, subsamp, flags);
501 }
502
503 /* TurboJPEG 1.4.x: TJCompressor::encodeYUV() int source */
Java_org_libjpegturbo_turbojpeg_TJCompressor_encodeYUV___3IIIIIII_3_3B_3I_3III(JNIEnv * env,jobject obj,jintArray src,jint x,jint y,jint width,jint stride,jint height,jint pf,jobjectArray dstobjs,jintArray jDstOffsets,jintArray jDstStrides,jint subsamp,jint flags)504 JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_encodeYUV___3IIIIIII_3_3B_3I_3III
505 (JNIEnv *env, jobject obj, jintArray src, jint x, jint y, jint width,
506 jint stride, jint height, jint pf, jobjectArray dstobjs,
507 jintArray jDstOffsets, jintArray jDstStrides, jint subsamp, jint flags)
508 {
509 if (pf < 0 || pf >= org_libjpegturbo_turbojpeg_TJ_NUMPF)
510 THROW_ARG("Invalid argument in encodeYUV()");
511 if (tjPixelSize[pf] != sizeof(jint))
512 THROW_ARG("Pixel format must be 32-bit when encoding from an integer buffer.");
513
514 TJCompressor_encodeYUV(env, obj, src, sizeof(jint), x, y, width,
515 stride * sizeof(jint), height, pf, dstobjs,
516 jDstOffsets, jDstStrides, subsamp, flags);
517
518 bailout:
519 return;
520 }
521
TJCompressor_encodeYUV_12(JNIEnv * env,jobject obj,jarray src,jint srcElementSize,jint width,jint pitch,jint height,jint pf,jbyteArray dst,jint subsamp,jint flags)522 static void JNICALL TJCompressor_encodeYUV_12
523 (JNIEnv *env, jobject obj, jarray src, jint srcElementSize, jint width,
524 jint pitch, jint height, jint pf, jbyteArray dst, jint subsamp, jint flags)
525 {
526 tjhandle handle = 0;
527 jsize arraySize = 0;
528 unsigned char *srcBuf = NULL, *dstBuf = NULL;
529
530 GET_HANDLE();
531
532 if (pf < 0 || pf >= org_libjpegturbo_turbojpeg_TJ_NUMPF || width < 1 ||
533 height < 1 || pitch < 0)
534 THROW_ARG("Invalid argument in encodeYUV()");
535 if (org_libjpegturbo_turbojpeg_TJ_NUMPF != TJ_NUMPF)
536 THROW_ARG("Mismatch between Java and C API");
537
538 arraySize = (pitch == 0) ? width * tjPixelSize[pf] * height : pitch * height;
539 if ((*env)->GetArrayLength(env, src) * srcElementSize < arraySize)
540 THROW_ARG("Source buffer is not large enough");
541 if ((*env)->GetArrayLength(env, dst) <
542 (jsize)tjBufSizeYUV(width, height, subsamp))
543 THROW_ARG("Destination buffer is not large enough");
544
545 BAILIF0(srcBuf = (*env)->GetPrimitiveArrayCritical(env, src, 0));
546 BAILIF0(dstBuf = (*env)->GetPrimitiveArrayCritical(env, dst, 0));
547
548 if (tjEncodeYUV2(handle, srcBuf, width, pitch, height, pf, dstBuf, subsamp,
549 flags) == -1) {
550 SAFE_RELEASE(dst, dstBuf);
551 SAFE_RELEASE(src, srcBuf);
552 THROW_TJ();
553 }
554
555 bailout:
556 SAFE_RELEASE(dst, dstBuf);
557 SAFE_RELEASE(src, srcBuf);
558 }
559
560 /* TurboJPEG 1.2.x: TJCompressor::encodeYUV() byte source */
Java_org_libjpegturbo_turbojpeg_TJCompressor_encodeYUV___3BIIII_3BII(JNIEnv * env,jobject obj,jbyteArray src,jint width,jint pitch,jint height,jint pf,jbyteArray dst,jint subsamp,jint flags)561 JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_encodeYUV___3BIIII_3BII
562 (JNIEnv *env, jobject obj, jbyteArray src, jint width, jint pitch,
563 jint height, jint pf, jbyteArray dst, jint subsamp, jint flags)
564 {
565 TJCompressor_encodeYUV_12(env, obj, src, 1, width, pitch, height, pf, dst,
566 subsamp, flags);
567 }
568
569 /* TurboJPEG 1.2.x: TJCompressor::encodeYUV() int source */
Java_org_libjpegturbo_turbojpeg_TJCompressor_encodeYUV___3IIIII_3BII(JNIEnv * env,jobject obj,jintArray src,jint width,jint stride,jint height,jint pf,jbyteArray dst,jint subsamp,jint flags)570 JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_encodeYUV___3IIIII_3BII
571 (JNIEnv *env, jobject obj, jintArray src, jint width, jint stride,
572 jint height, jint pf, jbyteArray dst, jint subsamp, jint flags)
573 {
574 if (pf < 0 || pf >= org_libjpegturbo_turbojpeg_TJ_NUMPF)
575 THROW_ARG("Invalid argument in encodeYUV()");
576 if (tjPixelSize[pf] != sizeof(jint))
577 THROW_ARG("Pixel format must be 32-bit when encoding from an integer buffer.");
578
579 TJCompressor_encodeYUV_12(env, obj, src, sizeof(jint), width,
580 stride * sizeof(jint), height, pf, dst, subsamp,
581 flags);
582
583 bailout:
584 return;
585 }
586
587 /* TurboJPEG 1.2.x: TJCompressor::destroy() */
Java_org_libjpegturbo_turbojpeg_TJCompressor_destroy(JNIEnv * env,jobject obj)588 JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_destroy
589 (JNIEnv *env, jobject obj)
590 {
591 tjhandle handle = 0;
592
593 GET_HANDLE();
594
595 if (tjDestroy(handle) == -1) THROW_TJ();
596 (*env)->SetLongField(env, obj, _fid, 0);
597
598 bailout:
599 return;
600 }
601
602 /* TurboJPEG 1.2.x: TJDecompressor::init() */
Java_org_libjpegturbo_turbojpeg_TJDecompressor_init(JNIEnv * env,jobject obj)603 JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_init
604 (JNIEnv *env, jobject obj)
605 {
606 jclass cls;
607 jfieldID fid;
608 tjhandle handle;
609
610 if ((handle = tjInitDecompress()) == NULL)
611 THROW(tjGetErrorStr(), "org/libjpegturbo/turbojpeg/TJException");
612
613 BAILIF0(cls = (*env)->GetObjectClass(env, obj));
614 BAILIF0(fid = (*env)->GetFieldID(env, cls, "handle", "J"));
615 (*env)->SetLongField(env, obj, fid, (size_t)handle);
616
617 bailout:
618 return;
619 }
620
621 /* TurboJPEG 1.2.x: TJDecompressor::getScalingFactors() */
Java_org_libjpegturbo_turbojpeg_TJ_getScalingFactors(JNIEnv * env,jclass cls)622 JNIEXPORT jobjectArray JNICALL Java_org_libjpegturbo_turbojpeg_TJ_getScalingFactors
623 (JNIEnv *env, jclass cls)
624 {
625 jclass sfcls = NULL;
626 jfieldID fid = 0;
627 tjscalingfactor *sf = NULL;
628 int n = 0, i;
629 jobject sfobj = NULL;
630 jobjectArray sfjava = NULL;
631
632 if ((sf = tjGetScalingFactors(&n)) == NULL || n == 0)
633 THROW_ARG(tjGetErrorStr());
634
635 BAILIF0(sfcls = (*env)->FindClass(env,
636 "org/libjpegturbo/turbojpeg/TJScalingFactor"));
637 BAILIF0(sfjava = (jobjectArray)(*env)->NewObjectArray(env, n, sfcls, 0));
638
639 for (i = 0; i < n; i++) {
640 BAILIF0(sfobj = (*env)->AllocObject(env, sfcls));
641 BAILIF0(fid = (*env)->GetFieldID(env, sfcls, "num", "I"));
642 (*env)->SetIntField(env, sfobj, fid, sf[i].num);
643 BAILIF0(fid = (*env)->GetFieldID(env, sfcls, "denom", "I"));
644 (*env)->SetIntField(env, sfobj, fid, sf[i].denom);
645 (*env)->SetObjectArrayElement(env, sfjava, i, sfobj);
646 }
647
648 bailout:
649 return sfjava;
650 }
651
652 /* TurboJPEG 1.2.x: TJDecompressor::decompressHeader() */
Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompressHeader(JNIEnv * env,jobject obj,jbyteArray src,jint jpegSize)653 JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompressHeader
654 (JNIEnv *env, jobject obj, jbyteArray src, jint jpegSize)
655 {
656 tjhandle handle = 0;
657 unsigned char *jpegBuf = NULL;
658 int width = 0, height = 0, jpegSubsamp = -1, jpegColorspace = -1;
659
660 GET_HANDLE();
661
662 if ((*env)->GetArrayLength(env, src) < jpegSize)
663 THROW_ARG("Source buffer is not large enough");
664
665 BAILIF0(jpegBuf = (*env)->GetPrimitiveArrayCritical(env, src, 0));
666
667 if (tjDecompressHeader3(handle, jpegBuf, (unsigned long)jpegSize, &width,
668 &height, &jpegSubsamp, &jpegColorspace) == -1) {
669 SAFE_RELEASE(src, jpegBuf);
670 THROW_TJ();
671 }
672
673 SAFE_RELEASE(src, jpegBuf);
674
675 BAILIF0(_fid = (*env)->GetFieldID(env, _cls, "jpegSubsamp", "I"));
676 (*env)->SetIntField(env, obj, _fid, jpegSubsamp);
677 if ((_fid = (*env)->GetFieldID(env, _cls, "jpegColorspace", "I")) == 0)
678 (*env)->ExceptionClear(env);
679 else
680 (*env)->SetIntField(env, obj, _fid, jpegColorspace);
681 BAILIF0(_fid = (*env)->GetFieldID(env, _cls, "jpegWidth", "I"));
682 (*env)->SetIntField(env, obj, _fid, width);
683 BAILIF0(_fid = (*env)->GetFieldID(env, _cls, "jpegHeight", "I"));
684 (*env)->SetIntField(env, obj, _fid, height);
685
686 bailout:
687 SAFE_RELEASE(src, jpegBuf);
688 }
689
TJDecompressor_decompress(JNIEnv * env,jobject obj,jbyteArray src,jint jpegSize,jarray dst,jint dstElementSize,jint x,jint y,jint width,jint pitch,jint height,jint pf,jint flags)690 static void TJDecompressor_decompress
691 (JNIEnv *env, jobject obj, jbyteArray src, jint jpegSize, jarray dst,
692 jint dstElementSize, jint x, jint y, jint width, jint pitch, jint height,
693 jint pf, jint flags)
694 {
695 tjhandle handle = 0;
696 jsize arraySize = 0, actualPitch;
697 unsigned char *jpegBuf = NULL, *dstBuf = NULL;
698
699 GET_HANDLE();
700
701 if (pf < 0 || pf >= org_libjpegturbo_turbojpeg_TJ_NUMPF)
702 THROW_ARG("Invalid argument in decompress()");
703 if (org_libjpegturbo_turbojpeg_TJ_NUMPF != TJ_NUMPF)
704 THROW_ARG("Mismatch between Java and C API");
705
706 if ((*env)->GetArrayLength(env, src) < jpegSize)
707 THROW_ARG("Source buffer is not large enough");
708 actualPitch = (pitch == 0) ? width * tjPixelSize[pf] : pitch;
709 arraySize = (y + height - 1) * actualPitch + (x + width) * tjPixelSize[pf];
710 if ((*env)->GetArrayLength(env, dst) * dstElementSize < arraySize)
711 THROW_ARG("Destination buffer is not large enough");
712
713 BAILIF0(jpegBuf = (*env)->GetPrimitiveArrayCritical(env, src, 0));
714 BAILIF0(dstBuf = (*env)->GetPrimitiveArrayCritical(env, dst, 0));
715
716 if (tjDecompress2(handle, jpegBuf, (unsigned long)jpegSize,
717 &dstBuf[y * actualPitch + x * tjPixelSize[pf]], width,
718 pitch, height, pf, flags) == -1) {
719 SAFE_RELEASE(dst, dstBuf);
720 SAFE_RELEASE(src, jpegBuf);
721 THROW_TJ();
722 }
723
724 bailout:
725 SAFE_RELEASE(dst, dstBuf);
726 SAFE_RELEASE(src, jpegBuf);
727 }
728
729 /* TurboJPEG 1.3.x: TJDecompressor::decompress() byte destination */
Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompress___3BI_3BIIIIIII(JNIEnv * env,jobject obj,jbyteArray src,jint jpegSize,jbyteArray dst,jint x,jint y,jint width,jint pitch,jint height,jint pf,jint flags)730 JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompress___3BI_3BIIIIIII
731 (JNIEnv *env, jobject obj, jbyteArray src, jint jpegSize, jbyteArray dst,
732 jint x, jint y, jint width, jint pitch, jint height, jint pf, jint flags)
733 {
734 TJDecompressor_decompress(env, obj, src, jpegSize, dst, 1, x, y, width,
735 pitch, height, pf, flags);
736 }
737
738 /* TurboJPEG 1.2.x: TJDecompressor::decompress() byte destination */
Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompress___3BI_3BIIIII(JNIEnv * env,jobject obj,jbyteArray src,jint jpegSize,jbyteArray dst,jint width,jint pitch,jint height,jint pf,jint flags)739 JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompress___3BI_3BIIIII
740 (JNIEnv *env, jobject obj, jbyteArray src, jint jpegSize, jbyteArray dst,
741 jint width, jint pitch, jint height, jint pf, jint flags)
742 {
743 TJDecompressor_decompress(env, obj, src, jpegSize, dst, 1, 0, 0, width,
744 pitch, height, pf, flags);
745 }
746
747 /* TurboJPEG 1.3.x: TJDecompressor::decompress() int destination */
Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompress___3BI_3IIIIIIII(JNIEnv * env,jobject obj,jbyteArray src,jint jpegSize,jintArray dst,jint x,jint y,jint width,jint stride,jint height,jint pf,jint flags)748 JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompress___3BI_3IIIIIIII
749 (JNIEnv *env, jobject obj, jbyteArray src, jint jpegSize, jintArray dst,
750 jint x, jint y, jint width, jint stride, jint height, jint pf, jint flags)
751 {
752 if (pf < 0 || pf >= org_libjpegturbo_turbojpeg_TJ_NUMPF)
753 THROW_ARG("Invalid argument in decompress()");
754 if (tjPixelSize[pf] != sizeof(jint))
755 THROW_ARG("Pixel format must be 32-bit when decompressing to an integer buffer.");
756
757 TJDecompressor_decompress(env, obj, src, jpegSize, dst, sizeof(jint), x, y,
758 width, stride * sizeof(jint), height, pf, flags);
759
760 bailout:
761 return;
762 }
763
764 /* TurboJPEG 1.2.x: TJDecompressor::decompress() int destination */
Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompress___3BI_3IIIIII(JNIEnv * env,jobject obj,jbyteArray src,jint jpegSize,jintArray dst,jint width,jint stride,jint height,jint pf,jint flags)765 JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompress___3BI_3IIIIII
766 (JNIEnv *env, jobject obj, jbyteArray src, jint jpegSize, jintArray dst,
767 jint width, jint stride, jint height, jint pf, jint flags)
768 {
769 if (pf < 0 || pf >= org_libjpegturbo_turbojpeg_TJ_NUMPF)
770 THROW_ARG("Invalid argument in decompress()");
771 if (tjPixelSize[pf] != sizeof(jint))
772 THROW_ARG("Pixel format must be 32-bit when decompressing to an integer buffer.");
773
774 TJDecompressor_decompress(env, obj, src, jpegSize, dst, sizeof(jint), 0, 0,
775 width, stride * sizeof(jint), height, pf, flags);
776
777 bailout:
778 return;
779 }
780
781 /* TurboJPEG 1.4.x: TJDecompressor::decompressToYUV() */
Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompressToYUV___3BI_3_3B_3II_3III(JNIEnv * env,jobject obj,jbyteArray src,jint jpegSize,jobjectArray dstobjs,jintArray jDstOffsets,jint desiredWidth,jintArray jDstStrides,jint desiredHeight,jint flags)782 JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompressToYUV___3BI_3_3B_3II_3III
783 (JNIEnv *env, jobject obj, jbyteArray src, jint jpegSize,
784 jobjectArray dstobjs, jintArray jDstOffsets, jint desiredWidth,
785 jintArray jDstStrides, jint desiredHeight, jint flags)
786 {
787 tjhandle handle = 0;
788 jbyteArray jDstPlanes[3] = { NULL, NULL, NULL };
789 unsigned char *jpegBuf = NULL, *dstPlanes[3];
790 int *dstOffsets = NULL, *dstStrides = NULL;
791 int jpegSubsamp = -1, jpegWidth = 0, jpegHeight = 0;
792 int nc = 0, i, width, height, scaledWidth, scaledHeight, nsf = 0;
793 tjscalingfactor *sf;
794
795 GET_HANDLE();
796
797 if ((*env)->GetArrayLength(env, src) < jpegSize)
798 THROW_ARG("Source buffer is not large enough");
799 BAILIF0(_fid = (*env)->GetFieldID(env, _cls, "jpegSubsamp", "I"));
800 jpegSubsamp = (int)(*env)->GetIntField(env, obj, _fid);
801 BAILIF0(_fid = (*env)->GetFieldID(env, _cls, "jpegWidth", "I"));
802 jpegWidth = (int)(*env)->GetIntField(env, obj, _fid);
803 BAILIF0(_fid = (*env)->GetFieldID(env, _cls, "jpegHeight", "I"));
804 jpegHeight = (int)(*env)->GetIntField(env, obj, _fid);
805
806 nc = (jpegSubsamp == org_libjpegturbo_turbojpeg_TJ_SAMP_GRAY ? 1 : 3);
807
808 width = desiredWidth;
809 height = desiredHeight;
810 if (width == 0) width = jpegWidth;
811 if (height == 0) height = jpegHeight;
812 sf = tjGetScalingFactors(&nsf);
813 if (!sf || nsf < 1)
814 THROW_ARG(tjGetErrorStr());
815 for (i = 0; i < nsf; i++) {
816 scaledWidth = TJSCALED(jpegWidth, sf[i]);
817 scaledHeight = TJSCALED(jpegHeight, sf[i]);
818 if (scaledWidth <= width && scaledHeight <= height)
819 break;
820 }
821 if (i >= nsf)
822 THROW_ARG("Could not scale down to desired image dimensions");
823
824 #define RELEASE_ARRAYS_DECOMPRESSTOYUV() { \
825 SAFE_RELEASE(src, jpegBuf); \
826 for (i = 0; i < nc; i++) \
827 SAFE_RELEASE(jDstPlanes[i], dstPlanes[i]); \
828 SAFE_RELEASE(jDstStrides, dstStrides); \
829 SAFE_RELEASE(jDstOffsets, dstOffsets); \
830 }
831
832 BAILIF0(dstOffsets = (*env)->GetPrimitiveArrayCritical(env, jDstOffsets, 0));
833 BAILIF0(dstStrides = (*env)->GetPrimitiveArrayCritical(env, jDstStrides, 0));
834 for (i = 0; i < nc; i++) {
835 int planeSize = tjPlaneSizeYUV(i, scaledWidth, dstStrides[i], scaledHeight,
836 jpegSubsamp);
837 int pw = tjPlaneWidth(i, scaledWidth, jpegSubsamp);
838
839 if (planeSize < 0 || pw < 0) {
840 RELEASE_ARRAYS_DECOMPRESSTOYUV();
841 THROW_ARG(tjGetErrorStr());
842 }
843
844 if (dstOffsets[i] < 0) {
845 RELEASE_ARRAYS_DECOMPRESSTOYUV();
846 THROW_ARG("Invalid argument in decompressToYUV()");
847 }
848 if (dstStrides[i] < 0 && dstOffsets[i] - planeSize + pw < 0) {
849 RELEASE_ARRAYS_DECOMPRESSTOYUV();
850 THROW_ARG("Negative plane stride would cause memory to be accessed below plane boundary");
851 }
852
853 BAILIF0(jDstPlanes[i] = (*env)->GetObjectArrayElement(env, dstobjs, i));
854 if ((*env)->GetArrayLength(env, jDstPlanes[i]) <
855 dstOffsets[i] + planeSize) {
856 RELEASE_ARRAYS_DECOMPRESSTOYUV();
857 THROW_ARG("Destination plane is not large enough");
858 }
859
860 BAILIF0(dstPlanes[i] =
861 (*env)->GetPrimitiveArrayCritical(env, jDstPlanes[i], 0));
862 dstPlanes[i] = &dstPlanes[i][dstOffsets[i]];
863 }
864 BAILIF0(jpegBuf = (*env)->GetPrimitiveArrayCritical(env, src, 0));
865
866 if (tjDecompressToYUVPlanes(handle, jpegBuf, (unsigned long)jpegSize,
867 dstPlanes, desiredWidth, dstStrides,
868 desiredHeight, flags) == -1) {
869 RELEASE_ARRAYS_DECOMPRESSTOYUV();
870 THROW_TJ();
871 }
872
873 bailout:
874 RELEASE_ARRAYS_DECOMPRESSTOYUV();
875 }
876
877 /* TurboJPEG 1.2.x: TJDecompressor::decompressToYUV() */
Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompressToYUV___3BI_3BI(JNIEnv * env,jobject obj,jbyteArray src,jint jpegSize,jbyteArray dst,jint flags)878 JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompressToYUV___3BI_3BI
879 (JNIEnv *env, jobject obj, jbyteArray src, jint jpegSize, jbyteArray dst,
880 jint flags)
881 {
882 tjhandle handle = 0;
883 unsigned char *jpegBuf = NULL, *dstBuf = NULL;
884 int jpegSubsamp = -1, jpegWidth = 0, jpegHeight = 0;
885
886 GET_HANDLE();
887
888 if ((*env)->GetArrayLength(env, src) < jpegSize)
889 THROW_ARG("Source buffer is not large enough");
890 BAILIF0(_fid = (*env)->GetFieldID(env, _cls, "jpegSubsamp", "I"));
891 jpegSubsamp = (int)(*env)->GetIntField(env, obj, _fid);
892 BAILIF0(_fid = (*env)->GetFieldID(env, _cls, "jpegWidth", "I"));
893 jpegWidth = (int)(*env)->GetIntField(env, obj, _fid);
894 BAILIF0(_fid = (*env)->GetFieldID(env, _cls, "jpegHeight", "I"));
895 jpegHeight = (int)(*env)->GetIntField(env, obj, _fid);
896 if ((*env)->GetArrayLength(env, dst) <
897 (jsize)tjBufSizeYUV(jpegWidth, jpegHeight, jpegSubsamp))
898 THROW_ARG("Destination buffer is not large enough");
899
900 BAILIF0(jpegBuf = (*env)->GetPrimitiveArrayCritical(env, src, 0));
901 BAILIF0(dstBuf = (*env)->GetPrimitiveArrayCritical(env, dst, 0));
902
903 if (tjDecompressToYUV(handle, jpegBuf, (unsigned long)jpegSize, dstBuf,
904 flags) == -1) {
905 SAFE_RELEASE(dst, dstBuf);
906 SAFE_RELEASE(src, jpegBuf);
907 THROW_TJ();
908 }
909
910 bailout:
911 SAFE_RELEASE(dst, dstBuf);
912 SAFE_RELEASE(src, jpegBuf);
913 }
914
TJDecompressor_decodeYUV(JNIEnv * env,jobject obj,jobjectArray srcobjs,jintArray jSrcOffsets,jintArray jSrcStrides,jint subsamp,jarray dst,jint dstElementSize,jint x,jint y,jint width,jint pitch,jint height,jint pf,jint flags)915 static void TJDecompressor_decodeYUV
916 (JNIEnv *env, jobject obj, jobjectArray srcobjs, jintArray jSrcOffsets,
917 jintArray jSrcStrides, jint subsamp, jarray dst, jint dstElementSize,
918 jint x, jint y, jint width, jint pitch, jint height, jint pf, jint flags)
919 {
920 tjhandle handle = 0;
921 jsize arraySize = 0, actualPitch;
922 jbyteArray jSrcPlanes[3] = { NULL, NULL, NULL };
923 const unsigned char *srcPlanes[3];
924 unsigned char *dstBuf = NULL;
925 int *srcOffsets = NULL, *srcStrides = NULL;
926 int nc = (subsamp == org_libjpegturbo_turbojpeg_TJ_SAMP_GRAY ? 1 : 3), i;
927
928 GET_HANDLE();
929
930 if (pf < 0 || pf >= org_libjpegturbo_turbojpeg_TJ_NUMPF || subsamp < 0 ||
931 subsamp >= org_libjpegturbo_turbojpeg_TJ_NUMSAMP)
932 THROW_ARG("Invalid argument in decodeYUV()");
933 if (org_libjpegturbo_turbojpeg_TJ_NUMPF != TJ_NUMPF ||
934 org_libjpegturbo_turbojpeg_TJ_NUMSAMP != TJ_NUMSAMP)
935 THROW_ARG("Mismatch between Java and C API");
936
937 if ((*env)->GetArrayLength(env, srcobjs) < nc)
938 THROW_ARG("Planes array is too small for the subsampling type");
939 if ((*env)->GetArrayLength(env, jSrcOffsets) < nc)
940 THROW_ARG("Offsets array is too small for the subsampling type");
941 if ((*env)->GetArrayLength(env, jSrcStrides) < nc)
942 THROW_ARG("Strides array is too small for the subsampling type");
943
944 actualPitch = (pitch == 0) ? width * tjPixelSize[pf] : pitch;
945 arraySize = (y + height - 1) * actualPitch + (x + width) * tjPixelSize[pf];
946 if ((*env)->GetArrayLength(env, dst) * dstElementSize < arraySize)
947 THROW_ARG("Destination buffer is not large enough");
948
949 #define RELEASE_ARRAYS_DECODEYUV() { \
950 SAFE_RELEASE(dst, dstBuf); \
951 for (i = 0; i < nc; i++) \
952 SAFE_RELEASE(jSrcPlanes[i], srcPlanes[i]); \
953 SAFE_RELEASE(jSrcStrides, srcStrides); \
954 SAFE_RELEASE(jSrcOffsets, srcOffsets); \
955 }
956
957 BAILIF0(srcOffsets = (*env)->GetPrimitiveArrayCritical(env, jSrcOffsets, 0));
958 BAILIF0(srcStrides = (*env)->GetPrimitiveArrayCritical(env, jSrcStrides, 0));
959 for (i = 0; i < nc; i++) {
960 int planeSize = tjPlaneSizeYUV(i, width, srcStrides[i], height, subsamp);
961 int pw = tjPlaneWidth(i, width, subsamp);
962
963 if (planeSize < 0 || pw < 0) {
964 RELEASE_ARRAYS_DECODEYUV();
965 THROW_ARG(tjGetErrorStr());
966 }
967
968 if (srcOffsets[i] < 0) {
969 RELEASE_ARRAYS_DECODEYUV();
970 THROW_ARG("Invalid argument in decodeYUV()");
971 }
972 if (srcStrides[i] < 0 && srcOffsets[i] - planeSize + pw < 0) {
973 RELEASE_ARRAYS_DECODEYUV();
974 THROW_ARG("Negative plane stride would cause memory to be accessed below plane boundary");
975 }
976
977 BAILIF0(jSrcPlanes[i] = (*env)->GetObjectArrayElement(env, srcobjs, i));
978 if ((*env)->GetArrayLength(env, jSrcPlanes[i]) <
979 srcOffsets[i] + planeSize) {
980 RELEASE_ARRAYS_DECODEYUV();
981 THROW_ARG("Source plane is not large enough");
982 }
983
984 BAILIF0(srcPlanes[i] =
985 (*env)->GetPrimitiveArrayCritical(env, jSrcPlanes[i], 0));
986 srcPlanes[i] = &srcPlanes[i][srcOffsets[i]];
987 }
988 BAILIF0(dstBuf = (*env)->GetPrimitiveArrayCritical(env, dst, 0));
989
990 if (tjDecodeYUVPlanes(handle, srcPlanes, srcStrides, subsamp,
991 &dstBuf[y * actualPitch + x * tjPixelSize[pf]], width,
992 pitch, height, pf, flags) == -1) {
993 RELEASE_ARRAYS_DECODEYUV();
994 THROW_TJ();
995 }
996
997 bailout:
998 RELEASE_ARRAYS_DECODEYUV();
999 }
1000
1001 /* TurboJPEG 1.4.x: TJDecompressor::decodeYUV() byte destination */
Java_org_libjpegturbo_turbojpeg_TJDecompressor_decodeYUV___3_3B_3I_3II_3BIIIIIII(JNIEnv * env,jobject obj,jobjectArray srcobjs,jintArray jSrcOffsets,jintArray jSrcStrides,jint subsamp,jbyteArray dst,jint x,jint y,jint width,jint pitch,jint height,jint pf,jint flags)1002 JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decodeYUV___3_3B_3I_3II_3BIIIIIII
1003 (JNIEnv *env, jobject obj, jobjectArray srcobjs, jintArray jSrcOffsets,
1004 jintArray jSrcStrides, jint subsamp, jbyteArray dst, jint x, jint y,
1005 jint width, jint pitch, jint height, jint pf, jint flags)
1006 {
1007 TJDecompressor_decodeYUV(env, obj, srcobjs, jSrcOffsets, jSrcStrides,
1008 subsamp, dst, 1, x, y, width, pitch, height, pf,
1009 flags);
1010 }
1011
1012 /* TurboJPEG 1.4.x: TJDecompressor::decodeYUV() int destination */
Java_org_libjpegturbo_turbojpeg_TJDecompressor_decodeYUV___3_3B_3I_3II_3IIIIIIII(JNIEnv * env,jobject obj,jobjectArray srcobjs,jintArray jSrcOffsets,jintArray jSrcStrides,jint subsamp,jintArray dst,jint x,jint y,jint width,jint stride,jint height,jint pf,jint flags)1013 JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decodeYUV___3_3B_3I_3II_3IIIIIIII
1014 (JNIEnv *env, jobject obj, jobjectArray srcobjs, jintArray jSrcOffsets,
1015 jintArray jSrcStrides, jint subsamp, jintArray dst, jint x, jint y,
1016 jint width, jint stride, jint height, jint pf, jint flags)
1017 {
1018 if (pf < 0 || pf >= org_libjpegturbo_turbojpeg_TJ_NUMPF)
1019 THROW_ARG("Invalid argument in decodeYUV()");
1020 if (tjPixelSize[pf] != sizeof(jint))
1021 THROW_ARG("Pixel format must be 32-bit when decoding to an integer buffer.");
1022
1023 TJDecompressor_decodeYUV(env, obj, srcobjs, jSrcOffsets, jSrcStrides,
1024 subsamp, dst, sizeof(jint), x, y, width,
1025 stride * sizeof(jint), height, pf, flags);
1026
1027 bailout:
1028 return;
1029 }
1030
1031 /* TurboJPEG 1.2.x: TJTransformer::init() */
Java_org_libjpegturbo_turbojpeg_TJTransformer_init(JNIEnv * env,jobject obj)1032 JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJTransformer_init
1033 (JNIEnv *env, jobject obj)
1034 {
1035 jclass cls;
1036 jfieldID fid;
1037 tjhandle handle;
1038
1039 if ((handle = tjInitTransform()) == NULL)
1040 THROW(tjGetErrorStr(), "org/libjpegturbo/turbojpeg/TJException");
1041
1042 BAILIF0(cls = (*env)->GetObjectClass(env, obj));
1043 BAILIF0(fid = (*env)->GetFieldID(env, cls, "handle", "J"));
1044 (*env)->SetLongField(env, obj, fid, (size_t)handle);
1045
1046 bailout:
1047 return;
1048 }
1049
1050 typedef struct _JNICustomFilterParams {
1051 JNIEnv *env;
1052 jobject tobj;
1053 jobject cfobj;
1054 } JNICustomFilterParams;
1055
JNICustomFilter(short * coeffs,tjregion arrayRegion,tjregion planeRegion,int componentIndex,int transformIndex,tjtransform * transform)1056 static int JNICustomFilter(short *coeffs, tjregion arrayRegion,
1057 tjregion planeRegion, int componentIndex,
1058 int transformIndex, tjtransform *transform)
1059 {
1060 JNICustomFilterParams *params = (JNICustomFilterParams *)transform->data;
1061 JNIEnv *env = params->env;
1062 jobject tobj = params->tobj, cfobj = params->cfobj;
1063 jobject arrayRegionObj, planeRegionObj, bufobj, borobj;
1064 jclass cls;
1065 jmethodID mid;
1066 jfieldID fid;
1067
1068 BAILIF0(bufobj = (*env)->NewDirectByteBuffer(env, coeffs,
1069 sizeof(short) * arrayRegion.w * arrayRegion.h));
1070 BAILIF0(cls = (*env)->FindClass(env, "java/nio/ByteOrder"));
1071 BAILIF0(mid = (*env)->GetStaticMethodID(env, cls, "nativeOrder",
1072 "()Ljava/nio/ByteOrder;"));
1073 BAILIF0(borobj = (*env)->CallStaticObjectMethod(env, cls, mid));
1074 BAILIF0(cls = (*env)->GetObjectClass(env, bufobj));
1075 BAILIF0(mid = (*env)->GetMethodID(env, cls, "order",
1076 "(Ljava/nio/ByteOrder;)Ljava/nio/ByteBuffer;"));
1077 (*env)->CallObjectMethod(env, bufobj, mid, borobj);
1078 BAILIF0(mid = (*env)->GetMethodID(env, cls, "asShortBuffer",
1079 "()Ljava/nio/ShortBuffer;"));
1080 BAILIF0(bufobj = (*env)->CallObjectMethod(env, bufobj, mid));
1081
1082 BAILIF0(cls = (*env)->FindClass(env, "java/awt/Rectangle"));
1083 BAILIF0(arrayRegionObj = (*env)->AllocObject(env, cls));
1084 BAILIF0(fid = (*env)->GetFieldID(env, cls, "x", "I"));
1085 (*env)->SetIntField(env, arrayRegionObj, fid, arrayRegion.x);
1086 BAILIF0(fid = (*env)->GetFieldID(env, cls, "y", "I"));
1087 (*env)->SetIntField(env, arrayRegionObj, fid, arrayRegion.y);
1088 BAILIF0(fid = (*env)->GetFieldID(env, cls, "width", "I"));
1089 (*env)->SetIntField(env, arrayRegionObj, fid, arrayRegion.w);
1090 BAILIF0(fid = (*env)->GetFieldID(env, cls, "height", "I"));
1091 (*env)->SetIntField(env, arrayRegionObj, fid, arrayRegion.h);
1092
1093 BAILIF0(planeRegionObj = (*env)->AllocObject(env, cls));
1094 BAILIF0(fid = (*env)->GetFieldID(env, cls, "x", "I"));
1095 (*env)->SetIntField(env, planeRegionObj, fid, planeRegion.x);
1096 BAILIF0(fid = (*env)->GetFieldID(env, cls, "y", "I"));
1097 (*env)->SetIntField(env, planeRegionObj, fid, planeRegion.y);
1098 BAILIF0(fid = (*env)->GetFieldID(env, cls, "width", "I"));
1099 (*env)->SetIntField(env, planeRegionObj, fid, planeRegion.w);
1100 BAILIF0(fid = (*env)->GetFieldID(env, cls, "height", "I"));
1101 (*env)->SetIntField(env, planeRegionObj, fid, planeRegion.h);
1102
1103 BAILIF0(cls = (*env)->GetObjectClass(env, cfobj));
1104 BAILIF0(mid = (*env)->GetMethodID(env, cls, "customFilter",
1105 "(Ljava/nio/ShortBuffer;Ljava/awt/Rectangle;Ljava/awt/Rectangle;IILorg/libjpegturbo/turbojpeg/TJTransform;)V"));
1106 (*env)->CallVoidMethod(env, cfobj, mid, bufobj, arrayRegionObj,
1107 planeRegionObj, componentIndex, transformIndex, tobj);
1108
1109 return 0;
1110
1111 bailout:
1112 return -1;
1113 }
1114
1115 /* TurboJPEG 1.2.x: TJTransformer::transform() */
Java_org_libjpegturbo_turbojpeg_TJTransformer_transform(JNIEnv * env,jobject obj,jbyteArray jsrcBuf,jint jpegSize,jobjectArray dstobjs,jobjectArray tobjs,jint flags)1116 JNIEXPORT jintArray JNICALL Java_org_libjpegturbo_turbojpeg_TJTransformer_transform
1117 (JNIEnv *env, jobject obj, jbyteArray jsrcBuf, jint jpegSize,
1118 jobjectArray dstobjs, jobjectArray tobjs, jint flags)
1119 {
1120 tjhandle handle = 0;
1121 unsigned char *jpegBuf = NULL, **dstBufs = NULL;
1122 jsize n = 0;
1123 unsigned long *dstSizes = NULL;
1124 tjtransform *t = NULL;
1125 jbyteArray *jdstBufs = NULL;
1126 int i, jpegWidth = 0, jpegHeight = 0, jpegSubsamp;
1127 jintArray jdstSizes = 0;
1128 jint *dstSizesi = NULL;
1129 JNICustomFilterParams *params = NULL;
1130
1131 GET_HANDLE();
1132
1133 if ((*env)->GetArrayLength(env, jsrcBuf) < jpegSize)
1134 THROW_ARG("Source buffer is not large enough");
1135 BAILIF0(_fid = (*env)->GetFieldID(env, _cls, "jpegWidth", "I"));
1136 jpegWidth = (int)(*env)->GetIntField(env, obj, _fid);
1137 BAILIF0(_fid = (*env)->GetFieldID(env, _cls, "jpegHeight", "I"));
1138 jpegHeight = (int)(*env)->GetIntField(env, obj, _fid);
1139 BAILIF0(_fid = (*env)->GetFieldID(env, _cls, "jpegSubsamp", "I"));
1140 jpegSubsamp = (int)(*env)->GetIntField(env, obj, _fid);
1141
1142 n = (*env)->GetArrayLength(env, dstobjs);
1143 if (n != (*env)->GetArrayLength(env, tobjs))
1144 THROW_ARG("Mismatch between size of transforms array and destination buffers array");
1145
1146 if ((dstBufs =
1147 (unsigned char **)malloc(sizeof(unsigned char *) * n)) == NULL)
1148 THROW_MEM();
1149 if ((jdstBufs = (jbyteArray *)malloc(sizeof(jbyteArray) * n)) == NULL)
1150 THROW_MEM();
1151 if ((dstSizes = (unsigned long *)malloc(sizeof(unsigned long) * n)) == NULL)
1152 THROW_MEM();
1153 if ((t = (tjtransform *)malloc(sizeof(tjtransform) * n)) == NULL)
1154 THROW_MEM();
1155 if ((params = (JNICustomFilterParams *)malloc(sizeof(JNICustomFilterParams) *
1156 n)) == NULL)
1157 THROW_MEM();
1158 for (i = 0; i < n; i++) {
1159 dstBufs[i] = NULL; jdstBufs[i] = NULL; dstSizes[i] = 0;
1160 memset(&t[i], 0, sizeof(tjtransform));
1161 memset(¶ms[i], 0, sizeof(JNICustomFilterParams));
1162 }
1163
1164 for (i = 0; i < n; i++) {
1165 jobject tobj, cfobj;
1166
1167 BAILIF0(tobj = (*env)->GetObjectArrayElement(env, tobjs, i));
1168 BAILIF0(_cls = (*env)->GetObjectClass(env, tobj));
1169 BAILIF0(_fid = (*env)->GetFieldID(env, _cls, "op", "I"));
1170 t[i].op = (*env)->GetIntField(env, tobj, _fid);
1171 BAILIF0(_fid = (*env)->GetFieldID(env, _cls, "options", "I"));
1172 t[i].options = (*env)->GetIntField(env, tobj, _fid);
1173 BAILIF0(_fid = (*env)->GetFieldID(env, _cls, "x", "I"));
1174 t[i].r.x = (*env)->GetIntField(env, tobj, _fid);
1175 BAILIF0(_fid = (*env)->GetFieldID(env, _cls, "y", "I"));
1176 t[i].r.y = (*env)->GetIntField(env, tobj, _fid);
1177 BAILIF0(_fid = (*env)->GetFieldID(env, _cls, "width", "I"));
1178 t[i].r.w = (*env)->GetIntField(env, tobj, _fid);
1179 BAILIF0(_fid = (*env)->GetFieldID(env, _cls, "height", "I"));
1180 t[i].r.h = (*env)->GetIntField(env, tobj, _fid);
1181
1182 BAILIF0(_fid = (*env)->GetFieldID(env, _cls, "cf",
1183 "Lorg/libjpegturbo/turbojpeg/TJCustomFilter;"));
1184 cfobj = (*env)->GetObjectField(env, tobj, _fid);
1185 if (cfobj) {
1186 params[i].env = env;
1187 params[i].tobj = tobj;
1188 params[i].cfobj = cfobj;
1189 t[i].customFilter = JNICustomFilter;
1190 t[i].data = (void *)¶ms[i];
1191 }
1192 }
1193
1194 for (i = 0; i < n; i++) {
1195 int w = jpegWidth, h = jpegHeight;
1196
1197 if (t[i].r.w != 0) w = t[i].r.w;
1198 if (t[i].r.h != 0) h = t[i].r.h;
1199 BAILIF0(jdstBufs[i] = (*env)->GetObjectArrayElement(env, dstobjs, i));
1200 if ((unsigned long)(*env)->GetArrayLength(env, jdstBufs[i]) <
1201 tjBufSize(w, h, jpegSubsamp))
1202 THROW_ARG("Destination buffer is not large enough");
1203 }
1204 BAILIF0(jpegBuf = (*env)->GetPrimitiveArrayCritical(env, jsrcBuf, 0));
1205 for (i = 0; i < n; i++)
1206 BAILIF0(dstBufs[i] =
1207 (*env)->GetPrimitiveArrayCritical(env, jdstBufs[i], 0));
1208
1209 if (tjTransform(handle, jpegBuf, jpegSize, n, dstBufs, dstSizes, t,
1210 flags | TJFLAG_NOREALLOC) == -1) {
1211 for (i = 0; i < n; i++)
1212 SAFE_RELEASE(jdstBufs[i], dstBufs[i]);
1213 SAFE_RELEASE(jsrcBuf, jpegBuf);
1214 THROW_TJ();
1215 }
1216
1217 for (i = 0; i < n; i++)
1218 SAFE_RELEASE(jdstBufs[i], dstBufs[i]);
1219 SAFE_RELEASE(jsrcBuf, jpegBuf);
1220
1221 jdstSizes = (*env)->NewIntArray(env, n);
1222 BAILIF0(dstSizesi = (*env)->GetIntArrayElements(env, jdstSizes, 0));
1223 for (i = 0; i < n; i++) dstSizesi[i] = (int)dstSizes[i];
1224
1225 bailout:
1226 if (dstSizesi) (*env)->ReleaseIntArrayElements(env, jdstSizes, dstSizesi, 0);
1227 if (dstBufs) {
1228 for (i = 0; i < n; i++) {
1229 if (dstBufs[i] && jdstBufs && jdstBufs[i])
1230 (*env)->ReleasePrimitiveArrayCritical(env, jdstBufs[i], dstBufs[i], 0);
1231 }
1232 free(dstBufs);
1233 }
1234 SAFE_RELEASE(jsrcBuf, jpegBuf);
1235 if (jdstBufs) free(jdstBufs);
1236 if (dstSizes) free(dstSizes);
1237 if (t) free(t);
1238 return jdstSizes;
1239 }
1240
1241 /* TurboJPEG 1.2.x: TJDecompressor::destroy() */
Java_org_libjpegturbo_turbojpeg_TJDecompressor_destroy(JNIEnv * env,jobject obj)1242 JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_destroy
1243 (JNIEnv *env, jobject obj)
1244 {
1245 Java_org_libjpegturbo_turbojpeg_TJCompressor_destroy(env, obj);
1246 }
1247