DRC | f8e0055 | 2011-02-04 11:06:36 +0000 | [diff] [blame] | 1 | /* |
DRC | 5ea77d8 | 2018-10-26 08:55:22 -0500 | [diff] [blame^] | 2 | * Copyright (C)2011-2018 D. R. Commander. All Rights Reserved. |
DRC | f8e0055 | 2011-02-04 11:06:36 +0000 | [diff] [blame] | 3 | * |
| 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 | |
DRC | e857301 | 2011-03-04 10:13:59 +0000 | [diff] [blame] | 29 | #include <stdlib.h> |
| 30 | #include <string.h> |
DRC | f8e0055 | 2011-02-04 11:06:36 +0000 | [diff] [blame] | 31 | #include "turbojpeg.h" |
DRC | bc2e66c | 2012-10-02 06:47:37 +0000 | [diff] [blame] | 32 | #ifdef WIN32 |
| 33 | #include "tjutil.h" |
| 34 | #endif |
DRC | f8e0055 | 2011-02-04 11:06:36 +0000 | [diff] [blame] | 35 | #include <jni.h> |
DRC | c5a4199 | 2011-02-08 06:54:36 +0000 | [diff] [blame] | 36 | #include "java/org_libjpegturbo_turbojpeg_TJCompressor.h" |
| 37 | #include "java/org_libjpegturbo_turbojpeg_TJDecompressor.h" |
| 38 | #include "java/org_libjpegturbo_turbojpeg_TJ.h" |
DRC | f8e0055 | 2011-02-04 11:06:36 +0000 | [diff] [blame] | 39 | |
DRC | 293263c | 2018-03-17 15:14:35 -0500 | [diff] [blame] | 40 | #define PAD(v, p) ((v + (p) - 1) & (~((p) - 1))) |
DRC | 40dd314 | 2014-08-17 12:23:49 +0000 | [diff] [blame] | 41 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 42 | #define bailif0(f) { \ |
| 43 | if (!(f) || (*env)->ExceptionCheck(env)) { \ |
| 44 | goto bailout; \ |
| 45 | } \ |
DRC | f8e0055 | 2011-02-04 11:06:36 +0000 | [diff] [blame] | 46 | } |
| 47 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 48 | #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; \ |
DRC | d4092f6 | 2017-06-27 10:54:21 -0500 | [diff] [blame] | 71 | } |
DRC | b3817da | 2015-07-14 20:42:52 +0000 | [diff] [blame] | 72 | |
DRC | 293263c | 2018-03-17 15:14:35 -0500 | [diff] [blame] | 73 | #define _throwarg(msg) _throw(msg, "java/lang/IllegalArgumentException") |
DRC | b3817da | 2015-07-14 20:42:52 +0000 | [diff] [blame] | 74 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 75 | #define _throwmem() \ |
| 76 | _throw("Memory allocation failure", "java/lang/OutOfMemoryError"); |
DRC | b3817da | 2015-07-14 20:42:52 +0000 | [diff] [blame] | 77 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 78 | #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); |
DRC | f8e0055 | 2011-02-04 11:06:36 +0000 | [diff] [blame] | 85 | |
DRC | bdb36e1 | 2014-08-22 15:39:32 +0000 | [diff] [blame] | 86 | #ifdef _WIN32 |
DRC | 293263c | 2018-03-17 15:14:35 -0500 | [diff] [blame] | 87 | #define setenv(envvar, value, dummy) _putenv_s(envvar, value) |
DRC | bdb36e1 | 2014-08-22 15:39:32 +0000 | [diff] [blame] | 88 | #endif |
| 89 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 90 | #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 | } \ |
DRC | 0713c1b | 2014-08-22 13:43:33 +0000 | [diff] [blame] | 99 | } |
| 100 | |
| 101 | int ProcessSystemProperties(JNIEnv *env) |
| 102 | { |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 103 | jclass cls; |
| 104 | jmethodID mid; |
| 105 | jstring jName, jValue; |
| 106 | const char *value; |
DRC | 0713c1b | 2014-08-22 13:43:33 +0000 | [diff] [blame] | 107 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 108 | bailif0(cls = (*env)->FindClass(env, "java/lang/System")); |
| 109 | bailif0(mid = (*env)->GetStaticMethodID(env, cls, "getProperty", |
| 110 | "(Ljava/lang/String;)Ljava/lang/String;")); |
DRC | 0713c1b | 2014-08-22 13:43:33 +0000 | [diff] [blame] | 111 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 112 | 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; |
DRC | 0713c1b | 2014-08-22 13:43:33 +0000 | [diff] [blame] | 117 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 118 | bailout: |
| 119 | return -1; |
DRC | 0713c1b | 2014-08-22 13:43:33 +0000 | [diff] [blame] | 120 | } |
| 121 | |
DRC | a4940d1 | 2014-08-15 16:07:15 +0000 | [diff] [blame] | 122 | /* TurboJPEG 1.2.x: TJ::bufSize() */ |
DRC | 3bad53f | 2011-02-23 02:20:49 +0000 | [diff] [blame] | 123 | JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJ_bufSize |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 124 | (JNIEnv *env, jclass cls, jint width, jint height, jint jpegSubsamp) |
DRC | f8e0055 | 2011-02-04 11:06:36 +0000 | [diff] [blame] | 125 | { |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 126 | jint retval = (jint)tjBufSize(width, height, jpegSubsamp); |
DRC | 36336fc | 2011-02-22 10:27:31 +0000 | [diff] [blame] | 127 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 128 | if (retval == -1) _throwarg(tjGetErrorStr()); |
| 129 | |
| 130 | bailout: |
| 131 | return retval; |
DRC | 36336fc | 2011-02-22 10:27:31 +0000 | [diff] [blame] | 132 | } |
| 133 | |
DRC | a4940d1 | 2014-08-15 16:07:15 +0000 | [diff] [blame] | 134 | /* TurboJPEG 1.4.x: TJ::bufSizeYUV() */ |
DRC | fef9852 | 2013-04-28 01:32:52 +0000 | [diff] [blame] | 135 | JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJ_bufSizeYUV__IIII |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 136 | (JNIEnv *env, jclass cls, jint width, jint pad, jint height, jint subsamp) |
DRC | 36336fc | 2011-02-22 10:27:31 +0000 | [diff] [blame] | 137 | { |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 138 | jint retval = (jint)tjBufSizeYUV2(width, pad, height, subsamp); |
DRC | 36336fc | 2011-02-22 10:27:31 +0000 | [diff] [blame] | 139 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 140 | if (retval == -1) _throwarg(tjGetErrorStr()); |
| 141 | |
| 142 | bailout: |
| 143 | return retval; |
DRC | f8e0055 | 2011-02-04 11:06:36 +0000 | [diff] [blame] | 144 | } |
| 145 | |
DRC | a4940d1 | 2014-08-15 16:07:15 +0000 | [diff] [blame] | 146 | /* TurboJPEG 1.2.x: TJ::bufSizeYUV() */ |
DRC | fef9852 | 2013-04-28 01:32:52 +0000 | [diff] [blame] | 147 | JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJ_bufSizeYUV__III |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 148 | (JNIEnv *env, jclass cls, jint width, jint height, jint subsamp) |
DRC | fef9852 | 2013-04-28 01:32:52 +0000 | [diff] [blame] | 149 | { |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 150 | return Java_org_libjpegturbo_turbojpeg_TJ_bufSizeYUV__IIII(env, cls, width, |
| 151 | 4, height, |
| 152 | subsamp); |
DRC | fef9852 | 2013-04-28 01:32:52 +0000 | [diff] [blame] | 153 | } |
| 154 | |
DRC | 40dd314 | 2014-08-17 12:23:49 +0000 | [diff] [blame] | 155 | /* TurboJPEG 1.4.x: TJ::planeSizeYUV() */ |
| 156 | JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJ_planeSizeYUV__IIIII |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 157 | (JNIEnv *env, jclass cls, jint componentID, jint width, jint stride, |
| 158 | jint height, jint subsamp) |
DRC | 40dd314 | 2014-08-17 12:23:49 +0000 | [diff] [blame] | 159 | { |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 160 | jint retval = (jint)tjPlaneSizeYUV(componentID, width, stride, height, |
| 161 | subsamp); |
DRC | 40dd314 | 2014-08-17 12:23:49 +0000 | [diff] [blame] | 162 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 163 | if (retval == -1) _throwarg(tjGetErrorStr()); |
| 164 | |
| 165 | bailout: |
| 166 | return retval; |
DRC | 40dd314 | 2014-08-17 12:23:49 +0000 | [diff] [blame] | 167 | } |
| 168 | |
| 169 | /* TurboJPEG 1.4.x: TJ::planeWidth() */ |
| 170 | JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJ_planeWidth__III |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 171 | (JNIEnv *env, jclass cls, jint componentID, jint width, jint subsamp) |
DRC | 40dd314 | 2014-08-17 12:23:49 +0000 | [diff] [blame] | 172 | { |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 173 | jint retval = (jint)tjPlaneWidth(componentID, width, subsamp); |
DRC | 40dd314 | 2014-08-17 12:23:49 +0000 | [diff] [blame] | 174 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 175 | if (retval == -1) _throwarg(tjGetErrorStr()); |
| 176 | |
| 177 | bailout: |
| 178 | return retval; |
DRC | 40dd314 | 2014-08-17 12:23:49 +0000 | [diff] [blame] | 179 | } |
| 180 | |
| 181 | /* TurboJPEG 1.4.x: TJ::planeHeight() */ |
| 182 | JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJ_planeHeight__III |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 183 | (JNIEnv *env, jclass cls, jint componentID, jint height, jint subsamp) |
DRC | 40dd314 | 2014-08-17 12:23:49 +0000 | [diff] [blame] | 184 | { |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 185 | jint retval = (jint)tjPlaneHeight(componentID, height, subsamp); |
DRC | 40dd314 | 2014-08-17 12:23:49 +0000 | [diff] [blame] | 186 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 187 | if (retval == -1) _throwarg(tjGetErrorStr()); |
| 188 | |
| 189 | bailout: |
| 190 | return retval; |
DRC | 40dd314 | 2014-08-17 12:23:49 +0000 | [diff] [blame] | 191 | } |
| 192 | |
DRC | a4940d1 | 2014-08-15 16:07:15 +0000 | [diff] [blame] | 193 | /* TurboJPEG 1.2.x: TJCompressor::init() */ |
DRC | c5a4199 | 2011-02-08 06:54:36 +0000 | [diff] [blame] | 194 | JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_init |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 195 | (JNIEnv *env, jobject obj) |
DRC | f8e0055 | 2011-02-04 11:06:36 +0000 | [diff] [blame] | 196 | { |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 197 | jclass cls; |
| 198 | jfieldID fid; |
| 199 | tjhandle handle; |
DRC | f8e0055 | 2011-02-04 11:06:36 +0000 | [diff] [blame] | 200 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 201 | if ((handle = tjInitCompress()) == NULL) |
| 202 | _throw(tjGetErrorStr(), "org/libjpegturbo/turbojpeg/TJException"); |
DRC | f8e0055 | 2011-02-04 11:06:36 +0000 | [diff] [blame] | 203 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 204 | bailif0(cls = (*env)->GetObjectClass(env, obj)); |
| 205 | bailif0(fid = (*env)->GetFieldID(env, cls, "handle", "J")); |
| 206 | (*env)->SetLongField(env, obj, fid, (size_t)handle); |
DRC | f8e0055 | 2011-02-04 11:06:36 +0000 | [diff] [blame] | 207 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 208 | bailout: |
| 209 | return; |
DRC | f8e0055 | 2011-02-04 11:06:36 +0000 | [diff] [blame] | 210 | } |
| 211 | |
DRC | 5d87f6d | 2014-08-15 16:40:56 +0000 | [diff] [blame] | 212 | static jint TJCompressor_compress |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 213 | (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) |
DRC | f8e0055 | 2011-02-04 11:06:36 +0000 | [diff] [blame] | 216 | { |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 217 | tjhandle handle = 0; |
| 218 | unsigned long jpegSize = 0; |
| 219 | jsize arraySize = 0, actualPitch; |
| 220 | unsigned char *srcBuf = NULL, *jpegBuf = NULL; |
DRC | f8e0055 | 2011-02-04 11:06:36 +0000 | [diff] [blame] | 221 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 222 | gethandle(); |
DRC | f8e0055 | 2011-02-04 11:06:36 +0000 | [diff] [blame] | 223 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 224 | 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"); |
DRC | 4f1580c | 2011-02-25 06:11:03 +0000 | [diff] [blame] | 229 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 230 | 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"); |
DRC | 6acf52b | 2011-03-02 01:09:20 +0000 | [diff] [blame] | 237 | |
DRC | 5ea77d8 | 2018-10-26 08:55:22 -0500 | [diff] [blame^] | 238 | if (ProcessSystemProperties(env) < 0) goto bailout; |
| 239 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 240 | bailif0(srcBuf = (*env)->GetPrimitiveArrayCritical(env, src, 0)); |
| 241 | bailif0(jpegBuf = (*env)->GetPrimitiveArrayCritical(env, dst, 0)); |
DRC | f8e0055 | 2011-02-04 11:06:36 +0000 | [diff] [blame] | 242 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 243 | 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(); |
DRC | fac3bea | 2012-09-24 02:27:55 +0000 | [diff] [blame] | 247 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 248 | bailout: |
| 249 | if (jpegBuf) (*env)->ReleasePrimitiveArrayCritical(env, dst, jpegBuf, 0); |
| 250 | if (srcBuf) (*env)->ReleasePrimitiveArrayCritical(env, src, srcBuf, 0); |
| 251 | return (jint)jpegSize; |
DRC | fac3bea | 2012-09-24 02:27:55 +0000 | [diff] [blame] | 252 | } |
| 253 | |
DRC | a4940d1 | 2014-08-15 16:07:15 +0000 | [diff] [blame] | 254 | /* TurboJPEG 1.3.x: TJCompressor::compress() byte source */ |
DRC | 927a10d | 2014-08-15 13:18:58 +0000 | [diff] [blame] | 255 | JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_compress___3BIIIIII_3BIII |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 256 | (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) |
DRC | 927a10d | 2014-08-15 13:18:58 +0000 | [diff] [blame] | 259 | { |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 260 | return TJCompressor_compress(env, obj, src, 1, x, y, width, pitch, height, |
| 261 | pf, dst, jpegSubsamp, jpegQual, flags); |
DRC | 927a10d | 2014-08-15 13:18:58 +0000 | [diff] [blame] | 262 | } |
| 263 | |
DRC | a4940d1 | 2014-08-15 16:07:15 +0000 | [diff] [blame] | 264 | /* TurboJPEG 1.2.x: TJCompressor::compress() byte source */ |
DRC | fac3bea | 2012-09-24 02:27:55 +0000 | [diff] [blame] | 265 | JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_compress___3BIIII_3BIII |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 266 | (JNIEnv *env, jobject obj, jbyteArray src, jint width, jint pitch, |
| 267 | jint height, jint pf, jbyteArray dst, jint jpegSubsamp, jint jpegQual, |
| 268 | jint flags) |
DRC | fac3bea | 2012-09-24 02:27:55 +0000 | [diff] [blame] | 269 | { |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 270 | return TJCompressor_compress(env, obj, src, 1, 0, 0, width, pitch, height, |
| 271 | pf, dst, jpegSubsamp, jpegQual, flags); |
DRC | fac3bea | 2012-09-24 02:27:55 +0000 | [diff] [blame] | 272 | } |
| 273 | |
DRC | a4940d1 | 2014-08-15 16:07:15 +0000 | [diff] [blame] | 274 | /* TurboJPEG 1.3.x: TJCompressor::compress() int source */ |
DRC | fac3bea | 2012-09-24 02:27:55 +0000 | [diff] [blame] | 275 | JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_compress___3IIIIIII_3BIII |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 276 | (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) |
DRC | fac3bea | 2012-09-24 02:27:55 +0000 | [diff] [blame] | 279 | { |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 280 | 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."); |
DRC | fac3bea | 2012-09-24 02:27:55 +0000 | [diff] [blame] | 284 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 285 | return TJCompressor_compress(env, obj, src, sizeof(jint), x, y, width, |
| 286 | stride * sizeof(jint), height, pf, dst, |
| 287 | jpegSubsamp, jpegQual, flags); |
DRC | f8e0055 | 2011-02-04 11:06:36 +0000 | [diff] [blame] | 288 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 289 | bailout: |
| 290 | return 0; |
DRC | f8e0055 | 2011-02-04 11:06:36 +0000 | [diff] [blame] | 291 | } |
| 292 | |
DRC | a4940d1 | 2014-08-15 16:07:15 +0000 | [diff] [blame] | 293 | /* TurboJPEG 1.2.x: TJCompressor::compress() int source */ |
DRC | 4f1580c | 2011-02-25 06:11:03 +0000 | [diff] [blame] | 294 | JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_compress___3IIIII_3BIII |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 295 | (JNIEnv *env, jobject obj, jintArray src, jint width, jint stride, |
| 296 | jint height, jint pf, jbyteArray dst, jint jpegSubsamp, jint jpegQual, |
| 297 | jint flags) |
DRC | 84a1bcc | 2011-02-23 12:09:56 +0000 | [diff] [blame] | 298 | { |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 299 | 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."); |
DRC | 927a10d | 2014-08-15 13:18:58 +0000 | [diff] [blame] | 303 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 304 | return TJCompressor_compress(env, obj, src, sizeof(jint), 0, 0, width, |
| 305 | stride * sizeof(jint), height, pf, dst, |
| 306 | jpegSubsamp, jpegQual, flags); |
DRC | 927a10d | 2014-08-15 13:18:58 +0000 | [diff] [blame] | 307 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 308 | bailout: |
| 309 | return 0; |
DRC | 84a1bcc | 2011-02-23 12:09:56 +0000 | [diff] [blame] | 310 | } |
| 311 | |
DRC | a4940d1 | 2014-08-15 16:07:15 +0000 | [diff] [blame] | 312 | /* TurboJPEG 1.4.x: TJCompressor::compressFromYUV() */ |
DRC | 40dd314 | 2014-08-17 12:23:49 +0000 | [diff] [blame] | 313 | JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_compressFromYUV___3_3B_3II_3III_3BII |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 314 | (JNIEnv *env, jobject obj, jobjectArray srcobjs, jintArray jSrcOffsets, |
| 315 | jint width, jintArray jSrcStrides, jint height, jint subsamp, |
| 316 | jbyteArray dst, jint jpegQual, jint flags) |
DRC | 1e67274 | 2013-10-31 05:04:51 +0000 | [diff] [blame] | 317 | { |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 318 | 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; |
DRC | 1e67274 | 2013-10-31 05:04:51 +0000 | [diff] [blame] | 325 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 326 | gethandle(); |
DRC | 1e67274 | 2013-10-31 05:04:51 +0000 | [diff] [blame] | 327 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 328 | 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"); |
DRC | 40dd314 | 2014-08-17 12:23:49 +0000 | [diff] [blame] | 332 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 333 | 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"); |
DRC | 40dd314 | 2014-08-17 12:23:49 +0000 | [diff] [blame] | 339 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 340 | jpegSize = tjBufSize(width, height, subsamp); |
| 341 | if ((*env)->GetArrayLength(env, dst) < (jsize)jpegSize) |
| 342 | _throwarg("Destination buffer is not large enough"); |
DRC | 1e67274 | 2013-10-31 05:04:51 +0000 | [diff] [blame] | 343 | |
DRC | 5ea77d8 | 2018-10-26 08:55:22 -0500 | [diff] [blame^] | 344 | if (ProcessSystemProperties(env) < 0) goto bailout; |
| 345 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 346 | bailif0(srcOffsets = (*env)->GetPrimitiveArrayCritical(env, jSrcOffsets, 0)); |
| 347 | bailif0(srcStrides = (*env)->GetPrimitiveArrayCritical(env, jSrcStrides, 0)); |
| 348 | for (i = 0; i < nc; i++) { |
| 349 | int planeSize = tjPlaneSizeYUV(i, width, srcStrides[i], height, subsamp); |
| 350 | int pw = tjPlaneWidth(i, width, subsamp); |
DRC | 40dd314 | 2014-08-17 12:23:49 +0000 | [diff] [blame] | 351 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 352 | if (planeSize < 0 || pw < 0) |
| 353 | _throwarg(tjGetErrorStr()); |
DRC | 40dd314 | 2014-08-17 12:23:49 +0000 | [diff] [blame] | 354 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 355 | if (srcOffsets[i] < 0) |
| 356 | _throwarg("Invalid argument in compressFromYUV()"); |
| 357 | if (srcStrides[i] < 0 && srcOffsets[i] - planeSize + pw < 0) |
| 358 | _throwarg("Negative plane stride would cause memory to be accessed below plane boundary"); |
DRC | 40dd314 | 2014-08-17 12:23:49 +0000 | [diff] [blame] | 359 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 360 | bailif0(jSrcPlanes[i] = (*env)->GetObjectArrayElement(env, srcobjs, i)); |
| 361 | if ((*env)->GetArrayLength(env, jSrcPlanes[i]) < srcOffsets[i] + planeSize) |
| 362 | _throwarg("Source plane is not large enough"); |
DRC | 40dd314 | 2014-08-17 12:23:49 +0000 | [diff] [blame] | 363 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 364 | bailif0(srcPlanes[i] = |
| 365 | (*env)->GetPrimitiveArrayCritical(env, jSrcPlanes[i], 0)); |
| 366 | srcPlanes[i] = &srcPlanes[i][srcOffsets[i]]; |
| 367 | } |
| 368 | bailif0(jpegBuf = (*env)->GetPrimitiveArrayCritical(env, dst, 0)); |
DRC | 1e67274 | 2013-10-31 05:04:51 +0000 | [diff] [blame] | 369 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 370 | if (tjCompressFromYUVPlanes(handle, srcPlanes, width, srcStrides, height, |
| 371 | subsamp, &jpegBuf, &jpegSize, jpegQual, |
| 372 | flags | TJFLAG_NOREALLOC) == -1) |
| 373 | _throwtj(); |
DRC | 1e67274 | 2013-10-31 05:04:51 +0000 | [diff] [blame] | 374 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 375 | bailout: |
| 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; |
DRC | 1e67274 | 2013-10-31 05:04:51 +0000 | [diff] [blame] | 387 | } |
| 388 | |
DRC | 5d87f6d | 2014-08-15 16:40:56 +0000 | [diff] [blame] | 389 | static void TJCompressor_encodeYUV |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 390 | (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) |
DRC | 4f1580c | 2011-02-25 06:11:03 +0000 | [diff] [blame] | 393 | { |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 394 | 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; |
DRC | 40dd314 | 2014-08-17 12:23:49 +0000 | [diff] [blame] | 400 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 401 | gethandle(); |
DRC | 40dd314 | 2014-08-17 12:23:49 +0000 | [diff] [blame] | 402 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 403 | 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"); |
DRC | 40dd314 | 2014-08-17 12:23:49 +0000 | [diff] [blame] | 410 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 411 | 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"); |
DRC | 40dd314 | 2014-08-17 12:23:49 +0000 | [diff] [blame] | 417 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 418 | 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"); |
DRC | 40dd314 | 2014-08-17 12:23:49 +0000 | [diff] [blame] | 422 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 423 | 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); |
DRC | 40dd314 | 2014-08-17 12:23:49 +0000 | [diff] [blame] | 428 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 429 | if (planeSize < 0 || pw < 0) |
| 430 | _throwarg(tjGetErrorStr()); |
DRC | 40dd314 | 2014-08-17 12:23:49 +0000 | [diff] [blame] | 431 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 432 | 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"); |
DRC | 40dd314 | 2014-08-17 12:23:49 +0000 | [diff] [blame] | 436 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 437 | 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"); |
DRC | 40dd314 | 2014-08-17 12:23:49 +0000 | [diff] [blame] | 440 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 441 | 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)); |
DRC | 40dd314 | 2014-08-17 12:23:49 +0000 | [diff] [blame] | 446 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 447 | if (tjEncodeYUVPlanes(handle, &srcBuf[y * actualPitch + x * tjPixelSize[pf]], |
| 448 | width, pitch, height, pf, dstPlanes, dstStrides, |
| 449 | subsamp, flags) == -1) |
| 450 | _throwtj(); |
DRC | 40dd314 | 2014-08-17 12:23:49 +0000 | [diff] [blame] | 451 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 452 | bailout: |
| 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); |
DRC | 40dd314 | 2014-08-17 12:23:49 +0000 | [diff] [blame] | 463 | } |
| 464 | |
| 465 | /* TurboJPEG 1.4.x: TJCompressor::encodeYUV() byte source */ |
| 466 | JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_encodeYUV___3BIIIIII_3_3B_3I_3III |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 467 | (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) |
DRC | 40dd314 | 2014-08-17 12:23:49 +0000 | [diff] [blame] | 470 | { |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 471 | TJCompressor_encodeYUV(env, obj, src, 1, x, y, width, pitch, height, pf, |
| 472 | dstobjs, jDstOffsets, jDstStrides, subsamp, flags); |
DRC | 40dd314 | 2014-08-17 12:23:49 +0000 | [diff] [blame] | 473 | } |
| 474 | |
| 475 | /* TurboJPEG 1.4.x: TJCompressor::encodeYUV() int source */ |
| 476 | JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_encodeYUV___3IIIIIII_3_3B_3I_3III |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 477 | (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) |
DRC | 40dd314 | 2014-08-17 12:23:49 +0000 | [diff] [blame] | 480 | { |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 481 | 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."); |
DRC | 40dd314 | 2014-08-17 12:23:49 +0000 | [diff] [blame] | 485 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 486 | TJCompressor_encodeYUV(env, obj, src, sizeof(jint), x, y, width, |
| 487 | stride * sizeof(jint), height, pf, dstobjs, |
| 488 | jDstOffsets, jDstStrides, subsamp, flags); |
DRC | 40dd314 | 2014-08-17 12:23:49 +0000 | [diff] [blame] | 489 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 490 | bailout: |
| 491 | return; |
DRC | 40dd314 | 2014-08-17 12:23:49 +0000 | [diff] [blame] | 492 | } |
| 493 | |
| 494 | JNIEXPORT void JNICALL TJCompressor_encodeYUV_12 |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 495 | (JNIEnv *env, jobject obj, jarray src, jint srcElementSize, jint width, |
| 496 | jint pitch, jint height, jint pf, jbyteArray dst, jint subsamp, jint flags) |
DRC | 40dd314 | 2014-08-17 12:23:49 +0000 | [diff] [blame] | 497 | { |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 498 | tjhandle handle = 0; |
| 499 | jsize arraySize = 0; |
| 500 | unsigned char *srcBuf = NULL, *dstBuf = NULL; |
DRC | 4f1580c | 2011-02-25 06:11:03 +0000 | [diff] [blame] | 501 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 502 | gethandle(); |
DRC | 4f1580c | 2011-02-25 06:11:03 +0000 | [diff] [blame] | 503 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 504 | 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"); |
DRC | 4f1580c | 2011-02-25 06:11:03 +0000 | [diff] [blame] | 509 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 510 | 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"); |
DRC | 6acf52b | 2011-03-02 01:09:20 +0000 | [diff] [blame] | 516 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 517 | bailif0(srcBuf = (*env)->GetPrimitiveArrayCritical(env, src, 0)); |
| 518 | bailif0(dstBuf = (*env)->GetPrimitiveArrayCritical(env, dst, 0)); |
DRC | 4f1580c | 2011-02-25 06:11:03 +0000 | [diff] [blame] | 519 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 520 | if (tjEncodeYUV2(handle, srcBuf, width, pitch, height, pf, dstBuf, subsamp, |
| 521 | flags) == -1) |
| 522 | _throwtj(); |
DRC | 4f1580c | 2011-02-25 06:11:03 +0000 | [diff] [blame] | 523 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 524 | bailout: |
| 525 | if (dstBuf) (*env)->ReleasePrimitiveArrayCritical(env, dst, dstBuf, 0); |
| 526 | if (srcBuf) (*env)->ReleasePrimitiveArrayCritical(env, src, srcBuf, 0); |
DRC | 4f1580c | 2011-02-25 06:11:03 +0000 | [diff] [blame] | 527 | } |
| 528 | |
DRC | a4940d1 | 2014-08-15 16:07:15 +0000 | [diff] [blame] | 529 | /* TurboJPEG 1.2.x: TJCompressor::encodeYUV() byte source */ |
DRC | fef9852 | 2013-04-28 01:32:52 +0000 | [diff] [blame] | 530 | JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_encodeYUV___3BIIII_3BII |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 531 | (JNIEnv *env, jobject obj, jbyteArray src, jint width, jint pitch, |
| 532 | jint height, jint pf, jbyteArray dst, jint subsamp, jint flags) |
DRC | 4f1580c | 2011-02-25 06:11:03 +0000 | [diff] [blame] | 533 | { |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 534 | TJCompressor_encodeYUV_12(env, obj, src, 1, width, pitch, height, pf, dst, |
| 535 | subsamp, flags); |
DRC | 4f1580c | 2011-02-25 06:11:03 +0000 | [diff] [blame] | 536 | } |
| 537 | |
DRC | a4940d1 | 2014-08-15 16:07:15 +0000 | [diff] [blame] | 538 | /* TurboJPEG 1.2.x: TJCompressor::encodeYUV() int source */ |
DRC | fef9852 | 2013-04-28 01:32:52 +0000 | [diff] [blame] | 539 | JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_encodeYUV___3IIIII_3BII |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 540 | (JNIEnv *env, jobject obj, jintArray src, jint width, jint stride, |
| 541 | jint height, jint pf, jbyteArray dst, jint subsamp, jint flags) |
DRC | fef9852 | 2013-04-28 01:32:52 +0000 | [diff] [blame] | 542 | { |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 543 | 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."); |
DRC | 927a10d | 2014-08-15 13:18:58 +0000 | [diff] [blame] | 547 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 548 | TJCompressor_encodeYUV_12(env, obj, src, sizeof(jint), width, |
| 549 | stride * sizeof(jint), height, pf, dst, subsamp, |
| 550 | flags); |
DRC | 927a10d | 2014-08-15 13:18:58 +0000 | [diff] [blame] | 551 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 552 | bailout: |
| 553 | return; |
DRC | fef9852 | 2013-04-28 01:32:52 +0000 | [diff] [blame] | 554 | } |
| 555 | |
DRC | a4940d1 | 2014-08-15 16:07:15 +0000 | [diff] [blame] | 556 | /* TurboJPEG 1.2.x: TJCompressor::destroy() */ |
DRC | c5a4199 | 2011-02-08 06:54:36 +0000 | [diff] [blame] | 557 | JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_destroy |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 558 | (JNIEnv *env, jobject obj) |
DRC | f8e0055 | 2011-02-04 11:06:36 +0000 | [diff] [blame] | 559 | { |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 560 | tjhandle handle = 0; |
DRC | f8e0055 | 2011-02-04 11:06:36 +0000 | [diff] [blame] | 561 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 562 | gethandle(); |
DRC | f8e0055 | 2011-02-04 11:06:36 +0000 | [diff] [blame] | 563 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 564 | if (tjDestroy(handle) == -1) _throwtj(); |
| 565 | (*env)->SetLongField(env, obj, _fid, 0); |
DRC | f8e0055 | 2011-02-04 11:06:36 +0000 | [diff] [blame] | 566 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 567 | bailout: |
| 568 | return; |
DRC | f8e0055 | 2011-02-04 11:06:36 +0000 | [diff] [blame] | 569 | } |
| 570 | |
DRC | a4940d1 | 2014-08-15 16:07:15 +0000 | [diff] [blame] | 571 | /* TurboJPEG 1.2.x: TJDecompressor::init() */ |
DRC | c5a4199 | 2011-02-08 06:54:36 +0000 | [diff] [blame] | 572 | JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_init |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 573 | (JNIEnv *env, jobject obj) |
DRC | f8e0055 | 2011-02-04 11:06:36 +0000 | [diff] [blame] | 574 | { |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 575 | jclass cls; |
| 576 | jfieldID fid; |
| 577 | tjhandle handle; |
DRC | f8e0055 | 2011-02-04 11:06:36 +0000 | [diff] [blame] | 578 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 579 | if ((handle = tjInitDecompress()) == NULL) |
| 580 | _throw(tjGetErrorStr(), "org/libjpegturbo/turbojpeg/TJException"); |
DRC | f8e0055 | 2011-02-04 11:06:36 +0000 | [diff] [blame] | 581 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 582 | bailif0(cls = (*env)->GetObjectClass(env, obj)); |
| 583 | bailif0(fid = (*env)->GetFieldID(env, cls, "handle", "J")); |
| 584 | (*env)->SetLongField(env, obj, fid, (size_t)handle); |
DRC | f8e0055 | 2011-02-04 11:06:36 +0000 | [diff] [blame] | 585 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 586 | bailout: |
| 587 | return; |
DRC | f8e0055 | 2011-02-04 11:06:36 +0000 | [diff] [blame] | 588 | } |
| 589 | |
DRC | a4940d1 | 2014-08-15 16:07:15 +0000 | [diff] [blame] | 590 | /* TurboJPEG 1.2.x: TJDecompressor::getScalingFactors() */ |
DRC | 109a578 | 2011-03-01 09:53:07 +0000 | [diff] [blame] | 591 | JNIEXPORT jobjectArray JNICALL Java_org_libjpegturbo_turbojpeg_TJ_getScalingFactors |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 592 | (JNIEnv *env, jclass cls) |
DRC | 36336fc | 2011-02-22 10:27:31 +0000 | [diff] [blame] | 593 | { |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 594 | jclass sfcls = NULL; |
| 595 | jfieldID fid = 0; |
| 596 | tjscalingfactor *sf = NULL; |
| 597 | int n = 0, i; |
| 598 | jobject sfobj = NULL; |
| 599 | jobjectArray sfjava = NULL; |
DRC | 109a578 | 2011-03-01 09:53:07 +0000 | [diff] [blame] | 600 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 601 | if ((sf = tjGetScalingFactors(&n)) == NULL || n == 0) |
| 602 | _throwarg(tjGetErrorStr()); |
DRC | 36336fc | 2011-02-22 10:27:31 +0000 | [diff] [blame] | 603 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 604 | bailif0(sfcls = (*env)->FindClass(env, |
| 605 | "org/libjpegturbo/turbojpeg/TJScalingFactor")); |
| 606 | bailif0(sfjava = (jobjectArray)(*env)->NewObjectArray(env, n, sfcls, 0)); |
DRC | 36336fc | 2011-02-22 10:27:31 +0000 | [diff] [blame] | 607 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 608 | 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 | } |
DRC | 36336fc | 2011-02-22 10:27:31 +0000 | [diff] [blame] | 616 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 617 | bailout: |
| 618 | return sfjava; |
DRC | 36336fc | 2011-02-22 10:27:31 +0000 | [diff] [blame] | 619 | } |
| 620 | |
DRC | a4940d1 | 2014-08-15 16:07:15 +0000 | [diff] [blame] | 621 | /* TurboJPEG 1.2.x: TJDecompressor::decompressHeader() */ |
DRC | 3bad53f | 2011-02-23 02:20:49 +0000 | [diff] [blame] | 622 | JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompressHeader |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 623 | (JNIEnv *env, jobject obj, jbyteArray src, jint jpegSize) |
DRC | f8e0055 | 2011-02-04 11:06:36 +0000 | [diff] [blame] | 624 | { |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 625 | tjhandle handle = 0; |
| 626 | unsigned char *jpegBuf = NULL; |
| 627 | int width = 0, height = 0, jpegSubsamp = -1, jpegColorspace = -1; |
DRC | f8e0055 | 2011-02-04 11:06:36 +0000 | [diff] [blame] | 628 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 629 | gethandle(); |
DRC | f8e0055 | 2011-02-04 11:06:36 +0000 | [diff] [blame] | 630 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 631 | if ((*env)->GetArrayLength(env, src) < jpegSize) |
| 632 | _throwarg("Source buffer is not large enough"); |
DRC | 6acf52b | 2011-03-02 01:09:20 +0000 | [diff] [blame] | 633 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 634 | bailif0(jpegBuf = (*env)->GetPrimitiveArrayCritical(env, src, 0)); |
DRC | f8e0055 | 2011-02-04 11:06:36 +0000 | [diff] [blame] | 635 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 636 | if (tjDecompressHeader3(handle, jpegBuf, (unsigned long)jpegSize, &width, |
| 637 | &height, &jpegSubsamp, &jpegColorspace) == -1) |
| 638 | _throwtj(); |
DRC | 8951cf0 | 2014-08-14 16:54:04 +0000 | [diff] [blame] | 639 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 640 | (*env)->ReleasePrimitiveArrayCritical(env, src, jpegBuf, 0); |
| 641 | jpegBuf = NULL; |
DRC | f8e0055 | 2011-02-04 11:06:36 +0000 | [diff] [blame] | 642 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 643 | 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); |
DRC | f8e0055 | 2011-02-04 11:06:36 +0000 | [diff] [blame] | 653 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 654 | bailout: |
| 655 | if (jpegBuf) (*env)->ReleasePrimitiveArrayCritical(env, src, jpegBuf, 0); |
DRC | f8e0055 | 2011-02-04 11:06:36 +0000 | [diff] [blame] | 656 | } |
| 657 | |
DRC | 5d87f6d | 2014-08-15 16:40:56 +0000 | [diff] [blame] | 658 | static void TJDecompressor_decompress |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 659 | (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) |
DRC | f8e0055 | 2011-02-04 11:06:36 +0000 | [diff] [blame] | 662 | { |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 663 | tjhandle handle = 0; |
| 664 | jsize arraySize = 0, actualPitch; |
| 665 | unsigned char *jpegBuf = NULL, *dstBuf = NULL; |
DRC | f8e0055 | 2011-02-04 11:06:36 +0000 | [diff] [blame] | 666 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 667 | gethandle(); |
DRC | f8e0055 | 2011-02-04 11:06:36 +0000 | [diff] [blame] | 668 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 669 | 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"); |
DRC | 4f1580c | 2011-02-25 06:11:03 +0000 | [diff] [blame] | 673 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 674 | 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"); |
DRC | 6acf52b | 2011-03-02 01:09:20 +0000 | [diff] [blame] | 680 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 681 | bailif0(jpegBuf = (*env)->GetPrimitiveArrayCritical(env, src, 0)); |
| 682 | bailif0(dstBuf = (*env)->GetPrimitiveArrayCritical(env, dst, 0)); |
DRC | f8e0055 | 2011-02-04 11:06:36 +0000 | [diff] [blame] | 683 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 684 | if (tjDecompress2(handle, jpegBuf, (unsigned long)jpegSize, |
| 685 | &dstBuf[y * actualPitch + x * tjPixelSize[pf]], width, |
| 686 | pitch, height, pf, flags) == -1) |
| 687 | _throwtj(); |
DRC | f659f43 | 2012-06-06 08:41:06 +0000 | [diff] [blame] | 688 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 689 | bailout: |
| 690 | if (dstBuf) (*env)->ReleasePrimitiveArrayCritical(env, dst, dstBuf, 0); |
| 691 | if (jpegBuf) (*env)->ReleasePrimitiveArrayCritical(env, src, jpegBuf, 0); |
DRC | f659f43 | 2012-06-06 08:41:06 +0000 | [diff] [blame] | 692 | } |
| 693 | |
DRC | a4940d1 | 2014-08-15 16:07:15 +0000 | [diff] [blame] | 694 | /* TurboJPEG 1.3.x: TJDecompressor::decompress() byte destination */ |
DRC | 927a10d | 2014-08-15 13:18:58 +0000 | [diff] [blame] | 695 | JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompress___3BI_3BIIIIIII |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 696 | (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) |
DRC | 927a10d | 2014-08-15 13:18:58 +0000 | [diff] [blame] | 698 | { |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 699 | TJDecompressor_decompress(env, obj, src, jpegSize, dst, 1, x, y, width, |
| 700 | pitch, height, pf, flags); |
DRC | 927a10d | 2014-08-15 13:18:58 +0000 | [diff] [blame] | 701 | } |
| 702 | |
DRC | a4940d1 | 2014-08-15 16:07:15 +0000 | [diff] [blame] | 703 | /* TurboJPEG 1.2.x: TJDecompressor::decompress() byte destination */ |
DRC | f659f43 | 2012-06-06 08:41:06 +0000 | [diff] [blame] | 704 | JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompress___3BI_3BIIIII |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 705 | (JNIEnv *env, jobject obj, jbyteArray src, jint jpegSize, jbyteArray dst, |
| 706 | jint width, jint pitch, jint height, jint pf, jint flags) |
DRC | f659f43 | 2012-06-06 08:41:06 +0000 | [diff] [blame] | 707 | { |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 708 | TJDecompressor_decompress(env, obj, src, jpegSize, dst, 1, 0, 0, width, |
| 709 | pitch, height, pf, flags); |
DRC | f659f43 | 2012-06-06 08:41:06 +0000 | [diff] [blame] | 710 | } |
| 711 | |
DRC | a4940d1 | 2014-08-15 16:07:15 +0000 | [diff] [blame] | 712 | /* TurboJPEG 1.3.x: TJDecompressor::decompress() int destination */ |
DRC | f659f43 | 2012-06-06 08:41:06 +0000 | [diff] [blame] | 713 | JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompress___3BI_3IIIIIIII |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 714 | (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) |
DRC | f659f43 | 2012-06-06 08:41:06 +0000 | [diff] [blame] | 716 | { |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 717 | 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."); |
DRC | f659f43 | 2012-06-06 08:41:06 +0000 | [diff] [blame] | 721 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 722 | TJDecompressor_decompress(env, obj, src, jpegSize, dst, sizeof(jint), x, y, |
| 723 | width, stride * sizeof(jint), height, pf, flags); |
DRC | f8e0055 | 2011-02-04 11:06:36 +0000 | [diff] [blame] | 724 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 725 | bailout: |
| 726 | return; |
DRC | f8e0055 | 2011-02-04 11:06:36 +0000 | [diff] [blame] | 727 | } |
| 728 | |
DRC | a4940d1 | 2014-08-15 16:07:15 +0000 | [diff] [blame] | 729 | /* TurboJPEG 1.2.x: TJDecompressor::decompress() int destination */ |
DRC | 4f1580c | 2011-02-25 06:11:03 +0000 | [diff] [blame] | 730 | JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompress___3BI_3IIIIII |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 731 | (JNIEnv *env, jobject obj, jbyteArray src, jint jpegSize, jintArray dst, |
| 732 | jint width, jint stride, jint height, jint pf, jint flags) |
DRC | 84a1bcc | 2011-02-23 12:09:56 +0000 | [diff] [blame] | 733 | { |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 734 | 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."); |
DRC | 927a10d | 2014-08-15 13:18:58 +0000 | [diff] [blame] | 738 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 739 | TJDecompressor_decompress(env, obj, src, jpegSize, dst, sizeof(jint), 0, 0, |
| 740 | width, stride * sizeof(jint), height, pf, flags); |
DRC | 927a10d | 2014-08-15 13:18:58 +0000 | [diff] [blame] | 741 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 742 | bailout: |
| 743 | return; |
DRC | 4f1580c | 2011-02-25 06:11:03 +0000 | [diff] [blame] | 744 | } |
DRC | 84a1bcc | 2011-02-23 12:09:56 +0000 | [diff] [blame] | 745 | |
DRC | a4940d1 | 2014-08-15 16:07:15 +0000 | [diff] [blame] | 746 | /* TurboJPEG 1.4.x: TJDecompressor::decompressToYUV() */ |
DRC | 40dd314 | 2014-08-17 12:23:49 +0000 | [diff] [blame] | 747 | JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompressToYUV___3BI_3_3B_3II_3III |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 748 | (JNIEnv *env, jobject obj, jbyteArray src, jint jpegSize, |
| 749 | jobjectArray dstobjs, jintArray jDstOffsets, jint desiredWidth, |
| 750 | jintArray jDstStrides, jint desiredHeight, jint flags) |
DRC | 4f1580c | 2011-02-25 06:11:03 +0000 | [diff] [blame] | 751 | { |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 752 | 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; |
DRC | 40dd314 | 2014-08-17 12:23:49 +0000 | [diff] [blame] | 759 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 760 | gethandle(); |
DRC | 4f1580c | 2011-02-25 06:11:03 +0000 | [diff] [blame] | 761 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 762 | 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); |
DRC | 4f1580c | 2011-02-25 06:11:03 +0000 | [diff] [blame] | 770 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 771 | nc = (jpegSubsamp == org_libjpegturbo_turbojpeg_TJ_SAMP_GRAY ? 1 : 3); |
DRC | 6acf52b | 2011-03-02 01:09:20 +0000 | [diff] [blame] | 772 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 773 | 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"); |
DRC | 4f1580c | 2011-02-25 06:11:03 +0000 | [diff] [blame] | 788 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 789 | 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); |
DRC | 40dd314 | 2014-08-17 12:23:49 +0000 | [diff] [blame] | 795 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 796 | if (planeSize < 0 || pw < 0) |
| 797 | _throwarg(tjGetErrorStr()); |
DRC | 40dd314 | 2014-08-17 12:23:49 +0000 | [diff] [blame] | 798 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 799 | 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"); |
DRC | 40dd314 | 2014-08-17 12:23:49 +0000 | [diff] [blame] | 803 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 804 | 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"); |
DRC | 40dd314 | 2014-08-17 12:23:49 +0000 | [diff] [blame] | 807 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 808 | 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)); |
DRC | 40dd314 | 2014-08-17 12:23:49 +0000 | [diff] [blame] | 813 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 814 | if (tjDecompressToYUVPlanes(handle, jpegBuf, (unsigned long)jpegSize, |
| 815 | dstPlanes, desiredWidth, dstStrides, |
| 816 | desiredHeight, flags) == -1) |
| 817 | _throwtj(); |
DRC | 40dd314 | 2014-08-17 12:23:49 +0000 | [diff] [blame] | 818 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 819 | bailout: |
| 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); |
DRC | 84a1bcc | 2011-02-23 12:09:56 +0000 | [diff] [blame] | 830 | } |
| 831 | |
DRC | a4940d1 | 2014-08-15 16:07:15 +0000 | [diff] [blame] | 832 | /* TurboJPEG 1.2.x: TJDecompressor::decompressToYUV() */ |
DRC | fef9852 | 2013-04-28 01:32:52 +0000 | [diff] [blame] | 833 | JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompressToYUV___3BI_3BI |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 834 | (JNIEnv *env, jobject obj, jbyteArray src, jint jpegSize, jbyteArray dst, |
| 835 | jint flags) |
DRC | fef9852 | 2013-04-28 01:32:52 +0000 | [diff] [blame] | 836 | { |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 837 | tjhandle handle = 0; |
| 838 | unsigned char *jpegBuf = NULL, *dstBuf = NULL; |
| 839 | int jpegSubsamp = -1, jpegWidth = 0, jpegHeight = 0; |
DRC | fc26b65 | 2014-03-16 22:56:26 +0000 | [diff] [blame] | 840 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 841 | gethandle(); |
DRC | fc26b65 | 2014-03-16 22:56:26 +0000 | [diff] [blame] | 842 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 843 | 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"); |
DRC | 40dd314 | 2014-08-17 12:23:49 +0000 | [diff] [blame] | 854 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 855 | bailif0(jpegBuf = (*env)->GetPrimitiveArrayCritical(env, src, 0)); |
| 856 | bailif0(dstBuf = (*env)->GetPrimitiveArrayCritical(env, dst, 0)); |
DRC | 40dd314 | 2014-08-17 12:23:49 +0000 | [diff] [blame] | 857 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 858 | if (tjDecompressToYUV(handle, jpegBuf, (unsigned long)jpegSize, dstBuf, |
| 859 | flags) == -1) |
| 860 | _throwtj(); |
DRC | 40dd314 | 2014-08-17 12:23:49 +0000 | [diff] [blame] | 861 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 862 | bailout: |
| 863 | if (dstBuf) (*env)->ReleasePrimitiveArrayCritical(env, dst, dstBuf, 0); |
| 864 | if (jpegBuf) (*env)->ReleasePrimitiveArrayCritical(env, src, jpegBuf, 0); |
DRC | 40dd314 | 2014-08-17 12:23:49 +0000 | [diff] [blame] | 865 | } |
| 866 | |
| 867 | static void TJDecompressor_decodeYUV |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 868 | (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) |
DRC | 40dd314 | 2014-08-17 12:23:49 +0000 | [diff] [blame] | 871 | { |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 872 | 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; |
DRC | 40dd314 | 2014-08-17 12:23:49 +0000 | [diff] [blame] | 879 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 880 | gethandle(); |
DRC | 40dd314 | 2014-08-17 12:23:49 +0000 | [diff] [blame] | 881 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 882 | 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"); |
DRC | fc26b65 | 2014-03-16 22:56:26 +0000 | [diff] [blame] | 888 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 889 | 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"); |
DRC | 40dd314 | 2014-08-17 12:23:49 +0000 | [diff] [blame] | 895 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 896 | 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"); |
DRC | fc26b65 | 2014-03-16 22:56:26 +0000 | [diff] [blame] | 900 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 901 | 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); |
DRC | 40dd314 | 2014-08-17 12:23:49 +0000 | [diff] [blame] | 906 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 907 | if (planeSize < 0 || pw < 0) |
| 908 | _throwarg(tjGetErrorStr()); |
DRC | 40dd314 | 2014-08-17 12:23:49 +0000 | [diff] [blame] | 909 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 910 | 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"); |
DRC | 40dd314 | 2014-08-17 12:23:49 +0000 | [diff] [blame] | 914 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 915 | 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"); |
DRC | 40dd314 | 2014-08-17 12:23:49 +0000 | [diff] [blame] | 918 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 919 | 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)); |
DRC | fc26b65 | 2014-03-16 22:56:26 +0000 | [diff] [blame] | 924 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 925 | if (tjDecodeYUVPlanes(handle, srcPlanes, srcStrides, subsamp, |
| 926 | &dstBuf[y * actualPitch + x * tjPixelSize[pf]], width, |
| 927 | pitch, height, pf, flags) == -1) |
| 928 | _throwtj(); |
DRC | fc26b65 | 2014-03-16 22:56:26 +0000 | [diff] [blame] | 929 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 930 | bailout: |
| 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); |
DRC | fc26b65 | 2014-03-16 22:56:26 +0000 | [diff] [blame] | 941 | } |
| 942 | |
DRC | a4940d1 | 2014-08-15 16:07:15 +0000 | [diff] [blame] | 943 | /* TurboJPEG 1.4.x: TJDecompressor::decodeYUV() byte destination */ |
DRC | 40dd314 | 2014-08-17 12:23:49 +0000 | [diff] [blame] | 944 | JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decodeYUV___3_3B_3I_3II_3BIIIIIII |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 945 | (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) |
DRC | 927a10d | 2014-08-15 13:18:58 +0000 | [diff] [blame] | 948 | { |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 949 | TJDecompressor_decodeYUV(env, obj, srcobjs, jSrcOffsets, jSrcStrides, |
| 950 | subsamp, dst, 1, x, y, width, pitch, height, pf, |
| 951 | flags); |
DRC | 927a10d | 2014-08-15 13:18:58 +0000 | [diff] [blame] | 952 | } |
| 953 | |
DRC | a4940d1 | 2014-08-15 16:07:15 +0000 | [diff] [blame] | 954 | /* TurboJPEG 1.4.x: TJDecompressor::decodeYUV() int destination */ |
DRC | 40dd314 | 2014-08-17 12:23:49 +0000 | [diff] [blame] | 955 | JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decodeYUV___3_3B_3I_3II_3IIIIIIII |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 956 | (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) |
DRC | fc26b65 | 2014-03-16 22:56:26 +0000 | [diff] [blame] | 959 | { |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 960 | 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."); |
DRC | fc26b65 | 2014-03-16 22:56:26 +0000 | [diff] [blame] | 964 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 965 | TJDecompressor_decodeYUV(env, obj, srcobjs, jSrcOffsets, jSrcStrides, |
| 966 | subsamp, dst, sizeof(jint), x, y, width, |
| 967 | stride * sizeof(jint), height, pf, flags); |
DRC | fc26b65 | 2014-03-16 22:56:26 +0000 | [diff] [blame] | 968 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 969 | bailout: |
| 970 | return; |
DRC | fc26b65 | 2014-03-16 22:56:26 +0000 | [diff] [blame] | 971 | } |
| 972 | |
DRC | a4940d1 | 2014-08-15 16:07:15 +0000 | [diff] [blame] | 973 | /* TurboJPEG 1.2.x: TJTransformer::init() */ |
DRC | e857301 | 2011-03-04 10:13:59 +0000 | [diff] [blame] | 974 | JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJTransformer_init |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 975 | (JNIEnv *env, jobject obj) |
DRC | e857301 | 2011-03-04 10:13:59 +0000 | [diff] [blame] | 976 | { |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 977 | jclass cls; |
| 978 | jfieldID fid; |
| 979 | tjhandle handle; |
DRC | e857301 | 2011-03-04 10:13:59 +0000 | [diff] [blame] | 980 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 981 | if ((handle = tjInitTransform()) == NULL) |
| 982 | _throw(tjGetErrorStr(), "org/libjpegturbo/turbojpeg/TJException"); |
DRC | e857301 | 2011-03-04 10:13:59 +0000 | [diff] [blame] | 983 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 984 | bailif0(cls = (*env)->GetObjectClass(env, obj)); |
| 985 | bailif0(fid = (*env)->GetFieldID(env, cls, "handle", "J")); |
| 986 | (*env)->SetLongField(env, obj, fid, (size_t)handle); |
DRC | e857301 | 2011-03-04 10:13:59 +0000 | [diff] [blame] | 987 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 988 | bailout: |
| 989 | return; |
DRC | e857301 | 2011-03-04 10:13:59 +0000 | [diff] [blame] | 990 | } |
| 991 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 992 | typedef struct _JNICustomFilterParams { |
| 993 | JNIEnv *env; |
| 994 | jobject tobj; |
| 995 | jobject cfobj; |
DRC | f546711 | 2011-09-20 05:02:19 +0000 | [diff] [blame] | 996 | } JNICustomFilterParams; |
| 997 | |
| 998 | static int JNICustomFilter(short *coeffs, tjregion arrayRegion, |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 999 | tjregion planeRegion, int componentIndex, |
| 1000 | int transformIndex, tjtransform *transform) |
DRC | f546711 | 2011-09-20 05:02:19 +0000 | [diff] [blame] | 1001 | { |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 1002 | 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; |
DRC | f546711 | 2011-09-20 05:02:19 +0000 | [diff] [blame] | 1009 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 1010 | 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)); |
DRC | f546711 | 2011-09-20 05:02:19 +0000 | [diff] [blame] | 1023 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 1024 | 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); |
DRC | f546711 | 2011-09-20 05:02:19 +0000 | [diff] [blame] | 1034 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 1035 | 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); |
DRC | f546711 | 2011-09-20 05:02:19 +0000 | [diff] [blame] | 1044 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 1045 | 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); |
DRC | f546711 | 2011-09-20 05:02:19 +0000 | [diff] [blame] | 1050 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 1051 | return 0; |
DRC | f546711 | 2011-09-20 05:02:19 +0000 | [diff] [blame] | 1052 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 1053 | bailout: |
| 1054 | return -1; |
DRC | f546711 | 2011-09-20 05:02:19 +0000 | [diff] [blame] | 1055 | } |
| 1056 | |
DRC | a4940d1 | 2014-08-15 16:07:15 +0000 | [diff] [blame] | 1057 | /* TurboJPEG 1.2.x: TJTransformer::transform() */ |
DRC | e857301 | 2011-03-04 10:13:59 +0000 | [diff] [blame] | 1058 | JNIEXPORT jintArray JNICALL Java_org_libjpegturbo_turbojpeg_TJTransformer_transform |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 1059 | (JNIEnv *env, jobject obj, jbyteArray jsrcBuf, jint jpegSize, |
| 1060 | jobjectArray dstobjs, jobjectArray tobjs, jint flags) |
DRC | e857301 | 2011-03-04 10:13:59 +0000 | [diff] [blame] | 1061 | { |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 1062 | 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; |
DRC | e857301 | 2011-03-04 10:13:59 +0000 | [diff] [blame] | 1072 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 1073 | gethandle(); |
DRC | e857301 | 2011-03-04 10:13:59 +0000 | [diff] [blame] | 1074 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 1075 | 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); |
DRC | e857301 | 2011-03-04 10:13:59 +0000 | [diff] [blame] | 1083 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 1084 | n = (*env)->GetArrayLength(env, dstobjs); |
| 1085 | if (n != (*env)->GetArrayLength(env, tobjs)) |
| 1086 | _throwarg("Mismatch between size of transforms array and destination buffers array"); |
DRC | e857301 | 2011-03-04 10:13:59 +0000 | [diff] [blame] | 1087 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 1088 | 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(¶ms[i], 0, sizeof(JNICustomFilterParams)); |
| 1104 | } |
DRC | e857301 | 2011-03-04 10:13:59 +0000 | [diff] [blame] | 1105 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 1106 | for (i = 0; i < n; i++) { |
| 1107 | jobject tobj, cfobj; |
DRC | e857301 | 2011-03-04 10:13:59 +0000 | [diff] [blame] | 1108 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 1109 | 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); |
DRC | f546711 | 2011-09-20 05:02:19 +0000 | [diff] [blame] | 1123 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 1124 | 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 *)¶ms[i]; |
| 1133 | } |
| 1134 | } |
DRC | e857301 | 2011-03-04 10:13:59 +0000 | [diff] [blame] | 1135 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 1136 | for (i = 0; i < n; i++) { |
| 1137 | int w = jpegWidth, h = jpegHeight; |
DRC | e857301 | 2011-03-04 10:13:59 +0000 | [diff] [blame] | 1138 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 1139 | 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)); |
DRC | 8951cf0 | 2014-08-14 16:54:04 +0000 | [diff] [blame] | 1150 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 1151 | if (tjTransform(handle, jpegBuf, jpegSize, n, dstBufs, dstSizes, t, |
| 1152 | flags | TJFLAG_NOREALLOC) == -1) |
| 1153 | _throwtj(); |
DRC | e857301 | 2011-03-04 10:13:59 +0000 | [diff] [blame] | 1154 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 1155 | 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; |
DRC | e857301 | 2011-03-04 10:13:59 +0000 | [diff] [blame] | 1161 | |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 1162 | 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 | |
| 1166 | bailout: |
| 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; |
DRC | e857301 | 2011-03-04 10:13:59 +0000 | [diff] [blame] | 1180 | } |
| 1181 | |
DRC | a4940d1 | 2014-08-15 16:07:15 +0000 | [diff] [blame] | 1182 | /* TurboJPEG 1.2.x: TJDecompressor::destroy() */ |
DRC | c5a4199 | 2011-02-08 06:54:36 +0000 | [diff] [blame] | 1183 | JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_destroy |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 1184 | (JNIEnv *env, jobject obj) |
DRC | f8e0055 | 2011-02-04 11:06:36 +0000 | [diff] [blame] | 1185 | { |
DRC | 19c791c | 2018-03-08 10:55:20 -0600 | [diff] [blame] | 1186 | Java_org_libjpegturbo_turbojpeg_TJCompressor_destroy(env, obj); |
DRC | f8e0055 | 2011-02-04 11:06:36 +0000 | [diff] [blame] | 1187 | } |