コード例 #1
0
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() );
    }

}
コード例 #2
0
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() );
    }

}
コード例 #3
0
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());
	}
}
コード例 #4
0
ファイル: turbojpeg-jni.c プロジェクト: Doug-Pardee/LightZone
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;
}
コード例 #5
0
ファイル: turbojpeg-jni.c プロジェクト: Doug-Pardee/LightZone
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;
}
コード例 #6
0
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;
}
コード例 #7
0
/* 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;
}
コード例 #8
0
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;
}
コード例 #9
0
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;
}
コード例 #10
0
/* 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;
}
コード例 #11
0
ファイル: turbojpeg-jni.c プロジェクト: Doug-Pardee/LightZone
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;
}
コード例 #12
0
// 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;
}
コード例 #13
0
ファイル: turbojpeg-jni.c プロジェクト: Doug-Pardee/LightZone
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;
}
コード例 #14
0
ファイル: images.cpp プロジェクト: ema29/TemplePlus
	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;
	}
コード例 #15
0
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() );
    }

}
コード例 #16
0
ファイル: VrCommon.cpp プロジェクト: beijingkaka/shellspace
// 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;
}
コード例 #17
0
ファイル: turbojpeg-jni.c プロジェクト: Doug-Pardee/LightZone
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;
}
コード例 #18
0
ファイル: turbojpeg-jni.c プロジェクト: Doug-Pardee/LightZone
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;
}
コード例 #19
0
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;
}
コード例 #20
0
ファイル: turbojpeg-jni.c プロジェクト: Doug-Pardee/LightZone
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;
}
コード例 #21
0
ファイル: turbojpeg-jni.c プロジェクト: Doug-Pardee/LightZone
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;
}
コード例 #22
0
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;
}
コード例 #23
0
ファイル: VrCommon.cpp プロジェクト: beijingkaka/shellspace
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 );
}
コード例 #24
0
ファイル: turbojpeg-jni.c プロジェクト: Doug-Pardee/LightZone
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;
}
コード例 #25
0
ファイル: main.c プロジェクト: InvncibiltyCloak/radial_ws281x
// 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;
}
コード例 #26
0
ファイル: jpeg.c プロジェクト: darcyg/vapoursynth-plugins
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;
コード例 #27
0
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;
}
コード例 #28
0
/* 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;
}
コード例 #29
0
/* 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;
}
コード例 #30
0
ファイル: turbojpeg-jni.c プロジェクト: Doug-Pardee/LightZone
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(&params[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 *)&params[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;
}