blob: 999247940132fb5221a803969cb86278b61a5ea8 [file] [log] [blame]
DRCf8e00552011-02-04 11:06:36 +00001/*
DRC6399d0a2019-04-23 14:10:04 -05002 * Copyright (C)2011-2019 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"
DRC6399d0a2019-04-23 14:10:04 -050038#include "java/org_libjpegturbo_turbojpeg_TJTransformer.h"
DRCc5a41992011-02-08 06:54:36 +000039#include "java/org_libjpegturbo_turbojpeg_TJ.h"
DRCf8e00552011-02-04 11:06:36 +000040
DRCbce58f42019-04-12 07:49:35 -050041#define BAILIF0(f) { \
DRC19c791c2018-03-08 10:55:20 -060042 if (!(f) || (*env)->ExceptionCheck(env)) { \
43 goto bailout; \
44 } \
DRCf8e00552011-02-04 11:06:36 +000045}
46
DRCbce58f42019-04-12 07:49:35 -050047#define THROW(msg, exceptionClass) { \
DRC19c791c2018-03-08 10:55:20 -060048 jclass _exccls = (*env)->FindClass(env, exceptionClass); \
49 \
DRCbce58f42019-04-12 07:49:35 -050050 BAILIF0(_exccls); \
DRC19c791c2018-03-08 10:55:20 -060051 (*env)->ThrowNew(env, _exccls, msg); \
52 goto bailout; \
53}
54
DRCbce58f42019-04-12 07:49:35 -050055#define THROW_TJ() { \
DRC19c791c2018-03-08 10:55:20 -060056 jclass _exccls; \
57 jmethodID _excid; \
58 jobject _excobj; \
59 jstring _errstr; \
60 \
DRCbce58f42019-04-12 07:49:35 -050061 BAILIF0(_errstr = (*env)->NewStringUTF(env, tjGetErrorStr2(handle))); \
62 BAILIF0(_exccls = (*env)->FindClass(env, \
DRC19c791c2018-03-08 10:55:20 -060063 "org/libjpegturbo/turbojpeg/TJException")); \
DRCbce58f42019-04-12 07:49:35 -050064 BAILIF0(_excid = (*env)->GetMethodID(env, _exccls, "<init>", \
DRC19c791c2018-03-08 10:55:20 -060065 "(Ljava/lang/String;I)V")); \
DRCbce58f42019-04-12 07:49:35 -050066 BAILIF0(_excobj = (*env)->NewObject(env, _exccls, _excid, _errstr, \
DRC19c791c2018-03-08 10:55:20 -060067 tjGetErrorCode(handle))); \
68 (*env)->Throw(env, _excobj); \
69 goto bailout; \
DRCd4092f62017-06-27 10:54:21 -050070}
DRCb3817da2015-07-14 20:42:52 +000071
DRCbce58f42019-04-12 07:49:35 -050072#define THROW_ARG(msg) THROW(msg, "java/lang/IllegalArgumentException")
DRCb3817da2015-07-14 20:42:52 +000073
DRCbce58f42019-04-12 07:49:35 -050074#define THROW_MEM() \
75 THROW("Memory allocation failure", "java/lang/OutOfMemoryError");
DRCb3817da2015-07-14 20:42:52 +000076
DRCbce58f42019-04-12 07:49:35 -050077#define GET_HANDLE() \
DRC19c791c2018-03-08 10:55:20 -060078 jclass _cls = (*env)->GetObjectClass(env, obj); \
79 jfieldID _fid; \
80 \
DRCbce58f42019-04-12 07:49:35 -050081 BAILIF0(_cls); \
82 BAILIF0(_fid = (*env)->GetFieldID(env, _cls, "handle", "J")); \
DRC19c791c2018-03-08 10:55:20 -060083 handle = (tjhandle)(size_t)(*env)->GetLongField(env, obj, _fid);
DRCf8e00552011-02-04 11:06:36 +000084
DRCbdb36e12014-08-22 15:39:32 +000085#ifdef _WIN32
DRC293263c2018-03-17 15:14:35 -050086#define setenv(envvar, value, dummy) _putenv_s(envvar, value)
DRCbdb36e12014-08-22 15:39:32 +000087#endif
88
DRCbce58f42019-04-12 07:49:35 -050089#define PROP2ENV(property, envvar) { \
DRC19c791c2018-03-08 10:55:20 -060090 if ((jName = (*env)->NewStringUTF(env, property)) != NULL && \
91 (jValue = (*env)->CallStaticObjectMethod(env, cls, mid, \
92 jName)) != NULL) { \
93 if ((value = (*env)->GetStringUTFChars(env, jValue, 0)) != NULL) { \
94 setenv(envvar, value, 1); \
95 (*env)->ReleaseStringUTFChars(env, jValue, value); \
96 } \
97 } \
DRC0713c1b2014-08-22 13:43:33 +000098}
99
DRC33011752019-04-12 08:47:28 -0500100#define SAFE_RELEASE(javaArray, cArray) { \
101 if (javaArray && cArray) \
102 (*env)->ReleasePrimitiveArrayCritical(env, javaArray, (void *)cArray, 0); \
103 cArray = NULL; \
104}
105
DRC6399d0a2019-04-23 14:10:04 -0500106static int ProcessSystemProperties(JNIEnv *env)
DRC0713c1b2014-08-22 13:43:33 +0000107{
DRC19c791c2018-03-08 10:55:20 -0600108 jclass cls;
109 jmethodID mid;
110 jstring jName, jValue;
111 const char *value;
DRC0713c1b2014-08-22 13:43:33 +0000112
DRCbce58f42019-04-12 07:49:35 -0500113 BAILIF0(cls = (*env)->FindClass(env, "java/lang/System"));
114 BAILIF0(mid = (*env)->GetStaticMethodID(env, cls, "getProperty",
DRC19c791c2018-03-08 10:55:20 -0600115 "(Ljava/lang/String;)Ljava/lang/String;"));
DRC0713c1b2014-08-22 13:43:33 +0000116
DRCbce58f42019-04-12 07:49:35 -0500117 PROP2ENV("turbojpeg.optimize", "TJ_OPTIMIZE");
118 PROP2ENV("turbojpeg.arithmetic", "TJ_ARITHMETIC");
119 PROP2ENV("turbojpeg.restart", "TJ_RESTART");
120 PROP2ENV("turbojpeg.progressive", "TJ_PROGRESSIVE");
DRC19c791c2018-03-08 10:55:20 -0600121 return 0;
DRC0713c1b2014-08-22 13:43:33 +0000122
DRC19c791c2018-03-08 10:55:20 -0600123bailout:
124 return -1;
DRC0713c1b2014-08-22 13:43:33 +0000125}
126
DRCa4940d12014-08-15 16:07:15 +0000127/* TurboJPEG 1.2.x: TJ::bufSize() */
DRC3bad53f2011-02-23 02:20:49 +0000128JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJ_bufSize
DRC19c791c2018-03-08 10:55:20 -0600129 (JNIEnv *env, jclass cls, jint width, jint height, jint jpegSubsamp)
DRCf8e00552011-02-04 11:06:36 +0000130{
DRC19c791c2018-03-08 10:55:20 -0600131 jint retval = (jint)tjBufSize(width, height, jpegSubsamp);
DRC36336fc2011-02-22 10:27:31 +0000132
DRCbce58f42019-04-12 07:49:35 -0500133 if (retval == -1) THROW_ARG(tjGetErrorStr());
DRC19c791c2018-03-08 10:55:20 -0600134
135bailout:
136 return retval;
DRC36336fc2011-02-22 10:27:31 +0000137}
138
DRCa4940d12014-08-15 16:07:15 +0000139/* TurboJPEG 1.4.x: TJ::bufSizeYUV() */
DRCfef98522013-04-28 01:32:52 +0000140JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJ_bufSizeYUV__IIII
DRC19c791c2018-03-08 10:55:20 -0600141 (JNIEnv *env, jclass cls, jint width, jint pad, jint height, jint subsamp)
DRC36336fc2011-02-22 10:27:31 +0000142{
DRC19c791c2018-03-08 10:55:20 -0600143 jint retval = (jint)tjBufSizeYUV2(width, pad, height, subsamp);
DRC36336fc2011-02-22 10:27:31 +0000144
DRCbce58f42019-04-12 07:49:35 -0500145 if (retval == -1) THROW_ARG(tjGetErrorStr());
DRC19c791c2018-03-08 10:55:20 -0600146
147bailout:
148 return retval;
DRCf8e00552011-02-04 11:06:36 +0000149}
150
DRCa4940d12014-08-15 16:07:15 +0000151/* TurboJPEG 1.2.x: TJ::bufSizeYUV() */
DRCfef98522013-04-28 01:32:52 +0000152JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJ_bufSizeYUV__III
DRC19c791c2018-03-08 10:55:20 -0600153 (JNIEnv *env, jclass cls, jint width, jint height, jint subsamp)
DRCfef98522013-04-28 01:32:52 +0000154{
DRC19c791c2018-03-08 10:55:20 -0600155 return Java_org_libjpegturbo_turbojpeg_TJ_bufSizeYUV__IIII(env, cls, width,
156 4, height,
157 subsamp);
DRCfef98522013-04-28 01:32:52 +0000158}
159
DRC40dd3142014-08-17 12:23:49 +0000160/* TurboJPEG 1.4.x: TJ::planeSizeYUV() */
161JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJ_planeSizeYUV__IIIII
DRC19c791c2018-03-08 10:55:20 -0600162 (JNIEnv *env, jclass cls, jint componentID, jint width, jint stride,
163 jint height, jint subsamp)
DRC40dd3142014-08-17 12:23:49 +0000164{
DRC19c791c2018-03-08 10:55:20 -0600165 jint retval = (jint)tjPlaneSizeYUV(componentID, width, stride, height,
166 subsamp);
DRC40dd3142014-08-17 12:23:49 +0000167
DRCbce58f42019-04-12 07:49:35 -0500168 if (retval == -1) THROW_ARG(tjGetErrorStr());
DRC19c791c2018-03-08 10:55:20 -0600169
170bailout:
171 return retval;
DRC40dd3142014-08-17 12:23:49 +0000172}
173
174/* TurboJPEG 1.4.x: TJ::planeWidth() */
175JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJ_planeWidth__III
DRC19c791c2018-03-08 10:55:20 -0600176 (JNIEnv *env, jclass cls, jint componentID, jint width, jint subsamp)
DRC40dd3142014-08-17 12:23:49 +0000177{
DRC19c791c2018-03-08 10:55:20 -0600178 jint retval = (jint)tjPlaneWidth(componentID, width, subsamp);
DRC40dd3142014-08-17 12:23:49 +0000179
DRCbce58f42019-04-12 07:49:35 -0500180 if (retval == -1) THROW_ARG(tjGetErrorStr());
DRC19c791c2018-03-08 10:55:20 -0600181
182bailout:
183 return retval;
DRC40dd3142014-08-17 12:23:49 +0000184}
185
186/* TurboJPEG 1.4.x: TJ::planeHeight() */
187JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJ_planeHeight__III
DRC19c791c2018-03-08 10:55:20 -0600188 (JNIEnv *env, jclass cls, jint componentID, jint height, jint subsamp)
DRC40dd3142014-08-17 12:23:49 +0000189{
DRC19c791c2018-03-08 10:55:20 -0600190 jint retval = (jint)tjPlaneHeight(componentID, height, subsamp);
DRC40dd3142014-08-17 12:23:49 +0000191
DRCbce58f42019-04-12 07:49:35 -0500192 if (retval == -1) THROW_ARG(tjGetErrorStr());
DRC19c791c2018-03-08 10:55:20 -0600193
194bailout:
195 return retval;
DRC40dd3142014-08-17 12:23:49 +0000196}
197
DRCa4940d12014-08-15 16:07:15 +0000198/* TurboJPEG 1.2.x: TJCompressor::init() */
DRCc5a41992011-02-08 06:54:36 +0000199JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_init
DRC19c791c2018-03-08 10:55:20 -0600200 (JNIEnv *env, jobject obj)
DRCf8e00552011-02-04 11:06:36 +0000201{
DRC19c791c2018-03-08 10:55:20 -0600202 jclass cls;
203 jfieldID fid;
204 tjhandle handle;
DRCf8e00552011-02-04 11:06:36 +0000205
DRC19c791c2018-03-08 10:55:20 -0600206 if ((handle = tjInitCompress()) == NULL)
DRCbce58f42019-04-12 07:49:35 -0500207 THROW(tjGetErrorStr(), "org/libjpegturbo/turbojpeg/TJException");
DRCf8e00552011-02-04 11:06:36 +0000208
DRCbce58f42019-04-12 07:49:35 -0500209 BAILIF0(cls = (*env)->GetObjectClass(env, obj));
210 BAILIF0(fid = (*env)->GetFieldID(env, cls, "handle", "J"));
DRC19c791c2018-03-08 10:55:20 -0600211 (*env)->SetLongField(env, obj, fid, (size_t)handle);
DRCf8e00552011-02-04 11:06:36 +0000212
DRC19c791c2018-03-08 10:55:20 -0600213bailout:
214 return;
DRCf8e00552011-02-04 11:06:36 +0000215}
216
DRC5d87f6d2014-08-15 16:40:56 +0000217static jint TJCompressor_compress
DRC19c791c2018-03-08 10:55:20 -0600218 (JNIEnv *env, jobject obj, jarray src, jint srcElementSize, jint x, jint y,
219 jint width, jint pitch, jint height, jint pf, jbyteArray dst,
220 jint jpegSubsamp, jint jpegQual, jint flags)
DRCf8e00552011-02-04 11:06:36 +0000221{
DRC19c791c2018-03-08 10:55:20 -0600222 tjhandle handle = 0;
223 unsigned long jpegSize = 0;
224 jsize arraySize = 0, actualPitch;
225 unsigned char *srcBuf = NULL, *jpegBuf = NULL;
DRCf8e00552011-02-04 11:06:36 +0000226
DRCbce58f42019-04-12 07:49:35 -0500227 GET_HANDLE();
DRCf8e00552011-02-04 11:06:36 +0000228
DRC19c791c2018-03-08 10:55:20 -0600229 if (pf < 0 || pf >= org_libjpegturbo_turbojpeg_TJ_NUMPF || width < 1 ||
230 height < 1 || pitch < 0)
DRCbce58f42019-04-12 07:49:35 -0500231 THROW_ARG("Invalid argument in compress()");
DRC19c791c2018-03-08 10:55:20 -0600232 if (org_libjpegturbo_turbojpeg_TJ_NUMPF != TJ_NUMPF)
DRCbce58f42019-04-12 07:49:35 -0500233 THROW_ARG("Mismatch between Java and C API");
DRC4f1580c2011-02-25 06:11:03 +0000234
DRC19c791c2018-03-08 10:55:20 -0600235 actualPitch = (pitch == 0) ? width * tjPixelSize[pf] : pitch;
236 arraySize = (y + height - 1) * actualPitch + (x + width) * tjPixelSize[pf];
237 if ((*env)->GetArrayLength(env, src) * srcElementSize < arraySize)
DRCbce58f42019-04-12 07:49:35 -0500238 THROW_ARG("Source buffer is not large enough");
DRC19c791c2018-03-08 10:55:20 -0600239 jpegSize = tjBufSize(width, height, jpegSubsamp);
240 if ((*env)->GetArrayLength(env, dst) < (jsize)jpegSize)
DRCbce58f42019-04-12 07:49:35 -0500241 THROW_ARG("Destination buffer is not large enough");
DRC6acf52b2011-03-02 01:09:20 +0000242
DRC5ea77d82018-10-26 08:55:22 -0500243 if (ProcessSystemProperties(env) < 0) goto bailout;
244
DRCbce58f42019-04-12 07:49:35 -0500245 BAILIF0(srcBuf = (*env)->GetPrimitiveArrayCritical(env, src, 0));
246 BAILIF0(jpegBuf = (*env)->GetPrimitiveArrayCritical(env, dst, 0));
DRCf8e00552011-02-04 11:06:36 +0000247
DRC19c791c2018-03-08 10:55:20 -0600248 if (tjCompress2(handle, &srcBuf[y * actualPitch + x * tjPixelSize[pf]],
249 width, pitch, height, pf, &jpegBuf, &jpegSize, jpegSubsamp,
DRC33011752019-04-12 08:47:28 -0500250 jpegQual, flags | TJFLAG_NOREALLOC) == -1) {
251 SAFE_RELEASE(dst, jpegBuf);
252 SAFE_RELEASE(src, srcBuf);
DRCbce58f42019-04-12 07:49:35 -0500253 THROW_TJ();
DRC33011752019-04-12 08:47:28 -0500254 }
DRCfac3bea2012-09-24 02:27:55 +0000255
DRC19c791c2018-03-08 10:55:20 -0600256bailout:
DRC33011752019-04-12 08:47:28 -0500257 SAFE_RELEASE(dst, jpegBuf);
258 SAFE_RELEASE(src, srcBuf);
DRC19c791c2018-03-08 10:55:20 -0600259 return (jint)jpegSize;
DRCfac3bea2012-09-24 02:27:55 +0000260}
261
DRCa4940d12014-08-15 16:07:15 +0000262/* TurboJPEG 1.3.x: TJCompressor::compress() byte source */
DRC927a10d2014-08-15 13:18:58 +0000263JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_compress___3BIIIIII_3BIII
DRC19c791c2018-03-08 10:55:20 -0600264 (JNIEnv *env, jobject obj, jbyteArray src, jint x, jint y, jint width,
265 jint pitch, jint height, jint pf, jbyteArray dst, jint jpegSubsamp,
266 jint jpegQual, jint flags)
DRC927a10d2014-08-15 13:18:58 +0000267{
DRC19c791c2018-03-08 10:55:20 -0600268 return TJCompressor_compress(env, obj, src, 1, x, y, width, pitch, height,
269 pf, dst, jpegSubsamp, jpegQual, flags);
DRC927a10d2014-08-15 13:18:58 +0000270}
271
DRCa4940d12014-08-15 16:07:15 +0000272/* TurboJPEG 1.2.x: TJCompressor::compress() byte source */
DRCfac3bea2012-09-24 02:27:55 +0000273JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_compress___3BIIII_3BIII
DRC19c791c2018-03-08 10:55:20 -0600274 (JNIEnv *env, jobject obj, jbyteArray src, jint width, jint pitch,
275 jint height, jint pf, jbyteArray dst, jint jpegSubsamp, jint jpegQual,
276 jint flags)
DRCfac3bea2012-09-24 02:27:55 +0000277{
DRC19c791c2018-03-08 10:55:20 -0600278 return TJCompressor_compress(env, obj, src, 1, 0, 0, width, pitch, height,
279 pf, dst, jpegSubsamp, jpegQual, flags);
DRCfac3bea2012-09-24 02:27:55 +0000280}
281
DRCa4940d12014-08-15 16:07:15 +0000282/* TurboJPEG 1.3.x: TJCompressor::compress() int source */
DRCfac3bea2012-09-24 02:27:55 +0000283JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_compress___3IIIIIII_3BIII
DRC19c791c2018-03-08 10:55:20 -0600284 (JNIEnv *env, jobject obj, jintArray src, jint x, jint y, jint width,
285 jint stride, jint height, jint pf, jbyteArray dst, jint jpegSubsamp,
286 jint jpegQual, jint flags)
DRCfac3bea2012-09-24 02:27:55 +0000287{
DRC19c791c2018-03-08 10:55:20 -0600288 if (pf < 0 || pf >= org_libjpegturbo_turbojpeg_TJ_NUMPF)
DRCbce58f42019-04-12 07:49:35 -0500289 THROW_ARG("Invalid argument in compress()");
DRC19c791c2018-03-08 10:55:20 -0600290 if (tjPixelSize[pf] != sizeof(jint))
DRCbce58f42019-04-12 07:49:35 -0500291 THROW_ARG("Pixel format must be 32-bit when compressing from an integer buffer.");
DRCfac3bea2012-09-24 02:27:55 +0000292
DRC19c791c2018-03-08 10:55:20 -0600293 return TJCompressor_compress(env, obj, src, sizeof(jint), x, y, width,
294 stride * sizeof(jint), height, pf, dst,
295 jpegSubsamp, jpegQual, flags);
DRCf8e00552011-02-04 11:06:36 +0000296
DRC19c791c2018-03-08 10:55:20 -0600297bailout:
298 return 0;
DRCf8e00552011-02-04 11:06:36 +0000299}
300
DRCa4940d12014-08-15 16:07:15 +0000301/* TurboJPEG 1.2.x: TJCompressor::compress() int source */
DRC4f1580c2011-02-25 06:11:03 +0000302JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_compress___3IIIII_3BIII
DRC19c791c2018-03-08 10:55:20 -0600303 (JNIEnv *env, jobject obj, jintArray src, jint width, jint stride,
304 jint height, jint pf, jbyteArray dst, jint jpegSubsamp, jint jpegQual,
305 jint flags)
DRC84a1bcc2011-02-23 12:09:56 +0000306{
DRC19c791c2018-03-08 10:55:20 -0600307 if (pf < 0 || pf >= org_libjpegturbo_turbojpeg_TJ_NUMPF)
DRCbce58f42019-04-12 07:49:35 -0500308 THROW_ARG("Invalid argument in compress()");
DRC19c791c2018-03-08 10:55:20 -0600309 if (tjPixelSize[pf] != sizeof(jint))
DRCbce58f42019-04-12 07:49:35 -0500310 THROW_ARG("Pixel format must be 32-bit when compressing from an integer buffer.");
DRC927a10d2014-08-15 13:18:58 +0000311
DRC19c791c2018-03-08 10:55:20 -0600312 return TJCompressor_compress(env, obj, src, sizeof(jint), 0, 0, width,
313 stride * sizeof(jint), height, pf, dst,
314 jpegSubsamp, jpegQual, flags);
DRC927a10d2014-08-15 13:18:58 +0000315
DRC19c791c2018-03-08 10:55:20 -0600316bailout:
317 return 0;
DRC84a1bcc2011-02-23 12:09:56 +0000318}
319
DRCa4940d12014-08-15 16:07:15 +0000320/* TurboJPEG 1.4.x: TJCompressor::compressFromYUV() */
DRC40dd3142014-08-17 12:23:49 +0000321JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_compressFromYUV___3_3B_3II_3III_3BII
DRC19c791c2018-03-08 10:55:20 -0600322 (JNIEnv *env, jobject obj, jobjectArray srcobjs, jintArray jSrcOffsets,
323 jint width, jintArray jSrcStrides, jint height, jint subsamp,
324 jbyteArray dst, jint jpegQual, jint flags)
DRC1e672742013-10-31 05:04:51 +0000325{
DRC19c791c2018-03-08 10:55:20 -0600326 tjhandle handle = 0;
327 unsigned long jpegSize = 0;
328 jbyteArray jSrcPlanes[3] = { NULL, NULL, NULL };
329 const unsigned char *srcPlanes[3];
330 unsigned char *jpegBuf = NULL;
331 int *srcOffsets = NULL, *srcStrides = NULL;
332 int nc = (subsamp == org_libjpegturbo_turbojpeg_TJ_SAMP_GRAY ? 1 : 3), i;
DRC1e672742013-10-31 05:04:51 +0000333
DRCbce58f42019-04-12 07:49:35 -0500334 GET_HANDLE();
DRC1e672742013-10-31 05:04:51 +0000335
DRC19c791c2018-03-08 10:55:20 -0600336 if (subsamp < 0 || subsamp >= org_libjpegturbo_turbojpeg_TJ_NUMSAMP)
DRCbce58f42019-04-12 07:49:35 -0500337 THROW_ARG("Invalid argument in compressFromYUV()");
DRC19c791c2018-03-08 10:55:20 -0600338 if (org_libjpegturbo_turbojpeg_TJ_NUMSAMP != TJ_NUMSAMP)
DRCbce58f42019-04-12 07:49:35 -0500339 THROW_ARG("Mismatch between Java and C API");
DRC40dd3142014-08-17 12:23:49 +0000340
DRC19c791c2018-03-08 10:55:20 -0600341 if ((*env)->GetArrayLength(env, srcobjs) < nc)
DRCbce58f42019-04-12 07:49:35 -0500342 THROW_ARG("Planes array is too small for the subsampling type");
DRC19c791c2018-03-08 10:55:20 -0600343 if ((*env)->GetArrayLength(env, jSrcOffsets) < nc)
DRCbce58f42019-04-12 07:49:35 -0500344 THROW_ARG("Offsets array is too small for the subsampling type");
DRC19c791c2018-03-08 10:55:20 -0600345 if ((*env)->GetArrayLength(env, jSrcStrides) < nc)
DRCbce58f42019-04-12 07:49:35 -0500346 THROW_ARG("Strides array is too small for the subsampling type");
DRC40dd3142014-08-17 12:23:49 +0000347
DRC19c791c2018-03-08 10:55:20 -0600348 jpegSize = tjBufSize(width, height, subsamp);
349 if ((*env)->GetArrayLength(env, dst) < (jsize)jpegSize)
DRCbce58f42019-04-12 07:49:35 -0500350 THROW_ARG("Destination buffer is not large enough");
DRC1e672742013-10-31 05:04:51 +0000351
DRC5ea77d82018-10-26 08:55:22 -0500352 if (ProcessSystemProperties(env) < 0) goto bailout;
353
DRC33011752019-04-12 08:47:28 -0500354#define RELEASE_ARRAYS_COMPRESSFROMYUV() { \
355 SAFE_RELEASE(dst, jpegBuf); \
356 for (i = 0; i < nc; i++) \
357 SAFE_RELEASE(jSrcPlanes[i], srcPlanes[i]); \
358 SAFE_RELEASE(jSrcStrides, srcStrides); \
359 SAFE_RELEASE(jSrcOffsets, srcOffsets); \
360}
361
DRCbce58f42019-04-12 07:49:35 -0500362 BAILIF0(srcOffsets = (*env)->GetPrimitiveArrayCritical(env, jSrcOffsets, 0));
363 BAILIF0(srcStrides = (*env)->GetPrimitiveArrayCritical(env, jSrcStrides, 0));
DRC19c791c2018-03-08 10:55:20 -0600364 for (i = 0; i < nc; i++) {
365 int planeSize = tjPlaneSizeYUV(i, width, srcStrides[i], height, subsamp);
366 int pw = tjPlaneWidth(i, width, subsamp);
DRC40dd3142014-08-17 12:23:49 +0000367
DRC33011752019-04-12 08:47:28 -0500368 if (planeSize < 0 || pw < 0) {
369 RELEASE_ARRAYS_COMPRESSFROMYUV();
DRCbce58f42019-04-12 07:49:35 -0500370 THROW_ARG(tjGetErrorStr());
DRC33011752019-04-12 08:47:28 -0500371 }
DRC40dd3142014-08-17 12:23:49 +0000372
DRC33011752019-04-12 08:47:28 -0500373 if (srcOffsets[i] < 0) {
374 RELEASE_ARRAYS_COMPRESSFROMYUV();
DRCbce58f42019-04-12 07:49:35 -0500375 THROW_ARG("Invalid argument in compressFromYUV()");
DRC33011752019-04-12 08:47:28 -0500376 }
377 if (srcStrides[i] < 0 && srcOffsets[i] - planeSize + pw < 0) {
378 RELEASE_ARRAYS_COMPRESSFROMYUV();
DRCbce58f42019-04-12 07:49:35 -0500379 THROW_ARG("Negative plane stride would cause memory to be accessed below plane boundary");
DRC33011752019-04-12 08:47:28 -0500380 }
DRC40dd3142014-08-17 12:23:49 +0000381
DRCbce58f42019-04-12 07:49:35 -0500382 BAILIF0(jSrcPlanes[i] = (*env)->GetObjectArrayElement(env, srcobjs, i));
DRC33011752019-04-12 08:47:28 -0500383 if ((*env)->GetArrayLength(env, jSrcPlanes[i]) <
384 srcOffsets[i] + planeSize) {
385 RELEASE_ARRAYS_COMPRESSFROMYUV();
DRCbce58f42019-04-12 07:49:35 -0500386 THROW_ARG("Source plane is not large enough");
DRC33011752019-04-12 08:47:28 -0500387 }
DRC40dd3142014-08-17 12:23:49 +0000388
DRCbce58f42019-04-12 07:49:35 -0500389 BAILIF0(srcPlanes[i] =
DRC19c791c2018-03-08 10:55:20 -0600390 (*env)->GetPrimitiveArrayCritical(env, jSrcPlanes[i], 0));
391 srcPlanes[i] = &srcPlanes[i][srcOffsets[i]];
392 }
DRCbce58f42019-04-12 07:49:35 -0500393 BAILIF0(jpegBuf = (*env)->GetPrimitiveArrayCritical(env, dst, 0));
DRC1e672742013-10-31 05:04:51 +0000394
DRC19c791c2018-03-08 10:55:20 -0600395 if (tjCompressFromYUVPlanes(handle, srcPlanes, width, srcStrides, height,
396 subsamp, &jpegBuf, &jpegSize, jpegQual,
DRC33011752019-04-12 08:47:28 -0500397 flags | TJFLAG_NOREALLOC) == -1) {
398 RELEASE_ARRAYS_COMPRESSFROMYUV();
DRCbce58f42019-04-12 07:49:35 -0500399 THROW_TJ();
DRC33011752019-04-12 08:47:28 -0500400 }
DRC1e672742013-10-31 05:04:51 +0000401
DRC19c791c2018-03-08 10:55:20 -0600402bailout:
DRC33011752019-04-12 08:47:28 -0500403 RELEASE_ARRAYS_COMPRESSFROMYUV();
DRC19c791c2018-03-08 10:55:20 -0600404 return (jint)jpegSize;
DRC1e672742013-10-31 05:04:51 +0000405}
406
DRC5d87f6d2014-08-15 16:40:56 +0000407static void TJCompressor_encodeYUV
DRC19c791c2018-03-08 10:55:20 -0600408 (JNIEnv *env, jobject obj, jarray src, jint srcElementSize, jint x, jint y,
409 jint width, jint pitch, jint height, jint pf, jobjectArray dstobjs,
410 jintArray jDstOffsets, jintArray jDstStrides, jint subsamp, jint flags)
DRC4f1580c2011-02-25 06:11:03 +0000411{
DRC19c791c2018-03-08 10:55:20 -0600412 tjhandle handle = 0;
413 jsize arraySize = 0, actualPitch;
414 jbyteArray jDstPlanes[3] = { NULL, NULL, NULL };
415 unsigned char *srcBuf = NULL, *dstPlanes[3];
416 int *dstOffsets = NULL, *dstStrides = NULL;
417 int nc = (subsamp == org_libjpegturbo_turbojpeg_TJ_SAMP_GRAY ? 1 : 3), i;
DRC40dd3142014-08-17 12:23:49 +0000418
DRCbce58f42019-04-12 07:49:35 -0500419 GET_HANDLE();
DRC40dd3142014-08-17 12:23:49 +0000420
DRC19c791c2018-03-08 10:55:20 -0600421 if (pf < 0 || pf >= org_libjpegturbo_turbojpeg_TJ_NUMPF || width < 1 ||
422 height < 1 || pitch < 0 || subsamp < 0 ||
423 subsamp >= org_libjpegturbo_turbojpeg_TJ_NUMSAMP)
DRCbce58f42019-04-12 07:49:35 -0500424 THROW_ARG("Invalid argument in encodeYUV()");
DRC19c791c2018-03-08 10:55:20 -0600425 if (org_libjpegturbo_turbojpeg_TJ_NUMPF != TJ_NUMPF ||
426 org_libjpegturbo_turbojpeg_TJ_NUMSAMP != TJ_NUMSAMP)
DRCbce58f42019-04-12 07:49:35 -0500427 THROW_ARG("Mismatch between Java and C API");
DRC40dd3142014-08-17 12:23:49 +0000428
DRC19c791c2018-03-08 10:55:20 -0600429 if ((*env)->GetArrayLength(env, dstobjs) < nc)
DRCbce58f42019-04-12 07:49:35 -0500430 THROW_ARG("Planes array is too small for the subsampling type");
DRC19c791c2018-03-08 10:55:20 -0600431 if ((*env)->GetArrayLength(env, jDstOffsets) < nc)
DRCbce58f42019-04-12 07:49:35 -0500432 THROW_ARG("Offsets array is too small for the subsampling type");
DRC19c791c2018-03-08 10:55:20 -0600433 if ((*env)->GetArrayLength(env, jDstStrides) < nc)
DRCbce58f42019-04-12 07:49:35 -0500434 THROW_ARG("Strides array is too small for the subsampling type");
DRC40dd3142014-08-17 12:23:49 +0000435
DRC19c791c2018-03-08 10:55:20 -0600436 actualPitch = (pitch == 0) ? width * tjPixelSize[pf] : pitch;
437 arraySize = (y + height - 1) * actualPitch + (x + width) * tjPixelSize[pf];
438 if ((*env)->GetArrayLength(env, src) * srcElementSize < arraySize)
DRCbce58f42019-04-12 07:49:35 -0500439 THROW_ARG("Source buffer is not large enough");
DRC40dd3142014-08-17 12:23:49 +0000440
DRC33011752019-04-12 08:47:28 -0500441#define RELEASE_ARRAYS_ENCODEYUV() { \
442 SAFE_RELEASE(src, srcBuf); \
443 for (i = 0; i < nc; i++) \
444 SAFE_RELEASE(jDstPlanes[i], dstPlanes[i]); \
445 SAFE_RELEASE(jDstStrides, dstStrides); \
446 SAFE_RELEASE(jDstOffsets, dstOffsets); \
447}
448
DRCbce58f42019-04-12 07:49:35 -0500449 BAILIF0(dstOffsets = (*env)->GetPrimitiveArrayCritical(env, jDstOffsets, 0));
450 BAILIF0(dstStrides = (*env)->GetPrimitiveArrayCritical(env, jDstStrides, 0));
DRC19c791c2018-03-08 10:55:20 -0600451 for (i = 0; i < nc; i++) {
452 int planeSize = tjPlaneSizeYUV(i, width, dstStrides[i], height, subsamp);
453 int pw = tjPlaneWidth(i, width, subsamp);
DRC40dd3142014-08-17 12:23:49 +0000454
DRC33011752019-04-12 08:47:28 -0500455 if (planeSize < 0 || pw < 0) {
456 RELEASE_ARRAYS_ENCODEYUV();
DRCbce58f42019-04-12 07:49:35 -0500457 THROW_ARG(tjGetErrorStr());
DRC33011752019-04-12 08:47:28 -0500458 }
DRC40dd3142014-08-17 12:23:49 +0000459
DRC33011752019-04-12 08:47:28 -0500460 if (dstOffsets[i] < 0) {
461 RELEASE_ARRAYS_ENCODEYUV();
DRCbce58f42019-04-12 07:49:35 -0500462 THROW_ARG("Invalid argument in encodeYUV()");
DRC33011752019-04-12 08:47:28 -0500463 }
464 if (dstStrides[i] < 0 && dstOffsets[i] - planeSize + pw < 0) {
465 RELEASE_ARRAYS_ENCODEYUV();
DRCbce58f42019-04-12 07:49:35 -0500466 THROW_ARG("Negative plane stride would cause memory to be accessed below plane boundary");
DRC33011752019-04-12 08:47:28 -0500467 }
DRC40dd3142014-08-17 12:23:49 +0000468
DRCbce58f42019-04-12 07:49:35 -0500469 BAILIF0(jDstPlanes[i] = (*env)->GetObjectArrayElement(env, dstobjs, i));
DRC33011752019-04-12 08:47:28 -0500470 if ((*env)->GetArrayLength(env, jDstPlanes[i]) <
471 dstOffsets[i] + planeSize) {
472 RELEASE_ARRAYS_ENCODEYUV();
DRCbce58f42019-04-12 07:49:35 -0500473 THROW_ARG("Destination plane is not large enough");
DRC33011752019-04-12 08:47:28 -0500474 }
DRC40dd3142014-08-17 12:23:49 +0000475
DRCbce58f42019-04-12 07:49:35 -0500476 BAILIF0(dstPlanes[i] =
DRC19c791c2018-03-08 10:55:20 -0600477 (*env)->GetPrimitiveArrayCritical(env, jDstPlanes[i], 0));
478 dstPlanes[i] = &dstPlanes[i][dstOffsets[i]];
479 }
DRCbce58f42019-04-12 07:49:35 -0500480 BAILIF0(srcBuf = (*env)->GetPrimitiveArrayCritical(env, src, 0));
DRC40dd3142014-08-17 12:23:49 +0000481
DRC19c791c2018-03-08 10:55:20 -0600482 if (tjEncodeYUVPlanes(handle, &srcBuf[y * actualPitch + x * tjPixelSize[pf]],
483 width, pitch, height, pf, dstPlanes, dstStrides,
DRC33011752019-04-12 08:47:28 -0500484 subsamp, flags) == -1) {
485 RELEASE_ARRAYS_ENCODEYUV();
DRCbce58f42019-04-12 07:49:35 -0500486 THROW_TJ();
DRC33011752019-04-12 08:47:28 -0500487 }
DRC40dd3142014-08-17 12:23:49 +0000488
DRC19c791c2018-03-08 10:55:20 -0600489bailout:
DRC33011752019-04-12 08:47:28 -0500490 RELEASE_ARRAYS_ENCODEYUV();
DRC40dd3142014-08-17 12:23:49 +0000491}
492
493/* TurboJPEG 1.4.x: TJCompressor::encodeYUV() byte source */
494JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_encodeYUV___3BIIIIII_3_3B_3I_3III
DRC19c791c2018-03-08 10:55:20 -0600495 (JNIEnv *env, jobject obj, jbyteArray src, jint x, jint y, jint width,
496 jint pitch, jint height, jint pf, jobjectArray dstobjs,
497 jintArray jDstOffsets, jintArray jDstStrides, jint subsamp, jint flags)
DRC40dd3142014-08-17 12:23:49 +0000498{
DRC19c791c2018-03-08 10:55:20 -0600499 TJCompressor_encodeYUV(env, obj, src, 1, x, y, width, pitch, height, pf,
500 dstobjs, jDstOffsets, jDstStrides, subsamp, flags);
DRC40dd3142014-08-17 12:23:49 +0000501}
502
503/* TurboJPEG 1.4.x: TJCompressor::encodeYUV() int source */
504JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_encodeYUV___3IIIIIII_3_3B_3I_3III
DRC19c791c2018-03-08 10:55:20 -0600505 (JNIEnv *env, jobject obj, jintArray src, jint x, jint y, jint width,
506 jint stride, jint height, jint pf, jobjectArray dstobjs,
507 jintArray jDstOffsets, jintArray jDstStrides, jint subsamp, jint flags)
DRC40dd3142014-08-17 12:23:49 +0000508{
DRC19c791c2018-03-08 10:55:20 -0600509 if (pf < 0 || pf >= org_libjpegturbo_turbojpeg_TJ_NUMPF)
DRCbce58f42019-04-12 07:49:35 -0500510 THROW_ARG("Invalid argument in encodeYUV()");
DRC19c791c2018-03-08 10:55:20 -0600511 if (tjPixelSize[pf] != sizeof(jint))
DRCbce58f42019-04-12 07:49:35 -0500512 THROW_ARG("Pixel format must be 32-bit when encoding from an integer buffer.");
DRC40dd3142014-08-17 12:23:49 +0000513
DRC19c791c2018-03-08 10:55:20 -0600514 TJCompressor_encodeYUV(env, obj, src, sizeof(jint), x, y, width,
515 stride * sizeof(jint), height, pf, dstobjs,
516 jDstOffsets, jDstStrides, subsamp, flags);
DRC40dd3142014-08-17 12:23:49 +0000517
DRC19c791c2018-03-08 10:55:20 -0600518bailout:
519 return;
DRC40dd3142014-08-17 12:23:49 +0000520}
521
DRC6399d0a2019-04-23 14:10:04 -0500522static void JNICALL TJCompressor_encodeYUV_12
DRC19c791c2018-03-08 10:55:20 -0600523 (JNIEnv *env, jobject obj, jarray src, jint srcElementSize, jint width,
524 jint pitch, jint height, jint pf, jbyteArray dst, jint subsamp, jint flags)
DRC40dd3142014-08-17 12:23:49 +0000525{
DRC19c791c2018-03-08 10:55:20 -0600526 tjhandle handle = 0;
527 jsize arraySize = 0;
528 unsigned char *srcBuf = NULL, *dstBuf = NULL;
DRC4f1580c2011-02-25 06:11:03 +0000529
DRCbce58f42019-04-12 07:49:35 -0500530 GET_HANDLE();
DRC4f1580c2011-02-25 06:11:03 +0000531
DRC19c791c2018-03-08 10:55:20 -0600532 if (pf < 0 || pf >= org_libjpegturbo_turbojpeg_TJ_NUMPF || width < 1 ||
533 height < 1 || pitch < 0)
DRCbce58f42019-04-12 07:49:35 -0500534 THROW_ARG("Invalid argument in encodeYUV()");
DRC19c791c2018-03-08 10:55:20 -0600535 if (org_libjpegturbo_turbojpeg_TJ_NUMPF != TJ_NUMPF)
DRCbce58f42019-04-12 07:49:35 -0500536 THROW_ARG("Mismatch between Java and C API");
DRC4f1580c2011-02-25 06:11:03 +0000537
DRC19c791c2018-03-08 10:55:20 -0600538 arraySize = (pitch == 0) ? width * tjPixelSize[pf] * height : pitch * height;
539 if ((*env)->GetArrayLength(env, src) * srcElementSize < arraySize)
DRCbce58f42019-04-12 07:49:35 -0500540 THROW_ARG("Source buffer is not large enough");
DRC19c791c2018-03-08 10:55:20 -0600541 if ((*env)->GetArrayLength(env, dst) <
542 (jsize)tjBufSizeYUV(width, height, subsamp))
DRCbce58f42019-04-12 07:49:35 -0500543 THROW_ARG("Destination buffer is not large enough");
DRC6acf52b2011-03-02 01:09:20 +0000544
DRCbce58f42019-04-12 07:49:35 -0500545 BAILIF0(srcBuf = (*env)->GetPrimitiveArrayCritical(env, src, 0));
546 BAILIF0(dstBuf = (*env)->GetPrimitiveArrayCritical(env, dst, 0));
DRC4f1580c2011-02-25 06:11:03 +0000547
DRC19c791c2018-03-08 10:55:20 -0600548 if (tjEncodeYUV2(handle, srcBuf, width, pitch, height, pf, dstBuf, subsamp,
DRC33011752019-04-12 08:47:28 -0500549 flags) == -1) {
550 SAFE_RELEASE(dst, dstBuf);
551 SAFE_RELEASE(src, srcBuf);
DRCbce58f42019-04-12 07:49:35 -0500552 THROW_TJ();
DRC33011752019-04-12 08:47:28 -0500553 }
DRC4f1580c2011-02-25 06:11:03 +0000554
DRC19c791c2018-03-08 10:55:20 -0600555bailout:
DRC33011752019-04-12 08:47:28 -0500556 SAFE_RELEASE(dst, dstBuf);
557 SAFE_RELEASE(src, srcBuf);
DRC4f1580c2011-02-25 06:11:03 +0000558}
559
DRCa4940d12014-08-15 16:07:15 +0000560/* TurboJPEG 1.2.x: TJCompressor::encodeYUV() byte source */
DRCfef98522013-04-28 01:32:52 +0000561JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_encodeYUV___3BIIII_3BII
DRC19c791c2018-03-08 10:55:20 -0600562 (JNIEnv *env, jobject obj, jbyteArray src, jint width, jint pitch,
563 jint height, jint pf, jbyteArray dst, jint subsamp, jint flags)
DRC4f1580c2011-02-25 06:11:03 +0000564{
DRC19c791c2018-03-08 10:55:20 -0600565 TJCompressor_encodeYUV_12(env, obj, src, 1, width, pitch, height, pf, dst,
566 subsamp, flags);
DRC4f1580c2011-02-25 06:11:03 +0000567}
568
DRCa4940d12014-08-15 16:07:15 +0000569/* TurboJPEG 1.2.x: TJCompressor::encodeYUV() int source */
DRCfef98522013-04-28 01:32:52 +0000570JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_encodeYUV___3IIIII_3BII
DRC19c791c2018-03-08 10:55:20 -0600571 (JNIEnv *env, jobject obj, jintArray src, jint width, jint stride,
572 jint height, jint pf, jbyteArray dst, jint subsamp, jint flags)
DRCfef98522013-04-28 01:32:52 +0000573{
DRC19c791c2018-03-08 10:55:20 -0600574 if (pf < 0 || pf >= org_libjpegturbo_turbojpeg_TJ_NUMPF)
DRCbce58f42019-04-12 07:49:35 -0500575 THROW_ARG("Invalid argument in encodeYUV()");
DRC19c791c2018-03-08 10:55:20 -0600576 if (tjPixelSize[pf] != sizeof(jint))
DRCbce58f42019-04-12 07:49:35 -0500577 THROW_ARG("Pixel format must be 32-bit when encoding from an integer buffer.");
DRC927a10d2014-08-15 13:18:58 +0000578
DRC19c791c2018-03-08 10:55:20 -0600579 TJCompressor_encodeYUV_12(env, obj, src, sizeof(jint), width,
580 stride * sizeof(jint), height, pf, dst, subsamp,
581 flags);
DRC927a10d2014-08-15 13:18:58 +0000582
DRC19c791c2018-03-08 10:55:20 -0600583bailout:
584 return;
DRCfef98522013-04-28 01:32:52 +0000585}
586
DRCa4940d12014-08-15 16:07:15 +0000587/* TurboJPEG 1.2.x: TJCompressor::destroy() */
DRCc5a41992011-02-08 06:54:36 +0000588JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_destroy
DRC19c791c2018-03-08 10:55:20 -0600589 (JNIEnv *env, jobject obj)
DRCf8e00552011-02-04 11:06:36 +0000590{
DRC19c791c2018-03-08 10:55:20 -0600591 tjhandle handle = 0;
DRCf8e00552011-02-04 11:06:36 +0000592
DRCbce58f42019-04-12 07:49:35 -0500593 GET_HANDLE();
DRCf8e00552011-02-04 11:06:36 +0000594
DRCbce58f42019-04-12 07:49:35 -0500595 if (tjDestroy(handle) == -1) THROW_TJ();
DRC19c791c2018-03-08 10:55:20 -0600596 (*env)->SetLongField(env, obj, _fid, 0);
DRCf8e00552011-02-04 11:06:36 +0000597
DRC19c791c2018-03-08 10:55:20 -0600598bailout:
599 return;
DRCf8e00552011-02-04 11:06:36 +0000600}
601
DRCa4940d12014-08-15 16:07:15 +0000602/* TurboJPEG 1.2.x: TJDecompressor::init() */
DRCc5a41992011-02-08 06:54:36 +0000603JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_init
DRC19c791c2018-03-08 10:55:20 -0600604 (JNIEnv *env, jobject obj)
DRCf8e00552011-02-04 11:06:36 +0000605{
DRC19c791c2018-03-08 10:55:20 -0600606 jclass cls;
607 jfieldID fid;
608 tjhandle handle;
DRCf8e00552011-02-04 11:06:36 +0000609
DRC19c791c2018-03-08 10:55:20 -0600610 if ((handle = tjInitDecompress()) == NULL)
DRCbce58f42019-04-12 07:49:35 -0500611 THROW(tjGetErrorStr(), "org/libjpegturbo/turbojpeg/TJException");
DRCf8e00552011-02-04 11:06:36 +0000612
DRCbce58f42019-04-12 07:49:35 -0500613 BAILIF0(cls = (*env)->GetObjectClass(env, obj));
614 BAILIF0(fid = (*env)->GetFieldID(env, cls, "handle", "J"));
DRC19c791c2018-03-08 10:55:20 -0600615 (*env)->SetLongField(env, obj, fid, (size_t)handle);
DRCf8e00552011-02-04 11:06:36 +0000616
DRC19c791c2018-03-08 10:55:20 -0600617bailout:
618 return;
DRCf8e00552011-02-04 11:06:36 +0000619}
620
DRCa4940d12014-08-15 16:07:15 +0000621/* TurboJPEG 1.2.x: TJDecompressor::getScalingFactors() */
DRC109a5782011-03-01 09:53:07 +0000622JNIEXPORT jobjectArray JNICALL Java_org_libjpegturbo_turbojpeg_TJ_getScalingFactors
DRC19c791c2018-03-08 10:55:20 -0600623 (JNIEnv *env, jclass cls)
DRC36336fc2011-02-22 10:27:31 +0000624{
DRC19c791c2018-03-08 10:55:20 -0600625 jclass sfcls = NULL;
626 jfieldID fid = 0;
627 tjscalingfactor *sf = NULL;
628 int n = 0, i;
629 jobject sfobj = NULL;
630 jobjectArray sfjava = NULL;
DRC109a5782011-03-01 09:53:07 +0000631
DRC19c791c2018-03-08 10:55:20 -0600632 if ((sf = tjGetScalingFactors(&n)) == NULL || n == 0)
DRCbce58f42019-04-12 07:49:35 -0500633 THROW_ARG(tjGetErrorStr());
DRC36336fc2011-02-22 10:27:31 +0000634
DRCbce58f42019-04-12 07:49:35 -0500635 BAILIF0(sfcls = (*env)->FindClass(env,
DRC19c791c2018-03-08 10:55:20 -0600636 "org/libjpegturbo/turbojpeg/TJScalingFactor"));
DRCbce58f42019-04-12 07:49:35 -0500637 BAILIF0(sfjava = (jobjectArray)(*env)->NewObjectArray(env, n, sfcls, 0));
DRC36336fc2011-02-22 10:27:31 +0000638
DRC19c791c2018-03-08 10:55:20 -0600639 for (i = 0; i < n; i++) {
DRCbce58f42019-04-12 07:49:35 -0500640 BAILIF0(sfobj = (*env)->AllocObject(env, sfcls));
641 BAILIF0(fid = (*env)->GetFieldID(env, sfcls, "num", "I"));
DRC19c791c2018-03-08 10:55:20 -0600642 (*env)->SetIntField(env, sfobj, fid, sf[i].num);
DRCbce58f42019-04-12 07:49:35 -0500643 BAILIF0(fid = (*env)->GetFieldID(env, sfcls, "denom", "I"));
DRC19c791c2018-03-08 10:55:20 -0600644 (*env)->SetIntField(env, sfobj, fid, sf[i].denom);
645 (*env)->SetObjectArrayElement(env, sfjava, i, sfobj);
646 }
DRC36336fc2011-02-22 10:27:31 +0000647
DRC19c791c2018-03-08 10:55:20 -0600648bailout:
649 return sfjava;
DRC36336fc2011-02-22 10:27:31 +0000650}
651
DRCa4940d12014-08-15 16:07:15 +0000652/* TurboJPEG 1.2.x: TJDecompressor::decompressHeader() */
DRC3bad53f2011-02-23 02:20:49 +0000653JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompressHeader
DRC19c791c2018-03-08 10:55:20 -0600654 (JNIEnv *env, jobject obj, jbyteArray src, jint jpegSize)
DRCf8e00552011-02-04 11:06:36 +0000655{
DRC19c791c2018-03-08 10:55:20 -0600656 tjhandle handle = 0;
657 unsigned char *jpegBuf = NULL;
658 int width = 0, height = 0, jpegSubsamp = -1, jpegColorspace = -1;
DRCf8e00552011-02-04 11:06:36 +0000659
DRCbce58f42019-04-12 07:49:35 -0500660 GET_HANDLE();
DRCf8e00552011-02-04 11:06:36 +0000661
DRC19c791c2018-03-08 10:55:20 -0600662 if ((*env)->GetArrayLength(env, src) < jpegSize)
DRCbce58f42019-04-12 07:49:35 -0500663 THROW_ARG("Source buffer is not large enough");
DRC6acf52b2011-03-02 01:09:20 +0000664
DRCbce58f42019-04-12 07:49:35 -0500665 BAILIF0(jpegBuf = (*env)->GetPrimitiveArrayCritical(env, src, 0));
DRCf8e00552011-02-04 11:06:36 +0000666
DRC19c791c2018-03-08 10:55:20 -0600667 if (tjDecompressHeader3(handle, jpegBuf, (unsigned long)jpegSize, &width,
DRC33011752019-04-12 08:47:28 -0500668 &height, &jpegSubsamp, &jpegColorspace) == -1) {
669 SAFE_RELEASE(src, jpegBuf);
DRCbce58f42019-04-12 07:49:35 -0500670 THROW_TJ();
DRC33011752019-04-12 08:47:28 -0500671 }
DRC8951cf02014-08-14 16:54:04 +0000672
DRC33011752019-04-12 08:47:28 -0500673 SAFE_RELEASE(src, jpegBuf);
DRCf8e00552011-02-04 11:06:36 +0000674
DRCbce58f42019-04-12 07:49:35 -0500675 BAILIF0(_fid = (*env)->GetFieldID(env, _cls, "jpegSubsamp", "I"));
DRC19c791c2018-03-08 10:55:20 -0600676 (*env)->SetIntField(env, obj, _fid, jpegSubsamp);
677 if ((_fid = (*env)->GetFieldID(env, _cls, "jpegColorspace", "I")) == 0)
678 (*env)->ExceptionClear(env);
679 else
680 (*env)->SetIntField(env, obj, _fid, jpegColorspace);
DRCbce58f42019-04-12 07:49:35 -0500681 BAILIF0(_fid = (*env)->GetFieldID(env, _cls, "jpegWidth", "I"));
DRC19c791c2018-03-08 10:55:20 -0600682 (*env)->SetIntField(env, obj, _fid, width);
DRCbce58f42019-04-12 07:49:35 -0500683 BAILIF0(_fid = (*env)->GetFieldID(env, _cls, "jpegHeight", "I"));
DRC19c791c2018-03-08 10:55:20 -0600684 (*env)->SetIntField(env, obj, _fid, height);
DRCf8e00552011-02-04 11:06:36 +0000685
DRC19c791c2018-03-08 10:55:20 -0600686bailout:
DRC33011752019-04-12 08:47:28 -0500687 SAFE_RELEASE(src, jpegBuf);
DRCf8e00552011-02-04 11:06:36 +0000688}
689
DRC5d87f6d2014-08-15 16:40:56 +0000690static void TJDecompressor_decompress
DRC19c791c2018-03-08 10:55:20 -0600691 (JNIEnv *env, jobject obj, jbyteArray src, jint jpegSize, jarray dst,
692 jint dstElementSize, jint x, jint y, jint width, jint pitch, jint height,
693 jint pf, jint flags)
DRCf8e00552011-02-04 11:06:36 +0000694{
DRC19c791c2018-03-08 10:55:20 -0600695 tjhandle handle = 0;
696 jsize arraySize = 0, actualPitch;
697 unsigned char *jpegBuf = NULL, *dstBuf = NULL;
DRCf8e00552011-02-04 11:06:36 +0000698
DRCbce58f42019-04-12 07:49:35 -0500699 GET_HANDLE();
DRCf8e00552011-02-04 11:06:36 +0000700
DRC19c791c2018-03-08 10:55:20 -0600701 if (pf < 0 || pf >= org_libjpegturbo_turbojpeg_TJ_NUMPF)
DRCbce58f42019-04-12 07:49:35 -0500702 THROW_ARG("Invalid argument in decompress()");
DRC19c791c2018-03-08 10:55:20 -0600703 if (org_libjpegturbo_turbojpeg_TJ_NUMPF != TJ_NUMPF)
DRCbce58f42019-04-12 07:49:35 -0500704 THROW_ARG("Mismatch between Java and C API");
DRC4f1580c2011-02-25 06:11:03 +0000705
DRC19c791c2018-03-08 10:55:20 -0600706 if ((*env)->GetArrayLength(env, src) < jpegSize)
DRCbce58f42019-04-12 07:49:35 -0500707 THROW_ARG("Source buffer is not large enough");
DRC19c791c2018-03-08 10:55:20 -0600708 actualPitch = (pitch == 0) ? width * tjPixelSize[pf] : pitch;
709 arraySize = (y + height - 1) * actualPitch + (x + width) * tjPixelSize[pf];
710 if ((*env)->GetArrayLength(env, dst) * dstElementSize < arraySize)
DRCbce58f42019-04-12 07:49:35 -0500711 THROW_ARG("Destination buffer is not large enough");
DRC6acf52b2011-03-02 01:09:20 +0000712
DRCbce58f42019-04-12 07:49:35 -0500713 BAILIF0(jpegBuf = (*env)->GetPrimitiveArrayCritical(env, src, 0));
714 BAILIF0(dstBuf = (*env)->GetPrimitiveArrayCritical(env, dst, 0));
DRCf8e00552011-02-04 11:06:36 +0000715
DRC19c791c2018-03-08 10:55:20 -0600716 if (tjDecompress2(handle, jpegBuf, (unsigned long)jpegSize,
717 &dstBuf[y * actualPitch + x * tjPixelSize[pf]], width,
DRC33011752019-04-12 08:47:28 -0500718 pitch, height, pf, flags) == -1) {
719 SAFE_RELEASE(dst, dstBuf);
720 SAFE_RELEASE(src, jpegBuf);
DRCbce58f42019-04-12 07:49:35 -0500721 THROW_TJ();
DRC33011752019-04-12 08:47:28 -0500722 }
DRCf659f432012-06-06 08:41:06 +0000723
DRC19c791c2018-03-08 10:55:20 -0600724bailout:
DRC33011752019-04-12 08:47:28 -0500725 SAFE_RELEASE(dst, dstBuf);
726 SAFE_RELEASE(src, jpegBuf);
DRCf659f432012-06-06 08:41:06 +0000727}
728
DRCa4940d12014-08-15 16:07:15 +0000729/* TurboJPEG 1.3.x: TJDecompressor::decompress() byte destination */
DRC927a10d2014-08-15 13:18:58 +0000730JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompress___3BI_3BIIIIIII
DRC19c791c2018-03-08 10:55:20 -0600731 (JNIEnv *env, jobject obj, jbyteArray src, jint jpegSize, jbyteArray dst,
732 jint x, jint y, jint width, jint pitch, jint height, jint pf, jint flags)
DRC927a10d2014-08-15 13:18:58 +0000733{
DRC19c791c2018-03-08 10:55:20 -0600734 TJDecompressor_decompress(env, obj, src, jpegSize, dst, 1, x, y, width,
735 pitch, height, pf, flags);
DRC927a10d2014-08-15 13:18:58 +0000736}
737
DRCa4940d12014-08-15 16:07:15 +0000738/* TurboJPEG 1.2.x: TJDecompressor::decompress() byte destination */
DRCf659f432012-06-06 08:41:06 +0000739JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompress___3BI_3BIIIII
DRC19c791c2018-03-08 10:55:20 -0600740 (JNIEnv *env, jobject obj, jbyteArray src, jint jpegSize, jbyteArray dst,
741 jint width, jint pitch, jint height, jint pf, jint flags)
DRCf659f432012-06-06 08:41:06 +0000742{
DRC19c791c2018-03-08 10:55:20 -0600743 TJDecompressor_decompress(env, obj, src, jpegSize, dst, 1, 0, 0, width,
744 pitch, height, pf, flags);
DRCf659f432012-06-06 08:41:06 +0000745}
746
DRCa4940d12014-08-15 16:07:15 +0000747/* TurboJPEG 1.3.x: TJDecompressor::decompress() int destination */
DRCf659f432012-06-06 08:41:06 +0000748JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompress___3BI_3IIIIIIII
DRC19c791c2018-03-08 10:55:20 -0600749 (JNIEnv *env, jobject obj, jbyteArray src, jint jpegSize, jintArray dst,
750 jint x, jint y, jint width, jint stride, jint height, jint pf, jint flags)
DRCf659f432012-06-06 08:41:06 +0000751{
DRC19c791c2018-03-08 10:55:20 -0600752 if (pf < 0 || pf >= org_libjpegturbo_turbojpeg_TJ_NUMPF)
DRCbce58f42019-04-12 07:49:35 -0500753 THROW_ARG("Invalid argument in decompress()");
DRC19c791c2018-03-08 10:55:20 -0600754 if (tjPixelSize[pf] != sizeof(jint))
DRCbce58f42019-04-12 07:49:35 -0500755 THROW_ARG("Pixel format must be 32-bit when decompressing to an integer buffer.");
DRCf659f432012-06-06 08:41:06 +0000756
DRC19c791c2018-03-08 10:55:20 -0600757 TJDecompressor_decompress(env, obj, src, jpegSize, dst, sizeof(jint), x, y,
758 width, stride * sizeof(jint), height, pf, flags);
DRCf8e00552011-02-04 11:06:36 +0000759
DRC19c791c2018-03-08 10:55:20 -0600760bailout:
761 return;
DRCf8e00552011-02-04 11:06:36 +0000762}
763
DRCa4940d12014-08-15 16:07:15 +0000764/* TurboJPEG 1.2.x: TJDecompressor::decompress() int destination */
DRC4f1580c2011-02-25 06:11:03 +0000765JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompress___3BI_3IIIIII
DRC19c791c2018-03-08 10:55:20 -0600766 (JNIEnv *env, jobject obj, jbyteArray src, jint jpegSize, jintArray dst,
767 jint width, jint stride, jint height, jint pf, jint flags)
DRC84a1bcc2011-02-23 12:09:56 +0000768{
DRC19c791c2018-03-08 10:55:20 -0600769 if (pf < 0 || pf >= org_libjpegturbo_turbojpeg_TJ_NUMPF)
DRCbce58f42019-04-12 07:49:35 -0500770 THROW_ARG("Invalid argument in decompress()");
DRC19c791c2018-03-08 10:55:20 -0600771 if (tjPixelSize[pf] != sizeof(jint))
DRCbce58f42019-04-12 07:49:35 -0500772 THROW_ARG("Pixel format must be 32-bit when decompressing to an integer buffer.");
DRC927a10d2014-08-15 13:18:58 +0000773
DRC19c791c2018-03-08 10:55:20 -0600774 TJDecompressor_decompress(env, obj, src, jpegSize, dst, sizeof(jint), 0, 0,
775 width, stride * sizeof(jint), height, pf, flags);
DRC927a10d2014-08-15 13:18:58 +0000776
DRC19c791c2018-03-08 10:55:20 -0600777bailout:
778 return;
DRC4f1580c2011-02-25 06:11:03 +0000779}
DRC84a1bcc2011-02-23 12:09:56 +0000780
DRCa4940d12014-08-15 16:07:15 +0000781/* TurboJPEG 1.4.x: TJDecompressor::decompressToYUV() */
DRC40dd3142014-08-17 12:23:49 +0000782JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompressToYUV___3BI_3_3B_3II_3III
DRC19c791c2018-03-08 10:55:20 -0600783 (JNIEnv *env, jobject obj, jbyteArray src, jint jpegSize,
784 jobjectArray dstobjs, jintArray jDstOffsets, jint desiredWidth,
785 jintArray jDstStrides, jint desiredHeight, jint flags)
DRC4f1580c2011-02-25 06:11:03 +0000786{
DRC19c791c2018-03-08 10:55:20 -0600787 tjhandle handle = 0;
788 jbyteArray jDstPlanes[3] = { NULL, NULL, NULL };
789 unsigned char *jpegBuf = NULL, *dstPlanes[3];
790 int *dstOffsets = NULL, *dstStrides = NULL;
791 int jpegSubsamp = -1, jpegWidth = 0, jpegHeight = 0;
792 int nc = 0, i, width, height, scaledWidth, scaledHeight, nsf = 0;
793 tjscalingfactor *sf;
DRC40dd3142014-08-17 12:23:49 +0000794
DRCbce58f42019-04-12 07:49:35 -0500795 GET_HANDLE();
DRC4f1580c2011-02-25 06:11:03 +0000796
DRC19c791c2018-03-08 10:55:20 -0600797 if ((*env)->GetArrayLength(env, src) < jpegSize)
DRCbce58f42019-04-12 07:49:35 -0500798 THROW_ARG("Source buffer is not large enough");
799 BAILIF0(_fid = (*env)->GetFieldID(env, _cls, "jpegSubsamp", "I"));
DRC19c791c2018-03-08 10:55:20 -0600800 jpegSubsamp = (int)(*env)->GetIntField(env, obj, _fid);
DRCbce58f42019-04-12 07:49:35 -0500801 BAILIF0(_fid = (*env)->GetFieldID(env, _cls, "jpegWidth", "I"));
DRC19c791c2018-03-08 10:55:20 -0600802 jpegWidth = (int)(*env)->GetIntField(env, obj, _fid);
DRCbce58f42019-04-12 07:49:35 -0500803 BAILIF0(_fid = (*env)->GetFieldID(env, _cls, "jpegHeight", "I"));
DRC19c791c2018-03-08 10:55:20 -0600804 jpegHeight = (int)(*env)->GetIntField(env, obj, _fid);
DRC4f1580c2011-02-25 06:11:03 +0000805
DRC19c791c2018-03-08 10:55:20 -0600806 nc = (jpegSubsamp == org_libjpegturbo_turbojpeg_TJ_SAMP_GRAY ? 1 : 3);
DRC6acf52b2011-03-02 01:09:20 +0000807
DRC19c791c2018-03-08 10:55:20 -0600808 width = desiredWidth;
809 height = desiredHeight;
810 if (width == 0) width = jpegWidth;
811 if (height == 0) height = jpegHeight;
812 sf = tjGetScalingFactors(&nsf);
813 if (!sf || nsf < 1)
DRCbce58f42019-04-12 07:49:35 -0500814 THROW_ARG(tjGetErrorStr());
DRC19c791c2018-03-08 10:55:20 -0600815 for (i = 0; i < nsf; i++) {
816 scaledWidth = TJSCALED(jpegWidth, sf[i]);
817 scaledHeight = TJSCALED(jpegHeight, sf[i]);
818 if (scaledWidth <= width && scaledHeight <= height)
819 break;
820 }
821 if (i >= nsf)
DRCbce58f42019-04-12 07:49:35 -0500822 THROW_ARG("Could not scale down to desired image dimensions");
DRC4f1580c2011-02-25 06:11:03 +0000823
DRC33011752019-04-12 08:47:28 -0500824#define RELEASE_ARRAYS_DECOMPRESSTOYUV() { \
825 SAFE_RELEASE(src, jpegBuf); \
826 for (i = 0; i < nc; i++) \
827 SAFE_RELEASE(jDstPlanes[i], dstPlanes[i]); \
828 SAFE_RELEASE(jDstStrides, dstStrides); \
829 SAFE_RELEASE(jDstOffsets, dstOffsets); \
830}
831
DRCbce58f42019-04-12 07:49:35 -0500832 BAILIF0(dstOffsets = (*env)->GetPrimitiveArrayCritical(env, jDstOffsets, 0));
833 BAILIF0(dstStrides = (*env)->GetPrimitiveArrayCritical(env, jDstStrides, 0));
DRC19c791c2018-03-08 10:55:20 -0600834 for (i = 0; i < nc; i++) {
835 int planeSize = tjPlaneSizeYUV(i, scaledWidth, dstStrides[i], scaledHeight,
836 jpegSubsamp);
837 int pw = tjPlaneWidth(i, scaledWidth, jpegSubsamp);
DRC40dd3142014-08-17 12:23:49 +0000838
DRC33011752019-04-12 08:47:28 -0500839 if (planeSize < 0 || pw < 0) {
840 RELEASE_ARRAYS_DECOMPRESSTOYUV();
DRCbce58f42019-04-12 07:49:35 -0500841 THROW_ARG(tjGetErrorStr());
DRC33011752019-04-12 08:47:28 -0500842 }
DRC40dd3142014-08-17 12:23:49 +0000843
DRC33011752019-04-12 08:47:28 -0500844 if (dstOffsets[i] < 0) {
845 RELEASE_ARRAYS_DECOMPRESSTOYUV();
DRCbce58f42019-04-12 07:49:35 -0500846 THROW_ARG("Invalid argument in decompressToYUV()");
DRC33011752019-04-12 08:47:28 -0500847 }
848 if (dstStrides[i] < 0 && dstOffsets[i] - planeSize + pw < 0) {
849 RELEASE_ARRAYS_DECOMPRESSTOYUV();
DRCbce58f42019-04-12 07:49:35 -0500850 THROW_ARG("Negative plane stride would cause memory to be accessed below plane boundary");
DRC33011752019-04-12 08:47:28 -0500851 }
DRC40dd3142014-08-17 12:23:49 +0000852
DRCbce58f42019-04-12 07:49:35 -0500853 BAILIF0(jDstPlanes[i] = (*env)->GetObjectArrayElement(env, dstobjs, i));
DRC33011752019-04-12 08:47:28 -0500854 if ((*env)->GetArrayLength(env, jDstPlanes[i]) <
855 dstOffsets[i] + planeSize) {
856 RELEASE_ARRAYS_DECOMPRESSTOYUV();
DRCbce58f42019-04-12 07:49:35 -0500857 THROW_ARG("Destination plane is not large enough");
DRC33011752019-04-12 08:47:28 -0500858 }
DRC40dd3142014-08-17 12:23:49 +0000859
DRCbce58f42019-04-12 07:49:35 -0500860 BAILIF0(dstPlanes[i] =
DRC19c791c2018-03-08 10:55:20 -0600861 (*env)->GetPrimitiveArrayCritical(env, jDstPlanes[i], 0));
862 dstPlanes[i] = &dstPlanes[i][dstOffsets[i]];
863 }
DRCbce58f42019-04-12 07:49:35 -0500864 BAILIF0(jpegBuf = (*env)->GetPrimitiveArrayCritical(env, src, 0));
DRC40dd3142014-08-17 12:23:49 +0000865
DRC19c791c2018-03-08 10:55:20 -0600866 if (tjDecompressToYUVPlanes(handle, jpegBuf, (unsigned long)jpegSize,
867 dstPlanes, desiredWidth, dstStrides,
DRC33011752019-04-12 08:47:28 -0500868 desiredHeight, flags) == -1) {
869 RELEASE_ARRAYS_DECOMPRESSTOYUV();
DRCbce58f42019-04-12 07:49:35 -0500870 THROW_TJ();
DRC33011752019-04-12 08:47:28 -0500871 }
DRC40dd3142014-08-17 12:23:49 +0000872
DRC19c791c2018-03-08 10:55:20 -0600873bailout:
DRC33011752019-04-12 08:47:28 -0500874 RELEASE_ARRAYS_DECOMPRESSTOYUV();
DRC84a1bcc2011-02-23 12:09:56 +0000875}
876
DRCa4940d12014-08-15 16:07:15 +0000877/* TurboJPEG 1.2.x: TJDecompressor::decompressToYUV() */
DRCfef98522013-04-28 01:32:52 +0000878JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompressToYUV___3BI_3BI
DRC19c791c2018-03-08 10:55:20 -0600879 (JNIEnv *env, jobject obj, jbyteArray src, jint jpegSize, jbyteArray dst,
880 jint flags)
DRCfef98522013-04-28 01:32:52 +0000881{
DRC19c791c2018-03-08 10:55:20 -0600882 tjhandle handle = 0;
883 unsigned char *jpegBuf = NULL, *dstBuf = NULL;
884 int jpegSubsamp = -1, jpegWidth = 0, jpegHeight = 0;
DRCfc26b652014-03-16 22:56:26 +0000885
DRCbce58f42019-04-12 07:49:35 -0500886 GET_HANDLE();
DRCfc26b652014-03-16 22:56:26 +0000887
DRC19c791c2018-03-08 10:55:20 -0600888 if ((*env)->GetArrayLength(env, src) < jpegSize)
DRCbce58f42019-04-12 07:49:35 -0500889 THROW_ARG("Source buffer is not large enough");
890 BAILIF0(_fid = (*env)->GetFieldID(env, _cls, "jpegSubsamp", "I"));
DRC19c791c2018-03-08 10:55:20 -0600891 jpegSubsamp = (int)(*env)->GetIntField(env, obj, _fid);
DRCbce58f42019-04-12 07:49:35 -0500892 BAILIF0(_fid = (*env)->GetFieldID(env, _cls, "jpegWidth", "I"));
DRC19c791c2018-03-08 10:55:20 -0600893 jpegWidth = (int)(*env)->GetIntField(env, obj, _fid);
DRCbce58f42019-04-12 07:49:35 -0500894 BAILIF0(_fid = (*env)->GetFieldID(env, _cls, "jpegHeight", "I"));
DRC19c791c2018-03-08 10:55:20 -0600895 jpegHeight = (int)(*env)->GetIntField(env, obj, _fid);
896 if ((*env)->GetArrayLength(env, dst) <
897 (jsize)tjBufSizeYUV(jpegWidth, jpegHeight, jpegSubsamp))
DRCbce58f42019-04-12 07:49:35 -0500898 THROW_ARG("Destination buffer is not large enough");
DRC40dd3142014-08-17 12:23:49 +0000899
DRCbce58f42019-04-12 07:49:35 -0500900 BAILIF0(jpegBuf = (*env)->GetPrimitiveArrayCritical(env, src, 0));
901 BAILIF0(dstBuf = (*env)->GetPrimitiveArrayCritical(env, dst, 0));
DRC40dd3142014-08-17 12:23:49 +0000902
DRC19c791c2018-03-08 10:55:20 -0600903 if (tjDecompressToYUV(handle, jpegBuf, (unsigned long)jpegSize, dstBuf,
DRC33011752019-04-12 08:47:28 -0500904 flags) == -1) {
905 SAFE_RELEASE(dst, dstBuf);
906 SAFE_RELEASE(src, jpegBuf);
DRCbce58f42019-04-12 07:49:35 -0500907 THROW_TJ();
DRC33011752019-04-12 08:47:28 -0500908 }
DRC40dd3142014-08-17 12:23:49 +0000909
DRC19c791c2018-03-08 10:55:20 -0600910bailout:
DRC33011752019-04-12 08:47:28 -0500911 SAFE_RELEASE(dst, dstBuf);
912 SAFE_RELEASE(src, jpegBuf);
DRC40dd3142014-08-17 12:23:49 +0000913}
914
915static void TJDecompressor_decodeYUV
DRC19c791c2018-03-08 10:55:20 -0600916 (JNIEnv *env, jobject obj, jobjectArray srcobjs, jintArray jSrcOffsets,
917 jintArray jSrcStrides, jint subsamp, jarray dst, jint dstElementSize,
918 jint x, jint y, jint width, jint pitch, jint height, jint pf, jint flags)
DRC40dd3142014-08-17 12:23:49 +0000919{
DRC19c791c2018-03-08 10:55:20 -0600920 tjhandle handle = 0;
921 jsize arraySize = 0, actualPitch;
922 jbyteArray jSrcPlanes[3] = { NULL, NULL, NULL };
923 const unsigned char *srcPlanes[3];
924 unsigned char *dstBuf = NULL;
925 int *srcOffsets = NULL, *srcStrides = NULL;
926 int nc = (subsamp == org_libjpegturbo_turbojpeg_TJ_SAMP_GRAY ? 1 : 3), i;
DRC40dd3142014-08-17 12:23:49 +0000927
DRCbce58f42019-04-12 07:49:35 -0500928 GET_HANDLE();
DRC40dd3142014-08-17 12:23:49 +0000929
DRC19c791c2018-03-08 10:55:20 -0600930 if (pf < 0 || pf >= org_libjpegturbo_turbojpeg_TJ_NUMPF || subsamp < 0 ||
931 subsamp >= org_libjpegturbo_turbojpeg_TJ_NUMSAMP)
DRCbce58f42019-04-12 07:49:35 -0500932 THROW_ARG("Invalid argument in decodeYUV()");
DRC19c791c2018-03-08 10:55:20 -0600933 if (org_libjpegturbo_turbojpeg_TJ_NUMPF != TJ_NUMPF ||
934 org_libjpegturbo_turbojpeg_TJ_NUMSAMP != TJ_NUMSAMP)
DRCbce58f42019-04-12 07:49:35 -0500935 THROW_ARG("Mismatch between Java and C API");
DRCfc26b652014-03-16 22:56:26 +0000936
DRC19c791c2018-03-08 10:55:20 -0600937 if ((*env)->GetArrayLength(env, srcobjs) < nc)
DRCbce58f42019-04-12 07:49:35 -0500938 THROW_ARG("Planes array is too small for the subsampling type");
DRC19c791c2018-03-08 10:55:20 -0600939 if ((*env)->GetArrayLength(env, jSrcOffsets) < nc)
DRCbce58f42019-04-12 07:49:35 -0500940 THROW_ARG("Offsets array is too small for the subsampling type");
DRC19c791c2018-03-08 10:55:20 -0600941 if ((*env)->GetArrayLength(env, jSrcStrides) < nc)
DRCbce58f42019-04-12 07:49:35 -0500942 THROW_ARG("Strides array is too small for the subsampling type");
DRC40dd3142014-08-17 12:23:49 +0000943
DRC19c791c2018-03-08 10:55:20 -0600944 actualPitch = (pitch == 0) ? width * tjPixelSize[pf] : pitch;
945 arraySize = (y + height - 1) * actualPitch + (x + width) * tjPixelSize[pf];
946 if ((*env)->GetArrayLength(env, dst) * dstElementSize < arraySize)
DRCbce58f42019-04-12 07:49:35 -0500947 THROW_ARG("Destination buffer is not large enough");
DRCfc26b652014-03-16 22:56:26 +0000948
DRC33011752019-04-12 08:47:28 -0500949#define RELEASE_ARRAYS_DECODEYUV() { \
950 SAFE_RELEASE(dst, dstBuf); \
951 for (i = 0; i < nc; i++) \
952 SAFE_RELEASE(jSrcPlanes[i], srcPlanes[i]); \
953 SAFE_RELEASE(jSrcStrides, srcStrides); \
954 SAFE_RELEASE(jSrcOffsets, srcOffsets); \
955}
956
DRCbce58f42019-04-12 07:49:35 -0500957 BAILIF0(srcOffsets = (*env)->GetPrimitiveArrayCritical(env, jSrcOffsets, 0));
958 BAILIF0(srcStrides = (*env)->GetPrimitiveArrayCritical(env, jSrcStrides, 0));
DRC19c791c2018-03-08 10:55:20 -0600959 for (i = 0; i < nc; i++) {
960 int planeSize = tjPlaneSizeYUV(i, width, srcStrides[i], height, subsamp);
961 int pw = tjPlaneWidth(i, width, subsamp);
DRC40dd3142014-08-17 12:23:49 +0000962
DRC33011752019-04-12 08:47:28 -0500963 if (planeSize < 0 || pw < 0) {
964 RELEASE_ARRAYS_DECODEYUV();
DRCbce58f42019-04-12 07:49:35 -0500965 THROW_ARG(tjGetErrorStr());
DRC33011752019-04-12 08:47:28 -0500966 }
DRC40dd3142014-08-17 12:23:49 +0000967
DRC33011752019-04-12 08:47:28 -0500968 if (srcOffsets[i] < 0) {
969 RELEASE_ARRAYS_DECODEYUV();
DRCbce58f42019-04-12 07:49:35 -0500970 THROW_ARG("Invalid argument in decodeYUV()");
DRC33011752019-04-12 08:47:28 -0500971 }
972 if (srcStrides[i] < 0 && srcOffsets[i] - planeSize + pw < 0) {
973 RELEASE_ARRAYS_DECODEYUV();
DRCbce58f42019-04-12 07:49:35 -0500974 THROW_ARG("Negative plane stride would cause memory to be accessed below plane boundary");
DRC33011752019-04-12 08:47:28 -0500975 }
DRC40dd3142014-08-17 12:23:49 +0000976
DRCbce58f42019-04-12 07:49:35 -0500977 BAILIF0(jSrcPlanes[i] = (*env)->GetObjectArrayElement(env, srcobjs, i));
DRC33011752019-04-12 08:47:28 -0500978 if ((*env)->GetArrayLength(env, jSrcPlanes[i]) <
979 srcOffsets[i] + planeSize) {
980 RELEASE_ARRAYS_DECODEYUV();
DRCbce58f42019-04-12 07:49:35 -0500981 THROW_ARG("Source plane is not large enough");
DRC33011752019-04-12 08:47:28 -0500982 }
DRC40dd3142014-08-17 12:23:49 +0000983
DRCbce58f42019-04-12 07:49:35 -0500984 BAILIF0(srcPlanes[i] =
DRC19c791c2018-03-08 10:55:20 -0600985 (*env)->GetPrimitiveArrayCritical(env, jSrcPlanes[i], 0));
986 srcPlanes[i] = &srcPlanes[i][srcOffsets[i]];
987 }
DRCbce58f42019-04-12 07:49:35 -0500988 BAILIF0(dstBuf = (*env)->GetPrimitiveArrayCritical(env, dst, 0));
DRCfc26b652014-03-16 22:56:26 +0000989
DRC19c791c2018-03-08 10:55:20 -0600990 if (tjDecodeYUVPlanes(handle, srcPlanes, srcStrides, subsamp,
991 &dstBuf[y * actualPitch + x * tjPixelSize[pf]], width,
DRC33011752019-04-12 08:47:28 -0500992 pitch, height, pf, flags) == -1) {
993 RELEASE_ARRAYS_DECODEYUV();
DRCbce58f42019-04-12 07:49:35 -0500994 THROW_TJ();
DRC33011752019-04-12 08:47:28 -0500995 }
DRCfc26b652014-03-16 22:56:26 +0000996
DRC19c791c2018-03-08 10:55:20 -0600997bailout:
DRC33011752019-04-12 08:47:28 -0500998 RELEASE_ARRAYS_DECODEYUV();
DRCfc26b652014-03-16 22:56:26 +0000999}
1000
DRCa4940d12014-08-15 16:07:15 +00001001/* TurboJPEG 1.4.x: TJDecompressor::decodeYUV() byte destination */
DRC40dd3142014-08-17 12:23:49 +00001002JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decodeYUV___3_3B_3I_3II_3BIIIIIII
DRC19c791c2018-03-08 10:55:20 -06001003 (JNIEnv *env, jobject obj, jobjectArray srcobjs, jintArray jSrcOffsets,
1004 jintArray jSrcStrides, jint subsamp, jbyteArray dst, jint x, jint y,
1005 jint width, jint pitch, jint height, jint pf, jint flags)
DRC927a10d2014-08-15 13:18:58 +00001006{
DRC19c791c2018-03-08 10:55:20 -06001007 TJDecompressor_decodeYUV(env, obj, srcobjs, jSrcOffsets, jSrcStrides,
1008 subsamp, dst, 1, x, y, width, pitch, height, pf,
1009 flags);
DRC927a10d2014-08-15 13:18:58 +00001010}
1011
DRCa4940d12014-08-15 16:07:15 +00001012/* TurboJPEG 1.4.x: TJDecompressor::decodeYUV() int destination */
DRC40dd3142014-08-17 12:23:49 +00001013JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decodeYUV___3_3B_3I_3II_3IIIIIIII
DRC19c791c2018-03-08 10:55:20 -06001014 (JNIEnv *env, jobject obj, jobjectArray srcobjs, jintArray jSrcOffsets,
1015 jintArray jSrcStrides, jint subsamp, jintArray dst, jint x, jint y,
1016 jint width, jint stride, jint height, jint pf, jint flags)
DRCfc26b652014-03-16 22:56:26 +00001017{
DRC19c791c2018-03-08 10:55:20 -06001018 if (pf < 0 || pf >= org_libjpegturbo_turbojpeg_TJ_NUMPF)
DRCbce58f42019-04-12 07:49:35 -05001019 THROW_ARG("Invalid argument in decodeYUV()");
DRC19c791c2018-03-08 10:55:20 -06001020 if (tjPixelSize[pf] != sizeof(jint))
DRCbce58f42019-04-12 07:49:35 -05001021 THROW_ARG("Pixel format must be 32-bit when decoding to an integer buffer.");
DRCfc26b652014-03-16 22:56:26 +00001022
DRC19c791c2018-03-08 10:55:20 -06001023 TJDecompressor_decodeYUV(env, obj, srcobjs, jSrcOffsets, jSrcStrides,
1024 subsamp, dst, sizeof(jint), x, y, width,
1025 stride * sizeof(jint), height, pf, flags);
DRCfc26b652014-03-16 22:56:26 +00001026
DRC19c791c2018-03-08 10:55:20 -06001027bailout:
1028 return;
DRCfc26b652014-03-16 22:56:26 +00001029}
1030
DRCa4940d12014-08-15 16:07:15 +00001031/* TurboJPEG 1.2.x: TJTransformer::init() */
DRCe8573012011-03-04 10:13:59 +00001032JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJTransformer_init
DRC19c791c2018-03-08 10:55:20 -06001033 (JNIEnv *env, jobject obj)
DRCe8573012011-03-04 10:13:59 +00001034{
DRC19c791c2018-03-08 10:55:20 -06001035 jclass cls;
1036 jfieldID fid;
1037 tjhandle handle;
DRCe8573012011-03-04 10:13:59 +00001038
DRC19c791c2018-03-08 10:55:20 -06001039 if ((handle = tjInitTransform()) == NULL)
DRCbce58f42019-04-12 07:49:35 -05001040 THROW(tjGetErrorStr(), "org/libjpegturbo/turbojpeg/TJException");
DRCe8573012011-03-04 10:13:59 +00001041
DRCbce58f42019-04-12 07:49:35 -05001042 BAILIF0(cls = (*env)->GetObjectClass(env, obj));
1043 BAILIF0(fid = (*env)->GetFieldID(env, cls, "handle", "J"));
DRC19c791c2018-03-08 10:55:20 -06001044 (*env)->SetLongField(env, obj, fid, (size_t)handle);
DRCe8573012011-03-04 10:13:59 +00001045
DRC19c791c2018-03-08 10:55:20 -06001046bailout:
1047 return;
DRCe8573012011-03-04 10:13:59 +00001048}
1049
DRC19c791c2018-03-08 10:55:20 -06001050typedef struct _JNICustomFilterParams {
1051 JNIEnv *env;
1052 jobject tobj;
1053 jobject cfobj;
DRCf5467112011-09-20 05:02:19 +00001054} JNICustomFilterParams;
1055
1056static int JNICustomFilter(short *coeffs, tjregion arrayRegion,
DRC19c791c2018-03-08 10:55:20 -06001057 tjregion planeRegion, int componentIndex,
1058 int transformIndex, tjtransform *transform)
DRCf5467112011-09-20 05:02:19 +00001059{
DRC19c791c2018-03-08 10:55:20 -06001060 JNICustomFilterParams *params = (JNICustomFilterParams *)transform->data;
1061 JNIEnv *env = params->env;
1062 jobject tobj = params->tobj, cfobj = params->cfobj;
1063 jobject arrayRegionObj, planeRegionObj, bufobj, borobj;
1064 jclass cls;
1065 jmethodID mid;
1066 jfieldID fid;
DRCf5467112011-09-20 05:02:19 +00001067
DRCbce58f42019-04-12 07:49:35 -05001068 BAILIF0(bufobj = (*env)->NewDirectByteBuffer(env, coeffs,
DRC19c791c2018-03-08 10:55:20 -06001069 sizeof(short) * arrayRegion.w * arrayRegion.h));
DRCbce58f42019-04-12 07:49:35 -05001070 BAILIF0(cls = (*env)->FindClass(env, "java/nio/ByteOrder"));
1071 BAILIF0(mid = (*env)->GetStaticMethodID(env, cls, "nativeOrder",
DRC19c791c2018-03-08 10:55:20 -06001072 "()Ljava/nio/ByteOrder;"));
DRCbce58f42019-04-12 07:49:35 -05001073 BAILIF0(borobj = (*env)->CallStaticObjectMethod(env, cls, mid));
1074 BAILIF0(cls = (*env)->GetObjectClass(env, bufobj));
1075 BAILIF0(mid = (*env)->GetMethodID(env, cls, "order",
DRC19c791c2018-03-08 10:55:20 -06001076 "(Ljava/nio/ByteOrder;)Ljava/nio/ByteBuffer;"));
1077 (*env)->CallObjectMethod(env, bufobj, mid, borobj);
DRCbce58f42019-04-12 07:49:35 -05001078 BAILIF0(mid = (*env)->GetMethodID(env, cls, "asShortBuffer",
DRC19c791c2018-03-08 10:55:20 -06001079 "()Ljava/nio/ShortBuffer;"));
DRCbce58f42019-04-12 07:49:35 -05001080 BAILIF0(bufobj = (*env)->CallObjectMethod(env, bufobj, mid));
DRCf5467112011-09-20 05:02:19 +00001081
DRCbce58f42019-04-12 07:49:35 -05001082 BAILIF0(cls = (*env)->FindClass(env, "java/awt/Rectangle"));
1083 BAILIF0(arrayRegionObj = (*env)->AllocObject(env, cls));
1084 BAILIF0(fid = (*env)->GetFieldID(env, cls, "x", "I"));
DRC19c791c2018-03-08 10:55:20 -06001085 (*env)->SetIntField(env, arrayRegionObj, fid, arrayRegion.x);
DRCbce58f42019-04-12 07:49:35 -05001086 BAILIF0(fid = (*env)->GetFieldID(env, cls, "y", "I"));
DRC19c791c2018-03-08 10:55:20 -06001087 (*env)->SetIntField(env, arrayRegionObj, fid, arrayRegion.y);
DRCbce58f42019-04-12 07:49:35 -05001088 BAILIF0(fid = (*env)->GetFieldID(env, cls, "width", "I"));
DRC19c791c2018-03-08 10:55:20 -06001089 (*env)->SetIntField(env, arrayRegionObj, fid, arrayRegion.w);
DRCbce58f42019-04-12 07:49:35 -05001090 BAILIF0(fid = (*env)->GetFieldID(env, cls, "height", "I"));
DRC19c791c2018-03-08 10:55:20 -06001091 (*env)->SetIntField(env, arrayRegionObj, fid, arrayRegion.h);
DRCf5467112011-09-20 05:02:19 +00001092
DRCbce58f42019-04-12 07:49:35 -05001093 BAILIF0(planeRegionObj = (*env)->AllocObject(env, cls));
1094 BAILIF0(fid = (*env)->GetFieldID(env, cls, "x", "I"));
DRC19c791c2018-03-08 10:55:20 -06001095 (*env)->SetIntField(env, planeRegionObj, fid, planeRegion.x);
DRCbce58f42019-04-12 07:49:35 -05001096 BAILIF0(fid = (*env)->GetFieldID(env, cls, "y", "I"));
DRC19c791c2018-03-08 10:55:20 -06001097 (*env)->SetIntField(env, planeRegionObj, fid, planeRegion.y);
DRCbce58f42019-04-12 07:49:35 -05001098 BAILIF0(fid = (*env)->GetFieldID(env, cls, "width", "I"));
DRC19c791c2018-03-08 10:55:20 -06001099 (*env)->SetIntField(env, planeRegionObj, fid, planeRegion.w);
DRCbce58f42019-04-12 07:49:35 -05001100 BAILIF0(fid = (*env)->GetFieldID(env, cls, "height", "I"));
DRC19c791c2018-03-08 10:55:20 -06001101 (*env)->SetIntField(env, planeRegionObj, fid, planeRegion.h);
DRCf5467112011-09-20 05:02:19 +00001102
DRCbce58f42019-04-12 07:49:35 -05001103 BAILIF0(cls = (*env)->GetObjectClass(env, cfobj));
1104 BAILIF0(mid = (*env)->GetMethodID(env, cls, "customFilter",
DRC19c791c2018-03-08 10:55:20 -06001105 "(Ljava/nio/ShortBuffer;Ljava/awt/Rectangle;Ljava/awt/Rectangle;IILorg/libjpegturbo/turbojpeg/TJTransform;)V"));
1106 (*env)->CallVoidMethod(env, cfobj, mid, bufobj, arrayRegionObj,
1107 planeRegionObj, componentIndex, transformIndex, tobj);
DRCf5467112011-09-20 05:02:19 +00001108
DRC19c791c2018-03-08 10:55:20 -06001109 return 0;
DRCf5467112011-09-20 05:02:19 +00001110
DRC19c791c2018-03-08 10:55:20 -06001111bailout:
1112 return -1;
DRCf5467112011-09-20 05:02:19 +00001113}
1114
DRCa4940d12014-08-15 16:07:15 +00001115/* TurboJPEG 1.2.x: TJTransformer::transform() */
DRCe8573012011-03-04 10:13:59 +00001116JNIEXPORT jintArray JNICALL Java_org_libjpegturbo_turbojpeg_TJTransformer_transform
DRC19c791c2018-03-08 10:55:20 -06001117 (JNIEnv *env, jobject obj, jbyteArray jsrcBuf, jint jpegSize,
1118 jobjectArray dstobjs, jobjectArray tobjs, jint flags)
DRCe8573012011-03-04 10:13:59 +00001119{
DRC19c791c2018-03-08 10:55:20 -06001120 tjhandle handle = 0;
1121 unsigned char *jpegBuf = NULL, **dstBufs = NULL;
1122 jsize n = 0;
1123 unsigned long *dstSizes = NULL;
1124 tjtransform *t = NULL;
1125 jbyteArray *jdstBufs = NULL;
1126 int i, jpegWidth = 0, jpegHeight = 0, jpegSubsamp;
1127 jintArray jdstSizes = 0;
1128 jint *dstSizesi = NULL;
1129 JNICustomFilterParams *params = NULL;
DRCe8573012011-03-04 10:13:59 +00001130
DRCbce58f42019-04-12 07:49:35 -05001131 GET_HANDLE();
DRCe8573012011-03-04 10:13:59 +00001132
DRC19c791c2018-03-08 10:55:20 -06001133 if ((*env)->GetArrayLength(env, jsrcBuf) < jpegSize)
DRCbce58f42019-04-12 07:49:35 -05001134 THROW_ARG("Source buffer is not large enough");
1135 BAILIF0(_fid = (*env)->GetFieldID(env, _cls, "jpegWidth", "I"));
DRC19c791c2018-03-08 10:55:20 -06001136 jpegWidth = (int)(*env)->GetIntField(env, obj, _fid);
DRCbce58f42019-04-12 07:49:35 -05001137 BAILIF0(_fid = (*env)->GetFieldID(env, _cls, "jpegHeight", "I"));
DRC19c791c2018-03-08 10:55:20 -06001138 jpegHeight = (int)(*env)->GetIntField(env, obj, _fid);
DRCbce58f42019-04-12 07:49:35 -05001139 BAILIF0(_fid = (*env)->GetFieldID(env, _cls, "jpegSubsamp", "I"));
DRC19c791c2018-03-08 10:55:20 -06001140 jpegSubsamp = (int)(*env)->GetIntField(env, obj, _fid);
DRCe8573012011-03-04 10:13:59 +00001141
DRC19c791c2018-03-08 10:55:20 -06001142 n = (*env)->GetArrayLength(env, dstobjs);
1143 if (n != (*env)->GetArrayLength(env, tobjs))
DRCbce58f42019-04-12 07:49:35 -05001144 THROW_ARG("Mismatch between size of transforms array and destination buffers array");
DRCe8573012011-03-04 10:13:59 +00001145
DRC19c791c2018-03-08 10:55:20 -06001146 if ((dstBufs =
1147 (unsigned char **)malloc(sizeof(unsigned char *) * n)) == NULL)
DRCbce58f42019-04-12 07:49:35 -05001148 THROW_MEM();
DRC19c791c2018-03-08 10:55:20 -06001149 if ((jdstBufs = (jbyteArray *)malloc(sizeof(jbyteArray) * n)) == NULL)
DRCbce58f42019-04-12 07:49:35 -05001150 THROW_MEM();
DRC19c791c2018-03-08 10:55:20 -06001151 if ((dstSizes = (unsigned long *)malloc(sizeof(unsigned long) * n)) == NULL)
DRCbce58f42019-04-12 07:49:35 -05001152 THROW_MEM();
DRC19c791c2018-03-08 10:55:20 -06001153 if ((t = (tjtransform *)malloc(sizeof(tjtransform) * n)) == NULL)
DRCbce58f42019-04-12 07:49:35 -05001154 THROW_MEM();
DRC19c791c2018-03-08 10:55:20 -06001155 if ((params = (JNICustomFilterParams *)malloc(sizeof(JNICustomFilterParams) *
1156 n)) == NULL)
DRCbce58f42019-04-12 07:49:35 -05001157 THROW_MEM();
DRC19c791c2018-03-08 10:55:20 -06001158 for (i = 0; i < n; i++) {
1159 dstBufs[i] = NULL; jdstBufs[i] = NULL; dstSizes[i] = 0;
1160 memset(&t[i], 0, sizeof(tjtransform));
1161 memset(&params[i], 0, sizeof(JNICustomFilterParams));
1162 }
DRCe8573012011-03-04 10:13:59 +00001163
DRC19c791c2018-03-08 10:55:20 -06001164 for (i = 0; i < n; i++) {
1165 jobject tobj, cfobj;
DRCe8573012011-03-04 10:13:59 +00001166
DRCbce58f42019-04-12 07:49:35 -05001167 BAILIF0(tobj = (*env)->GetObjectArrayElement(env, tobjs, i));
1168 BAILIF0(_cls = (*env)->GetObjectClass(env, tobj));
1169 BAILIF0(_fid = (*env)->GetFieldID(env, _cls, "op", "I"));
DRC19c791c2018-03-08 10:55:20 -06001170 t[i].op = (*env)->GetIntField(env, tobj, _fid);
DRCbce58f42019-04-12 07:49:35 -05001171 BAILIF0(_fid = (*env)->GetFieldID(env, _cls, "options", "I"));
DRC19c791c2018-03-08 10:55:20 -06001172 t[i].options = (*env)->GetIntField(env, tobj, _fid);
DRCbce58f42019-04-12 07:49:35 -05001173 BAILIF0(_fid = (*env)->GetFieldID(env, _cls, "x", "I"));
DRC19c791c2018-03-08 10:55:20 -06001174 t[i].r.x = (*env)->GetIntField(env, tobj, _fid);
DRCbce58f42019-04-12 07:49:35 -05001175 BAILIF0(_fid = (*env)->GetFieldID(env, _cls, "y", "I"));
DRC19c791c2018-03-08 10:55:20 -06001176 t[i].r.y = (*env)->GetIntField(env, tobj, _fid);
DRCbce58f42019-04-12 07:49:35 -05001177 BAILIF0(_fid = (*env)->GetFieldID(env, _cls, "width", "I"));
DRC19c791c2018-03-08 10:55:20 -06001178 t[i].r.w = (*env)->GetIntField(env, tobj, _fid);
DRCbce58f42019-04-12 07:49:35 -05001179 BAILIF0(_fid = (*env)->GetFieldID(env, _cls, "height", "I"));
DRC19c791c2018-03-08 10:55:20 -06001180 t[i].r.h = (*env)->GetIntField(env, tobj, _fid);
DRCf5467112011-09-20 05:02:19 +00001181
DRCbce58f42019-04-12 07:49:35 -05001182 BAILIF0(_fid = (*env)->GetFieldID(env, _cls, "cf",
DRC19c791c2018-03-08 10:55:20 -06001183 "Lorg/libjpegturbo/turbojpeg/TJCustomFilter;"));
1184 cfobj = (*env)->GetObjectField(env, tobj, _fid);
1185 if (cfobj) {
1186 params[i].env = env;
1187 params[i].tobj = tobj;
1188 params[i].cfobj = cfobj;
1189 t[i].customFilter = JNICustomFilter;
1190 t[i].data = (void *)&params[i];
1191 }
1192 }
DRCe8573012011-03-04 10:13:59 +00001193
DRC19c791c2018-03-08 10:55:20 -06001194 for (i = 0; i < n; i++) {
1195 int w = jpegWidth, h = jpegHeight;
DRCe8573012011-03-04 10:13:59 +00001196
DRC19c791c2018-03-08 10:55:20 -06001197 if (t[i].r.w != 0) w = t[i].r.w;
1198 if (t[i].r.h != 0) h = t[i].r.h;
DRCbce58f42019-04-12 07:49:35 -05001199 BAILIF0(jdstBufs[i] = (*env)->GetObjectArrayElement(env, dstobjs, i));
DRC19c791c2018-03-08 10:55:20 -06001200 if ((unsigned long)(*env)->GetArrayLength(env, jdstBufs[i]) <
1201 tjBufSize(w, h, jpegSubsamp))
DRCbce58f42019-04-12 07:49:35 -05001202 THROW_ARG("Destination buffer is not large enough");
DRC19c791c2018-03-08 10:55:20 -06001203 }
DRCbce58f42019-04-12 07:49:35 -05001204 BAILIF0(jpegBuf = (*env)->GetPrimitiveArrayCritical(env, jsrcBuf, 0));
DRC19c791c2018-03-08 10:55:20 -06001205 for (i = 0; i < n; i++)
DRCbce58f42019-04-12 07:49:35 -05001206 BAILIF0(dstBufs[i] =
DRC19c791c2018-03-08 10:55:20 -06001207 (*env)->GetPrimitiveArrayCritical(env, jdstBufs[i], 0));
DRC8951cf02014-08-14 16:54:04 +00001208
DRC19c791c2018-03-08 10:55:20 -06001209 if (tjTransform(handle, jpegBuf, jpegSize, n, dstBufs, dstSizes, t,
DRC33011752019-04-12 08:47:28 -05001210 flags | TJFLAG_NOREALLOC) == -1) {
1211 for (i = 0; i < n; i++)
1212 SAFE_RELEASE(jdstBufs[i], dstBufs[i]);
1213 SAFE_RELEASE(jsrcBuf, jpegBuf);
DRCbce58f42019-04-12 07:49:35 -05001214 THROW_TJ();
DRC19c791c2018-03-08 10:55:20 -06001215 }
DRC33011752019-04-12 08:47:28 -05001216
1217 for (i = 0; i < n; i++)
1218 SAFE_RELEASE(jdstBufs[i], dstBufs[i]);
1219 SAFE_RELEASE(jsrcBuf, jpegBuf);
DRCe8573012011-03-04 10:13:59 +00001220
DRC19c791c2018-03-08 10:55:20 -06001221 jdstSizes = (*env)->NewIntArray(env, n);
DRCbce58f42019-04-12 07:49:35 -05001222 BAILIF0(dstSizesi = (*env)->GetIntArrayElements(env, jdstSizes, 0));
DRC19c791c2018-03-08 10:55:20 -06001223 for (i = 0; i < n; i++) dstSizesi[i] = (int)dstSizes[i];
1224
1225bailout:
1226 if (dstSizesi) (*env)->ReleaseIntArrayElements(env, jdstSizes, dstSizesi, 0);
1227 if (dstBufs) {
1228 for (i = 0; i < n; i++) {
1229 if (dstBufs[i] && jdstBufs && jdstBufs[i])
1230 (*env)->ReleasePrimitiveArrayCritical(env, jdstBufs[i], dstBufs[i], 0);
1231 }
1232 free(dstBufs);
1233 }
DRC33011752019-04-12 08:47:28 -05001234 SAFE_RELEASE(jsrcBuf, jpegBuf);
DRC19c791c2018-03-08 10:55:20 -06001235 if (jdstBufs) free(jdstBufs);
1236 if (dstSizes) free(dstSizes);
1237 if (t) free(t);
1238 return jdstSizes;
DRCe8573012011-03-04 10:13:59 +00001239}
1240
DRCa4940d12014-08-15 16:07:15 +00001241/* TurboJPEG 1.2.x: TJDecompressor::destroy() */
DRCc5a41992011-02-08 06:54:36 +00001242JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_destroy
DRC19c791c2018-03-08 10:55:20 -06001243 (JNIEnv *env, jobject obj)
DRCf8e00552011-02-04 11:06:36 +00001244{
DRC19c791c2018-03-08 10:55:20 -06001245 Java_org_libjpegturbo_turbojpeg_TJCompressor_destroy(env, obj);
DRCf8e00552011-02-04 11:06:36 +00001246}