blob: 55d3342be6b4e2356ff5d83de0c25499993e3ff4 [file] [log] [blame]
DRCf8e00552011-02-04 11:06:36 +00001/*
DRCb9ab64d2017-05-11 21:02:29 -05002 * Copyright (C)2011-2017 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
DRC19c791c2018-03-08 10:55:20 -060040#define PAD(v, p) ((v + (p) - 1) & (~((p) - 1)))
DRC40dd3142014-08-17 12:23:49 +000041
DRC19c791c2018-03-08 10:55:20 -060042#define bailif0(f) { \
43 if (!(f) || (*env)->ExceptionCheck(env)) { \
44 goto bailout; \
45 } \
DRCf8e00552011-02-04 11:06:36 +000046}
47
DRC19c791c2018-03-08 10:55:20 -060048#define _throw(msg, exceptionClass) { \
49 jclass _exccls = (*env)->FindClass(env, exceptionClass); \
50 \
51 bailif0(_exccls); \
52 (*env)->ThrowNew(env, _exccls, msg); \
53 goto bailout; \
54}
55
56#define _throwtj() { \
57 jclass _exccls; \
58 jmethodID _excid; \
59 jobject _excobj; \
60 jstring _errstr; \
61 \
62 bailif0(_errstr = (*env)->NewStringUTF(env, tjGetErrorStr2(handle))); \
63 bailif0(_exccls = (*env)->FindClass(env, \
64 "org/libjpegturbo/turbojpeg/TJException")); \
65 bailif0(_excid = (*env)->GetMethodID(env, _exccls, "<init>", \
66 "(Ljava/lang/String;I)V")); \
67 bailif0(_excobj = (*env)->NewObject(env, _exccls, _excid, _errstr, \
68 tjGetErrorCode(handle))); \
69 (*env)->Throw(env, _excobj); \
70 goto bailout; \
DRCd4092f62017-06-27 10:54:21 -050071}
DRCb3817da2015-07-14 20:42:52 +000072
73#define _throwarg(msg) _throw(msg, "java/lang/IllegalArgumentException")
74
DRC19c791c2018-03-08 10:55:20 -060075#define _throwmem() \
76 _throw("Memory allocation failure", "java/lang/OutOfMemoryError");
DRCb3817da2015-07-14 20:42:52 +000077
DRC19c791c2018-03-08 10:55:20 -060078#define gethandle() \
79 jclass _cls = (*env)->GetObjectClass(env, obj); \
80 jfieldID _fid; \
81 \
82 bailif0(_cls); \
83 bailif0(_fid = (*env)->GetFieldID(env, _cls, "handle", "J")); \
84 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
87#define setenv(envvar, value, dummy) _putenv_s(envvar, value)
88#endif
89
DRC19c791c2018-03-08 10:55:20 -060090#define prop2env(property, envvar) { \
91 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
DRC19c791c2018-03-08 10:55:20 -0600108 bailif0(cls = (*env)->FindClass(env, "java/lang/System"));
109 bailif0(mid = (*env)->GetStaticMethodID(env, cls, "getProperty",
110 "(Ljava/lang/String;)Ljava/lang/String;"));
DRC0713c1b2014-08-22 13:43:33 +0000111
DRC19c791c2018-03-08 10:55:20 -0600112 prop2env("turbojpeg.optimize", "TJ_OPTIMIZE");
113 prop2env("turbojpeg.arithmetic", "TJ_ARITHMETIC");
114 prop2env("turbojpeg.restart", "TJ_RESTART");
115 prop2env("turbojpeg.progressive", "TJ_PROGRESSIVE");
116 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
DRC19c791c2018-03-08 10:55:20 -0600128 if (retval == -1) _throwarg(tjGetErrorStr());
129
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
DRC19c791c2018-03-08 10:55:20 -0600140 if (retval == -1) _throwarg(tjGetErrorStr());
141
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
DRC19c791c2018-03-08 10:55:20 -0600163 if (retval == -1) _throwarg(tjGetErrorStr());
164
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
DRC19c791c2018-03-08 10:55:20 -0600175 if (retval == -1) _throwarg(tjGetErrorStr());
176
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
DRC19c791c2018-03-08 10:55:20 -0600187 if (retval == -1) _throwarg(tjGetErrorStr());
188
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)
202 _throw(tjGetErrorStr(), "org/libjpegturbo/turbojpeg/TJException");
DRCf8e00552011-02-04 11:06:36 +0000203
DRC19c791c2018-03-08 10:55:20 -0600204 bailif0(cls = (*env)->GetObjectClass(env, obj));
205 bailif0(fid = (*env)->GetFieldID(env, cls, "handle", "J"));
206 (*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
DRC19c791c2018-03-08 10:55:20 -0600222 gethandle();
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)
226 _throwarg("Invalid argument in compress()");
227 if (org_libjpegturbo_turbojpeg_TJ_NUMPF != TJ_NUMPF)
228 _throwarg("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)
233 _throwarg("Source buffer is not large enough");
234 jpegSize = tjBufSize(width, height, jpegSubsamp);
235 if ((*env)->GetArrayLength(env, dst) < (jsize)jpegSize)
236 _throwarg("Destination buffer is not large enough");
DRC6acf52b2011-03-02 01:09:20 +0000237
DRC19c791c2018-03-08 10:55:20 -0600238 bailif0(srcBuf = (*env)->GetPrimitiveArrayCritical(env, src, 0));
239 bailif0(jpegBuf = (*env)->GetPrimitiveArrayCritical(env, dst, 0));
DRCf8e00552011-02-04 11:06:36 +0000240
DRC19c791c2018-03-08 10:55:20 -0600241 if (ProcessSystemProperties(env) < 0) goto bailout;
DRC0713c1b2014-08-22 13:43:33 +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)
246 _throwtj();
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)
281 _throwarg("Invalid argument in compress()");
282 if (tjPixelSize[pf] != sizeof(jint))
283 _throwarg("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)
300 _throwarg("Invalid argument in compress()");
301 if (tjPixelSize[pf] != sizeof(jint))
302 _throwarg("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
DRC19c791c2018-03-08 10:55:20 -0600326 gethandle();
DRC1e672742013-10-31 05:04:51 +0000327
DRC19c791c2018-03-08 10:55:20 -0600328 if (subsamp < 0 || subsamp >= org_libjpegturbo_turbojpeg_TJ_NUMSAMP)
329 _throwarg("Invalid argument in compressFromYUV()");
330 if (org_libjpegturbo_turbojpeg_TJ_NUMSAMP != TJ_NUMSAMP)
331 _throwarg("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)
334 _throwarg("Planes array is too small for the subsampling type");
335 if ((*env)->GetArrayLength(env, jSrcOffsets) < nc)
336 _throwarg("Offsets array is too small for the subsampling type");
337 if ((*env)->GetArrayLength(env, jSrcStrides) < nc)
338 _throwarg("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)
342 _throwarg("Destination buffer is not large enough");
DRC1e672742013-10-31 05:04:51 +0000343
DRC19c791c2018-03-08 10:55:20 -0600344 bailif0(srcOffsets = (*env)->GetPrimitiveArrayCritical(env, jSrcOffsets, 0));
345 bailif0(srcStrides = (*env)->GetPrimitiveArrayCritical(env, jSrcStrides, 0));
346 for (i = 0; i < nc; i++) {
347 int planeSize = tjPlaneSizeYUV(i, width, srcStrides[i], height, subsamp);
348 int pw = tjPlaneWidth(i, width, subsamp);
DRC40dd3142014-08-17 12:23:49 +0000349
DRC19c791c2018-03-08 10:55:20 -0600350 if (planeSize < 0 || pw < 0)
351 _throwarg(tjGetErrorStr());
DRC40dd3142014-08-17 12:23:49 +0000352
DRC19c791c2018-03-08 10:55:20 -0600353 if (srcOffsets[i] < 0)
354 _throwarg("Invalid argument in compressFromYUV()");
355 if (srcStrides[i] < 0 && srcOffsets[i] - planeSize + pw < 0)
356 _throwarg("Negative plane stride would cause memory to be accessed below plane boundary");
DRC40dd3142014-08-17 12:23:49 +0000357
DRC19c791c2018-03-08 10:55:20 -0600358 bailif0(jSrcPlanes[i] = (*env)->GetObjectArrayElement(env, srcobjs, i));
359 if ((*env)->GetArrayLength(env, jSrcPlanes[i]) < srcOffsets[i] + planeSize)
360 _throwarg("Source plane is not large enough");
DRC40dd3142014-08-17 12:23:49 +0000361
DRC19c791c2018-03-08 10:55:20 -0600362 bailif0(srcPlanes[i] =
363 (*env)->GetPrimitiveArrayCritical(env, jSrcPlanes[i], 0));
364 srcPlanes[i] = &srcPlanes[i][srcOffsets[i]];
365 }
366 bailif0(jpegBuf = (*env)->GetPrimitiveArrayCritical(env, dst, 0));
DRC1e672742013-10-31 05:04:51 +0000367
DRC19c791c2018-03-08 10:55:20 -0600368 if (ProcessSystemProperties(env) < 0) goto bailout;
DRC0713c1b2014-08-22 13:43:33 +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)
373 _throwtj();
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
DRC19c791c2018-03-08 10:55:20 -0600401 gethandle();
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)
406 _throwarg("Invalid argument in encodeYUV()");
407 if (org_libjpegturbo_turbojpeg_TJ_NUMPF != TJ_NUMPF ||
408 org_libjpegturbo_turbojpeg_TJ_NUMSAMP != TJ_NUMSAMP)
409 _throwarg("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)
412 _throwarg("Planes array is too small for the subsampling type");
413 if ((*env)->GetArrayLength(env, jDstOffsets) < nc)
414 _throwarg("Offsets array is too small for the subsampling type");
415 if ((*env)->GetArrayLength(env, jDstStrides) < nc)
416 _throwarg("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)
421 _throwarg("Source buffer is not large enough");
DRC40dd3142014-08-17 12:23:49 +0000422
DRC19c791c2018-03-08 10:55:20 -0600423 bailif0(dstOffsets = (*env)->GetPrimitiveArrayCritical(env, jDstOffsets, 0));
424 bailif0(dstStrides = (*env)->GetPrimitiveArrayCritical(env, jDstStrides, 0));
425 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)
430 _throwarg(tjGetErrorStr());
DRC40dd3142014-08-17 12:23:49 +0000431
DRC19c791c2018-03-08 10:55:20 -0600432 if (dstOffsets[i] < 0)
433 _throwarg("Invalid argument in encodeYUV()");
434 if (dstStrides[i] < 0 && dstOffsets[i] - planeSize + pw < 0)
435 _throwarg("Negative plane stride would cause memory to be accessed below plane boundary");
DRC40dd3142014-08-17 12:23:49 +0000436
DRC19c791c2018-03-08 10:55:20 -0600437 bailif0(jDstPlanes[i] = (*env)->GetObjectArrayElement(env, dstobjs, i));
438 if ((*env)->GetArrayLength(env, jDstPlanes[i]) < dstOffsets[i] + planeSize)
439 _throwarg("Destination plane is not large enough");
DRC40dd3142014-08-17 12:23:49 +0000440
DRC19c791c2018-03-08 10:55:20 -0600441 bailif0(dstPlanes[i] =
442 (*env)->GetPrimitiveArrayCritical(env, jDstPlanes[i], 0));
443 dstPlanes[i] = &dstPlanes[i][dstOffsets[i]];
444 }
445 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)
450 _throwtj();
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)
482 _throwarg("Invalid argument in encodeYUV()");
483 if (tjPixelSize[pf] != sizeof(jint))
484 _throwarg("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
DRC19c791c2018-03-08 10:55:20 -0600502 gethandle();
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)
506 _throwarg("Invalid argument in encodeYUV()");
507 if (org_libjpegturbo_turbojpeg_TJ_NUMPF != TJ_NUMPF)
508 _throwarg("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)
512 _throwarg("Source buffer is not large enough");
513 if ((*env)->GetArrayLength(env, dst) <
514 (jsize)tjBufSizeYUV(width, height, subsamp))
515 _throwarg("Destination buffer is not large enough");
DRC6acf52b2011-03-02 01:09:20 +0000516
DRC19c791c2018-03-08 10:55:20 -0600517 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)
522 _throwtj();
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)
544 _throwarg("Invalid argument in encodeYUV()");
545 if (tjPixelSize[pf] != sizeof(jint))
546 _throwarg("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
DRC19c791c2018-03-08 10:55:20 -0600562 gethandle();
DRCf8e00552011-02-04 11:06:36 +0000563
DRC19c791c2018-03-08 10:55:20 -0600564 if (tjDestroy(handle) == -1) _throwtj();
565 (*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)
580 _throw(tjGetErrorStr(), "org/libjpegturbo/turbojpeg/TJException");
DRCf8e00552011-02-04 11:06:36 +0000581
DRC19c791c2018-03-08 10:55:20 -0600582 bailif0(cls = (*env)->GetObjectClass(env, obj));
583 bailif0(fid = (*env)->GetFieldID(env, cls, "handle", "J"));
584 (*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)
602 _throwarg(tjGetErrorStr());
DRC36336fc2011-02-22 10:27:31 +0000603
DRC19c791c2018-03-08 10:55:20 -0600604 bailif0(sfcls = (*env)->FindClass(env,
605 "org/libjpegturbo/turbojpeg/TJScalingFactor"));
606 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++) {
609 bailif0(sfobj = (*env)->AllocObject(env, sfcls));
610 bailif0(fid = (*env)->GetFieldID(env, sfcls, "num", "I"));
611 (*env)->SetIntField(env, sfobj, fid, sf[i].num);
612 bailif0(fid = (*env)->GetFieldID(env, sfcls, "denom", "I"));
613 (*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
DRC19c791c2018-03-08 10:55:20 -0600629 gethandle();
DRCf8e00552011-02-04 11:06:36 +0000630
DRC19c791c2018-03-08 10:55:20 -0600631 if ((*env)->GetArrayLength(env, src) < jpegSize)
632 _throwarg("Source buffer is not large enough");
DRC6acf52b2011-03-02 01:09:20 +0000633
DRC19c791c2018-03-08 10:55:20 -0600634 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)
638 _throwtj();
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
DRC19c791c2018-03-08 10:55:20 -0600643 bailif0(_fid = (*env)->GetFieldID(env, _cls, "jpegSubsamp", "I"));
644 (*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);
649 bailif0(_fid = (*env)->GetFieldID(env, _cls, "jpegWidth", "I"));
650 (*env)->SetIntField(env, obj, _fid, width);
651 bailif0(_fid = (*env)->GetFieldID(env, _cls, "jpegHeight", "I"));
652 (*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
DRC19c791c2018-03-08 10:55:20 -0600667 gethandle();
DRCf8e00552011-02-04 11:06:36 +0000668
DRC19c791c2018-03-08 10:55:20 -0600669 if (pf < 0 || pf >= org_libjpegturbo_turbojpeg_TJ_NUMPF)
670 _throwarg("Invalid argument in decompress()");
671 if (org_libjpegturbo_turbojpeg_TJ_NUMPF != TJ_NUMPF)
672 _throwarg("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)
675 _throwarg("Source buffer is not large enough");
676 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)
679 _throwarg("Destination buffer is not large enough");
DRC6acf52b2011-03-02 01:09:20 +0000680
DRC19c791c2018-03-08 10:55:20 -0600681 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)
687 _throwtj();
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)
718 _throwarg("Invalid argument in decompress()");
719 if (tjPixelSize[pf] != sizeof(jint))
720 _throwarg("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)
735 _throwarg("Invalid argument in decompress()");
736 if (tjPixelSize[pf] != sizeof(jint))
737 _throwarg("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
DRC19c791c2018-03-08 10:55:20 -0600760 gethandle();
DRC4f1580c2011-02-25 06:11:03 +0000761
DRC19c791c2018-03-08 10:55:20 -0600762 if ((*env)->GetArrayLength(env, src) < jpegSize)
763 _throwarg("Source buffer is not large enough");
764 bailif0(_fid = (*env)->GetFieldID(env, _cls, "jpegSubsamp", "I"));
765 jpegSubsamp = (int)(*env)->GetIntField(env, obj, _fid);
766 bailif0(_fid = (*env)->GetFieldID(env, _cls, "jpegWidth", "I"));
767 jpegWidth = (int)(*env)->GetIntField(env, obj, _fid);
768 bailif0(_fid = (*env)->GetFieldID(env, _cls, "jpegHeight", "I"));
769 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)
779 _throwarg(tjGetErrorStr());
780 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)
787 _throwarg("Could not scale down to desired image dimensions");
DRC4f1580c2011-02-25 06:11:03 +0000788
DRC19c791c2018-03-08 10:55:20 -0600789 bailif0(dstOffsets = (*env)->GetPrimitiveArrayCritical(env, jDstOffsets, 0));
790 bailif0(dstStrides = (*env)->GetPrimitiveArrayCritical(env, jDstStrides, 0));
791 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)
797 _throwarg(tjGetErrorStr());
DRC40dd3142014-08-17 12:23:49 +0000798
DRC19c791c2018-03-08 10:55:20 -0600799 if (dstOffsets[i] < 0)
800 _throwarg("Invalid argument in decompressToYUV()");
801 if (dstStrides[i] < 0 && dstOffsets[i] - planeSize + pw < 0)
802 _throwarg("Negative plane stride would cause memory to be accessed below plane boundary");
DRC40dd3142014-08-17 12:23:49 +0000803
DRC19c791c2018-03-08 10:55:20 -0600804 bailif0(jDstPlanes[i] = (*env)->GetObjectArrayElement(env, dstobjs, i));
805 if ((*env)->GetArrayLength(env, jDstPlanes[i]) < dstOffsets[i] + planeSize)
806 _throwarg("Destination plane is not large enough");
DRC40dd3142014-08-17 12:23:49 +0000807
DRC19c791c2018-03-08 10:55:20 -0600808 bailif0(dstPlanes[i] =
809 (*env)->GetPrimitiveArrayCritical(env, jDstPlanes[i], 0));
810 dstPlanes[i] = &dstPlanes[i][dstOffsets[i]];
811 }
812 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)
817 _throwtj();
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
DRC19c791c2018-03-08 10:55:20 -0600841 gethandle();
DRCfc26b652014-03-16 22:56:26 +0000842
DRC19c791c2018-03-08 10:55:20 -0600843 if ((*env)->GetArrayLength(env, src) < jpegSize)
844 _throwarg("Source buffer is not large enough");
845 bailif0(_fid = (*env)->GetFieldID(env, _cls, "jpegSubsamp", "I"));
846 jpegSubsamp = (int)(*env)->GetIntField(env, obj, _fid);
847 bailif0(_fid = (*env)->GetFieldID(env, _cls, "jpegWidth", "I"));
848 jpegWidth = (int)(*env)->GetIntField(env, obj, _fid);
849 bailif0(_fid = (*env)->GetFieldID(env, _cls, "jpegHeight", "I"));
850 jpegHeight = (int)(*env)->GetIntField(env, obj, _fid);
851 if ((*env)->GetArrayLength(env, dst) <
852 (jsize)tjBufSizeYUV(jpegWidth, jpegHeight, jpegSubsamp))
853 _throwarg("Destination buffer is not large enough");
DRC40dd3142014-08-17 12:23:49 +0000854
DRC19c791c2018-03-08 10:55:20 -0600855 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)
860 _throwtj();
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
DRC19c791c2018-03-08 10:55:20 -0600880 gethandle();
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)
884 _throwarg("Invalid argument in decodeYUV()");
885 if (org_libjpegturbo_turbojpeg_TJ_NUMPF != TJ_NUMPF ||
886 org_libjpegturbo_turbojpeg_TJ_NUMSAMP != TJ_NUMSAMP)
887 _throwarg("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)
890 _throwarg("Planes array is too small for the subsampling type");
891 if ((*env)->GetArrayLength(env, jSrcOffsets) < nc)
892 _throwarg("Offsets array is too small for the subsampling type");
893 if ((*env)->GetArrayLength(env, jSrcStrides) < nc)
894 _throwarg("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)
899 _throwarg("Destination buffer is not large enough");
DRCfc26b652014-03-16 22:56:26 +0000900
DRC19c791c2018-03-08 10:55:20 -0600901 bailif0(srcOffsets = (*env)->GetPrimitiveArrayCritical(env, jSrcOffsets, 0));
902 bailif0(srcStrides = (*env)->GetPrimitiveArrayCritical(env, jSrcStrides, 0));
903 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)
908 _throwarg(tjGetErrorStr());
DRC40dd3142014-08-17 12:23:49 +0000909
DRC19c791c2018-03-08 10:55:20 -0600910 if (srcOffsets[i] < 0)
911 _throwarg("Invalid argument in decodeYUV()");
912 if (srcStrides[i] < 0 && srcOffsets[i] - planeSize + pw < 0)
913 _throwarg("Negative plane stride would cause memory to be accessed below plane boundary");
DRC40dd3142014-08-17 12:23:49 +0000914
DRC19c791c2018-03-08 10:55:20 -0600915 bailif0(jSrcPlanes[i] = (*env)->GetObjectArrayElement(env, srcobjs, i));
916 if ((*env)->GetArrayLength(env, jSrcPlanes[i]) < srcOffsets[i] + planeSize)
917 _throwarg("Source plane is not large enough");
DRC40dd3142014-08-17 12:23:49 +0000918
DRC19c791c2018-03-08 10:55:20 -0600919 bailif0(srcPlanes[i] =
920 (*env)->GetPrimitiveArrayCritical(env, jSrcPlanes[i], 0));
921 srcPlanes[i] = &srcPlanes[i][srcOffsets[i]];
922 }
923 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)
928 _throwtj();
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)
961 _throwarg("Invalid argument in decodeYUV()");
962 if (tjPixelSize[pf] != sizeof(jint))
963 _throwarg("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)
982 _throw(tjGetErrorStr(), "org/libjpegturbo/turbojpeg/TJException");
DRCe8573012011-03-04 10:13:59 +0000983
DRC19c791c2018-03-08 10:55:20 -0600984 bailif0(cls = (*env)->GetObjectClass(env, obj));
985 bailif0(fid = (*env)->GetFieldID(env, cls, "handle", "J"));
986 (*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
DRC19c791c2018-03-08 10:55:20 -06001010 bailif0(bufobj = (*env)->NewDirectByteBuffer(env, coeffs,
1011 sizeof(short) * arrayRegion.w * arrayRegion.h));
1012 bailif0(cls = (*env)->FindClass(env, "java/nio/ByteOrder"));
1013 bailif0(mid = (*env)->GetStaticMethodID(env, cls, "nativeOrder",
1014 "()Ljava/nio/ByteOrder;"));
1015 bailif0(borobj = (*env)->CallStaticObjectMethod(env, cls, mid));
1016 bailif0(cls = (*env)->GetObjectClass(env, bufobj));
1017 bailif0(mid = (*env)->GetMethodID(env, cls, "order",
1018 "(Ljava/nio/ByteOrder;)Ljava/nio/ByteBuffer;"));
1019 (*env)->CallObjectMethod(env, bufobj, mid, borobj);
1020 bailif0(mid = (*env)->GetMethodID(env, cls, "asShortBuffer",
1021 "()Ljava/nio/ShortBuffer;"));
1022 bailif0(bufobj = (*env)->CallObjectMethod(env, bufobj, mid));
DRCf5467112011-09-20 05:02:19 +00001023
DRC19c791c2018-03-08 10:55:20 -06001024 bailif0(cls = (*env)->FindClass(env, "java/awt/Rectangle"));
1025 bailif0(arrayRegionObj = (*env)->AllocObject(env, cls));
1026 bailif0(fid = (*env)->GetFieldID(env, cls, "x", "I"));
1027 (*env)->SetIntField(env, arrayRegionObj, fid, arrayRegion.x);
1028 bailif0(fid = (*env)->GetFieldID(env, cls, "y", "I"));
1029 (*env)->SetIntField(env, arrayRegionObj, fid, arrayRegion.y);
1030 bailif0(fid = (*env)->GetFieldID(env, cls, "width", "I"));
1031 (*env)->SetIntField(env, arrayRegionObj, fid, arrayRegion.w);
1032 bailif0(fid = (*env)->GetFieldID(env, cls, "height", "I"));
1033 (*env)->SetIntField(env, arrayRegionObj, fid, arrayRegion.h);
DRCf5467112011-09-20 05:02:19 +00001034
DRC19c791c2018-03-08 10:55:20 -06001035 bailif0(planeRegionObj = (*env)->AllocObject(env, cls));
1036 bailif0(fid = (*env)->GetFieldID(env, cls, "x", "I"));
1037 (*env)->SetIntField(env, planeRegionObj, fid, planeRegion.x);
1038 bailif0(fid = (*env)->GetFieldID(env, cls, "y", "I"));
1039 (*env)->SetIntField(env, planeRegionObj, fid, planeRegion.y);
1040 bailif0(fid = (*env)->GetFieldID(env, cls, "width", "I"));
1041 (*env)->SetIntField(env, planeRegionObj, fid, planeRegion.w);
1042 bailif0(fid = (*env)->GetFieldID(env, cls, "height", "I"));
1043 (*env)->SetIntField(env, planeRegionObj, fid, planeRegion.h);
DRCf5467112011-09-20 05:02:19 +00001044
DRC19c791c2018-03-08 10:55:20 -06001045 bailif0(cls = (*env)->GetObjectClass(env, cfobj));
1046 bailif0(mid = (*env)->GetMethodID(env, cls, "customFilter",
1047 "(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
DRC19c791c2018-03-08 10:55:20 -06001073 gethandle();
DRCe8573012011-03-04 10:13:59 +00001074
DRC19c791c2018-03-08 10:55:20 -06001075 if ((*env)->GetArrayLength(env, jsrcBuf) < jpegSize)
1076 _throwarg("Source buffer is not large enough");
1077 bailif0(_fid = (*env)->GetFieldID(env, _cls, "jpegWidth", "I"));
1078 jpegWidth = (int)(*env)->GetIntField(env, obj, _fid);
1079 bailif0(_fid = (*env)->GetFieldID(env, _cls, "jpegHeight", "I"));
1080 jpegHeight = (int)(*env)->GetIntField(env, obj, _fid);
1081 bailif0(_fid = (*env)->GetFieldID(env, _cls, "jpegSubsamp", "I"));
1082 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))
1086 _throwarg("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)
1090 _throwmem();
1091 if ((jdstBufs = (jbyteArray *)malloc(sizeof(jbyteArray) * n)) == NULL)
1092 _throwmem();
1093 if ((dstSizes = (unsigned long *)malloc(sizeof(unsigned long) * n)) == NULL)
1094 _throwmem();
1095 if ((t = (tjtransform *)malloc(sizeof(tjtransform) * n)) == NULL)
1096 _throwmem();
1097 if ((params = (JNICustomFilterParams *)malloc(sizeof(JNICustomFilterParams) *
1098 n)) == NULL)
1099 _throwmem();
1100 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
DRC19c791c2018-03-08 10:55:20 -06001109 bailif0(tobj = (*env)->GetObjectArrayElement(env, tobjs, i));
1110 bailif0(_cls = (*env)->GetObjectClass(env, tobj));
1111 bailif0(_fid = (*env)->GetFieldID(env, _cls, "op", "I"));
1112 t[i].op = (*env)->GetIntField(env, tobj, _fid);
1113 bailif0(_fid = (*env)->GetFieldID(env, _cls, "options", "I"));
1114 t[i].options = (*env)->GetIntField(env, tobj, _fid);
1115 bailif0(_fid = (*env)->GetFieldID(env, _cls, "x", "I"));
1116 t[i].r.x = (*env)->GetIntField(env, tobj, _fid);
1117 bailif0(_fid = (*env)->GetFieldID(env, _cls, "y", "I"));
1118 t[i].r.y = (*env)->GetIntField(env, tobj, _fid);
1119 bailif0(_fid = (*env)->GetFieldID(env, _cls, "width", "I"));
1120 t[i].r.w = (*env)->GetIntField(env, tobj, _fid);
1121 bailif0(_fid = (*env)->GetFieldID(env, _cls, "height", "I"));
1122 t[i].r.h = (*env)->GetIntField(env, tobj, _fid);
DRCf5467112011-09-20 05:02:19 +00001123
DRC19c791c2018-03-08 10:55:20 -06001124 bailif0(_fid = (*env)->GetFieldID(env, _cls, "cf",
1125 "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;
1141 bailif0(jdstBufs[i] = (*env)->GetObjectArrayElement(env, dstobjs, i));
1142 if ((unsigned long)(*env)->GetArrayLength(env, jdstBufs[i]) <
1143 tjBufSize(w, h, jpegSubsamp))
1144 _throwarg("Destination buffer is not large enough");
1145 }
1146 bailif0(jpegBuf = (*env)->GetPrimitiveArrayCritical(env, jsrcBuf, 0));
1147 for (i = 0; i < n; i++)
1148 bailif0(dstBufs[i] =
1149 (*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)
1153 _throwtj();
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);
1163 bailif0(dstSizesi = (*env)->GetIntArrayElements(env, jdstSizes, 0));
1164 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}