• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C)2011-2013 D. R. Commander.  All Rights Reserved.
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 
29 #include <stdlib.h>
30 #include <string.h>
31 #include "turbojpeg.h"
32 #ifdef WIN32
33 #include "tjutil.h"
34 #endif
35 #include <jni.h>
36 #include "java/org_libjpegturbo_turbojpeg_TJCompressor.h"
37 #include "java/org_libjpegturbo_turbojpeg_TJDecompressor.h"
38 #include "java/org_libjpegturbo_turbojpeg_TJ.h"
39 
40 #define _throw(msg) {  \
41 	jclass _exccls=(*env)->FindClass(env, "java/lang/Exception");  \
42 	if(!_exccls) goto bailout;  \
43 	(*env)->ThrowNew(env, _exccls, msg);  \
44 	goto bailout;  \
45 }
46 
47 #define bailif0(f) {if(!(f)) {  \
48 	char temps[80];  \
49 	snprintf(temps, 80, "Unexpected NULL condition in line %d", __LINE__);  \
50 	_throw(temps);  \
51 }}
52 
53 #define gethandle()  \
54 	jclass _cls=(*env)->GetObjectClass(env, obj);  \
55 	jfieldID _fid;  \
56 	if(!_cls) goto bailout;  \
57 	bailif0(_fid=(*env)->GetFieldID(env, _cls, "handle", "J"));  \
58 	handle=(tjhandle)(jlong)(*env)->GetLongField(env, obj, _fid);  \
59 
Java_org_libjpegturbo_turbojpeg_TJ_bufSize(JNIEnv * env,jclass cls,jint width,jint height,jint jpegSubsamp)60 JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJ_bufSize
61 	(JNIEnv *env, jclass cls, jint width, jint height, jint jpegSubsamp)
62 {
63 	jint retval=(jint)tjBufSize(width, height, jpegSubsamp);
64 	if(retval==-1) _throw(tjGetErrorStr());
65 
66 	bailout:
67 	return retval;
68 }
69 
Java_org_libjpegturbo_turbojpeg_TJ_bufSizeYUV(JNIEnv * env,jclass cls,jint width,jint height,jint subsamp)70 JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJ_bufSizeYUV
71 	(JNIEnv *env, jclass cls, jint width, jint height, jint subsamp)
72 {
73 	jint retval=(jint)tjBufSizeYUV(width, height, subsamp);
74 	if(retval==-1) _throw(tjGetErrorStr());
75 
76 	bailout:
77 	return retval;
78 }
79 
Java_org_libjpegturbo_turbojpeg_TJCompressor_init(JNIEnv * env,jobject obj)80 JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_init
81 	(JNIEnv *env, jobject obj)
82 {
83 	jclass cls;
84 	jfieldID fid;
85 	tjhandle handle;
86 
87 	if((handle=tjInitCompress())==NULL)
88 		_throw(tjGetErrorStr());
89 
90 	bailif0(cls=(*env)->GetObjectClass(env, obj));
91 	bailif0(fid=(*env)->GetFieldID(env, cls, "handle", "J"));
92 	(*env)->SetLongField(env, obj, fid, (jlong)handle);
93 
94 	bailout:
95 	return;
96 }
97 
Java_org_libjpegturbo_turbojpeg_TJCompressor_compress___3BIIIIII_3BIII(JNIEnv * env,jobject obj,jbyteArray src,jint x,jint y,jint width,jint pitch,jint height,jint pf,jbyteArray dst,jint jpegSubsamp,jint jpegQual,jint flags)98 JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_compress___3BIIIIII_3BIII
99 	(JNIEnv *env, jobject obj, jbyteArray src, jint x, jint y, jint width,
100 		jint pitch, jint height, jint pf, jbyteArray dst, jint jpegSubsamp,
101 		jint jpegQual, jint flags)
102 {
103 	tjhandle handle=0;
104 	unsigned long jpegSize=0;
105 	jsize arraySize=0, actualPitch;
106 	unsigned char *srcBuf=NULL, *jpegBuf=NULL;
107 
108 	gethandle();
109 
110 	if(pf<0 || pf>=org_libjpegturbo_turbojpeg_TJ_NUMPF || width<1 || height<1
111 		|| pitch<0)
112 		_throw("Invalid argument in compress()");
113 	if(org_libjpegturbo_turbojpeg_TJ_NUMPF!=TJ_NUMPF)
114 		_throw("Mismatch between Java and C API");
115 
116 	actualPitch=(pitch==0)? width*tjPixelSize[pf]:pitch;
117 	arraySize=(y+height-1)*actualPitch + x+width;
118 	if((*env)->GetArrayLength(env, src)<arraySize)
119 		_throw("Source buffer is not large enough");
120 	jpegSize=tjBufSize(width, height, jpegSubsamp);
121 	if((*env)->GetArrayLength(env, dst)<(jsize)jpegSize)
122 		_throw("Destination buffer is not large enough");
123 
124 	bailif0(srcBuf=(*env)->GetPrimitiveArrayCritical(env, src, 0));
125 	bailif0(jpegBuf=(*env)->GetPrimitiveArrayCritical(env, dst, 0));
126 
127 	if(tjCompress2(handle, &srcBuf[y*actualPitch + x*tjPixelSize[pf]], width,
128 		pitch, height, pf, &jpegBuf, &jpegSize, jpegSubsamp, jpegQual,
129 		flags|TJFLAG_NOREALLOC)==-1)
130 	{
131 		(*env)->ReleasePrimitiveArrayCritical(env, dst, jpegBuf, 0);
132 		(*env)->ReleasePrimitiveArrayCritical(env, src, srcBuf, 0);
133 		jpegBuf=srcBuf=NULL;
134 		_throw(tjGetErrorStr());
135 	}
136 
137 	bailout:
138 	if(jpegBuf) (*env)->ReleasePrimitiveArrayCritical(env, dst, jpegBuf, 0);
139 	if(srcBuf) (*env)->ReleasePrimitiveArrayCritical(env, src, srcBuf, 0);
140 	return (jint)jpegSize;
141 }
142 
Java_org_libjpegturbo_turbojpeg_TJCompressor_compress___3BIIII_3BIII(JNIEnv * env,jobject obj,jbyteArray src,jint width,jint pitch,jint height,jint pf,jbyteArray dst,jint jpegSubsamp,jint jpegQual,jint flags)143 JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_compress___3BIIII_3BIII
144 	(JNIEnv *env, jobject obj, jbyteArray src, jint width, jint pitch,
145 		jint height, jint pf, jbyteArray dst, jint jpegSubsamp, jint jpegQual,
146 		jint flags)
147 {
148 	return Java_org_libjpegturbo_turbojpeg_TJCompressor_compress___3BIIIIII_3BIII(
149 		env, obj, src, 0, 0, width, pitch, height, pf, dst, jpegSubsamp, jpegQual,
150 		flags);
151 }
152 
Java_org_libjpegturbo_turbojpeg_TJCompressor_compress___3IIIIIII_3BIII(JNIEnv * env,jobject obj,jintArray src,jint x,jint y,jint width,jint stride,jint height,jint pf,jbyteArray dst,jint jpegSubsamp,jint jpegQual,jint flags)153 JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_compress___3IIIIIII_3BIII
154 	(JNIEnv *env, jobject obj, jintArray src, jint x, jint y, jint width,
155 		jint stride, jint height, jint pf, jbyteArray dst, jint jpegSubsamp,
156 		jint jpegQual, jint flags)
157 {
158 	tjhandle handle=0;
159 	unsigned long jpegSize=0;
160 	jsize arraySize=0, actualStride;
161 	unsigned char *srcBuf=NULL, *jpegBuf=NULL;
162 
163 	gethandle();
164 
165 	if(pf<0 || pf>=org_libjpegturbo_turbojpeg_TJ_NUMPF || width<1 || height<1
166 		|| stride<0)
167 		_throw("Invalid argument in compress()");
168 	if(org_libjpegturbo_turbojpeg_TJ_NUMPF!=TJ_NUMPF)
169 		_throw("Mismatch between Java and C API");
170 	if(tjPixelSize[pf]!=sizeof(jint))
171 		_throw("Pixel format must be 32-bit when compressing from an integer buffer.");
172 
173 	actualStride=(stride==0)? width:stride;
174 	arraySize=(y+height-1)*actualStride + x+width;
175 	if((*env)->GetArrayLength(env, src)<arraySize)
176 		_throw("Source buffer is not large enough");
177 	jpegSize=tjBufSize(width, height, jpegSubsamp);
178 	if((*env)->GetArrayLength(env, dst)<(jsize)jpegSize)
179 		_throw("Destination buffer is not large enough");
180 
181 	bailif0(srcBuf=(*env)->GetPrimitiveArrayCritical(env, src, 0));
182 	bailif0(jpegBuf=(*env)->GetPrimitiveArrayCritical(env, dst, 0));
183 
184 	if(tjCompress2(handle, &srcBuf[(y*actualStride + x)*sizeof(int)], width,
185 		stride*sizeof(jint), height, pf, &jpegBuf, &jpegSize, jpegSubsamp,
186 		jpegQual, flags|TJFLAG_NOREALLOC)==-1)
187 	{
188 		(*env)->ReleasePrimitiveArrayCritical(env, dst, jpegBuf, 0);
189 		(*env)->ReleasePrimitiveArrayCritical(env, src, srcBuf, 0);
190 		jpegBuf=srcBuf=NULL;
191 		_throw(tjGetErrorStr());
192 	}
193 
194 	bailout:
195 	if(jpegBuf) (*env)->ReleasePrimitiveArrayCritical(env, dst, jpegBuf, 0);
196 	if(srcBuf) (*env)->ReleasePrimitiveArrayCritical(env, src, srcBuf, 0);
197 	return (jint)jpegSize;
198 }
199 
Java_org_libjpegturbo_turbojpeg_TJCompressor_compress___3IIIII_3BIII(JNIEnv * env,jobject obj,jintArray src,jint width,jint pitch,jint height,jint pf,jbyteArray dst,jint jpegSubsamp,jint jpegQual,jint flags)200 JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_compress___3IIIII_3BIII
201 	(JNIEnv *env, jobject obj, jintArray src, jint width, jint pitch,
202 		jint height, jint pf, jbyteArray dst, jint jpegSubsamp, jint jpegQual,
203 		jint flags)
204 {
205 	return Java_org_libjpegturbo_turbojpeg_TJCompressor_compress___3IIIIIII_3BIII(
206 		env, obj, src, 0, 0, width, pitch, height, pf, dst, jpegSubsamp, jpegQual,
207 		flags);
208 }
209 
Java_org_libjpegturbo_turbojpeg_TJCompressor_encodeYUV___3BIIII_3BII(JNIEnv * env,jobject obj,jbyteArray src,jint width,jint pitch,jint height,jint pf,jbyteArray dst,jint subsamp,jint flags)210 JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_encodeYUV___3BIIII_3BII
211 	(JNIEnv *env, jobject obj, jbyteArray src, jint width, jint pitch,
212 		jint height, jint pf, jbyteArray dst, jint subsamp, jint flags)
213 {
214 	tjhandle handle=0;
215 	jsize arraySize=0;
216 	unsigned char *srcBuf=NULL, *dstBuf=NULL;
217 
218 	gethandle();
219 
220 	if(pf<0 || pf>=org_libjpegturbo_turbojpeg_TJ_NUMPF || width<1 || height<1
221 		|| pitch<0)
222 		_throw("Invalid argument in encodeYUV()");
223 	if(org_libjpegturbo_turbojpeg_TJ_NUMPF!=TJ_NUMPF)
224 		_throw("Mismatch between Java and C API");
225 
226 	arraySize=(pitch==0)? width*tjPixelSize[pf]*height:pitch*height;
227 	if((*env)->GetArrayLength(env, src)<arraySize)
228 		_throw("Source buffer is not large enough");
229 	if((*env)->GetArrayLength(env, dst)
230 		<(jsize)tjBufSizeYUV(width, height, subsamp))
231 		_throw("Destination buffer is not large enough");
232 
233 	bailif0(srcBuf=(*env)->GetPrimitiveArrayCritical(env, src, 0));
234 	bailif0(dstBuf=(*env)->GetPrimitiveArrayCritical(env, dst, 0));
235 
236 	if(tjEncodeYUV2(handle, srcBuf, width, pitch, height, pf, dstBuf, subsamp,
237 		flags)==-1)
238 	{
239 		(*env)->ReleasePrimitiveArrayCritical(env, dst, dstBuf, 0);
240 		(*env)->ReleasePrimitiveArrayCritical(env, src, srcBuf, 0);
241 		dstBuf=srcBuf=NULL;
242 		_throw(tjGetErrorStr());
243 	}
244 
245 	bailout:
246 	if(dstBuf) (*env)->ReleasePrimitiveArrayCritical(env, dst, dstBuf, 0);
247 	if(srcBuf) (*env)->ReleasePrimitiveArrayCritical(env, src, srcBuf, 0);
248 	return;
249 }
250 
Java_org_libjpegturbo_turbojpeg_TJCompressor_encodeYUV___3IIIII_3BII(JNIEnv * env,jobject obj,jintArray src,jint width,jint stride,jint height,jint pf,jbyteArray dst,jint subsamp,jint flags)251 JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_encodeYUV___3IIIII_3BII
252 	(JNIEnv *env, jobject obj, jintArray src, jint width, jint stride,
253 		jint height, jint pf, jbyteArray dst, jint subsamp, jint flags)
254 {
255 	tjhandle handle=0;
256 	jsize arraySize=0;
257 	unsigned char *srcBuf=NULL, *dstBuf=NULL;
258 
259 	gethandle();
260 
261 	if(pf<0 || pf>=org_libjpegturbo_turbojpeg_TJ_NUMPF || width<1 || height<1
262 		|| stride<0)
263 		_throw("Invalid argument in encodeYUV()");
264 	if(org_libjpegturbo_turbojpeg_TJ_NUMPF!=TJ_NUMPF)
265 		_throw("Mismatch between Java and C API");
266 	if(tjPixelSize[pf]!=sizeof(jint))
267 		_throw("Pixel format must be 32-bit when encoding from an integer buffer.");
268 
269 	arraySize=(stride==0)? width*height:stride*height;
270 	if((*env)->GetArrayLength(env, src)<arraySize)
271 		_throw("Source buffer is not large enough");
272 	if((*env)->GetArrayLength(env, dst)
273 		<(jsize)tjBufSizeYUV(width, height, subsamp))
274 		_throw("Destination buffer is not large enough");
275 
276 	bailif0(srcBuf=(*env)->GetPrimitiveArrayCritical(env, src, 0));
277 	bailif0(dstBuf=(*env)->GetPrimitiveArrayCritical(env, dst, 0));
278 
279 	if(tjEncodeYUV2(handle, srcBuf, width, stride*sizeof(jint), height, pf,
280 		dstBuf, subsamp, flags)==-1)
281 	{
282 		(*env)->ReleasePrimitiveArrayCritical(env, dst, dstBuf, 0);
283 		(*env)->ReleasePrimitiveArrayCritical(env, src, srcBuf, 0);
284 		dstBuf=srcBuf=NULL;
285 		_throw(tjGetErrorStr());
286 	}
287 
288 	bailout:
289 	if(dstBuf) (*env)->ReleasePrimitiveArrayCritical(env, dst, dstBuf, 0);
290 	if(srcBuf) (*env)->ReleasePrimitiveArrayCritical(env, src, srcBuf, 0);
291 	return;
292 }
293 
Java_org_libjpegturbo_turbojpeg_TJCompressor_destroy(JNIEnv * env,jobject obj)294 JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_destroy
295 	(JNIEnv *env, jobject obj)
296 {
297 	tjhandle handle=0;
298 
299 	gethandle();
300 
301 	if(tjDestroy(handle)==-1) _throw(tjGetErrorStr());
302 	(*env)->SetLongField(env, obj, _fid, 0);
303 
304 	bailout:
305 	return;
306 }
307 
Java_org_libjpegturbo_turbojpeg_TJDecompressor_init(JNIEnv * env,jobject obj)308 JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_init
309 	(JNIEnv *env, jobject obj)
310 {
311 	jclass cls;
312 	jfieldID fid;
313 	tjhandle handle;
314 
315 	if((handle=tjInitDecompress())==NULL) _throw(tjGetErrorStr());
316 
317 	bailif0(cls=(*env)->GetObjectClass(env, obj));
318 	bailif0(fid=(*env)->GetFieldID(env, cls, "handle", "J"));
319 	(*env)->SetLongField(env, obj, fid, (jlong)handle);
320 
321 	bailout:
322 	return;
323 }
324 
Java_org_libjpegturbo_turbojpeg_TJ_getScalingFactors(JNIEnv * env,jclass cls)325 JNIEXPORT jobjectArray JNICALL Java_org_libjpegturbo_turbojpeg_TJ_getScalingFactors
326 	(JNIEnv *env, jclass cls)
327 {
328   jclass sfcls=NULL;  jfieldID fid=0;
329 	tjscalingfactor *sf=NULL;  int n=0, i;
330 	jobject sfobj=NULL;
331 	jobjectArray sfjava=NULL;
332 
333 	if((sf=tjGetScalingFactors(&n))==NULL || n==0)
334 		_throw(tjGetErrorStr());
335 
336 	bailif0(sfcls=(*env)->FindClass(env, "org/libjpegturbo/turbojpeg/TJScalingFactor"));
337 	bailif0(sfjava=(jobjectArray)(*env)->NewObjectArray(env, n, sfcls, 0));
338 
339 	for(i=0; i<n; i++)
340 	{
341 		bailif0(sfobj=(*env)->AllocObject(env, sfcls));
342 		bailif0(fid=(*env)->GetFieldID(env, sfcls, "num", "I"));
343 		(*env)->SetIntField(env, sfobj, fid, sf[i].num);
344 		bailif0(fid=(*env)->GetFieldID(env, sfcls, "denom", "I"));
345 		(*env)->SetIntField(env, sfobj, fid, sf[i].denom);
346 		(*env)->SetObjectArrayElement(env, sfjava, i, sfobj);
347 	}
348 
349 	bailout:
350 	return sfjava;
351 }
352 
Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompressHeader(JNIEnv * env,jobject obj,jbyteArray src,jint jpegSize)353 JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompressHeader
354 	(JNIEnv *env, jobject obj, jbyteArray src, jint jpegSize)
355 {
356 	tjhandle handle=0;
357 	unsigned char *jpegBuf=NULL;
358 	int width=0, height=0, jpegSubsamp=-1;
359 
360 	gethandle();
361 
362 	if((*env)->GetArrayLength(env, src)<jpegSize)
363 		_throw("Source buffer is not large enough");
364 
365 	bailif0(jpegBuf=(*env)->GetPrimitiveArrayCritical(env, src, 0));
366 
367 	if(tjDecompressHeader2(handle, jpegBuf, (unsigned long)jpegSize,
368 		&width, &height, &jpegSubsamp)==-1)
369 	{
370 		(*env)->ReleasePrimitiveArrayCritical(env, src, jpegBuf, 0);
371 		_throw(tjGetErrorStr());
372 	}
373 	(*env)->ReleasePrimitiveArrayCritical(env, src, jpegBuf, 0);  jpegBuf=NULL;
374 
375 	bailif0(_fid=(*env)->GetFieldID(env, _cls, "jpegSubsamp", "I"));
376 	(*env)->SetIntField(env, obj, _fid, jpegSubsamp);
377 	bailif0(_fid=(*env)->GetFieldID(env, _cls, "jpegWidth", "I"));
378 	(*env)->SetIntField(env, obj, _fid, width);
379 	bailif0(_fid=(*env)->GetFieldID(env, _cls, "jpegHeight", "I"));
380 	(*env)->SetIntField(env, obj, _fid, height);
381 
382 	bailout:
383 	return;
384 }
385 
Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompress___3BI_3BIIIIIII(JNIEnv * env,jobject obj,jbyteArray src,jint jpegSize,jbyteArray dst,jint x,jint y,jint width,jint pitch,jint height,jint pf,jint flags)386 JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompress___3BI_3BIIIIIII
387 	(JNIEnv *env, jobject obj, jbyteArray src, jint jpegSize, jbyteArray dst,
388 		jint x, jint y, jint width, jint pitch, jint height, jint pf, jint flags)
389 {
390 	tjhandle handle=0;
391 	jsize arraySize=0, actualPitch;
392 	unsigned char *jpegBuf=NULL, *dstBuf=NULL;
393 
394 	gethandle();
395 
396 	if(pf<0 || pf>=org_libjpegturbo_turbojpeg_TJ_NUMPF)
397 		_throw("Invalid argument in decompress()");
398 	if(org_libjpegturbo_turbojpeg_TJ_NUMPF!=TJ_NUMPF)
399 		_throw("Mismatch between Java and C API");
400 
401 	if((*env)->GetArrayLength(env, src)<jpegSize)
402 		_throw("Source buffer is not large enough");
403 	actualPitch=(pitch==0)? width*tjPixelSize[pf]:pitch;
404 	arraySize=(y+height-1)*actualPitch + (x+width)*tjPixelSize[pf];
405 	if((*env)->GetArrayLength(env, dst)<arraySize)
406 		_throw("Destination buffer is not large enough");
407 
408 	bailif0(jpegBuf=(*env)->GetPrimitiveArrayCritical(env, src, 0));
409 	bailif0(dstBuf=(*env)->GetPrimitiveArrayCritical(env, dst, 0));
410 
411 	if(tjDecompress2(handle, jpegBuf, (unsigned long)jpegSize,
412 		&dstBuf[y*actualPitch + x*tjPixelSize[pf]], width, pitch, height, pf,
413 		flags)==-1)
414 	{
415 		(*env)->ReleasePrimitiveArrayCritical(env, dst, dstBuf, 0);
416 		(*env)->ReleasePrimitiveArrayCritical(env, src, jpegBuf, 0);
417 		dstBuf=jpegBuf=NULL;
418 		_throw(tjGetErrorStr());
419 	}
420 
421 	bailout:
422 	if(dstBuf) (*env)->ReleasePrimitiveArrayCritical(env, dst, dstBuf, 0);
423 	if(jpegBuf) (*env)->ReleasePrimitiveArrayCritical(env, src, jpegBuf, 0);
424 	return;
425 }
426 
Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompress___3BI_3BIIIII(JNIEnv * env,jobject obj,jbyteArray src,jint jpegSize,jbyteArray dst,jint width,jint pitch,jint height,jint pf,jint flags)427 JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompress___3BI_3BIIIII
428 	(JNIEnv *env, jobject obj, jbyteArray src, jint jpegSize, jbyteArray dst,
429 		jint width, jint pitch, jint height, jint pf, jint flags)
430 {
431 	Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompress___3BI_3BIIIIIII
432 		(env, obj, src, jpegSize, dst, 0, 0, width, pitch, height, pf, flags);
433 }
434 
Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompress___3BI_3IIIIIIII(JNIEnv * env,jobject obj,jbyteArray src,jint jpegSize,jintArray dst,jint x,jint y,jint width,jint stride,jint height,jint pf,jint flags)435 JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompress___3BI_3IIIIIIII
436 	(JNIEnv *env, jobject obj, jbyteArray src, jint jpegSize, jintArray dst,
437 		jint x, jint y, jint width, jint stride, jint height, jint pf, jint flags)
438 {
439 	tjhandle handle=0;
440 	jsize arraySize=0, actualStride;
441 	unsigned char *jpegBuf=NULL, *dstBuf=NULL;
442 
443 	gethandle();
444 
445 	if(pf<0 || pf>=org_libjpegturbo_turbojpeg_TJ_NUMPF)
446 		_throw("Invalid argument in decompress()");
447 	if(org_libjpegturbo_turbojpeg_TJ_NUMPF!=TJ_NUMPF)
448 		_throw("Mismatch between Java and C API");
449 	if(tjPixelSize[pf]!=sizeof(jint))
450 		_throw("Pixel format must be 32-bit when decompressing to an integer buffer.");
451 
452 	if((*env)->GetArrayLength(env, src)<jpegSize)
453 		_throw("Source buffer is not large enough");
454 	actualStride=(stride==0)? width:stride;
455 	arraySize=(y+height-1)*actualStride + x+width;
456 	if((*env)->GetArrayLength(env, dst)<arraySize)
457 		_throw("Destination buffer is not large enough");
458 
459 	bailif0(jpegBuf=(*env)->GetPrimitiveArrayCritical(env, src, 0));
460 	bailif0(dstBuf=(*env)->GetPrimitiveArrayCritical(env, dst, 0));
461 
462 	if(tjDecompress2(handle, jpegBuf, (unsigned long)jpegSize,
463 		&dstBuf[(y*actualStride + x)*sizeof(int)], width, stride*sizeof(jint),
464 		height, pf, flags)==-1)
465 	{
466 		(*env)->ReleasePrimitiveArrayCritical(env, dst, dstBuf, 0);
467 		(*env)->ReleasePrimitiveArrayCritical(env, src, jpegBuf, 0);
468 		dstBuf=jpegBuf=NULL;
469 		_throw(tjGetErrorStr());
470 	}
471 
472 	bailout:
473 	if(dstBuf) (*env)->ReleasePrimitiveArrayCritical(env, dst, dstBuf, 0);
474 	if(jpegBuf) (*env)->ReleasePrimitiveArrayCritical(env, src, jpegBuf, 0);
475 	return;
476 }
477 
Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompress___3BI_3IIIIII(JNIEnv * env,jobject obj,jbyteArray src,jint jpegSize,jintArray dst,jint width,jint stride,jint height,jint pf,jint flags)478 JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompress___3BI_3IIIIII
479 	(JNIEnv *env, jobject obj, jbyteArray src, jint jpegSize, jintArray dst,
480 		jint width, jint stride, jint height, jint pf, jint flags)
481 {
482 	Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompress___3BI_3IIIIIIII
483 		(env, obj, src, jpegSize, dst, 0, 0, width, stride, height, pf, flags);
484 
485 }
486 
Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompressToYUV(JNIEnv * env,jobject obj,jbyteArray src,jint jpegSize,jbyteArray dst,jint flags)487 JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompressToYUV
488 	(JNIEnv *env, jobject obj, jbyteArray src, jint jpegSize, jbyteArray dst,
489 		jint flags)
490 {
491 	tjhandle handle=0;
492 	unsigned char *jpegBuf=NULL, *dstBuf=NULL;
493 	int jpegSubsamp=-1, jpegWidth=0, jpegHeight=0;
494 
495 	gethandle();
496 
497 	if((*env)->GetArrayLength(env, src)<jpegSize)
498 		_throw("Source buffer is not large enough");
499 	bailif0(_fid=(*env)->GetFieldID(env, _cls, "jpegSubsamp", "I"));
500 	jpegSubsamp=(int)(*env)->GetIntField(env, obj, _fid);
501 	bailif0(_fid=(*env)->GetFieldID(env, _cls, "jpegWidth", "I"));
502 	jpegWidth=(int)(*env)->GetIntField(env, obj, _fid);
503 	bailif0(_fid=(*env)->GetFieldID(env, _cls, "jpegHeight", "I"));
504 	jpegHeight=(int)(*env)->GetIntField(env, obj, _fid);
505 	if((*env)->GetArrayLength(env, dst)
506 		<(jsize)tjBufSizeYUV(jpegWidth, jpegHeight, jpegSubsamp))
507 		_throw("Destination buffer is not large enough");
508 
509 	bailif0(jpegBuf=(*env)->GetPrimitiveArrayCritical(env, src, 0));
510 	bailif0(dstBuf=(*env)->GetPrimitiveArrayCritical(env, dst, 0));
511 
512 	if(tjDecompressToYUV(handle, jpegBuf, (unsigned long)jpegSize, dstBuf,
513 		flags)==-1)
514 	{
515 		(*env)->ReleasePrimitiveArrayCritical(env, dst, dstBuf, 0);
516 		(*env)->ReleasePrimitiveArrayCritical(env, src, jpegBuf, 0);
517 		dstBuf=jpegBuf=NULL;
518 		_throw(tjGetErrorStr());
519 	}
520 
521 	bailout:
522 	if(dstBuf) (*env)->ReleasePrimitiveArrayCritical(env, dst, dstBuf, 0);
523 	if(jpegBuf) (*env)->ReleasePrimitiveArrayCritical(env, src, jpegBuf, 0);
524 	return;
525 }
526 
Java_org_libjpegturbo_turbojpeg_TJTransformer_init(JNIEnv * env,jobject obj)527 JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJTransformer_init
528 	(JNIEnv *env, jobject obj)
529 {
530 	jclass cls;
531 	jfieldID fid;
532 	tjhandle handle;
533 
534 	if((handle=tjInitTransform())==NULL) _throw(tjGetErrorStr());
535 
536 	bailif0(cls=(*env)->GetObjectClass(env, obj));
537 	bailif0(fid=(*env)->GetFieldID(env, cls, "handle", "J"));
538 	(*env)->SetLongField(env, obj, fid, (jlong)handle);
539 
540 	bailout:
541 	return;
542 }
543 
544 typedef struct _JNICustomFilterParams
545 {
546 	JNIEnv *env;
547 	jobject tobj;
548 	jobject cfobj;
549 } JNICustomFilterParams;
550 
JNICustomFilter(short * coeffs,tjregion arrayRegion,tjregion planeRegion,int componentIndex,int transformIndex,tjtransform * transform)551 static int JNICustomFilter(short *coeffs, tjregion arrayRegion,
552 	tjregion planeRegion, int componentIndex, int transformIndex,
553 	tjtransform *transform)
554 {
555 	JNICustomFilterParams *params=(JNICustomFilterParams *)transform->data;
556 	JNIEnv *env=params->env;
557 	jobject tobj=params->tobj, cfobj=params->cfobj;
558   jobject arrayRegionObj, planeRegionObj, bufobj, borobj;
559 	jclass cls;  jmethodID mid;  jfieldID fid;
560 
561 	bailif0(bufobj=(*env)->NewDirectByteBuffer(env, coeffs,
562 		sizeof(short)*arrayRegion.w*arrayRegion.h));
563 	bailif0(cls=(*env)->FindClass(env, "java/nio/ByteOrder"));
564   bailif0(mid=(*env)->GetStaticMethodID(env, cls, "nativeOrder",
565 		"()Ljava/nio/ByteOrder;"));
566 	bailif0(borobj=(*env)->CallStaticObjectMethod(env, cls, mid));
567 	bailif0(cls=(*env)->GetObjectClass(env, bufobj));
568 	bailif0(mid=(*env)->GetMethodID(env, cls, "order",
569 		"(Ljava/nio/ByteOrder;)Ljava/nio/ByteBuffer;"));
570 	(*env)->CallObjectMethod(env, bufobj, mid, borobj);
571   bailif0(mid=(*env)->GetMethodID(env, cls, "asShortBuffer",
572 		"()Ljava/nio/ShortBuffer;"));
573 	bailif0(bufobj=(*env)->CallObjectMethod(env, bufobj, mid));
574 
575 	bailif0(cls=(*env)->FindClass(env, "java/awt/Rectangle"));
576 	bailif0(arrayRegionObj=(*env)->AllocObject(env, cls));
577 	bailif0(fid=(*env)->GetFieldID(env, cls, "x", "I"));
578 	(*env)->SetIntField(env, arrayRegionObj, fid, arrayRegion.x);
579 	bailif0(fid=(*env)->GetFieldID(env, cls, "y", "I"));
580 	(*env)->SetIntField(env, arrayRegionObj, fid, arrayRegion.y);
581 	bailif0(fid=(*env)->GetFieldID(env, cls, "width", "I"));
582 	(*env)->SetIntField(env, arrayRegionObj, fid, arrayRegion.w);
583 	bailif0(fid=(*env)->GetFieldID(env, cls, "height", "I"));
584 	(*env)->SetIntField(env, arrayRegionObj, fid, arrayRegion.h);
585 
586 	bailif0(planeRegionObj=(*env)->AllocObject(env, cls));
587 	bailif0(fid=(*env)->GetFieldID(env, cls, "x", "I"));
588 	(*env)->SetIntField(env, planeRegionObj, fid, planeRegion.x);
589 	bailif0(fid=(*env)->GetFieldID(env, cls, "y", "I"));
590 	(*env)->SetIntField(env, planeRegionObj, fid, planeRegion.y);
591 	bailif0(fid=(*env)->GetFieldID(env, cls, "width", "I"));
592 	(*env)->SetIntField(env, planeRegionObj, fid, planeRegion.w);
593 	bailif0(fid=(*env)->GetFieldID(env, cls, "height", "I"));
594 	(*env)->SetIntField(env, planeRegionObj, fid, planeRegion.h);
595 
596 	bailif0(cls=(*env)->GetObjectClass(env, cfobj));
597 	bailif0(mid=(*env)->GetMethodID(env, cls, "customFilter",
598 		"(Ljava/nio/ShortBuffer;Ljava/awt/Rectangle;Ljava/awt/Rectangle;IILorg/libjpegturbo/turbojpeg/TJTransform;)V"));
599 	(*env)->CallVoidMethod(env, cfobj, mid, bufobj, arrayRegionObj,
600 		planeRegionObj, componentIndex, transformIndex, tobj);
601 
602 	return 0;
603 
604 	bailout:
605 	return -1;
606 }
607 
Java_org_libjpegturbo_turbojpeg_TJTransformer_transform(JNIEnv * env,jobject obj,jbyteArray jsrcBuf,jint jpegSize,jobjectArray dstobjs,jobjectArray tobjs,jint flags)608 JNIEXPORT jintArray JNICALL Java_org_libjpegturbo_turbojpeg_TJTransformer_transform
609 	(JNIEnv *env, jobject obj, jbyteArray jsrcBuf, jint jpegSize,
610 		jobjectArray dstobjs, jobjectArray tobjs, jint flags)
611 {
612 	tjhandle handle=0;  int i;
613 	unsigned char *jpegBuf=NULL, **dstBufs=NULL;  jsize n=0;
614 	unsigned long *dstSizes=NULL;  tjtransform *t=NULL;
615 	jbyteArray *jdstBufs=NULL;
616 	int jpegWidth=0, jpegHeight=0, jpegSubsamp;
617 	jintArray jdstSizes=0;  jint *dstSizesi=NULL;
618 	JNICustomFilterParams *params=NULL;
619 
620 	gethandle();
621 
622 	if((*env)->GetArrayLength(env, jsrcBuf)<jpegSize)
623 		_throw("Source buffer is not large enough");
624 	bailif0(_fid=(*env)->GetFieldID(env, _cls, "jpegWidth", "I"));
625 	jpegWidth=(int)(*env)->GetIntField(env, obj, _fid);
626 	bailif0(_fid=(*env)->GetFieldID(env, _cls, "jpegHeight", "I"));
627 	jpegHeight=(int)(*env)->GetIntField(env, obj, _fid);
628 	bailif0(_fid=(*env)->GetFieldID(env, _cls, "jpegSubsamp", "I"));
629 	jpegSubsamp=(int)(*env)->GetIntField(env, obj, _fid);
630 
631 	n=(*env)->GetArrayLength(env, dstobjs);
632 	if(n!=(*env)->GetArrayLength(env, tobjs))
633 		_throw("Mismatch between size of transforms array and destination buffers array");
634 
635 	if((dstBufs=(unsigned char **)malloc(sizeof(unsigned char *)*n))==NULL)
636 		_throw("Memory allocation failure");
637 	if((jdstBufs=(jbyteArray *)malloc(sizeof(jbyteArray)*n))==NULL)
638 		_throw("Memory allocation failure");
639 	if((dstSizes=(unsigned long *)malloc(sizeof(unsigned long)*n))==NULL)
640 		_throw("Memory allocation failure");
641 	if((t=(tjtransform *)malloc(sizeof(tjtransform)*n))==NULL)
642 		_throw("Memory allocation failure");
643 	if((params=(JNICustomFilterParams *)malloc(sizeof(JNICustomFilterParams)*n))
644 		==NULL)
645 		_throw("Memory allocation failure");
646 	for(i=0; i<n; i++)
647 	{
648 		dstBufs[i]=NULL;  jdstBufs[i]=NULL;  dstSizes[i]=0;
649 		memset(&t[i], 0, sizeof(tjtransform));
650 		memset(&params[i], 0, sizeof(JNICustomFilterParams));
651 	}
652 
653 	for(i=0; i<n; i++)
654 	{
655 		jobject tobj, cfobj;
656 
657 		bailif0(tobj=(*env)->GetObjectArrayElement(env, tobjs, i));
658 		bailif0(_cls=(*env)->GetObjectClass(env, tobj));
659 		bailif0(_fid=(*env)->GetFieldID(env, _cls, "op", "I"));
660 		t[i].op=(*env)->GetIntField(env, tobj, _fid);
661 		bailif0(_fid=(*env)->GetFieldID(env, _cls, "options", "I"));
662 		t[i].options=(*env)->GetIntField(env, tobj, _fid);
663 		bailif0(_fid=(*env)->GetFieldID(env, _cls, "x", "I"));
664 		t[i].r.x=(*env)->GetIntField(env, tobj, _fid);
665 		bailif0(_fid=(*env)->GetFieldID(env, _cls, "y", "I"));
666 		t[i].r.y=(*env)->GetIntField(env, tobj, _fid);
667 		bailif0(_fid=(*env)->GetFieldID(env, _cls, "width", "I"));
668 		t[i].r.w=(*env)->GetIntField(env, tobj, _fid);
669 		bailif0(_fid=(*env)->GetFieldID(env, _cls, "height", "I"));
670 		t[i].r.h=(*env)->GetIntField(env, tobj, _fid);
671 
672 		bailif0(_fid=(*env)->GetFieldID(env, _cls, "cf",
673 			"Lorg/libjpegturbo/turbojpeg/TJCustomFilter;"));
674 		cfobj=(*env)->GetObjectField(env, tobj, _fid);
675 		if(cfobj)
676 		{
677 			params[i].env=env;
678 			params[i].tobj=tobj;
679 			params[i].cfobj=cfobj;
680 			t[i].customFilter=JNICustomFilter;
681 			t[i].data=(void *)&params[i];
682 		}
683 	}
684 
685 	bailif0(jpegBuf=(*env)->GetPrimitiveArrayCritical(env, jsrcBuf, 0));
686 	for(i=0; i<n; i++)
687 	{
688 		int w=jpegWidth, h=jpegHeight;
689 		if(t[i].r.w!=0) w=t[i].r.w;
690 		if(t[i].r.h!=0) h=t[i].r.h;
691 		bailif0(jdstBufs[i]=(*env)->GetObjectArrayElement(env, dstobjs, i));
692 		if((unsigned long)(*env)->GetArrayLength(env, jdstBufs[i])
693 			<tjBufSize(w, h, jpegSubsamp))
694 			_throw("Destination buffer is not large enough");
695 		bailif0(dstBufs[i]=(*env)->GetPrimitiveArrayCritical(env, jdstBufs[i], 0));
696 	}
697 
698 	if(tjTransform(handle, jpegBuf, jpegSize, n, dstBufs, dstSizes, t,
699 		flags|TJFLAG_NOREALLOC)==-1)
700 	{
701 		(*env)->ReleasePrimitiveArrayCritical(env, jsrcBuf, jpegBuf, 0);
702 		jpegBuf=NULL;
703 		for(i=0; i<n; i++)
704 		{
705 			(*env)->ReleasePrimitiveArrayCritical(env, jdstBufs[i], dstBufs[i], 0);
706 			dstBufs[i]=NULL;
707 		}
708 		_throw(tjGetErrorStr());
709 	}
710 
711 	jdstSizes=(*env)->NewIntArray(env, n);
712 	bailif0(dstSizesi=(*env)->GetIntArrayElements(env, jdstSizes, 0));
713 	for(i=0; i<n; i++) dstSizesi[i]=(int)dstSizes[i];
714 
715 	bailout:
716 	if(jpegBuf) (*env)->ReleasePrimitiveArrayCritical(env, jsrcBuf, jpegBuf, 0);
717 	if(dstBufs)
718 	{
719 		for(i=0; i<n; i++)
720 		{
721 			if(dstBufs[i] && jdstBufs && jdstBufs[i])
722 				(*env)->ReleasePrimitiveArrayCritical(env, jdstBufs[i], dstBufs[i], 0);
723 		}
724 		free(dstBufs);
725 	}
726 	if(jdstBufs) free(jdstBufs);
727 	if(dstSizes) free(dstSizes);
728 	if(dstSizesi) (*env)->ReleaseIntArrayElements(env, jdstSizes, dstSizesi, 0);
729 	if(t) free(t);
730 	return jdstSizes;
731 }
732 
Java_org_libjpegturbo_turbojpeg_TJDecompressor_destroy(JNIEnv * env,jobject obj)733 JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_destroy
734 	(JNIEnv *env, jobject obj)
735 {
736 	Java_org_libjpegturbo_turbojpeg_TJCompressor_destroy(env, obj);
737 }
738