blob: 1bf478f11e8f282b958d5466119354dcec85affc [file] [log] [blame]
DRCf8e00552011-02-04 11:06:36 +00001/*
DRCfc26b652014-03-16 22:56:26 +00002 * Copyright (C)2011-2014 D. R. Commander. All Rights Reserved.
DRCf8e00552011-02-04 11:06:36 +00003 *
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
DRCe8573012011-03-04 10:13:59 +000029#include <stdlib.h>
30#include <string.h>
DRCf8e00552011-02-04 11:06:36 +000031#include "turbojpeg.h"
DRCbc2e66c2012-10-02 06:47:37 +000032#ifdef WIN32
33#include "tjutil.h"
34#endif
DRCf8e00552011-02-04 11:06:36 +000035#include <jni.h>
DRCc5a41992011-02-08 06:54:36 +000036#include "java/org_libjpegturbo_turbojpeg_TJCompressor.h"
37#include "java/org_libjpegturbo_turbojpeg_TJDecompressor.h"
38#include "java/org_libjpegturbo_turbojpeg_TJ.h"
DRCf8e00552011-02-04 11:06:36 +000039
DRC40dd3142014-08-17 12:23:49 +000040#define PAD(v, p) ((v+(p)-1)&(~((p)-1)))
41
DRCf8e00552011-02-04 11:06:36 +000042#define _throw(msg) { \
43 jclass _exccls=(*env)->FindClass(env, "java/lang/Exception"); \
44 if(!_exccls) goto bailout; \
45 (*env)->ThrowNew(env, _exccls, msg); \
46 goto bailout; \
47}
48
DRCfac3bea2012-09-24 02:27:55 +000049#define bailif0(f) {if(!(f)) { \
50 char temps[80]; \
51 snprintf(temps, 80, "Unexpected NULL condition in line %d", __LINE__); \
52 _throw(temps); \
53}}
DRCf8e00552011-02-04 11:06:36 +000054
DRC3bad53f2011-02-23 02:20:49 +000055#define gethandle() \
DRCf8e00552011-02-04 11:06:36 +000056 jclass _cls=(*env)->GetObjectClass(env, obj); \
57 jfieldID _fid; \
58 if(!_cls) goto bailout; \
59 bailif0(_fid=(*env)->GetFieldID(env, _cls, "handle", "J")); \
DRC46a03922014-08-15 14:40:05 +000060 handle=(tjhandle)(size_t)(*env)->GetLongField(env, obj, _fid); \
DRCf8e00552011-02-04 11:06:36 +000061
DRCbdb36e12014-08-22 15:39:32 +000062#ifdef _WIN32
63#define setenv(envvar, value, dummy) _putenv_s(envvar, value)
64#endif
65
DRC0713c1b2014-08-22 13:43:33 +000066#define prop2env(property, envvar) \
67{ \
68 if((jName=(*env)->NewStringUTF(env, property))!=NULL \
69 && (jValue=(*env)->CallStaticObjectMethod(env, cls, mid, jName))!=NULL) \
70 { \
71 if((value=(*env)->GetStringUTFChars(env, jValue, 0))!=NULL) \
72 { \
73 setenv(envvar, value, 1); \
74 (*env)->ReleaseStringUTFChars(env, jValue, value); \
75 } \
76 } \
77}
78
79int ProcessSystemProperties(JNIEnv *env)
80{
81 jclass cls; jmethodID mid;
82 jstring jName, jValue;
83 const char *value;
84
85 bailif0(cls=(*env)->FindClass(env, "java/lang/System"));
86 bailif0(mid=(*env)->GetStaticMethodID(env, cls, "getProperty",
87 "(Ljava/lang/String;)Ljava/lang/String;"));
88
89 prop2env("turbojpeg.optimize", "TJ_OPTIMIZE");
90 prop2env("turbojpeg.arithmetic", "TJ_ARITHMETIC");
91 prop2env("turbojpeg.restart", "TJ_RESTART");
92 prop2env("turbojpeg.progressive", "TJ_PROGRESSIVE");
93 return 0;
94
95 bailout:
96 return -1;
97}
98
DRCa4940d12014-08-15 16:07:15 +000099/* TurboJPEG 1.2.x: TJ::bufSize() */
DRC3bad53f2011-02-23 02:20:49 +0000100JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJ_bufSize
DRC9b49f0e2011-07-12 03:17:23 +0000101 (JNIEnv *env, jclass cls, jint width, jint height, jint jpegSubsamp)
DRCf8e00552011-02-04 11:06:36 +0000102{
DRC9b49f0e2011-07-12 03:17:23 +0000103 jint retval=(jint)tjBufSize(width, height, jpegSubsamp);
DRC36336fc2011-02-22 10:27:31 +0000104 if(retval==-1) _throw(tjGetErrorStr());
105
106 bailout:
107 return retval;
108}
109
DRCa4940d12014-08-15 16:07:15 +0000110/* TurboJPEG 1.4.x: TJ::bufSizeYUV() */
DRCfef98522013-04-28 01:32:52 +0000111JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJ_bufSizeYUV__IIII
112 (JNIEnv *env, jclass cls, jint width, jint pad, jint height, jint subsamp)
DRC36336fc2011-02-22 10:27:31 +0000113{
DRCfef98522013-04-28 01:32:52 +0000114 jint retval=(jint)tjBufSizeYUV2(width, pad, height, subsamp);
DRC36336fc2011-02-22 10:27:31 +0000115 if(retval==-1) _throw(tjGetErrorStr());
116
117 bailout:
118 return retval;
DRCf8e00552011-02-04 11:06:36 +0000119}
120
DRCa4940d12014-08-15 16:07:15 +0000121/* TurboJPEG 1.2.x: TJ::bufSizeYUV() */
DRCfef98522013-04-28 01:32:52 +0000122JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJ_bufSizeYUV__III
123 (JNIEnv *env, jclass cls, jint width, jint height, jint subsamp)
124{
125 return Java_org_libjpegturbo_turbojpeg_TJ_bufSizeYUV__IIII(env, cls, width,
126 4, height, subsamp);
127}
128
DRC40dd3142014-08-17 12:23:49 +0000129/* TurboJPEG 1.4.x: TJ::planeSizeYUV() */
130JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJ_planeSizeYUV__IIIII
131 (JNIEnv *env, jclass cls, jint componentID, jint width, jint stride,
132 jint height, jint subsamp)
133{
134 jint retval=(jint)tjPlaneSizeYUV(componentID, width, stride, height,
135 subsamp);
136 if(retval==-1) _throw(tjGetErrorStr());
137
138 bailout:
139 return retval;
140}
141
142/* TurboJPEG 1.4.x: TJ::planeWidth() */
143JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJ_planeWidth__III
144 (JNIEnv *env, jclass cls, jint componentID, jint width, jint subsamp)
145{
146 jint retval=(jint)tjPlaneWidth(componentID, width, subsamp);
147 if(retval==-1) _throw(tjGetErrorStr());
148
149 bailout:
150 return retval;
151}
152
153/* TurboJPEG 1.4.x: TJ::planeHeight() */
154JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJ_planeHeight__III
155 (JNIEnv *env, jclass cls, jint componentID, jint height, jint subsamp)
156{
157 jint retval=(jint)tjPlaneHeight(componentID, height, subsamp);
158 if(retval==-1) _throw(tjGetErrorStr());
159
160 bailout:
161 return retval;
162}
163
DRCa4940d12014-08-15 16:07:15 +0000164/* TurboJPEG 1.2.x: TJCompressor::init() */
DRCc5a41992011-02-08 06:54:36 +0000165JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_init
DRCf8e00552011-02-04 11:06:36 +0000166 (JNIEnv *env, jobject obj)
167{
168 jclass cls;
169 jfieldID fid;
170 tjhandle handle;
171
DRC1a3dbe62011-02-28 10:51:55 +0000172 if((handle=tjInitCompress())==NULL)
DRCf8e00552011-02-04 11:06:36 +0000173 _throw(tjGetErrorStr());
174
175 bailif0(cls=(*env)->GetObjectClass(env, obj));
176 bailif0(fid=(*env)->GetFieldID(env, cls, "handle", "J"));
DRC46a03922014-08-15 14:40:05 +0000177 (*env)->SetLongField(env, obj, fid, (size_t)handle);
DRCf8e00552011-02-04 11:06:36 +0000178
179 bailout:
180 return;
181}
182
DRC5d87f6d2014-08-15 16:40:56 +0000183static jint TJCompressor_compress
DRC927a10d2014-08-15 13:18:58 +0000184 (JNIEnv *env, jobject obj, jarray src, jint srcElementSize, jint x, jint y,
185 jint width, jint pitch, jint height, jint pf, jbyteArray dst,
186 jint jpegSubsamp, jint jpegQual, jint flags)
DRCf8e00552011-02-04 11:06:36 +0000187{
DRC9b28def2011-05-21 14:37:15 +0000188 tjhandle handle=0;
DRCfac3bea2012-09-24 02:27:55 +0000189 unsigned long jpegSize=0;
190 jsize arraySize=0, actualPitch;
DRC9b28def2011-05-21 14:37:15 +0000191 unsigned char *srcBuf=NULL, *jpegBuf=NULL;
DRCf8e00552011-02-04 11:06:36 +0000192
193 gethandle();
194
DRC92549de2011-03-15 20:52:02 +0000195 if(pf<0 || pf>=org_libjpegturbo_turbojpeg_TJ_NUMPF || width<1 || height<1
DRC6acf52b2011-03-02 01:09:20 +0000196 || pitch<0)
DRC4f1580c2011-02-25 06:11:03 +0000197 _throw("Invalid argument in compress()");
DRC9b28def2011-05-21 14:37:15 +0000198 if(org_libjpegturbo_turbojpeg_TJ_NUMPF!=TJ_NUMPF)
199 _throw("Mismatch between Java and C API");
DRC4f1580c2011-02-25 06:11:03 +0000200
DRCfac3bea2012-09-24 02:27:55 +0000201 actualPitch=(pitch==0)? width*tjPixelSize[pf]:pitch;
DRC927a10d2014-08-15 13:18:58 +0000202 arraySize=(y+height-1)*actualPitch + (x+width)*tjPixelSize[pf];
203 if((*env)->GetArrayLength(env, src)*srcElementSize<arraySize)
DRC6acf52b2011-03-02 01:09:20 +0000204 _throw("Source buffer is not large enough");
DRC9b49f0e2011-07-12 03:17:23 +0000205 jpegSize=tjBufSize(width, height, jpegSubsamp);
DRC9b28def2011-05-21 14:37:15 +0000206 if((*env)->GetArrayLength(env, dst)<(jsize)jpegSize)
DRC6acf52b2011-03-02 01:09:20 +0000207 _throw("Destination buffer is not large enough");
208
DRC9b28def2011-05-21 14:37:15 +0000209 bailif0(srcBuf=(*env)->GetPrimitiveArrayCritical(env, src, 0));
210 bailif0(jpegBuf=(*env)->GetPrimitiveArrayCritical(env, dst, 0));
DRCf8e00552011-02-04 11:06:36 +0000211
DRC0713c1b2014-08-22 13:43:33 +0000212 if(ProcessSystemProperties(env)<0) goto bailout;
213
DRCfac3bea2012-09-24 02:27:55 +0000214 if(tjCompress2(handle, &srcBuf[y*actualPitch + x*tjPixelSize[pf]], width,
215 pitch, height, pf, &jpegBuf, &jpegSize, jpegSubsamp, jpegQual,
216 flags|TJFLAG_NOREALLOC)==-1)
DRCfac3bea2012-09-24 02:27:55 +0000217 _throw(tjGetErrorStr());
DRCfac3bea2012-09-24 02:27:55 +0000218
219 bailout:
220 if(jpegBuf) (*env)->ReleasePrimitiveArrayCritical(env, dst, jpegBuf, 0);
221 if(srcBuf) (*env)->ReleasePrimitiveArrayCritical(env, src, srcBuf, 0);
222 return (jint)jpegSize;
223}
224
DRCa4940d12014-08-15 16:07:15 +0000225/* TurboJPEG 1.3.x: TJCompressor::compress() byte source */
DRC927a10d2014-08-15 13:18:58 +0000226JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_compress___3BIIIIII_3BIII
227 (JNIEnv *env, jobject obj, jbyteArray src, jint x, jint y, jint width,
228 jint pitch, jint height, jint pf, jbyteArray dst, jint jpegSubsamp,
229 jint jpegQual, jint flags)
230{
231 return TJCompressor_compress(env, obj, src, 1, x, y, width, pitch, height,
232 pf, dst, jpegSubsamp, jpegQual, flags);
233}
234
DRCa4940d12014-08-15 16:07:15 +0000235/* TurboJPEG 1.2.x: TJCompressor::compress() byte source */
DRCfac3bea2012-09-24 02:27:55 +0000236JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_compress___3BIIII_3BIII
237 (JNIEnv *env, jobject obj, jbyteArray src, jint width, jint pitch,
238 jint height, jint pf, jbyteArray dst, jint jpegSubsamp, jint jpegQual,
239 jint flags)
240{
DRC927a10d2014-08-15 13:18:58 +0000241 return TJCompressor_compress(env, obj, src, 1, 0, 0, width, pitch, height,
242 pf, dst, jpegSubsamp, jpegQual, flags);
DRCfac3bea2012-09-24 02:27:55 +0000243}
244
DRCa4940d12014-08-15 16:07:15 +0000245/* TurboJPEG 1.3.x: TJCompressor::compress() int source */
DRCfac3bea2012-09-24 02:27:55 +0000246JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_compress___3IIIIIII_3BIII
247 (JNIEnv *env, jobject obj, jintArray src, jint x, jint y, jint width,
248 jint stride, jint height, jint pf, jbyteArray dst, jint jpegSubsamp,
249 jint jpegQual, jint flags)
250{
DRC927a10d2014-08-15 13:18:58 +0000251 if(pf<0 || pf>=org_libjpegturbo_turbojpeg_TJ_NUMPF)
DRCfac3bea2012-09-24 02:27:55 +0000252 _throw("Invalid argument in compress()");
DRCfac3bea2012-09-24 02:27:55 +0000253 if(tjPixelSize[pf]!=sizeof(jint))
254 _throw("Pixel format must be 32-bit when compressing from an integer buffer.");
255
DRC927a10d2014-08-15 13:18:58 +0000256 return TJCompressor_compress(env, obj, src, sizeof(jint), x, y, width,
257 stride*sizeof(jint), height, pf, dst, jpegSubsamp, jpegQual, flags);
DRCf8e00552011-02-04 11:06:36 +0000258
259 bailout:
DRC927a10d2014-08-15 13:18:58 +0000260 return 0;
DRCf8e00552011-02-04 11:06:36 +0000261}
262
DRCa4940d12014-08-15 16:07:15 +0000263/* TurboJPEG 1.2.x: TJCompressor::compress() int source */
DRC4f1580c2011-02-25 06:11:03 +0000264JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_compress___3IIIII_3BIII
DRC927a10d2014-08-15 13:18:58 +0000265 (JNIEnv *env, jobject obj, jintArray src, jint width, jint stride,
DRC9b28def2011-05-21 14:37:15 +0000266 jint height, jint pf, jbyteArray dst, jint jpegSubsamp, jint jpegQual,
DRC4f1580c2011-02-25 06:11:03 +0000267 jint flags)
DRC84a1bcc2011-02-23 12:09:56 +0000268{
DRC927a10d2014-08-15 13:18:58 +0000269 if(pf<0 || pf>=org_libjpegturbo_turbojpeg_TJ_NUMPF)
270 _throw("Invalid argument in compress()");
271 if(tjPixelSize[pf]!=sizeof(jint))
272 _throw("Pixel format must be 32-bit when compressing from an integer buffer.");
273
274 return TJCompressor_compress(env, obj, src, sizeof(jint), 0, 0, width,
275 stride*sizeof(jint), height, pf, dst, jpegSubsamp, jpegQual, flags);
276
277 bailout:
278 return 0;
DRC84a1bcc2011-02-23 12:09:56 +0000279}
280
DRCa4940d12014-08-15 16:07:15 +0000281/* TurboJPEG 1.4.x: TJCompressor::compressFromYUV() */
DRC40dd3142014-08-17 12:23:49 +0000282JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_compressFromYUV___3_3B_3II_3III_3BII
283 (JNIEnv *env, jobject obj, jobjectArray srcobjs, jintArray jSrcOffsets,
284 jint width, jintArray jSrcStrides, jint height, jint subsamp,
285 jbyteArray dst, jint jpegQual, jint flags)
DRC1e672742013-10-31 05:04:51 +0000286{
287 tjhandle handle=0;
288 unsigned long jpegSize=0;
DRC40dd3142014-08-17 12:23:49 +0000289 jbyteArray jSrcPlanes[3]={NULL, NULL, NULL};
290 unsigned char *srcPlanes[3], *jpegBuf=NULL;
291 int *srcOffsets=NULL, *srcStrides=NULL;
292 int nc=(subsamp==org_libjpegturbo_turbojpeg_TJ_SAMP_GRAY? 1:3), i;
DRC1e672742013-10-31 05:04:51 +0000293
294 gethandle();
295
DRC40dd3142014-08-17 12:23:49 +0000296 if(subsamp<0 || subsamp>=org_libjpegturbo_turbojpeg_TJ_NUMSAMP)
297 _throw("Invalid argument in compressFromYUV()");
298 if(org_libjpegturbo_turbojpeg_TJ_NUMSAMP!=TJ_NUMSAMP)
299 _throw("Mismatch between Java and C API");
300
301 if((*env)->GetArrayLength(env, srcobjs)<nc)
302 _throw("Planes array is too small for the subsampling type");
303 if((*env)->GetArrayLength(env, jSrcOffsets)<nc)
304 _throw("Offsets array is too small for the subsampling type");
305 if((*env)->GetArrayLength(env, jSrcStrides)<nc)
306 _throw("Strides array is too small for the subsampling type");
307
DRC1e672742013-10-31 05:04:51 +0000308 jpegSize=tjBufSize(width, height, subsamp);
309 if((*env)->GetArrayLength(env, dst)<(jsize)jpegSize)
310 _throw("Destination buffer is not large enough");
311
DRC40dd3142014-08-17 12:23:49 +0000312 bailif0(srcOffsets=(*env)->GetPrimitiveArrayCritical(env, jSrcOffsets, 0));
313 bailif0(srcStrides=(*env)->GetPrimitiveArrayCritical(env, jSrcStrides, 0));
314 for(i=0; i<nc; i++)
315 {
316 int planeSize=tjPlaneSizeYUV(i, width, srcStrides[i], height, subsamp);
317 int pw=tjPlaneWidth(i, width, subsamp);
318
319 if(planeSize<0 || pw<0)
320 _throw(tjGetErrorStr());
321
322 if(srcOffsets[i]<0)
323 _throw("Invalid argument in compressFromYUV()");
324 if(srcStrides[i]<0 && srcOffsets[i]-planeSize+pw<0)
325 _throw("Negative plane stride would cause memory to be accessed below plane boundary");
326
327 bailif0(jSrcPlanes[i]=(*env)->GetObjectArrayElement(env, srcobjs, i));
328 if((*env)->GetArrayLength(env, jSrcPlanes[i])<srcOffsets[i]+planeSize)
329 _throw("Source plane is not large enough");
330
331 bailif0(srcPlanes[i]=(*env)->GetPrimitiveArrayCritical(env, jSrcPlanes[i],
332 0));
333 srcPlanes[i]=&srcPlanes[i][srcOffsets[i]];
334 }
DRC1e672742013-10-31 05:04:51 +0000335 bailif0(jpegBuf=(*env)->GetPrimitiveArrayCritical(env, dst, 0));
336
DRC0713c1b2014-08-22 13:43:33 +0000337 if(ProcessSystemProperties(env)<0) goto bailout;
338
DRC40dd3142014-08-17 12:23:49 +0000339 if(tjCompressFromYUVPlanes(handle, srcPlanes, width, srcStrides, height,
340 subsamp, &jpegBuf, &jpegSize, jpegQual, flags|TJFLAG_NOREALLOC)==-1)
DRC1e672742013-10-31 05:04:51 +0000341 _throw(tjGetErrorStr());
DRC1e672742013-10-31 05:04:51 +0000342
343 bailout:
344 if(jpegBuf) (*env)->ReleasePrimitiveArrayCritical(env, dst, jpegBuf, 0);
DRC40dd3142014-08-17 12:23:49 +0000345 for(i=0; i<nc; i++)
346 {
347 if(srcPlanes[i] && jSrcPlanes[i])
348 (*env)->ReleasePrimitiveArrayCritical(env, jSrcPlanes[i], srcPlanes[i],
349 0);
350 }
351 if(srcStrides)
352 (*env)->ReleasePrimitiveArrayCritical(env, jSrcStrides, srcStrides, 0);
353 if(srcOffsets)
354 (*env)->ReleasePrimitiveArrayCritical(env, jSrcOffsets, srcOffsets, 0);
DRC1e672742013-10-31 05:04:51 +0000355 return (jint)jpegSize;
356}
357
DRC5d87f6d2014-08-15 16:40:56 +0000358static void TJCompressor_encodeYUV
DRC927a10d2014-08-15 13:18:58 +0000359 (JNIEnv *env, jobject obj, jarray src, jint srcElementSize, jint x, jint y,
DRC40dd3142014-08-17 12:23:49 +0000360 jint width, jint pitch, jint height, jint pf, jobjectArray dstobjs,
361 jintArray jDstOffsets, jintArray jDstStrides, jint subsamp, jint flags)
DRC4f1580c2011-02-25 06:11:03 +0000362{
DRC9b28def2011-05-21 14:37:15 +0000363 tjhandle handle=0;
DRC40dd3142014-08-17 12:23:49 +0000364 jsize arraySize=0, actualPitch;
365 jbyteArray jDstPlanes[3]={NULL, NULL, NULL};
366 unsigned char *srcBuf=NULL, *dstPlanes[3];
367 int *dstOffsets=NULL, *dstStrides=NULL;
368 int nc=(subsamp==org_libjpegturbo_turbojpeg_TJ_SAMP_GRAY? 1:3), i;
369
370 gethandle();
371
372 if(pf<0 || pf>=org_libjpegturbo_turbojpeg_TJ_NUMPF || width<1 || height<1
373 || pitch<0 || subsamp<0 || subsamp>=org_libjpegturbo_turbojpeg_TJ_NUMSAMP)
374 _throw("Invalid argument in encodeYUV()");
375 if(org_libjpegturbo_turbojpeg_TJ_NUMPF!=TJ_NUMPF
376 || org_libjpegturbo_turbojpeg_TJ_NUMSAMP!=TJ_NUMSAMP)
377 _throw("Mismatch between Java and C API");
378
379 if((*env)->GetArrayLength(env, dstobjs)<nc)
380 _throw("Planes array is too small for the subsampling type");
381 if((*env)->GetArrayLength(env, jDstOffsets)<nc)
382 _throw("Offsets array is too small for the subsampling type");
383 if((*env)->GetArrayLength(env, jDstStrides)<nc)
384 _throw("Strides array is too small for the subsampling type");
385
386 actualPitch=(pitch==0)? width*tjPixelSize[pf]:pitch;
387 arraySize=(y+height-1)*actualPitch + (x+width)*tjPixelSize[pf];
388 if((*env)->GetArrayLength(env, src)*srcElementSize<arraySize)
389 _throw("Source buffer is not large enough");
390
391 bailif0(dstOffsets=(*env)->GetPrimitiveArrayCritical(env, jDstOffsets, 0));
392 bailif0(dstStrides=(*env)->GetPrimitiveArrayCritical(env, jDstStrides, 0));
393 for(i=0; i<nc; i++)
394 {
395 int planeSize=tjPlaneSizeYUV(i, width, dstStrides[i], height, subsamp);
396 int pw=tjPlaneWidth(i, width, subsamp);
397
398 if(planeSize<0 || pw<0)
399 _throw(tjGetErrorStr());
400
401 if(dstOffsets[i]<0)
402 _throw("Invalid argument in encodeYUV()");
403 if(dstStrides[i]<0 && dstOffsets[i]-planeSize+pw<0)
404 _throw("Negative plane stride would cause memory to be accessed below plane boundary");
405
406 bailif0(jDstPlanes[i]=(*env)->GetObjectArrayElement(env, dstobjs, i));
407 if((*env)->GetArrayLength(env, jDstPlanes[i])<dstOffsets[i]+planeSize)
408 _throw("Destination plane is not large enough");
409
410 bailif0(dstPlanes[i]=(*env)->GetPrimitiveArrayCritical(env, jDstPlanes[i],
411 0));
412 dstPlanes[i]=&dstPlanes[i][dstOffsets[i]];
413 }
414 bailif0(srcBuf=(*env)->GetPrimitiveArrayCritical(env, src, 0));
415
416 if(tjEncodeYUVPlanes(handle, &srcBuf[y*actualPitch + x*tjPixelSize[pf]],
417 width, pitch, height, pf, dstPlanes, dstStrides, subsamp, flags)==-1)
418 _throw(tjGetErrorStr());
419
420 bailout:
421 if(srcBuf) (*env)->ReleasePrimitiveArrayCritical(env, src, srcBuf, 0);
422 for(i=0; i<nc; i++)
423 {
424 if(dstPlanes[i] && jDstPlanes[i])
425 (*env)->ReleasePrimitiveArrayCritical(env, jDstPlanes[i], dstPlanes[i],
426 0);
427 }
428 if(dstStrides)
429 (*env)->ReleasePrimitiveArrayCritical(env, jDstStrides, dstStrides, 0);
430 if(dstOffsets)
431 (*env)->ReleasePrimitiveArrayCritical(env, jDstOffsets, dstOffsets, 0);
432 return;
433}
434
435/* TurboJPEG 1.4.x: TJCompressor::encodeYUV() byte source */
436JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_encodeYUV___3BIIIIII_3_3B_3I_3III
437 (JNIEnv *env, jobject obj, jbyteArray src, jint x, jint y, jint width,
438 jint pitch, jint height, jint pf, jobjectArray dstobjs,
439 jintArray jDstOffsets, jintArray jDstStrides, jint subsamp, jint flags)
440{
441 TJCompressor_encodeYUV(env, obj, src, 1, x, y, width, pitch, height, pf,
442 dstobjs, jDstOffsets, jDstStrides, subsamp, flags);
443}
444
445/* TurboJPEG 1.4.x: TJCompressor::encodeYUV() int source */
446JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_encodeYUV___3IIIIIII_3_3B_3I_3III
447 (JNIEnv *env, jobject obj, jintArray src, jint x, jint y, jint width,
448 jint stride, jint height, jint pf, jobjectArray dstobjs,
449 jintArray jDstOffsets, jintArray jDstStrides, jint subsamp, jint flags)
450{
451 if(pf<0 || pf>=org_libjpegturbo_turbojpeg_TJ_NUMPF)
452 _throw("Invalid argument in encodeYUV()");
453 if(tjPixelSize[pf]!=sizeof(jint))
454 _throw("Pixel format must be 32-bit when encoding from an integer buffer.");
455
456 TJCompressor_encodeYUV(env, obj, src, sizeof(jint), x, y, width,
457 stride*sizeof(jint), height, pf, dstobjs, jDstOffsets, jDstStrides,
458 subsamp, flags);
459
460 bailout:
461 return;
462}
463
464JNIEXPORT void JNICALL TJCompressor_encodeYUV_12
465 (JNIEnv *env, jobject obj, jarray src, jint srcElementSize, jint width,
466 jint pitch, jint height, jint pf, jbyteArray dst, jint subsamp, jint flags)
467{
468 tjhandle handle=0;
469 jsize arraySize=0;
DRC9b28def2011-05-21 14:37:15 +0000470 unsigned char *srcBuf=NULL, *dstBuf=NULL;
DRC4f1580c2011-02-25 06:11:03 +0000471
472 gethandle();
473
DRC92549de2011-03-15 20:52:02 +0000474 if(pf<0 || pf>=org_libjpegturbo_turbojpeg_TJ_NUMPF || width<1 || height<1
DRC6acf52b2011-03-02 01:09:20 +0000475 || pitch<0)
DRC4f1580c2011-02-25 06:11:03 +0000476 _throw("Invalid argument in encodeYUV()");
DRC9b28def2011-05-21 14:37:15 +0000477 if(org_libjpegturbo_turbojpeg_TJ_NUMPF!=TJ_NUMPF)
478 _throw("Mismatch between Java and C API");
DRC4f1580c2011-02-25 06:11:03 +0000479
DRC40dd3142014-08-17 12:23:49 +0000480 arraySize=(pitch==0)? width*tjPixelSize[pf]*height:pitch*height;
DRC927a10d2014-08-15 13:18:58 +0000481 if((*env)->GetArrayLength(env, src)*srcElementSize<arraySize)
DRC6acf52b2011-03-02 01:09:20 +0000482 _throw("Source buffer is not large enough");
DRC40dd3142014-08-17 12:23:49 +0000483 if((*env)->GetArrayLength(env, dst)
484 <(jsize)tjBufSizeYUV(width, height, subsamp))
DRC6acf52b2011-03-02 01:09:20 +0000485 _throw("Destination buffer is not large enough");
486
DRC9b28def2011-05-21 14:37:15 +0000487 bailif0(srcBuf=(*env)->GetPrimitiveArrayCritical(env, src, 0));
488 bailif0(dstBuf=(*env)->GetPrimitiveArrayCritical(env, dst, 0));
DRC4f1580c2011-02-25 06:11:03 +0000489
DRC40dd3142014-08-17 12:23:49 +0000490 if(tjEncodeYUV2(handle, srcBuf, width, pitch, height, pf, dstBuf, subsamp,
491 flags)==-1)
DRC4f1580c2011-02-25 06:11:03 +0000492 _throw(tjGetErrorStr());
DRC4f1580c2011-02-25 06:11:03 +0000493
494 bailout:
DRC9b28def2011-05-21 14:37:15 +0000495 if(dstBuf) (*env)->ReleasePrimitiveArrayCritical(env, dst, dstBuf, 0);
496 if(srcBuf) (*env)->ReleasePrimitiveArrayCritical(env, src, srcBuf, 0);
DRC4f1580c2011-02-25 06:11:03 +0000497 return;
498}
499
DRCa4940d12014-08-15 16:07:15 +0000500/* TurboJPEG 1.2.x: TJCompressor::encodeYUV() byte source */
DRCfef98522013-04-28 01:32:52 +0000501JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_encodeYUV___3BIIII_3BII
502 (JNIEnv *env, jobject obj, jbyteArray src, jint width, jint pitch,
DRC6acf52b2011-03-02 01:09:20 +0000503 jint height, jint pf, jbyteArray dst, jint subsamp, jint flags)
DRC4f1580c2011-02-25 06:11:03 +0000504{
DRC40dd3142014-08-17 12:23:49 +0000505 TJCompressor_encodeYUV_12(env, obj, src, 1, width, pitch, height, pf, dst,
506 subsamp, flags);
DRC4f1580c2011-02-25 06:11:03 +0000507}
508
DRCa4940d12014-08-15 16:07:15 +0000509/* TurboJPEG 1.2.x: TJCompressor::encodeYUV() int source */
DRCfef98522013-04-28 01:32:52 +0000510JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_encodeYUV___3IIIII_3BII
DRC927a10d2014-08-15 13:18:58 +0000511 (JNIEnv *env, jobject obj, jintArray src, jint width, jint stride,
DRCfef98522013-04-28 01:32:52 +0000512 jint height, jint pf, jbyteArray dst, jint subsamp, jint flags)
513{
DRC927a10d2014-08-15 13:18:58 +0000514 if(pf<0 || pf>=org_libjpegturbo_turbojpeg_TJ_NUMPF)
515 _throw("Invalid argument in encodeYUV()");
516 if(tjPixelSize[pf]!=sizeof(jint))
517 _throw("Pixel format must be 32-bit when encoding from an integer buffer.");
518
DRC40dd3142014-08-17 12:23:49 +0000519 TJCompressor_encodeYUV_12(env, obj, src, sizeof(jint), width,
520 stride*sizeof(jint), height, pf, dst, subsamp, flags);
DRC927a10d2014-08-15 13:18:58 +0000521
522 bailout:
523 return;
DRCfef98522013-04-28 01:32:52 +0000524}
525
DRCa4940d12014-08-15 16:07:15 +0000526/* TurboJPEG 1.2.x: TJCompressor::destroy() */
DRCc5a41992011-02-08 06:54:36 +0000527JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_destroy
DRCf8e00552011-02-04 11:06:36 +0000528 (JNIEnv *env, jobject obj)
529{
530 tjhandle handle=0;
531
532 gethandle();
533
534 if(tjDestroy(handle)==-1) _throw(tjGetErrorStr());
DRC3bad53f2011-02-23 02:20:49 +0000535 (*env)->SetLongField(env, obj, _fid, 0);
DRCf8e00552011-02-04 11:06:36 +0000536
537 bailout:
538 return;
539}
540
DRCa4940d12014-08-15 16:07:15 +0000541/* TurboJPEG 1.2.x: TJDecompressor::init() */
DRCc5a41992011-02-08 06:54:36 +0000542JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_init
DRCf8e00552011-02-04 11:06:36 +0000543 (JNIEnv *env, jobject obj)
544{
545 jclass cls;
546 jfieldID fid;
547 tjhandle handle;
548
DRC1a3dbe62011-02-28 10:51:55 +0000549 if((handle=tjInitDecompress())==NULL) _throw(tjGetErrorStr());
DRCf8e00552011-02-04 11:06:36 +0000550
551 bailif0(cls=(*env)->GetObjectClass(env, obj));
552 bailif0(fid=(*env)->GetFieldID(env, cls, "handle", "J"));
DRC46a03922014-08-15 14:40:05 +0000553 (*env)->SetLongField(env, obj, fid, (size_t)handle);
DRCf8e00552011-02-04 11:06:36 +0000554
555 bailout:
556 return;
557}
558
DRCa4940d12014-08-15 16:07:15 +0000559/* TurboJPEG 1.2.x: TJDecompressor::getScalingFactors() */
DRC109a5782011-03-01 09:53:07 +0000560JNIEXPORT jobjectArray JNICALL Java_org_libjpegturbo_turbojpeg_TJ_getScalingFactors
561 (JNIEnv *env, jclass cls)
DRC36336fc2011-02-22 10:27:31 +0000562{
DRCb7c8c862014-08-15 16:20:59 +0000563 jclass sfcls=NULL; jfieldID fid=0;
DRC109a5782011-03-01 09:53:07 +0000564 tjscalingfactor *sf=NULL; int n=0, i;
565 jobject sfobj=NULL;
566 jobjectArray sfjava=NULL;
567
568 if((sf=tjGetScalingFactors(&n))==NULL || n==0)
DRC36336fc2011-02-22 10:27:31 +0000569 _throw(tjGetErrorStr());
570
DRCb2f94152011-04-02 02:09:03 +0000571 bailif0(sfcls=(*env)->FindClass(env, "org/libjpegturbo/turbojpeg/TJScalingFactor"));
DRC109a5782011-03-01 09:53:07 +0000572 bailif0(sfjava=(jobjectArray)(*env)->NewObjectArray(env, n, sfcls, 0));
DRC36336fc2011-02-22 10:27:31 +0000573
DRC109a5782011-03-01 09:53:07 +0000574 for(i=0; i<n; i++)
575 {
576 bailif0(sfobj=(*env)->AllocObject(env, sfcls));
577 bailif0(fid=(*env)->GetFieldID(env, sfcls, "num", "I"));
578 (*env)->SetIntField(env, sfobj, fid, sf[i].num);
579 bailif0(fid=(*env)->GetFieldID(env, sfcls, "denom", "I"));
580 (*env)->SetIntField(env, sfobj, fid, sf[i].denom);
581 (*env)->SetObjectArrayElement(env, sfjava, i, sfobj);
582 }
DRC36336fc2011-02-22 10:27:31 +0000583
584 bailout:
DRC109a5782011-03-01 09:53:07 +0000585 return sfjava;
DRC36336fc2011-02-22 10:27:31 +0000586}
587
DRCa4940d12014-08-15 16:07:15 +0000588/* TurboJPEG 1.2.x: TJDecompressor::decompressHeader() */
DRC3bad53f2011-02-23 02:20:49 +0000589JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompressHeader
DRC9b28def2011-05-21 14:37:15 +0000590 (JNIEnv *env, jobject obj, jbyteArray src, jint jpegSize)
DRCf8e00552011-02-04 11:06:36 +0000591{
DRCf8e00552011-02-04 11:06:36 +0000592 tjhandle handle=0;
DRC9b28def2011-05-21 14:37:15 +0000593 unsigned char *jpegBuf=NULL;
DRC38cb1ec2013-08-23 04:45:43 +0000594 int width=0, height=0, jpegSubsamp=-1, jpegColorspace=-1;
DRCf8e00552011-02-04 11:06:36 +0000595
596 gethandle();
597
DRC9b28def2011-05-21 14:37:15 +0000598 if((*env)->GetArrayLength(env, src)<jpegSize)
DRC6acf52b2011-03-02 01:09:20 +0000599 _throw("Source buffer is not large enough");
600
DRC9b28def2011-05-21 14:37:15 +0000601 bailif0(jpegBuf=(*env)->GetPrimitiveArrayCritical(env, src, 0));
DRCf8e00552011-02-04 11:06:36 +0000602
DRC1a45b812014-05-09 18:06:58 +0000603 if(tjDecompressHeader3(handle, jpegBuf, (unsigned long)jpegSize,
DRC38cb1ec2013-08-23 04:45:43 +0000604 &width, &height, &jpegSubsamp, &jpegColorspace)==-1)
DRCf8e00552011-02-04 11:06:36 +0000605 _throw(tjGetErrorStr());
DRC8951cf02014-08-14 16:54:04 +0000606
DRC9b28def2011-05-21 14:37:15 +0000607 (*env)->ReleasePrimitiveArrayCritical(env, src, jpegBuf, 0); jpegBuf=NULL;
DRCf8e00552011-02-04 11:06:36 +0000608
DRC26dd86b2014-08-15 14:01:21 +0000609 bailif0(_fid=(*env)->GetFieldID(env, _cls, "jpegSubsamp", "I"));
DRC9b28def2011-05-21 14:37:15 +0000610 (*env)->SetIntField(env, obj, _fid, jpegSubsamp);
DRC26dd86b2014-08-15 14:01:21 +0000611 if((_fid=(*env)->GetFieldID(env, _cls, "jpegColorspace", "I"))==0)
612 (*env)->ExceptionClear(env);
613 else
614 (*env)->SetIntField(env, obj, _fid, jpegColorspace);
615 bailif0(_fid=(*env)->GetFieldID(env, _cls, "jpegWidth", "I"));
DRC3bad53f2011-02-23 02:20:49 +0000616 (*env)->SetIntField(env, obj, _fid, width);
DRC26dd86b2014-08-15 14:01:21 +0000617 bailif0(_fid=(*env)->GetFieldID(env, _cls, "jpegHeight", "I"));
DRC3bad53f2011-02-23 02:20:49 +0000618 (*env)->SetIntField(env, obj, _fid, height);
DRCf8e00552011-02-04 11:06:36 +0000619
620 bailout:
DRC8951cf02014-08-14 16:54:04 +0000621 if(jpegBuf) (*env)->ReleasePrimitiveArrayCritical(env, src, jpegBuf, 0);
DRC3bad53f2011-02-23 02:20:49 +0000622 return;
DRCf8e00552011-02-04 11:06:36 +0000623}
624
DRC5d87f6d2014-08-15 16:40:56 +0000625static void TJDecompressor_decompress
DRC927a10d2014-08-15 13:18:58 +0000626 (JNIEnv *env, jobject obj, jbyteArray src, jint jpegSize, jarray dst,
627 jint dstElementSize, jint x, jint y, jint width, jint pitch, jint height,
628 jint pf, jint flags)
DRCf8e00552011-02-04 11:06:36 +0000629{
DRC9b28def2011-05-21 14:37:15 +0000630 tjhandle handle=0;
DRCf659f432012-06-06 08:41:06 +0000631 jsize arraySize=0, actualPitch;
DRC9b28def2011-05-21 14:37:15 +0000632 unsigned char *jpegBuf=NULL, *dstBuf=NULL;
DRCf8e00552011-02-04 11:06:36 +0000633
634 gethandle();
635
DRC92549de2011-03-15 20:52:02 +0000636 if(pf<0 || pf>=org_libjpegturbo_turbojpeg_TJ_NUMPF)
DRC4f1580c2011-02-25 06:11:03 +0000637 _throw("Invalid argument in decompress()");
DRC9b28def2011-05-21 14:37:15 +0000638 if(org_libjpegturbo_turbojpeg_TJ_NUMPF!=TJ_NUMPF)
639 _throw("Mismatch between Java and C API");
DRC4f1580c2011-02-25 06:11:03 +0000640
DRC9b28def2011-05-21 14:37:15 +0000641 if((*env)->GetArrayLength(env, src)<jpegSize)
DRC6acf52b2011-03-02 01:09:20 +0000642 _throw("Source buffer is not large enough");
DRCf659f432012-06-06 08:41:06 +0000643 actualPitch=(pitch==0)? width*tjPixelSize[pf]:pitch;
DRCdc31f0b2012-06-07 09:38:57 +0000644 arraySize=(y+height-1)*actualPitch + (x+width)*tjPixelSize[pf];
DRC927a10d2014-08-15 13:18:58 +0000645 if((*env)->GetArrayLength(env, dst)*dstElementSize<arraySize)
DRC6acf52b2011-03-02 01:09:20 +0000646 _throw("Destination buffer is not large enough");
647
DRC9b28def2011-05-21 14:37:15 +0000648 bailif0(jpegBuf=(*env)->GetPrimitiveArrayCritical(env, src, 0));
649 bailif0(dstBuf=(*env)->GetPrimitiveArrayCritical(env, dst, 0));
DRCf8e00552011-02-04 11:06:36 +0000650
DRCf659f432012-06-06 08:41:06 +0000651 if(tjDecompress2(handle, jpegBuf, (unsigned long)jpegSize,
652 &dstBuf[y*actualPitch + x*tjPixelSize[pf]], width, pitch, height, pf,
653 flags)==-1)
DRCf659f432012-06-06 08:41:06 +0000654 _throw(tjGetErrorStr());
DRCf659f432012-06-06 08:41:06 +0000655
656 bailout:
657 if(dstBuf) (*env)->ReleasePrimitiveArrayCritical(env, dst, dstBuf, 0);
658 if(jpegBuf) (*env)->ReleasePrimitiveArrayCritical(env, src, jpegBuf, 0);
659 return;
660}
661
DRCa4940d12014-08-15 16:07:15 +0000662/* TurboJPEG 1.3.x: TJDecompressor::decompress() byte destination */
DRC927a10d2014-08-15 13:18:58 +0000663JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompress___3BI_3BIIIIIII
664 (JNIEnv *env, jobject obj, jbyteArray src, jint jpegSize, jbyteArray dst,
665 jint x, jint y, jint width, jint pitch, jint height, jint pf, jint flags)
666{
667 TJDecompressor_decompress(env, obj, src, jpegSize, dst, 1, x, y, width,
668 pitch, height, pf, flags);
669}
670
DRCa4940d12014-08-15 16:07:15 +0000671/* TurboJPEG 1.2.x: TJDecompressor::decompress() byte destination */
DRCf659f432012-06-06 08:41:06 +0000672JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompress___3BI_3BIIIII
673 (JNIEnv *env, jobject obj, jbyteArray src, jint jpegSize, jbyteArray dst,
674 jint width, jint pitch, jint height, jint pf, jint flags)
675{
DRC927a10d2014-08-15 13:18:58 +0000676 TJDecompressor_decompress(env, obj, src, jpegSize, dst, 1, 0, 0, width,
677 pitch, height, pf, flags);
DRCf659f432012-06-06 08:41:06 +0000678}
679
DRCa4940d12014-08-15 16:07:15 +0000680/* TurboJPEG 1.3.x: TJDecompressor::decompress() int destination */
DRCf659f432012-06-06 08:41:06 +0000681JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompress___3BI_3IIIIIIII
682 (JNIEnv *env, jobject obj, jbyteArray src, jint jpegSize, jintArray dst,
683 jint x, jint y, jint width, jint stride, jint height, jint pf, jint flags)
684{
DRCf659f432012-06-06 08:41:06 +0000685 if(pf<0 || pf>=org_libjpegturbo_turbojpeg_TJ_NUMPF)
686 _throw("Invalid argument in decompress()");
DRCf659f432012-06-06 08:41:06 +0000687 if(tjPixelSize[pf]!=sizeof(jint))
688 _throw("Pixel format must be 32-bit when decompressing to an integer buffer.");
689
DRC927a10d2014-08-15 13:18:58 +0000690 TJDecompressor_decompress(env, obj, src, jpegSize, dst, sizeof(jint), x, y,
691 width, stride*sizeof(jint), height, pf, flags);
DRCf8e00552011-02-04 11:06:36 +0000692
693 bailout:
DRCf8e00552011-02-04 11:06:36 +0000694 return;
695}
696
DRCa4940d12014-08-15 16:07:15 +0000697/* TurboJPEG 1.2.x: TJDecompressor::decompress() int destination */
DRC4f1580c2011-02-25 06:11:03 +0000698JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompress___3BI_3IIIIII
DRC9b28def2011-05-21 14:37:15 +0000699 (JNIEnv *env, jobject obj, jbyteArray src, jint jpegSize, jintArray dst,
DRCf659f432012-06-06 08:41:06 +0000700 jint width, jint stride, jint height, jint pf, jint flags)
DRC84a1bcc2011-02-23 12:09:56 +0000701{
DRC927a10d2014-08-15 13:18:58 +0000702 if(pf<0 || pf>=org_libjpegturbo_turbojpeg_TJ_NUMPF)
703 _throw("Invalid argument in decompress()");
704 if(tjPixelSize[pf]!=sizeof(jint))
705 _throw("Pixel format must be 32-bit when decompressing to an integer buffer.");
706
707 TJDecompressor_decompress(env, obj, src, jpegSize, dst, sizeof(jint), 0, 0,
708 width, stride*sizeof(jint), height, pf, flags);
709
710 bailout:
711 return;
DRC1a45b812014-05-09 18:06:58 +0000712
DRC4f1580c2011-02-25 06:11:03 +0000713}
DRC84a1bcc2011-02-23 12:09:56 +0000714
DRCa4940d12014-08-15 16:07:15 +0000715/* TurboJPEG 1.4.x: TJDecompressor::decompressToYUV() */
DRC40dd3142014-08-17 12:23:49 +0000716JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompressToYUV___3BI_3_3B_3II_3III
717 (JNIEnv *env, jobject obj, jbyteArray src, jint jpegSize,
718 jobjectArray dstobjs, jintArray jDstOffsets, jint desiredWidth,
719 jintArray jDstStrides, jint desiredHeight, jint flags)
DRC4f1580c2011-02-25 06:11:03 +0000720{
721 tjhandle handle=0;
DRC40dd3142014-08-17 12:23:49 +0000722 jbyteArray jDstPlanes[3]={NULL, NULL, NULL};
723 unsigned char *jpegBuf=NULL, *dstPlanes[3];
724 int *dstOffsets=NULL, *dstStrides=NULL;
DRC6acf52b2011-03-02 01:09:20 +0000725 int jpegSubsamp=-1, jpegWidth=0, jpegHeight=0;
DRC40dd3142014-08-17 12:23:49 +0000726 int nc=0, i, width, height, scaledWidth, scaledHeight, nsf=0;
727 tjscalingfactor *sf;
728
DRC4f1580c2011-02-25 06:11:03 +0000729
730 gethandle();
731
DRC9b28def2011-05-21 14:37:15 +0000732 if((*env)->GetArrayLength(env, src)<jpegSize)
DRC6acf52b2011-03-02 01:09:20 +0000733 _throw("Source buffer is not large enough");
DRC26dd86b2014-08-15 14:01:21 +0000734 bailif0(_fid=(*env)->GetFieldID(env, _cls, "jpegSubsamp", "I"));
DRC6acf52b2011-03-02 01:09:20 +0000735 jpegSubsamp=(int)(*env)->GetIntField(env, obj, _fid);
DRC26dd86b2014-08-15 14:01:21 +0000736 bailif0(_fid=(*env)->GetFieldID(env, _cls, "jpegWidth", "I"));
DRC6acf52b2011-03-02 01:09:20 +0000737 jpegWidth=(int)(*env)->GetIntField(env, obj, _fid);
DRC26dd86b2014-08-15 14:01:21 +0000738 bailif0(_fid=(*env)->GetFieldID(env, _cls, "jpegHeight", "I"));
DRC6acf52b2011-03-02 01:09:20 +0000739 jpegHeight=(int)(*env)->GetIntField(env, obj, _fid);
DRC6acf52b2011-03-02 01:09:20 +0000740
DRC40dd3142014-08-17 12:23:49 +0000741 nc=(jpegSubsamp==org_libjpegturbo_turbojpeg_TJ_SAMP_GRAY? 1:3);
DRC4f1580c2011-02-25 06:11:03 +0000742
DRC40dd3142014-08-17 12:23:49 +0000743 width=desiredWidth; height=desiredHeight;
744 if(width==0) width=jpegWidth;
745 if(height==0) height=jpegHeight;
746 sf=tjGetScalingFactors(&nsf);
747 if(!sf || nsf<1)
748 _throw(tjGetErrorStr());
749 for(i=0; i<nsf; i++)
750 {
751 scaledWidth=TJSCALED(jpegWidth, sf[i]);
752 scaledHeight=TJSCALED(jpegHeight, sf[i]);
753 if(scaledWidth<=width && scaledHeight<=height)
754 break;
755 }
756
757 bailif0(dstOffsets=(*env)->GetPrimitiveArrayCritical(env, jDstOffsets, 0));
758 bailif0(dstStrides=(*env)->GetPrimitiveArrayCritical(env, jDstStrides, 0));
759 for(i=0; i<nc; i++)
760 {
761 int planeSize=tjPlaneSizeYUV(i, scaledWidth, dstStrides[i], scaledHeight,
762 jpegSubsamp);
763 int pw=tjPlaneWidth(i, scaledWidth, jpegSubsamp);
764
765 if(planeSize<0 || pw<0)
766 _throw(tjGetErrorStr());
767
768 if(dstOffsets[i]<0)
769 _throw("Invalid argument in decompressToYUV()");
770 if(dstStrides[i]<0 && dstOffsets[i]-planeSize+pw<0)
771 _throw("Negative plane stride would cause memory to be accessed below plane boundary");
772
773 bailif0(jDstPlanes[i]=(*env)->GetObjectArrayElement(env, dstobjs, i));
774 if((*env)->GetArrayLength(env, jDstPlanes[i])<dstOffsets[i]+planeSize)
775 _throw("Destination plane is not large enough");
776
777 bailif0(dstPlanes[i]=(*env)->GetPrimitiveArrayCritical(env, jDstPlanes[i],
778 0));
779 dstPlanes[i]=&dstPlanes[i][dstOffsets[i]];
780 }
781 bailif0(jpegBuf=(*env)->GetPrimitiveArrayCritical(env, src, 0));
782
783 if(tjDecompressToYUVPlanes(handle, jpegBuf, (unsigned long)jpegSize,
784 dstPlanes, desiredWidth, dstStrides, desiredHeight, flags)==-1)
DRC4f1580c2011-02-25 06:11:03 +0000785 _throw(tjGetErrorStr());
DRC4f1580c2011-02-25 06:11:03 +0000786
787 bailout:
DRC9b28def2011-05-21 14:37:15 +0000788 if(jpegBuf) (*env)->ReleasePrimitiveArrayCritical(env, src, jpegBuf, 0);
DRC40dd3142014-08-17 12:23:49 +0000789 for(i=0; i<nc; i++)
790 {
791 if(dstPlanes[i] && jDstPlanes[i])
792 (*env)->ReleasePrimitiveArrayCritical(env, jDstPlanes[i], dstPlanes[i],
793 0);
794 }
795 if(dstStrides)
796 (*env)->ReleasePrimitiveArrayCritical(env, jDstStrides, dstStrides, 0);
797 if(dstOffsets)
798 (*env)->ReleasePrimitiveArrayCritical(env, jDstOffsets, dstOffsets, 0);
DRC4f1580c2011-02-25 06:11:03 +0000799 return;
DRC84a1bcc2011-02-23 12:09:56 +0000800}
801
DRCa4940d12014-08-15 16:07:15 +0000802/* TurboJPEG 1.2.x: TJDecompressor::decompressToYUV() */
DRCfef98522013-04-28 01:32:52 +0000803JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompressToYUV___3BI_3BI
804 (JNIEnv *env, jobject obj, jbyteArray src, jint jpegSize, jbyteArray dst,
805 jint flags)
806{
DRCfc26b652014-03-16 22:56:26 +0000807 tjhandle handle=0;
DRC40dd3142014-08-17 12:23:49 +0000808 unsigned char *jpegBuf=NULL, *dstBuf=NULL;
809 int jpegSubsamp=-1, jpegWidth=0, jpegHeight=0;
DRCfc26b652014-03-16 22:56:26 +0000810
811 gethandle();
812
DRC40dd3142014-08-17 12:23:49 +0000813 if((*env)->GetArrayLength(env, src)<jpegSize)
814 _throw("Source buffer is not large enough");
815 bailif0(_fid=(*env)->GetFieldID(env, _cls, "jpegSubsamp", "I"));
816 jpegSubsamp=(int)(*env)->GetIntField(env, obj, _fid);
817 bailif0(_fid=(*env)->GetFieldID(env, _cls, "jpegWidth", "I"));
818 jpegWidth=(int)(*env)->GetIntField(env, obj, _fid);
819 bailif0(_fid=(*env)->GetFieldID(env, _cls, "jpegHeight", "I"));
820 jpegHeight=(int)(*env)->GetIntField(env, obj, _fid);
821 if((*env)->GetArrayLength(env, dst)
822 <(jsize)tjBufSizeYUV(jpegWidth, jpegHeight, jpegSubsamp))
823 _throw("Destination buffer is not large enough");
824
825 bailif0(jpegBuf=(*env)->GetPrimitiveArrayCritical(env, src, 0));
826 bailif0(dstBuf=(*env)->GetPrimitiveArrayCritical(env, dst, 0));
827
828 if(tjDecompressToYUV(handle, jpegBuf, (unsigned long)jpegSize, dstBuf,
829 flags)==-1)
830 _throw(tjGetErrorStr());
831
832 bailout:
833 if(dstBuf) (*env)->ReleasePrimitiveArrayCritical(env, dst, dstBuf, 0);
834 if(jpegBuf) (*env)->ReleasePrimitiveArrayCritical(env, src, jpegBuf, 0);
835 return;
836}
837
838static void TJDecompressor_decodeYUV
839 (JNIEnv *env, jobject obj, jobjectArray srcobjs, jintArray jSrcOffsets,
840 jintArray jSrcStrides, jint subsamp, jarray dst, jint dstElementSize,
841 jint x, jint y, jint width, jint pitch, jint height, jint pf, jint flags)
842{
843 tjhandle handle=0;
844 jsize arraySize=0, actualPitch;
845 jbyteArray jSrcPlanes[3]={NULL, NULL, NULL};
846 unsigned char *srcPlanes[3], *dstBuf=NULL;
847 int *srcOffsets=NULL, *srcStrides=NULL;
848 int nc=(subsamp==org_libjpegturbo_turbojpeg_TJ_SAMP_GRAY? 1:3), i;
849
850 gethandle();
851
852 if(pf<0 || pf>=org_libjpegturbo_turbojpeg_TJ_NUMPF || subsamp<0
853 || subsamp>=org_libjpegturbo_turbojpeg_TJ_NUMSAMP)
DRCfc26b652014-03-16 22:56:26 +0000854 _throw("Invalid argument in decodeYUV()");
DRC40dd3142014-08-17 12:23:49 +0000855 if(org_libjpegturbo_turbojpeg_TJ_NUMPF!=TJ_NUMPF
856 || org_libjpegturbo_turbojpeg_TJ_NUMSAMP!=TJ_NUMSAMP)
DRCfc26b652014-03-16 22:56:26 +0000857 _throw("Mismatch between Java and C API");
858
DRC40dd3142014-08-17 12:23:49 +0000859 if((*env)->GetArrayLength(env, srcobjs)<nc)
860 _throw("Planes array is too small for the subsampling type");
861 if((*env)->GetArrayLength(env, jSrcOffsets)<nc)
862 _throw("Offsets array is too small for the subsampling type");
863 if((*env)->GetArrayLength(env, jSrcStrides)<nc)
864 _throw("Strides array is too small for the subsampling type");
865
DRCfc26b652014-03-16 22:56:26 +0000866 actualPitch=(pitch==0)? width*tjPixelSize[pf]:pitch;
867 arraySize=(y+height-1)*actualPitch + (x+width)*tjPixelSize[pf];
DRC927a10d2014-08-15 13:18:58 +0000868 if((*env)->GetArrayLength(env, dst)*dstElementSize<arraySize)
DRCfc26b652014-03-16 22:56:26 +0000869 _throw("Destination buffer is not large enough");
870
DRC40dd3142014-08-17 12:23:49 +0000871 bailif0(srcOffsets=(*env)->GetPrimitiveArrayCritical(env, jSrcOffsets, 0));
872 bailif0(srcStrides=(*env)->GetPrimitiveArrayCritical(env, jSrcStrides, 0));
873 for(i=0; i<nc; i++)
874 {
875 int planeSize=tjPlaneSizeYUV(i, width, srcStrides[i], height, subsamp);
876 int pw=tjPlaneWidth(i, width, subsamp);
877
878 if(planeSize<0 || pw<0)
879 _throw(tjGetErrorStr());
880
881 if(srcOffsets[i]<0)
882 _throw("Invalid argument in decodeYUV()");
883 if(srcStrides[i]<0 && srcOffsets[i]-planeSize+pw<0)
884 _throw("Negative plane stride would cause memory to be accessed below plane boundary");
885
886 bailif0(jSrcPlanes[i]=(*env)->GetObjectArrayElement(env, srcobjs, i));
887 if((*env)->GetArrayLength(env, jSrcPlanes[i])<srcOffsets[i]+planeSize)
888 _throw("Source plane is not large enough");
889
890 bailif0(srcPlanes[i]=(*env)->GetPrimitiveArrayCritical(env, jSrcPlanes[i],
891 0));
892 srcPlanes[i]=&srcPlanes[i][srcOffsets[i]];
893 }
DRCfc26b652014-03-16 22:56:26 +0000894 bailif0(dstBuf=(*env)->GetPrimitiveArrayCritical(env, dst, 0));
895
DRC40dd3142014-08-17 12:23:49 +0000896 if(tjDecodeYUVPlanes(handle, srcPlanes, srcStrides, subsamp,
DRCfc26b652014-03-16 22:56:26 +0000897 &dstBuf[y*actualPitch + x*tjPixelSize[pf]], width, pitch, height, pf,
898 flags)==-1)
DRCfc26b652014-03-16 22:56:26 +0000899 _throw(tjGetErrorStr());
DRCfc26b652014-03-16 22:56:26 +0000900
901 bailout:
902 if(dstBuf) (*env)->ReleasePrimitiveArrayCritical(env, dst, dstBuf, 0);
DRC40dd3142014-08-17 12:23:49 +0000903 for(i=0; i<nc; i++)
904 {
905 if(srcPlanes[i] && jSrcPlanes[i])
906 (*env)->ReleasePrimitiveArrayCritical(env, jSrcPlanes[i], srcPlanes[i],
907 0);
908 }
909 if(srcStrides)
910 (*env)->ReleasePrimitiveArrayCritical(env, jSrcStrides, srcStrides, 0);
911 if(srcOffsets)
912 (*env)->ReleasePrimitiveArrayCritical(env, jSrcOffsets, srcOffsets, 0);
DRCfc26b652014-03-16 22:56:26 +0000913 return;
914}
915
DRCa4940d12014-08-15 16:07:15 +0000916/* TurboJPEG 1.4.x: TJDecompressor::decodeYUV() byte destination */
DRC40dd3142014-08-17 12:23:49 +0000917JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decodeYUV___3_3B_3I_3II_3BIIIIIII
918 (JNIEnv *env, jobject obj, jobjectArray srcobjs, jintArray jSrcOffsets,
919 jintArray jSrcStrides, jint subsamp, jbyteArray dst, jint x, jint y,
920 jint width, jint pitch, jint height, jint pf, jint flags)
DRC927a10d2014-08-15 13:18:58 +0000921{
DRC40dd3142014-08-17 12:23:49 +0000922 TJDecompressor_decodeYUV(env, obj, srcobjs, jSrcOffsets, jSrcStrides,
923 subsamp, dst, 1, x, y, width, pitch, height, pf, flags);
DRC927a10d2014-08-15 13:18:58 +0000924}
925
DRCa4940d12014-08-15 16:07:15 +0000926/* TurboJPEG 1.4.x: TJDecompressor::decodeYUV() int destination */
DRC40dd3142014-08-17 12:23:49 +0000927JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decodeYUV___3_3B_3I_3II_3IIIIIIII
928 (JNIEnv *env, jobject obj, jobjectArray srcobjs, jintArray jSrcOffsets,
929 jintArray jSrcStrides, jint subsamp, jintArray dst, jint x, jint y,
930 jint width, jint stride, jint height, jint pf, jint flags)
DRCfc26b652014-03-16 22:56:26 +0000931{
DRCfc26b652014-03-16 22:56:26 +0000932 if(pf<0 || pf>=org_libjpegturbo_turbojpeg_TJ_NUMPF)
933 _throw("Invalid argument in decodeYUV()");
DRCfc26b652014-03-16 22:56:26 +0000934 if(tjPixelSize[pf]!=sizeof(jint))
935 _throw("Pixel format must be 32-bit when decoding to an integer buffer.");
936
DRC40dd3142014-08-17 12:23:49 +0000937 TJDecompressor_decodeYUV(env, obj, srcobjs, jSrcOffsets, jSrcStrides,
938 subsamp, dst, sizeof(jint), x, y, width, stride*sizeof(jint), height, pf,
939 flags);
DRCfc26b652014-03-16 22:56:26 +0000940
941 bailout:
DRCfc26b652014-03-16 22:56:26 +0000942 return;
943}
944
DRCa4940d12014-08-15 16:07:15 +0000945/* TurboJPEG 1.2.x: TJTransformer::init() */
DRCe8573012011-03-04 10:13:59 +0000946JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJTransformer_init
947 (JNIEnv *env, jobject obj)
948{
949 jclass cls;
950 jfieldID fid;
951 tjhandle handle;
952
953 if((handle=tjInitTransform())==NULL) _throw(tjGetErrorStr());
954
955 bailif0(cls=(*env)->GetObjectClass(env, obj));
956 bailif0(fid=(*env)->GetFieldID(env, cls, "handle", "J"));
DRC46a03922014-08-15 14:40:05 +0000957 (*env)->SetLongField(env, obj, fid, (size_t)handle);
DRCe8573012011-03-04 10:13:59 +0000958
959 bailout:
960 return;
961}
962
DRCf5467112011-09-20 05:02:19 +0000963typedef struct _JNICustomFilterParams
964{
965 JNIEnv *env;
966 jobject tobj;
967 jobject cfobj;
968} JNICustomFilterParams;
969
970static int JNICustomFilter(short *coeffs, tjregion arrayRegion,
971 tjregion planeRegion, int componentIndex, int transformIndex,
972 tjtransform *transform)
973{
974 JNICustomFilterParams *params=(JNICustomFilterParams *)transform->data;
975 JNIEnv *env=params->env;
976 jobject tobj=params->tobj, cfobj=params->cfobj;
DRCb7c8c862014-08-15 16:20:59 +0000977 jobject arrayRegionObj, planeRegionObj, bufobj, borobj;
DRCf5467112011-09-20 05:02:19 +0000978 jclass cls; jmethodID mid; jfieldID fid;
979
980 bailif0(bufobj=(*env)->NewDirectByteBuffer(env, coeffs,
981 sizeof(short)*arrayRegion.w*arrayRegion.h));
982 bailif0(cls=(*env)->FindClass(env, "java/nio/ByteOrder"));
DRCb7c8c862014-08-15 16:20:59 +0000983 bailif0(mid=(*env)->GetStaticMethodID(env, cls, "nativeOrder",
DRCf5467112011-09-20 05:02:19 +0000984 "()Ljava/nio/ByteOrder;"));
985 bailif0(borobj=(*env)->CallStaticObjectMethod(env, cls, mid));
986 bailif0(cls=(*env)->GetObjectClass(env, bufobj));
987 bailif0(mid=(*env)->GetMethodID(env, cls, "order",
988 "(Ljava/nio/ByteOrder;)Ljava/nio/ByteBuffer;"));
989 (*env)->CallObjectMethod(env, bufobj, mid, borobj);
DRCb7c8c862014-08-15 16:20:59 +0000990 bailif0(mid=(*env)->GetMethodID(env, cls, "asShortBuffer",
DRCf5467112011-09-20 05:02:19 +0000991 "()Ljava/nio/ShortBuffer;"));
992 bailif0(bufobj=(*env)->CallObjectMethod(env, bufobj, mid));
993
994 bailif0(cls=(*env)->FindClass(env, "java/awt/Rectangle"));
995 bailif0(arrayRegionObj=(*env)->AllocObject(env, cls));
996 bailif0(fid=(*env)->GetFieldID(env, cls, "x", "I"));
997 (*env)->SetIntField(env, arrayRegionObj, fid, arrayRegion.x);
998 bailif0(fid=(*env)->GetFieldID(env, cls, "y", "I"));
999 (*env)->SetIntField(env, arrayRegionObj, fid, arrayRegion.y);
1000 bailif0(fid=(*env)->GetFieldID(env, cls, "width", "I"));
1001 (*env)->SetIntField(env, arrayRegionObj, fid, arrayRegion.w);
1002 bailif0(fid=(*env)->GetFieldID(env, cls, "height", "I"));
1003 (*env)->SetIntField(env, arrayRegionObj, fid, arrayRegion.h);
1004
1005 bailif0(planeRegionObj=(*env)->AllocObject(env, cls));
1006 bailif0(fid=(*env)->GetFieldID(env, cls, "x", "I"));
1007 (*env)->SetIntField(env, planeRegionObj, fid, planeRegion.x);
1008 bailif0(fid=(*env)->GetFieldID(env, cls, "y", "I"));
1009 (*env)->SetIntField(env, planeRegionObj, fid, planeRegion.y);
1010 bailif0(fid=(*env)->GetFieldID(env, cls, "width", "I"));
1011 (*env)->SetIntField(env, planeRegionObj, fid, planeRegion.w);
1012 bailif0(fid=(*env)->GetFieldID(env, cls, "height", "I"));
1013 (*env)->SetIntField(env, planeRegionObj, fid, planeRegion.h);
1014
1015 bailif0(cls=(*env)->GetObjectClass(env, cfobj));
1016 bailif0(mid=(*env)->GetMethodID(env, cls, "customFilter",
1017 "(Ljava/nio/ShortBuffer;Ljava/awt/Rectangle;Ljava/awt/Rectangle;IILorg/libjpegturbo/turbojpeg/TJTransform;)V"));
1018 (*env)->CallVoidMethod(env, cfobj, mid, bufobj, arrayRegionObj,
1019 planeRegionObj, componentIndex, transformIndex, tobj);
1020
1021 return 0;
1022
1023 bailout:
1024 return -1;
1025}
1026
DRCa4940d12014-08-15 16:07:15 +00001027/* TurboJPEG 1.2.x: TJTransformer::transform() */
DRCe8573012011-03-04 10:13:59 +00001028JNIEXPORT jintArray JNICALL Java_org_libjpegturbo_turbojpeg_TJTransformer_transform
DRC9b28def2011-05-21 14:37:15 +00001029 (JNIEnv *env, jobject obj, jbyteArray jsrcBuf, jint jpegSize,
DRCe8573012011-03-04 10:13:59 +00001030 jobjectArray dstobjs, jobjectArray tobjs, jint flags)
1031{
1032 tjhandle handle=0; int i;
DRC9b28def2011-05-21 14:37:15 +00001033 unsigned char *jpegBuf=NULL, **dstBufs=NULL; jsize n=0;
1034 unsigned long *dstSizes=NULL; tjtransform *t=NULL;
1035 jbyteArray *jdstBufs=NULL;
DRC9b49f0e2011-07-12 03:17:23 +00001036 int jpegWidth=0, jpegHeight=0, jpegSubsamp;
DRC9b28def2011-05-21 14:37:15 +00001037 jintArray jdstSizes=0; jint *dstSizesi=NULL;
DRCf5467112011-09-20 05:02:19 +00001038 JNICustomFilterParams *params=NULL;
DRCe8573012011-03-04 10:13:59 +00001039
1040 gethandle();
1041
DRC9b28def2011-05-21 14:37:15 +00001042 if((*env)->GetArrayLength(env, jsrcBuf)<jpegSize)
DRCe8573012011-03-04 10:13:59 +00001043 _throw("Source buffer is not large enough");
DRC26dd86b2014-08-15 14:01:21 +00001044 bailif0(_fid=(*env)->GetFieldID(env, _cls, "jpegWidth", "I"));
DRCe8573012011-03-04 10:13:59 +00001045 jpegWidth=(int)(*env)->GetIntField(env, obj, _fid);
DRC26dd86b2014-08-15 14:01:21 +00001046 bailif0(_fid=(*env)->GetFieldID(env, _cls, "jpegHeight", "I"));
DRCe8573012011-03-04 10:13:59 +00001047 jpegHeight=(int)(*env)->GetIntField(env, obj, _fid);
DRC26dd86b2014-08-15 14:01:21 +00001048 bailif0(_fid=(*env)->GetFieldID(env, _cls, "jpegSubsamp", "I"));
DRC9b49f0e2011-07-12 03:17:23 +00001049 jpegSubsamp=(int)(*env)->GetIntField(env, obj, _fid);
DRCe8573012011-03-04 10:13:59 +00001050
1051 n=(*env)->GetArrayLength(env, dstobjs);
1052 if(n!=(*env)->GetArrayLength(env, tobjs))
1053 _throw("Mismatch between size of transforms array and destination buffers array");
1054
DRC9b28def2011-05-21 14:37:15 +00001055 if((dstBufs=(unsigned char **)malloc(sizeof(unsigned char *)*n))==NULL)
DRCe8573012011-03-04 10:13:59 +00001056 _throw("Memory allocation failure");
DRC9b28def2011-05-21 14:37:15 +00001057 if((jdstBufs=(jbyteArray *)malloc(sizeof(jbyteArray)*n))==NULL)
DRCe8573012011-03-04 10:13:59 +00001058 _throw("Memory allocation failure");
DRC9b28def2011-05-21 14:37:15 +00001059 if((dstSizes=(unsigned long *)malloc(sizeof(unsigned long)*n))==NULL)
DRCe8573012011-03-04 10:13:59 +00001060 _throw("Memory allocation failure");
1061 if((t=(tjtransform *)malloc(sizeof(tjtransform)*n))==NULL)
1062 _throw("Memory allocation failure");
DRCf5467112011-09-20 05:02:19 +00001063 if((params=(JNICustomFilterParams *)malloc(sizeof(JNICustomFilterParams)*n))
1064 ==NULL)
1065 _throw("Memory allocation failure");
DRCe8573012011-03-04 10:13:59 +00001066 for(i=0; i<n; i++)
1067 {
DRC9b28def2011-05-21 14:37:15 +00001068 dstBufs[i]=NULL; jdstBufs[i]=NULL; dstSizes[i]=0;
DRCe8573012011-03-04 10:13:59 +00001069 memset(&t[i], 0, sizeof(tjtransform));
DRCf5467112011-09-20 05:02:19 +00001070 memset(&params[i], 0, sizeof(JNICustomFilterParams));
DRCe8573012011-03-04 10:13:59 +00001071 }
1072
1073 for(i=0; i<n; i++)
1074 {
DRCf5467112011-09-20 05:02:19 +00001075 jobject tobj, cfobj;
DRCe8573012011-03-04 10:13:59 +00001076
1077 bailif0(tobj=(*env)->GetObjectArrayElement(env, tobjs, i));
1078 bailif0(_cls=(*env)->GetObjectClass(env, tobj));
1079 bailif0(_fid=(*env)->GetFieldID(env, _cls, "op", "I"));
1080 t[i].op=(*env)->GetIntField(env, tobj, _fid);
1081 bailif0(_fid=(*env)->GetFieldID(env, _cls, "options", "I"));
1082 t[i].options=(*env)->GetIntField(env, tobj, _fid);
1083 bailif0(_fid=(*env)->GetFieldID(env, _cls, "x", "I"));
1084 t[i].r.x=(*env)->GetIntField(env, tobj, _fid);
1085 bailif0(_fid=(*env)->GetFieldID(env, _cls, "y", "I"));
1086 t[i].r.y=(*env)->GetIntField(env, tobj, _fid);
1087 bailif0(_fid=(*env)->GetFieldID(env, _cls, "width", "I"));
1088 t[i].r.w=(*env)->GetIntField(env, tobj, _fid);
1089 bailif0(_fid=(*env)->GetFieldID(env, _cls, "height", "I"));
1090 t[i].r.h=(*env)->GetIntField(env, tobj, _fid);
DRCf5467112011-09-20 05:02:19 +00001091
DRCf5467112011-09-20 05:02:19 +00001092 bailif0(_fid=(*env)->GetFieldID(env, _cls, "cf",
1093 "Lorg/libjpegturbo/turbojpeg/TJCustomFilter;"));
DRC06420c42011-09-26 18:46:09 +00001094 cfobj=(*env)->GetObjectField(env, tobj, _fid);
1095 if(cfobj)
1096 {
1097 params[i].env=env;
1098 params[i].tobj=tobj;
1099 params[i].cfobj=cfobj;
1100 t[i].customFilter=JNICustomFilter;
1101 t[i].data=(void *)&params[i];
1102 }
DRCe8573012011-03-04 10:13:59 +00001103 }
1104
DRCe8573012011-03-04 10:13:59 +00001105 for(i=0; i<n; i++)
1106 {
1107 int w=jpegWidth, h=jpegHeight;
1108 if(t[i].r.w!=0) w=t[i].r.w;
1109 if(t[i].r.h!=0) h=t[i].r.h;
DRC9b28def2011-05-21 14:37:15 +00001110 bailif0(jdstBufs[i]=(*env)->GetObjectArrayElement(env, dstobjs, i));
DRCefe28ce2012-01-17 11:48:38 +00001111 if((unsigned long)(*env)->GetArrayLength(env, jdstBufs[i])
1112 <tjBufSize(w, h, jpegSubsamp))
DRCe8573012011-03-04 10:13:59 +00001113 _throw("Destination buffer is not large enough");
DRCe8573012011-03-04 10:13:59 +00001114 }
DRC8951cf02014-08-14 16:54:04 +00001115 bailif0(jpegBuf=(*env)->GetPrimitiveArrayCritical(env, jsrcBuf, 0));
1116 for(i=0; i<n; i++)
1117 bailif0(dstBufs[i]=(*env)->GetPrimitiveArrayCritical(env, jdstBufs[i], 0));
DRCe8573012011-03-04 10:13:59 +00001118
DRC9b28def2011-05-21 14:37:15 +00001119 if(tjTransform(handle, jpegBuf, jpegSize, n, dstBufs, dstSizes, t,
DRC4db92ad2011-05-25 04:52:25 +00001120 flags|TJFLAG_NOREALLOC)==-1)
DRCe8573012011-03-04 10:13:59 +00001121 _throw(tjGetErrorStr());
DRC8951cf02014-08-14 16:54:04 +00001122
1123 for(i=0; i<n; i++)
1124 {
1125 (*env)->ReleasePrimitiveArrayCritical(env, jdstBufs[i], dstBufs[i], 0);
1126 dstBufs[i]=NULL;
DRCe8573012011-03-04 10:13:59 +00001127 }
DRC8951cf02014-08-14 16:54:04 +00001128 (*env)->ReleasePrimitiveArrayCritical(env, jsrcBuf, jpegBuf, 0);
1129 jpegBuf=NULL;
DRCe8573012011-03-04 10:13:59 +00001130
DRC9b28def2011-05-21 14:37:15 +00001131 jdstSizes=(*env)->NewIntArray(env, n);
1132 bailif0(dstSizesi=(*env)->GetIntArrayElements(env, jdstSizes, 0));
1133 for(i=0; i<n; i++) dstSizesi[i]=(int)dstSizes[i];
DRCe8573012011-03-04 10:13:59 +00001134
1135 bailout:
DRC8951cf02014-08-14 16:54:04 +00001136 if(dstSizesi) (*env)->ReleaseIntArrayElements(env, jdstSizes, dstSizesi, 0);
DRC9b28def2011-05-21 14:37:15 +00001137 if(dstBufs)
DRCe8573012011-03-04 10:13:59 +00001138 {
1139 for(i=0; i<n; i++)
1140 {
DRC9b28def2011-05-21 14:37:15 +00001141 if(dstBufs[i] && jdstBufs && jdstBufs[i])
1142 (*env)->ReleasePrimitiveArrayCritical(env, jdstBufs[i], dstBufs[i], 0);
DRCe8573012011-03-04 10:13:59 +00001143 }
DRC9b28def2011-05-21 14:37:15 +00001144 free(dstBufs);
DRCe8573012011-03-04 10:13:59 +00001145 }
DRC8951cf02014-08-14 16:54:04 +00001146 if(jpegBuf) (*env)->ReleasePrimitiveArrayCritical(env, jsrcBuf, jpegBuf, 0);
DRC9b28def2011-05-21 14:37:15 +00001147 if(jdstBufs) free(jdstBufs);
1148 if(dstSizes) free(dstSizes);
DRCe8573012011-03-04 10:13:59 +00001149 if(t) free(t);
DRC9b28def2011-05-21 14:37:15 +00001150 return jdstSizes;
DRCe8573012011-03-04 10:13:59 +00001151}
1152
DRCa4940d12014-08-15 16:07:15 +00001153/* TurboJPEG 1.2.x: TJDecompressor::destroy() */
DRCc5a41992011-02-08 06:54:36 +00001154JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_destroy
DRCf8e00552011-02-04 11:06:36 +00001155 (JNIEnv *env, jobject obj)
1156{
DRCc5a41992011-02-08 06:54:36 +00001157 Java_org_libjpegturbo_turbojpeg_TJCompressor_destroy(env, obj);
DRCf8e00552011-02-04 11:06:36 +00001158}