blob: cab57bdf98c9108ddf2b1692e186cdd1a844daed [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
DRCa4940d12014-08-15 16:07:15 +000062/* TurboJPEG 1.2.x: TJ::bufSize() */
DRC3bad53f2011-02-23 02:20:49 +000063JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJ_bufSize
DRC9b49f0e2011-07-12 03:17:23 +000064 (JNIEnv *env, jclass cls, jint width, jint height, jint jpegSubsamp)
DRCf8e00552011-02-04 11:06:36 +000065{
DRC9b49f0e2011-07-12 03:17:23 +000066 jint retval=(jint)tjBufSize(width, height, jpegSubsamp);
DRC36336fc2011-02-22 10:27:31 +000067 if(retval==-1) _throw(tjGetErrorStr());
68
69 bailout:
70 return retval;
71}
72
DRCa4940d12014-08-15 16:07:15 +000073/* TurboJPEG 1.4.x: TJ::bufSizeYUV() */
DRCfef98522013-04-28 01:32:52 +000074JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJ_bufSizeYUV__IIII
75 (JNIEnv *env, jclass cls, jint width, jint pad, jint height, jint subsamp)
DRC36336fc2011-02-22 10:27:31 +000076{
DRCfef98522013-04-28 01:32:52 +000077 jint retval=(jint)tjBufSizeYUV2(width, pad, height, subsamp);
DRC36336fc2011-02-22 10:27:31 +000078 if(retval==-1) _throw(tjGetErrorStr());
79
80 bailout:
81 return retval;
DRCf8e00552011-02-04 11:06:36 +000082}
83
DRCa4940d12014-08-15 16:07:15 +000084/* TurboJPEG 1.2.x: TJ::bufSizeYUV() */
DRCfef98522013-04-28 01:32:52 +000085JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJ_bufSizeYUV__III
86 (JNIEnv *env, jclass cls, jint width, jint height, jint subsamp)
87{
88 return Java_org_libjpegturbo_turbojpeg_TJ_bufSizeYUV__IIII(env, cls, width,
89 4, height, subsamp);
90}
91
DRC40dd3142014-08-17 12:23:49 +000092/* TurboJPEG 1.4.x: TJ::planeSizeYUV() */
93JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJ_planeSizeYUV__IIIII
94 (JNIEnv *env, jclass cls, jint componentID, jint width, jint stride,
95 jint height, jint subsamp)
96{
97 jint retval=(jint)tjPlaneSizeYUV(componentID, width, stride, height,
98 subsamp);
99 if(retval==-1) _throw(tjGetErrorStr());
100
101 bailout:
102 return retval;
103}
104
105/* TurboJPEG 1.4.x: TJ::planeWidth() */
106JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJ_planeWidth__III
107 (JNIEnv *env, jclass cls, jint componentID, jint width, jint subsamp)
108{
109 jint retval=(jint)tjPlaneWidth(componentID, width, subsamp);
110 if(retval==-1) _throw(tjGetErrorStr());
111
112 bailout:
113 return retval;
114}
115
116/* TurboJPEG 1.4.x: TJ::planeHeight() */
117JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJ_planeHeight__III
118 (JNIEnv *env, jclass cls, jint componentID, jint height, jint subsamp)
119{
120 jint retval=(jint)tjPlaneHeight(componentID, height, subsamp);
121 if(retval==-1) _throw(tjGetErrorStr());
122
123 bailout:
124 return retval;
125}
126
DRCa4940d12014-08-15 16:07:15 +0000127/* TurboJPEG 1.2.x: TJCompressor::init() */
DRCc5a41992011-02-08 06:54:36 +0000128JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_init
DRCf8e00552011-02-04 11:06:36 +0000129 (JNIEnv *env, jobject obj)
130{
131 jclass cls;
132 jfieldID fid;
133 tjhandle handle;
134
DRC1a3dbe62011-02-28 10:51:55 +0000135 if((handle=tjInitCompress())==NULL)
DRCf8e00552011-02-04 11:06:36 +0000136 _throw(tjGetErrorStr());
137
138 bailif0(cls=(*env)->GetObjectClass(env, obj));
139 bailif0(fid=(*env)->GetFieldID(env, cls, "handle", "J"));
DRC46a03922014-08-15 14:40:05 +0000140 (*env)->SetLongField(env, obj, fid, (size_t)handle);
DRCf8e00552011-02-04 11:06:36 +0000141
142 bailout:
143 return;
144}
145
DRC5d87f6d2014-08-15 16:40:56 +0000146static jint TJCompressor_compress
DRC927a10d2014-08-15 13:18:58 +0000147 (JNIEnv *env, jobject obj, jarray src, jint srcElementSize, jint x, jint y,
148 jint width, jint pitch, jint height, jint pf, jbyteArray dst,
149 jint jpegSubsamp, jint jpegQual, jint flags)
DRCf8e00552011-02-04 11:06:36 +0000150{
DRC9b28def2011-05-21 14:37:15 +0000151 tjhandle handle=0;
DRCfac3bea2012-09-24 02:27:55 +0000152 unsigned long jpegSize=0;
153 jsize arraySize=0, actualPitch;
DRC9b28def2011-05-21 14:37:15 +0000154 unsigned char *srcBuf=NULL, *jpegBuf=NULL;
DRCf8e00552011-02-04 11:06:36 +0000155
156 gethandle();
157
DRC92549de2011-03-15 20:52:02 +0000158 if(pf<0 || pf>=org_libjpegturbo_turbojpeg_TJ_NUMPF || width<1 || height<1
DRC6acf52b2011-03-02 01:09:20 +0000159 || pitch<0)
DRC4f1580c2011-02-25 06:11:03 +0000160 _throw("Invalid argument in compress()");
DRC9b28def2011-05-21 14:37:15 +0000161 if(org_libjpegturbo_turbojpeg_TJ_NUMPF!=TJ_NUMPF)
162 _throw("Mismatch between Java and C API");
DRC4f1580c2011-02-25 06:11:03 +0000163
DRCfac3bea2012-09-24 02:27:55 +0000164 actualPitch=(pitch==0)? width*tjPixelSize[pf]:pitch;
DRC927a10d2014-08-15 13:18:58 +0000165 arraySize=(y+height-1)*actualPitch + (x+width)*tjPixelSize[pf];
166 if((*env)->GetArrayLength(env, src)*srcElementSize<arraySize)
DRC6acf52b2011-03-02 01:09:20 +0000167 _throw("Source buffer is not large enough");
DRC9b49f0e2011-07-12 03:17:23 +0000168 jpegSize=tjBufSize(width, height, jpegSubsamp);
DRC9b28def2011-05-21 14:37:15 +0000169 if((*env)->GetArrayLength(env, dst)<(jsize)jpegSize)
DRC6acf52b2011-03-02 01:09:20 +0000170 _throw("Destination buffer is not large enough");
171
DRC9b28def2011-05-21 14:37:15 +0000172 bailif0(srcBuf=(*env)->GetPrimitiveArrayCritical(env, src, 0));
173 bailif0(jpegBuf=(*env)->GetPrimitiveArrayCritical(env, dst, 0));
DRCf8e00552011-02-04 11:06:36 +0000174
DRCfac3bea2012-09-24 02:27:55 +0000175 if(tjCompress2(handle, &srcBuf[y*actualPitch + x*tjPixelSize[pf]], width,
176 pitch, height, pf, &jpegBuf, &jpegSize, jpegSubsamp, jpegQual,
177 flags|TJFLAG_NOREALLOC)==-1)
DRCfac3bea2012-09-24 02:27:55 +0000178 _throw(tjGetErrorStr());
DRCfac3bea2012-09-24 02:27:55 +0000179
180 bailout:
181 if(jpegBuf) (*env)->ReleasePrimitiveArrayCritical(env, dst, jpegBuf, 0);
182 if(srcBuf) (*env)->ReleasePrimitiveArrayCritical(env, src, srcBuf, 0);
183 return (jint)jpegSize;
184}
185
DRCa4940d12014-08-15 16:07:15 +0000186/* TurboJPEG 1.3.x: TJCompressor::compress() byte source */
DRC927a10d2014-08-15 13:18:58 +0000187JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_compress___3BIIIIII_3BIII
188 (JNIEnv *env, jobject obj, jbyteArray src, jint x, jint y, jint width,
189 jint pitch, jint height, jint pf, jbyteArray dst, jint jpegSubsamp,
190 jint jpegQual, jint flags)
191{
192 return TJCompressor_compress(env, obj, src, 1, x, y, width, pitch, height,
193 pf, dst, jpegSubsamp, jpegQual, flags);
194}
195
DRCa4940d12014-08-15 16:07:15 +0000196/* TurboJPEG 1.2.x: TJCompressor::compress() byte source */
DRCfac3bea2012-09-24 02:27:55 +0000197JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_compress___3BIIII_3BIII
198 (JNIEnv *env, jobject obj, jbyteArray src, jint width, jint pitch,
199 jint height, jint pf, jbyteArray dst, jint jpegSubsamp, jint jpegQual,
200 jint flags)
201{
DRC927a10d2014-08-15 13:18:58 +0000202 return TJCompressor_compress(env, obj, src, 1, 0, 0, width, pitch, height,
203 pf, dst, jpegSubsamp, jpegQual, flags);
DRCfac3bea2012-09-24 02:27:55 +0000204}
205
DRCa4940d12014-08-15 16:07:15 +0000206/* TurboJPEG 1.3.x: TJCompressor::compress() int source */
DRCfac3bea2012-09-24 02:27:55 +0000207JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_compress___3IIIIIII_3BIII
208 (JNIEnv *env, jobject obj, jintArray src, jint x, jint y, jint width,
209 jint stride, jint height, jint pf, jbyteArray dst, jint jpegSubsamp,
210 jint jpegQual, jint flags)
211{
DRC927a10d2014-08-15 13:18:58 +0000212 if(pf<0 || pf>=org_libjpegturbo_turbojpeg_TJ_NUMPF)
DRCfac3bea2012-09-24 02:27:55 +0000213 _throw("Invalid argument in compress()");
DRCfac3bea2012-09-24 02:27:55 +0000214 if(tjPixelSize[pf]!=sizeof(jint))
215 _throw("Pixel format must be 32-bit when compressing from an integer buffer.");
216
DRC927a10d2014-08-15 13:18:58 +0000217 return TJCompressor_compress(env, obj, src, sizeof(jint), x, y, width,
218 stride*sizeof(jint), height, pf, dst, jpegSubsamp, jpegQual, flags);
DRCf8e00552011-02-04 11:06:36 +0000219
220 bailout:
DRC927a10d2014-08-15 13:18:58 +0000221 return 0;
DRCf8e00552011-02-04 11:06:36 +0000222}
223
DRCa4940d12014-08-15 16:07:15 +0000224/* TurboJPEG 1.2.x: TJCompressor::compress() int source */
DRC4f1580c2011-02-25 06:11:03 +0000225JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_compress___3IIIII_3BIII
DRC927a10d2014-08-15 13:18:58 +0000226 (JNIEnv *env, jobject obj, jintArray src, jint width, jint stride,
DRC9b28def2011-05-21 14:37:15 +0000227 jint height, jint pf, jbyteArray dst, jint jpegSubsamp, jint jpegQual,
DRC4f1580c2011-02-25 06:11:03 +0000228 jint flags)
DRC84a1bcc2011-02-23 12:09:56 +0000229{
DRC927a10d2014-08-15 13:18:58 +0000230 if(pf<0 || pf>=org_libjpegturbo_turbojpeg_TJ_NUMPF)
231 _throw("Invalid argument in compress()");
232 if(tjPixelSize[pf]!=sizeof(jint))
233 _throw("Pixel format must be 32-bit when compressing from an integer buffer.");
234
235 return TJCompressor_compress(env, obj, src, sizeof(jint), 0, 0, width,
236 stride*sizeof(jint), height, pf, dst, jpegSubsamp, jpegQual, flags);
237
238 bailout:
239 return 0;
DRC84a1bcc2011-02-23 12:09:56 +0000240}
241
DRCa4940d12014-08-15 16:07:15 +0000242/* TurboJPEG 1.4.x: TJCompressor::compressFromYUV() */
DRC40dd3142014-08-17 12:23:49 +0000243JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_compressFromYUV___3_3B_3II_3III_3BII
244 (JNIEnv *env, jobject obj, jobjectArray srcobjs, jintArray jSrcOffsets,
245 jint width, jintArray jSrcStrides, jint height, jint subsamp,
246 jbyteArray dst, jint jpegQual, jint flags)
DRC1e672742013-10-31 05:04:51 +0000247{
248 tjhandle handle=0;
249 unsigned long jpegSize=0;
DRC40dd3142014-08-17 12:23:49 +0000250 jbyteArray jSrcPlanes[3]={NULL, NULL, NULL};
251 unsigned char *srcPlanes[3], *jpegBuf=NULL;
252 int *srcOffsets=NULL, *srcStrides=NULL;
253 int nc=(subsamp==org_libjpegturbo_turbojpeg_TJ_SAMP_GRAY? 1:3), i;
DRC1e672742013-10-31 05:04:51 +0000254
255 gethandle();
256
DRC40dd3142014-08-17 12:23:49 +0000257 if(subsamp<0 || subsamp>=org_libjpegturbo_turbojpeg_TJ_NUMSAMP)
258 _throw("Invalid argument in compressFromYUV()");
259 if(org_libjpegturbo_turbojpeg_TJ_NUMSAMP!=TJ_NUMSAMP)
260 _throw("Mismatch between Java and C API");
261
262 if((*env)->GetArrayLength(env, srcobjs)<nc)
263 _throw("Planes array is too small for the subsampling type");
264 if((*env)->GetArrayLength(env, jSrcOffsets)<nc)
265 _throw("Offsets array is too small for the subsampling type");
266 if((*env)->GetArrayLength(env, jSrcStrides)<nc)
267 _throw("Strides array is too small for the subsampling type");
268
DRC1e672742013-10-31 05:04:51 +0000269 jpegSize=tjBufSize(width, height, subsamp);
270 if((*env)->GetArrayLength(env, dst)<(jsize)jpegSize)
271 _throw("Destination buffer is not large enough");
272
DRC40dd3142014-08-17 12:23:49 +0000273 bailif0(srcOffsets=(*env)->GetPrimitiveArrayCritical(env, jSrcOffsets, 0));
274 bailif0(srcStrides=(*env)->GetPrimitiveArrayCritical(env, jSrcStrides, 0));
275 for(i=0; i<nc; i++)
276 {
277 int planeSize=tjPlaneSizeYUV(i, width, srcStrides[i], height, subsamp);
278 int pw=tjPlaneWidth(i, width, subsamp);
279
280 if(planeSize<0 || pw<0)
281 _throw(tjGetErrorStr());
282
283 if(srcOffsets[i]<0)
284 _throw("Invalid argument in compressFromYUV()");
285 if(srcStrides[i]<0 && srcOffsets[i]-planeSize+pw<0)
286 _throw("Negative plane stride would cause memory to be accessed below plane boundary");
287
288 bailif0(jSrcPlanes[i]=(*env)->GetObjectArrayElement(env, srcobjs, i));
289 if((*env)->GetArrayLength(env, jSrcPlanes[i])<srcOffsets[i]+planeSize)
290 _throw("Source plane is not large enough");
291
292 bailif0(srcPlanes[i]=(*env)->GetPrimitiveArrayCritical(env, jSrcPlanes[i],
293 0));
294 srcPlanes[i]=&srcPlanes[i][srcOffsets[i]];
295 }
DRC1e672742013-10-31 05:04:51 +0000296 bailif0(jpegBuf=(*env)->GetPrimitiveArrayCritical(env, dst, 0));
297
DRC40dd3142014-08-17 12:23:49 +0000298 if(tjCompressFromYUVPlanes(handle, srcPlanes, width, srcStrides, height,
299 subsamp, &jpegBuf, &jpegSize, jpegQual, flags|TJFLAG_NOREALLOC)==-1)
DRC1e672742013-10-31 05:04:51 +0000300 _throw(tjGetErrorStr());
DRC1e672742013-10-31 05:04:51 +0000301
302 bailout:
303 if(jpegBuf) (*env)->ReleasePrimitiveArrayCritical(env, dst, jpegBuf, 0);
DRC40dd3142014-08-17 12:23:49 +0000304 for(i=0; i<nc; i++)
305 {
306 if(srcPlanes[i] && jSrcPlanes[i])
307 (*env)->ReleasePrimitiveArrayCritical(env, jSrcPlanes[i], srcPlanes[i],
308 0);
309 }
310 if(srcStrides)
311 (*env)->ReleasePrimitiveArrayCritical(env, jSrcStrides, srcStrides, 0);
312 if(srcOffsets)
313 (*env)->ReleasePrimitiveArrayCritical(env, jSrcOffsets, srcOffsets, 0);
DRC1e672742013-10-31 05:04:51 +0000314 return (jint)jpegSize;
315}
316
DRC5d87f6d2014-08-15 16:40:56 +0000317static void TJCompressor_encodeYUV
DRC927a10d2014-08-15 13:18:58 +0000318 (JNIEnv *env, jobject obj, jarray src, jint srcElementSize, jint x, jint y,
DRC40dd3142014-08-17 12:23:49 +0000319 jint width, jint pitch, jint height, jint pf, jobjectArray dstobjs,
320 jintArray jDstOffsets, jintArray jDstStrides, jint subsamp, jint flags)
DRC4f1580c2011-02-25 06:11:03 +0000321{
DRC9b28def2011-05-21 14:37:15 +0000322 tjhandle handle=0;
DRC40dd3142014-08-17 12:23:49 +0000323 jsize arraySize=0, actualPitch;
324 jbyteArray jDstPlanes[3]={NULL, NULL, NULL};
325 unsigned char *srcBuf=NULL, *dstPlanes[3];
326 int *dstOffsets=NULL, *dstStrides=NULL;
327 int nc=(subsamp==org_libjpegturbo_turbojpeg_TJ_SAMP_GRAY? 1:3), i;
328
329 gethandle();
330
331 if(pf<0 || pf>=org_libjpegturbo_turbojpeg_TJ_NUMPF || width<1 || height<1
332 || pitch<0 || subsamp<0 || subsamp>=org_libjpegturbo_turbojpeg_TJ_NUMSAMP)
333 _throw("Invalid argument in encodeYUV()");
334 if(org_libjpegturbo_turbojpeg_TJ_NUMPF!=TJ_NUMPF
335 || org_libjpegturbo_turbojpeg_TJ_NUMSAMP!=TJ_NUMSAMP)
336 _throw("Mismatch between Java and C API");
337
338 if((*env)->GetArrayLength(env, dstobjs)<nc)
339 _throw("Planes array is too small for the subsampling type");
340 if((*env)->GetArrayLength(env, jDstOffsets)<nc)
341 _throw("Offsets array is too small for the subsampling type");
342 if((*env)->GetArrayLength(env, jDstStrides)<nc)
343 _throw("Strides array is too small for the subsampling type");
344
345 actualPitch=(pitch==0)? width*tjPixelSize[pf]:pitch;
346 arraySize=(y+height-1)*actualPitch + (x+width)*tjPixelSize[pf];
347 if((*env)->GetArrayLength(env, src)*srcElementSize<arraySize)
348 _throw("Source buffer is not large enough");
349
350 bailif0(dstOffsets=(*env)->GetPrimitiveArrayCritical(env, jDstOffsets, 0));
351 bailif0(dstStrides=(*env)->GetPrimitiveArrayCritical(env, jDstStrides, 0));
352 for(i=0; i<nc; i++)
353 {
354 int planeSize=tjPlaneSizeYUV(i, width, dstStrides[i], height, subsamp);
355 int pw=tjPlaneWidth(i, width, subsamp);
356
357 if(planeSize<0 || pw<0)
358 _throw(tjGetErrorStr());
359
360 if(dstOffsets[i]<0)
361 _throw("Invalid argument in encodeYUV()");
362 if(dstStrides[i]<0 && dstOffsets[i]-planeSize+pw<0)
363 _throw("Negative plane stride would cause memory to be accessed below plane boundary");
364
365 bailif0(jDstPlanes[i]=(*env)->GetObjectArrayElement(env, dstobjs, i));
366 if((*env)->GetArrayLength(env, jDstPlanes[i])<dstOffsets[i]+planeSize)
367 _throw("Destination plane is not large enough");
368
369 bailif0(dstPlanes[i]=(*env)->GetPrimitiveArrayCritical(env, jDstPlanes[i],
370 0));
371 dstPlanes[i]=&dstPlanes[i][dstOffsets[i]];
372 }
373 bailif0(srcBuf=(*env)->GetPrimitiveArrayCritical(env, src, 0));
374
375 if(tjEncodeYUVPlanes(handle, &srcBuf[y*actualPitch + x*tjPixelSize[pf]],
376 width, pitch, height, pf, dstPlanes, dstStrides, subsamp, flags)==-1)
377 _throw(tjGetErrorStr());
378
379 bailout:
380 if(srcBuf) (*env)->ReleasePrimitiveArrayCritical(env, src, srcBuf, 0);
381 for(i=0; i<nc; i++)
382 {
383 if(dstPlanes[i] && jDstPlanes[i])
384 (*env)->ReleasePrimitiveArrayCritical(env, jDstPlanes[i], dstPlanes[i],
385 0);
386 }
387 if(dstStrides)
388 (*env)->ReleasePrimitiveArrayCritical(env, jDstStrides, dstStrides, 0);
389 if(dstOffsets)
390 (*env)->ReleasePrimitiveArrayCritical(env, jDstOffsets, dstOffsets, 0);
391 return;
392}
393
394/* TurboJPEG 1.4.x: TJCompressor::encodeYUV() byte source */
395JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_encodeYUV___3BIIIIII_3_3B_3I_3III
396 (JNIEnv *env, jobject obj, jbyteArray src, jint x, jint y, jint width,
397 jint pitch, jint height, jint pf, jobjectArray dstobjs,
398 jintArray jDstOffsets, jintArray jDstStrides, jint subsamp, jint flags)
399{
400 TJCompressor_encodeYUV(env, obj, src, 1, x, y, width, pitch, height, pf,
401 dstobjs, jDstOffsets, jDstStrides, subsamp, flags);
402}
403
404/* TurboJPEG 1.4.x: TJCompressor::encodeYUV() int source */
405JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_encodeYUV___3IIIIIII_3_3B_3I_3III
406 (JNIEnv *env, jobject obj, jintArray src, jint x, jint y, jint width,
407 jint stride, jint height, jint pf, jobjectArray dstobjs,
408 jintArray jDstOffsets, jintArray jDstStrides, jint subsamp, jint flags)
409{
410 if(pf<0 || pf>=org_libjpegturbo_turbojpeg_TJ_NUMPF)
411 _throw("Invalid argument in encodeYUV()");
412 if(tjPixelSize[pf]!=sizeof(jint))
413 _throw("Pixel format must be 32-bit when encoding from an integer buffer.");
414
415 TJCompressor_encodeYUV(env, obj, src, sizeof(jint), x, y, width,
416 stride*sizeof(jint), height, pf, dstobjs, jDstOffsets, jDstStrides,
417 subsamp, flags);
418
419 bailout:
420 return;
421}
422
423JNIEXPORT void JNICALL TJCompressor_encodeYUV_12
424 (JNIEnv *env, jobject obj, jarray src, jint srcElementSize, jint width,
425 jint pitch, jint height, jint pf, jbyteArray dst, jint subsamp, jint flags)
426{
427 tjhandle handle=0;
428 jsize arraySize=0;
DRC9b28def2011-05-21 14:37:15 +0000429 unsigned char *srcBuf=NULL, *dstBuf=NULL;
DRC4f1580c2011-02-25 06:11:03 +0000430
431 gethandle();
432
DRC92549de2011-03-15 20:52:02 +0000433 if(pf<0 || pf>=org_libjpegturbo_turbojpeg_TJ_NUMPF || width<1 || height<1
DRC6acf52b2011-03-02 01:09:20 +0000434 || pitch<0)
DRC4f1580c2011-02-25 06:11:03 +0000435 _throw("Invalid argument in encodeYUV()");
DRC9b28def2011-05-21 14:37:15 +0000436 if(org_libjpegturbo_turbojpeg_TJ_NUMPF!=TJ_NUMPF)
437 _throw("Mismatch between Java and C API");
DRC4f1580c2011-02-25 06:11:03 +0000438
DRC40dd3142014-08-17 12:23:49 +0000439 arraySize=(pitch==0)? width*tjPixelSize[pf]*height:pitch*height;
DRC927a10d2014-08-15 13:18:58 +0000440 if((*env)->GetArrayLength(env, src)*srcElementSize<arraySize)
DRC6acf52b2011-03-02 01:09:20 +0000441 _throw("Source buffer is not large enough");
DRC40dd3142014-08-17 12:23:49 +0000442 if((*env)->GetArrayLength(env, dst)
443 <(jsize)tjBufSizeYUV(width, height, subsamp))
DRC6acf52b2011-03-02 01:09:20 +0000444 _throw("Destination buffer is not large enough");
445
DRC9b28def2011-05-21 14:37:15 +0000446 bailif0(srcBuf=(*env)->GetPrimitiveArrayCritical(env, src, 0));
447 bailif0(dstBuf=(*env)->GetPrimitiveArrayCritical(env, dst, 0));
DRC4f1580c2011-02-25 06:11:03 +0000448
DRC40dd3142014-08-17 12:23:49 +0000449 if(tjEncodeYUV2(handle, srcBuf, width, pitch, height, pf, dstBuf, subsamp,
450 flags)==-1)
DRC4f1580c2011-02-25 06:11:03 +0000451 _throw(tjGetErrorStr());
DRC4f1580c2011-02-25 06:11:03 +0000452
453 bailout:
DRC9b28def2011-05-21 14:37:15 +0000454 if(dstBuf) (*env)->ReleasePrimitiveArrayCritical(env, dst, dstBuf, 0);
455 if(srcBuf) (*env)->ReleasePrimitiveArrayCritical(env, src, srcBuf, 0);
DRC4f1580c2011-02-25 06:11:03 +0000456 return;
457}
458
DRCa4940d12014-08-15 16:07:15 +0000459/* TurboJPEG 1.2.x: TJCompressor::encodeYUV() byte source */
DRCfef98522013-04-28 01:32:52 +0000460JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_encodeYUV___3BIIII_3BII
461 (JNIEnv *env, jobject obj, jbyteArray src, jint width, jint pitch,
DRC6acf52b2011-03-02 01:09:20 +0000462 jint height, jint pf, jbyteArray dst, jint subsamp, jint flags)
DRC4f1580c2011-02-25 06:11:03 +0000463{
DRC40dd3142014-08-17 12:23:49 +0000464 TJCompressor_encodeYUV_12(env, obj, src, 1, width, pitch, height, pf, dst,
465 subsamp, flags);
DRC4f1580c2011-02-25 06:11:03 +0000466}
467
DRCa4940d12014-08-15 16:07:15 +0000468/* TurboJPEG 1.2.x: TJCompressor::encodeYUV() int source */
DRCfef98522013-04-28 01:32:52 +0000469JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_encodeYUV___3IIIII_3BII
DRC927a10d2014-08-15 13:18:58 +0000470 (JNIEnv *env, jobject obj, jintArray src, jint width, jint stride,
DRCfef98522013-04-28 01:32:52 +0000471 jint height, jint pf, jbyteArray dst, jint subsamp, jint flags)
472{
DRC927a10d2014-08-15 13:18:58 +0000473 if(pf<0 || pf>=org_libjpegturbo_turbojpeg_TJ_NUMPF)
474 _throw("Invalid argument in encodeYUV()");
475 if(tjPixelSize[pf]!=sizeof(jint))
476 _throw("Pixel format must be 32-bit when encoding from an integer buffer.");
477
DRC40dd3142014-08-17 12:23:49 +0000478 TJCompressor_encodeYUV_12(env, obj, src, sizeof(jint), width,
479 stride*sizeof(jint), height, pf, dst, subsamp, flags);
DRC927a10d2014-08-15 13:18:58 +0000480
481 bailout:
482 return;
DRCfef98522013-04-28 01:32:52 +0000483}
484
DRCa4940d12014-08-15 16:07:15 +0000485/* TurboJPEG 1.2.x: TJCompressor::destroy() */
DRCc5a41992011-02-08 06:54:36 +0000486JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_destroy
DRCf8e00552011-02-04 11:06:36 +0000487 (JNIEnv *env, jobject obj)
488{
489 tjhandle handle=0;
490
491 gethandle();
492
493 if(tjDestroy(handle)==-1) _throw(tjGetErrorStr());
DRC3bad53f2011-02-23 02:20:49 +0000494 (*env)->SetLongField(env, obj, _fid, 0);
DRCf8e00552011-02-04 11:06:36 +0000495
496 bailout:
497 return;
498}
499
DRCa4940d12014-08-15 16:07:15 +0000500/* TurboJPEG 1.2.x: TJDecompressor::init() */
DRCc5a41992011-02-08 06:54:36 +0000501JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_init
DRCf8e00552011-02-04 11:06:36 +0000502 (JNIEnv *env, jobject obj)
503{
504 jclass cls;
505 jfieldID fid;
506 tjhandle handle;
507
DRC1a3dbe62011-02-28 10:51:55 +0000508 if((handle=tjInitDecompress())==NULL) _throw(tjGetErrorStr());
DRCf8e00552011-02-04 11:06:36 +0000509
510 bailif0(cls=(*env)->GetObjectClass(env, obj));
511 bailif0(fid=(*env)->GetFieldID(env, cls, "handle", "J"));
DRC46a03922014-08-15 14:40:05 +0000512 (*env)->SetLongField(env, obj, fid, (size_t)handle);
DRCf8e00552011-02-04 11:06:36 +0000513
514 bailout:
515 return;
516}
517
DRCa4940d12014-08-15 16:07:15 +0000518/* TurboJPEG 1.2.x: TJDecompressor::getScalingFactors() */
DRC109a5782011-03-01 09:53:07 +0000519JNIEXPORT jobjectArray JNICALL Java_org_libjpegturbo_turbojpeg_TJ_getScalingFactors
520 (JNIEnv *env, jclass cls)
DRC36336fc2011-02-22 10:27:31 +0000521{
DRCb7c8c862014-08-15 16:20:59 +0000522 jclass sfcls=NULL; jfieldID fid=0;
DRC109a5782011-03-01 09:53:07 +0000523 tjscalingfactor *sf=NULL; int n=0, i;
524 jobject sfobj=NULL;
525 jobjectArray sfjava=NULL;
526
527 if((sf=tjGetScalingFactors(&n))==NULL || n==0)
DRC36336fc2011-02-22 10:27:31 +0000528 _throw(tjGetErrorStr());
529
DRCb2f94152011-04-02 02:09:03 +0000530 bailif0(sfcls=(*env)->FindClass(env, "org/libjpegturbo/turbojpeg/TJScalingFactor"));
DRC109a5782011-03-01 09:53:07 +0000531 bailif0(sfjava=(jobjectArray)(*env)->NewObjectArray(env, n, sfcls, 0));
DRC36336fc2011-02-22 10:27:31 +0000532
DRC109a5782011-03-01 09:53:07 +0000533 for(i=0; i<n; i++)
534 {
535 bailif0(sfobj=(*env)->AllocObject(env, sfcls));
536 bailif0(fid=(*env)->GetFieldID(env, sfcls, "num", "I"));
537 (*env)->SetIntField(env, sfobj, fid, sf[i].num);
538 bailif0(fid=(*env)->GetFieldID(env, sfcls, "denom", "I"));
539 (*env)->SetIntField(env, sfobj, fid, sf[i].denom);
540 (*env)->SetObjectArrayElement(env, sfjava, i, sfobj);
541 }
DRC36336fc2011-02-22 10:27:31 +0000542
543 bailout:
DRC109a5782011-03-01 09:53:07 +0000544 return sfjava;
DRC36336fc2011-02-22 10:27:31 +0000545}
546
DRCa4940d12014-08-15 16:07:15 +0000547/* TurboJPEG 1.2.x: TJDecompressor::decompressHeader() */
DRC3bad53f2011-02-23 02:20:49 +0000548JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompressHeader
DRC9b28def2011-05-21 14:37:15 +0000549 (JNIEnv *env, jobject obj, jbyteArray src, jint jpegSize)
DRCf8e00552011-02-04 11:06:36 +0000550{
DRCf8e00552011-02-04 11:06:36 +0000551 tjhandle handle=0;
DRC9b28def2011-05-21 14:37:15 +0000552 unsigned char *jpegBuf=NULL;
DRC38cb1ec2013-08-23 04:45:43 +0000553 int width=0, height=0, jpegSubsamp=-1, jpegColorspace=-1;
DRCf8e00552011-02-04 11:06:36 +0000554
555 gethandle();
556
DRC9b28def2011-05-21 14:37:15 +0000557 if((*env)->GetArrayLength(env, src)<jpegSize)
DRC6acf52b2011-03-02 01:09:20 +0000558 _throw("Source buffer is not large enough");
559
DRC9b28def2011-05-21 14:37:15 +0000560 bailif0(jpegBuf=(*env)->GetPrimitiveArrayCritical(env, src, 0));
DRCf8e00552011-02-04 11:06:36 +0000561
DRC1a45b812014-05-09 18:06:58 +0000562 if(tjDecompressHeader3(handle, jpegBuf, (unsigned long)jpegSize,
DRC38cb1ec2013-08-23 04:45:43 +0000563 &width, &height, &jpegSubsamp, &jpegColorspace)==-1)
DRCf8e00552011-02-04 11:06:36 +0000564 _throw(tjGetErrorStr());
DRC8951cf02014-08-14 16:54:04 +0000565
DRC9b28def2011-05-21 14:37:15 +0000566 (*env)->ReleasePrimitiveArrayCritical(env, src, jpegBuf, 0); jpegBuf=NULL;
DRCf8e00552011-02-04 11:06:36 +0000567
DRC26dd86b2014-08-15 14:01:21 +0000568 bailif0(_fid=(*env)->GetFieldID(env, _cls, "jpegSubsamp", "I"));
DRC9b28def2011-05-21 14:37:15 +0000569 (*env)->SetIntField(env, obj, _fid, jpegSubsamp);
DRC26dd86b2014-08-15 14:01:21 +0000570 if((_fid=(*env)->GetFieldID(env, _cls, "jpegColorspace", "I"))==0)
571 (*env)->ExceptionClear(env);
572 else
573 (*env)->SetIntField(env, obj, _fid, jpegColorspace);
574 bailif0(_fid=(*env)->GetFieldID(env, _cls, "jpegWidth", "I"));
DRC3bad53f2011-02-23 02:20:49 +0000575 (*env)->SetIntField(env, obj, _fid, width);
DRC26dd86b2014-08-15 14:01:21 +0000576 bailif0(_fid=(*env)->GetFieldID(env, _cls, "jpegHeight", "I"));
DRC3bad53f2011-02-23 02:20:49 +0000577 (*env)->SetIntField(env, obj, _fid, height);
DRCf8e00552011-02-04 11:06:36 +0000578
579 bailout:
DRC8951cf02014-08-14 16:54:04 +0000580 if(jpegBuf) (*env)->ReleasePrimitiveArrayCritical(env, src, jpegBuf, 0);
DRC3bad53f2011-02-23 02:20:49 +0000581 return;
DRCf8e00552011-02-04 11:06:36 +0000582}
583
DRC5d87f6d2014-08-15 16:40:56 +0000584static void TJDecompressor_decompress
DRC927a10d2014-08-15 13:18:58 +0000585 (JNIEnv *env, jobject obj, jbyteArray src, jint jpegSize, jarray dst,
586 jint dstElementSize, jint x, jint y, jint width, jint pitch, jint height,
587 jint pf, jint flags)
DRCf8e00552011-02-04 11:06:36 +0000588{
DRC9b28def2011-05-21 14:37:15 +0000589 tjhandle handle=0;
DRCf659f432012-06-06 08:41:06 +0000590 jsize arraySize=0, actualPitch;
DRC9b28def2011-05-21 14:37:15 +0000591 unsigned char *jpegBuf=NULL, *dstBuf=NULL;
DRCf8e00552011-02-04 11:06:36 +0000592
593 gethandle();
594
DRC92549de2011-03-15 20:52:02 +0000595 if(pf<0 || pf>=org_libjpegturbo_turbojpeg_TJ_NUMPF)
DRC4f1580c2011-02-25 06:11:03 +0000596 _throw("Invalid argument in decompress()");
DRC9b28def2011-05-21 14:37:15 +0000597 if(org_libjpegturbo_turbojpeg_TJ_NUMPF!=TJ_NUMPF)
598 _throw("Mismatch between Java and C API");
DRC4f1580c2011-02-25 06:11:03 +0000599
DRC9b28def2011-05-21 14:37:15 +0000600 if((*env)->GetArrayLength(env, src)<jpegSize)
DRC6acf52b2011-03-02 01:09:20 +0000601 _throw("Source buffer is not large enough");
DRCf659f432012-06-06 08:41:06 +0000602 actualPitch=(pitch==0)? width*tjPixelSize[pf]:pitch;
DRCdc31f0b2012-06-07 09:38:57 +0000603 arraySize=(y+height-1)*actualPitch + (x+width)*tjPixelSize[pf];
DRC927a10d2014-08-15 13:18:58 +0000604 if((*env)->GetArrayLength(env, dst)*dstElementSize<arraySize)
DRC6acf52b2011-03-02 01:09:20 +0000605 _throw("Destination buffer is not large enough");
606
DRC9b28def2011-05-21 14:37:15 +0000607 bailif0(jpegBuf=(*env)->GetPrimitiveArrayCritical(env, src, 0));
608 bailif0(dstBuf=(*env)->GetPrimitiveArrayCritical(env, dst, 0));
DRCf8e00552011-02-04 11:06:36 +0000609
DRCf659f432012-06-06 08:41:06 +0000610 if(tjDecompress2(handle, jpegBuf, (unsigned long)jpegSize,
611 &dstBuf[y*actualPitch + x*tjPixelSize[pf]], width, pitch, height, pf,
612 flags)==-1)
DRCf659f432012-06-06 08:41:06 +0000613 _throw(tjGetErrorStr());
DRCf659f432012-06-06 08:41:06 +0000614
615 bailout:
616 if(dstBuf) (*env)->ReleasePrimitiveArrayCritical(env, dst, dstBuf, 0);
617 if(jpegBuf) (*env)->ReleasePrimitiveArrayCritical(env, src, jpegBuf, 0);
618 return;
619}
620
DRCa4940d12014-08-15 16:07:15 +0000621/* TurboJPEG 1.3.x: TJDecompressor::decompress() byte destination */
DRC927a10d2014-08-15 13:18:58 +0000622JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompress___3BI_3BIIIIIII
623 (JNIEnv *env, jobject obj, jbyteArray src, jint jpegSize, jbyteArray dst,
624 jint x, jint y, jint width, jint pitch, jint height, jint pf, jint flags)
625{
626 TJDecompressor_decompress(env, obj, src, jpegSize, dst, 1, x, y, width,
627 pitch, height, pf, flags);
628}
629
DRCa4940d12014-08-15 16:07:15 +0000630/* TurboJPEG 1.2.x: TJDecompressor::decompress() byte destination */
DRCf659f432012-06-06 08:41:06 +0000631JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompress___3BI_3BIIIII
632 (JNIEnv *env, jobject obj, jbyteArray src, jint jpegSize, jbyteArray dst,
633 jint width, jint pitch, jint height, jint pf, jint flags)
634{
DRC927a10d2014-08-15 13:18:58 +0000635 TJDecompressor_decompress(env, obj, src, jpegSize, dst, 1, 0, 0, width,
636 pitch, height, pf, flags);
DRCf659f432012-06-06 08:41:06 +0000637}
638
DRCa4940d12014-08-15 16:07:15 +0000639/* TurboJPEG 1.3.x: TJDecompressor::decompress() int destination */
DRCf659f432012-06-06 08:41:06 +0000640JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompress___3BI_3IIIIIIII
641 (JNIEnv *env, jobject obj, jbyteArray src, jint jpegSize, jintArray dst,
642 jint x, jint y, jint width, jint stride, jint height, jint pf, jint flags)
643{
DRCf659f432012-06-06 08:41:06 +0000644 if(pf<0 || pf>=org_libjpegturbo_turbojpeg_TJ_NUMPF)
645 _throw("Invalid argument in decompress()");
DRCf659f432012-06-06 08:41:06 +0000646 if(tjPixelSize[pf]!=sizeof(jint))
647 _throw("Pixel format must be 32-bit when decompressing to an integer buffer.");
648
DRC927a10d2014-08-15 13:18:58 +0000649 TJDecompressor_decompress(env, obj, src, jpegSize, dst, sizeof(jint), x, y,
650 width, stride*sizeof(jint), height, pf, flags);
DRCf8e00552011-02-04 11:06:36 +0000651
652 bailout:
DRCf8e00552011-02-04 11:06:36 +0000653 return;
654}
655
DRCa4940d12014-08-15 16:07:15 +0000656/* TurboJPEG 1.2.x: TJDecompressor::decompress() int destination */
DRC4f1580c2011-02-25 06:11:03 +0000657JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompress___3BI_3IIIIII
DRC9b28def2011-05-21 14:37:15 +0000658 (JNIEnv *env, jobject obj, jbyteArray src, jint jpegSize, jintArray dst,
DRCf659f432012-06-06 08:41:06 +0000659 jint width, jint stride, jint height, jint pf, jint flags)
DRC84a1bcc2011-02-23 12:09:56 +0000660{
DRC927a10d2014-08-15 13:18:58 +0000661 if(pf<0 || pf>=org_libjpegturbo_turbojpeg_TJ_NUMPF)
662 _throw("Invalid argument in decompress()");
663 if(tjPixelSize[pf]!=sizeof(jint))
664 _throw("Pixel format must be 32-bit when decompressing to an integer buffer.");
665
666 TJDecompressor_decompress(env, obj, src, jpegSize, dst, sizeof(jint), 0, 0,
667 width, stride*sizeof(jint), height, pf, flags);
668
669 bailout:
670 return;
DRC1a45b812014-05-09 18:06:58 +0000671
DRC4f1580c2011-02-25 06:11:03 +0000672}
DRC84a1bcc2011-02-23 12:09:56 +0000673
DRCa4940d12014-08-15 16:07:15 +0000674/* TurboJPEG 1.4.x: TJDecompressor::decompressToYUV() */
DRC40dd3142014-08-17 12:23:49 +0000675JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompressToYUV___3BI_3_3B_3II_3III
676 (JNIEnv *env, jobject obj, jbyteArray src, jint jpegSize,
677 jobjectArray dstobjs, jintArray jDstOffsets, jint desiredWidth,
678 jintArray jDstStrides, jint desiredHeight, jint flags)
DRC4f1580c2011-02-25 06:11:03 +0000679{
680 tjhandle handle=0;
DRC40dd3142014-08-17 12:23:49 +0000681 jbyteArray jDstPlanes[3]={NULL, NULL, NULL};
682 unsigned char *jpegBuf=NULL, *dstPlanes[3];
683 int *dstOffsets=NULL, *dstStrides=NULL;
DRC6acf52b2011-03-02 01:09:20 +0000684 int jpegSubsamp=-1, jpegWidth=0, jpegHeight=0;
DRC40dd3142014-08-17 12:23:49 +0000685 int nc=0, i, width, height, scaledWidth, scaledHeight, nsf=0;
686 tjscalingfactor *sf;
687
DRC4f1580c2011-02-25 06:11:03 +0000688
689 gethandle();
690
DRC9b28def2011-05-21 14:37:15 +0000691 if((*env)->GetArrayLength(env, src)<jpegSize)
DRC6acf52b2011-03-02 01:09:20 +0000692 _throw("Source buffer is not large enough");
DRC26dd86b2014-08-15 14:01:21 +0000693 bailif0(_fid=(*env)->GetFieldID(env, _cls, "jpegSubsamp", "I"));
DRC6acf52b2011-03-02 01:09:20 +0000694 jpegSubsamp=(int)(*env)->GetIntField(env, obj, _fid);
DRC26dd86b2014-08-15 14:01:21 +0000695 bailif0(_fid=(*env)->GetFieldID(env, _cls, "jpegWidth", "I"));
DRC6acf52b2011-03-02 01:09:20 +0000696 jpegWidth=(int)(*env)->GetIntField(env, obj, _fid);
DRC26dd86b2014-08-15 14:01:21 +0000697 bailif0(_fid=(*env)->GetFieldID(env, _cls, "jpegHeight", "I"));
DRC6acf52b2011-03-02 01:09:20 +0000698 jpegHeight=(int)(*env)->GetIntField(env, obj, _fid);
DRC6acf52b2011-03-02 01:09:20 +0000699
DRC40dd3142014-08-17 12:23:49 +0000700 nc=(jpegSubsamp==org_libjpegturbo_turbojpeg_TJ_SAMP_GRAY? 1:3);
DRC4f1580c2011-02-25 06:11:03 +0000701
DRC40dd3142014-08-17 12:23:49 +0000702 width=desiredWidth; height=desiredHeight;
703 if(width==0) width=jpegWidth;
704 if(height==0) height=jpegHeight;
705 sf=tjGetScalingFactors(&nsf);
706 if(!sf || nsf<1)
707 _throw(tjGetErrorStr());
708 for(i=0; i<nsf; i++)
709 {
710 scaledWidth=TJSCALED(jpegWidth, sf[i]);
711 scaledHeight=TJSCALED(jpegHeight, sf[i]);
712 if(scaledWidth<=width && scaledHeight<=height)
713 break;
714 }
715
716 bailif0(dstOffsets=(*env)->GetPrimitiveArrayCritical(env, jDstOffsets, 0));
717 bailif0(dstStrides=(*env)->GetPrimitiveArrayCritical(env, jDstStrides, 0));
718 for(i=0; i<nc; i++)
719 {
720 int planeSize=tjPlaneSizeYUV(i, scaledWidth, dstStrides[i], scaledHeight,
721 jpegSubsamp);
722 int pw=tjPlaneWidth(i, scaledWidth, jpegSubsamp);
723
724 if(planeSize<0 || pw<0)
725 _throw(tjGetErrorStr());
726
727 if(dstOffsets[i]<0)
728 _throw("Invalid argument in decompressToYUV()");
729 if(dstStrides[i]<0 && dstOffsets[i]-planeSize+pw<0)
730 _throw("Negative plane stride would cause memory to be accessed below plane boundary");
731
732 bailif0(jDstPlanes[i]=(*env)->GetObjectArrayElement(env, dstobjs, i));
733 if((*env)->GetArrayLength(env, jDstPlanes[i])<dstOffsets[i]+planeSize)
734 _throw("Destination plane is not large enough");
735
736 bailif0(dstPlanes[i]=(*env)->GetPrimitiveArrayCritical(env, jDstPlanes[i],
737 0));
738 dstPlanes[i]=&dstPlanes[i][dstOffsets[i]];
739 }
740 bailif0(jpegBuf=(*env)->GetPrimitiveArrayCritical(env, src, 0));
741
742 if(tjDecompressToYUVPlanes(handle, jpegBuf, (unsigned long)jpegSize,
743 dstPlanes, desiredWidth, dstStrides, desiredHeight, flags)==-1)
DRC4f1580c2011-02-25 06:11:03 +0000744 _throw(tjGetErrorStr());
DRC4f1580c2011-02-25 06:11:03 +0000745
746 bailout:
DRC9b28def2011-05-21 14:37:15 +0000747 if(jpegBuf) (*env)->ReleasePrimitiveArrayCritical(env, src, jpegBuf, 0);
DRC40dd3142014-08-17 12:23:49 +0000748 for(i=0; i<nc; i++)
749 {
750 if(dstPlanes[i] && jDstPlanes[i])
751 (*env)->ReleasePrimitiveArrayCritical(env, jDstPlanes[i], dstPlanes[i],
752 0);
753 }
754 if(dstStrides)
755 (*env)->ReleasePrimitiveArrayCritical(env, jDstStrides, dstStrides, 0);
756 if(dstOffsets)
757 (*env)->ReleasePrimitiveArrayCritical(env, jDstOffsets, dstOffsets, 0);
DRC4f1580c2011-02-25 06:11:03 +0000758 return;
DRC84a1bcc2011-02-23 12:09:56 +0000759}
760
DRCa4940d12014-08-15 16:07:15 +0000761/* TurboJPEG 1.2.x: TJDecompressor::decompressToYUV() */
DRCfef98522013-04-28 01:32:52 +0000762JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompressToYUV___3BI_3BI
763 (JNIEnv *env, jobject obj, jbyteArray src, jint jpegSize, jbyteArray dst,
764 jint flags)
765{
DRCfc26b652014-03-16 22:56:26 +0000766 tjhandle handle=0;
DRC40dd3142014-08-17 12:23:49 +0000767 unsigned char *jpegBuf=NULL, *dstBuf=NULL;
768 int jpegSubsamp=-1, jpegWidth=0, jpegHeight=0;
DRCfc26b652014-03-16 22:56:26 +0000769
770 gethandle();
771
DRC40dd3142014-08-17 12:23:49 +0000772 if((*env)->GetArrayLength(env, src)<jpegSize)
773 _throw("Source buffer is not large enough");
774 bailif0(_fid=(*env)->GetFieldID(env, _cls, "jpegSubsamp", "I"));
775 jpegSubsamp=(int)(*env)->GetIntField(env, obj, _fid);
776 bailif0(_fid=(*env)->GetFieldID(env, _cls, "jpegWidth", "I"));
777 jpegWidth=(int)(*env)->GetIntField(env, obj, _fid);
778 bailif0(_fid=(*env)->GetFieldID(env, _cls, "jpegHeight", "I"));
779 jpegHeight=(int)(*env)->GetIntField(env, obj, _fid);
780 if((*env)->GetArrayLength(env, dst)
781 <(jsize)tjBufSizeYUV(jpegWidth, jpegHeight, jpegSubsamp))
782 _throw("Destination buffer is not large enough");
783
784 bailif0(jpegBuf=(*env)->GetPrimitiveArrayCritical(env, src, 0));
785 bailif0(dstBuf=(*env)->GetPrimitiveArrayCritical(env, dst, 0));
786
787 if(tjDecompressToYUV(handle, jpegBuf, (unsigned long)jpegSize, dstBuf,
788 flags)==-1)
789 _throw(tjGetErrorStr());
790
791 bailout:
792 if(dstBuf) (*env)->ReleasePrimitiveArrayCritical(env, dst, dstBuf, 0);
793 if(jpegBuf) (*env)->ReleasePrimitiveArrayCritical(env, src, jpegBuf, 0);
794 return;
795}
796
797static void TJDecompressor_decodeYUV
798 (JNIEnv *env, jobject obj, jobjectArray srcobjs, jintArray jSrcOffsets,
799 jintArray jSrcStrides, jint subsamp, jarray dst, jint dstElementSize,
800 jint x, jint y, jint width, jint pitch, jint height, jint pf, jint flags)
801{
802 tjhandle handle=0;
803 jsize arraySize=0, actualPitch;
804 jbyteArray jSrcPlanes[3]={NULL, NULL, NULL};
805 unsigned char *srcPlanes[3], *dstBuf=NULL;
806 int *srcOffsets=NULL, *srcStrides=NULL;
807 int nc=(subsamp==org_libjpegturbo_turbojpeg_TJ_SAMP_GRAY? 1:3), i;
808
809 gethandle();
810
811 if(pf<0 || pf>=org_libjpegturbo_turbojpeg_TJ_NUMPF || subsamp<0
812 || subsamp>=org_libjpegturbo_turbojpeg_TJ_NUMSAMP)
DRCfc26b652014-03-16 22:56:26 +0000813 _throw("Invalid argument in decodeYUV()");
DRC40dd3142014-08-17 12:23:49 +0000814 if(org_libjpegturbo_turbojpeg_TJ_NUMPF!=TJ_NUMPF
815 || org_libjpegturbo_turbojpeg_TJ_NUMSAMP!=TJ_NUMSAMP)
DRCfc26b652014-03-16 22:56:26 +0000816 _throw("Mismatch between Java and C API");
817
DRC40dd3142014-08-17 12:23:49 +0000818 if((*env)->GetArrayLength(env, srcobjs)<nc)
819 _throw("Planes array is too small for the subsampling type");
820 if((*env)->GetArrayLength(env, jSrcOffsets)<nc)
821 _throw("Offsets array is too small for the subsampling type");
822 if((*env)->GetArrayLength(env, jSrcStrides)<nc)
823 _throw("Strides array is too small for the subsampling type");
824
DRCfc26b652014-03-16 22:56:26 +0000825 actualPitch=(pitch==0)? width*tjPixelSize[pf]:pitch;
826 arraySize=(y+height-1)*actualPitch + (x+width)*tjPixelSize[pf];
DRC927a10d2014-08-15 13:18:58 +0000827 if((*env)->GetArrayLength(env, dst)*dstElementSize<arraySize)
DRCfc26b652014-03-16 22:56:26 +0000828 _throw("Destination buffer is not large enough");
829
DRC40dd3142014-08-17 12:23:49 +0000830 bailif0(srcOffsets=(*env)->GetPrimitiveArrayCritical(env, jSrcOffsets, 0));
831 bailif0(srcStrides=(*env)->GetPrimitiveArrayCritical(env, jSrcStrides, 0));
832 for(i=0; i<nc; i++)
833 {
834 int planeSize=tjPlaneSizeYUV(i, width, srcStrides[i], height, subsamp);
835 int pw=tjPlaneWidth(i, width, subsamp);
836
837 if(planeSize<0 || pw<0)
838 _throw(tjGetErrorStr());
839
840 if(srcOffsets[i]<0)
841 _throw("Invalid argument in decodeYUV()");
842 if(srcStrides[i]<0 && srcOffsets[i]-planeSize+pw<0)
843 _throw("Negative plane stride would cause memory to be accessed below plane boundary");
844
845 bailif0(jSrcPlanes[i]=(*env)->GetObjectArrayElement(env, srcobjs, i));
846 if((*env)->GetArrayLength(env, jSrcPlanes[i])<srcOffsets[i]+planeSize)
847 _throw("Source plane is not large enough");
848
849 bailif0(srcPlanes[i]=(*env)->GetPrimitiveArrayCritical(env, jSrcPlanes[i],
850 0));
851 srcPlanes[i]=&srcPlanes[i][srcOffsets[i]];
852 }
DRCfc26b652014-03-16 22:56:26 +0000853 bailif0(dstBuf=(*env)->GetPrimitiveArrayCritical(env, dst, 0));
854
DRC40dd3142014-08-17 12:23:49 +0000855 if(tjDecodeYUVPlanes(handle, srcPlanes, srcStrides, subsamp,
DRCfc26b652014-03-16 22:56:26 +0000856 &dstBuf[y*actualPitch + x*tjPixelSize[pf]], width, pitch, height, pf,
857 flags)==-1)
DRCfc26b652014-03-16 22:56:26 +0000858 _throw(tjGetErrorStr());
DRCfc26b652014-03-16 22:56:26 +0000859
860 bailout:
861 if(dstBuf) (*env)->ReleasePrimitiveArrayCritical(env, dst, dstBuf, 0);
DRC40dd3142014-08-17 12:23:49 +0000862 for(i=0; i<nc; i++)
863 {
864 if(srcPlanes[i] && jSrcPlanes[i])
865 (*env)->ReleasePrimitiveArrayCritical(env, jSrcPlanes[i], srcPlanes[i],
866 0);
867 }
868 if(srcStrides)
869 (*env)->ReleasePrimitiveArrayCritical(env, jSrcStrides, srcStrides, 0);
870 if(srcOffsets)
871 (*env)->ReleasePrimitiveArrayCritical(env, jSrcOffsets, srcOffsets, 0);
DRCfc26b652014-03-16 22:56:26 +0000872 return;
873}
874
DRCa4940d12014-08-15 16:07:15 +0000875/* TurboJPEG 1.4.x: TJDecompressor::decodeYUV() byte destination */
DRC40dd3142014-08-17 12:23:49 +0000876JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decodeYUV___3_3B_3I_3II_3BIIIIIII
877 (JNIEnv *env, jobject obj, jobjectArray srcobjs, jintArray jSrcOffsets,
878 jintArray jSrcStrides, jint subsamp, jbyteArray dst, jint x, jint y,
879 jint width, jint pitch, jint height, jint pf, jint flags)
DRC927a10d2014-08-15 13:18:58 +0000880{
DRC40dd3142014-08-17 12:23:49 +0000881 TJDecompressor_decodeYUV(env, obj, srcobjs, jSrcOffsets, jSrcStrides,
882 subsamp, dst, 1, x, y, width, pitch, height, pf, flags);
DRC927a10d2014-08-15 13:18:58 +0000883}
884
DRCa4940d12014-08-15 16:07:15 +0000885/* TurboJPEG 1.4.x: TJDecompressor::decodeYUV() int destination */
DRC40dd3142014-08-17 12:23:49 +0000886JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decodeYUV___3_3B_3I_3II_3IIIIIIII
887 (JNIEnv *env, jobject obj, jobjectArray srcobjs, jintArray jSrcOffsets,
888 jintArray jSrcStrides, jint subsamp, jintArray dst, jint x, jint y,
889 jint width, jint stride, jint height, jint pf, jint flags)
DRCfc26b652014-03-16 22:56:26 +0000890{
DRCfc26b652014-03-16 22:56:26 +0000891 if(pf<0 || pf>=org_libjpegturbo_turbojpeg_TJ_NUMPF)
892 _throw("Invalid argument in decodeYUV()");
DRCfc26b652014-03-16 22:56:26 +0000893 if(tjPixelSize[pf]!=sizeof(jint))
894 _throw("Pixel format must be 32-bit when decoding to an integer buffer.");
895
DRC40dd3142014-08-17 12:23:49 +0000896 TJDecompressor_decodeYUV(env, obj, srcobjs, jSrcOffsets, jSrcStrides,
897 subsamp, dst, sizeof(jint), x, y, width, stride*sizeof(jint), height, pf,
898 flags);
DRCfc26b652014-03-16 22:56:26 +0000899
900 bailout:
DRCfc26b652014-03-16 22:56:26 +0000901 return;
902}
903
DRCa4940d12014-08-15 16:07:15 +0000904/* TurboJPEG 1.2.x: TJTransformer::init() */
DRCe8573012011-03-04 10:13:59 +0000905JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJTransformer_init
906 (JNIEnv *env, jobject obj)
907{
908 jclass cls;
909 jfieldID fid;
910 tjhandle handle;
911
912 if((handle=tjInitTransform())==NULL) _throw(tjGetErrorStr());
913
914 bailif0(cls=(*env)->GetObjectClass(env, obj));
915 bailif0(fid=(*env)->GetFieldID(env, cls, "handle", "J"));
DRC46a03922014-08-15 14:40:05 +0000916 (*env)->SetLongField(env, obj, fid, (size_t)handle);
DRCe8573012011-03-04 10:13:59 +0000917
918 bailout:
919 return;
920}
921
DRCf5467112011-09-20 05:02:19 +0000922typedef struct _JNICustomFilterParams
923{
924 JNIEnv *env;
925 jobject tobj;
926 jobject cfobj;
927} JNICustomFilterParams;
928
929static int JNICustomFilter(short *coeffs, tjregion arrayRegion,
930 tjregion planeRegion, int componentIndex, int transformIndex,
931 tjtransform *transform)
932{
933 JNICustomFilterParams *params=(JNICustomFilterParams *)transform->data;
934 JNIEnv *env=params->env;
935 jobject tobj=params->tobj, cfobj=params->cfobj;
DRCb7c8c862014-08-15 16:20:59 +0000936 jobject arrayRegionObj, planeRegionObj, bufobj, borobj;
DRCf5467112011-09-20 05:02:19 +0000937 jclass cls; jmethodID mid; jfieldID fid;
938
939 bailif0(bufobj=(*env)->NewDirectByteBuffer(env, coeffs,
940 sizeof(short)*arrayRegion.w*arrayRegion.h));
941 bailif0(cls=(*env)->FindClass(env, "java/nio/ByteOrder"));
DRCb7c8c862014-08-15 16:20:59 +0000942 bailif0(mid=(*env)->GetStaticMethodID(env, cls, "nativeOrder",
DRCf5467112011-09-20 05:02:19 +0000943 "()Ljava/nio/ByteOrder;"));
944 bailif0(borobj=(*env)->CallStaticObjectMethod(env, cls, mid));
945 bailif0(cls=(*env)->GetObjectClass(env, bufobj));
946 bailif0(mid=(*env)->GetMethodID(env, cls, "order",
947 "(Ljava/nio/ByteOrder;)Ljava/nio/ByteBuffer;"));
948 (*env)->CallObjectMethod(env, bufobj, mid, borobj);
DRCb7c8c862014-08-15 16:20:59 +0000949 bailif0(mid=(*env)->GetMethodID(env, cls, "asShortBuffer",
DRCf5467112011-09-20 05:02:19 +0000950 "()Ljava/nio/ShortBuffer;"));
951 bailif0(bufobj=(*env)->CallObjectMethod(env, bufobj, mid));
952
953 bailif0(cls=(*env)->FindClass(env, "java/awt/Rectangle"));
954 bailif0(arrayRegionObj=(*env)->AllocObject(env, cls));
955 bailif0(fid=(*env)->GetFieldID(env, cls, "x", "I"));
956 (*env)->SetIntField(env, arrayRegionObj, fid, arrayRegion.x);
957 bailif0(fid=(*env)->GetFieldID(env, cls, "y", "I"));
958 (*env)->SetIntField(env, arrayRegionObj, fid, arrayRegion.y);
959 bailif0(fid=(*env)->GetFieldID(env, cls, "width", "I"));
960 (*env)->SetIntField(env, arrayRegionObj, fid, arrayRegion.w);
961 bailif0(fid=(*env)->GetFieldID(env, cls, "height", "I"));
962 (*env)->SetIntField(env, arrayRegionObj, fid, arrayRegion.h);
963
964 bailif0(planeRegionObj=(*env)->AllocObject(env, cls));
965 bailif0(fid=(*env)->GetFieldID(env, cls, "x", "I"));
966 (*env)->SetIntField(env, planeRegionObj, fid, planeRegion.x);
967 bailif0(fid=(*env)->GetFieldID(env, cls, "y", "I"));
968 (*env)->SetIntField(env, planeRegionObj, fid, planeRegion.y);
969 bailif0(fid=(*env)->GetFieldID(env, cls, "width", "I"));
970 (*env)->SetIntField(env, planeRegionObj, fid, planeRegion.w);
971 bailif0(fid=(*env)->GetFieldID(env, cls, "height", "I"));
972 (*env)->SetIntField(env, planeRegionObj, fid, planeRegion.h);
973
974 bailif0(cls=(*env)->GetObjectClass(env, cfobj));
975 bailif0(mid=(*env)->GetMethodID(env, cls, "customFilter",
976 "(Ljava/nio/ShortBuffer;Ljava/awt/Rectangle;Ljava/awt/Rectangle;IILorg/libjpegturbo/turbojpeg/TJTransform;)V"));
977 (*env)->CallVoidMethod(env, cfobj, mid, bufobj, arrayRegionObj,
978 planeRegionObj, componentIndex, transformIndex, tobj);
979
980 return 0;
981
982 bailout:
983 return -1;
984}
985
DRCa4940d12014-08-15 16:07:15 +0000986/* TurboJPEG 1.2.x: TJTransformer::transform() */
DRCe8573012011-03-04 10:13:59 +0000987JNIEXPORT jintArray JNICALL Java_org_libjpegturbo_turbojpeg_TJTransformer_transform
DRC9b28def2011-05-21 14:37:15 +0000988 (JNIEnv *env, jobject obj, jbyteArray jsrcBuf, jint jpegSize,
DRCe8573012011-03-04 10:13:59 +0000989 jobjectArray dstobjs, jobjectArray tobjs, jint flags)
990{
991 tjhandle handle=0; int i;
DRC9b28def2011-05-21 14:37:15 +0000992 unsigned char *jpegBuf=NULL, **dstBufs=NULL; jsize n=0;
993 unsigned long *dstSizes=NULL; tjtransform *t=NULL;
994 jbyteArray *jdstBufs=NULL;
DRC9b49f0e2011-07-12 03:17:23 +0000995 int jpegWidth=0, jpegHeight=0, jpegSubsamp;
DRC9b28def2011-05-21 14:37:15 +0000996 jintArray jdstSizes=0; jint *dstSizesi=NULL;
DRCf5467112011-09-20 05:02:19 +0000997 JNICustomFilterParams *params=NULL;
DRCe8573012011-03-04 10:13:59 +0000998
999 gethandle();
1000
DRC9b28def2011-05-21 14:37:15 +00001001 if((*env)->GetArrayLength(env, jsrcBuf)<jpegSize)
DRCe8573012011-03-04 10:13:59 +00001002 _throw("Source buffer is not large enough");
DRC26dd86b2014-08-15 14:01:21 +00001003 bailif0(_fid=(*env)->GetFieldID(env, _cls, "jpegWidth", "I"));
DRCe8573012011-03-04 10:13:59 +00001004 jpegWidth=(int)(*env)->GetIntField(env, obj, _fid);
DRC26dd86b2014-08-15 14:01:21 +00001005 bailif0(_fid=(*env)->GetFieldID(env, _cls, "jpegHeight", "I"));
DRCe8573012011-03-04 10:13:59 +00001006 jpegHeight=(int)(*env)->GetIntField(env, obj, _fid);
DRC26dd86b2014-08-15 14:01:21 +00001007 bailif0(_fid=(*env)->GetFieldID(env, _cls, "jpegSubsamp", "I"));
DRC9b49f0e2011-07-12 03:17:23 +00001008 jpegSubsamp=(int)(*env)->GetIntField(env, obj, _fid);
DRCe8573012011-03-04 10:13:59 +00001009
1010 n=(*env)->GetArrayLength(env, dstobjs);
1011 if(n!=(*env)->GetArrayLength(env, tobjs))
1012 _throw("Mismatch between size of transforms array and destination buffers array");
1013
DRC9b28def2011-05-21 14:37:15 +00001014 if((dstBufs=(unsigned char **)malloc(sizeof(unsigned char *)*n))==NULL)
DRCe8573012011-03-04 10:13:59 +00001015 _throw("Memory allocation failure");
DRC9b28def2011-05-21 14:37:15 +00001016 if((jdstBufs=(jbyteArray *)malloc(sizeof(jbyteArray)*n))==NULL)
DRCe8573012011-03-04 10:13:59 +00001017 _throw("Memory allocation failure");
DRC9b28def2011-05-21 14:37:15 +00001018 if((dstSizes=(unsigned long *)malloc(sizeof(unsigned long)*n))==NULL)
DRCe8573012011-03-04 10:13:59 +00001019 _throw("Memory allocation failure");
1020 if((t=(tjtransform *)malloc(sizeof(tjtransform)*n))==NULL)
1021 _throw("Memory allocation failure");
DRCf5467112011-09-20 05:02:19 +00001022 if((params=(JNICustomFilterParams *)malloc(sizeof(JNICustomFilterParams)*n))
1023 ==NULL)
1024 _throw("Memory allocation failure");
DRCe8573012011-03-04 10:13:59 +00001025 for(i=0; i<n; i++)
1026 {
DRC9b28def2011-05-21 14:37:15 +00001027 dstBufs[i]=NULL; jdstBufs[i]=NULL; dstSizes[i]=0;
DRCe8573012011-03-04 10:13:59 +00001028 memset(&t[i], 0, sizeof(tjtransform));
DRCf5467112011-09-20 05:02:19 +00001029 memset(&params[i], 0, sizeof(JNICustomFilterParams));
DRCe8573012011-03-04 10:13:59 +00001030 }
1031
1032 for(i=0; i<n; i++)
1033 {
DRCf5467112011-09-20 05:02:19 +00001034 jobject tobj, cfobj;
DRCe8573012011-03-04 10:13:59 +00001035
1036 bailif0(tobj=(*env)->GetObjectArrayElement(env, tobjs, i));
1037 bailif0(_cls=(*env)->GetObjectClass(env, tobj));
1038 bailif0(_fid=(*env)->GetFieldID(env, _cls, "op", "I"));
1039 t[i].op=(*env)->GetIntField(env, tobj, _fid);
1040 bailif0(_fid=(*env)->GetFieldID(env, _cls, "options", "I"));
1041 t[i].options=(*env)->GetIntField(env, tobj, _fid);
1042 bailif0(_fid=(*env)->GetFieldID(env, _cls, "x", "I"));
1043 t[i].r.x=(*env)->GetIntField(env, tobj, _fid);
1044 bailif0(_fid=(*env)->GetFieldID(env, _cls, "y", "I"));
1045 t[i].r.y=(*env)->GetIntField(env, tobj, _fid);
1046 bailif0(_fid=(*env)->GetFieldID(env, _cls, "width", "I"));
1047 t[i].r.w=(*env)->GetIntField(env, tobj, _fid);
1048 bailif0(_fid=(*env)->GetFieldID(env, _cls, "height", "I"));
1049 t[i].r.h=(*env)->GetIntField(env, tobj, _fid);
DRCf5467112011-09-20 05:02:19 +00001050
DRCf5467112011-09-20 05:02:19 +00001051 bailif0(_fid=(*env)->GetFieldID(env, _cls, "cf",
1052 "Lorg/libjpegturbo/turbojpeg/TJCustomFilter;"));
DRC06420c42011-09-26 18:46:09 +00001053 cfobj=(*env)->GetObjectField(env, tobj, _fid);
1054 if(cfobj)
1055 {
1056 params[i].env=env;
1057 params[i].tobj=tobj;
1058 params[i].cfobj=cfobj;
1059 t[i].customFilter=JNICustomFilter;
1060 t[i].data=(void *)&params[i];
1061 }
DRCe8573012011-03-04 10:13:59 +00001062 }
1063
DRCe8573012011-03-04 10:13:59 +00001064 for(i=0; i<n; i++)
1065 {
1066 int w=jpegWidth, h=jpegHeight;
1067 if(t[i].r.w!=0) w=t[i].r.w;
1068 if(t[i].r.h!=0) h=t[i].r.h;
DRC9b28def2011-05-21 14:37:15 +00001069 bailif0(jdstBufs[i]=(*env)->GetObjectArrayElement(env, dstobjs, i));
DRCefe28ce2012-01-17 11:48:38 +00001070 if((unsigned long)(*env)->GetArrayLength(env, jdstBufs[i])
1071 <tjBufSize(w, h, jpegSubsamp))
DRCe8573012011-03-04 10:13:59 +00001072 _throw("Destination buffer is not large enough");
DRCe8573012011-03-04 10:13:59 +00001073 }
DRC8951cf02014-08-14 16:54:04 +00001074 bailif0(jpegBuf=(*env)->GetPrimitiveArrayCritical(env, jsrcBuf, 0));
1075 for(i=0; i<n; i++)
1076 bailif0(dstBufs[i]=(*env)->GetPrimitiveArrayCritical(env, jdstBufs[i], 0));
DRCe8573012011-03-04 10:13:59 +00001077
DRC9b28def2011-05-21 14:37:15 +00001078 if(tjTransform(handle, jpegBuf, jpegSize, n, dstBufs, dstSizes, t,
DRC4db92ad2011-05-25 04:52:25 +00001079 flags|TJFLAG_NOREALLOC)==-1)
DRCe8573012011-03-04 10:13:59 +00001080 _throw(tjGetErrorStr());
DRC8951cf02014-08-14 16:54:04 +00001081
1082 for(i=0; i<n; i++)
1083 {
1084 (*env)->ReleasePrimitiveArrayCritical(env, jdstBufs[i], dstBufs[i], 0);
1085 dstBufs[i]=NULL;
DRCe8573012011-03-04 10:13:59 +00001086 }
DRC8951cf02014-08-14 16:54:04 +00001087 (*env)->ReleasePrimitiveArrayCritical(env, jsrcBuf, jpegBuf, 0);
1088 jpegBuf=NULL;
DRCe8573012011-03-04 10:13:59 +00001089
DRC9b28def2011-05-21 14:37:15 +00001090 jdstSizes=(*env)->NewIntArray(env, n);
1091 bailif0(dstSizesi=(*env)->GetIntArrayElements(env, jdstSizes, 0));
1092 for(i=0; i<n; i++) dstSizesi[i]=(int)dstSizes[i];
DRCe8573012011-03-04 10:13:59 +00001093
1094 bailout:
DRC8951cf02014-08-14 16:54:04 +00001095 if(dstSizesi) (*env)->ReleaseIntArrayElements(env, jdstSizes, dstSizesi, 0);
DRC9b28def2011-05-21 14:37:15 +00001096 if(dstBufs)
DRCe8573012011-03-04 10:13:59 +00001097 {
1098 for(i=0; i<n; i++)
1099 {
DRC9b28def2011-05-21 14:37:15 +00001100 if(dstBufs[i] && jdstBufs && jdstBufs[i])
1101 (*env)->ReleasePrimitiveArrayCritical(env, jdstBufs[i], dstBufs[i], 0);
DRCe8573012011-03-04 10:13:59 +00001102 }
DRC9b28def2011-05-21 14:37:15 +00001103 free(dstBufs);
DRCe8573012011-03-04 10:13:59 +00001104 }
DRC8951cf02014-08-14 16:54:04 +00001105 if(jpegBuf) (*env)->ReleasePrimitiveArrayCritical(env, jsrcBuf, jpegBuf, 0);
DRC9b28def2011-05-21 14:37:15 +00001106 if(jdstBufs) free(jdstBufs);
1107 if(dstSizes) free(dstSizes);
DRCe8573012011-03-04 10:13:59 +00001108 if(t) free(t);
DRC9b28def2011-05-21 14:37:15 +00001109 return jdstSizes;
DRCe8573012011-03-04 10:13:59 +00001110}
1111
DRCa4940d12014-08-15 16:07:15 +00001112/* TurboJPEG 1.2.x: TJDecompressor::destroy() */
DRCc5a41992011-02-08 06:54:36 +00001113JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_destroy
DRCf8e00552011-02-04 11:06:36 +00001114 (JNIEnv *env, jobject obj)
1115{
DRCc5a41992011-02-08 06:54:36 +00001116 Java_org_libjpegturbo_turbojpeg_TJCompressor_destroy(env, obj);
DRCf8e00552011-02-04 11:06:36 +00001117}