blob: 13f18f780de7997b81bef8c7861bdc7a38a4b984 [file] [log] [blame]
DRCf8e00552011-02-04 11:06:36 +00001/*
DRC5ea77d82018-10-26 08:55:22 -05002 * Copyright (C)2011-2018 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
DRC293263c2018-03-17 15:14:35 -050040#define PAD(v, p) ((v + (p) - 1) & (~((p) - 1)))
DRC40dd3142014-08-17 12:23:49 +000041
DRCd8b95102019-04-12 07:49:35 -050042#define BAILIF0(f) { \
DRC19c791c2018-03-08 10:55:20 -060043 if (!(f) || (*env)->ExceptionCheck(env)) { \
44 goto bailout; \
45 } \
DRCf8e00552011-02-04 11:06:36 +000046}
47
DRCd8b95102019-04-12 07:49:35 -050048#define THROW(msg, exceptionClass) { \
DRC19c791c2018-03-08 10:55:20 -060049 jclass _exccls = (*env)->FindClass(env, exceptionClass); \
50 \
DRCd8b95102019-04-12 07:49:35 -050051 BAILIF0(_exccls); \
DRC19c791c2018-03-08 10:55:20 -060052 (*env)->ThrowNew(env, _exccls, msg); \
53 goto bailout; \
54}
55
DRCd8b95102019-04-12 07:49:35 -050056#define THROW_TJ() { \
DRC19c791c2018-03-08 10:55:20 -060057 jclass _exccls; \
58 jmethodID _excid; \
59 jobject _excobj; \
60 jstring _errstr; \
61 \
DRCd8b95102019-04-12 07:49:35 -050062 BAILIF0(_errstr = (*env)->NewStringUTF(env, tjGetErrorStr2(handle))); \
63 BAILIF0(_exccls = (*env)->FindClass(env, \
DRC19c791c2018-03-08 10:55:20 -060064 "org/libjpegturbo/turbojpeg/TJException")); \
DRCd8b95102019-04-12 07:49:35 -050065 BAILIF0(_excid = (*env)->GetMethodID(env, _exccls, "<init>", \
DRC19c791c2018-03-08 10:55:20 -060066 "(Ljava/lang/String;I)V")); \
DRCd8b95102019-04-12 07:49:35 -050067 BAILIF0(_excobj = (*env)->NewObject(env, _exccls, _excid, _errstr, \
DRC19c791c2018-03-08 10:55:20 -060068 tjGetErrorCode(handle))); \
69 (*env)->Throw(env, _excobj); \
70 goto bailout; \
DRCd4092f62017-06-27 10:54:21 -050071}
DRCb3817da2015-07-14 20:42:52 +000072
DRCd8b95102019-04-12 07:49:35 -050073#define THROW_ARG(msg) THROW(msg, "java/lang/IllegalArgumentException")
DRCb3817da2015-07-14 20:42:52 +000074
DRCd8b95102019-04-12 07:49:35 -050075#define THROW_MEM() \
76 THROW("Memory allocation failure", "java/lang/OutOfMemoryError");
DRCb3817da2015-07-14 20:42:52 +000077
DRCd8b95102019-04-12 07:49:35 -050078#define GET_HANDLE() \
DRC19c791c2018-03-08 10:55:20 -060079 jclass _cls = (*env)->GetObjectClass(env, obj); \
80 jfieldID _fid; \
81 \
DRCd8b95102019-04-12 07:49:35 -050082 BAILIF0(_cls); \
83 BAILIF0(_fid = (*env)->GetFieldID(env, _cls, "handle", "J")); \
DRC19c791c2018-03-08 10:55:20 -060084 handle = (tjhandle)(size_t)(*env)->GetLongField(env, obj, _fid);
DRCf8e00552011-02-04 11:06:36 +000085
DRCbdb36e12014-08-22 15:39:32 +000086#ifdef _WIN32
DRC293263c2018-03-17 15:14:35 -050087#define setenv(envvar, value, dummy) _putenv_s(envvar, value)
DRCbdb36e12014-08-22 15:39:32 +000088#endif
89
DRCd8b95102019-04-12 07:49:35 -050090#define PROP2ENV(property, envvar) { \
DRC19c791c2018-03-08 10:55:20 -060091 if ((jName = (*env)->NewStringUTF(env, property)) != NULL && \
92 (jValue = (*env)->CallStaticObjectMethod(env, cls, mid, \
93 jName)) != NULL) { \
94 if ((value = (*env)->GetStringUTFChars(env, jValue, 0)) != NULL) { \
95 setenv(envvar, value, 1); \
96 (*env)->ReleaseStringUTFChars(env, jValue, value); \
97 } \
98 } \
DRC0713c1b2014-08-22 13:43:33 +000099}
100
101int ProcessSystemProperties(JNIEnv *env)
102{
DRC19c791c2018-03-08 10:55:20 -0600103 jclass cls;
104 jmethodID mid;
105 jstring jName, jValue;
106 const char *value;
DRC0713c1b2014-08-22 13:43:33 +0000107
DRCd8b95102019-04-12 07:49:35 -0500108 BAILIF0(cls = (*env)->FindClass(env, "java/lang/System"));
109 BAILIF0(mid = (*env)->GetStaticMethodID(env, cls, "getProperty",
DRC19c791c2018-03-08 10:55:20 -0600110 "(Ljava/lang/String;)Ljava/lang/String;"));
DRC0713c1b2014-08-22 13:43:33 +0000111
DRCd8b95102019-04-12 07:49:35 -0500112 PROP2ENV("turbojpeg.optimize", "TJ_OPTIMIZE");
113 PROP2ENV("turbojpeg.arithmetic", "TJ_ARITHMETIC");
114 PROP2ENV("turbojpeg.restart", "TJ_RESTART");
115 PROP2ENV("turbojpeg.progressive", "TJ_PROGRESSIVE");
DRC19c791c2018-03-08 10:55:20 -0600116 return 0;
DRC0713c1b2014-08-22 13:43:33 +0000117
DRC19c791c2018-03-08 10:55:20 -0600118bailout:
119 return -1;
DRC0713c1b2014-08-22 13:43:33 +0000120}
121
DRCa4940d12014-08-15 16:07:15 +0000122/* TurboJPEG 1.2.x: TJ::bufSize() */
DRC3bad53f2011-02-23 02:20:49 +0000123JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJ_bufSize
DRC19c791c2018-03-08 10:55:20 -0600124 (JNIEnv *env, jclass cls, jint width, jint height, jint jpegSubsamp)
DRCf8e00552011-02-04 11:06:36 +0000125{
DRC19c791c2018-03-08 10:55:20 -0600126 jint retval = (jint)tjBufSize(width, height, jpegSubsamp);
DRC36336fc2011-02-22 10:27:31 +0000127
DRCd8b95102019-04-12 07:49:35 -0500128 if (retval == -1) THROW_ARG(tjGetErrorStr());
DRC19c791c2018-03-08 10:55:20 -0600129
130bailout:
131 return retval;
DRC36336fc2011-02-22 10:27:31 +0000132}
133
DRCa4940d12014-08-15 16:07:15 +0000134/* TurboJPEG 1.4.x: TJ::bufSizeYUV() */
DRCfef98522013-04-28 01:32:52 +0000135JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJ_bufSizeYUV__IIII
DRC19c791c2018-03-08 10:55:20 -0600136 (JNIEnv *env, jclass cls, jint width, jint pad, jint height, jint subsamp)
DRC36336fc2011-02-22 10:27:31 +0000137{
DRC19c791c2018-03-08 10:55:20 -0600138 jint retval = (jint)tjBufSizeYUV2(width, pad, height, subsamp);
DRC36336fc2011-02-22 10:27:31 +0000139
DRCd8b95102019-04-12 07:49:35 -0500140 if (retval == -1) THROW_ARG(tjGetErrorStr());
DRC19c791c2018-03-08 10:55:20 -0600141
142bailout:
143 return retval;
DRCf8e00552011-02-04 11:06:36 +0000144}
145
DRCa4940d12014-08-15 16:07:15 +0000146/* TurboJPEG 1.2.x: TJ::bufSizeYUV() */
DRCfef98522013-04-28 01:32:52 +0000147JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJ_bufSizeYUV__III
DRC19c791c2018-03-08 10:55:20 -0600148 (JNIEnv *env, jclass cls, jint width, jint height, jint subsamp)
DRCfef98522013-04-28 01:32:52 +0000149{
DRC19c791c2018-03-08 10:55:20 -0600150 return Java_org_libjpegturbo_turbojpeg_TJ_bufSizeYUV__IIII(env, cls, width,
151 4, height,
152 subsamp);
DRCfef98522013-04-28 01:32:52 +0000153}
154
DRC40dd3142014-08-17 12:23:49 +0000155/* TurboJPEG 1.4.x: TJ::planeSizeYUV() */
156JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJ_planeSizeYUV__IIIII
DRC19c791c2018-03-08 10:55:20 -0600157 (JNIEnv *env, jclass cls, jint componentID, jint width, jint stride,
158 jint height, jint subsamp)
DRC40dd3142014-08-17 12:23:49 +0000159{
DRC19c791c2018-03-08 10:55:20 -0600160 jint retval = (jint)tjPlaneSizeYUV(componentID, width, stride, height,
161 subsamp);
DRC40dd3142014-08-17 12:23:49 +0000162
DRCd8b95102019-04-12 07:49:35 -0500163 if (retval == -1) THROW_ARG(tjGetErrorStr());
DRC19c791c2018-03-08 10:55:20 -0600164
165bailout:
166 return retval;
DRC40dd3142014-08-17 12:23:49 +0000167}
168
169/* TurboJPEG 1.4.x: TJ::planeWidth() */
170JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJ_planeWidth__III
DRC19c791c2018-03-08 10:55:20 -0600171 (JNIEnv *env, jclass cls, jint componentID, jint width, jint subsamp)
DRC40dd3142014-08-17 12:23:49 +0000172{
DRC19c791c2018-03-08 10:55:20 -0600173 jint retval = (jint)tjPlaneWidth(componentID, width, subsamp);
DRC40dd3142014-08-17 12:23:49 +0000174
DRCd8b95102019-04-12 07:49:35 -0500175 if (retval == -1) THROW_ARG(tjGetErrorStr());
DRC19c791c2018-03-08 10:55:20 -0600176
177bailout:
178 return retval;
DRC40dd3142014-08-17 12:23:49 +0000179}
180
181/* TurboJPEG 1.4.x: TJ::planeHeight() */
182JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJ_planeHeight__III
DRC19c791c2018-03-08 10:55:20 -0600183 (JNIEnv *env, jclass cls, jint componentID, jint height, jint subsamp)
DRC40dd3142014-08-17 12:23:49 +0000184{
DRC19c791c2018-03-08 10:55:20 -0600185 jint retval = (jint)tjPlaneHeight(componentID, height, subsamp);
DRC40dd3142014-08-17 12:23:49 +0000186
DRCd8b95102019-04-12 07:49:35 -0500187 if (retval == -1) THROW_ARG(tjGetErrorStr());
DRC19c791c2018-03-08 10:55:20 -0600188
189bailout:
190 return retval;
DRC40dd3142014-08-17 12:23:49 +0000191}
192
DRCa4940d12014-08-15 16:07:15 +0000193/* TurboJPEG 1.2.x: TJCompressor::init() */
DRCc5a41992011-02-08 06:54:36 +0000194JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_init
DRC19c791c2018-03-08 10:55:20 -0600195 (JNIEnv *env, jobject obj)
DRCf8e00552011-02-04 11:06:36 +0000196{
DRC19c791c2018-03-08 10:55:20 -0600197 jclass cls;
198 jfieldID fid;
199 tjhandle handle;
DRCf8e00552011-02-04 11:06:36 +0000200
DRC19c791c2018-03-08 10:55:20 -0600201 if ((handle = tjInitCompress()) == NULL)
DRCd8b95102019-04-12 07:49:35 -0500202 THROW(tjGetErrorStr(), "org/libjpegturbo/turbojpeg/TJException");
DRCf8e00552011-02-04 11:06:36 +0000203
DRCd8b95102019-04-12 07:49:35 -0500204 BAILIF0(cls = (*env)->GetObjectClass(env, obj));
205 BAILIF0(fid = (*env)->GetFieldID(env, cls, "handle", "J"));
DRC19c791c2018-03-08 10:55:20 -0600206 (*env)->SetLongField(env, obj, fid, (size_t)handle);
DRCf8e00552011-02-04 11:06:36 +0000207
DRC19c791c2018-03-08 10:55:20 -0600208bailout:
209 return;
DRCf8e00552011-02-04 11:06:36 +0000210}
211
DRC5d87f6d2014-08-15 16:40:56 +0000212static jint TJCompressor_compress
DRC19c791c2018-03-08 10:55:20 -0600213 (JNIEnv *env, jobject obj, jarray src, jint srcElementSize, jint x, jint y,
214 jint width, jint pitch, jint height, jint pf, jbyteArray dst,
215 jint jpegSubsamp, jint jpegQual, jint flags)
DRCf8e00552011-02-04 11:06:36 +0000216{
DRC19c791c2018-03-08 10:55:20 -0600217 tjhandle handle = 0;
218 unsigned long jpegSize = 0;
219 jsize arraySize = 0, actualPitch;
220 unsigned char *srcBuf = NULL, *jpegBuf = NULL;
DRCf8e00552011-02-04 11:06:36 +0000221
DRCd8b95102019-04-12 07:49:35 -0500222 GET_HANDLE();
DRCf8e00552011-02-04 11:06:36 +0000223
DRC19c791c2018-03-08 10:55:20 -0600224 if (pf < 0 || pf >= org_libjpegturbo_turbojpeg_TJ_NUMPF || width < 1 ||
225 height < 1 || pitch < 0)
DRCd8b95102019-04-12 07:49:35 -0500226 THROW_ARG("Invalid argument in compress()");
DRC19c791c2018-03-08 10:55:20 -0600227 if (org_libjpegturbo_turbojpeg_TJ_NUMPF != TJ_NUMPF)
DRCd8b95102019-04-12 07:49:35 -0500228 THROW_ARG("Mismatch between Java and C API");
DRC4f1580c2011-02-25 06:11:03 +0000229
DRC19c791c2018-03-08 10:55:20 -0600230 actualPitch = (pitch == 0) ? width * tjPixelSize[pf] : pitch;
231 arraySize = (y + height - 1) * actualPitch + (x + width) * tjPixelSize[pf];
232 if ((*env)->GetArrayLength(env, src) * srcElementSize < arraySize)
DRCd8b95102019-04-12 07:49:35 -0500233 THROW_ARG("Source buffer is not large enough");
DRC19c791c2018-03-08 10:55:20 -0600234 jpegSize = tjBufSize(width, height, jpegSubsamp);
235 if ((*env)->GetArrayLength(env, dst) < (jsize)jpegSize)
DRCd8b95102019-04-12 07:49:35 -0500236 THROW_ARG("Destination buffer is not large enough");
DRC6acf52b2011-03-02 01:09:20 +0000237
DRC5ea77d82018-10-26 08:55:22 -0500238 if (ProcessSystemProperties(env) < 0) goto bailout;
239
DRCd8b95102019-04-12 07:49:35 -0500240 BAILIF0(srcBuf = (*env)->GetPrimitiveArrayCritical(env, src, 0));
241 BAILIF0(jpegBuf = (*env)->GetPrimitiveArrayCritical(env, dst, 0));
DRCf8e00552011-02-04 11:06:36 +0000242
DRC19c791c2018-03-08 10:55:20 -0600243 if (tjCompress2(handle, &srcBuf[y * actualPitch + x * tjPixelSize[pf]],
244 width, pitch, height, pf, &jpegBuf, &jpegSize, jpegSubsamp,
245 jpegQual, flags | TJFLAG_NOREALLOC) == -1)
DRCd8b95102019-04-12 07:49:35 -0500246 THROW_TJ();
DRCfac3bea2012-09-24 02:27:55 +0000247
DRC19c791c2018-03-08 10:55:20 -0600248bailout:
249 if (jpegBuf) (*env)->ReleasePrimitiveArrayCritical(env, dst, jpegBuf, 0);
250 if (srcBuf) (*env)->ReleasePrimitiveArrayCritical(env, src, srcBuf, 0);
251 return (jint)jpegSize;
DRCfac3bea2012-09-24 02:27:55 +0000252}
253
DRCa4940d12014-08-15 16:07:15 +0000254/* TurboJPEG 1.3.x: TJCompressor::compress() byte source */
DRC927a10d2014-08-15 13:18:58 +0000255JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_compress___3BIIIIII_3BIII
DRC19c791c2018-03-08 10:55:20 -0600256 (JNIEnv *env, jobject obj, jbyteArray src, jint x, jint y, jint width,
257 jint pitch, jint height, jint pf, jbyteArray dst, jint jpegSubsamp,
258 jint jpegQual, jint flags)
DRC927a10d2014-08-15 13:18:58 +0000259{
DRC19c791c2018-03-08 10:55:20 -0600260 return TJCompressor_compress(env, obj, src, 1, x, y, width, pitch, height,
261 pf, dst, jpegSubsamp, jpegQual, flags);
DRC927a10d2014-08-15 13:18:58 +0000262}
263
DRCa4940d12014-08-15 16:07:15 +0000264/* TurboJPEG 1.2.x: TJCompressor::compress() byte source */
DRCfac3bea2012-09-24 02:27:55 +0000265JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_compress___3BIIII_3BIII
DRC19c791c2018-03-08 10:55:20 -0600266 (JNIEnv *env, jobject obj, jbyteArray src, jint width, jint pitch,
267 jint height, jint pf, jbyteArray dst, jint jpegSubsamp, jint jpegQual,
268 jint flags)
DRCfac3bea2012-09-24 02:27:55 +0000269{
DRC19c791c2018-03-08 10:55:20 -0600270 return TJCompressor_compress(env, obj, src, 1, 0, 0, width, pitch, height,
271 pf, dst, jpegSubsamp, jpegQual, flags);
DRCfac3bea2012-09-24 02:27:55 +0000272}
273
DRCa4940d12014-08-15 16:07:15 +0000274/* TurboJPEG 1.3.x: TJCompressor::compress() int source */
DRCfac3bea2012-09-24 02:27:55 +0000275JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_compress___3IIIIIII_3BIII
DRC19c791c2018-03-08 10:55:20 -0600276 (JNIEnv *env, jobject obj, jintArray src, jint x, jint y, jint width,
277 jint stride, jint height, jint pf, jbyteArray dst, jint jpegSubsamp,
278 jint jpegQual, jint flags)
DRCfac3bea2012-09-24 02:27:55 +0000279{
DRC19c791c2018-03-08 10:55:20 -0600280 if (pf < 0 || pf >= org_libjpegturbo_turbojpeg_TJ_NUMPF)
DRCd8b95102019-04-12 07:49:35 -0500281 THROW_ARG("Invalid argument in compress()");
DRC19c791c2018-03-08 10:55:20 -0600282 if (tjPixelSize[pf] != sizeof(jint))
DRCd8b95102019-04-12 07:49:35 -0500283 THROW_ARG("Pixel format must be 32-bit when compressing from an integer buffer.");
DRCfac3bea2012-09-24 02:27:55 +0000284
DRC19c791c2018-03-08 10:55:20 -0600285 return TJCompressor_compress(env, obj, src, sizeof(jint), x, y, width,
286 stride * sizeof(jint), height, pf, dst,
287 jpegSubsamp, jpegQual, flags);
DRCf8e00552011-02-04 11:06:36 +0000288
DRC19c791c2018-03-08 10:55:20 -0600289bailout:
290 return 0;
DRCf8e00552011-02-04 11:06:36 +0000291}
292
DRCa4940d12014-08-15 16:07:15 +0000293/* TurboJPEG 1.2.x: TJCompressor::compress() int source */
DRC4f1580c2011-02-25 06:11:03 +0000294JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_compress___3IIIII_3BIII
DRC19c791c2018-03-08 10:55:20 -0600295 (JNIEnv *env, jobject obj, jintArray src, jint width, jint stride,
296 jint height, jint pf, jbyteArray dst, jint jpegSubsamp, jint jpegQual,
297 jint flags)
DRC84a1bcc2011-02-23 12:09:56 +0000298{
DRC19c791c2018-03-08 10:55:20 -0600299 if (pf < 0 || pf >= org_libjpegturbo_turbojpeg_TJ_NUMPF)
DRCd8b95102019-04-12 07:49:35 -0500300 THROW_ARG("Invalid argument in compress()");
DRC19c791c2018-03-08 10:55:20 -0600301 if (tjPixelSize[pf] != sizeof(jint))
DRCd8b95102019-04-12 07:49:35 -0500302 THROW_ARG("Pixel format must be 32-bit when compressing from an integer buffer.");
DRC927a10d2014-08-15 13:18:58 +0000303
DRC19c791c2018-03-08 10:55:20 -0600304 return TJCompressor_compress(env, obj, src, sizeof(jint), 0, 0, width,
305 stride * sizeof(jint), height, pf, dst,
306 jpegSubsamp, jpegQual, flags);
DRC927a10d2014-08-15 13:18:58 +0000307
DRC19c791c2018-03-08 10:55:20 -0600308bailout:
309 return 0;
DRC84a1bcc2011-02-23 12:09:56 +0000310}
311
DRCa4940d12014-08-15 16:07:15 +0000312/* TurboJPEG 1.4.x: TJCompressor::compressFromYUV() */
DRC40dd3142014-08-17 12:23:49 +0000313JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_compressFromYUV___3_3B_3II_3III_3BII
DRC19c791c2018-03-08 10:55:20 -0600314 (JNIEnv *env, jobject obj, jobjectArray srcobjs, jintArray jSrcOffsets,
315 jint width, jintArray jSrcStrides, jint height, jint subsamp,
316 jbyteArray dst, jint jpegQual, jint flags)
DRC1e672742013-10-31 05:04:51 +0000317{
DRC19c791c2018-03-08 10:55:20 -0600318 tjhandle handle = 0;
319 unsigned long jpegSize = 0;
320 jbyteArray jSrcPlanes[3] = { NULL, NULL, NULL };
321 const unsigned char *srcPlanes[3];
322 unsigned char *jpegBuf = NULL;
323 int *srcOffsets = NULL, *srcStrides = NULL;
324 int nc = (subsamp == org_libjpegturbo_turbojpeg_TJ_SAMP_GRAY ? 1 : 3), i;
DRC1e672742013-10-31 05:04:51 +0000325
DRCd8b95102019-04-12 07:49:35 -0500326 GET_HANDLE();
DRC1e672742013-10-31 05:04:51 +0000327
DRC19c791c2018-03-08 10:55:20 -0600328 if (subsamp < 0 || subsamp >= org_libjpegturbo_turbojpeg_TJ_NUMSAMP)
DRCd8b95102019-04-12 07:49:35 -0500329 THROW_ARG("Invalid argument in compressFromYUV()");
DRC19c791c2018-03-08 10:55:20 -0600330 if (org_libjpegturbo_turbojpeg_TJ_NUMSAMP != TJ_NUMSAMP)
DRCd8b95102019-04-12 07:49:35 -0500331 THROW_ARG("Mismatch between Java and C API");
DRC40dd3142014-08-17 12:23:49 +0000332
DRC19c791c2018-03-08 10:55:20 -0600333 if ((*env)->GetArrayLength(env, srcobjs) < nc)
DRCd8b95102019-04-12 07:49:35 -0500334 THROW_ARG("Planes array is too small for the subsampling type");
DRC19c791c2018-03-08 10:55:20 -0600335 if ((*env)->GetArrayLength(env, jSrcOffsets) < nc)
DRCd8b95102019-04-12 07:49:35 -0500336 THROW_ARG("Offsets array is too small for the subsampling type");
DRC19c791c2018-03-08 10:55:20 -0600337 if ((*env)->GetArrayLength(env, jSrcStrides) < nc)
DRCd8b95102019-04-12 07:49:35 -0500338 THROW_ARG("Strides array is too small for the subsampling type");
DRC40dd3142014-08-17 12:23:49 +0000339
DRC19c791c2018-03-08 10:55:20 -0600340 jpegSize = tjBufSize(width, height, subsamp);
341 if ((*env)->GetArrayLength(env, dst) < (jsize)jpegSize)
DRCd8b95102019-04-12 07:49:35 -0500342 THROW_ARG("Destination buffer is not large enough");
DRC1e672742013-10-31 05:04:51 +0000343
DRC5ea77d82018-10-26 08:55:22 -0500344 if (ProcessSystemProperties(env) < 0) goto bailout;
345
DRCd8b95102019-04-12 07:49:35 -0500346 BAILIF0(srcOffsets = (*env)->GetPrimitiveArrayCritical(env, jSrcOffsets, 0));
347 BAILIF0(srcStrides = (*env)->GetPrimitiveArrayCritical(env, jSrcStrides, 0));
DRC19c791c2018-03-08 10:55:20 -0600348 for (i = 0; i < nc; i++) {
349 int planeSize = tjPlaneSizeYUV(i, width, srcStrides[i], height, subsamp);
350 int pw = tjPlaneWidth(i, width, subsamp);
DRC40dd3142014-08-17 12:23:49 +0000351
DRC19c791c2018-03-08 10:55:20 -0600352 if (planeSize < 0 || pw < 0)
DRCd8b95102019-04-12 07:49:35 -0500353 THROW_ARG(tjGetErrorStr());
DRC40dd3142014-08-17 12:23:49 +0000354
DRC19c791c2018-03-08 10:55:20 -0600355 if (srcOffsets[i] < 0)
DRCd8b95102019-04-12 07:49:35 -0500356 THROW_ARG("Invalid argument in compressFromYUV()");
DRC19c791c2018-03-08 10:55:20 -0600357 if (srcStrides[i] < 0 && srcOffsets[i] - planeSize + pw < 0)
DRCd8b95102019-04-12 07:49:35 -0500358 THROW_ARG("Negative plane stride would cause memory to be accessed below plane boundary");
DRC40dd3142014-08-17 12:23:49 +0000359
DRCd8b95102019-04-12 07:49:35 -0500360 BAILIF0(jSrcPlanes[i] = (*env)->GetObjectArrayElement(env, srcobjs, i));
DRC19c791c2018-03-08 10:55:20 -0600361 if ((*env)->GetArrayLength(env, jSrcPlanes[i]) < srcOffsets[i] + planeSize)
DRCd8b95102019-04-12 07:49:35 -0500362 THROW_ARG("Source plane is not large enough");
DRC40dd3142014-08-17 12:23:49 +0000363
DRCd8b95102019-04-12 07:49:35 -0500364 BAILIF0(srcPlanes[i] =
DRC19c791c2018-03-08 10:55:20 -0600365 (*env)->GetPrimitiveArrayCritical(env, jSrcPlanes[i], 0));
366 srcPlanes[i] = &srcPlanes[i][srcOffsets[i]];
367 }
DRCd8b95102019-04-12 07:49:35 -0500368 BAILIF0(jpegBuf = (*env)->GetPrimitiveArrayCritical(env, dst, 0));
DRC1e672742013-10-31 05:04:51 +0000369
DRC19c791c2018-03-08 10:55:20 -0600370 if (tjCompressFromYUVPlanes(handle, srcPlanes, width, srcStrides, height,
371 subsamp, &jpegBuf, &jpegSize, jpegQual,
372 flags | TJFLAG_NOREALLOC) == -1)
DRCd8b95102019-04-12 07:49:35 -0500373 THROW_TJ();
DRC1e672742013-10-31 05:04:51 +0000374
DRC19c791c2018-03-08 10:55:20 -0600375bailout:
376 if (jpegBuf) (*env)->ReleasePrimitiveArrayCritical(env, dst, jpegBuf, 0);
377 for (i = 0; i < nc; i++) {
378 if (srcPlanes[i] && jSrcPlanes[i])
379 (*env)->ReleasePrimitiveArrayCritical(env, jSrcPlanes[i],
380 (unsigned char *)srcPlanes[i], 0);
381 }
382 if (srcStrides)
383 (*env)->ReleasePrimitiveArrayCritical(env, jSrcStrides, srcStrides, 0);
384 if (srcOffsets)
385 (*env)->ReleasePrimitiveArrayCritical(env, jSrcOffsets, srcOffsets, 0);
386 return (jint)jpegSize;
DRC1e672742013-10-31 05:04:51 +0000387}
388
DRC5d87f6d2014-08-15 16:40:56 +0000389static void TJCompressor_encodeYUV
DRC19c791c2018-03-08 10:55:20 -0600390 (JNIEnv *env, jobject obj, jarray src, jint srcElementSize, jint x, jint y,
391 jint width, jint pitch, jint height, jint pf, jobjectArray dstobjs,
392 jintArray jDstOffsets, jintArray jDstStrides, jint subsamp, jint flags)
DRC4f1580c2011-02-25 06:11:03 +0000393{
DRC19c791c2018-03-08 10:55:20 -0600394 tjhandle handle = 0;
395 jsize arraySize = 0, actualPitch;
396 jbyteArray jDstPlanes[3] = { NULL, NULL, NULL };
397 unsigned char *srcBuf = NULL, *dstPlanes[3];
398 int *dstOffsets = NULL, *dstStrides = NULL;
399 int nc = (subsamp == org_libjpegturbo_turbojpeg_TJ_SAMP_GRAY ? 1 : 3), i;
DRC40dd3142014-08-17 12:23:49 +0000400
DRCd8b95102019-04-12 07:49:35 -0500401 GET_HANDLE();
DRC40dd3142014-08-17 12:23:49 +0000402
DRC19c791c2018-03-08 10:55:20 -0600403 if (pf < 0 || pf >= org_libjpegturbo_turbojpeg_TJ_NUMPF || width < 1 ||
404 height < 1 || pitch < 0 || subsamp < 0 ||
405 subsamp >= org_libjpegturbo_turbojpeg_TJ_NUMSAMP)
DRCd8b95102019-04-12 07:49:35 -0500406 THROW_ARG("Invalid argument in encodeYUV()");
DRC19c791c2018-03-08 10:55:20 -0600407 if (org_libjpegturbo_turbojpeg_TJ_NUMPF != TJ_NUMPF ||
408 org_libjpegturbo_turbojpeg_TJ_NUMSAMP != TJ_NUMSAMP)
DRCd8b95102019-04-12 07:49:35 -0500409 THROW_ARG("Mismatch between Java and C API");
DRC40dd3142014-08-17 12:23:49 +0000410
DRC19c791c2018-03-08 10:55:20 -0600411 if ((*env)->GetArrayLength(env, dstobjs) < nc)
DRCd8b95102019-04-12 07:49:35 -0500412 THROW_ARG("Planes array is too small for the subsampling type");
DRC19c791c2018-03-08 10:55:20 -0600413 if ((*env)->GetArrayLength(env, jDstOffsets) < nc)
DRCd8b95102019-04-12 07:49:35 -0500414 THROW_ARG("Offsets array is too small for the subsampling type");
DRC19c791c2018-03-08 10:55:20 -0600415 if ((*env)->GetArrayLength(env, jDstStrides) < nc)
DRCd8b95102019-04-12 07:49:35 -0500416 THROW_ARG("Strides array is too small for the subsampling type");
DRC40dd3142014-08-17 12:23:49 +0000417
DRC19c791c2018-03-08 10:55:20 -0600418 actualPitch = (pitch == 0) ? width * tjPixelSize[pf] : pitch;
419 arraySize = (y + height - 1) * actualPitch + (x + width) * tjPixelSize[pf];
420 if ((*env)->GetArrayLength(env, src) * srcElementSize < arraySize)
DRCd8b95102019-04-12 07:49:35 -0500421 THROW_ARG("Source buffer is not large enough");
DRC40dd3142014-08-17 12:23:49 +0000422
DRCd8b95102019-04-12 07:49:35 -0500423 BAILIF0(dstOffsets = (*env)->GetPrimitiveArrayCritical(env, jDstOffsets, 0));
424 BAILIF0(dstStrides = (*env)->GetPrimitiveArrayCritical(env, jDstStrides, 0));
DRC19c791c2018-03-08 10:55:20 -0600425 for (i = 0; i < nc; i++) {
426 int planeSize = tjPlaneSizeYUV(i, width, dstStrides[i], height, subsamp);
427 int pw = tjPlaneWidth(i, width, subsamp);
DRC40dd3142014-08-17 12:23:49 +0000428
DRC19c791c2018-03-08 10:55:20 -0600429 if (planeSize < 0 || pw < 0)
DRCd8b95102019-04-12 07:49:35 -0500430 THROW_ARG(tjGetErrorStr());
DRC40dd3142014-08-17 12:23:49 +0000431
DRC19c791c2018-03-08 10:55:20 -0600432 if (dstOffsets[i] < 0)
DRCd8b95102019-04-12 07:49:35 -0500433 THROW_ARG("Invalid argument in encodeYUV()");
DRC19c791c2018-03-08 10:55:20 -0600434 if (dstStrides[i] < 0 && dstOffsets[i] - planeSize + pw < 0)
DRCd8b95102019-04-12 07:49:35 -0500435 THROW_ARG("Negative plane stride would cause memory to be accessed below plane boundary");
DRC40dd3142014-08-17 12:23:49 +0000436
DRCd8b95102019-04-12 07:49:35 -0500437 BAILIF0(jDstPlanes[i] = (*env)->GetObjectArrayElement(env, dstobjs, i));
DRC19c791c2018-03-08 10:55:20 -0600438 if ((*env)->GetArrayLength(env, jDstPlanes[i]) < dstOffsets[i] + planeSize)
DRCd8b95102019-04-12 07:49:35 -0500439 THROW_ARG("Destination plane is not large enough");
DRC40dd3142014-08-17 12:23:49 +0000440
DRCd8b95102019-04-12 07:49:35 -0500441 BAILIF0(dstPlanes[i] =
DRC19c791c2018-03-08 10:55:20 -0600442 (*env)->GetPrimitiveArrayCritical(env, jDstPlanes[i], 0));
443 dstPlanes[i] = &dstPlanes[i][dstOffsets[i]];
444 }
DRCd8b95102019-04-12 07:49:35 -0500445 BAILIF0(srcBuf = (*env)->GetPrimitiveArrayCritical(env, src, 0));
DRC40dd3142014-08-17 12:23:49 +0000446
DRC19c791c2018-03-08 10:55:20 -0600447 if (tjEncodeYUVPlanes(handle, &srcBuf[y * actualPitch + x * tjPixelSize[pf]],
448 width, pitch, height, pf, dstPlanes, dstStrides,
449 subsamp, flags) == -1)
DRCd8b95102019-04-12 07:49:35 -0500450 THROW_TJ();
DRC40dd3142014-08-17 12:23:49 +0000451
DRC19c791c2018-03-08 10:55:20 -0600452bailout:
453 if (srcBuf) (*env)->ReleasePrimitiveArrayCritical(env, src, srcBuf, 0);
454 for (i = 0; i < nc; i++) {
455 if (dstPlanes[i] && jDstPlanes[i])
456 (*env)->ReleasePrimitiveArrayCritical(env, jDstPlanes[i], dstPlanes[i],
457 0);
458 }
459 if (dstStrides)
460 (*env)->ReleasePrimitiveArrayCritical(env, jDstStrides, dstStrides, 0);
461 if (dstOffsets)
462 (*env)->ReleasePrimitiveArrayCritical(env, jDstOffsets, dstOffsets, 0);
DRC40dd3142014-08-17 12:23:49 +0000463}
464
465/* TurboJPEG 1.4.x: TJCompressor::encodeYUV() byte source */
466JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_encodeYUV___3BIIIIII_3_3B_3I_3III
DRC19c791c2018-03-08 10:55:20 -0600467 (JNIEnv *env, jobject obj, jbyteArray src, jint x, jint y, jint width,
468 jint pitch, jint height, jint pf, jobjectArray dstobjs,
469 jintArray jDstOffsets, jintArray jDstStrides, jint subsamp, jint flags)
DRC40dd3142014-08-17 12:23:49 +0000470{
DRC19c791c2018-03-08 10:55:20 -0600471 TJCompressor_encodeYUV(env, obj, src, 1, x, y, width, pitch, height, pf,
472 dstobjs, jDstOffsets, jDstStrides, subsamp, flags);
DRC40dd3142014-08-17 12:23:49 +0000473}
474
475/* TurboJPEG 1.4.x: TJCompressor::encodeYUV() int source */
476JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_encodeYUV___3IIIIIII_3_3B_3I_3III
DRC19c791c2018-03-08 10:55:20 -0600477 (JNIEnv *env, jobject obj, jintArray src, jint x, jint y, jint width,
478 jint stride, jint height, jint pf, jobjectArray dstobjs,
479 jintArray jDstOffsets, jintArray jDstStrides, jint subsamp, jint flags)
DRC40dd3142014-08-17 12:23:49 +0000480{
DRC19c791c2018-03-08 10:55:20 -0600481 if (pf < 0 || pf >= org_libjpegturbo_turbojpeg_TJ_NUMPF)
DRCd8b95102019-04-12 07:49:35 -0500482 THROW_ARG("Invalid argument in encodeYUV()");
DRC19c791c2018-03-08 10:55:20 -0600483 if (tjPixelSize[pf] != sizeof(jint))
DRCd8b95102019-04-12 07:49:35 -0500484 THROW_ARG("Pixel format must be 32-bit when encoding from an integer buffer.");
DRC40dd3142014-08-17 12:23:49 +0000485
DRC19c791c2018-03-08 10:55:20 -0600486 TJCompressor_encodeYUV(env, obj, src, sizeof(jint), x, y, width,
487 stride * sizeof(jint), height, pf, dstobjs,
488 jDstOffsets, jDstStrides, subsamp, flags);
DRC40dd3142014-08-17 12:23:49 +0000489
DRC19c791c2018-03-08 10:55:20 -0600490bailout:
491 return;
DRC40dd3142014-08-17 12:23:49 +0000492}
493
494JNIEXPORT void JNICALL TJCompressor_encodeYUV_12
DRC19c791c2018-03-08 10:55:20 -0600495 (JNIEnv *env, jobject obj, jarray src, jint srcElementSize, jint width,
496 jint pitch, jint height, jint pf, jbyteArray dst, jint subsamp, jint flags)
DRC40dd3142014-08-17 12:23:49 +0000497{
DRC19c791c2018-03-08 10:55:20 -0600498 tjhandle handle = 0;
499 jsize arraySize = 0;
500 unsigned char *srcBuf = NULL, *dstBuf = NULL;
DRC4f1580c2011-02-25 06:11:03 +0000501
DRCd8b95102019-04-12 07:49:35 -0500502 GET_HANDLE();
DRC4f1580c2011-02-25 06:11:03 +0000503
DRC19c791c2018-03-08 10:55:20 -0600504 if (pf < 0 || pf >= org_libjpegturbo_turbojpeg_TJ_NUMPF || width < 1 ||
505 height < 1 || pitch < 0)
DRCd8b95102019-04-12 07:49:35 -0500506 THROW_ARG("Invalid argument in encodeYUV()");
DRC19c791c2018-03-08 10:55:20 -0600507 if (org_libjpegturbo_turbojpeg_TJ_NUMPF != TJ_NUMPF)
DRCd8b95102019-04-12 07:49:35 -0500508 THROW_ARG("Mismatch between Java and C API");
DRC4f1580c2011-02-25 06:11:03 +0000509
DRC19c791c2018-03-08 10:55:20 -0600510 arraySize = (pitch == 0) ? width * tjPixelSize[pf] * height : pitch * height;
511 if ((*env)->GetArrayLength(env, src) * srcElementSize < arraySize)
DRCd8b95102019-04-12 07:49:35 -0500512 THROW_ARG("Source buffer is not large enough");
DRC19c791c2018-03-08 10:55:20 -0600513 if ((*env)->GetArrayLength(env, dst) <
514 (jsize)tjBufSizeYUV(width, height, subsamp))
DRCd8b95102019-04-12 07:49:35 -0500515 THROW_ARG("Destination buffer is not large enough");
DRC6acf52b2011-03-02 01:09:20 +0000516
DRCd8b95102019-04-12 07:49:35 -0500517 BAILIF0(srcBuf = (*env)->GetPrimitiveArrayCritical(env, src, 0));
518 BAILIF0(dstBuf = (*env)->GetPrimitiveArrayCritical(env, dst, 0));
DRC4f1580c2011-02-25 06:11:03 +0000519
DRC19c791c2018-03-08 10:55:20 -0600520 if (tjEncodeYUV2(handle, srcBuf, width, pitch, height, pf, dstBuf, subsamp,
521 flags) == -1)
DRCd8b95102019-04-12 07:49:35 -0500522 THROW_TJ();
DRC4f1580c2011-02-25 06:11:03 +0000523
DRC19c791c2018-03-08 10:55:20 -0600524bailout:
525 if (dstBuf) (*env)->ReleasePrimitiveArrayCritical(env, dst, dstBuf, 0);
526 if (srcBuf) (*env)->ReleasePrimitiveArrayCritical(env, src, srcBuf, 0);
DRC4f1580c2011-02-25 06:11:03 +0000527}
528
DRCa4940d12014-08-15 16:07:15 +0000529/* TurboJPEG 1.2.x: TJCompressor::encodeYUV() byte source */
DRCfef98522013-04-28 01:32:52 +0000530JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_encodeYUV___3BIIII_3BII
DRC19c791c2018-03-08 10:55:20 -0600531 (JNIEnv *env, jobject obj, jbyteArray src, jint width, jint pitch,
532 jint height, jint pf, jbyteArray dst, jint subsamp, jint flags)
DRC4f1580c2011-02-25 06:11:03 +0000533{
DRC19c791c2018-03-08 10:55:20 -0600534 TJCompressor_encodeYUV_12(env, obj, src, 1, width, pitch, height, pf, dst,
535 subsamp, flags);
DRC4f1580c2011-02-25 06:11:03 +0000536}
537
DRCa4940d12014-08-15 16:07:15 +0000538/* TurboJPEG 1.2.x: TJCompressor::encodeYUV() int source */
DRCfef98522013-04-28 01:32:52 +0000539JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_encodeYUV___3IIIII_3BII
DRC19c791c2018-03-08 10:55:20 -0600540 (JNIEnv *env, jobject obj, jintArray src, jint width, jint stride,
541 jint height, jint pf, jbyteArray dst, jint subsamp, jint flags)
DRCfef98522013-04-28 01:32:52 +0000542{
DRC19c791c2018-03-08 10:55:20 -0600543 if (pf < 0 || pf >= org_libjpegturbo_turbojpeg_TJ_NUMPF)
DRCd8b95102019-04-12 07:49:35 -0500544 THROW_ARG("Invalid argument in encodeYUV()");
DRC19c791c2018-03-08 10:55:20 -0600545 if (tjPixelSize[pf] != sizeof(jint))
DRCd8b95102019-04-12 07:49:35 -0500546 THROW_ARG("Pixel format must be 32-bit when encoding from an integer buffer.");
DRC927a10d2014-08-15 13:18:58 +0000547
DRC19c791c2018-03-08 10:55:20 -0600548 TJCompressor_encodeYUV_12(env, obj, src, sizeof(jint), width,
549 stride * sizeof(jint), height, pf, dst, subsamp,
550 flags);
DRC927a10d2014-08-15 13:18:58 +0000551
DRC19c791c2018-03-08 10:55:20 -0600552bailout:
553 return;
DRCfef98522013-04-28 01:32:52 +0000554}
555
DRCa4940d12014-08-15 16:07:15 +0000556/* TurboJPEG 1.2.x: TJCompressor::destroy() */
DRCc5a41992011-02-08 06:54:36 +0000557JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_destroy
DRC19c791c2018-03-08 10:55:20 -0600558 (JNIEnv *env, jobject obj)
DRCf8e00552011-02-04 11:06:36 +0000559{
DRC19c791c2018-03-08 10:55:20 -0600560 tjhandle handle = 0;
DRCf8e00552011-02-04 11:06:36 +0000561
DRCd8b95102019-04-12 07:49:35 -0500562 GET_HANDLE();
DRCf8e00552011-02-04 11:06:36 +0000563
DRCd8b95102019-04-12 07:49:35 -0500564 if (tjDestroy(handle) == -1) THROW_TJ();
DRC19c791c2018-03-08 10:55:20 -0600565 (*env)->SetLongField(env, obj, _fid, 0);
DRCf8e00552011-02-04 11:06:36 +0000566
DRC19c791c2018-03-08 10:55:20 -0600567bailout:
568 return;
DRCf8e00552011-02-04 11:06:36 +0000569}
570
DRCa4940d12014-08-15 16:07:15 +0000571/* TurboJPEG 1.2.x: TJDecompressor::init() */
DRCc5a41992011-02-08 06:54:36 +0000572JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_init
DRC19c791c2018-03-08 10:55:20 -0600573 (JNIEnv *env, jobject obj)
DRCf8e00552011-02-04 11:06:36 +0000574{
DRC19c791c2018-03-08 10:55:20 -0600575 jclass cls;
576 jfieldID fid;
577 tjhandle handle;
DRCf8e00552011-02-04 11:06:36 +0000578
DRC19c791c2018-03-08 10:55:20 -0600579 if ((handle = tjInitDecompress()) == NULL)
DRCd8b95102019-04-12 07:49:35 -0500580 THROW(tjGetErrorStr(), "org/libjpegturbo/turbojpeg/TJException");
DRCf8e00552011-02-04 11:06:36 +0000581
DRCd8b95102019-04-12 07:49:35 -0500582 BAILIF0(cls = (*env)->GetObjectClass(env, obj));
583 BAILIF0(fid = (*env)->GetFieldID(env, cls, "handle", "J"));
DRC19c791c2018-03-08 10:55:20 -0600584 (*env)->SetLongField(env, obj, fid, (size_t)handle);
DRCf8e00552011-02-04 11:06:36 +0000585
DRC19c791c2018-03-08 10:55:20 -0600586bailout:
587 return;
DRCf8e00552011-02-04 11:06:36 +0000588}
589
DRCa4940d12014-08-15 16:07:15 +0000590/* TurboJPEG 1.2.x: TJDecompressor::getScalingFactors() */
DRC109a5782011-03-01 09:53:07 +0000591JNIEXPORT jobjectArray JNICALL Java_org_libjpegturbo_turbojpeg_TJ_getScalingFactors
DRC19c791c2018-03-08 10:55:20 -0600592 (JNIEnv *env, jclass cls)
DRC36336fc2011-02-22 10:27:31 +0000593{
DRC19c791c2018-03-08 10:55:20 -0600594 jclass sfcls = NULL;
595 jfieldID fid = 0;
596 tjscalingfactor *sf = NULL;
597 int n = 0, i;
598 jobject sfobj = NULL;
599 jobjectArray sfjava = NULL;
DRC109a5782011-03-01 09:53:07 +0000600
DRC19c791c2018-03-08 10:55:20 -0600601 if ((sf = tjGetScalingFactors(&n)) == NULL || n == 0)
DRCd8b95102019-04-12 07:49:35 -0500602 THROW_ARG(tjGetErrorStr());
DRC36336fc2011-02-22 10:27:31 +0000603
DRCd8b95102019-04-12 07:49:35 -0500604 BAILIF0(sfcls = (*env)->FindClass(env,
DRC19c791c2018-03-08 10:55:20 -0600605 "org/libjpegturbo/turbojpeg/TJScalingFactor"));
DRCd8b95102019-04-12 07:49:35 -0500606 BAILIF0(sfjava = (jobjectArray)(*env)->NewObjectArray(env, n, sfcls, 0));
DRC36336fc2011-02-22 10:27:31 +0000607
DRC19c791c2018-03-08 10:55:20 -0600608 for (i = 0; i < n; i++) {
DRCd8b95102019-04-12 07:49:35 -0500609 BAILIF0(sfobj = (*env)->AllocObject(env, sfcls));
610 BAILIF0(fid = (*env)->GetFieldID(env, sfcls, "num", "I"));
DRC19c791c2018-03-08 10:55:20 -0600611 (*env)->SetIntField(env, sfobj, fid, sf[i].num);
DRCd8b95102019-04-12 07:49:35 -0500612 BAILIF0(fid = (*env)->GetFieldID(env, sfcls, "denom", "I"));
DRC19c791c2018-03-08 10:55:20 -0600613 (*env)->SetIntField(env, sfobj, fid, sf[i].denom);
614 (*env)->SetObjectArrayElement(env, sfjava, i, sfobj);
615 }
DRC36336fc2011-02-22 10:27:31 +0000616
DRC19c791c2018-03-08 10:55:20 -0600617bailout:
618 return sfjava;
DRC36336fc2011-02-22 10:27:31 +0000619}
620
DRCa4940d12014-08-15 16:07:15 +0000621/* TurboJPEG 1.2.x: TJDecompressor::decompressHeader() */
DRC3bad53f2011-02-23 02:20:49 +0000622JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompressHeader
DRC19c791c2018-03-08 10:55:20 -0600623 (JNIEnv *env, jobject obj, jbyteArray src, jint jpegSize)
DRCf8e00552011-02-04 11:06:36 +0000624{
DRC19c791c2018-03-08 10:55:20 -0600625 tjhandle handle = 0;
626 unsigned char *jpegBuf = NULL;
627 int width = 0, height = 0, jpegSubsamp = -1, jpegColorspace = -1;
DRCf8e00552011-02-04 11:06:36 +0000628
DRCd8b95102019-04-12 07:49:35 -0500629 GET_HANDLE();
DRCf8e00552011-02-04 11:06:36 +0000630
DRC19c791c2018-03-08 10:55:20 -0600631 if ((*env)->GetArrayLength(env, src) < jpegSize)
DRCd8b95102019-04-12 07:49:35 -0500632 THROW_ARG("Source buffer is not large enough");
DRC6acf52b2011-03-02 01:09:20 +0000633
DRCd8b95102019-04-12 07:49:35 -0500634 BAILIF0(jpegBuf = (*env)->GetPrimitiveArrayCritical(env, src, 0));
DRCf8e00552011-02-04 11:06:36 +0000635
DRC19c791c2018-03-08 10:55:20 -0600636 if (tjDecompressHeader3(handle, jpegBuf, (unsigned long)jpegSize, &width,
637 &height, &jpegSubsamp, &jpegColorspace) == -1)
DRCd8b95102019-04-12 07:49:35 -0500638 THROW_TJ();
DRC8951cf02014-08-14 16:54:04 +0000639
DRC19c791c2018-03-08 10:55:20 -0600640 (*env)->ReleasePrimitiveArrayCritical(env, src, jpegBuf, 0);
641 jpegBuf = NULL;
DRCf8e00552011-02-04 11:06:36 +0000642
DRCd8b95102019-04-12 07:49:35 -0500643 BAILIF0(_fid = (*env)->GetFieldID(env, _cls, "jpegSubsamp", "I"));
DRC19c791c2018-03-08 10:55:20 -0600644 (*env)->SetIntField(env, obj, _fid, jpegSubsamp);
645 if ((_fid = (*env)->GetFieldID(env, _cls, "jpegColorspace", "I")) == 0)
646 (*env)->ExceptionClear(env);
647 else
648 (*env)->SetIntField(env, obj, _fid, jpegColorspace);
DRCd8b95102019-04-12 07:49:35 -0500649 BAILIF0(_fid = (*env)->GetFieldID(env, _cls, "jpegWidth", "I"));
DRC19c791c2018-03-08 10:55:20 -0600650 (*env)->SetIntField(env, obj, _fid, width);
DRCd8b95102019-04-12 07:49:35 -0500651 BAILIF0(_fid = (*env)->GetFieldID(env, _cls, "jpegHeight", "I"));
DRC19c791c2018-03-08 10:55:20 -0600652 (*env)->SetIntField(env, obj, _fid, height);
DRCf8e00552011-02-04 11:06:36 +0000653
DRC19c791c2018-03-08 10:55:20 -0600654bailout:
655 if (jpegBuf) (*env)->ReleasePrimitiveArrayCritical(env, src, jpegBuf, 0);
DRCf8e00552011-02-04 11:06:36 +0000656}
657
DRC5d87f6d2014-08-15 16:40:56 +0000658static void TJDecompressor_decompress
DRC19c791c2018-03-08 10:55:20 -0600659 (JNIEnv *env, jobject obj, jbyteArray src, jint jpegSize, jarray dst,
660 jint dstElementSize, jint x, jint y, jint width, jint pitch, jint height,
661 jint pf, jint flags)
DRCf8e00552011-02-04 11:06:36 +0000662{
DRC19c791c2018-03-08 10:55:20 -0600663 tjhandle handle = 0;
664 jsize arraySize = 0, actualPitch;
665 unsigned char *jpegBuf = NULL, *dstBuf = NULL;
DRCf8e00552011-02-04 11:06:36 +0000666
DRCd8b95102019-04-12 07:49:35 -0500667 GET_HANDLE();
DRCf8e00552011-02-04 11:06:36 +0000668
DRC19c791c2018-03-08 10:55:20 -0600669 if (pf < 0 || pf >= org_libjpegturbo_turbojpeg_TJ_NUMPF)
DRCd8b95102019-04-12 07:49:35 -0500670 THROW_ARG("Invalid argument in decompress()");
DRC19c791c2018-03-08 10:55:20 -0600671 if (org_libjpegturbo_turbojpeg_TJ_NUMPF != TJ_NUMPF)
DRCd8b95102019-04-12 07:49:35 -0500672 THROW_ARG("Mismatch between Java and C API");
DRC4f1580c2011-02-25 06:11:03 +0000673
DRC19c791c2018-03-08 10:55:20 -0600674 if ((*env)->GetArrayLength(env, src) < jpegSize)
DRCd8b95102019-04-12 07:49:35 -0500675 THROW_ARG("Source buffer is not large enough");
DRC19c791c2018-03-08 10:55:20 -0600676 actualPitch = (pitch == 0) ? width * tjPixelSize[pf] : pitch;
677 arraySize = (y + height - 1) * actualPitch + (x + width) * tjPixelSize[pf];
678 if ((*env)->GetArrayLength(env, dst) * dstElementSize < arraySize)
DRCd8b95102019-04-12 07:49:35 -0500679 THROW_ARG("Destination buffer is not large enough");
DRC6acf52b2011-03-02 01:09:20 +0000680
DRCd8b95102019-04-12 07:49:35 -0500681 BAILIF0(jpegBuf = (*env)->GetPrimitiveArrayCritical(env, src, 0));
682 BAILIF0(dstBuf = (*env)->GetPrimitiveArrayCritical(env, dst, 0));
DRCf8e00552011-02-04 11:06:36 +0000683
DRC19c791c2018-03-08 10:55:20 -0600684 if (tjDecompress2(handle, jpegBuf, (unsigned long)jpegSize,
685 &dstBuf[y * actualPitch + x * tjPixelSize[pf]], width,
686 pitch, height, pf, flags) == -1)
DRCd8b95102019-04-12 07:49:35 -0500687 THROW_TJ();
DRCf659f432012-06-06 08:41:06 +0000688
DRC19c791c2018-03-08 10:55:20 -0600689bailout:
690 if (dstBuf) (*env)->ReleasePrimitiveArrayCritical(env, dst, dstBuf, 0);
691 if (jpegBuf) (*env)->ReleasePrimitiveArrayCritical(env, src, jpegBuf, 0);
DRCf659f432012-06-06 08:41:06 +0000692}
693
DRCa4940d12014-08-15 16:07:15 +0000694/* TurboJPEG 1.3.x: TJDecompressor::decompress() byte destination */
DRC927a10d2014-08-15 13:18:58 +0000695JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompress___3BI_3BIIIIIII
DRC19c791c2018-03-08 10:55:20 -0600696 (JNIEnv *env, jobject obj, jbyteArray src, jint jpegSize, jbyteArray dst,
697 jint x, jint y, jint width, jint pitch, jint height, jint pf, jint flags)
DRC927a10d2014-08-15 13:18:58 +0000698{
DRC19c791c2018-03-08 10:55:20 -0600699 TJDecompressor_decompress(env, obj, src, jpegSize, dst, 1, x, y, width,
700 pitch, height, pf, flags);
DRC927a10d2014-08-15 13:18:58 +0000701}
702
DRCa4940d12014-08-15 16:07:15 +0000703/* TurboJPEG 1.2.x: TJDecompressor::decompress() byte destination */
DRCf659f432012-06-06 08:41:06 +0000704JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompress___3BI_3BIIIII
DRC19c791c2018-03-08 10:55:20 -0600705 (JNIEnv *env, jobject obj, jbyteArray src, jint jpegSize, jbyteArray dst,
706 jint width, jint pitch, jint height, jint pf, jint flags)
DRCf659f432012-06-06 08:41:06 +0000707{
DRC19c791c2018-03-08 10:55:20 -0600708 TJDecompressor_decompress(env, obj, src, jpegSize, dst, 1, 0, 0, width,
709 pitch, height, pf, flags);
DRCf659f432012-06-06 08:41:06 +0000710}
711
DRCa4940d12014-08-15 16:07:15 +0000712/* TurboJPEG 1.3.x: TJDecompressor::decompress() int destination */
DRCf659f432012-06-06 08:41:06 +0000713JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompress___3BI_3IIIIIIII
DRC19c791c2018-03-08 10:55:20 -0600714 (JNIEnv *env, jobject obj, jbyteArray src, jint jpegSize, jintArray dst,
715 jint x, jint y, jint width, jint stride, jint height, jint pf, jint flags)
DRCf659f432012-06-06 08:41:06 +0000716{
DRC19c791c2018-03-08 10:55:20 -0600717 if (pf < 0 || pf >= org_libjpegturbo_turbojpeg_TJ_NUMPF)
DRCd8b95102019-04-12 07:49:35 -0500718 THROW_ARG("Invalid argument in decompress()");
DRC19c791c2018-03-08 10:55:20 -0600719 if (tjPixelSize[pf] != sizeof(jint))
DRCd8b95102019-04-12 07:49:35 -0500720 THROW_ARG("Pixel format must be 32-bit when decompressing to an integer buffer.");
DRCf659f432012-06-06 08:41:06 +0000721
DRC19c791c2018-03-08 10:55:20 -0600722 TJDecompressor_decompress(env, obj, src, jpegSize, dst, sizeof(jint), x, y,
723 width, stride * sizeof(jint), height, pf, flags);
DRCf8e00552011-02-04 11:06:36 +0000724
DRC19c791c2018-03-08 10:55:20 -0600725bailout:
726 return;
DRCf8e00552011-02-04 11:06:36 +0000727}
728
DRCa4940d12014-08-15 16:07:15 +0000729/* TurboJPEG 1.2.x: TJDecompressor::decompress() int destination */
DRC4f1580c2011-02-25 06:11:03 +0000730JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompress___3BI_3IIIIII
DRC19c791c2018-03-08 10:55:20 -0600731 (JNIEnv *env, jobject obj, jbyteArray src, jint jpegSize, jintArray dst,
732 jint width, jint stride, jint height, jint pf, jint flags)
DRC84a1bcc2011-02-23 12:09:56 +0000733{
DRC19c791c2018-03-08 10:55:20 -0600734 if (pf < 0 || pf >= org_libjpegturbo_turbojpeg_TJ_NUMPF)
DRCd8b95102019-04-12 07:49:35 -0500735 THROW_ARG("Invalid argument in decompress()");
DRC19c791c2018-03-08 10:55:20 -0600736 if (tjPixelSize[pf] != sizeof(jint))
DRCd8b95102019-04-12 07:49:35 -0500737 THROW_ARG("Pixel format must be 32-bit when decompressing to an integer buffer.");
DRC927a10d2014-08-15 13:18:58 +0000738
DRC19c791c2018-03-08 10:55:20 -0600739 TJDecompressor_decompress(env, obj, src, jpegSize, dst, sizeof(jint), 0, 0,
740 width, stride * sizeof(jint), height, pf, flags);
DRC927a10d2014-08-15 13:18:58 +0000741
DRC19c791c2018-03-08 10:55:20 -0600742bailout:
743 return;
DRC4f1580c2011-02-25 06:11:03 +0000744}
DRC84a1bcc2011-02-23 12:09:56 +0000745
DRCa4940d12014-08-15 16:07:15 +0000746/* TurboJPEG 1.4.x: TJDecompressor::decompressToYUV() */
DRC40dd3142014-08-17 12:23:49 +0000747JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompressToYUV___3BI_3_3B_3II_3III
DRC19c791c2018-03-08 10:55:20 -0600748 (JNIEnv *env, jobject obj, jbyteArray src, jint jpegSize,
749 jobjectArray dstobjs, jintArray jDstOffsets, jint desiredWidth,
750 jintArray jDstStrides, jint desiredHeight, jint flags)
DRC4f1580c2011-02-25 06:11:03 +0000751{
DRC19c791c2018-03-08 10:55:20 -0600752 tjhandle handle = 0;
753 jbyteArray jDstPlanes[3] = { NULL, NULL, NULL };
754 unsigned char *jpegBuf = NULL, *dstPlanes[3];
755 int *dstOffsets = NULL, *dstStrides = NULL;
756 int jpegSubsamp = -1, jpegWidth = 0, jpegHeight = 0;
757 int nc = 0, i, width, height, scaledWidth, scaledHeight, nsf = 0;
758 tjscalingfactor *sf;
DRC40dd3142014-08-17 12:23:49 +0000759
DRCd8b95102019-04-12 07:49:35 -0500760 GET_HANDLE();
DRC4f1580c2011-02-25 06:11:03 +0000761
DRC19c791c2018-03-08 10:55:20 -0600762 if ((*env)->GetArrayLength(env, src) < jpegSize)
DRCd8b95102019-04-12 07:49:35 -0500763 THROW_ARG("Source buffer is not large enough");
764 BAILIF0(_fid = (*env)->GetFieldID(env, _cls, "jpegSubsamp", "I"));
DRC19c791c2018-03-08 10:55:20 -0600765 jpegSubsamp = (int)(*env)->GetIntField(env, obj, _fid);
DRCd8b95102019-04-12 07:49:35 -0500766 BAILIF0(_fid = (*env)->GetFieldID(env, _cls, "jpegWidth", "I"));
DRC19c791c2018-03-08 10:55:20 -0600767 jpegWidth = (int)(*env)->GetIntField(env, obj, _fid);
DRCd8b95102019-04-12 07:49:35 -0500768 BAILIF0(_fid = (*env)->GetFieldID(env, _cls, "jpegHeight", "I"));
DRC19c791c2018-03-08 10:55:20 -0600769 jpegHeight = (int)(*env)->GetIntField(env, obj, _fid);
DRC4f1580c2011-02-25 06:11:03 +0000770
DRC19c791c2018-03-08 10:55:20 -0600771 nc = (jpegSubsamp == org_libjpegturbo_turbojpeg_TJ_SAMP_GRAY ? 1 : 3);
DRC6acf52b2011-03-02 01:09:20 +0000772
DRC19c791c2018-03-08 10:55:20 -0600773 width = desiredWidth;
774 height = desiredHeight;
775 if (width == 0) width = jpegWidth;
776 if (height == 0) height = jpegHeight;
777 sf = tjGetScalingFactors(&nsf);
778 if (!sf || nsf < 1)
DRCd8b95102019-04-12 07:49:35 -0500779 THROW_ARG(tjGetErrorStr());
DRC19c791c2018-03-08 10:55:20 -0600780 for (i = 0; i < nsf; i++) {
781 scaledWidth = TJSCALED(jpegWidth, sf[i]);
782 scaledHeight = TJSCALED(jpegHeight, sf[i]);
783 if (scaledWidth <= width && scaledHeight <= height)
784 break;
785 }
786 if (i >= nsf)
DRCd8b95102019-04-12 07:49:35 -0500787 THROW_ARG("Could not scale down to desired image dimensions");
DRC4f1580c2011-02-25 06:11:03 +0000788
DRCd8b95102019-04-12 07:49:35 -0500789 BAILIF0(dstOffsets = (*env)->GetPrimitiveArrayCritical(env, jDstOffsets, 0));
790 BAILIF0(dstStrides = (*env)->GetPrimitiveArrayCritical(env, jDstStrides, 0));
DRC19c791c2018-03-08 10:55:20 -0600791 for (i = 0; i < nc; i++) {
792 int planeSize = tjPlaneSizeYUV(i, scaledWidth, dstStrides[i], scaledHeight,
793 jpegSubsamp);
794 int pw = tjPlaneWidth(i, scaledWidth, jpegSubsamp);
DRC40dd3142014-08-17 12:23:49 +0000795
DRC19c791c2018-03-08 10:55:20 -0600796 if (planeSize < 0 || pw < 0)
DRCd8b95102019-04-12 07:49:35 -0500797 THROW_ARG(tjGetErrorStr());
DRC40dd3142014-08-17 12:23:49 +0000798
DRC19c791c2018-03-08 10:55:20 -0600799 if (dstOffsets[i] < 0)
DRCd8b95102019-04-12 07:49:35 -0500800 THROW_ARG("Invalid argument in decompressToYUV()");
DRC19c791c2018-03-08 10:55:20 -0600801 if (dstStrides[i] < 0 && dstOffsets[i] - planeSize + pw < 0)
DRCd8b95102019-04-12 07:49:35 -0500802 THROW_ARG("Negative plane stride would cause memory to be accessed below plane boundary");
DRC40dd3142014-08-17 12:23:49 +0000803
DRCd8b95102019-04-12 07:49:35 -0500804 BAILIF0(jDstPlanes[i] = (*env)->GetObjectArrayElement(env, dstobjs, i));
DRC19c791c2018-03-08 10:55:20 -0600805 if ((*env)->GetArrayLength(env, jDstPlanes[i]) < dstOffsets[i] + planeSize)
DRCd8b95102019-04-12 07:49:35 -0500806 THROW_ARG("Destination plane is not large enough");
DRC40dd3142014-08-17 12:23:49 +0000807
DRCd8b95102019-04-12 07:49:35 -0500808 BAILIF0(dstPlanes[i] =
DRC19c791c2018-03-08 10:55:20 -0600809 (*env)->GetPrimitiveArrayCritical(env, jDstPlanes[i], 0));
810 dstPlanes[i] = &dstPlanes[i][dstOffsets[i]];
811 }
DRCd8b95102019-04-12 07:49:35 -0500812 BAILIF0(jpegBuf = (*env)->GetPrimitiveArrayCritical(env, src, 0));
DRC40dd3142014-08-17 12:23:49 +0000813
DRC19c791c2018-03-08 10:55:20 -0600814 if (tjDecompressToYUVPlanes(handle, jpegBuf, (unsigned long)jpegSize,
815 dstPlanes, desiredWidth, dstStrides,
816 desiredHeight, flags) == -1)
DRCd8b95102019-04-12 07:49:35 -0500817 THROW_TJ();
DRC40dd3142014-08-17 12:23:49 +0000818
DRC19c791c2018-03-08 10:55:20 -0600819bailout:
820 if (jpegBuf) (*env)->ReleasePrimitiveArrayCritical(env, src, jpegBuf, 0);
821 for (i = 0; i < nc; i++) {
822 if (dstPlanes[i] && jDstPlanes[i])
823 (*env)->ReleasePrimitiveArrayCritical(env, jDstPlanes[i], dstPlanes[i],
824 0);
825 }
826 if (dstStrides)
827 (*env)->ReleasePrimitiveArrayCritical(env, jDstStrides, dstStrides, 0);
828 if (dstOffsets)
829 (*env)->ReleasePrimitiveArrayCritical(env, jDstOffsets, dstOffsets, 0);
DRC84a1bcc2011-02-23 12:09:56 +0000830}
831
DRCa4940d12014-08-15 16:07:15 +0000832/* TurboJPEG 1.2.x: TJDecompressor::decompressToYUV() */
DRCfef98522013-04-28 01:32:52 +0000833JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompressToYUV___3BI_3BI
DRC19c791c2018-03-08 10:55:20 -0600834 (JNIEnv *env, jobject obj, jbyteArray src, jint jpegSize, jbyteArray dst,
835 jint flags)
DRCfef98522013-04-28 01:32:52 +0000836{
DRC19c791c2018-03-08 10:55:20 -0600837 tjhandle handle = 0;
838 unsigned char *jpegBuf = NULL, *dstBuf = NULL;
839 int jpegSubsamp = -1, jpegWidth = 0, jpegHeight = 0;
DRCfc26b652014-03-16 22:56:26 +0000840
DRCd8b95102019-04-12 07:49:35 -0500841 GET_HANDLE();
DRCfc26b652014-03-16 22:56:26 +0000842
DRC19c791c2018-03-08 10:55:20 -0600843 if ((*env)->GetArrayLength(env, src) < jpegSize)
DRCd8b95102019-04-12 07:49:35 -0500844 THROW_ARG("Source buffer is not large enough");
845 BAILIF0(_fid = (*env)->GetFieldID(env, _cls, "jpegSubsamp", "I"));
DRC19c791c2018-03-08 10:55:20 -0600846 jpegSubsamp = (int)(*env)->GetIntField(env, obj, _fid);
DRCd8b95102019-04-12 07:49:35 -0500847 BAILIF0(_fid = (*env)->GetFieldID(env, _cls, "jpegWidth", "I"));
DRC19c791c2018-03-08 10:55:20 -0600848 jpegWidth = (int)(*env)->GetIntField(env, obj, _fid);
DRCd8b95102019-04-12 07:49:35 -0500849 BAILIF0(_fid = (*env)->GetFieldID(env, _cls, "jpegHeight", "I"));
DRC19c791c2018-03-08 10:55:20 -0600850 jpegHeight = (int)(*env)->GetIntField(env, obj, _fid);
851 if ((*env)->GetArrayLength(env, dst) <
852 (jsize)tjBufSizeYUV(jpegWidth, jpegHeight, jpegSubsamp))
DRCd8b95102019-04-12 07:49:35 -0500853 THROW_ARG("Destination buffer is not large enough");
DRC40dd3142014-08-17 12:23:49 +0000854
DRCd8b95102019-04-12 07:49:35 -0500855 BAILIF0(jpegBuf = (*env)->GetPrimitiveArrayCritical(env, src, 0));
856 BAILIF0(dstBuf = (*env)->GetPrimitiveArrayCritical(env, dst, 0));
DRC40dd3142014-08-17 12:23:49 +0000857
DRC19c791c2018-03-08 10:55:20 -0600858 if (tjDecompressToYUV(handle, jpegBuf, (unsigned long)jpegSize, dstBuf,
859 flags) == -1)
DRCd8b95102019-04-12 07:49:35 -0500860 THROW_TJ();
DRC40dd3142014-08-17 12:23:49 +0000861
DRC19c791c2018-03-08 10:55:20 -0600862bailout:
863 if (dstBuf) (*env)->ReleasePrimitiveArrayCritical(env, dst, dstBuf, 0);
864 if (jpegBuf) (*env)->ReleasePrimitiveArrayCritical(env, src, jpegBuf, 0);
DRC40dd3142014-08-17 12:23:49 +0000865}
866
867static void TJDecompressor_decodeYUV
DRC19c791c2018-03-08 10:55:20 -0600868 (JNIEnv *env, jobject obj, jobjectArray srcobjs, jintArray jSrcOffsets,
869 jintArray jSrcStrides, jint subsamp, jarray dst, jint dstElementSize,
870 jint x, jint y, jint width, jint pitch, jint height, jint pf, jint flags)
DRC40dd3142014-08-17 12:23:49 +0000871{
DRC19c791c2018-03-08 10:55:20 -0600872 tjhandle handle = 0;
873 jsize arraySize = 0, actualPitch;
874 jbyteArray jSrcPlanes[3] = { NULL, NULL, NULL };
875 const unsigned char *srcPlanes[3];
876 unsigned char *dstBuf = NULL;
877 int *srcOffsets = NULL, *srcStrides = NULL;
878 int nc = (subsamp == org_libjpegturbo_turbojpeg_TJ_SAMP_GRAY ? 1 : 3), i;
DRC40dd3142014-08-17 12:23:49 +0000879
DRCd8b95102019-04-12 07:49:35 -0500880 GET_HANDLE();
DRC40dd3142014-08-17 12:23:49 +0000881
DRC19c791c2018-03-08 10:55:20 -0600882 if (pf < 0 || pf >= org_libjpegturbo_turbojpeg_TJ_NUMPF || subsamp < 0 ||
883 subsamp >= org_libjpegturbo_turbojpeg_TJ_NUMSAMP)
DRCd8b95102019-04-12 07:49:35 -0500884 THROW_ARG("Invalid argument in decodeYUV()");
DRC19c791c2018-03-08 10:55:20 -0600885 if (org_libjpegturbo_turbojpeg_TJ_NUMPF != TJ_NUMPF ||
886 org_libjpegturbo_turbojpeg_TJ_NUMSAMP != TJ_NUMSAMP)
DRCd8b95102019-04-12 07:49:35 -0500887 THROW_ARG("Mismatch between Java and C API");
DRCfc26b652014-03-16 22:56:26 +0000888
DRC19c791c2018-03-08 10:55:20 -0600889 if ((*env)->GetArrayLength(env, srcobjs) < nc)
DRCd8b95102019-04-12 07:49:35 -0500890 THROW_ARG("Planes array is too small for the subsampling type");
DRC19c791c2018-03-08 10:55:20 -0600891 if ((*env)->GetArrayLength(env, jSrcOffsets) < nc)
DRCd8b95102019-04-12 07:49:35 -0500892 THROW_ARG("Offsets array is too small for the subsampling type");
DRC19c791c2018-03-08 10:55:20 -0600893 if ((*env)->GetArrayLength(env, jSrcStrides) < nc)
DRCd8b95102019-04-12 07:49:35 -0500894 THROW_ARG("Strides array is too small for the subsampling type");
DRC40dd3142014-08-17 12:23:49 +0000895
DRC19c791c2018-03-08 10:55:20 -0600896 actualPitch = (pitch == 0) ? width * tjPixelSize[pf] : pitch;
897 arraySize = (y + height - 1) * actualPitch + (x + width) * tjPixelSize[pf];
898 if ((*env)->GetArrayLength(env, dst) * dstElementSize < arraySize)
DRCd8b95102019-04-12 07:49:35 -0500899 THROW_ARG("Destination buffer is not large enough");
DRCfc26b652014-03-16 22:56:26 +0000900
DRCd8b95102019-04-12 07:49:35 -0500901 BAILIF0(srcOffsets = (*env)->GetPrimitiveArrayCritical(env, jSrcOffsets, 0));
902 BAILIF0(srcStrides = (*env)->GetPrimitiveArrayCritical(env, jSrcStrides, 0));
DRC19c791c2018-03-08 10:55:20 -0600903 for (i = 0; i < nc; i++) {
904 int planeSize = tjPlaneSizeYUV(i, width, srcStrides[i], height, subsamp);
905 int pw = tjPlaneWidth(i, width, subsamp);
DRC40dd3142014-08-17 12:23:49 +0000906
DRC19c791c2018-03-08 10:55:20 -0600907 if (planeSize < 0 || pw < 0)
DRCd8b95102019-04-12 07:49:35 -0500908 THROW_ARG(tjGetErrorStr());
DRC40dd3142014-08-17 12:23:49 +0000909
DRC19c791c2018-03-08 10:55:20 -0600910 if (srcOffsets[i] < 0)
DRCd8b95102019-04-12 07:49:35 -0500911 THROW_ARG("Invalid argument in decodeYUV()");
DRC19c791c2018-03-08 10:55:20 -0600912 if (srcStrides[i] < 0 && srcOffsets[i] - planeSize + pw < 0)
DRCd8b95102019-04-12 07:49:35 -0500913 THROW_ARG("Negative plane stride would cause memory to be accessed below plane boundary");
DRC40dd3142014-08-17 12:23:49 +0000914
DRCd8b95102019-04-12 07:49:35 -0500915 BAILIF0(jSrcPlanes[i] = (*env)->GetObjectArrayElement(env, srcobjs, i));
DRC19c791c2018-03-08 10:55:20 -0600916 if ((*env)->GetArrayLength(env, jSrcPlanes[i]) < srcOffsets[i] + planeSize)
DRCd8b95102019-04-12 07:49:35 -0500917 THROW_ARG("Source plane is not large enough");
DRC40dd3142014-08-17 12:23:49 +0000918
DRCd8b95102019-04-12 07:49:35 -0500919 BAILIF0(srcPlanes[i] =
DRC19c791c2018-03-08 10:55:20 -0600920 (*env)->GetPrimitiveArrayCritical(env, jSrcPlanes[i], 0));
921 srcPlanes[i] = &srcPlanes[i][srcOffsets[i]];
922 }
DRCd8b95102019-04-12 07:49:35 -0500923 BAILIF0(dstBuf = (*env)->GetPrimitiveArrayCritical(env, dst, 0));
DRCfc26b652014-03-16 22:56:26 +0000924
DRC19c791c2018-03-08 10:55:20 -0600925 if (tjDecodeYUVPlanes(handle, srcPlanes, srcStrides, subsamp,
926 &dstBuf[y * actualPitch + x * tjPixelSize[pf]], width,
927 pitch, height, pf, flags) == -1)
DRCd8b95102019-04-12 07:49:35 -0500928 THROW_TJ();
DRCfc26b652014-03-16 22:56:26 +0000929
DRC19c791c2018-03-08 10:55:20 -0600930bailout:
931 if (dstBuf) (*env)->ReleasePrimitiveArrayCritical(env, dst, dstBuf, 0);
932 for (i = 0; i < nc; i++) {
933 if (srcPlanes[i] && jSrcPlanes[i])
934 (*env)->ReleasePrimitiveArrayCritical(env, jSrcPlanes[i],
935 (unsigned char *)srcPlanes[i], 0);
936 }
937 if (srcStrides)
938 (*env)->ReleasePrimitiveArrayCritical(env, jSrcStrides, srcStrides, 0);
939 if (srcOffsets)
940 (*env)->ReleasePrimitiveArrayCritical(env, jSrcOffsets, srcOffsets, 0);
DRCfc26b652014-03-16 22:56:26 +0000941}
942
DRCa4940d12014-08-15 16:07:15 +0000943/* TurboJPEG 1.4.x: TJDecompressor::decodeYUV() byte destination */
DRC40dd3142014-08-17 12:23:49 +0000944JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decodeYUV___3_3B_3I_3II_3BIIIIIII
DRC19c791c2018-03-08 10:55:20 -0600945 (JNIEnv *env, jobject obj, jobjectArray srcobjs, jintArray jSrcOffsets,
946 jintArray jSrcStrides, jint subsamp, jbyteArray dst, jint x, jint y,
947 jint width, jint pitch, jint height, jint pf, jint flags)
DRC927a10d2014-08-15 13:18:58 +0000948{
DRC19c791c2018-03-08 10:55:20 -0600949 TJDecompressor_decodeYUV(env, obj, srcobjs, jSrcOffsets, jSrcStrides,
950 subsamp, dst, 1, x, y, width, pitch, height, pf,
951 flags);
DRC927a10d2014-08-15 13:18:58 +0000952}
953
DRCa4940d12014-08-15 16:07:15 +0000954/* TurboJPEG 1.4.x: TJDecompressor::decodeYUV() int destination */
DRC40dd3142014-08-17 12:23:49 +0000955JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decodeYUV___3_3B_3I_3II_3IIIIIIII
DRC19c791c2018-03-08 10:55:20 -0600956 (JNIEnv *env, jobject obj, jobjectArray srcobjs, jintArray jSrcOffsets,
957 jintArray jSrcStrides, jint subsamp, jintArray dst, jint x, jint y,
958 jint width, jint stride, jint height, jint pf, jint flags)
DRCfc26b652014-03-16 22:56:26 +0000959{
DRC19c791c2018-03-08 10:55:20 -0600960 if (pf < 0 || pf >= org_libjpegturbo_turbojpeg_TJ_NUMPF)
DRCd8b95102019-04-12 07:49:35 -0500961 THROW_ARG("Invalid argument in decodeYUV()");
DRC19c791c2018-03-08 10:55:20 -0600962 if (tjPixelSize[pf] != sizeof(jint))
DRCd8b95102019-04-12 07:49:35 -0500963 THROW_ARG("Pixel format must be 32-bit when decoding to an integer buffer.");
DRCfc26b652014-03-16 22:56:26 +0000964
DRC19c791c2018-03-08 10:55:20 -0600965 TJDecompressor_decodeYUV(env, obj, srcobjs, jSrcOffsets, jSrcStrides,
966 subsamp, dst, sizeof(jint), x, y, width,
967 stride * sizeof(jint), height, pf, flags);
DRCfc26b652014-03-16 22:56:26 +0000968
DRC19c791c2018-03-08 10:55:20 -0600969bailout:
970 return;
DRCfc26b652014-03-16 22:56:26 +0000971}
972
DRCa4940d12014-08-15 16:07:15 +0000973/* TurboJPEG 1.2.x: TJTransformer::init() */
DRCe8573012011-03-04 10:13:59 +0000974JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJTransformer_init
DRC19c791c2018-03-08 10:55:20 -0600975 (JNIEnv *env, jobject obj)
DRCe8573012011-03-04 10:13:59 +0000976{
DRC19c791c2018-03-08 10:55:20 -0600977 jclass cls;
978 jfieldID fid;
979 tjhandle handle;
DRCe8573012011-03-04 10:13:59 +0000980
DRC19c791c2018-03-08 10:55:20 -0600981 if ((handle = tjInitTransform()) == NULL)
DRCd8b95102019-04-12 07:49:35 -0500982 THROW(tjGetErrorStr(), "org/libjpegturbo/turbojpeg/TJException");
DRCe8573012011-03-04 10:13:59 +0000983
DRCd8b95102019-04-12 07:49:35 -0500984 BAILIF0(cls = (*env)->GetObjectClass(env, obj));
985 BAILIF0(fid = (*env)->GetFieldID(env, cls, "handle", "J"));
DRC19c791c2018-03-08 10:55:20 -0600986 (*env)->SetLongField(env, obj, fid, (size_t)handle);
DRCe8573012011-03-04 10:13:59 +0000987
DRC19c791c2018-03-08 10:55:20 -0600988bailout:
989 return;
DRCe8573012011-03-04 10:13:59 +0000990}
991
DRC19c791c2018-03-08 10:55:20 -0600992typedef struct _JNICustomFilterParams {
993 JNIEnv *env;
994 jobject tobj;
995 jobject cfobj;
DRCf5467112011-09-20 05:02:19 +0000996} JNICustomFilterParams;
997
998static int JNICustomFilter(short *coeffs, tjregion arrayRegion,
DRC19c791c2018-03-08 10:55:20 -0600999 tjregion planeRegion, int componentIndex,
1000 int transformIndex, tjtransform *transform)
DRCf5467112011-09-20 05:02:19 +00001001{
DRC19c791c2018-03-08 10:55:20 -06001002 JNICustomFilterParams *params = (JNICustomFilterParams *)transform->data;
1003 JNIEnv *env = params->env;
1004 jobject tobj = params->tobj, cfobj = params->cfobj;
1005 jobject arrayRegionObj, planeRegionObj, bufobj, borobj;
1006 jclass cls;
1007 jmethodID mid;
1008 jfieldID fid;
DRCf5467112011-09-20 05:02:19 +00001009
DRCd8b95102019-04-12 07:49:35 -05001010 BAILIF0(bufobj = (*env)->NewDirectByteBuffer(env, coeffs,
DRC19c791c2018-03-08 10:55:20 -06001011 sizeof(short) * arrayRegion.w * arrayRegion.h));
DRCd8b95102019-04-12 07:49:35 -05001012 BAILIF0(cls = (*env)->FindClass(env, "java/nio/ByteOrder"));
1013 BAILIF0(mid = (*env)->GetStaticMethodID(env, cls, "nativeOrder",
DRC19c791c2018-03-08 10:55:20 -06001014 "()Ljava/nio/ByteOrder;"));
DRCd8b95102019-04-12 07:49:35 -05001015 BAILIF0(borobj = (*env)->CallStaticObjectMethod(env, cls, mid));
1016 BAILIF0(cls = (*env)->GetObjectClass(env, bufobj));
1017 BAILIF0(mid = (*env)->GetMethodID(env, cls, "order",
DRC19c791c2018-03-08 10:55:20 -06001018 "(Ljava/nio/ByteOrder;)Ljava/nio/ByteBuffer;"));
1019 (*env)->CallObjectMethod(env, bufobj, mid, borobj);
DRCd8b95102019-04-12 07:49:35 -05001020 BAILIF0(mid = (*env)->GetMethodID(env, cls, "asShortBuffer",
DRC19c791c2018-03-08 10:55:20 -06001021 "()Ljava/nio/ShortBuffer;"));
DRCd8b95102019-04-12 07:49:35 -05001022 BAILIF0(bufobj = (*env)->CallObjectMethod(env, bufobj, mid));
DRCf5467112011-09-20 05:02:19 +00001023
DRCd8b95102019-04-12 07:49:35 -05001024 BAILIF0(cls = (*env)->FindClass(env, "java/awt/Rectangle"));
1025 BAILIF0(arrayRegionObj = (*env)->AllocObject(env, cls));
1026 BAILIF0(fid = (*env)->GetFieldID(env, cls, "x", "I"));
DRC19c791c2018-03-08 10:55:20 -06001027 (*env)->SetIntField(env, arrayRegionObj, fid, arrayRegion.x);
DRCd8b95102019-04-12 07:49:35 -05001028 BAILIF0(fid = (*env)->GetFieldID(env, cls, "y", "I"));
DRC19c791c2018-03-08 10:55:20 -06001029 (*env)->SetIntField(env, arrayRegionObj, fid, arrayRegion.y);
DRCd8b95102019-04-12 07:49:35 -05001030 BAILIF0(fid = (*env)->GetFieldID(env, cls, "width", "I"));
DRC19c791c2018-03-08 10:55:20 -06001031 (*env)->SetIntField(env, arrayRegionObj, fid, arrayRegion.w);
DRCd8b95102019-04-12 07:49:35 -05001032 BAILIF0(fid = (*env)->GetFieldID(env, cls, "height", "I"));
DRC19c791c2018-03-08 10:55:20 -06001033 (*env)->SetIntField(env, arrayRegionObj, fid, arrayRegion.h);
DRCf5467112011-09-20 05:02:19 +00001034
DRCd8b95102019-04-12 07:49:35 -05001035 BAILIF0(planeRegionObj = (*env)->AllocObject(env, cls));
1036 BAILIF0(fid = (*env)->GetFieldID(env, cls, "x", "I"));
DRC19c791c2018-03-08 10:55:20 -06001037 (*env)->SetIntField(env, planeRegionObj, fid, planeRegion.x);
DRCd8b95102019-04-12 07:49:35 -05001038 BAILIF0(fid = (*env)->GetFieldID(env, cls, "y", "I"));
DRC19c791c2018-03-08 10:55:20 -06001039 (*env)->SetIntField(env, planeRegionObj, fid, planeRegion.y);
DRCd8b95102019-04-12 07:49:35 -05001040 BAILIF0(fid = (*env)->GetFieldID(env, cls, "width", "I"));
DRC19c791c2018-03-08 10:55:20 -06001041 (*env)->SetIntField(env, planeRegionObj, fid, planeRegion.w);
DRCd8b95102019-04-12 07:49:35 -05001042 BAILIF0(fid = (*env)->GetFieldID(env, cls, "height", "I"));
DRC19c791c2018-03-08 10:55:20 -06001043 (*env)->SetIntField(env, planeRegionObj, fid, planeRegion.h);
DRCf5467112011-09-20 05:02:19 +00001044
DRCd8b95102019-04-12 07:49:35 -05001045 BAILIF0(cls = (*env)->GetObjectClass(env, cfobj));
1046 BAILIF0(mid = (*env)->GetMethodID(env, cls, "customFilter",
DRC19c791c2018-03-08 10:55:20 -06001047 "(Ljava/nio/ShortBuffer;Ljava/awt/Rectangle;Ljava/awt/Rectangle;IILorg/libjpegturbo/turbojpeg/TJTransform;)V"));
1048 (*env)->CallVoidMethod(env, cfobj, mid, bufobj, arrayRegionObj,
1049 planeRegionObj, componentIndex, transformIndex, tobj);
DRCf5467112011-09-20 05:02:19 +00001050
DRC19c791c2018-03-08 10:55:20 -06001051 return 0;
DRCf5467112011-09-20 05:02:19 +00001052
DRC19c791c2018-03-08 10:55:20 -06001053bailout:
1054 return -1;
DRCf5467112011-09-20 05:02:19 +00001055}
1056
DRCa4940d12014-08-15 16:07:15 +00001057/* TurboJPEG 1.2.x: TJTransformer::transform() */
DRCe8573012011-03-04 10:13:59 +00001058JNIEXPORT jintArray JNICALL Java_org_libjpegturbo_turbojpeg_TJTransformer_transform
DRC19c791c2018-03-08 10:55:20 -06001059 (JNIEnv *env, jobject obj, jbyteArray jsrcBuf, jint jpegSize,
1060 jobjectArray dstobjs, jobjectArray tobjs, jint flags)
DRCe8573012011-03-04 10:13:59 +00001061{
DRC19c791c2018-03-08 10:55:20 -06001062 tjhandle handle = 0;
1063 unsigned char *jpegBuf = NULL, **dstBufs = NULL;
1064 jsize n = 0;
1065 unsigned long *dstSizes = NULL;
1066 tjtransform *t = NULL;
1067 jbyteArray *jdstBufs = NULL;
1068 int i, jpegWidth = 0, jpegHeight = 0, jpegSubsamp;
1069 jintArray jdstSizes = 0;
1070 jint *dstSizesi = NULL;
1071 JNICustomFilterParams *params = NULL;
DRCe8573012011-03-04 10:13:59 +00001072
DRCd8b95102019-04-12 07:49:35 -05001073 GET_HANDLE();
DRCe8573012011-03-04 10:13:59 +00001074
DRC19c791c2018-03-08 10:55:20 -06001075 if ((*env)->GetArrayLength(env, jsrcBuf) < jpegSize)
DRCd8b95102019-04-12 07:49:35 -05001076 THROW_ARG("Source buffer is not large enough");
1077 BAILIF0(_fid = (*env)->GetFieldID(env, _cls, "jpegWidth", "I"));
DRC19c791c2018-03-08 10:55:20 -06001078 jpegWidth = (int)(*env)->GetIntField(env, obj, _fid);
DRCd8b95102019-04-12 07:49:35 -05001079 BAILIF0(_fid = (*env)->GetFieldID(env, _cls, "jpegHeight", "I"));
DRC19c791c2018-03-08 10:55:20 -06001080 jpegHeight = (int)(*env)->GetIntField(env, obj, _fid);
DRCd8b95102019-04-12 07:49:35 -05001081 BAILIF0(_fid = (*env)->GetFieldID(env, _cls, "jpegSubsamp", "I"));
DRC19c791c2018-03-08 10:55:20 -06001082 jpegSubsamp = (int)(*env)->GetIntField(env, obj, _fid);
DRCe8573012011-03-04 10:13:59 +00001083
DRC19c791c2018-03-08 10:55:20 -06001084 n = (*env)->GetArrayLength(env, dstobjs);
1085 if (n != (*env)->GetArrayLength(env, tobjs))
DRCd8b95102019-04-12 07:49:35 -05001086 THROW_ARG("Mismatch between size of transforms array and destination buffers array");
DRCe8573012011-03-04 10:13:59 +00001087
DRC19c791c2018-03-08 10:55:20 -06001088 if ((dstBufs =
1089 (unsigned char **)malloc(sizeof(unsigned char *) * n)) == NULL)
DRCd8b95102019-04-12 07:49:35 -05001090 THROW_MEM();
DRC19c791c2018-03-08 10:55:20 -06001091 if ((jdstBufs = (jbyteArray *)malloc(sizeof(jbyteArray) * n)) == NULL)
DRCd8b95102019-04-12 07:49:35 -05001092 THROW_MEM();
DRC19c791c2018-03-08 10:55:20 -06001093 if ((dstSizes = (unsigned long *)malloc(sizeof(unsigned long) * n)) == NULL)
DRCd8b95102019-04-12 07:49:35 -05001094 THROW_MEM();
DRC19c791c2018-03-08 10:55:20 -06001095 if ((t = (tjtransform *)malloc(sizeof(tjtransform) * n)) == NULL)
DRCd8b95102019-04-12 07:49:35 -05001096 THROW_MEM();
DRC19c791c2018-03-08 10:55:20 -06001097 if ((params = (JNICustomFilterParams *)malloc(sizeof(JNICustomFilterParams) *
1098 n)) == NULL)
DRCd8b95102019-04-12 07:49:35 -05001099 THROW_MEM();
DRC19c791c2018-03-08 10:55:20 -06001100 for (i = 0; i < n; i++) {
1101 dstBufs[i] = NULL; jdstBufs[i] = NULL; dstSizes[i] = 0;
1102 memset(&t[i], 0, sizeof(tjtransform));
1103 memset(&params[i], 0, sizeof(JNICustomFilterParams));
1104 }
DRCe8573012011-03-04 10:13:59 +00001105
DRC19c791c2018-03-08 10:55:20 -06001106 for (i = 0; i < n; i++) {
1107 jobject tobj, cfobj;
DRCe8573012011-03-04 10:13:59 +00001108
DRCd8b95102019-04-12 07:49:35 -05001109 BAILIF0(tobj = (*env)->GetObjectArrayElement(env, tobjs, i));
1110 BAILIF0(_cls = (*env)->GetObjectClass(env, tobj));
1111 BAILIF0(_fid = (*env)->GetFieldID(env, _cls, "op", "I"));
DRC19c791c2018-03-08 10:55:20 -06001112 t[i].op = (*env)->GetIntField(env, tobj, _fid);
DRCd8b95102019-04-12 07:49:35 -05001113 BAILIF0(_fid = (*env)->GetFieldID(env, _cls, "options", "I"));
DRC19c791c2018-03-08 10:55:20 -06001114 t[i].options = (*env)->GetIntField(env, tobj, _fid);
DRCd8b95102019-04-12 07:49:35 -05001115 BAILIF0(_fid = (*env)->GetFieldID(env, _cls, "x", "I"));
DRC19c791c2018-03-08 10:55:20 -06001116 t[i].r.x = (*env)->GetIntField(env, tobj, _fid);
DRCd8b95102019-04-12 07:49:35 -05001117 BAILIF0(_fid = (*env)->GetFieldID(env, _cls, "y", "I"));
DRC19c791c2018-03-08 10:55:20 -06001118 t[i].r.y = (*env)->GetIntField(env, tobj, _fid);
DRCd8b95102019-04-12 07:49:35 -05001119 BAILIF0(_fid = (*env)->GetFieldID(env, _cls, "width", "I"));
DRC19c791c2018-03-08 10:55:20 -06001120 t[i].r.w = (*env)->GetIntField(env, tobj, _fid);
DRCd8b95102019-04-12 07:49:35 -05001121 BAILIF0(_fid = (*env)->GetFieldID(env, _cls, "height", "I"));
DRC19c791c2018-03-08 10:55:20 -06001122 t[i].r.h = (*env)->GetIntField(env, tobj, _fid);
DRCf5467112011-09-20 05:02:19 +00001123
DRCd8b95102019-04-12 07:49:35 -05001124 BAILIF0(_fid = (*env)->GetFieldID(env, _cls, "cf",
DRC19c791c2018-03-08 10:55:20 -06001125 "Lorg/libjpegturbo/turbojpeg/TJCustomFilter;"));
1126 cfobj = (*env)->GetObjectField(env, tobj, _fid);
1127 if (cfobj) {
1128 params[i].env = env;
1129 params[i].tobj = tobj;
1130 params[i].cfobj = cfobj;
1131 t[i].customFilter = JNICustomFilter;
1132 t[i].data = (void *)&params[i];
1133 }
1134 }
DRCe8573012011-03-04 10:13:59 +00001135
DRC19c791c2018-03-08 10:55:20 -06001136 for (i = 0; i < n; i++) {
1137 int w = jpegWidth, h = jpegHeight;
DRCe8573012011-03-04 10:13:59 +00001138
DRC19c791c2018-03-08 10:55:20 -06001139 if (t[i].r.w != 0) w = t[i].r.w;
1140 if (t[i].r.h != 0) h = t[i].r.h;
DRCd8b95102019-04-12 07:49:35 -05001141 BAILIF0(jdstBufs[i] = (*env)->GetObjectArrayElement(env, dstobjs, i));
DRC19c791c2018-03-08 10:55:20 -06001142 if ((unsigned long)(*env)->GetArrayLength(env, jdstBufs[i]) <
1143 tjBufSize(w, h, jpegSubsamp))
DRCd8b95102019-04-12 07:49:35 -05001144 THROW_ARG("Destination buffer is not large enough");
DRC19c791c2018-03-08 10:55:20 -06001145 }
DRCd8b95102019-04-12 07:49:35 -05001146 BAILIF0(jpegBuf = (*env)->GetPrimitiveArrayCritical(env, jsrcBuf, 0));
DRC19c791c2018-03-08 10:55:20 -06001147 for (i = 0; i < n; i++)
DRCd8b95102019-04-12 07:49:35 -05001148 BAILIF0(dstBufs[i] =
DRC19c791c2018-03-08 10:55:20 -06001149 (*env)->GetPrimitiveArrayCritical(env, jdstBufs[i], 0));
DRC8951cf02014-08-14 16:54:04 +00001150
DRC19c791c2018-03-08 10:55:20 -06001151 if (tjTransform(handle, jpegBuf, jpegSize, n, dstBufs, dstSizes, t,
1152 flags | TJFLAG_NOREALLOC) == -1)
DRCd8b95102019-04-12 07:49:35 -05001153 THROW_TJ();
DRCe8573012011-03-04 10:13:59 +00001154
DRC19c791c2018-03-08 10:55:20 -06001155 for (i = 0; i < n; i++) {
1156 (*env)->ReleasePrimitiveArrayCritical(env, jdstBufs[i], dstBufs[i], 0);
1157 dstBufs[i] = NULL;
1158 }
1159 (*env)->ReleasePrimitiveArrayCritical(env, jsrcBuf, jpegBuf, 0);
1160 jpegBuf = NULL;
DRCe8573012011-03-04 10:13:59 +00001161
DRC19c791c2018-03-08 10:55:20 -06001162 jdstSizes = (*env)->NewIntArray(env, n);
DRCd8b95102019-04-12 07:49:35 -05001163 BAILIF0(dstSizesi = (*env)->GetIntArrayElements(env, jdstSizes, 0));
DRC19c791c2018-03-08 10:55:20 -06001164 for (i = 0; i < n; i++) dstSizesi[i] = (int)dstSizes[i];
1165
1166bailout:
1167 if (dstSizesi) (*env)->ReleaseIntArrayElements(env, jdstSizes, dstSizesi, 0);
1168 if (dstBufs) {
1169 for (i = 0; i < n; i++) {
1170 if (dstBufs[i] && jdstBufs && jdstBufs[i])
1171 (*env)->ReleasePrimitiveArrayCritical(env, jdstBufs[i], dstBufs[i], 0);
1172 }
1173 free(dstBufs);
1174 }
1175 if (jpegBuf) (*env)->ReleasePrimitiveArrayCritical(env, jsrcBuf, jpegBuf, 0);
1176 if (jdstBufs) free(jdstBufs);
1177 if (dstSizes) free(dstSizes);
1178 if (t) free(t);
1179 return jdstSizes;
DRCe8573012011-03-04 10:13:59 +00001180}
1181
DRCa4940d12014-08-15 16:07:15 +00001182/* TurboJPEG 1.2.x: TJDecompressor::destroy() */
DRCc5a41992011-02-08 06:54:36 +00001183JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_destroy
DRC19c791c2018-03-08 10:55:20 -06001184 (JNIEnv *env, jobject obj)
DRCf8e00552011-02-04 11:06:36 +00001185{
DRC19c791c2018-03-08 10:55:20 -06001186 Java_org_libjpegturbo_turbojpeg_TJCompressor_destroy(env, obj);
DRCf8e00552011-02-04 11:06:36 +00001187}