void BEJPEG::read_header ( void ) { int image_width = 0; int image_height = 0; tjhandle jpeg_decompressor = tjInitDecompress(); if ( NULL != jpeg_decompressor ) { if ( data.size() > 0) { int error = tjDecompressHeader3 ( jpeg_decompressor, &data[0], data.size(), &image_width, &image_height, &chrominance_subsampling, &pixel_format ); tjDestroy(jpeg_decompressor); // error = if ( 0 == error ) { adjust_dimensions ( image_width, image_height ); } else { throw BEPlugin_Exception ( kJPEGReadHeaderError, tjGetErrorStr() ); } } else { throw BEPlugin_Exception ( kErrorParameterMissing ); } } else { throw BEPlugin_Exception ( kJPEGInitDecompressorError, tjGetErrorStr() ); } }
void BEJPEG::decompress ( void ) { read_header(); tjhandle jpeg_decompressor = tjInitDecompress(); if ( NULL != jpeg_decompressor ) { std::vector<unsigned char> decompressed_image ( width * height * tjPixelSize[pixel_format] ); if ( data.size() > 0) { int error = tjDecompress2 ( jpeg_decompressor, &data[0], data.size(), &decompressed_image[0], width, 0, height, pixel_format, 0 ); tjDestroy ( jpeg_decompressor ); // error = if ( 0 == error ) { data = decompressed_image; } else { throw BEPlugin_Exception ( kJPEGDecompressionError, tjGetErrorStr() ); } } else { throw BEPlugin_Exception ( kErrorParameterMissing ); } } else { throw BEPlugin_Exception ( kJPEGInitDecompressorError, tjGetErrorStr() ); } }
ofxTurboJpeg::ofxTurboJpeg() { handleCompress = tjInitCompress(); if (handleCompress == NULL) { printf("Error in tjInitCompress():\n%s\n", tjGetErrorStr()); } handleDecompress = tjInitDecompress(); if (handleDecompress == NULL) { printf("Error in tjInitDeCompress():\n%s\n", tjGetErrorStr()); } }
JNIEXPORT jobjectArray JNICALL Java_org_libjpegturbo_turbojpeg_TJ_getScalingFactors (JNIEnv *env, jclass cls) { jclass sfcls=NULL; jfieldID fid=0; tjscalingfactor *sf=NULL; int n=0, i; jobject sfobj=NULL; jobjectArray sfjava=NULL; if((sf=tjGetScalingFactors(&n))==NULL || n==0) _throw(tjGetErrorStr()); bailif0(sfcls=(*env)->FindClass(env, "org/libjpegturbo/turbojpeg/TJScalingFactor")); bailif0(sfjava=(jobjectArray)(*env)->NewObjectArray(env, n, sfcls, 0)); for(i=0; i<n; i++) { bailif0(sfobj=(*env)->AllocObject(env, sfcls)); bailif0(fid=(*env)->GetFieldID(env, sfcls, "num", "I")); (*env)->SetIntField(env, sfobj, fid, sf[i].num); bailif0(fid=(*env)->GetFieldID(env, sfcls, "denom", "I")); (*env)->SetIntField(env, sfobj, fid, sf[i].denom); (*env)->SetObjectArrayElement(env, sfjava, i, sfobj); } bailout: return sfjava; }
JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompressHeader (JNIEnv *env, jobject obj, jbyteArray src, jint jpegSize) { tjhandle handle=0; unsigned char *jpegBuf=NULL; int width=0, height=0, jpegSubsamp=-1; gethandle(); if((*env)->GetArrayLength(env, src)<jpegSize) _throw("Source buffer is not large enough"); bailif0(jpegBuf=(*env)->GetPrimitiveArrayCritical(env, src, 0)); if(tjDecompressHeader2(handle, jpegBuf, (unsigned long)jpegSize, &width, &height, &jpegSubsamp)==-1) { (*env)->ReleasePrimitiveArrayCritical(env, src, jpegBuf, 0); _throw(tjGetErrorStr()); } (*env)->ReleasePrimitiveArrayCritical(env, src, jpegBuf, 0); jpegBuf=NULL; bailif0(_fid=(*env)->GetFieldID(env, _cls, "jpegSubsamp", "I")); (*env)->SetIntField(env, obj, _fid, jpegSubsamp); bailif0(_fid=(*env)->GetFieldID(env, _cls, "jpegWidth", "I")); (*env)->SetIntField(env, obj, _fid, width); bailif0(_fid=(*env)->GetFieldID(env, _cls, "jpegHeight", "I")); (*env)->SetIntField(env, obj, _fid, height); bailout: return; }
bool TurboJpegReaderPlugin::getRegionOfDefinition( const OFX::RegionOfDefinitionArguments& args, OfxRectD& rod ) { try { FILE *file = NULL; unsigned char *jpegbuf = NULL; unsigned long jpgbufsize = 0; file = fopen( getAbsoluteFilenameAt( args.time ).c_str(), "rb" ); if( file == NULL ) { BOOST_THROW_EXCEPTION( exception::File() << exception::user( "TurboJpeg: Unable to open file" ) << exception::filename( getAbsoluteFilenameAt( args.time ) ) ); } fseek( file, 0, SEEK_END ); jpgbufsize = ftell( file ); jpegbuf = new unsigned char[ jpgbufsize ]; fseek(file, 0, SEEK_SET); fread( jpegbuf, jpgbufsize, 1, file ); const tjhandle jpeghandle = tjInitDecompress(); int width = 0; int height = 0; int jpegsubsamp = -1; int ret = tjDecompressHeader2( jpeghandle, jpegbuf, jpgbufsize, &width, &height, &jpegsubsamp ); if( ret != 0 ) { BOOST_THROW_EXCEPTION( exception::FileNotExist() << exception::user( tjGetErrorStr() ) << exception::filename( getAbsoluteFilenameAt( args.time ) ) ); } tjDestroy( jpeghandle ); //free(jpegbuf); delete[] jpegbuf; jpegbuf = NULL; fclose(file); file=NULL; rod.x1 = 0; rod.x2 = width * this->_clipDst->getPixelAspectRatio(); rod.y1 = 0; rod.y2 = height; //TUTTLE_COUT_VAR( rod ); } catch( std::exception& e ) { BOOST_THROW_EXCEPTION( exception::FileNotExist() << exception::user( "TurboJpeg: Unable to open file" ) << exception::filename( getAbsoluteFilenameAt( args.time ) ) ); } return true; }
/* TurboJPEG 1.2.x: TJDecompressor::decompressToYUV() */ JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompressToYUV (JNIEnv *env, jobject obj, jbyteArray src, jint jpegSize, jbyteArray dst, jint flags) { tjhandle handle=0; unsigned char *jpegBuf=NULL, *dstBuf=NULL; int jpegSubsamp=-1, jpegWidth=0, jpegHeight=0; gethandle(); if((*env)->GetArrayLength(env, src)<jpegSize) _throw("Source buffer is not large enough"); bailif0(_fid=(*env)->GetFieldID(env, _cls, "jpegSubsamp", "I")); jpegSubsamp=(int)(*env)->GetIntField(env, obj, _fid); bailif0(_fid=(*env)->GetFieldID(env, _cls, "jpegWidth", "I")); jpegWidth=(int)(*env)->GetIntField(env, obj, _fid); bailif0(_fid=(*env)->GetFieldID(env, _cls, "jpegHeight", "I")); jpegHeight=(int)(*env)->GetIntField(env, obj, _fid); if((*env)->GetArrayLength(env, dst) <(jsize)tjBufSizeYUV(jpegWidth, jpegHeight, jpegSubsamp)) _throw("Destination buffer is not large enough"); bailif0(jpegBuf=(*env)->GetPrimitiveArrayCritical(env, src, 0)); bailif0(dstBuf=(*env)->GetPrimitiveArrayCritical(env, dst, 0)); if(tjDecompressToYUV(handle, jpegBuf, (unsigned long)jpegSize, dstBuf, flags)==-1) _throw(tjGetErrorStr()); bailout: if(dstBuf) (*env)->ReleasePrimitiveArrayCritical(env, dst, dstBuf, 0); if(jpegBuf) (*env)->ReleasePrimitiveArrayCritical(env, src, jpegBuf, 0); return; }
static void TJCompressor_encodeYUV (JNIEnv *env, jobject obj, jarray src, jint srcElementSize, jint width, jint pitch, jint height, jint pf, jbyteArray dst, jint subsamp, jint flags) { tjhandle handle=0; jsize arraySize=0; unsigned char *srcBuf=NULL, *dstBuf=NULL; gethandle(); if(pf<0 || pf>=org_libjpegturbo_turbojpeg_TJ_NUMPF || width<1 || height<1 || pitch<0) _throw("Invalid argument in encodeYUV()"); if(org_libjpegturbo_turbojpeg_TJ_NUMPF!=TJ_NUMPF) _throw("Mismatch between Java and C API"); arraySize=(pitch==0)? width*tjPixelSize[pf]*height:pitch*height; if((*env)->GetArrayLength(env, src)*srcElementSize<arraySize) _throw("Source buffer is not large enough"); if((*env)->GetArrayLength(env, dst) <(jsize)tjBufSizeYUV(width, height, subsamp)) _throw("Destination buffer is not large enough"); bailif0(srcBuf=(*env)->GetPrimitiveArrayCritical(env, src, 0)); bailif0(dstBuf=(*env)->GetPrimitiveArrayCritical(env, dst, 0)); if(tjEncodeYUV2(handle, srcBuf, width, pitch, height, pf, dstBuf, subsamp, flags)==-1) _throw(tjGetErrorStr()); bailout: if(dstBuf) (*env)->ReleasePrimitiveArrayCritical(env, dst, dstBuf, 0); if(srcBuf) (*env)->ReleasePrimitiveArrayCritical(env, src, srcBuf, 0); return; }
bool WriteJpeg( const char * destinationFile, const unsigned char * rgbxBuffer, int width, int height ) { tjhandle tj = tjInitCompress(); unsigned char * jpegBuf = NULL; unsigned long jpegSize = 0; const int r = tjCompress2( tj, ( unsigned char * )rgbxBuffer, // TJ isn't const correct... width, width * 4, height, TJPF_RGBX, &jpegBuf, &jpegSize, TJSAMP_444 /* TJSAMP_422 */, 90 /* jpegQual */, 0 /* flags */ ); if ( r != 0 ) { LOG_TJ( "tjCompress2 returned %s for %s", tjGetErrorStr(), destinationFile ); return false; } FILE * f = fopen( destinationFile, "wb" ); if ( f != NULL ) { fwrite( jpegBuf, jpegSize, 1, f ); fclose( f ); } else { LOG_TJ( "WriteJpeg failed to write to %s", destinationFile ); return false; } tjFree( jpegBuf ); tjDestroy( tj ); return true; }
/* TurboJPEG 1.4.x: TJ::planeHeight() */ JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJ_planeHeight__III (JNIEnv *env, jclass cls, jint componentID, jint height, jint subsamp) { jint retval=(jint)tjPlaneHeight(componentID, height, subsamp); if(retval==-1) _throwarg(tjGetErrorStr()); bailout: return retval; }
JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJ_bufSizeYUV (JNIEnv *env, jclass cls, jint width, jint height, jint subsamp) { jint retval=(jint)tjBufSizeYUV(width, height, subsamp); if(retval==-1) _throw(tjGetErrorStr()); bailout: return retval; }
// Drop-in replacement for stbi_load_from_memory(), but without component specification. // Often 2x - 3x faster. unsigned char * TurboJpegLoadFromMemory( const unsigned char * jpg, const int length, int * width, int * height ) { tjhandle tj = tjInitDecompress(); int jpegWidth; int jpegHeight; int jpegSubsamp; int jpegColorspace; const int headerRet = tjDecompressHeader3( tj, ( unsigned char * )jpg /* tj isn't const correct */, length, &jpegWidth, &jpegHeight, &jpegSubsamp, &jpegColorspace ); if ( headerRet ) { LOG_TJ( "TurboJpegLoadFromMemory: header: %s", tjGetErrorStr() ); tjDestroy( tj ); return NULL; } const int bufLen = jpegWidth * jpegHeight * 4; unsigned char * buffer = ( unsigned char * )malloc( bufLen ); if ( buffer != NULL ) { const int decompRet = tjDecompress2( tj, ( unsigned char * )jpg, length, buffer, jpegWidth, jpegWidth * 4, jpegHeight, TJPF_RGBX, 0 /* flags */ ); if ( decompRet ) { LOG_TJ( "TurboJpegLoadFromMemory: decompress: %s", tjGetErrorStr() ); tjDestroy( tj ); free( buffer ); return NULL; } tjDestroy( tj ); *width = jpegWidth; *height = jpegHeight; } return buffer; }
JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_destroy (JNIEnv *env, jobject obj) { tjhandle handle=0; gethandle(); if(tjDestroy(handle)==-1) _throw(tjGetErrorStr()); (*env)->SetLongField(env, obj, _fid, 0); bailout: return; }
std::unique_ptr<uint8_t[]> DecodeJpeg(const array_view<uint8_t> data) { TjDecompressHandle handle; int w, h; tjDecompressHeader(handle, &data[0], data.bytes(), &w, &h); std::unique_ptr<uint8_t[]> result(new uint8_t[w * h * 4]); auto status = tjDecompress2(handle, &data[0], data.bytes(), &result[0], w, w * 4, h, TJPF_BGRX, 0); if (status != 0) { throw TempleException("Unable to decompress jpeg image: {}", tjGetErrorStr()); } return result; }
void BEJPEG::compress ( void ) { tjhandle jpeg_compressor = tjInitCompress(); if ( NULL != jpeg_compressor ) { unsigned long image_size = width * height * tjPixelSize[pixel_format]; std::vector<unsigned char> image ( image_size ); unsigned char * compressed_image = &image[0]; int error = tjCompress2 ( jpeg_compressor, &data[0], width, 0, height, pixel_format, &compressed_image, &image_size, chrominance_subsampling, compression_level, 0 ); tjDestroy ( jpeg_compressor ); // error = if ( 0 == error ) { image.resize ( image_size ); data = image; } else { throw BEPlugin_Exception ( kJPEGCompressionError, tjGetErrorStr() ); } } else { throw BEPlugin_Exception ( kJPEGInitCcompressorError, tjGetErrorStr() ); } }
// Drop-in replacement for stbi_load_from_memory(), but without component specification. // Often 2x - 3x faster. unsigned char * TurboJpegLoadFromMemory( const unsigned char * jpg, const int length, int * width, int * height ) { tjhandle tj = tjInitDecompress(); int jpegWidth; int jpegHeight; int jpegSubsamp; int jpegColorspace; const int headerRet = tjDecompressHeader3( tj, ( unsigned char * )jpg /* tj isn't const correct */, length, &jpegWidth, &jpegHeight, &jpegSubsamp, &jpegColorspace ); if ( headerRet ) { LOG( "TurboJpegLoadFromMemory: header: %s", tjGetErrorStr() ); tjDestroy( tj ); return NULL; } MemBuffer tjb( jpegWidth * jpegHeight * 4 ); const int decompRet = tjDecompress2( tj, ( unsigned char * )jpg, length, ( unsigned char * )tjb.Buffer, jpegWidth, jpegWidth * 4, jpegHeight, TJPF_RGBX, 0 /* flags */ ); if ( decompRet ) { LOG( "TurboJpegLoadFromMemory: decompress: %s", tjGetErrorStr() ); tjDestroy( tj ); tjb.FreeData(); return NULL; } tjDestroy( tj ); *width = jpegWidth; *height = jpegHeight; return ( unsigned char * )tjb.Buffer; }
JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJTransformer_init (JNIEnv *env, jobject obj) { jclass cls; jfieldID fid; tjhandle handle; if((handle=tjInitTransform())==NULL) _throw(tjGetErrorStr()); bailif0(cls=(*env)->GetObjectClass(env, obj)); bailif0(fid=(*env)->GetFieldID(env, cls, "handle", "J")); (*env)->SetLongField(env, obj, fid, (jlong)handle); bailout: return; }
JNIEXPORT jint JNICALL 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) { tjhandle handle=0; unsigned long jpegSize=0; jsize arraySize=0, actualStride; unsigned char *srcBuf=NULL, *jpegBuf=NULL; gethandle(); if(pf<0 || pf>=org_libjpegturbo_turbojpeg_TJ_NUMPF || width<1 || height<1 || stride<0) _throw("Invalid argument in compress()"); if(org_libjpegturbo_turbojpeg_TJ_NUMPF!=TJ_NUMPF) _throw("Mismatch between Java and C API"); if(tjPixelSize[pf]!=sizeof(jint)) _throw("Pixel format must be 32-bit when compressing from an integer buffer."); actualStride=(stride==0)? width:stride; arraySize=(y+height-1)*actualStride + x+width; if((*env)->GetArrayLength(env, src)<arraySize) _throw("Source buffer is not large enough"); jpegSize=tjBufSize(width, height, jpegSubsamp); if((*env)->GetArrayLength(env, dst)<(jsize)jpegSize) _throw("Destination buffer is not large enough"); bailif0(srcBuf=(*env)->GetPrimitiveArrayCritical(env, src, 0)); bailif0(jpegBuf=(*env)->GetPrimitiveArrayCritical(env, dst, 0)); if(tjCompress2(handle, &srcBuf[(y*actualStride + x)*sizeof(int)], width, stride*sizeof(jint), height, pf, &jpegBuf, &jpegSize, jpegSubsamp, jpegQual, flags|TJFLAG_NOREALLOC)==-1) { (*env)->ReleasePrimitiveArrayCritical(env, dst, jpegBuf, 0); (*env)->ReleasePrimitiveArrayCritical(env, src, srcBuf, 0); jpegBuf=srcBuf=NULL; _throw(tjGetErrorStr()); } bailout: if(jpegBuf) (*env)->ReleasePrimitiveArrayCritical(env, dst, jpegBuf, 0); if(srcBuf) (*env)->ReleasePrimitiveArrayCritical(env, src, srcBuf, 0); return (jint)jpegSize; }
bool ofxTurboJpeg::load(const ofBuffer& buf, ofPixels &pix) { int w, h; int subsamp; int ok = tjDecompressHeader2(handleDecompress, (unsigned char*)buf.getData(), buf.size(), &w, &h, &subsamp); if (ok != 0) { printf("Error in tjDecompressHeader2():\n%s\n", tjGetErrorStr()); return false; } pix.allocate(w, h, 3); tjDecompress(handleDecompress, (unsigned char*)buf.getData(), buf.size(), pix.getData(), w, 0, h, 3, 0); return true; }
JNIEXPORT void JNICALL 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) { tjhandle handle=0; jsize arraySize=0, actualStride; unsigned char *jpegBuf=NULL, *dstBuf=NULL; gethandle(); if(pf<0 || pf>=org_libjpegturbo_turbojpeg_TJ_NUMPF) _throw("Invalid argument in decompress()"); if(org_libjpegturbo_turbojpeg_TJ_NUMPF!=TJ_NUMPF) _throw("Mismatch between Java and C API"); if(tjPixelSize[pf]!=sizeof(jint)) _throw("Pixel format must be 32-bit when decompressing to an integer buffer."); if((*env)->GetArrayLength(env, src)<jpegSize) _throw("Source buffer is not large enough"); actualStride=(stride==0)? width:stride; arraySize=(y+height-1)*actualStride + x+width; if((*env)->GetArrayLength(env, dst)<arraySize) _throw("Destination buffer is not large enough"); bailif0(jpegBuf=(*env)->GetPrimitiveArrayCritical(env, src, 0)); bailif0(dstBuf=(*env)->GetPrimitiveArrayCritical(env, dst, 0)); if(tjDecompress2(handle, jpegBuf, (unsigned long)jpegSize, &dstBuf[(y*actualStride + x)*sizeof(int)], width, stride*sizeof(jint), height, pf, flags)==-1) { (*env)->ReleasePrimitiveArrayCritical(env, dst, dstBuf, 0); (*env)->ReleasePrimitiveArrayCritical(env, src, jpegBuf, 0); dstBuf=jpegBuf=NULL; _throw(tjGetErrorStr()); } bailout: if(dstBuf) (*env)->ReleasePrimitiveArrayCritical(env, dst, dstBuf, 0); if(jpegBuf) (*env)->ReleasePrimitiveArrayCritical(env, src, jpegBuf, 0); return; }
JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_encodeYUV___3IIIII_3BII (JNIEnv *env, jobject obj, jintArray src, jint width, jint pitch, jint height, jint pf, jbyteArray dst, jint subsamp, jint flags) { tjhandle handle=0; jsize arraySize=0; unsigned char *srcBuf=NULL, *dstBuf=NULL; gethandle(); if(pf<0 || pf>=org_libjpegturbo_turbojpeg_TJ_NUMPF || width<1 || height<1 || pitch<0) _throw("Invalid argument in compress()"); if(org_libjpegturbo_turbojpeg_TJ_NUMPF!=TJ_NUMPF) _throw("Mismatch between Java and C API"); if(tjPixelSize[pf]!=sizeof(jint)) _throw("Pixel format must be 32-bit when encoding from an integer buffer."); arraySize=(pitch==0)? width*height:pitch*height; if((*env)->GetArrayLength(env, src)<arraySize) _throw("Source buffer is not large enough"); if((*env)->GetArrayLength(env, dst) <(jsize)tjBufSizeYUV(width, height, subsamp)) _throw("Destination buffer is not large enough"); bailif0(srcBuf=(*env)->GetPrimitiveArrayCritical(env, src, 0)); bailif0(dstBuf=(*env)->GetPrimitiveArrayCritical(env, dst, 0)); if(tjEncodeYUV2(handle, srcBuf, width, pitch*sizeof(jint), height, pf, dstBuf, subsamp, flags)==-1) { (*env)->ReleasePrimitiveArrayCritical(env, dst, dstBuf, 0); (*env)->ReleasePrimitiveArrayCritical(env, src, srcBuf, 0); dstBuf=srcBuf=NULL; _throw(tjGetErrorStr()); } bailout: if(dstBuf) (*env)->ReleasePrimitiveArrayCritical(env, dst, dstBuf, 0); if(srcBuf) (*env)->ReleasePrimitiveArrayCritical(env, src, srcBuf, 0); return; }
JNIEXPORT jint JNICALL 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) { tjhandle handle=0; unsigned long jpegSize=0; jsize arraySize=0; unsigned char *srcBuf=NULL, *jpegBuf=NULL; gethandle(); if(pf<0 || pf>=org_libjpegturbo_turbojpeg_TJ_NUMPF || width<1 || height<1 || pitch<0) _throw("Invalid argument in compress()"); if(org_libjpegturbo_turbojpeg_TJ_NUMPF!=TJ_NUMPF) _throw("Mismatch between Java and C API"); arraySize=(pitch==0)? width*tjPixelSize[pf]*height:pitch*height; if((*env)->GetArrayLength(env, src)<arraySize) _throw("Source buffer is not large enough"); jpegSize=tjBufSize(width, height, jpegSubsamp); if((*env)->GetArrayLength(env, dst)<(jsize)jpegSize) _throw("Destination buffer is not large enough"); bailif0(srcBuf=(*env)->GetPrimitiveArrayCritical(env, src, 0)); bailif0(jpegBuf=(*env)->GetPrimitiveArrayCritical(env, dst, 0)); if(tjCompress2(handle, srcBuf, width, pitch, height, pf, &jpegBuf, &jpegSize, jpegSubsamp, jpegQual, flags|TJFLAG_NOREALLOC)==-1) { (*env)->ReleasePrimitiveArrayCritical(env, dst, jpegBuf, 0); (*env)->ReleasePrimitiveArrayCritical(env, src, srcBuf, 0); jpegBuf=srcBuf=NULL; _throw(tjGetErrorStr()); } bailout: if(jpegBuf) (*env)->ReleasePrimitiveArrayCritical(env, dst, jpegBuf, 0); if(srcBuf) (*env)->ReleasePrimitiveArrayCritical(env, src, srcBuf, 0); return (jint)jpegSize; }
void WriteJpeg( const char * fullName, const unsigned char * rgbxBuffer, int width, int height ) { tjhandle tj = tjInitCompress(); unsigned char * jpegBuf = NULL; unsigned long jpegSize = 0; const int r = tjCompress2( tj, ( unsigned char * )rgbxBuffer, // TJ isn't const correct... width, width * 4, height, TJPF_RGBX, &jpegBuf, &jpegSize, TJSAMP_444 /* TJSAMP_422 */, 90 /* jpegQual */, 0 /* flags */ ); if ( r != 0 ) { LOG( "tjCompress2 returned %s for %s", tjGetErrorStr(), fullName ); return; } MemBuffer toFile( jpegBuf, jpegSize ); toFile.WriteToFile( fullName ); tjFree( jpegBuf ); tjDestroy( tj ); }
JNIEXPORT void JNICALL 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) { tjhandle handle=0; jsize arraySize=0, actualPitch; unsigned char *jpegBuf=NULL, *dstBuf=NULL; gethandle(); if(pf<0 || pf>=org_libjpegturbo_turbojpeg_TJ_NUMPF) _throw("Invalid argument in decompress()"); if(org_libjpegturbo_turbojpeg_TJ_NUMPF!=TJ_NUMPF) _throw("Mismatch between Java and C API"); if((*env)->GetArrayLength(env, src)<jpegSize) _throw("Source buffer is not large enough"); actualPitch=(pitch==0)? width*tjPixelSize[pf]:pitch; arraySize=(y+height-1)*actualPitch + (x+width)*tjPixelSize[pf]; if((*env)->GetArrayLength(env, dst)<arraySize) _throw("Destination buffer is not large enough"); bailif0(jpegBuf=(*env)->GetPrimitiveArrayCritical(env, src, 0)); bailif0(dstBuf=(*env)->GetPrimitiveArrayCritical(env, dst, 0)); if(tjDecompress2(handle, jpegBuf, (unsigned long)jpegSize, &dstBuf[y*actualPitch + x*tjPixelSize[pf]], width, pitch, height, pf, flags)==-1) { (*env)->ReleasePrimitiveArrayCritical(env, dst, dstBuf, 0); (*env)->ReleasePrimitiveArrayCritical(env, src, jpegBuf, 0); dstBuf=jpegBuf=NULL; _throw(tjGetErrorStr()); } bailout: if(dstBuf) (*env)->ReleasePrimitiveArrayCritical(env, dst, dstBuf, 0); if(jpegBuf) (*env)->ReleasePrimitiveArrayCritical(env, src, jpegBuf, 0); return; }
// Given a filename and an image object, it loads the file with that name into // the object. void loadImage(Image *image, char* filename) { FILE* jpegfile = fopen(filename, "rb"); if(jpegfile == NULL) { EPRINT("Error: Unable to open file!\n"); exit(-1); } struct stat stbuf; if ((fstat(fileno(jpegfile), &stbuf) != 0) || (!S_ISREG(stbuf.st_mode))) { EPRINT("Error: Unable to determine file size!\n"); exit(-1); } off_t filesize = stbuf.st_size; unsigned char* buffer = malloc(filesize); if (buffer == NULL) { EPRINT("Error: Unable to allocate memory for jpeg!\n"); exit(-1); } if(fread(buffer, 1, filesize, jpegfile) != filesize) { EPRINT("Error: Unable to read file!\n"); exit(-1); } fclose(jpegfile); tjhandle decomp; if(!(decomp = tjInitDecompress())) { EPRINT("Error: Unable to initialize TurboJPEG decompressor!\n"); EPRINT("%s\n", tjGetErrorStr()); exit(-1); } int width, height, jpegSubsamp, jpegColorspace; if(tjDecompressHeader3(decomp, buffer, filesize, &width, &height, &jpegSubsamp, &jpegColorspace)) { EPRINT("Error: Unable to read JPEG header!\n"); EPRINT("%s\n", tjGetErrorStr()); exit(-1); } image->width = width; image->height = height; unsigned long decompressed_size; decompressed_size = width*height*tjPixelSize[PIXEL_FORMAT]; unsigned char* buffer2 = malloc(decompressed_size); if(tjDecompress2(decomp, buffer, filesize, buffer2, width, width * tjPixelSize[PIXEL_FORMAT], height, PIXEL_FORMAT, TJFLAG_NOREALLOC)) { EPRINT("Error: Unable to decompress JPEG image!\n"); EPRINT("%s\n", tjGetErrorStr()); exit(-1); } // Free up some memory since we are done with image decoding tjDestroy(decomp); free(buffer); assert(tjPixelSize[PIXEL_FORMAT] == sizeof(Pixel)); image->data = (Pixel *) buffer2; return; }
static const char * VS_CC check_jpeg(img_hnd_t *ih, int n, FILE *fp, vs_args_t *va) { struct stat st; #ifdef _WIN32 wchar_t tmp[FILENAME_MAX * 2]; MultiByteToWideChar(CP_UTF8, 0, ih->src[n].name, -1, tmp, FILENAME_MAX * 2); if (wstat(tmp, &st)) { #else if (stat(ih->src[n].name, &st)) { #endif return "source file does not exist"; } ih->src[n].image_size = st.st_size; if (ih->src_buff_size < st.st_size) { ih->src_buff_size = st.st_size; free(ih->src_buff); ih->src_buff = malloc(ih->src_buff_size); if (!ih->src_buff) { return "failed to allocate read buffer"; } } unsigned long read = fread(ih->src_buff, 1, st.st_size, fp); fclose(fp); if (read < st.st_size) { return "failed to read jpeg file"; } int subsample, width, height; tjhandle handle = (tjhandle)ih->tjhandle; if (tjDecompressHeader2(handle, ih->src_buff, read, &width, &height, &subsample) != 0) { return tjGetErrorStr(); } if (subsample == TJSAMP_420 || subsample == TJSAMP_422) { width += width & 1; } if (subsample == TJSAMP_420 || subsample == TJSAMP_440) { height += height & 1; } ih->src[n].width = width; ih->src[n].height = height; VSPresetFormat pf = tjsamp_to_vspresetformat(subsample); ih->src[n].format = va->vsapi->getFormatPreset(pf, va->core); uint32_t row_size = tjBufSizeYUV(width, height, subsample) / height; if (row_size > va->max_row_size) { va->max_row_size = row_size; } ih->src[n].read = read_jpeg; return NULL; } const func_check_src check_src_jpeg = check_jpeg;
static void TJDecompressor_decodeYUV (JNIEnv *env, jobject obj, jobjectArray srcobjs, jintArray jSrcOffsets, jintArray jSrcStrides, jint subsamp, jarray dst, jint dstElementSize, jint x, jint y, jint width, jint pitch, jint height, jint pf, jint flags) { tjhandle handle=0; jsize arraySize=0, actualPitch; jbyteArray jSrcPlanes[3]={NULL, NULL, NULL}; unsigned char *srcPlanes[3], *dstBuf=NULL; int *srcOffsets=NULL, *srcStrides=NULL; int nc=(subsamp==org_libjpegturbo_turbojpeg_TJ_SAMP_GRAY? 1:3), i; gethandle(); if(pf<0 || pf>=org_libjpegturbo_turbojpeg_TJ_NUMPF || subsamp<0 || subsamp>=org_libjpegturbo_turbojpeg_TJ_NUMSAMP) _throwarg("Invalid argument in decodeYUV()"); if(org_libjpegturbo_turbojpeg_TJ_NUMPF!=TJ_NUMPF || org_libjpegturbo_turbojpeg_TJ_NUMSAMP!=TJ_NUMSAMP) _throwarg("Mismatch between Java and C API"); if((*env)->GetArrayLength(env, srcobjs)<nc) _throwarg("Planes array is too small for the subsampling type"); if((*env)->GetArrayLength(env, jSrcOffsets)<nc) _throwarg("Offsets array is too small for the subsampling type"); if((*env)->GetArrayLength(env, jSrcStrides)<nc) _throwarg("Strides array is too small for the subsampling type"); actualPitch=(pitch==0)? width*tjPixelSize[pf]:pitch; arraySize=(y+height-1)*actualPitch + (x+width)*tjPixelSize[pf]; if((*env)->GetArrayLength(env, dst)*dstElementSize<arraySize) _throwarg("Destination buffer is not large enough"); bailif0(srcOffsets=(*env)->GetPrimitiveArrayCritical(env, jSrcOffsets, 0)); bailif0(srcStrides=(*env)->GetPrimitiveArrayCritical(env, jSrcStrides, 0)); for(i=0; i<nc; i++) { int planeSize=tjPlaneSizeYUV(i, width, srcStrides[i], height, subsamp); int pw=tjPlaneWidth(i, width, subsamp); if(planeSize<0 || pw<0) _throwarg(tjGetErrorStr()); if(srcOffsets[i]<0) _throwarg("Invalid argument in decodeYUV()"); if(srcStrides[i]<0 && srcOffsets[i]-planeSize+pw<0) _throwarg("Negative plane stride would cause memory to be accessed below plane boundary"); bailif0(jSrcPlanes[i]=(*env)->GetObjectArrayElement(env, srcobjs, i)); if((*env)->GetArrayLength(env, jSrcPlanes[i])<srcOffsets[i]+planeSize) _throwarg("Source plane is not large enough"); bailif0(srcPlanes[i]=(*env)->GetPrimitiveArrayCritical(env, jSrcPlanes[i], 0)); srcPlanes[i]=&srcPlanes[i][srcOffsets[i]]; } bailif0(dstBuf=(*env)->GetPrimitiveArrayCritical(env, dst, 0)); if(tjDecodeYUVPlanes(handle, srcPlanes, srcStrides, subsamp, &dstBuf[y*actualPitch + x*tjPixelSize[pf]], width, pitch, height, pf, flags)==-1) _throwtj(); bailout: if(dstBuf) (*env)->ReleasePrimitiveArrayCritical(env, dst, dstBuf, 0); for(i=0; i<nc; i++) { if(srcPlanes[i] && jSrcPlanes[i]) (*env)->ReleasePrimitiveArrayCritical(env, jSrcPlanes[i], srcPlanes[i], 0); } if(srcStrides) (*env)->ReleasePrimitiveArrayCritical(env, jSrcStrides, srcStrides, 0); if(srcOffsets) (*env)->ReleasePrimitiveArrayCritical(env, jSrcOffsets, srcOffsets, 0); return; }
/* TurboJPEG 1.4.x: TJDecompressor::decompressToYUV() */ JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompressToYUV___3BI_3_3B_3II_3III (JNIEnv *env, jobject obj, jbyteArray src, jint jpegSize, jobjectArray dstobjs, jintArray jDstOffsets, jint desiredWidth, jintArray jDstStrides, jint desiredHeight, jint flags) { tjhandle handle=0; jbyteArray jDstPlanes[3]={NULL, NULL, NULL}; unsigned char *jpegBuf=NULL, *dstPlanes[3]; int *dstOffsets=NULL, *dstStrides=NULL; int jpegSubsamp=-1, jpegWidth=0, jpegHeight=0; int nc=0, i, width, height, scaledWidth, scaledHeight, nsf=0; tjscalingfactor *sf; gethandle(); if((*env)->GetArrayLength(env, src)<jpegSize) _throwarg("Source buffer is not large enough"); bailif0(_fid=(*env)->GetFieldID(env, _cls, "jpegSubsamp", "I")); jpegSubsamp=(int)(*env)->GetIntField(env, obj, _fid); bailif0(_fid=(*env)->GetFieldID(env, _cls, "jpegWidth", "I")); jpegWidth=(int)(*env)->GetIntField(env, obj, _fid); bailif0(_fid=(*env)->GetFieldID(env, _cls, "jpegHeight", "I")); jpegHeight=(int)(*env)->GetIntField(env, obj, _fid); nc=(jpegSubsamp==org_libjpegturbo_turbojpeg_TJ_SAMP_GRAY? 1:3); width=desiredWidth; height=desiredHeight; if(width==0) width=jpegWidth; if(height==0) height=jpegHeight; sf=tjGetScalingFactors(&nsf); if(!sf || nsf<1) _throwarg(tjGetErrorStr()); for(i=0; i<nsf; i++) { scaledWidth=TJSCALED(jpegWidth, sf[i]); scaledHeight=TJSCALED(jpegHeight, sf[i]); if(scaledWidth<=width && scaledHeight<=height) break; } bailif0(dstOffsets=(*env)->GetPrimitiveArrayCritical(env, jDstOffsets, 0)); bailif0(dstStrides=(*env)->GetPrimitiveArrayCritical(env, jDstStrides, 0)); for(i=0; i<nc; i++) { int planeSize=tjPlaneSizeYUV(i, scaledWidth, dstStrides[i], scaledHeight, jpegSubsamp); int pw=tjPlaneWidth(i, scaledWidth, jpegSubsamp); if(planeSize<0 || pw<0) _throwarg(tjGetErrorStr()); if(dstOffsets[i]<0) _throwarg("Invalid argument in decompressToYUV()"); if(dstStrides[i]<0 && dstOffsets[i]-planeSize+pw<0) _throwarg("Negative plane stride would cause memory to be accessed below plane boundary"); bailif0(jDstPlanes[i]=(*env)->GetObjectArrayElement(env, dstobjs, i)); if((*env)->GetArrayLength(env, jDstPlanes[i])<dstOffsets[i]+planeSize) _throwarg("Destination plane is not large enough"); bailif0(dstPlanes[i]=(*env)->GetPrimitiveArrayCritical(env, jDstPlanes[i], 0)); dstPlanes[i]=&dstPlanes[i][dstOffsets[i]]; } bailif0(jpegBuf=(*env)->GetPrimitiveArrayCritical(env, src, 0)); if(tjDecompressToYUVPlanes(handle, jpegBuf, (unsigned long)jpegSize, dstPlanes, desiredWidth, dstStrides, desiredHeight, flags)==-1) _throwtj(); bailout: if(jpegBuf) (*env)->ReleasePrimitiveArrayCritical(env, src, jpegBuf, 0); for(i=0; i<nc; i++) { if(dstPlanes[i] && jDstPlanes[i]) (*env)->ReleasePrimitiveArrayCritical(env, jDstPlanes[i], dstPlanes[i], 0); } if(dstStrides) (*env)->ReleasePrimitiveArrayCritical(env, jDstStrides, dstStrides, 0); if(dstOffsets) (*env)->ReleasePrimitiveArrayCritical(env, jDstOffsets, dstOffsets, 0); return; }
/* TurboJPEG 1.4.x: TJCompressor::compressFromYUV() */ JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_compressFromYUV___3_3B_3II_3III_3BII (JNIEnv *env, jobject obj, jobjectArray srcobjs, jintArray jSrcOffsets, jint width, jintArray jSrcStrides, jint height, jint subsamp, jbyteArray dst, jint jpegQual, jint flags) { tjhandle handle=0; unsigned long jpegSize=0; jbyteArray jSrcPlanes[3]={NULL, NULL, NULL}; unsigned char *srcPlanes[3], *jpegBuf=NULL; int *srcOffsets=NULL, *srcStrides=NULL; int nc=(subsamp==org_libjpegturbo_turbojpeg_TJ_SAMP_GRAY? 1:3), i; gethandle(); if(subsamp<0 || subsamp>=org_libjpegturbo_turbojpeg_TJ_NUMSAMP) _throwarg("Invalid argument in compressFromYUV()"); if(org_libjpegturbo_turbojpeg_TJ_NUMSAMP!=TJ_NUMSAMP) _throwarg("Mismatch between Java and C API"); if((*env)->GetArrayLength(env, srcobjs)<nc) _throwarg("Planes array is too small for the subsampling type"); if((*env)->GetArrayLength(env, jSrcOffsets)<nc) _throwarg("Offsets array is too small for the subsampling type"); if((*env)->GetArrayLength(env, jSrcStrides)<nc) _throwarg("Strides array is too small for the subsampling type"); jpegSize=tjBufSize(width, height, subsamp); if((*env)->GetArrayLength(env, dst)<(jsize)jpegSize) _throwarg("Destination buffer is not large enough"); bailif0(srcOffsets=(*env)->GetPrimitiveArrayCritical(env, jSrcOffsets, 0)); bailif0(srcStrides=(*env)->GetPrimitiveArrayCritical(env, jSrcStrides, 0)); for(i=0; i<nc; i++) { int planeSize=tjPlaneSizeYUV(i, width, srcStrides[i], height, subsamp); int pw=tjPlaneWidth(i, width, subsamp); if(planeSize<0 || pw<0) _throwarg(tjGetErrorStr()); if(srcOffsets[i]<0) _throwarg("Invalid argument in compressFromYUV()"); if(srcStrides[i]<0 && srcOffsets[i]-planeSize+pw<0) _throwarg("Negative plane stride would cause memory to be accessed below plane boundary"); bailif0(jSrcPlanes[i]=(*env)->GetObjectArrayElement(env, srcobjs, i)); if((*env)->GetArrayLength(env, jSrcPlanes[i])<srcOffsets[i]+planeSize) _throwarg("Source plane is not large enough"); bailif0(srcPlanes[i]=(*env)->GetPrimitiveArrayCritical(env, jSrcPlanes[i], 0)); srcPlanes[i]=&srcPlanes[i][srcOffsets[i]]; } bailif0(jpegBuf=(*env)->GetPrimitiveArrayCritical(env, dst, 0)); if(ProcessSystemProperties(env)<0) goto bailout; if(tjCompressFromYUVPlanes(handle, srcPlanes, width, srcStrides, height, subsamp, &jpegBuf, &jpegSize, jpegQual, flags|TJFLAG_NOREALLOC)==-1) _throwtj(); bailout: if(jpegBuf) (*env)->ReleasePrimitiveArrayCritical(env, dst, jpegBuf, 0); for(i=0; i<nc; i++) { if(srcPlanes[i] && jSrcPlanes[i]) (*env)->ReleasePrimitiveArrayCritical(env, jSrcPlanes[i], srcPlanes[i], 0); } if(srcStrides) (*env)->ReleasePrimitiveArrayCritical(env, jSrcStrides, srcStrides, 0); if(srcOffsets) (*env)->ReleasePrimitiveArrayCritical(env, jSrcOffsets, srcOffsets, 0); return (jint)jpegSize; }
JNIEXPORT jintArray JNICALL Java_org_libjpegturbo_turbojpeg_TJTransformer_transform (JNIEnv *env, jobject obj, jbyteArray jsrcBuf, jint jpegSize, jobjectArray dstobjs, jobjectArray tobjs, jint flags) { tjhandle handle=0; int i; unsigned char *jpegBuf=NULL, **dstBufs=NULL; jsize n=0; unsigned long *dstSizes=NULL; tjtransform *t=NULL; jbyteArray *jdstBufs=NULL; int jpegWidth=0, jpegHeight=0, jpegSubsamp; jintArray jdstSizes=0; jint *dstSizesi=NULL; JNICustomFilterParams *params=NULL; gethandle(); if((*env)->GetArrayLength(env, jsrcBuf)<jpegSize) _throw("Source buffer is not large enough"); bailif0(_fid=(*env)->GetFieldID(env, _cls, "jpegWidth", "I")); jpegWidth=(int)(*env)->GetIntField(env, obj, _fid); bailif0(_fid=(*env)->GetFieldID(env, _cls, "jpegHeight", "I")); jpegHeight=(int)(*env)->GetIntField(env, obj, _fid); bailif0(_fid=(*env)->GetFieldID(env, _cls, "jpegSubsamp", "I")); jpegSubsamp=(int)(*env)->GetIntField(env, obj, _fid); n=(*env)->GetArrayLength(env, dstobjs); if(n!=(*env)->GetArrayLength(env, tobjs)) _throw("Mismatch between size of transforms array and destination buffers array"); if((dstBufs=(unsigned char **)malloc(sizeof(unsigned char *)*n))==NULL) _throw("Memory allocation failure"); if((jdstBufs=(jbyteArray *)malloc(sizeof(jbyteArray)*n))==NULL) _throw("Memory allocation failure"); if((dstSizes=(unsigned long *)malloc(sizeof(unsigned long)*n))==NULL) _throw("Memory allocation failure"); if((t=(tjtransform *)malloc(sizeof(tjtransform)*n))==NULL) _throw("Memory allocation failure"); if((params=(JNICustomFilterParams *)malloc(sizeof(JNICustomFilterParams)*n)) ==NULL) _throw("Memory allocation failure"); for(i=0; i<n; i++) { dstBufs[i]=NULL; jdstBufs[i]=NULL; dstSizes[i]=0; memset(&t[i], 0, sizeof(tjtransform)); memset(¶ms[i], 0, sizeof(JNICustomFilterParams)); } for(i=0; i<n; i++) { jobject tobj, cfobj; bailif0(tobj=(*env)->GetObjectArrayElement(env, tobjs, i)); bailif0(_cls=(*env)->GetObjectClass(env, tobj)); bailif0(_fid=(*env)->GetFieldID(env, _cls, "op", "I")); t[i].op=(*env)->GetIntField(env, tobj, _fid); bailif0(_fid=(*env)->GetFieldID(env, _cls, "options", "I")); t[i].options=(*env)->GetIntField(env, tobj, _fid); bailif0(_fid=(*env)->GetFieldID(env, _cls, "x", "I")); t[i].r.x=(*env)->GetIntField(env, tobj, _fid); bailif0(_fid=(*env)->GetFieldID(env, _cls, "y", "I")); t[i].r.y=(*env)->GetIntField(env, tobj, _fid); bailif0(_fid=(*env)->GetFieldID(env, _cls, "width", "I")); t[i].r.w=(*env)->GetIntField(env, tobj, _fid); bailif0(_fid=(*env)->GetFieldID(env, _cls, "height", "I")); t[i].r.h=(*env)->GetIntField(env, tobj, _fid); bailif0(_fid=(*env)->GetFieldID(env, _cls, "cf", "Lorg/libjpegturbo/turbojpeg/TJCustomFilter;")); cfobj=(*env)->GetObjectField(env, tobj, _fid); if(cfobj) { params[i].env=env; params[i].tobj=tobj; params[i].cfobj=cfobj; t[i].customFilter=JNICustomFilter; t[i].data=(void *)¶ms[i]; } } bailif0(jpegBuf=(*env)->GetPrimitiveArrayCritical(env, jsrcBuf, 0)); for(i=0; i<n; i++) { int w=jpegWidth, h=jpegHeight; if(t[i].r.w!=0) w=t[i].r.w; if(t[i].r.h!=0) h=t[i].r.h; bailif0(jdstBufs[i]=(*env)->GetObjectArrayElement(env, dstobjs, i)); if((unsigned long)(*env)->GetArrayLength(env, jdstBufs[i]) <tjBufSize(w, h, jpegSubsamp)) _throw("Destination buffer is not large enough"); bailif0(dstBufs[i]=(*env)->GetPrimitiveArrayCritical(env, jdstBufs[i], 0)); } if(tjTransform(handle, jpegBuf, jpegSize, n, dstBufs, dstSizes, t, flags|TJFLAG_NOREALLOC)==-1) { (*env)->ReleasePrimitiveArrayCritical(env, jsrcBuf, jpegBuf, 0); jpegBuf=NULL; for(i=0; i<n; i++) { (*env)->ReleasePrimitiveArrayCritical(env, jdstBufs[i], dstBufs[i], 0); dstBufs[i]=NULL; } _throw(tjGetErrorStr()); } jdstSizes=(*env)->NewIntArray(env, n); bailif0(dstSizesi=(*env)->GetIntArrayElements(env, jdstSizes, 0)); for(i=0; i<n; i++) dstSizesi[i]=(int)dstSizes[i]; bailout: if(jpegBuf) (*env)->ReleasePrimitiveArrayCritical(env, jsrcBuf, jpegBuf, 0); if(dstBufs) { for(i=0; i<n; i++) { if(dstBufs[i] && jdstBufs && jdstBufs[i]) (*env)->ReleasePrimitiveArrayCritical(env, jdstBufs[i], dstBufs[i], 0); } free(dstBufs); } if(jdstBufs) free(jdstBufs); if(dstSizes) free(dstSizes); if(dstSizesi) (*env)->ReleaseIntArrayElements(env, jdstSizes, dstSizesi, 0); if(t) free(t); return jdstSizes; }