blob: 4d9900c91939faea68ffc6b60ba1f4adea555ed5 [file] [log] [blame]
DRCf8e00552011-02-04 11:06:36 +00001/*
DRC1a4778f2015-07-07 16:39:03 +00002 * Copyright (C)2011-2015 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
DRCb3817da2015-07-14 20:42:52 +000042#define _throw(msg, exceptionClass) { \
43 jclass _exccls=(*env)->FindClass(env, exceptionClass); \
44 if(!_exccls || (*env)->ExceptionCheck(env)) goto bailout; \
DRCf8e00552011-02-04 11:06:36 +000045 (*env)->ThrowNew(env, _exccls, msg); \
46 goto bailout; \
47}
48
DRC739edeb2015-07-21 09:34:02 -050049#define _throwtj() _throw(tjGetErrorStr(), "org/libjpegturbo/turbojpeg/TJException")
DRCb3817da2015-07-14 20:42:52 +000050
51#define _throwarg(msg) _throw(msg, "java/lang/IllegalArgumentException")
52
53#define _throwmem() _throw("Memory allocation failure", "java/lang/OutOfMemoryError");
54
55#define bailif0(f) {if(!(f) || (*env)->ExceptionCheck(env)) { \
56 goto bailout; \
DRCfac3bea2012-09-24 02:27:55 +000057}}
DRCf8e00552011-02-04 11:06:36 +000058
DRC3bad53f2011-02-23 02:20:49 +000059#define gethandle() \
DRCf8e00552011-02-04 11:06:36 +000060 jclass _cls=(*env)->GetObjectClass(env, obj); \
61 jfieldID _fid; \
DRCb3817da2015-07-14 20:42:52 +000062 if(!_cls || (*env)->ExceptionCheck(env)) goto bailout; \
DRCf8e00552011-02-04 11:06:36 +000063 bailif0(_fid=(*env)->GetFieldID(env, _cls, "handle", "J")); \
DRC46a03922014-08-15 14:40:05 +000064 handle=(tjhandle)(size_t)(*env)->GetLongField(env, obj, _fid); \
DRCf8e00552011-02-04 11:06:36 +000065
DRCbdb36e12014-08-22 15:39:32 +000066#ifdef _WIN32
67#define setenv(envvar, value, dummy) _putenv_s(envvar, value)
68#endif
69
DRC0713c1b2014-08-22 13:43:33 +000070#define prop2env(property, envvar) \
71{ \
72 if((jName=(*env)->NewStringUTF(env, property))!=NULL \
73 && (jValue=(*env)->CallStaticObjectMethod(env, cls, mid, jName))!=NULL) \
74 { \
75 if((value=(*env)->GetStringUTFChars(env, jValue, 0))!=NULL) \
76 { \
77 setenv(envvar, value, 1); \
78 (*env)->ReleaseStringUTFChars(env, jValue, value); \
79 } \
80 } \
81}
82
83int ProcessSystemProperties(JNIEnv *env)
84{
85 jclass cls; jmethodID mid;
86 jstring jName, jValue;
87 const char *value;
88
89 bailif0(cls=(*env)->FindClass(env, "java/lang/System"));
90 bailif0(mid=(*env)->GetStaticMethodID(env, cls, "getProperty",
91 "(Ljava/lang/String;)Ljava/lang/String;"));
92
93 prop2env("turbojpeg.optimize", "TJ_OPTIMIZE");
94 prop2env("turbojpeg.arithmetic", "TJ_ARITHMETIC");
95 prop2env("turbojpeg.restart", "TJ_RESTART");
96 prop2env("turbojpeg.progressive", "TJ_PROGRESSIVE");
97 return 0;
98
99 bailout:
100 return -1;
101}
102
DRCa4940d12014-08-15 16:07:15 +0000103/* TurboJPEG 1.2.x: TJ::bufSize() */
DRC3bad53f2011-02-23 02:20:49 +0000104JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJ_bufSize
DRC9b49f0e2011-07-12 03:17:23 +0000105 (JNIEnv *env, jclass cls, jint width, jint height, jint jpegSubsamp)
DRCf8e00552011-02-04 11:06:36 +0000106{
DRC9b49f0e2011-07-12 03:17:23 +0000107 jint retval=(jint)tjBufSize(width, height, jpegSubsamp);
DRC739edeb2015-07-21 09:34:02 -0500108 if(retval==-1) _throwarg(tjGetErrorStr());
DRC36336fc2011-02-22 10:27:31 +0000109
110 bailout:
111 return retval;
112}
113
DRCa4940d12014-08-15 16:07:15 +0000114/* TurboJPEG 1.4.x: TJ::bufSizeYUV() */
DRCfef98522013-04-28 01:32:52 +0000115JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJ_bufSizeYUV__IIII
116 (JNIEnv *env, jclass cls, jint width, jint pad, jint height, jint subsamp)
DRC36336fc2011-02-22 10:27:31 +0000117{
DRCfef98522013-04-28 01:32:52 +0000118 jint retval=(jint)tjBufSizeYUV2(width, pad, height, subsamp);
DRC739edeb2015-07-21 09:34:02 -0500119 if(retval==-1) _throwarg(tjGetErrorStr());
DRC36336fc2011-02-22 10:27:31 +0000120
121 bailout:
122 return retval;
DRCf8e00552011-02-04 11:06:36 +0000123}
124
DRCa4940d12014-08-15 16:07:15 +0000125/* TurboJPEG 1.2.x: TJ::bufSizeYUV() */
DRCfef98522013-04-28 01:32:52 +0000126JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJ_bufSizeYUV__III
127 (JNIEnv *env, jclass cls, jint width, jint height, jint subsamp)
128{
129 return Java_org_libjpegturbo_turbojpeg_TJ_bufSizeYUV__IIII(env, cls, width,
130 4, height, subsamp);
131}
132
DRC40dd3142014-08-17 12:23:49 +0000133/* TurboJPEG 1.4.x: TJ::planeSizeYUV() */
134JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJ_planeSizeYUV__IIIII
135 (JNIEnv *env, jclass cls, jint componentID, jint width, jint stride,
136 jint height, jint subsamp)
137{
138 jint retval=(jint)tjPlaneSizeYUV(componentID, width, stride, height,
139 subsamp);
DRC739edeb2015-07-21 09:34:02 -0500140 if(retval==-1) _throwarg(tjGetErrorStr());
DRC40dd3142014-08-17 12:23:49 +0000141
142 bailout:
143 return retval;
144}
145
146/* TurboJPEG 1.4.x: TJ::planeWidth() */
147JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJ_planeWidth__III
148 (JNIEnv *env, jclass cls, jint componentID, jint width, jint subsamp)
149{
150 jint retval=(jint)tjPlaneWidth(componentID, width, subsamp);
DRC739edeb2015-07-21 09:34:02 -0500151 if(retval==-1) _throwarg(tjGetErrorStr());
DRC40dd3142014-08-17 12:23:49 +0000152
153 bailout:
154 return retval;
155}
156
157/* TurboJPEG 1.4.x: TJ::planeHeight() */
158JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJ_planeHeight__III
159 (JNIEnv *env, jclass cls, jint componentID, jint height, jint subsamp)
160{
161 jint retval=(jint)tjPlaneHeight(componentID, height, subsamp);
DRC739edeb2015-07-21 09:34:02 -0500162 if(retval==-1) _throwarg(tjGetErrorStr());
DRC40dd3142014-08-17 12:23:49 +0000163
164 bailout:
165 return retval;
166}
167
DRCa4940d12014-08-15 16:07:15 +0000168/* TurboJPEG 1.2.x: TJCompressor::init() */
DRCc5a41992011-02-08 06:54:36 +0000169JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_init
DRCf8e00552011-02-04 11:06:36 +0000170 (JNIEnv *env, jobject obj)
171{
172 jclass cls;
173 jfieldID fid;
174 tjhandle handle;
175
DRC1a3dbe62011-02-28 10:51:55 +0000176 if((handle=tjInitCompress())==NULL)
DRCb3817da2015-07-14 20:42:52 +0000177 _throwtj();
DRCf8e00552011-02-04 11:06:36 +0000178
179 bailif0(cls=(*env)->GetObjectClass(env, obj));
180 bailif0(fid=(*env)->GetFieldID(env, cls, "handle", "J"));
DRC46a03922014-08-15 14:40:05 +0000181 (*env)->SetLongField(env, obj, fid, (size_t)handle);
DRCf8e00552011-02-04 11:06:36 +0000182
183 bailout:
184 return;
185}
186
DRC5d87f6d2014-08-15 16:40:56 +0000187static jint TJCompressor_compress
DRC927a10d2014-08-15 13:18:58 +0000188 (JNIEnv *env, jobject obj, jarray src, jint srcElementSize, jint x, jint y,
189 jint width, jint pitch, jint height, jint pf, jbyteArray dst,
190 jint jpegSubsamp, jint jpegQual, jint flags)
DRCf8e00552011-02-04 11:06:36 +0000191{
DRC9b28def2011-05-21 14:37:15 +0000192 tjhandle handle=0;
DRCfac3bea2012-09-24 02:27:55 +0000193 unsigned long jpegSize=0;
194 jsize arraySize=0, actualPitch;
DRC9b28def2011-05-21 14:37:15 +0000195 unsigned char *srcBuf=NULL, *jpegBuf=NULL;
DRCf8e00552011-02-04 11:06:36 +0000196
197 gethandle();
198
DRC92549de2011-03-15 20:52:02 +0000199 if(pf<0 || pf>=org_libjpegturbo_turbojpeg_TJ_NUMPF || width<1 || height<1
DRC6acf52b2011-03-02 01:09:20 +0000200 || pitch<0)
DRCb3817da2015-07-14 20:42:52 +0000201 _throwarg("Invalid argument in compress()");
DRC9b28def2011-05-21 14:37:15 +0000202 if(org_libjpegturbo_turbojpeg_TJ_NUMPF!=TJ_NUMPF)
DRCb3817da2015-07-14 20:42:52 +0000203 _throwarg("Mismatch between Java and C API");
DRC4f1580c2011-02-25 06:11:03 +0000204
DRCfac3bea2012-09-24 02:27:55 +0000205 actualPitch=(pitch==0)? width*tjPixelSize[pf]:pitch;
DRC927a10d2014-08-15 13:18:58 +0000206 arraySize=(y+height-1)*actualPitch + (x+width)*tjPixelSize[pf];
207 if((*env)->GetArrayLength(env, src)*srcElementSize<arraySize)
DRCb3817da2015-07-14 20:42:52 +0000208 _throwarg("Source buffer is not large enough");
DRC9b49f0e2011-07-12 03:17:23 +0000209 jpegSize=tjBufSize(width, height, jpegSubsamp);
DRC9b28def2011-05-21 14:37:15 +0000210 if((*env)->GetArrayLength(env, dst)<(jsize)jpegSize)
DRCb3817da2015-07-14 20:42:52 +0000211 _throwarg("Destination buffer is not large enough");
DRC6acf52b2011-03-02 01:09:20 +0000212
DRC9b28def2011-05-21 14:37:15 +0000213 bailif0(srcBuf=(*env)->GetPrimitiveArrayCritical(env, src, 0));
214 bailif0(jpegBuf=(*env)->GetPrimitiveArrayCritical(env, dst, 0));
DRCf8e00552011-02-04 11:06:36 +0000215
DRC0713c1b2014-08-22 13:43:33 +0000216 if(ProcessSystemProperties(env)<0) goto bailout;
217
DRCfac3bea2012-09-24 02:27:55 +0000218 if(tjCompress2(handle, &srcBuf[y*actualPitch + x*tjPixelSize[pf]], width,
219 pitch, height, pf, &jpegBuf, &jpegSize, jpegSubsamp, jpegQual,
220 flags|TJFLAG_NOREALLOC)==-1)
DRCb3817da2015-07-14 20:42:52 +0000221 _throwtj();
DRCfac3bea2012-09-24 02:27:55 +0000222
223 bailout:
224 if(jpegBuf) (*env)->ReleasePrimitiveArrayCritical(env, dst, jpegBuf, 0);
225 if(srcBuf) (*env)->ReleasePrimitiveArrayCritical(env, src, srcBuf, 0);
226 return (jint)jpegSize;
227}
228
DRCa4940d12014-08-15 16:07:15 +0000229/* TurboJPEG 1.3.x: TJCompressor::compress() byte source */
DRC927a10d2014-08-15 13:18:58 +0000230JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_compress___3BIIIIII_3BIII
231 (JNIEnv *env, jobject obj, jbyteArray src, jint x, jint y, jint width,
232 jint pitch, jint height, jint pf, jbyteArray dst, jint jpegSubsamp,
233 jint jpegQual, jint flags)
234{
235 return TJCompressor_compress(env, obj, src, 1, x, y, width, pitch, height,
236 pf, dst, jpegSubsamp, jpegQual, flags);
237}
238
DRCa4940d12014-08-15 16:07:15 +0000239/* TurboJPEG 1.2.x: TJCompressor::compress() byte source */
DRCfac3bea2012-09-24 02:27:55 +0000240JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_compress___3BIIII_3BIII
241 (JNIEnv *env, jobject obj, jbyteArray src, jint width, jint pitch,
242 jint height, jint pf, jbyteArray dst, jint jpegSubsamp, jint jpegQual,
243 jint flags)
244{
DRC927a10d2014-08-15 13:18:58 +0000245 return TJCompressor_compress(env, obj, src, 1, 0, 0, width, pitch, height,
246 pf, dst, jpegSubsamp, jpegQual, flags);
DRCfac3bea2012-09-24 02:27:55 +0000247}
248
DRCa4940d12014-08-15 16:07:15 +0000249/* TurboJPEG 1.3.x: TJCompressor::compress() int source */
DRCfac3bea2012-09-24 02:27:55 +0000250JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_compress___3IIIIIII_3BIII
251 (JNIEnv *env, jobject obj, jintArray src, jint x, jint y, jint width,
252 jint stride, jint height, jint pf, jbyteArray dst, jint jpegSubsamp,
253 jint jpegQual, jint flags)
254{
DRC927a10d2014-08-15 13:18:58 +0000255 if(pf<0 || pf>=org_libjpegturbo_turbojpeg_TJ_NUMPF)
DRCb3817da2015-07-14 20:42:52 +0000256 _throwarg("Invalid argument in compress()");
DRCfac3bea2012-09-24 02:27:55 +0000257 if(tjPixelSize[pf]!=sizeof(jint))
DRCb3817da2015-07-14 20:42:52 +0000258 _throwarg("Pixel format must be 32-bit when compressing from an integer buffer.");
DRCfac3bea2012-09-24 02:27:55 +0000259
DRC927a10d2014-08-15 13:18:58 +0000260 return TJCompressor_compress(env, obj, src, sizeof(jint), x, y, width,
261 stride*sizeof(jint), height, pf, dst, jpegSubsamp, jpegQual, flags);
DRCf8e00552011-02-04 11:06:36 +0000262
263 bailout:
DRC927a10d2014-08-15 13:18:58 +0000264 return 0;
DRCf8e00552011-02-04 11:06:36 +0000265}
266
DRCa4940d12014-08-15 16:07:15 +0000267/* TurboJPEG 1.2.x: TJCompressor::compress() int source */
DRC4f1580c2011-02-25 06:11:03 +0000268JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_compress___3IIIII_3BIII
DRC927a10d2014-08-15 13:18:58 +0000269 (JNIEnv *env, jobject obj, jintArray src, jint width, jint stride,
DRC9b28def2011-05-21 14:37:15 +0000270 jint height, jint pf, jbyteArray dst, jint jpegSubsamp, jint jpegQual,
DRC4f1580c2011-02-25 06:11:03 +0000271 jint flags)
DRC84a1bcc2011-02-23 12:09:56 +0000272{
DRC927a10d2014-08-15 13:18:58 +0000273 if(pf<0 || pf>=org_libjpegturbo_turbojpeg_TJ_NUMPF)
DRCb3817da2015-07-14 20:42:52 +0000274 _throwarg("Invalid argument in compress()");
DRC927a10d2014-08-15 13:18:58 +0000275 if(tjPixelSize[pf]!=sizeof(jint))
DRCb3817da2015-07-14 20:42:52 +0000276 _throwarg("Pixel format must be 32-bit when compressing from an integer buffer.");
DRC927a10d2014-08-15 13:18:58 +0000277
278 return TJCompressor_compress(env, obj, src, sizeof(jint), 0, 0, width,
279 stride*sizeof(jint), height, pf, dst, jpegSubsamp, jpegQual, flags);
280
281 bailout:
282 return 0;
DRC84a1bcc2011-02-23 12:09:56 +0000283}
284
DRCa4940d12014-08-15 16:07:15 +0000285/* TurboJPEG 1.4.x: TJCompressor::compressFromYUV() */
DRC40dd3142014-08-17 12:23:49 +0000286JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_compressFromYUV___3_3B_3II_3III_3BII
287 (JNIEnv *env, jobject obj, jobjectArray srcobjs, jintArray jSrcOffsets,
288 jint width, jintArray jSrcStrides, jint height, jint subsamp,
289 jbyteArray dst, jint jpegQual, jint flags)
DRC1e672742013-10-31 05:04:51 +0000290{
291 tjhandle handle=0;
292 unsigned long jpegSize=0;
DRC40dd3142014-08-17 12:23:49 +0000293 jbyteArray jSrcPlanes[3]={NULL, NULL, NULL};
DRC6fa14b32015-08-13 20:06:03 -0500294 const unsigned char *srcPlanes[3];
295 unsigned char *jpegBuf=NULL;
DRC40dd3142014-08-17 12:23:49 +0000296 int *srcOffsets=NULL, *srcStrides=NULL;
297 int nc=(subsamp==org_libjpegturbo_turbojpeg_TJ_SAMP_GRAY? 1:3), i;
DRC1e672742013-10-31 05:04:51 +0000298
299 gethandle();
300
DRC40dd3142014-08-17 12:23:49 +0000301 if(subsamp<0 || subsamp>=org_libjpegturbo_turbojpeg_TJ_NUMSAMP)
DRCb3817da2015-07-14 20:42:52 +0000302 _throwarg("Invalid argument in compressFromYUV()");
DRC40dd3142014-08-17 12:23:49 +0000303 if(org_libjpegturbo_turbojpeg_TJ_NUMSAMP!=TJ_NUMSAMP)
DRCb3817da2015-07-14 20:42:52 +0000304 _throwarg("Mismatch between Java and C API");
DRC40dd3142014-08-17 12:23:49 +0000305
306 if((*env)->GetArrayLength(env, srcobjs)<nc)
DRCb3817da2015-07-14 20:42:52 +0000307 _throwarg("Planes array is too small for the subsampling type");
DRC40dd3142014-08-17 12:23:49 +0000308 if((*env)->GetArrayLength(env, jSrcOffsets)<nc)
DRCb3817da2015-07-14 20:42:52 +0000309 _throwarg("Offsets array is too small for the subsampling type");
DRC40dd3142014-08-17 12:23:49 +0000310 if((*env)->GetArrayLength(env, jSrcStrides)<nc)
DRCb3817da2015-07-14 20:42:52 +0000311 _throwarg("Strides array is too small for the subsampling type");
DRC40dd3142014-08-17 12:23:49 +0000312
DRC1e672742013-10-31 05:04:51 +0000313 jpegSize=tjBufSize(width, height, subsamp);
314 if((*env)->GetArrayLength(env, dst)<(jsize)jpegSize)
DRCb3817da2015-07-14 20:42:52 +0000315 _throwarg("Destination buffer is not large enough");
DRC1e672742013-10-31 05:04:51 +0000316
DRC40dd3142014-08-17 12:23:49 +0000317 bailif0(srcOffsets=(*env)->GetPrimitiveArrayCritical(env, jSrcOffsets, 0));
318 bailif0(srcStrides=(*env)->GetPrimitiveArrayCritical(env, jSrcStrides, 0));
319 for(i=0; i<nc; i++)
320 {
321 int planeSize=tjPlaneSizeYUV(i, width, srcStrides[i], height, subsamp);
322 int pw=tjPlaneWidth(i, width, subsamp);
323
324 if(planeSize<0 || pw<0)
DRC739edeb2015-07-21 09:34:02 -0500325 _throwarg(tjGetErrorStr());
DRC40dd3142014-08-17 12:23:49 +0000326
327 if(srcOffsets[i]<0)
DRCb3817da2015-07-14 20:42:52 +0000328 _throwarg("Invalid argument in compressFromYUV()");
DRC40dd3142014-08-17 12:23:49 +0000329 if(srcStrides[i]<0 && srcOffsets[i]-planeSize+pw<0)
DRCb3817da2015-07-14 20:42:52 +0000330 _throwarg("Negative plane stride would cause memory to be accessed below plane boundary");
DRC40dd3142014-08-17 12:23:49 +0000331
332 bailif0(jSrcPlanes[i]=(*env)->GetObjectArrayElement(env, srcobjs, i));
333 if((*env)->GetArrayLength(env, jSrcPlanes[i])<srcOffsets[i]+planeSize)
DRCb3817da2015-07-14 20:42:52 +0000334 _throwarg("Source plane is not large enough");
DRC40dd3142014-08-17 12:23:49 +0000335
336 bailif0(srcPlanes[i]=(*env)->GetPrimitiveArrayCritical(env, jSrcPlanes[i],
337 0));
338 srcPlanes[i]=&srcPlanes[i][srcOffsets[i]];
339 }
DRC1e672742013-10-31 05:04:51 +0000340 bailif0(jpegBuf=(*env)->GetPrimitiveArrayCritical(env, dst, 0));
341
DRC0713c1b2014-08-22 13:43:33 +0000342 if(ProcessSystemProperties(env)<0) goto bailout;
343
DRC40dd3142014-08-17 12:23:49 +0000344 if(tjCompressFromYUVPlanes(handle, srcPlanes, width, srcStrides, height,
345 subsamp, &jpegBuf, &jpegSize, jpegQual, flags|TJFLAG_NOREALLOC)==-1)
DRCb3817da2015-07-14 20:42:52 +0000346 _throwtj();
DRC1e672742013-10-31 05:04:51 +0000347
348 bailout:
349 if(jpegBuf) (*env)->ReleasePrimitiveArrayCritical(env, dst, jpegBuf, 0);
DRC40dd3142014-08-17 12:23:49 +0000350 for(i=0; i<nc; i++)
351 {
352 if(srcPlanes[i] && jSrcPlanes[i])
DRC6fa14b32015-08-13 20:06:03 -0500353 (*env)->ReleasePrimitiveArrayCritical(env, jSrcPlanes[i],
354 (unsigned char *)srcPlanes[i], 0);
DRC40dd3142014-08-17 12:23:49 +0000355 }
356 if(srcStrides)
357 (*env)->ReleasePrimitiveArrayCritical(env, jSrcStrides, srcStrides, 0);
358 if(srcOffsets)
359 (*env)->ReleasePrimitiveArrayCritical(env, jSrcOffsets, srcOffsets, 0);
DRC1e672742013-10-31 05:04:51 +0000360 return (jint)jpegSize;
361}
362
DRC5d87f6d2014-08-15 16:40:56 +0000363static void TJCompressor_encodeYUV
DRC927a10d2014-08-15 13:18:58 +0000364 (JNIEnv *env, jobject obj, jarray src, jint srcElementSize, jint x, jint y,
DRC40dd3142014-08-17 12:23:49 +0000365 jint width, jint pitch, jint height, jint pf, jobjectArray dstobjs,
366 jintArray jDstOffsets, jintArray jDstStrides, jint subsamp, jint flags)
DRC4f1580c2011-02-25 06:11:03 +0000367{
DRC9b28def2011-05-21 14:37:15 +0000368 tjhandle handle=0;
DRC40dd3142014-08-17 12:23:49 +0000369 jsize arraySize=0, actualPitch;
370 jbyteArray jDstPlanes[3]={NULL, NULL, NULL};
371 unsigned char *srcBuf=NULL, *dstPlanes[3];
372 int *dstOffsets=NULL, *dstStrides=NULL;
373 int nc=(subsamp==org_libjpegturbo_turbojpeg_TJ_SAMP_GRAY? 1:3), i;
374
375 gethandle();
376
377 if(pf<0 || pf>=org_libjpegturbo_turbojpeg_TJ_NUMPF || width<1 || height<1
378 || pitch<0 || subsamp<0 || subsamp>=org_libjpegturbo_turbojpeg_TJ_NUMSAMP)
DRCb3817da2015-07-14 20:42:52 +0000379 _throwarg("Invalid argument in encodeYUV()");
DRC40dd3142014-08-17 12:23:49 +0000380 if(org_libjpegturbo_turbojpeg_TJ_NUMPF!=TJ_NUMPF
381 || org_libjpegturbo_turbojpeg_TJ_NUMSAMP!=TJ_NUMSAMP)
DRCb3817da2015-07-14 20:42:52 +0000382 _throwarg("Mismatch between Java and C API");
DRC40dd3142014-08-17 12:23:49 +0000383
384 if((*env)->GetArrayLength(env, dstobjs)<nc)
DRCb3817da2015-07-14 20:42:52 +0000385 _throwarg("Planes array is too small for the subsampling type");
DRC40dd3142014-08-17 12:23:49 +0000386 if((*env)->GetArrayLength(env, jDstOffsets)<nc)
DRCb3817da2015-07-14 20:42:52 +0000387 _throwarg("Offsets array is too small for the subsampling type");
DRC40dd3142014-08-17 12:23:49 +0000388 if((*env)->GetArrayLength(env, jDstStrides)<nc)
DRCb3817da2015-07-14 20:42:52 +0000389 _throwarg("Strides array is too small for the subsampling type");
DRC40dd3142014-08-17 12:23:49 +0000390
391 actualPitch=(pitch==0)? width*tjPixelSize[pf]:pitch;
392 arraySize=(y+height-1)*actualPitch + (x+width)*tjPixelSize[pf];
393 if((*env)->GetArrayLength(env, src)*srcElementSize<arraySize)
DRCb3817da2015-07-14 20:42:52 +0000394 _throwarg("Source buffer is not large enough");
DRC40dd3142014-08-17 12:23:49 +0000395
396 bailif0(dstOffsets=(*env)->GetPrimitiveArrayCritical(env, jDstOffsets, 0));
397 bailif0(dstStrides=(*env)->GetPrimitiveArrayCritical(env, jDstStrides, 0));
398 for(i=0; i<nc; i++)
399 {
400 int planeSize=tjPlaneSizeYUV(i, width, dstStrides[i], height, subsamp);
401 int pw=tjPlaneWidth(i, width, subsamp);
402
403 if(planeSize<0 || pw<0)
DRC739edeb2015-07-21 09:34:02 -0500404 _throwarg(tjGetErrorStr());
DRC40dd3142014-08-17 12:23:49 +0000405
406 if(dstOffsets[i]<0)
DRCb3817da2015-07-14 20:42:52 +0000407 _throwarg("Invalid argument in encodeYUV()");
DRC40dd3142014-08-17 12:23:49 +0000408 if(dstStrides[i]<0 && dstOffsets[i]-planeSize+pw<0)
DRCb3817da2015-07-14 20:42:52 +0000409 _throwarg("Negative plane stride would cause memory to be accessed below plane boundary");
DRC40dd3142014-08-17 12:23:49 +0000410
411 bailif0(jDstPlanes[i]=(*env)->GetObjectArrayElement(env, dstobjs, i));
412 if((*env)->GetArrayLength(env, jDstPlanes[i])<dstOffsets[i]+planeSize)
DRCb3817da2015-07-14 20:42:52 +0000413 _throwarg("Destination plane is not large enough");
DRC40dd3142014-08-17 12:23:49 +0000414
415 bailif0(dstPlanes[i]=(*env)->GetPrimitiveArrayCritical(env, jDstPlanes[i],
416 0));
417 dstPlanes[i]=&dstPlanes[i][dstOffsets[i]];
418 }
419 bailif0(srcBuf=(*env)->GetPrimitiveArrayCritical(env, src, 0));
420
421 if(tjEncodeYUVPlanes(handle, &srcBuf[y*actualPitch + x*tjPixelSize[pf]],
422 width, pitch, height, pf, dstPlanes, dstStrides, subsamp, flags)==-1)
DRCb3817da2015-07-14 20:42:52 +0000423 _throwtj();
DRC40dd3142014-08-17 12:23:49 +0000424
425 bailout:
426 if(srcBuf) (*env)->ReleasePrimitiveArrayCritical(env, src, srcBuf, 0);
427 for(i=0; i<nc; i++)
428 {
429 if(dstPlanes[i] && jDstPlanes[i])
430 (*env)->ReleasePrimitiveArrayCritical(env, jDstPlanes[i], dstPlanes[i],
431 0);
432 }
433 if(dstStrides)
434 (*env)->ReleasePrimitiveArrayCritical(env, jDstStrides, dstStrides, 0);
435 if(dstOffsets)
436 (*env)->ReleasePrimitiveArrayCritical(env, jDstOffsets, dstOffsets, 0);
437 return;
438}
439
440/* TurboJPEG 1.4.x: TJCompressor::encodeYUV() byte source */
441JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_encodeYUV___3BIIIIII_3_3B_3I_3III
442 (JNIEnv *env, jobject obj, jbyteArray src, jint x, jint y, jint width,
443 jint pitch, jint height, jint pf, jobjectArray dstobjs,
444 jintArray jDstOffsets, jintArray jDstStrides, jint subsamp, jint flags)
445{
446 TJCompressor_encodeYUV(env, obj, src, 1, x, y, width, pitch, height, pf,
447 dstobjs, jDstOffsets, jDstStrides, subsamp, flags);
448}
449
450/* TurboJPEG 1.4.x: TJCompressor::encodeYUV() int source */
451JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_encodeYUV___3IIIIIII_3_3B_3I_3III
452 (JNIEnv *env, jobject obj, jintArray src, jint x, jint y, jint width,
DRC6fa14b32015-08-13 20:06:03 -0500453 jint stride, jint height, jint pf, jobjectArray dstobjs,
DRC40dd3142014-08-17 12:23:49 +0000454 jintArray jDstOffsets, jintArray jDstStrides, jint subsamp, jint flags)
455{
456 if(pf<0 || pf>=org_libjpegturbo_turbojpeg_TJ_NUMPF)
DRCb3817da2015-07-14 20:42:52 +0000457 _throwarg("Invalid argument in encodeYUV()");
DRC40dd3142014-08-17 12:23:49 +0000458 if(tjPixelSize[pf]!=sizeof(jint))
DRCb3817da2015-07-14 20:42:52 +0000459 _throwarg("Pixel format must be 32-bit when encoding from an integer buffer.");
DRC40dd3142014-08-17 12:23:49 +0000460
461 TJCompressor_encodeYUV(env, obj, src, sizeof(jint), x, y, width,
462 stride*sizeof(jint), height, pf, dstobjs, jDstOffsets, jDstStrides,
463 subsamp, flags);
464
465 bailout:
466 return;
467}
468
469JNIEXPORT void JNICALL TJCompressor_encodeYUV_12
470 (JNIEnv *env, jobject obj, jarray src, jint srcElementSize, jint width,
471 jint pitch, jint height, jint pf, jbyteArray dst, jint subsamp, jint flags)
472{
473 tjhandle handle=0;
474 jsize arraySize=0;
DRC9b28def2011-05-21 14:37:15 +0000475 unsigned char *srcBuf=NULL, *dstBuf=NULL;
DRC4f1580c2011-02-25 06:11:03 +0000476
477 gethandle();
478
DRC92549de2011-03-15 20:52:02 +0000479 if(pf<0 || pf>=org_libjpegturbo_turbojpeg_TJ_NUMPF || width<1 || height<1
DRC6acf52b2011-03-02 01:09:20 +0000480 || pitch<0)
DRCb3817da2015-07-14 20:42:52 +0000481 _throwarg("Invalid argument in encodeYUV()");
DRC9b28def2011-05-21 14:37:15 +0000482 if(org_libjpegturbo_turbojpeg_TJ_NUMPF!=TJ_NUMPF)
DRCb3817da2015-07-14 20:42:52 +0000483 _throwarg("Mismatch between Java and C API");
DRC4f1580c2011-02-25 06:11:03 +0000484
DRC40dd3142014-08-17 12:23:49 +0000485 arraySize=(pitch==0)? width*tjPixelSize[pf]*height:pitch*height;
DRC927a10d2014-08-15 13:18:58 +0000486 if((*env)->GetArrayLength(env, src)*srcElementSize<arraySize)
DRCb3817da2015-07-14 20:42:52 +0000487 _throwarg("Source buffer is not large enough");
DRC40dd3142014-08-17 12:23:49 +0000488 if((*env)->GetArrayLength(env, dst)
489 <(jsize)tjBufSizeYUV(width, height, subsamp))
DRCb3817da2015-07-14 20:42:52 +0000490 _throwarg("Destination buffer is not large enough");
DRC6acf52b2011-03-02 01:09:20 +0000491
DRC9b28def2011-05-21 14:37:15 +0000492 bailif0(srcBuf=(*env)->GetPrimitiveArrayCritical(env, src, 0));
493 bailif0(dstBuf=(*env)->GetPrimitiveArrayCritical(env, dst, 0));
DRC4f1580c2011-02-25 06:11:03 +0000494
DRC40dd3142014-08-17 12:23:49 +0000495 if(tjEncodeYUV2(handle, srcBuf, width, pitch, height, pf, dstBuf, subsamp,
496 flags)==-1)
DRCb3817da2015-07-14 20:42:52 +0000497 _throwtj();
DRC4f1580c2011-02-25 06:11:03 +0000498
499 bailout:
DRC9b28def2011-05-21 14:37:15 +0000500 if(dstBuf) (*env)->ReleasePrimitiveArrayCritical(env, dst, dstBuf, 0);
501 if(srcBuf) (*env)->ReleasePrimitiveArrayCritical(env, src, srcBuf, 0);
DRC4f1580c2011-02-25 06:11:03 +0000502 return;
503}
504
DRCa4940d12014-08-15 16:07:15 +0000505/* TurboJPEG 1.2.x: TJCompressor::encodeYUV() byte source */
DRCfef98522013-04-28 01:32:52 +0000506JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_encodeYUV___3BIIII_3BII
507 (JNIEnv *env, jobject obj, jbyteArray src, jint width, jint pitch,
DRC6acf52b2011-03-02 01:09:20 +0000508 jint height, jint pf, jbyteArray dst, jint subsamp, jint flags)
DRC4f1580c2011-02-25 06:11:03 +0000509{
DRC40dd3142014-08-17 12:23:49 +0000510 TJCompressor_encodeYUV_12(env, obj, src, 1, width, pitch, height, pf, dst,
511 subsamp, flags);
DRC4f1580c2011-02-25 06:11:03 +0000512}
513
DRCa4940d12014-08-15 16:07:15 +0000514/* TurboJPEG 1.2.x: TJCompressor::encodeYUV() int source */
DRCfef98522013-04-28 01:32:52 +0000515JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_encodeYUV___3IIIII_3BII
DRC927a10d2014-08-15 13:18:58 +0000516 (JNIEnv *env, jobject obj, jintArray src, jint width, jint stride,
DRCfef98522013-04-28 01:32:52 +0000517 jint height, jint pf, jbyteArray dst, jint subsamp, jint flags)
518{
DRC927a10d2014-08-15 13:18:58 +0000519 if(pf<0 || pf>=org_libjpegturbo_turbojpeg_TJ_NUMPF)
DRCb3817da2015-07-14 20:42:52 +0000520 _throwarg("Invalid argument in encodeYUV()");
DRC927a10d2014-08-15 13:18:58 +0000521 if(tjPixelSize[pf]!=sizeof(jint))
DRCb3817da2015-07-14 20:42:52 +0000522 _throwarg("Pixel format must be 32-bit when encoding from an integer buffer.");
DRC927a10d2014-08-15 13:18:58 +0000523
DRC40dd3142014-08-17 12:23:49 +0000524 TJCompressor_encodeYUV_12(env, obj, src, sizeof(jint), width,
525 stride*sizeof(jint), height, pf, dst, subsamp, flags);
DRC927a10d2014-08-15 13:18:58 +0000526
527 bailout:
528 return;
DRCfef98522013-04-28 01:32:52 +0000529}
530
DRCa4940d12014-08-15 16:07:15 +0000531/* TurboJPEG 1.2.x: TJCompressor::destroy() */
DRCc5a41992011-02-08 06:54:36 +0000532JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_destroy
DRCf8e00552011-02-04 11:06:36 +0000533 (JNIEnv *env, jobject obj)
534{
535 tjhandle handle=0;
536
537 gethandle();
538
DRC739edeb2015-07-21 09:34:02 -0500539 if(tjDestroy(handle)==-1) _throwtj();
DRC3bad53f2011-02-23 02:20:49 +0000540 (*env)->SetLongField(env, obj, _fid, 0);
DRCf8e00552011-02-04 11:06:36 +0000541
542 bailout:
543 return;
544}
545
DRCa4940d12014-08-15 16:07:15 +0000546/* TurboJPEG 1.2.x: TJDecompressor::init() */
DRCc5a41992011-02-08 06:54:36 +0000547JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_init
DRCf8e00552011-02-04 11:06:36 +0000548 (JNIEnv *env, jobject obj)
549{
550 jclass cls;
551 jfieldID fid;
552 tjhandle handle;
553
DRCb3817da2015-07-14 20:42:52 +0000554 if((handle=tjInitDecompress())==NULL) _throwtj();
DRCf8e00552011-02-04 11:06:36 +0000555
556 bailif0(cls=(*env)->GetObjectClass(env, obj));
557 bailif0(fid=(*env)->GetFieldID(env, cls, "handle", "J"));
DRC46a03922014-08-15 14:40:05 +0000558 (*env)->SetLongField(env, obj, fid, (size_t)handle);
DRCf8e00552011-02-04 11:06:36 +0000559
560 bailout:
561 return;
562}
563
DRCa4940d12014-08-15 16:07:15 +0000564/* TurboJPEG 1.2.x: TJDecompressor::getScalingFactors() */
DRC109a5782011-03-01 09:53:07 +0000565JNIEXPORT jobjectArray JNICALL Java_org_libjpegturbo_turbojpeg_TJ_getScalingFactors
566 (JNIEnv *env, jclass cls)
DRC36336fc2011-02-22 10:27:31 +0000567{
DRCb7c8c862014-08-15 16:20:59 +0000568 jclass sfcls=NULL; jfieldID fid=0;
DRC109a5782011-03-01 09:53:07 +0000569 tjscalingfactor *sf=NULL; int n=0, i;
570 jobject sfobj=NULL;
571 jobjectArray sfjava=NULL;
572
573 if((sf=tjGetScalingFactors(&n))==NULL || n==0)
DRC739edeb2015-07-21 09:34:02 -0500574 _throwarg(tjGetErrorStr());
DRC36336fc2011-02-22 10:27:31 +0000575
DRCb2f94152011-04-02 02:09:03 +0000576 bailif0(sfcls=(*env)->FindClass(env, "org/libjpegturbo/turbojpeg/TJScalingFactor"));
DRC109a5782011-03-01 09:53:07 +0000577 bailif0(sfjava=(jobjectArray)(*env)->NewObjectArray(env, n, sfcls, 0));
DRC36336fc2011-02-22 10:27:31 +0000578
DRC109a5782011-03-01 09:53:07 +0000579 for(i=0; i<n; i++)
580 {
581 bailif0(sfobj=(*env)->AllocObject(env, sfcls));
582 bailif0(fid=(*env)->GetFieldID(env, sfcls, "num", "I"));
583 (*env)->SetIntField(env, sfobj, fid, sf[i].num);
584 bailif0(fid=(*env)->GetFieldID(env, sfcls, "denom", "I"));
585 (*env)->SetIntField(env, sfobj, fid, sf[i].denom);
586 (*env)->SetObjectArrayElement(env, sfjava, i, sfobj);
587 }
DRC36336fc2011-02-22 10:27:31 +0000588
589 bailout:
DRC109a5782011-03-01 09:53:07 +0000590 return sfjava;
DRC36336fc2011-02-22 10:27:31 +0000591}
592
DRCa4940d12014-08-15 16:07:15 +0000593/* TurboJPEG 1.2.x: TJDecompressor::decompressHeader() */
DRC3bad53f2011-02-23 02:20:49 +0000594JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompressHeader
DRC9b28def2011-05-21 14:37:15 +0000595 (JNIEnv *env, jobject obj, jbyteArray src, jint jpegSize)
DRCf8e00552011-02-04 11:06:36 +0000596{
DRCf8e00552011-02-04 11:06:36 +0000597 tjhandle handle=0;
DRC9b28def2011-05-21 14:37:15 +0000598 unsigned char *jpegBuf=NULL;
DRC38cb1ec2013-08-23 04:45:43 +0000599 int width=0, height=0, jpegSubsamp=-1, jpegColorspace=-1;
DRCf8e00552011-02-04 11:06:36 +0000600
601 gethandle();
602
DRC9b28def2011-05-21 14:37:15 +0000603 if((*env)->GetArrayLength(env, src)<jpegSize)
DRCb3817da2015-07-14 20:42:52 +0000604 _throwarg("Source buffer is not large enough");
DRC6acf52b2011-03-02 01:09:20 +0000605
DRC9b28def2011-05-21 14:37:15 +0000606 bailif0(jpegBuf=(*env)->GetPrimitiveArrayCritical(env, src, 0));
DRCf8e00552011-02-04 11:06:36 +0000607
DRC1a45b812014-05-09 18:06:58 +0000608 if(tjDecompressHeader3(handle, jpegBuf, (unsigned long)jpegSize,
DRC38cb1ec2013-08-23 04:45:43 +0000609 &width, &height, &jpegSubsamp, &jpegColorspace)==-1)
DRCb3817da2015-07-14 20:42:52 +0000610 _throwtj();
DRC8951cf02014-08-14 16:54:04 +0000611
DRC9b28def2011-05-21 14:37:15 +0000612 (*env)->ReleasePrimitiveArrayCritical(env, src, jpegBuf, 0); jpegBuf=NULL;
DRCf8e00552011-02-04 11:06:36 +0000613
DRC26dd86b2014-08-15 14:01:21 +0000614 bailif0(_fid=(*env)->GetFieldID(env, _cls, "jpegSubsamp", "I"));
DRC9b28def2011-05-21 14:37:15 +0000615 (*env)->SetIntField(env, obj, _fid, jpegSubsamp);
DRC26dd86b2014-08-15 14:01:21 +0000616 if((_fid=(*env)->GetFieldID(env, _cls, "jpegColorspace", "I"))==0)
617 (*env)->ExceptionClear(env);
618 else
619 (*env)->SetIntField(env, obj, _fid, jpegColorspace);
620 bailif0(_fid=(*env)->GetFieldID(env, _cls, "jpegWidth", "I"));
DRC3bad53f2011-02-23 02:20:49 +0000621 (*env)->SetIntField(env, obj, _fid, width);
DRC26dd86b2014-08-15 14:01:21 +0000622 bailif0(_fid=(*env)->GetFieldID(env, _cls, "jpegHeight", "I"));
DRC3bad53f2011-02-23 02:20:49 +0000623 (*env)->SetIntField(env, obj, _fid, height);
DRCf8e00552011-02-04 11:06:36 +0000624
625 bailout:
DRC8951cf02014-08-14 16:54:04 +0000626 if(jpegBuf) (*env)->ReleasePrimitiveArrayCritical(env, src, jpegBuf, 0);
DRC3bad53f2011-02-23 02:20:49 +0000627 return;
DRCf8e00552011-02-04 11:06:36 +0000628}
629
DRC5d87f6d2014-08-15 16:40:56 +0000630static void TJDecompressor_decompress
DRC927a10d2014-08-15 13:18:58 +0000631 (JNIEnv *env, jobject obj, jbyteArray src, jint jpegSize, jarray dst,
632 jint dstElementSize, jint x, jint y, jint width, jint pitch, jint height,
633 jint pf, jint flags)
DRCf8e00552011-02-04 11:06:36 +0000634{
DRC9b28def2011-05-21 14:37:15 +0000635 tjhandle handle=0;
DRCf659f432012-06-06 08:41:06 +0000636 jsize arraySize=0, actualPitch;
DRC9b28def2011-05-21 14:37:15 +0000637 unsigned char *jpegBuf=NULL, *dstBuf=NULL;
DRCf8e00552011-02-04 11:06:36 +0000638
639 gethandle();
640
DRC92549de2011-03-15 20:52:02 +0000641 if(pf<0 || pf>=org_libjpegturbo_turbojpeg_TJ_NUMPF)
DRCb3817da2015-07-14 20:42:52 +0000642 _throwarg("Invalid argument in decompress()");
DRC9b28def2011-05-21 14:37:15 +0000643 if(org_libjpegturbo_turbojpeg_TJ_NUMPF!=TJ_NUMPF)
DRCb3817da2015-07-14 20:42:52 +0000644 _throwarg("Mismatch between Java and C API");
DRC4f1580c2011-02-25 06:11:03 +0000645
DRC9b28def2011-05-21 14:37:15 +0000646 if((*env)->GetArrayLength(env, src)<jpegSize)
DRCb3817da2015-07-14 20:42:52 +0000647 _throwarg("Source buffer is not large enough");
DRCf659f432012-06-06 08:41:06 +0000648 actualPitch=(pitch==0)? width*tjPixelSize[pf]:pitch;
DRCdc31f0b2012-06-07 09:38:57 +0000649 arraySize=(y+height-1)*actualPitch + (x+width)*tjPixelSize[pf];
DRC927a10d2014-08-15 13:18:58 +0000650 if((*env)->GetArrayLength(env, dst)*dstElementSize<arraySize)
DRCb3817da2015-07-14 20:42:52 +0000651 _throwarg("Destination buffer is not large enough");
DRC6acf52b2011-03-02 01:09:20 +0000652
DRC9b28def2011-05-21 14:37:15 +0000653 bailif0(jpegBuf=(*env)->GetPrimitiveArrayCritical(env, src, 0));
654 bailif0(dstBuf=(*env)->GetPrimitiveArrayCritical(env, dst, 0));
DRCf8e00552011-02-04 11:06:36 +0000655
DRCf659f432012-06-06 08:41:06 +0000656 if(tjDecompress2(handle, jpegBuf, (unsigned long)jpegSize,
657 &dstBuf[y*actualPitch + x*tjPixelSize[pf]], width, pitch, height, pf,
658 flags)==-1)
DRCb3817da2015-07-14 20:42:52 +0000659 _throwtj();
DRCf659f432012-06-06 08:41:06 +0000660
661 bailout:
662 if(dstBuf) (*env)->ReleasePrimitiveArrayCritical(env, dst, dstBuf, 0);
663 if(jpegBuf) (*env)->ReleasePrimitiveArrayCritical(env, src, jpegBuf, 0);
664 return;
665}
666
DRCa4940d12014-08-15 16:07:15 +0000667/* TurboJPEG 1.3.x: TJDecompressor::decompress() byte destination */
DRC927a10d2014-08-15 13:18:58 +0000668JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompress___3BI_3BIIIIIII
669 (JNIEnv *env, jobject obj, jbyteArray src, jint jpegSize, jbyteArray dst,
670 jint x, jint y, jint width, jint pitch, jint height, jint pf, jint flags)
671{
672 TJDecompressor_decompress(env, obj, src, jpegSize, dst, 1, x, y, width,
673 pitch, height, pf, flags);
674}
675
DRCa4940d12014-08-15 16:07:15 +0000676/* TurboJPEG 1.2.x: TJDecompressor::decompress() byte destination */
DRCf659f432012-06-06 08:41:06 +0000677JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompress___3BI_3BIIIII
678 (JNIEnv *env, jobject obj, jbyteArray src, jint jpegSize, jbyteArray dst,
679 jint width, jint pitch, jint height, jint pf, jint flags)
680{
DRC927a10d2014-08-15 13:18:58 +0000681 TJDecompressor_decompress(env, obj, src, jpegSize, dst, 1, 0, 0, width,
682 pitch, height, pf, flags);
DRCf659f432012-06-06 08:41:06 +0000683}
684
DRCa4940d12014-08-15 16:07:15 +0000685/* TurboJPEG 1.3.x: TJDecompressor::decompress() int destination */
DRCf659f432012-06-06 08:41:06 +0000686JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompress___3BI_3IIIIIIII
687 (JNIEnv *env, jobject obj, jbyteArray src, jint jpegSize, jintArray dst,
688 jint x, jint y, jint width, jint stride, jint height, jint pf, jint flags)
689{
DRCf659f432012-06-06 08:41:06 +0000690 if(pf<0 || pf>=org_libjpegturbo_turbojpeg_TJ_NUMPF)
DRCb3817da2015-07-14 20:42:52 +0000691 _throwarg("Invalid argument in decompress()");
DRCf659f432012-06-06 08:41:06 +0000692 if(tjPixelSize[pf]!=sizeof(jint))
DRCb3817da2015-07-14 20:42:52 +0000693 _throwarg("Pixel format must be 32-bit when decompressing to an integer buffer.");
DRCf659f432012-06-06 08:41:06 +0000694
DRC927a10d2014-08-15 13:18:58 +0000695 TJDecompressor_decompress(env, obj, src, jpegSize, dst, sizeof(jint), x, y,
696 width, stride*sizeof(jint), height, pf, flags);
DRCf8e00552011-02-04 11:06:36 +0000697
698 bailout:
DRCf8e00552011-02-04 11:06:36 +0000699 return;
700}
701
DRCa4940d12014-08-15 16:07:15 +0000702/* TurboJPEG 1.2.x: TJDecompressor::decompress() int destination */
DRC4f1580c2011-02-25 06:11:03 +0000703JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompress___3BI_3IIIIII
DRC9b28def2011-05-21 14:37:15 +0000704 (JNIEnv *env, jobject obj, jbyteArray src, jint jpegSize, jintArray dst,
DRCf659f432012-06-06 08:41:06 +0000705 jint width, jint stride, jint height, jint pf, jint flags)
DRC84a1bcc2011-02-23 12:09:56 +0000706{
DRC927a10d2014-08-15 13:18:58 +0000707 if(pf<0 || pf>=org_libjpegturbo_turbojpeg_TJ_NUMPF)
DRCb3817da2015-07-14 20:42:52 +0000708 _throwarg("Invalid argument in decompress()");
DRC927a10d2014-08-15 13:18:58 +0000709 if(tjPixelSize[pf]!=sizeof(jint))
DRCb3817da2015-07-14 20:42:52 +0000710 _throwarg("Pixel format must be 32-bit when decompressing to an integer buffer.");
DRC927a10d2014-08-15 13:18:58 +0000711
712 TJDecompressor_decompress(env, obj, src, jpegSize, dst, sizeof(jint), 0, 0,
713 width, stride*sizeof(jint), height, pf, flags);
714
715 bailout:
716 return;
DRC1a45b812014-05-09 18:06:58 +0000717
DRC4f1580c2011-02-25 06:11:03 +0000718}
DRC84a1bcc2011-02-23 12:09:56 +0000719
DRCa4940d12014-08-15 16:07:15 +0000720/* TurboJPEG 1.4.x: TJDecompressor::decompressToYUV() */
DRC40dd3142014-08-17 12:23:49 +0000721JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompressToYUV___3BI_3_3B_3II_3III
722 (JNIEnv *env, jobject obj, jbyteArray src, jint jpegSize,
723 jobjectArray dstobjs, jintArray jDstOffsets, jint desiredWidth,
724 jintArray jDstStrides, jint desiredHeight, jint flags)
DRC4f1580c2011-02-25 06:11:03 +0000725{
726 tjhandle handle=0;
DRC40dd3142014-08-17 12:23:49 +0000727 jbyteArray jDstPlanes[3]={NULL, NULL, NULL};
728 unsigned char *jpegBuf=NULL, *dstPlanes[3];
729 int *dstOffsets=NULL, *dstStrides=NULL;
DRC6acf52b2011-03-02 01:09:20 +0000730 int jpegSubsamp=-1, jpegWidth=0, jpegHeight=0;
DRC40dd3142014-08-17 12:23:49 +0000731 int nc=0, i, width, height, scaledWidth, scaledHeight, nsf=0;
732 tjscalingfactor *sf;
733
DRC4f1580c2011-02-25 06:11:03 +0000734
735 gethandle();
736
DRC9b28def2011-05-21 14:37:15 +0000737 if((*env)->GetArrayLength(env, src)<jpegSize)
DRCb3817da2015-07-14 20:42:52 +0000738 _throwarg("Source buffer is not large enough");
DRC26dd86b2014-08-15 14:01:21 +0000739 bailif0(_fid=(*env)->GetFieldID(env, _cls, "jpegSubsamp", "I"));
DRC6acf52b2011-03-02 01:09:20 +0000740 jpegSubsamp=(int)(*env)->GetIntField(env, obj, _fid);
DRC26dd86b2014-08-15 14:01:21 +0000741 bailif0(_fid=(*env)->GetFieldID(env, _cls, "jpegWidth", "I"));
DRC6acf52b2011-03-02 01:09:20 +0000742 jpegWidth=(int)(*env)->GetIntField(env, obj, _fid);
DRC26dd86b2014-08-15 14:01:21 +0000743 bailif0(_fid=(*env)->GetFieldID(env, _cls, "jpegHeight", "I"));
DRC6acf52b2011-03-02 01:09:20 +0000744 jpegHeight=(int)(*env)->GetIntField(env, obj, _fid);
DRC6acf52b2011-03-02 01:09:20 +0000745
DRC40dd3142014-08-17 12:23:49 +0000746 nc=(jpegSubsamp==org_libjpegturbo_turbojpeg_TJ_SAMP_GRAY? 1:3);
DRC4f1580c2011-02-25 06:11:03 +0000747
DRC40dd3142014-08-17 12:23:49 +0000748 width=desiredWidth; height=desiredHeight;
749 if(width==0) width=jpegWidth;
750 if(height==0) height=jpegHeight;
751 sf=tjGetScalingFactors(&nsf);
752 if(!sf || nsf<1)
DRC739edeb2015-07-21 09:34:02 -0500753 _throwarg(tjGetErrorStr());
DRC40dd3142014-08-17 12:23:49 +0000754 for(i=0; i<nsf; i++)
755 {
756 scaledWidth=TJSCALED(jpegWidth, sf[i]);
757 scaledHeight=TJSCALED(jpegHeight, sf[i]);
758 if(scaledWidth<=width && scaledHeight<=height)
759 break;
760 }
761
762 bailif0(dstOffsets=(*env)->GetPrimitiveArrayCritical(env, jDstOffsets, 0));
763 bailif0(dstStrides=(*env)->GetPrimitiveArrayCritical(env, jDstStrides, 0));
764 for(i=0; i<nc; i++)
765 {
766 int planeSize=tjPlaneSizeYUV(i, scaledWidth, dstStrides[i], scaledHeight,
767 jpegSubsamp);
768 int pw=tjPlaneWidth(i, scaledWidth, jpegSubsamp);
769
770 if(planeSize<0 || pw<0)
DRC739edeb2015-07-21 09:34:02 -0500771 _throwarg(tjGetErrorStr());
DRC40dd3142014-08-17 12:23:49 +0000772
773 if(dstOffsets[i]<0)
DRCb3817da2015-07-14 20:42:52 +0000774 _throwarg("Invalid argument in decompressToYUV()");
DRC40dd3142014-08-17 12:23:49 +0000775 if(dstStrides[i]<0 && dstOffsets[i]-planeSize+pw<0)
DRCb3817da2015-07-14 20:42:52 +0000776 _throwarg("Negative plane stride would cause memory to be accessed below plane boundary");
DRC40dd3142014-08-17 12:23:49 +0000777
778 bailif0(jDstPlanes[i]=(*env)->GetObjectArrayElement(env, dstobjs, i));
779 if((*env)->GetArrayLength(env, jDstPlanes[i])<dstOffsets[i]+planeSize)
DRCb3817da2015-07-14 20:42:52 +0000780 _throwarg("Destination plane is not large enough");
DRC40dd3142014-08-17 12:23:49 +0000781
782 bailif0(dstPlanes[i]=(*env)->GetPrimitiveArrayCritical(env, jDstPlanes[i],
783 0));
784 dstPlanes[i]=&dstPlanes[i][dstOffsets[i]];
785 }
786 bailif0(jpegBuf=(*env)->GetPrimitiveArrayCritical(env, src, 0));
787
788 if(tjDecompressToYUVPlanes(handle, jpegBuf, (unsigned long)jpegSize,
789 dstPlanes, desiredWidth, dstStrides, desiredHeight, flags)==-1)
DRCb3817da2015-07-14 20:42:52 +0000790 _throwtj();
DRC4f1580c2011-02-25 06:11:03 +0000791
792 bailout:
DRC9b28def2011-05-21 14:37:15 +0000793 if(jpegBuf) (*env)->ReleasePrimitiveArrayCritical(env, src, jpegBuf, 0);
DRC40dd3142014-08-17 12:23:49 +0000794 for(i=0; i<nc; i++)
795 {
796 if(dstPlanes[i] && jDstPlanes[i])
797 (*env)->ReleasePrimitiveArrayCritical(env, jDstPlanes[i], dstPlanes[i],
798 0);
799 }
800 if(dstStrides)
801 (*env)->ReleasePrimitiveArrayCritical(env, jDstStrides, dstStrides, 0);
802 if(dstOffsets)
803 (*env)->ReleasePrimitiveArrayCritical(env, jDstOffsets, dstOffsets, 0);
DRC4f1580c2011-02-25 06:11:03 +0000804 return;
DRC84a1bcc2011-02-23 12:09:56 +0000805}
806
DRCa4940d12014-08-15 16:07:15 +0000807/* TurboJPEG 1.2.x: TJDecompressor::decompressToYUV() */
DRCfef98522013-04-28 01:32:52 +0000808JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompressToYUV___3BI_3BI
809 (JNIEnv *env, jobject obj, jbyteArray src, jint jpegSize, jbyteArray dst,
810 jint flags)
811{
DRCfc26b652014-03-16 22:56:26 +0000812 tjhandle handle=0;
DRC40dd3142014-08-17 12:23:49 +0000813 unsigned char *jpegBuf=NULL, *dstBuf=NULL;
814 int jpegSubsamp=-1, jpegWidth=0, jpegHeight=0;
DRCfc26b652014-03-16 22:56:26 +0000815
816 gethandle();
817
DRC40dd3142014-08-17 12:23:49 +0000818 if((*env)->GetArrayLength(env, src)<jpegSize)
DRCb3817da2015-07-14 20:42:52 +0000819 _throwarg("Source buffer is not large enough");
DRC40dd3142014-08-17 12:23:49 +0000820 bailif0(_fid=(*env)->GetFieldID(env, _cls, "jpegSubsamp", "I"));
821 jpegSubsamp=(int)(*env)->GetIntField(env, obj, _fid);
822 bailif0(_fid=(*env)->GetFieldID(env, _cls, "jpegWidth", "I"));
823 jpegWidth=(int)(*env)->GetIntField(env, obj, _fid);
824 bailif0(_fid=(*env)->GetFieldID(env, _cls, "jpegHeight", "I"));
825 jpegHeight=(int)(*env)->GetIntField(env, obj, _fid);
826 if((*env)->GetArrayLength(env, dst)
827 <(jsize)tjBufSizeYUV(jpegWidth, jpegHeight, jpegSubsamp))
DRCb3817da2015-07-14 20:42:52 +0000828 _throwarg("Destination buffer is not large enough");
DRC40dd3142014-08-17 12:23:49 +0000829
830 bailif0(jpegBuf=(*env)->GetPrimitiveArrayCritical(env, src, 0));
831 bailif0(dstBuf=(*env)->GetPrimitiveArrayCritical(env, dst, 0));
832
833 if(tjDecompressToYUV(handle, jpegBuf, (unsigned long)jpegSize, dstBuf,
834 flags)==-1)
DRCb3817da2015-07-14 20:42:52 +0000835 _throwtj();
DRC40dd3142014-08-17 12:23:49 +0000836
837 bailout:
838 if(dstBuf) (*env)->ReleasePrimitiveArrayCritical(env, dst, dstBuf, 0);
839 if(jpegBuf) (*env)->ReleasePrimitiveArrayCritical(env, src, jpegBuf, 0);
840 return;
841}
842
843static void TJDecompressor_decodeYUV
844 (JNIEnv *env, jobject obj, jobjectArray srcobjs, jintArray jSrcOffsets,
845 jintArray jSrcStrides, jint subsamp, jarray dst, jint dstElementSize,
846 jint x, jint y, jint width, jint pitch, jint height, jint pf, jint flags)
847{
848 tjhandle handle=0;
849 jsize arraySize=0, actualPitch;
850 jbyteArray jSrcPlanes[3]={NULL, NULL, NULL};
DRC6fa14b32015-08-13 20:06:03 -0500851 const unsigned char *srcPlanes[3];
852 unsigned char *dstBuf=NULL;
DRC40dd3142014-08-17 12:23:49 +0000853 int *srcOffsets=NULL, *srcStrides=NULL;
854 int nc=(subsamp==org_libjpegturbo_turbojpeg_TJ_SAMP_GRAY? 1:3), i;
855
856 gethandle();
857
858 if(pf<0 || pf>=org_libjpegturbo_turbojpeg_TJ_NUMPF || subsamp<0
859 || subsamp>=org_libjpegturbo_turbojpeg_TJ_NUMSAMP)
DRCb3817da2015-07-14 20:42:52 +0000860 _throwarg("Invalid argument in decodeYUV()");
DRC40dd3142014-08-17 12:23:49 +0000861 if(org_libjpegturbo_turbojpeg_TJ_NUMPF!=TJ_NUMPF
862 || org_libjpegturbo_turbojpeg_TJ_NUMSAMP!=TJ_NUMSAMP)
DRCb3817da2015-07-14 20:42:52 +0000863 _throwarg("Mismatch between Java and C API");
DRCfc26b652014-03-16 22:56:26 +0000864
DRC40dd3142014-08-17 12:23:49 +0000865 if((*env)->GetArrayLength(env, srcobjs)<nc)
DRCb3817da2015-07-14 20:42:52 +0000866 _throwarg("Planes array is too small for the subsampling type");
DRC40dd3142014-08-17 12:23:49 +0000867 if((*env)->GetArrayLength(env, jSrcOffsets)<nc)
DRCb3817da2015-07-14 20:42:52 +0000868 _throwarg("Offsets array is too small for the subsampling type");
DRC40dd3142014-08-17 12:23:49 +0000869 if((*env)->GetArrayLength(env, jSrcStrides)<nc)
DRCb3817da2015-07-14 20:42:52 +0000870 _throwarg("Strides array is too small for the subsampling type");
DRC40dd3142014-08-17 12:23:49 +0000871
DRCfc26b652014-03-16 22:56:26 +0000872 actualPitch=(pitch==0)? width*tjPixelSize[pf]:pitch;
873 arraySize=(y+height-1)*actualPitch + (x+width)*tjPixelSize[pf];
DRC927a10d2014-08-15 13:18:58 +0000874 if((*env)->GetArrayLength(env, dst)*dstElementSize<arraySize)
DRCb3817da2015-07-14 20:42:52 +0000875 _throwarg("Destination buffer is not large enough");
DRCfc26b652014-03-16 22:56:26 +0000876
DRC40dd3142014-08-17 12:23:49 +0000877 bailif0(srcOffsets=(*env)->GetPrimitiveArrayCritical(env, jSrcOffsets, 0));
878 bailif0(srcStrides=(*env)->GetPrimitiveArrayCritical(env, jSrcStrides, 0));
879 for(i=0; i<nc; i++)
880 {
881 int planeSize=tjPlaneSizeYUV(i, width, srcStrides[i], height, subsamp);
882 int pw=tjPlaneWidth(i, width, subsamp);
883
884 if(planeSize<0 || pw<0)
DRC739edeb2015-07-21 09:34:02 -0500885 _throwarg(tjGetErrorStr());
DRC40dd3142014-08-17 12:23:49 +0000886
887 if(srcOffsets[i]<0)
DRCb3817da2015-07-14 20:42:52 +0000888 _throwarg("Invalid argument in decodeYUV()");
DRC40dd3142014-08-17 12:23:49 +0000889 if(srcStrides[i]<0 && srcOffsets[i]-planeSize+pw<0)
DRCb3817da2015-07-14 20:42:52 +0000890 _throwarg("Negative plane stride would cause memory to be accessed below plane boundary");
DRC40dd3142014-08-17 12:23:49 +0000891
892 bailif0(jSrcPlanes[i]=(*env)->GetObjectArrayElement(env, srcobjs, i));
893 if((*env)->GetArrayLength(env, jSrcPlanes[i])<srcOffsets[i]+planeSize)
DRCb3817da2015-07-14 20:42:52 +0000894 _throwarg("Source plane is not large enough");
DRC40dd3142014-08-17 12:23:49 +0000895
896 bailif0(srcPlanes[i]=(*env)->GetPrimitiveArrayCritical(env, jSrcPlanes[i],
897 0));
898 srcPlanes[i]=&srcPlanes[i][srcOffsets[i]];
899 }
DRCfc26b652014-03-16 22:56:26 +0000900 bailif0(dstBuf=(*env)->GetPrimitiveArrayCritical(env, dst, 0));
901
DRC40dd3142014-08-17 12:23:49 +0000902 if(tjDecodeYUVPlanes(handle, srcPlanes, srcStrides, subsamp,
DRCfc26b652014-03-16 22:56:26 +0000903 &dstBuf[y*actualPitch + x*tjPixelSize[pf]], width, pitch, height, pf,
904 flags)==-1)
DRCb3817da2015-07-14 20:42:52 +0000905 _throwtj();
DRCfc26b652014-03-16 22:56:26 +0000906
907 bailout:
908 if(dstBuf) (*env)->ReleasePrimitiveArrayCritical(env, dst, dstBuf, 0);
DRC40dd3142014-08-17 12:23:49 +0000909 for(i=0; i<nc; i++)
910 {
911 if(srcPlanes[i] && jSrcPlanes[i])
DRC6fa14b32015-08-13 20:06:03 -0500912 (*env)->ReleasePrimitiveArrayCritical(env, jSrcPlanes[i],
913 (unsigned char *)srcPlanes[i], 0);
DRC40dd3142014-08-17 12:23:49 +0000914 }
915 if(srcStrides)
916 (*env)->ReleasePrimitiveArrayCritical(env, jSrcStrides, srcStrides, 0);
917 if(srcOffsets)
918 (*env)->ReleasePrimitiveArrayCritical(env, jSrcOffsets, srcOffsets, 0);
DRCfc26b652014-03-16 22:56:26 +0000919 return;
920}
921
DRCa4940d12014-08-15 16:07:15 +0000922/* TurboJPEG 1.4.x: TJDecompressor::decodeYUV() byte destination */
DRC40dd3142014-08-17 12:23:49 +0000923JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decodeYUV___3_3B_3I_3II_3BIIIIIII
924 (JNIEnv *env, jobject obj, jobjectArray srcobjs, jintArray jSrcOffsets,
925 jintArray jSrcStrides, jint subsamp, jbyteArray dst, jint x, jint y,
926 jint width, jint pitch, jint height, jint pf, jint flags)
DRC927a10d2014-08-15 13:18:58 +0000927{
DRC40dd3142014-08-17 12:23:49 +0000928 TJDecompressor_decodeYUV(env, obj, srcobjs, jSrcOffsets, jSrcStrides,
929 subsamp, dst, 1, x, y, width, pitch, height, pf, flags);
DRC927a10d2014-08-15 13:18:58 +0000930}
931
DRCa4940d12014-08-15 16:07:15 +0000932/* TurboJPEG 1.4.x: TJDecompressor::decodeYUV() int destination */
DRC40dd3142014-08-17 12:23:49 +0000933JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decodeYUV___3_3B_3I_3II_3IIIIIIII
934 (JNIEnv *env, jobject obj, jobjectArray srcobjs, jintArray jSrcOffsets,
935 jintArray jSrcStrides, jint subsamp, jintArray dst, jint x, jint y,
936 jint width, jint stride, jint height, jint pf, jint flags)
DRCfc26b652014-03-16 22:56:26 +0000937{
DRCfc26b652014-03-16 22:56:26 +0000938 if(pf<0 || pf>=org_libjpegturbo_turbojpeg_TJ_NUMPF)
DRCb3817da2015-07-14 20:42:52 +0000939 _throwarg("Invalid argument in decodeYUV()");
DRCfc26b652014-03-16 22:56:26 +0000940 if(tjPixelSize[pf]!=sizeof(jint))
DRCb3817da2015-07-14 20:42:52 +0000941 _throwarg("Pixel format must be 32-bit when decoding to an integer buffer.");
DRCfc26b652014-03-16 22:56:26 +0000942
DRC40dd3142014-08-17 12:23:49 +0000943 TJDecompressor_decodeYUV(env, obj, srcobjs, jSrcOffsets, jSrcStrides,
944 subsamp, dst, sizeof(jint), x, y, width, stride*sizeof(jint), height, pf,
945 flags);
DRCfc26b652014-03-16 22:56:26 +0000946
947 bailout:
DRCfc26b652014-03-16 22:56:26 +0000948 return;
949}
950
DRCa4940d12014-08-15 16:07:15 +0000951/* TurboJPEG 1.2.x: TJTransformer::init() */
DRCe8573012011-03-04 10:13:59 +0000952JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJTransformer_init
953 (JNIEnv *env, jobject obj)
954{
955 jclass cls;
956 jfieldID fid;
957 tjhandle handle;
958
DRCb3817da2015-07-14 20:42:52 +0000959 if((handle=tjInitTransform())==NULL) _throwtj();
DRCe8573012011-03-04 10:13:59 +0000960
961 bailif0(cls=(*env)->GetObjectClass(env, obj));
962 bailif0(fid=(*env)->GetFieldID(env, cls, "handle", "J"));
DRC46a03922014-08-15 14:40:05 +0000963 (*env)->SetLongField(env, obj, fid, (size_t)handle);
DRCe8573012011-03-04 10:13:59 +0000964
965 bailout:
966 return;
967}
968
DRCf5467112011-09-20 05:02:19 +0000969typedef struct _JNICustomFilterParams
970{
971 JNIEnv *env;
972 jobject tobj;
973 jobject cfobj;
974} JNICustomFilterParams;
975
976static int JNICustomFilter(short *coeffs, tjregion arrayRegion,
977 tjregion planeRegion, int componentIndex, int transformIndex,
978 tjtransform *transform)
979{
980 JNICustomFilterParams *params=(JNICustomFilterParams *)transform->data;
981 JNIEnv *env=params->env;
982 jobject tobj=params->tobj, cfobj=params->cfobj;
DRCb7c8c862014-08-15 16:20:59 +0000983 jobject arrayRegionObj, planeRegionObj, bufobj, borobj;
DRCf5467112011-09-20 05:02:19 +0000984 jclass cls; jmethodID mid; jfieldID fid;
985
986 bailif0(bufobj=(*env)->NewDirectByteBuffer(env, coeffs,
987 sizeof(short)*arrayRegion.w*arrayRegion.h));
988 bailif0(cls=(*env)->FindClass(env, "java/nio/ByteOrder"));
DRCb7c8c862014-08-15 16:20:59 +0000989 bailif0(mid=(*env)->GetStaticMethodID(env, cls, "nativeOrder",
DRCf5467112011-09-20 05:02:19 +0000990 "()Ljava/nio/ByteOrder;"));
991 bailif0(borobj=(*env)->CallStaticObjectMethod(env, cls, mid));
992 bailif0(cls=(*env)->GetObjectClass(env, bufobj));
993 bailif0(mid=(*env)->GetMethodID(env, cls, "order",
994 "(Ljava/nio/ByteOrder;)Ljava/nio/ByteBuffer;"));
995 (*env)->CallObjectMethod(env, bufobj, mid, borobj);
DRCb7c8c862014-08-15 16:20:59 +0000996 bailif0(mid=(*env)->GetMethodID(env, cls, "asShortBuffer",
DRCf5467112011-09-20 05:02:19 +0000997 "()Ljava/nio/ShortBuffer;"));
998 bailif0(bufobj=(*env)->CallObjectMethod(env, bufobj, mid));
999
1000 bailif0(cls=(*env)->FindClass(env, "java/awt/Rectangle"));
1001 bailif0(arrayRegionObj=(*env)->AllocObject(env, cls));
1002 bailif0(fid=(*env)->GetFieldID(env, cls, "x", "I"));
1003 (*env)->SetIntField(env, arrayRegionObj, fid, arrayRegion.x);
1004 bailif0(fid=(*env)->GetFieldID(env, cls, "y", "I"));
1005 (*env)->SetIntField(env, arrayRegionObj, fid, arrayRegion.y);
1006 bailif0(fid=(*env)->GetFieldID(env, cls, "width", "I"));
1007 (*env)->SetIntField(env, arrayRegionObj, fid, arrayRegion.w);
1008 bailif0(fid=(*env)->GetFieldID(env, cls, "height", "I"));
1009 (*env)->SetIntField(env, arrayRegionObj, fid, arrayRegion.h);
1010
1011 bailif0(planeRegionObj=(*env)->AllocObject(env, cls));
1012 bailif0(fid=(*env)->GetFieldID(env, cls, "x", "I"));
1013 (*env)->SetIntField(env, planeRegionObj, fid, planeRegion.x);
1014 bailif0(fid=(*env)->GetFieldID(env, cls, "y", "I"));
1015 (*env)->SetIntField(env, planeRegionObj, fid, planeRegion.y);
1016 bailif0(fid=(*env)->GetFieldID(env, cls, "width", "I"));
1017 (*env)->SetIntField(env, planeRegionObj, fid, planeRegion.w);
1018 bailif0(fid=(*env)->GetFieldID(env, cls, "height", "I"));
1019 (*env)->SetIntField(env, planeRegionObj, fid, planeRegion.h);
1020
1021 bailif0(cls=(*env)->GetObjectClass(env, cfobj));
1022 bailif0(mid=(*env)->GetMethodID(env, cls, "customFilter",
1023 "(Ljava/nio/ShortBuffer;Ljava/awt/Rectangle;Ljava/awt/Rectangle;IILorg/libjpegturbo/turbojpeg/TJTransform;)V"));
1024 (*env)->CallVoidMethod(env, cfobj, mid, bufobj, arrayRegionObj,
1025 planeRegionObj, componentIndex, transformIndex, tobj);
1026
1027 return 0;
1028
1029 bailout:
1030 return -1;
1031}
1032
DRCa4940d12014-08-15 16:07:15 +00001033/* TurboJPEG 1.2.x: TJTransformer::transform() */
DRCe8573012011-03-04 10:13:59 +00001034JNIEXPORT jintArray JNICALL Java_org_libjpegturbo_turbojpeg_TJTransformer_transform
DRC9b28def2011-05-21 14:37:15 +00001035 (JNIEnv *env, jobject obj, jbyteArray jsrcBuf, jint jpegSize,
DRCe8573012011-03-04 10:13:59 +00001036 jobjectArray dstobjs, jobjectArray tobjs, jint flags)
1037{
1038 tjhandle handle=0; int i;
DRC9b28def2011-05-21 14:37:15 +00001039 unsigned char *jpegBuf=NULL, **dstBufs=NULL; jsize n=0;
1040 unsigned long *dstSizes=NULL; tjtransform *t=NULL;
1041 jbyteArray *jdstBufs=NULL;
DRC9b49f0e2011-07-12 03:17:23 +00001042 int jpegWidth=0, jpegHeight=0, jpegSubsamp;
DRC9b28def2011-05-21 14:37:15 +00001043 jintArray jdstSizes=0; jint *dstSizesi=NULL;
DRCf5467112011-09-20 05:02:19 +00001044 JNICustomFilterParams *params=NULL;
DRCe8573012011-03-04 10:13:59 +00001045
1046 gethandle();
1047
DRC9b28def2011-05-21 14:37:15 +00001048 if((*env)->GetArrayLength(env, jsrcBuf)<jpegSize)
DRCb3817da2015-07-14 20:42:52 +00001049 _throwarg("Source buffer is not large enough");
DRC26dd86b2014-08-15 14:01:21 +00001050 bailif0(_fid=(*env)->GetFieldID(env, _cls, "jpegWidth", "I"));
DRCe8573012011-03-04 10:13:59 +00001051 jpegWidth=(int)(*env)->GetIntField(env, obj, _fid);
DRC26dd86b2014-08-15 14:01:21 +00001052 bailif0(_fid=(*env)->GetFieldID(env, _cls, "jpegHeight", "I"));
DRCe8573012011-03-04 10:13:59 +00001053 jpegHeight=(int)(*env)->GetIntField(env, obj, _fid);
DRC26dd86b2014-08-15 14:01:21 +00001054 bailif0(_fid=(*env)->GetFieldID(env, _cls, "jpegSubsamp", "I"));
DRC9b49f0e2011-07-12 03:17:23 +00001055 jpegSubsamp=(int)(*env)->GetIntField(env, obj, _fid);
DRCe8573012011-03-04 10:13:59 +00001056
1057 n=(*env)->GetArrayLength(env, dstobjs);
1058 if(n!=(*env)->GetArrayLength(env, tobjs))
DRCb3817da2015-07-14 20:42:52 +00001059 _throwarg("Mismatch between size of transforms array and destination buffers array");
DRCe8573012011-03-04 10:13:59 +00001060
DRC9b28def2011-05-21 14:37:15 +00001061 if((dstBufs=(unsigned char **)malloc(sizeof(unsigned char *)*n))==NULL)
DRCb3817da2015-07-14 20:42:52 +00001062 _throwmem();
DRC9b28def2011-05-21 14:37:15 +00001063 if((jdstBufs=(jbyteArray *)malloc(sizeof(jbyteArray)*n))==NULL)
DRCb3817da2015-07-14 20:42:52 +00001064 _throwmem();
DRC9b28def2011-05-21 14:37:15 +00001065 if((dstSizes=(unsigned long *)malloc(sizeof(unsigned long)*n))==NULL)
DRCb3817da2015-07-14 20:42:52 +00001066 _throwmem();
DRCe8573012011-03-04 10:13:59 +00001067 if((t=(tjtransform *)malloc(sizeof(tjtransform)*n))==NULL)
DRCb3817da2015-07-14 20:42:52 +00001068 _throwmem();
DRCf5467112011-09-20 05:02:19 +00001069 if((params=(JNICustomFilterParams *)malloc(sizeof(JNICustomFilterParams)*n))
1070 ==NULL)
DRCb3817da2015-07-14 20:42:52 +00001071 _throwmem();
DRCe8573012011-03-04 10:13:59 +00001072 for(i=0; i<n; i++)
1073 {
DRC9b28def2011-05-21 14:37:15 +00001074 dstBufs[i]=NULL; jdstBufs[i]=NULL; dstSizes[i]=0;
DRCe8573012011-03-04 10:13:59 +00001075 memset(&t[i], 0, sizeof(tjtransform));
DRCf5467112011-09-20 05:02:19 +00001076 memset(&params[i], 0, sizeof(JNICustomFilterParams));
DRCe8573012011-03-04 10:13:59 +00001077 }
1078
1079 for(i=0; i<n; i++)
1080 {
DRCf5467112011-09-20 05:02:19 +00001081 jobject tobj, cfobj;
DRCe8573012011-03-04 10:13:59 +00001082
1083 bailif0(tobj=(*env)->GetObjectArrayElement(env, tobjs, i));
1084 bailif0(_cls=(*env)->GetObjectClass(env, tobj));
1085 bailif0(_fid=(*env)->GetFieldID(env, _cls, "op", "I"));
1086 t[i].op=(*env)->GetIntField(env, tobj, _fid);
1087 bailif0(_fid=(*env)->GetFieldID(env, _cls, "options", "I"));
1088 t[i].options=(*env)->GetIntField(env, tobj, _fid);
1089 bailif0(_fid=(*env)->GetFieldID(env, _cls, "x", "I"));
1090 t[i].r.x=(*env)->GetIntField(env, tobj, _fid);
1091 bailif0(_fid=(*env)->GetFieldID(env, _cls, "y", "I"));
1092 t[i].r.y=(*env)->GetIntField(env, tobj, _fid);
1093 bailif0(_fid=(*env)->GetFieldID(env, _cls, "width", "I"));
1094 t[i].r.w=(*env)->GetIntField(env, tobj, _fid);
1095 bailif0(_fid=(*env)->GetFieldID(env, _cls, "height", "I"));
1096 t[i].r.h=(*env)->GetIntField(env, tobj, _fid);
DRCf5467112011-09-20 05:02:19 +00001097
DRCf5467112011-09-20 05:02:19 +00001098 bailif0(_fid=(*env)->GetFieldID(env, _cls, "cf",
1099 "Lorg/libjpegturbo/turbojpeg/TJCustomFilter;"));
DRC06420c42011-09-26 18:46:09 +00001100 cfobj=(*env)->GetObjectField(env, tobj, _fid);
1101 if(cfobj)
1102 {
1103 params[i].env=env;
1104 params[i].tobj=tobj;
1105 params[i].cfobj=cfobj;
1106 t[i].customFilter=JNICustomFilter;
1107 t[i].data=(void *)&params[i];
1108 }
DRCe8573012011-03-04 10:13:59 +00001109 }
1110
DRCe8573012011-03-04 10:13:59 +00001111 for(i=0; i<n; i++)
1112 {
1113 int w=jpegWidth, h=jpegHeight;
1114 if(t[i].r.w!=0) w=t[i].r.w;
1115 if(t[i].r.h!=0) h=t[i].r.h;
DRC9b28def2011-05-21 14:37:15 +00001116 bailif0(jdstBufs[i]=(*env)->GetObjectArrayElement(env, dstobjs, i));
DRCefe28ce2012-01-17 11:48:38 +00001117 if((unsigned long)(*env)->GetArrayLength(env, jdstBufs[i])
1118 <tjBufSize(w, h, jpegSubsamp))
DRCb3817da2015-07-14 20:42:52 +00001119 _throwarg("Destination buffer is not large enough");
DRCe8573012011-03-04 10:13:59 +00001120 }
DRC8951cf02014-08-14 16:54:04 +00001121 bailif0(jpegBuf=(*env)->GetPrimitiveArrayCritical(env, jsrcBuf, 0));
1122 for(i=0; i<n; i++)
1123 bailif0(dstBufs[i]=(*env)->GetPrimitiveArrayCritical(env, jdstBufs[i], 0));
DRCe8573012011-03-04 10:13:59 +00001124
DRC9b28def2011-05-21 14:37:15 +00001125 if(tjTransform(handle, jpegBuf, jpegSize, n, dstBufs, dstSizes, t,
DRC4db92ad2011-05-25 04:52:25 +00001126 flags|TJFLAG_NOREALLOC)==-1)
DRCb3817da2015-07-14 20:42:52 +00001127 _throwtj();
DRC8951cf02014-08-14 16:54:04 +00001128
1129 for(i=0; i<n; i++)
1130 {
1131 (*env)->ReleasePrimitiveArrayCritical(env, jdstBufs[i], dstBufs[i], 0);
1132 dstBufs[i]=NULL;
DRCe8573012011-03-04 10:13:59 +00001133 }
DRC8951cf02014-08-14 16:54:04 +00001134 (*env)->ReleasePrimitiveArrayCritical(env, jsrcBuf, jpegBuf, 0);
1135 jpegBuf=NULL;
DRCe8573012011-03-04 10:13:59 +00001136
DRC9b28def2011-05-21 14:37:15 +00001137 jdstSizes=(*env)->NewIntArray(env, n);
1138 bailif0(dstSizesi=(*env)->GetIntArrayElements(env, jdstSizes, 0));
1139 for(i=0; i<n; i++) dstSizesi[i]=(int)dstSizes[i];
DRCe8573012011-03-04 10:13:59 +00001140
1141 bailout:
DRC8951cf02014-08-14 16:54:04 +00001142 if(dstSizesi) (*env)->ReleaseIntArrayElements(env, jdstSizes, dstSizesi, 0);
DRC9b28def2011-05-21 14:37:15 +00001143 if(dstBufs)
DRCe8573012011-03-04 10:13:59 +00001144 {
1145 for(i=0; i<n; i++)
1146 {
DRC9b28def2011-05-21 14:37:15 +00001147 if(dstBufs[i] && jdstBufs && jdstBufs[i])
1148 (*env)->ReleasePrimitiveArrayCritical(env, jdstBufs[i], dstBufs[i], 0);
DRCe8573012011-03-04 10:13:59 +00001149 }
DRC9b28def2011-05-21 14:37:15 +00001150 free(dstBufs);
DRCe8573012011-03-04 10:13:59 +00001151 }
DRC8951cf02014-08-14 16:54:04 +00001152 if(jpegBuf) (*env)->ReleasePrimitiveArrayCritical(env, jsrcBuf, jpegBuf, 0);
DRC9b28def2011-05-21 14:37:15 +00001153 if(jdstBufs) free(jdstBufs);
1154 if(dstSizes) free(dstSizes);
DRCe8573012011-03-04 10:13:59 +00001155 if(t) free(t);
DRC9b28def2011-05-21 14:37:15 +00001156 return jdstSizes;
DRCe8573012011-03-04 10:13:59 +00001157}
1158
DRCa4940d12014-08-15 16:07:15 +00001159/* TurboJPEG 1.2.x: TJDecompressor::destroy() */
DRCc5a41992011-02-08 06:54:36 +00001160JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_destroy
DRCf8e00552011-02-04 11:06:36 +00001161 (JNIEnv *env, jobject obj)
1162{
DRCc5a41992011-02-08 06:54:36 +00001163 Java_org_libjpegturbo_turbojpeg_TJCompressor_destroy(env, obj);
DRCf8e00552011-02-04 11:06:36 +00001164}