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 60JNIEXPORT 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 70JNIEXPORT 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 80JNIEXPORT 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 98JNIEXPORT 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 143JNIEXPORT 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 153JNIEXPORT 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 200JNIEXPORT 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 210JNIEXPORT 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 251JNIEXPORT 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 294JNIEXPORT 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 308JNIEXPORT 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 325JNIEXPORT 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 353JNIEXPORT 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 386JNIEXPORT 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 427JNIEXPORT 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 435JNIEXPORT 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 478JNIEXPORT 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 487JNIEXPORT 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 527JNIEXPORT 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 544typedef struct _JNICustomFilterParams 545{ 546 JNIEnv *env; 547 jobject tobj; 548 jobject cfobj; 549} JNICustomFilterParams; 550 551static 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 608JNIEXPORT 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(¶ms[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 *)¶ms[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 733JNIEXPORT 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