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