/* TurboJPEG 1.2.x: TJDecompressor::decompressHeader() */
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, jpegColorspace=-1;

	gethandle();

	if((*env)->GetArrayLength(env, src)<jpegSize)
		_throwarg("Source buffer is not large enough");

	bailif0(jpegBuf=(*env)->GetPrimitiveArrayCritical(env, src, 0));

	if(tjDecompressHeader3(handle, jpegBuf, (unsigned long)jpegSize,
		&width, &height, &jpegSubsamp, &jpegColorspace)==-1)
		_throwtj();

	(*env)->ReleasePrimitiveArrayCritical(env, src, jpegBuf, 0);  jpegBuf=NULL;

	bailif0(_fid=(*env)->GetFieldID(env, _cls, "jpegSubsamp", "I"));
	(*env)->SetIntField(env, obj, _fid, jpegSubsamp);
	if((_fid=(*env)->GetFieldID(env, _cls, "jpegColorspace", "I"))==0)
		(*env)->ExceptionClear(env);
	else
		(*env)->SetIntField(env, obj, _fid, jpegColorspace);
	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:
	if(jpegBuf) (*env)->ReleasePrimitiveArrayCritical(env, src, jpegBuf, 0);
	return;
}
JNIEXPORT void JNICALL TJCompressor_encodeYUV_12
	(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)
		_throwarg("Invalid argument in encodeYUV()");
	if(org_libjpegturbo_turbojpeg_TJ_NUMPF!=TJ_NUMPF)
		_throwarg("Mismatch between Java and C API");

	arraySize=(pitch==0)? width*tjPixelSize[pf]*height:pitch*height;
	if((*env)->GetArrayLength(env, src)*srcElementSize<arraySize)
		_throwarg("Source buffer is not large enough");
	if((*env)->GetArrayLength(env, dst)
		<(jsize)tjBufSizeYUV(width, height, subsamp))
		_throwarg("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)
		_throwtj();

	bailout:
	if(dstBuf) (*env)->ReleasePrimitiveArrayCritical(env, dst, dstBuf, 0);
	if(srcBuf) (*env)->ReleasePrimitiveArrayCritical(env, src, srcBuf, 0);
	return;
}
/* TurboJPEG 1.2.x: TJDecompressor::decompressToYUV() */
JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompressToYUV___3BI_3BI
	(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)
		_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);
	if((*env)->GetArrayLength(env, dst)
		<(jsize)tjBufSizeYUV(jpegWidth, jpegHeight, jpegSubsamp))
		_throwarg("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)
		_throwtj();

	bailout:
	if(dstBuf) (*env)->ReleasePrimitiveArrayCritical(env, dst, dstBuf, 0);
	if(jpegBuf) (*env)->ReleasePrimitiveArrayCritical(env, src, jpegBuf, 0);
	return;
}
/* TurboJPEG 1.2.x: TJCompressor::destroy() */
JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_destroy
	(JNIEnv *env, jobject obj)
{
	tjhandle handle=0;

	gethandle();

	if(tjDestroy(handle)==-1) _throwtj();
	(*env)->SetLongField(env, obj, _fid, 0);

	bailout:
	return;
}
/* TurboJPEG 1.2.x: TJTransformer::init() */
JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJTransformer_init
	(JNIEnv *env, jobject obj)
{
	jclass cls;
	jfieldID fid;
	tjhandle handle;

	if((handle=tjInitTransform())==NULL) _throwtj();

	bailif0(cls=(*env)->GetObjectClass(env, obj));
	bailif0(fid=(*env)->GetFieldID(env, cls, "handle", "J"));
	(*env)->SetLongField(env, obj, fid, (size_t)handle);

	bailout:
	return;
}
static jint TJCompressor_compress
	(JNIEnv *env, jobject obj, jarray src, jint srcElementSize, jint x, jint y,
		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, actualPitch;
	unsigned char *srcBuf=NULL, *jpegBuf=NULL;

	gethandle();

	if(pf<0 || pf>=org_libjpegturbo_turbojpeg_TJ_NUMPF || width<1 || height<1
		|| pitch<0)
		_throwarg("Invalid argument in compress()");
	if(org_libjpegturbo_turbojpeg_TJ_NUMPF!=TJ_NUMPF)
		_throwarg("Mismatch between Java and C API");

	actualPitch=(pitch==0)? width*tjPixelSize[pf]:pitch;
	arraySize=(y+height-1)*actualPitch + (x+width)*tjPixelSize[pf];
	if((*env)->GetArrayLength(env, src)*srcElementSize<arraySize)
		_throwarg("Source buffer is not large enough");
	jpegSize=tjBufSize(width, height, jpegSubsamp);
	if((*env)->GetArrayLength(env, dst)<(jsize)jpegSize)
		_throwarg("Destination buffer is not large enough");

	bailif0(srcBuf=(*env)->GetPrimitiveArrayCritical(env, src, 0));
	bailif0(jpegBuf=(*env)->GetPrimitiveArrayCritical(env, dst, 0));

	if(ProcessSystemProperties(env)<0) goto bailout;

	if(tjCompress2(handle, &srcBuf[y*actualPitch + x*tjPixelSize[pf]], width,
		pitch, height, pf, &jpegBuf, &jpegSize, jpegSubsamp, jpegQual,
		flags|TJFLAG_NOREALLOC)==-1)
		_throwtj();

	bailout:
	if(jpegBuf) (*env)->ReleasePrimitiveArrayCritical(env, dst, jpegBuf, 0);
	if(srcBuf) (*env)->ReleasePrimitiveArrayCritical(env, src, srcBuf, 0);
	return (jint)jpegSize;
}
static void TJDecompressor_decompress
	(JNIEnv *env, jobject obj, jbyteArray src, jint jpegSize, 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;
	unsigned char *jpegBuf=NULL, *dstBuf=NULL;

	gethandle();

	if(pf<0 || pf>=org_libjpegturbo_turbojpeg_TJ_NUMPF)
		_throwarg("Invalid argument in decompress()");
	if(org_libjpegturbo_turbojpeg_TJ_NUMPF!=TJ_NUMPF)
		_throwarg("Mismatch between Java and C API");

	if((*env)->GetArrayLength(env, src)<jpegSize)
		_throwarg("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)*dstElementSize<arraySize)
		_throwarg("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)
		_throwtj();

	bailout:
	if(dstBuf) (*env)->ReleasePrimitiveArrayCritical(env, dst, dstBuf, 0);
	if(jpegBuf) (*env)->ReleasePrimitiveArrayCritical(env, src, jpegBuf, 0);
	return;
}
Beispiel #8
0
/* Decompression test */
int decomp(unsigned char *srcbuf, unsigned char **jpegbuf,
	unsigned long *jpegsize, unsigned char *dstbuf, int w, int h,
	int subsamp, int jpegqual, char *filename, int tilew, int tileh)
{
	char tempstr[1024], sizestr[20]="\0", qualstr[6]="\0", *ptr;
	FILE *file=NULL;  tjhandle handle=NULL;
	int row, col, iter=0, dstbufalloc=0, retval=0;
	double elapsed, elapsedDecode;
	int ps=tjPixelSize[pf];
	int scaledw=TJSCALED(w, sf);
	int scaledh=TJSCALED(h, sf);
	int pitch=scaledw*ps;
	int ntilesw=(w+tilew-1)/tilew, ntilesh=(h+tileh-1)/tileh;
	unsigned char *dstptr, *dstptr2, *yuvbuf=NULL;

	if(jpegqual>0)
	{
		snprintf(qualstr, 6, "_Q%d", jpegqual);
		qualstr[5]=0;
	}

	if((handle=tjInitDecompress())==NULL)
		_throwtj("executing tjInitDecompress()");

	if(dstbuf==NULL)
	{
		if((dstbuf=(unsigned char *)malloc(pitch*scaledh))==NULL)
			_throwunix("allocating destination buffer");
		dstbufalloc=1;
	}
	/* Set the destination buffer to gray so we know whether the decompressor
	   attempted to write to it */
	memset(dstbuf, 127, pitch*scaledh);

	if(doyuv)
	{
		int width=dotile? tilew:scaledw;
		int height=dotile? tileh:scaledh;
		int yuvsize=tjBufSizeYUV2(width, yuvpad, height, subsamp);
		if((yuvbuf=(unsigned char *)malloc(yuvsize))==NULL)
			_throwunix("allocating YUV buffer");
		memset(yuvbuf, 127, yuvsize);
	}

	/* Benchmark */
	iter=-warmup;
	elapsed=elapsedDecode=0.;
	while(1)
	{
		int tile=0;
		double start=gettime();
		for(row=0, dstptr=dstbuf; row<ntilesh; row++, dstptr+=pitch*tileh)
		{
			for(col=0, dstptr2=dstptr; col<ntilesw; col++, tile++, dstptr2+=ps*tilew)
			{
				int width=dotile? min(tilew, w-col*tilew):scaledw;
				int height=dotile? min(tileh, h-row*tileh):scaledh;
				if(doyuv)
				{
					double startDecode;
					if(tjDecompressToYUV2(handle, jpegbuf[tile], jpegsize[tile], yuvbuf,
						width, yuvpad, height, flags)==-1)
						_throwtj("executing tjDecompressToYUV2()");
					startDecode=gettime();
					if(tjDecodeYUV(handle, yuvbuf, yuvpad, subsamp, dstptr2, width,
						pitch, height, pf, flags)==-1)
						_throwtj("executing tjDecodeYUV()");
					if(iter>=0) elapsedDecode+=gettime()-startDecode;
				}
				else
					if(tjDecompress2(handle, jpegbuf[tile], jpegsize[tile], dstptr2,
						width, pitch, height, pf, flags)==-1)
						_throwtj("executing tjDecompress2()");
			}
		}
		iter++;
		if(iter>=1)
		{
			elapsed+=gettime()-start;
			if(elapsed>=benchtime) break;
		}
	}
	if(doyuv) elapsed-=elapsedDecode;

	if(tjDestroy(handle)==-1) _throwtj("executing tjDestroy()");
	handle=NULL;

	if(quiet)
	{
		printf("%-6s%s",
			sigfig((double)(w*h)/1000000.*(double)iter/elapsed, 4, tempstr, 1024),
			quiet==2? "\n":"  ");
		if(doyuv)
			printf("%s\n",
				sigfig((double)(w*h)/1000000.*(double)iter/elapsedDecode, 4, tempstr,
					1024));
		else if(quiet!=2) printf("\n");
	}
	else
	{
		printf("%s --> Frame rate:         %f fps\n",
			doyuv? "Decomp to YUV":"Decompress   ", (double)iter/elapsed);
		printf("                  Throughput:         %f Megapixels/sec\n",
			(double)(w*h)/1000000.*(double)iter/elapsed);
		if(doyuv)
		{
			printf("YUV Decode    --> Frame rate:         %f fps\n",
				(double)iter/elapsedDecode);
			printf("                  Throughput:         %f Megapixels/sec\n",
				(double)(w*h)/1000000.*(double)iter/elapsedDecode);
		}
	}
	if(sf.num!=1 || sf.denom!=1)
		snprintf(sizestr, 20, "%d_%d", sf.num, sf.denom);
	else if(tilew!=w || tileh!=h)
		snprintf(sizestr, 20, "%dx%d", tilew, tileh);
	else snprintf(sizestr, 20, "full");
	if(decomponly)
		snprintf(tempstr, 1024, "%s_%s.%s", filename, sizestr, ext);
	else
		snprintf(tempstr, 1024, "%s_%s%s_%s.%s", filename, subName[subsamp],
			qualstr, sizestr, ext);

	if(savebmp(tempstr, dstbuf, scaledw, scaledh, pf,
		(flags&TJFLAG_BOTTOMUP)!=0)==-1)
		_throwbmp("saving bitmap");
	ptr=strrchr(tempstr, '.');
	snprintf(ptr, 1024-(ptr-tempstr), "-err.%s", ext);
	if(srcbuf && sf.num==1 && sf.denom==1)
	{
		if(!quiet) printf("Compression error written to %s.\n", tempstr);
		if(subsamp==TJ_GRAYSCALE)
		{
			int index, index2;
			for(row=0, index=0; row<h; row++, index+=pitch)
			{
				for(col=0, index2=index; col<w; col++, index2+=ps)
				{
					int rindex=index2+tjRedOffset[pf];
					int gindex=index2+tjGreenOffset[pf];
					int bindex=index2+tjBlueOffset[pf];
					int y=(int)((double)srcbuf[rindex]*0.299
						+ (double)srcbuf[gindex]*0.587
						+ (double)srcbuf[bindex]*0.114 + 0.5);
					if(y>255) y=255;  if(y<0) y=0;
					dstbuf[rindex]=abs(dstbuf[rindex]-y);
					dstbuf[gindex]=abs(dstbuf[gindex]-y);
					dstbuf[bindex]=abs(dstbuf[bindex]-y);
				}
			}
		}
		else
		{
			for(row=0; row<h; row++)
				for(col=0; col<w*ps; col++)
					dstbuf[pitch*row+col]
						=abs(dstbuf[pitch*row+col]-srcbuf[pitch*row+col]);
		}
		if(savebmp(tempstr, dstbuf, w, h, pf,
			(flags&TJFLAG_BOTTOMUP)!=0)==-1)
			_throwbmp("saving bitmap");
	}

	bailout:
	if(file) fclose(file);
	if(handle) tjDestroy(handle);
	if(dstbuf && dstbufalloc) free(dstbuf);
	if(yuvbuf) free(yuvbuf);
	return retval;
}
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;
}
Beispiel #10
0
int decompTest(char *filename)
{
	FILE *file=NULL;  tjhandle handle=NULL;
	unsigned char **jpegbuf=NULL, *srcbuf=NULL;
	unsigned long *jpegsize=NULL, srcsize, totaljpegsize;
	tjtransform *t=NULL;
	int w=0, h=0, subsamp=-1, cs=-1, _w, _h, _tilew, _tileh,
		_ntilesw, _ntilesh, _subsamp;
	char *temp=NULL, tempstr[80], tempstr2[80];
	int row, col, i, iter, tilew, tileh, ntilesw=1, ntilesh=1, retval=0;
	double start, elapsed;
	int ps=tjPixelSize[pf], tile;

	if((file=fopen(filename, "rb"))==NULL)
		_throwunix("opening file");
	if(fseek(file, 0, SEEK_END)<0 || (srcsize=ftell(file))==(unsigned long)-1)
		_throwunix("determining file size");
	if((srcbuf=(unsigned char *)malloc(srcsize))==NULL)
		_throwunix("allocating memory");
	if(fseek(file, 0, SEEK_SET)<0)
		_throwunix("setting file position");
	if(fread(srcbuf, srcsize, 1, file)<1)
		_throwunix("reading JPEG data");
	fclose(file);  file=NULL;

	temp=strrchr(filename, '.');
	if(temp!=NULL) *temp='\0';

	if((handle=tjInitTransform())==NULL)
		_throwtj("executing tjInitTransform()");
	if(tjDecompressHeader3(handle, srcbuf, srcsize, &w, &h, &subsamp, &cs)==-1)
		_throwtj("executing tjDecompressHeader3()");
	if(cs==TJCS_YCCK || cs==TJCS_CMYK)
	{
		pf=TJPF_CMYK;  ps=tjPixelSize[pf];
	}

	if(quiet==1)
	{
		printf("All performance values in Mpixels/sec\n\n");
		printf("Bitmap     JPEG   JPEG     %s  %s   Xform   Comp    Decomp  ",
			dotile? "Tile ":"Image", dotile? "Tile ":"Image");
		if(doyuv) printf("Decode");
		printf("\n");
		printf("Format     CS     Subsamp  Width  Height  Perf    Ratio   Perf    ");
		if(doyuv) printf("Perf");
		printf("\n\n");
	}
	else if(!quiet)
		printf(">>>>>  JPEG %s --> %s (%s)  <<<<<\n",
			formatName(subsamp, cs, tempstr), pixFormatStr[pf],
			(flags&TJFLAG_BOTTOMUP)? "Bottom-up":"Top-down");

	for(tilew=dotile? 16:w, tileh=dotile? 16:h; ; tilew*=2, tileh*=2)
	{
		if(tilew>w) tilew=w;  if(tileh>h) tileh=h;
		ntilesw=(w+tilew-1)/tilew;  ntilesh=(h+tileh-1)/tileh;

		if((jpegbuf=(unsigned char **)malloc(sizeof(unsigned char *)
			*ntilesw*ntilesh))==NULL)
			_throwunix("allocating JPEG tile array");
		memset(jpegbuf, 0, sizeof(unsigned char *)*ntilesw*ntilesh);
		if((jpegsize=(unsigned long *)malloc(sizeof(unsigned long)
			*ntilesw*ntilesh))==NULL)
			_throwunix("allocating JPEG size array");
		memset(jpegsize, 0, sizeof(unsigned long)*ntilesw*ntilesh);

		if((flags&TJFLAG_NOREALLOC)!=0 || !dotile)
			for(i=0; i<ntilesw*ntilesh; i++)
			{
				if((jpegbuf[i]=(unsigned char *)tjAlloc(tjBufSize(tilew, tileh,
					subsamp)))==NULL)
					_throwunix("allocating JPEG tiles");
			}

		_w=w;  _h=h;  _tilew=tilew;  _tileh=tileh;
		if(!quiet)
		{
			printf("\n%s size: %d x %d", dotile? "Tile":"Image", _tilew,
				_tileh);
			if(sf.num!=1 || sf.denom!=1)
				printf(" --> %d x %d", TJSCALED(_w, sf), TJSCALED(_h, sf));
			printf("\n");
		}
		else if(quiet==1)
		{
			printf("%-4s (%s)  %-5s  %-5s    ", pixFormatStr[pf],
				(flags&TJFLAG_BOTTOMUP)? "BU":"TD", csName[cs], subNameLong[subsamp]);
			printf("%-5d  %-5d   ", tilew, tileh);
		}

		_subsamp=subsamp;
		if(dotile || xformop!=TJXOP_NONE || xformopt!=0 || customFilter)
		{
			if((t=(tjtransform *)malloc(sizeof(tjtransform)*ntilesw*ntilesh))
				==NULL)
				_throwunix("allocating image transform array");

			if(xformop==TJXOP_TRANSPOSE || xformop==TJXOP_TRANSVERSE
				|| xformop==TJXOP_ROT90 || xformop==TJXOP_ROT270)
			{
				_w=h;  _h=w;  _tilew=tileh;  _tileh=tilew;
			}

			if(xformopt&TJXOPT_GRAY) _subsamp=TJ_GRAYSCALE;
			if(xformop==TJXOP_HFLIP || xformop==TJXOP_ROT180)
				_w=_w-(_w%tjMCUWidth[_subsamp]);
			if(xformop==TJXOP_VFLIP || xformop==TJXOP_ROT180)
				_h=_h-(_h%tjMCUHeight[_subsamp]);
			if(xformop==TJXOP_TRANSVERSE || xformop==TJXOP_ROT90)
				_w=_w-(_w%tjMCUHeight[_subsamp]);
			if(xformop==TJXOP_TRANSVERSE || xformop==TJXOP_ROT270)
				_h=_h-(_h%tjMCUWidth[_subsamp]);
			_ntilesw=(_w+_tilew-1)/_tilew;
			_ntilesh=(_h+_tileh-1)/_tileh;

			if(xformop==TJXOP_TRANSPOSE || xformop==TJXOP_TRANSVERSE
				|| xformop==TJXOP_ROT90 || xformop==TJXOP_ROT270)
			{
				if(_subsamp==TJSAMP_422) _subsamp=TJSAMP_440;
				else if(_subsamp==TJSAMP_440) _subsamp=TJSAMP_422;
			}

			for(row=0, tile=0; row<_ntilesh; row++)
			{
				for(col=0; col<_ntilesw; col++, tile++)
				{
					t[tile].r.w=min(_tilew, _w-col*_tilew);
					t[tile].r.h=min(_tileh, _h-row*_tileh);
					t[tile].r.x=col*_tilew;
					t[tile].r.y=row*_tileh;
					t[tile].op=xformop;
					t[tile].options=xformopt|TJXOPT_TRIM;
					t[tile].customFilter=customFilter;
					if(t[tile].options&TJXOPT_NOOUTPUT && jpegbuf[tile])
					{
						tjFree(jpegbuf[tile]);  jpegbuf[tile]=NULL;
					}
				}
			}

			iter=-warmup;
			elapsed=0.;
			while(1)
			{
				start=gettime();
				if(tjTransform(handle, srcbuf, srcsize, _ntilesw*_ntilesh, jpegbuf,
					jpegsize, t, flags)==-1)
					_throwtj("executing tjTransform()");
				iter++;
				if(iter>=1)
				{
					elapsed+=gettime()-start;
					if(elapsed>=benchtime) break;
				}
			}

			free(t);  t=NULL;

			for(tile=0, totaljpegsize=0; tile<_ntilesw*_ntilesh; tile++)
				totaljpegsize+=jpegsize[tile];

			if(quiet)
			{
				printf("%-6s%s%-6s%s",
					sigfig((double)(w*h)/1000000./elapsed, 4, tempstr, 80),
					quiet==2? "\n":"  ",
					sigfig((double)(w*h*ps)/(double)totaljpegsize, 4, tempstr2, 80),
					quiet==2? "\n":"  ");
			}
			else if(!quiet)
			{
				printf("Transform     --> Frame rate:         %f fps\n", 1.0/elapsed);
				printf("                  Output image size:  %lu bytes\n", totaljpegsize);
				printf("                  Compression ratio:  %f:1\n",
					(double)(w*h*ps)/(double)totaljpegsize);
				printf("                  Throughput:         %f Megapixels/sec\n",
					(double)(w*h)/1000000./elapsed);
				printf("                  Output bit stream:  %f Megabits/sec\n",
					(double)totaljpegsize*8./1000000./elapsed);
			}
		}
		else
		{
			if(quiet==1) printf("N/A     N/A     ");
			jpegsize[0]=srcsize;
			memcpy(jpegbuf[0], srcbuf, srcsize);
		}

		if(w==tilew) _tilew=_w;
		if(h==tileh) _tileh=_h;
		if(!(xformopt&TJXOPT_NOOUTPUT))
		{
			if(decomp(NULL, jpegbuf, jpegsize, NULL, _w, _h, _subsamp, 0,
				filename, _tilew, _tileh)==-1)
				goto bailout;
		}
		else if(quiet==1) printf("N/A\n");

		for(i=0; i<ntilesw*ntilesh; i++)
		{
			tjFree(jpegbuf[i]);  jpegbuf[i]=NULL;
		}
		free(jpegbuf);  jpegbuf=NULL;
		if(jpegsize) {free(jpegsize);  jpegsize=NULL;}

		if(tilew==w && tileh==h) break;
	}

	bailout:
	if(file) {fclose(file);  file=NULL;}
	if(jpegbuf)
	{
		for(i=0; i<ntilesw*ntilesh; i++)
		{
			if(jpegbuf[i]) tjFree(jpegbuf[i]);  jpegbuf[i]=NULL;
		}
		free(jpegbuf);  jpegbuf=NULL;
	}
	if(jpegsize) {free(jpegsize);  jpegsize=NULL;}
	if(srcbuf) {free(srcbuf);  srcbuf=NULL;}
	if(t) {free(t);  t=NULL;}
	if(handle) {tjDestroy(handle);  handle=NULL;}
	return retval;
}
/* 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;
}
Beispiel #12
0
void dotestyuv(unsigned char *srcbuf, int w, int h, int subsamp,
	char *filename)
{
	char tempstr[1024], tempstr2[80];
	FILE *file=NULL;  tjhandle handle=NULL;
	unsigned char *dstbuf=NULL;
	double start, elapsed;
	int i, retval=0, ps=tjPixelSize[pf];
	int yuvsize=0;

	yuvsize=tjBufSizeYUV(w, h, subsamp);
	if((dstbuf=(unsigned char *)malloc(yuvsize)) == NULL)
		_throwunix("allocating image buffer");

	if(!quiet)
		printf(">>>>>  %s (%s) <--> YUV %s  <<<<<\n", pixFormatStr[pf],
			(flags&TJFLAG_BOTTOMUP)? "Bottom-up":"Top-down", subNameLong[subsamp]);

	if(quiet==1)
		printf("%s\t%s\t%s\tN/A\t", pixFormatStr[pf],
			(flags&TJFLAG_BOTTOMUP)? "BU":"TD", subNameLong[subsamp]);

	if((handle=tjInitCompress())==NULL)
		_throwtj("executing tjInitCompress()");

	/* Execute once to preload cache */
	if(tjEncodeYUV2(handle, srcbuf, w, 0, h, pf, dstbuf, subsamp, flags)==-1)
		_throwtj("executing tjEncodeYUV2()");

	/* Benchmark */
	for(i=0, start=gettime(); (elapsed=gettime()-start)<benchtime; i++)
	{
		if(tjEncodeYUV2(handle, srcbuf, w, 0, h, pf, dstbuf, subsamp, flags)==-1)
			_throwtj("executing tjEncodeYUV2()");
	}

	if(tjDestroy(handle)==-1) _throwtj("executing tjDestroy()");
	handle=NULL;

	if(quiet==1) printf("%-4d  %-4d\t", w, h);
	if(quiet)
	{
		printf("%s%c%s%c",
			sigfig((double)(w*h)/1000000.*(double)i/elapsed, 4, tempstr, 1024),
			quiet==2? '\n':'\t',
			sigfig((double)(w*h*ps)/(double)yuvsize, 4, tempstr2, 80),
			quiet==2? '\n':'\t');
	}
	else
	{
		printf("\n%s size: %d x %d\n", "Image", w, h);
		printf("C--> Frame rate:           %f fps\n", (double)i/elapsed);
		printf("     Output image size:    %d bytes\n", yuvsize);
		printf("     Compression ratio:    %f:1\n",
			(double)(w*h*ps)/(double)yuvsize);
		printf("     Source throughput:    %f Megapixels/sec\n",
			(double)(w*h)/1000000.*(double)i/elapsed);
		printf("     Output bit stream:    %f Megabits/sec\n",
			(double)yuvsize*8./1000000.*(double)i/elapsed);
	}
	snprintf(tempstr, 1024, "%s_%s.yuv", filename, subName[subsamp]);
	if((file=fopen(tempstr, "wb"))==NULL)
		_throwunix("opening reference image");
	if(fwrite(dstbuf, yuvsize, 1, file)!=1)
		_throwunix("writing reference image");
	fclose(file);  file=NULL;
	if(!quiet) printf("Reference image written to %s\n", tempstr);

	bailout:
	if(file) {fclose(file);  file=NULL;}
	if(dstbuf) {free(dstbuf);  dstbuf=NULL;}
	if(handle) {tjDestroy(handle);  handle=NULL;}
	return;
}
Beispiel #13
0
int main(int argc, char *argv[])
{
	unsigned char *srcbuf=NULL;  int w=0, h=0, i, j;
	int minqual=-1, maxqual=-1;  char *temp;
	int minarg=2, retval=0, subsamp=-1;

	if((scalingfactors=tjGetScalingFactors(&nsf))==NULL || nsf==0)
		_throwtj("executing tjGetScalingFactors()");

	if(argc<minarg) usage(argv[0]);

	temp=strrchr(argv[1], '.');
	if(temp!=NULL)
	{
		if(!strcasecmp(temp, ".bmp")) ext="bmp";
		if(!strcasecmp(temp, ".jpg") || !strcasecmp(temp, ".jpeg")) decomponly=1;
	}

	printf("\n");

	if(!decomponly)
	{
		minarg=3;
		if(argc<minarg) usage(argv[0]);
		if((minqual=atoi(argv[2]))<1 || minqual>100)
		{
			puts("ERROR: Quality must be between 1 and 100.");
			exit(1);
		}
		if((temp=strchr(argv[2], '-'))!=NULL && strlen(temp)>1
			&& sscanf(&temp[1], "%d", &maxqual)==1 && maxqual>minqual && maxqual>=1
			&& maxqual<=100) {}
		else maxqual=minqual;
	}

	if(argc>minarg)
	{
		for(i=minarg; i<argc; i++)
		{
			if(!strcasecmp(argv[i], "-tile"))
			{
				dotile=1;  xformopt|=TJXOPT_CROP;
			}
			if(!strcasecmp(argv[i], "-fastupsample"))
			{
				printf("Using fast upsampling code\n\n");
				flags|=TJFLAG_FASTUPSAMPLE;
			}
			if(!strcasecmp(argv[i], "-fastdct"))
			{
				printf("Using fastest DCT/IDCT algorithm\n\n");
				flags|=TJFLAG_FASTDCT;
			}
			if(!strcasecmp(argv[i], "-accuratedct"))
			{
				printf("Using most accurate DCT/IDCT algorithm\n\n");
				flags|=TJFLAG_ACCURATEDCT;
			}
			if(!strcasecmp(argv[i], "-rgb")) pf=TJPF_RGB;
			if(!strcasecmp(argv[i], "-rgbx")) pf=TJPF_RGBX;
			if(!strcasecmp(argv[i], "-bgr")) pf=TJPF_BGR;
			if(!strcasecmp(argv[i], "-bgrx")) pf=TJPF_BGRX;
			if(!strcasecmp(argv[i], "-xbgr")) pf=TJPF_XBGR;
			if(!strcasecmp(argv[i], "-xrgb")) pf=TJPF_XRGB;
			if(!strcasecmp(argv[i], "-cmyk")) pf=TJPF_CMYK;
			if(!strcasecmp(argv[i], "-bottomup")) flags|=TJFLAG_BOTTOMUP;
			if(!strcasecmp(argv[i], "-quiet")) quiet=1;
			if(!strcasecmp(argv[i], "-qq")) quiet=2;
			if(!strcasecmp(argv[i], "-scale") && i<argc-1)
			{
				int temp1=0, temp2=0, match=0;
				if(sscanf(argv[++i], "%d/%d", &temp1, &temp2)==2)
				{
					for(j=0; j<nsf; j++)
					{
						if((double)temp1/(double)temp2
							== (double)scalingfactors[j].num/(double)scalingfactors[j].denom)
						{
							sf=scalingfactors[j];
							match=1;  break;
						}
					}
					if(!match) usage(argv[0]);
				}
				else usage(argv[0]);
			}
			if(!strcasecmp(argv[i], "-hflip")) xformop=TJXOP_HFLIP;
			if(!strcasecmp(argv[i], "-vflip")) xformop=TJXOP_VFLIP;
			if(!strcasecmp(argv[i], "-transpose")) xformop=TJXOP_TRANSPOSE;
			if(!strcasecmp(argv[i], "-transverse")) xformop=TJXOP_TRANSVERSE;
			if(!strcasecmp(argv[i], "-rot90")) xformop=TJXOP_ROT90;
			if(!strcasecmp(argv[i], "-rot180")) xformop=TJXOP_ROT180;
			if(!strcasecmp(argv[i], "-rot270")) xformop=TJXOP_ROT270;
			if(!strcasecmp(argv[i], "-grayscale")) xformopt|=TJXOPT_GRAY;
			if(!strcasecmp(argv[i], "-custom")) customFilter=dummyDCTFilter;
			if(!strcasecmp(argv[i], "-nooutput")) xformopt|=TJXOPT_NOOUTPUT;
			if(!strcasecmp(argv[i], "-benchtime") && i<argc-1)
			{
				double temp=atof(argv[++i]);
				if(temp>0.0) benchtime=temp;
				else usage(argv[0]);
			}
			if(!strcasecmp(argv[i], "-warmup") && i<argc-1)
			{
				int temp=atoi(argv[++i]);
				if(temp>=0)
				{
					warmup=temp;
					printf("Warmup runs = %d\n\n", warmup);
				}
				else usage(argv[0]);
			}
			if(!strcmp(argv[i], "-?")) usage(argv[0]);
			if(!strcasecmp(argv[i], "-alloc")) flags&=(~TJFLAG_NOREALLOC);
			if(!strcasecmp(argv[i], "-bmp")) ext="bmp";
			if(!strcasecmp(argv[i], "-yuv"))
			{
				printf("Testing YUV planar encoding/decoding\n\n");
				doyuv=1;
			}
			if(!strcasecmp(argv[i], "-yuvpad") && i<argc-1)
			{
				int temp=atoi(argv[++i]);
				if(temp>=1) yuvpad=temp;
			}
			if(!strcasecmp(argv[i], "-subsamp") && i<argc-1)
			{
				i++;
				if(toupper(argv[i][0])=='G') subsamp=TJSAMP_GRAY;
				else
				{
					int temp=atoi(argv[i]);
					switch(temp)
					{
						case 444:  subsamp=TJSAMP_444;  break;
						case 422:  subsamp=TJSAMP_422;  break;
						case 440:  subsamp=TJSAMP_440;  break;
						case 420:  subsamp=TJSAMP_420;  break;
						case 411:  subsamp=TJSAMP_411;  break;
					}
				}
			}
			if(!strcasecmp(argv[i], "-componly")) componly=1;
		}
	}

	if((sf.num!=1 || sf.denom!=1) && dotile)
	{
		printf("Disabling tiled compression/decompression tests, because those tests do not\n");
		printf("work when scaled decompression is enabled.\n");
		dotile=0;
	}

	if((flags&TJFLAG_NOREALLOC)==0 && dotile)
	{
		printf("Disabling tiled compression/decompression tests, because those tests do not\n");
		printf("work when dynamic JPEG buffer allocation is enabled.\n\n");
		dotile=0;
	}

	if(!decomponly)
	{
		if(loadbmp(argv[1], &srcbuf, &w, &h, pf, (flags&TJFLAG_BOTTOMUP)!=0)==-1)
			_throwbmp("loading bitmap");
		temp=strrchr(argv[1], '.');
		if(temp!=NULL) *temp='\0';
	}

	if(quiet==1 && !decomponly)
	{
		printf("All performance values in Mpixels/sec\n\n");
		printf("Bitmap     JPEG     JPEG  %s  %s   ",
			dotile? "Tile ":"Image", dotile? "Tile ":"Image");
		if(doyuv) printf("Encode  ");
		printf("Comp    Comp    Decomp  ");
		if(doyuv) printf("Decode");
		printf("\n");
		printf("Format     Subsamp  Qual  Width  Height  ");
		if(doyuv) printf("Perf    ");
		printf("Perf    Ratio   Perf    ");
		if(doyuv) printf("Perf");
		printf("\n\n");
	}

	if(decomponly)
	{
		decompTest(argv[1]);
		printf("\n");
		goto bailout;
	}
	if(subsamp>=0 && subsamp<TJ_NUMSAMP)
	{
		for(i=maxqual; i>=minqual; i--)
			fullTest(srcbuf, w, h, subsamp, i, argv[1]);
		printf("\n");
	}
	else
	{
		if(pf!=TJPF_CMYK)
		{
			for(i=maxqual; i>=minqual; i--)
				fullTest(srcbuf, w, h, TJSAMP_GRAY, i, argv[1]);
			printf("\n");
		}
		for(i=maxqual; i>=minqual; i--)
			fullTest(srcbuf, w, h, TJSAMP_420, i, argv[1]);
		printf("\n");
		for(i=maxqual; i>=minqual; i--)
			fullTest(srcbuf, w, h, TJSAMP_422, i, argv[1]);
		printf("\n");
		for(i=maxqual; i>=minqual; i--)
			fullTest(srcbuf, w, h, TJSAMP_444, i, argv[1]);
		printf("\n");
	}

	bailout:
	if(srcbuf) free(srcbuf);
	return retval;
}
/* 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;
}
Beispiel #15
0
void dotest(unsigned char *srcbuf, int w, int h, int subsamp, int jpegqual,
	char *filename)
{
	char tempstr[1024], tempstr2[80];
	FILE *file=NULL;  tjhandle handle=NULL;
	unsigned char **jpegbuf=NULL, *tmpbuf=NULL, *srcptr, *srcptr2;
	double start, elapsed;
	int totaljpegsize=0, row, col, i, tilew=w, tileh=h, retval=0;
	unsigned long *jpegsize=NULL;
	int ps=tjPixelSize[pf], ntilesw=1, ntilesh=1, pitch=w*ps;

	if(yuv==YUVENCODE) {dotestyuv(srcbuf, w, h, subsamp, filename);  return;}

	if((tmpbuf=(unsigned char *)malloc(pitch*h)) == NULL)
		_throwunix("allocating temporary image buffer");

	if(!quiet)
		printf(">>>>>  %s (%s) <--> JPEG %s Q%d  <<<<<\n", pixFormatStr[pf],
			(flags&TJFLAG_BOTTOMUP)? "Bottom-up":"Top-down", subNameLong[subsamp],
			jpegqual);

	for(tilew=dotile? 8:w, tileh=dotile? 8:h; ; tilew*=2, tileh*=2)
	{
		if(tilew>w) tilew=w;  if(tileh>h) tileh=h;
		ntilesw=(w+tilew-1)/tilew;  ntilesh=(h+tileh-1)/tileh;

		if((jpegbuf=(unsigned char **)malloc(sizeof(unsigned char *)
			*ntilesw*ntilesh))==NULL)
			_throwunix("allocating JPEG tile array");
		memset(jpegbuf, 0, sizeof(unsigned char *)*ntilesw*ntilesh);
		if((jpegsize=(unsigned long *)malloc(sizeof(unsigned long)
			*ntilesw*ntilesh))==NULL)
			_throwunix("allocating JPEG size array");
		memset(jpegsize, 0, sizeof(unsigned long)*ntilesw*ntilesh);

		if((flags&TJFLAG_NOREALLOC)!=0)
			for(i=0; i<ntilesw*ntilesh; i++)
			{
				if((jpegbuf[i]=(unsigned char *)malloc(tjBufSize(tilew, tileh,
					subsamp)))==NULL)
					_throwunix("allocating JPEG tiles");
			}

		/* Compression test */
		if(quiet==1)
			printf("%s\t%s\t%s\t%d\t", pixFormatStr[pf],
				(flags&TJFLAG_BOTTOMUP)? "BU":"TD", subNameLong[subsamp], jpegqual);
		for(i=0; i<h; i++)
			memcpy(&tmpbuf[pitch*i], &srcbuf[w*ps*i], w*ps);
		if((handle=tjInitCompress())==NULL)
			_throwtj("executing tjInitCompress()");

		/* Execute once to preload cache */
		if(tjCompress2(handle, srcbuf, tilew, pitch, tileh, pf, &jpegbuf[0],
			&jpegsize[0], subsamp, jpegqual, flags)==-1)
			_throwtj("executing tjCompress2()");

		/* Benchmark */
		for(i=0, start=gettime(); (elapsed=gettime()-start)<benchtime; i++)
		{
			int tile=0;
			totaljpegsize=0;
			for(row=0, srcptr=srcbuf; row<ntilesh; row++, srcptr+=pitch*tileh)
			{
				for(col=0, srcptr2=srcptr; col<ntilesw; col++, tile++,
					srcptr2+=ps*tilew)
				{
					int width=min(tilew, w-col*tilew);
					int height=min(tileh, h-row*tileh);
					if(tjCompress2(handle, srcptr2, width, pitch, height, pf,
						&jpegbuf[tile], &jpegsize[tile], subsamp, jpegqual, flags)==-1)
						_throwtj("executing tjCompress()2");
					totaljpegsize+=jpegsize[tile];
				}
			}
		}

		if(tjDestroy(handle)==-1) _throwtj("executing tjDestroy()");
		handle=NULL;

		if(quiet==1) printf("%-4d  %-4d\t", tilew, tileh);
		if(quiet)
		{
			printf("%s%c%s%c",
				sigfig((double)(w*h)/1000000.*(double)i/elapsed, 4, tempstr, 1024),
				quiet==2? '\n':'\t',
				sigfig((double)(w*h*ps)/(double)totaljpegsize, 4, tempstr2, 80),
				quiet==2? '\n':'\t');
		}
		else
		{
			printf("\n%s size: %d x %d\n", dotile? "Tile":"Image", tilew,
				tileh);
			printf("C--> Frame rate:           %f fps\n", (double)i/elapsed);
			printf("     Output image size:    %d bytes\n", totaljpegsize);
			printf("     Compression ratio:    %f:1\n",
				(double)(w*h*ps)/(double)totaljpegsize);
			printf("     Source throughput:    %f Megapixels/sec\n",
				(double)(w*h)/1000000.*(double)i/elapsed);
			printf("     Output bit stream:    %f Megabits/sec\n",
				(double)totaljpegsize*8./1000000.*(double)i/elapsed);
		}
		if(tilew==w && tileh==h)
		{
			snprintf(tempstr, 1024, "%s_%s_Q%d.jpg", filename, subName[subsamp],
				jpegqual);
			if((file=fopen(tempstr, "wb"))==NULL)
				_throwunix("opening reference image");
			if(fwrite(jpegbuf[0], jpegsize[0], 1, file)!=1)
				_throwunix("writing reference image");
			fclose(file);  file=NULL;
			if(!quiet) printf("Reference image written to %s\n", tempstr);
		}

		/* Decompression test */
		if(decomptest(srcbuf, jpegbuf, jpegsize, tmpbuf, w, h, subsamp, jpegqual,
			filename, tilew, tileh)==-1)
			goto bailout;

		for(i=0; i<ntilesw*ntilesh; i++)
		{
			if(jpegbuf[i]) free(jpegbuf[i]);  jpegbuf[i]=NULL;
		}
		free(jpegbuf);  jpegbuf=NULL;
		free(jpegsize);  jpegsize=NULL;

		if(tilew==w && tileh==h) break;
	}

	bailout:
	if(file) {fclose(file);  file=NULL;}
	if(jpegbuf)
	{
		for(i=0; i<ntilesw*ntilesh; i++)
		{
			if(jpegbuf[i]) free(jpegbuf[i]);  jpegbuf[i]=NULL;
		}
		free(jpegbuf);  jpegbuf=NULL;
	}
	if(jpegsize) {free(jpegsize);  jpegsize=NULL;}
	if(tmpbuf) {free(tmpbuf);  tmpbuf=NULL;}
	if(handle) {tjDestroy(handle);  handle=NULL;}
	return;
}
Beispiel #16
0
int fullTest(unsigned char *srcbuf, int w, int h, int subsamp, int jpegqual,
	char *filename)
{
	char tempstr[1024], tempstr2[80];
	FILE *file=NULL;  tjhandle handle=NULL;
	unsigned char **jpegbuf=NULL, *yuvbuf=NULL, *tmpbuf=NULL, *srcptr, *srcptr2;
	double start, elapsed, elapsedEncode;
	int totaljpegsize=0, row, col, i, tilew=w, tileh=h, retval=0;
	int iter, yuvsize=0;
	unsigned long *jpegsize=NULL;
	int ps=tjPixelSize[pf];
	int ntilesw=1, ntilesh=1, pitch=w*ps;
	const char *pfStr=pixFormatStr[pf];

	if((tmpbuf=(unsigned char *)malloc(pitch*h)) == NULL)
		_throwunix("allocating temporary image buffer");

	if(!quiet)
		printf(">>>>>  %s (%s) <--> JPEG %s Q%d  <<<<<\n", pfStr,
			(flags&TJFLAG_BOTTOMUP)? "Bottom-up":"Top-down", subNameLong[subsamp],
			jpegqual);

	for(tilew=dotile? 8:w, tileh=dotile? 8:h; ; tilew*=2, tileh*=2)
	{
		if(tilew>w) tilew=w;  if(tileh>h) tileh=h;
		ntilesw=(w+tilew-1)/tilew;  ntilesh=(h+tileh-1)/tileh;

		if((jpegbuf=(unsigned char **)malloc(sizeof(unsigned char *)
			*ntilesw*ntilesh))==NULL)
			_throwunix("allocating JPEG tile array");
		memset(jpegbuf, 0, sizeof(unsigned char *)*ntilesw*ntilesh);
		if((jpegsize=(unsigned long *)malloc(sizeof(unsigned long)
			*ntilesw*ntilesh))==NULL)
			_throwunix("allocating JPEG size array");
		memset(jpegsize, 0, sizeof(unsigned long)*ntilesw*ntilesh);

		if((flags&TJFLAG_NOREALLOC)!=0)
			for(i=0; i<ntilesw*ntilesh; i++)
			{
				if((jpegbuf[i]=(unsigned char *)tjAlloc(tjBufSize(tilew, tileh,
					subsamp)))==NULL)
					_throwunix("allocating JPEG tiles");
			}

		/* Compression test */
		if(quiet==1)
			printf("%-4s (%s)  %-5s    %-3d   ", pfStr,
				(flags&TJFLAG_BOTTOMUP)? "BU":"TD", subNameLong[subsamp], jpegqual);
		for(i=0; i<h; i++)
			memcpy(&tmpbuf[pitch*i], &srcbuf[w*ps*i], w*ps);
		if((handle=tjInitCompress())==NULL)
			_throwtj("executing tjInitCompress()");

		if(doyuv)
		{
			yuvsize=tjBufSizeYUV2(tilew, yuvpad, tileh, subsamp);
			if((yuvbuf=(unsigned char *)malloc(yuvsize))==NULL)
				_throwunix("allocating YUV buffer");
			memset(yuvbuf, 127, yuvsize);
		}

		/* Benchmark */
		iter=-warmup;
		elapsed=elapsedEncode=0.;
		while(1)
		{
			int tile=0;
			totaljpegsize=0;
			start=gettime();
			for(row=0, srcptr=srcbuf; row<ntilesh; row++, srcptr+=pitch*tileh)
			{
				for(col=0, srcptr2=srcptr; col<ntilesw; col++, tile++,
					srcptr2+=ps*tilew)
				{
					int width=min(tilew, w-col*tilew);
					int height=min(tileh, h-row*tileh);
					if(doyuv)
					{
						double startEncode=gettime();
						if(tjEncodeYUV3(handle, srcptr2, width, pitch, height, pf, yuvbuf,
							yuvpad, subsamp, flags)==-1)
							_throwtj("executing tjEncodeYUV3()");
						if(iter>=0) elapsedEncode+=gettime()-startEncode;
						if(tjCompressFromYUV(handle, yuvbuf, width, yuvpad, height,
							subsamp, &jpegbuf[tile], &jpegsize[tile], jpegqual, flags)==-1)
							_throwtj("executing tjCompressFromYUV()");
					}
					else
					{
						if(tjCompress2(handle, srcptr2, width, pitch, height, pf,
							&jpegbuf[tile], &jpegsize[tile], subsamp, jpegqual, flags)==-1)
							_throwtj("executing tjCompress2()");
					}
					totaljpegsize+=jpegsize[tile];
				}
			}
			iter++;
			if(iter>=1)
			{
				elapsed+=gettime()-start;
				if(elapsed>=benchtime) break;
			}
		}
		if(doyuv) elapsed-=elapsedEncode;

		if(tjDestroy(handle)==-1) _throwtj("executing tjDestroy()");
		handle=NULL;

		if(quiet==1) printf("%-5d  %-5d   ", tilew, tileh);
		if(quiet)
		{
			if(doyuv)
				printf("%-6s%s",
					sigfig((double)(w*h)/1000000.*(double)iter/elapsedEncode, 4, tempstr,
						1024), quiet==2? "\n":"  ");
			printf("%-6s%s",
				sigfig((double)(w*h)/1000000.*(double)iter/elapsed, 4,	tempstr, 1024),
				quiet==2? "\n":"  ");
			printf("%-6s%s",
				sigfig((double)(w*h*ps)/(double)totaljpegsize, 4, tempstr2, 80),
				quiet==2? "\n":"  ");
		}
		else
		{
			printf("\n%s size: %d x %d\n", dotile? "Tile":"Image", tilew,
				tileh);
			if(doyuv)
			{
				printf("Encode YUV    --> Frame rate:         %f fps\n",
					(double)iter/elapsedEncode);
				printf("                  Output image size:  %d bytes\n", yuvsize);
				printf("                  Compression ratio:  %f:1\n",
					(double)(w*h*ps)/(double)yuvsize);
				printf("                  Throughput:         %f Megapixels/sec\n",
					(double)(w*h)/1000000.*(double)iter/elapsedEncode);
				printf("                  Output bit stream:  %f Megabits/sec\n",
					(double)yuvsize*8./1000000.*(double)iter/elapsedEncode);
			}
			printf("%s --> Frame rate:         %f fps\n",
				doyuv? "Comp from YUV":"Compress     ", (double)iter/elapsed);
			printf("                  Output image size:  %d bytes\n",
				totaljpegsize);
			printf("                  Compression ratio:  %f:1\n",
				(double)(w*h*ps)/(double)totaljpegsize);
			printf("                  Throughput:         %f Megapixels/sec\n",
				(double)(w*h)/1000000.*(double)iter/elapsed);
			printf("                  Output bit stream:  %f Megabits/sec\n",
				(double)totaljpegsize*8./1000000.*(double)iter/elapsed);
		}
		if(tilew==w && tileh==h)
		{
			snprintf(tempstr, 1024, "%s_%s_Q%d.jpg", filename, subName[subsamp],
				jpegqual);
			if((file=fopen(tempstr, "wb"))==NULL)
				_throwunix("opening reference image");
			if(fwrite(jpegbuf[0], jpegsize[0], 1, file)!=1)
				_throwunix("writing reference image");
			fclose(file);  file=NULL;
			if(!quiet) printf("Reference image written to %s\n", tempstr);
		}

		/* Decompression test */
		if(!componly)
		{
			if(decomp(srcbuf, jpegbuf, jpegsize, tmpbuf, w, h, subsamp, jpegqual,
				filename, tilew, tileh)==-1)
				goto bailout;
		}

		for(i=0; i<ntilesw*ntilesh; i++)
		{
			if(jpegbuf[i]) tjFree(jpegbuf[i]);  jpegbuf[i]=NULL;
		}
		free(jpegbuf);  jpegbuf=NULL;
		free(jpegsize);  jpegsize=NULL;
		if(doyuv)
		{
			free(yuvbuf);  yuvbuf=NULL;
		}

		if(tilew==w && tileh==h) break;
	}

	bailout:
	if(file) {fclose(file);  file=NULL;}
	if(jpegbuf)
	{
		for(i=0; i<ntilesw*ntilesh; i++)
		{
			if(jpegbuf[i]) tjFree(jpegbuf[i]);  jpegbuf[i]=NULL;
		}
		free(jpegbuf);  jpegbuf=NULL;
	}
	if(yuvbuf) {free(yuvbuf);  yuvbuf=NULL;}
	if(jpegsize) {free(jpegsize);  jpegsize=NULL;}
	if(tmpbuf) {free(tmpbuf);  tmpbuf=NULL;}
	if(handle) {tjDestroy(handle);  handle=NULL;}
	return retval;
}
/* TurboJPEG 1.2.x: TJTransformer::transform() */
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)
		_throwarg("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))
		_throwarg("Mismatch between size of transforms array and destination buffers array");

	if((dstBufs=(unsigned char **)malloc(sizeof(unsigned char *)*n))==NULL)
		_throwmem();
	if((jdstBufs=(jbyteArray *)malloc(sizeof(jbyteArray)*n))==NULL)
		_throwmem();
	if((dstSizes=(unsigned long *)malloc(sizeof(unsigned long)*n))==NULL)
		_throwmem();
	if((t=(tjtransform *)malloc(sizeof(tjtransform)*n))==NULL)
		_throwmem();
	if((params=(JNICustomFilterParams *)malloc(sizeof(JNICustomFilterParams)*n))
		==NULL)
		_throwmem();
	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];
		}
	}

	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))
			_throwarg("Destination buffer is not large enough");
	}
	bailif0(jpegBuf=(*env)->GetPrimitiveArrayCritical(env, jsrcBuf, 0));
	for(i=0; i<n; i++)
		bailif0(dstBufs[i]=(*env)->GetPrimitiveArrayCritical(env, jdstBufs[i], 0));

	if(tjTransform(handle, jpegBuf, jpegSize, n, dstBufs, dstSizes, t,
		flags|TJFLAG_NOREALLOC)==-1)
		_throwtj();

	for(i=0; i<n; i++)
	{
		(*env)->ReleasePrimitiveArrayCritical(env, jdstBufs[i], dstBufs[i], 0);
		dstBufs[i]=NULL;
	}
	(*env)->ReleasePrimitiveArrayCritical(env, jsrcBuf, jpegBuf, 0);
	jpegBuf=NULL;

	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(dstSizesi) (*env)->ReleaseIntArrayElements(env, jdstSizes, dstSizesi, 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(jpegBuf) (*env)->ReleasePrimitiveArrayCritical(env, jsrcBuf, jpegBuf, 0);
	if(jdstBufs) free(jdstBufs);
	if(dstSizes) free(dstSizes);
	if(t) free(t);
	return jdstSizes;
}
Beispiel #18
0
/* Decompression test */
int decomptest(unsigned char *srcbuf, unsigned char **jpegbuf,
	unsigned long *jpegsize, unsigned char *dstbuf, int w, int h,
	int subsamp, int jpegqual, char *filename, int tilew, int tileh)
{
	char tempstr[1024], sizestr[20]="\0", qualstr[6]="\0", *ptr;
	FILE *file=NULL;  tjhandle handle=NULL;
	int row, col, i, dstbufalloc=0, retval=0;
	double start, elapsed;
	int ps=tjPixelSize[pf];
	int yuvsize=tjBufSizeYUV(w, h, subsamp), bufsize;
	int scaledw=(yuv==YUVDECODE)? w : TJSCALED(w, sf);
	int scaledh=(yuv==YUVDECODE)? h : TJSCALED(h, sf);
	int pitch=scaledw*ps;
	int ntilesw=(w+tilew-1)/tilew, ntilesh=(h+tileh-1)/tileh;
	unsigned char *dstptr, *dstptr2;

	if(jpegqual>0)
	{
		snprintf(qualstr, 6, "_Q%d", jpegqual);
		qualstr[5]=0;
	}

	if((handle=tjInitDecompress())==NULL)
		_throwtj("executing tjInitDecompress()");

	bufsize=(yuv==YUVDECODE? yuvsize:pitch*h);
	if(dstbuf==NULL)
	{
		if((dstbuf=(unsigned char *)malloc(bufsize)) == NULL)
			_throwunix("allocating image buffer");
		dstbufalloc=1;
	}
	/* Set the destination buffer to gray so we know whether the decompressor
	   attempted to write to it */
	memset(dstbuf, 127, bufsize);

	/* Execute once to preload cache */
	if(yuv==YUVDECODE)
	{
		if(tjDecompressToYUV(handle, jpegbuf[0], jpegsize[0], dstbuf, flags)==-1)
			_throwtj("executing tjDecompressToYUV()");
	}
	else if(tjDecompress2(handle, jpegbuf[0], jpegsize[0], dstbuf, scaledw,
		pitch, scaledh, pf, flags)==-1)
		_throwtj("executing tjDecompress2()");

	/* Benchmark */
	for(i=0, start=gettime(); (elapsed=gettime()-start)<benchtime; i++)
	{
		int tile=0;
		if(yuv==YUVDECODE)
		{
			if(tjDecompressToYUV(handle, jpegbuf[0], jpegsize[0], dstbuf, flags)==-1)
			_throwtj("executing tjDecompressToYUV()");
		}
		else for(row=0, dstptr=dstbuf; row<ntilesh; row++, dstptr+=pitch*tileh)
		{
			for(col=0, dstptr2=dstptr; col<ntilesw; col++, tile++, dstptr2+=ps*tilew)
			{
				int width=dotile? min(tilew, w-col*tilew):scaledw;
				int height=dotile? min(tileh, h-row*tileh):scaledh;
				if(tjDecompress2(handle, jpegbuf[tile], jpegsize[tile], dstptr2, width,
					pitch, height, pf, flags)==-1)
					_throwtj("executing tjDecompress2()");
			}
		}
	}

	if(tjDestroy(handle)==-1) _throwtj("executing tjDestroy()");
	handle=NULL;

	if(quiet)
	{
		printf("%s\n",
			sigfig((double)(w*h)/1000000.*(double)i/elapsed, 4, tempstr, 1024));
	}
	else
	{
		printf("D--> Frame rate:           %f fps\n", (double)i/elapsed);
		printf("     Dest. throughput:     %f Megapixels/sec\n",
			(double)(w*h)/1000000.*(double)i/elapsed);
	}
	if(yuv==YUVDECODE)
	{
		snprintf(tempstr, 1024, "%s_%s%s.yuv", filename, subName[subsamp],
			qualstr);
		if((file=fopen(tempstr, "wb"))==NULL)
			_throwunix("opening YUV image for output");
		if(fwrite(dstbuf, yuvsize, 1, file)!=1)
			_throwunix("writing YUV image");
		fclose(file);  file=NULL;
	}
	else
	{
		if(sf.num!=1 || sf.denom!=1)
			snprintf(sizestr, 20, "%d_%d", sf.num, sf.denom);
		else if(tilew!=w || tileh!=h)
			snprintf(sizestr, 20, "%dx%d", tilew, tileh);
		else snprintf(sizestr, 20, "full");
		if(decomponly)
			snprintf(tempstr, 1024, "%s_%s.%s", filename, sizestr, ext);
		else
			snprintf(tempstr, 1024, "%s_%s%s_%s.%s", filename, subName[subsamp],
				qualstr, sizestr, ext);
		if(savebmp(tempstr, dstbuf, scaledw, scaledh, pf,
			(flags&TJFLAG_BOTTOMUP)!=0)==-1)
			_throwbmp("saving bitmap");
		ptr=strrchr(tempstr, '.');
		snprintf(ptr, 1024-(ptr-tempstr), "-err.%s", ext);
		if(srcbuf && sf.num==1 && sf.denom==1)
		{
			if(!quiet) printf("Compression error written to %s.\n", tempstr);
			if(subsamp==TJ_GRAYSCALE)
			{
				int index, index2;
				for(row=0, index=0; row<h; row++, index+=pitch)
				{
					for(col=0, index2=index; col<w; col++, index2+=ps)
					{
						int rindex=index2+tjRedOffset[pf];
						int gindex=index2+tjGreenOffset[pf];
						int bindex=index2+tjBlueOffset[pf];
						int y=(int)((double)srcbuf[rindex]*0.299
							+ (double)srcbuf[gindex]*0.587
							+ (double)srcbuf[bindex]*0.114 + 0.5);
						if(y>255) y=255;  if(y<0) y=0;
						dstbuf[rindex]=abs(dstbuf[rindex]-y);
						dstbuf[gindex]=abs(dstbuf[gindex]-y);
						dstbuf[bindex]=abs(dstbuf[bindex]-y);
					}
				}
			}		
			else
			{
				for(row=0; row<h; row++)
					for(col=0; col<w*ps; col++)
						dstbuf[pitch*row+col]
							=abs(dstbuf[pitch*row+col]-srcbuf[pitch*row+col]);
			}
			if(savebmp(tempstr, dstbuf, w, h, pf,
				(flags&TJFLAG_BOTTOMUP)!=0)==-1)
				_throwbmp("saving bitmap");
		}
	}

	bailout:
	if(file) {fclose(file);  file=NULL;}
	if(handle) {tjDestroy(handle);  handle=NULL;}
	if(dstbuf && dstbufalloc) {free(dstbuf);  dstbuf=NULL;}
	return retval;
}
Beispiel #19
0
int main(int argc, char *argv[])
{
	unsigned char *srcbuf=NULL;  int w, h, i, j;
	int minqual=-1, maxqual=-1;  char *temp;
	int minarg=2;  int retval=0;

	if((scalingfactors=tjGetScalingFactors(&nsf))==NULL || nsf==0)
		_throwtj("executing tjGetScalingFactors()");

	if(argc<minarg) usage(argv[0]);

	temp=strrchr(argv[1], '.');
	if(temp!=NULL)
	{
		if(!strcasecmp(temp, ".bmp")) ext="bmp";
		if(!strcasecmp(temp, ".jpg") || !strcasecmp(temp, ".jpeg")) decomponly=1;
	}

	printf("\n");

	if(argc>minarg)
	{
		for(i=minarg; i<argc; i++)
		{
			if(!strcasecmp(argv[i], "-yuvencode"))
			{
				printf("Testing YUV planar encoding\n\n");
				yuv=YUVENCODE;  maxqual=minqual=100;
			}
			if(!strcasecmp(argv[i], "-yuvdecode"))
			{
				printf("Testing YUV planar decoding\n\n");
				yuv=YUVDECODE;
			}
		}
	}

	if(!decomponly && yuv!=YUVENCODE)
	{
		minarg=3;
		if(argc<minarg) usage(argv[0]);
		if((minqual=atoi(argv[2]))<1 || minqual>100)
		{
			puts("ERROR: Quality must be between 1 and 100.");
			exit(1);
		}
		if((temp=strchr(argv[2], '-'))!=NULL && strlen(temp)>1
			&& sscanf(&temp[1], "%d", &maxqual)==1 && maxqual>minqual && maxqual>=1
			&& maxqual<=100) {}
		else maxqual=minqual;
	}

	if(argc>minarg)
	{
		for(i=minarg; i<argc; i++)
		{
			if(!strcasecmp(argv[i], "-tile"))
			{
				dotile=1;  xformopt|=TJXOPT_CROP;
			}
			if(!strcasecmp(argv[i], "-forcesse3"))
			{
				printf("Forcing SSE3 code\n\n");
				flags|=TJFLAG_FORCESSE3;
			}
			if(!strcasecmp(argv[i], "-forcesse2"))
			{
				printf("Forcing SSE2 code\n\n");
				flags|=TJFLAG_FORCESSE2;
			}
			if(!strcasecmp(argv[i], "-forcesse"))
			{
				printf("Forcing SSE code\n\n");
				flags|=TJFLAG_FORCESSE;
			}
			if(!strcasecmp(argv[i], "-forcemmx"))
			{
				printf("Forcing MMX code\n\n");
				flags|=TJFLAG_FORCEMMX;
			}
			if(!strcasecmp(argv[i], "-fastupsample"))
			{
				printf("Using fast upsampling code\n\n");
				flags|=TJFLAG_FASTUPSAMPLE;
			}
			if(!strcasecmp(argv[i], "-rgb")) pf=TJPF_RGB;
			if(!strcasecmp(argv[i], "-rgbx")) pf=TJPF_RGBX;
			if(!strcasecmp(argv[i], "-bgr")) pf=TJPF_BGR;
			if(!strcasecmp(argv[i], "-bgrx")) pf=TJPF_BGRX;
			if(!strcasecmp(argv[i], "-xbgr")) pf=TJPF_XBGR;
			if(!strcasecmp(argv[i], "-xrgb")) pf=TJPF_XRGB;
			if(!strcasecmp(argv[i], "-bottomup")) flags|=TJFLAG_BOTTOMUP;
			if(!strcasecmp(argv[i], "-quiet")) quiet=1;
			if(!strcasecmp(argv[i], "-qq")) quiet=2;
			if(!strcasecmp(argv[i], "-scale") && i<argc-1)
			{
				int temp1=0, temp2=0, match=0;
				if(sscanf(argv[++i], "%d/%d", &temp1, &temp2)==2)
				{
					for(j=0; j<nsf; j++)
					{
						if(temp1==scalingfactors[j].num && temp2==scalingfactors[j].denom)
						{
							sf=scalingfactors[j];
							match=1;  break;
						}
					}
					if(!match) usage(argv[0]);
				}
				else usage(argv[0]);
			}
			if(!strcasecmp(argv[i], "-hflip")) xformop=TJXOP_HFLIP;
			if(!strcasecmp(argv[i], "-vflip")) xformop=TJXOP_VFLIP;
			if(!strcasecmp(argv[i], "-transpose")) xformop=TJXOP_TRANSPOSE;
			if(!strcasecmp(argv[i], "-transverse")) xformop=TJXOP_TRANSVERSE;
			if(!strcasecmp(argv[i], "-rot90")) xformop=TJXOP_ROT90;
			if(!strcasecmp(argv[i], "-rot180")) xformop=TJXOP_ROT180;
			if(!strcasecmp(argv[i], "-rot270")) xformop=TJXOP_ROT270;
			if(!strcasecmp(argv[i], "-grayscale")) xformopt|=TJXOPT_GRAY;
			if(!strcasecmp(argv[i], "-benchtime") && i<argc-1)
			{
				double temp=atof(argv[++i]);
				if(temp>0.0) benchtime=temp;
				else usage(argv[0]);
			}
			if(!strcmp(argv[i], "-?")) usage(argv[0]);
			if(!strcasecmp(argv[i], "-alloc")) flags&=(~TJFLAG_NOREALLOC);
			if(!strcasecmp(argv[i], "-bmp")) ext="bmp";
		}
	}

	if((sf.num!=1 || sf.denom!=1) && dotile)
	{
		printf("Disabling tiled compression/decompression tests, because those tests do not\n");
		printf("work when scaled decompression is enabled.\n");
		dotile=0;
	}

	if(yuv && dotile)
	{
		printf("Disabling tiled compression/decompression tests, because those tests do not\n");
		printf("work when YUV encoding or decoding is enabled.\n\n");
		dotile=0;
	}

	if(!decomponly)
	{
		if(loadbmp(argv[1], &srcbuf, &w, &h, pf, (flags&TJFLAG_BOTTOMUP)!=0)==-1)
			_throwbmp("loading bitmap");
		temp=strrchr(argv[1], '.');
		if(temp!=NULL) *temp='\0';
	}

	if(quiet==1 && !decomponly)
	{
		printf("All performance values in Mpixels/sec\n\n");
		printf("Bitmap\tBitmap\tJPEG\tJPEG\t%s %s \tComp\tComp\tDecomp\n",
			dotile? "Tile ":"Image", dotile? "Tile ":"Image");
		printf("Format\tOrder\tSubsamp\tQual\tWidth Height\tPerf \tRatio\tPerf\n\n");
	}

	if(decomponly)
	{
		dodecomptest(argv[1]);
		printf("\n");
		goto bailout;
	}
	for(i=maxqual; i>=minqual; i--)
		dotest(srcbuf, w, h, TJ_GRAYSCALE, i, argv[1]);
	printf("\n");
	for(i=maxqual; i>=minqual; i--)
		dotest(srcbuf, w, h, TJ_420, i, argv[1]);
	printf("\n");
	for(i=maxqual; i>=minqual; i--)
		dotest(srcbuf, w, h, TJ_422, i, argv[1]);
	printf("\n");
	for(i=maxqual; i>=minqual; i--)
		dotest(srcbuf, w, h, TJ_444, i, argv[1]);
	printf("\n");

	bailout:
	if(srcbuf) free(srcbuf);
	return retval;
}
Beispiel #20
0
void dodecomptest(char *filename)
{
	FILE *file=NULL;  tjhandle handle=NULL;
	unsigned char **jpegbuf=NULL, *srcbuf=NULL;
	unsigned long *jpegsize=NULL, srcsize, totaljpegsize;
	tjtransform *t=NULL;
	int w=0, h=0, subsamp=-1, _w, _h, _tilew, _tileh,
		_ntilesw, _ntilesh, _subsamp;
	char *temp=NULL, tempstr[80], tempstr2[80];
	int row, col, i, tilew, tileh, ntilesw, ntilesh, retval=0;
	double start, elapsed;
	int ps=tjPixelSize[pf], tile;

	if((file=fopen(filename, "rb"))==NULL)
		_throwunix("opening file");
	if(fseek(file, 0, SEEK_END)<0 || (srcsize=ftell(file))<0)
		_throwunix("determining file size");
	if((srcbuf=(unsigned char *)malloc(srcsize))==NULL)
		_throwunix("allocating memory");
	if(fseek(file, 0, SEEK_SET)<0)
		_throwunix("setting file position");
	if(fread(srcbuf, srcsize, 1, file)<1)
		_throwunix("reading JPEG data");
	fclose(file);  file=NULL;

	temp=strrchr(filename, '.');
	if(temp!=NULL) *temp='\0';

	if((handle=tjInitTransform())==NULL)
		_throwtj("executing tjInitTransform()");
	if(tjDecompressHeader2(handle, srcbuf, srcsize, &w, &h, &subsamp)==-1)
		_throwtj("executing tjDecompressHeader2()");

	if(quiet==1)
	{
		printf("All performance values in Mpixels/sec\n\n");
		printf("Bitmap\tBitmap\tJPEG\t%s %s \tXform\tComp\tDecomp\n",
			dotile? "Tile ":"Image", dotile? "Tile ":"Image");
		printf("Format\tOrder\tSubsamp\tWidth Height\tPerf \tRatio\tPerf\n\n");
	}
	else if(!quiet)
	{
		printf(">>>>>  JPEG %s --> %s (%s)  <<<<<\n", subNameLong[subsamp],
			pixFormatStr[pf], (flags&TJFLAG_BOTTOMUP)? "Bottom-up":"Top-down");
	}

	for(tilew=dotile? 16:w, tileh=dotile? 16:h; ; tilew*=2, tileh*=2)
	{
		if(tilew>w) tilew=w;  if(tileh>h) tileh=h;
		ntilesw=(w+tilew-1)/tilew;  ntilesh=(h+tileh-1)/tileh;

		if((jpegbuf=(unsigned char **)malloc(sizeof(unsigned char *)
			*ntilesw*ntilesh))==NULL)
			_throwunix("allocating JPEG tile array");
		memset(jpegbuf, 0, sizeof(unsigned char *)*ntilesw*ntilesh);
		if((jpegsize=(unsigned long *)malloc(sizeof(unsigned long)
			*ntilesw*ntilesh))==NULL)
			_throwunix("allocating JPEG size array");
		memset(jpegsize, 0, sizeof(unsigned long)*ntilesw*ntilesh);

		if((flags&TJFLAG_NOREALLOC)!=0)
			for(i=0; i<ntilesw*ntilesh; i++)
			{
				if((jpegbuf[i]=(unsigned char *)malloc(tjBufSize(tilew, tileh,
					subsamp)))==NULL)
					_throwunix("allocating JPEG tiles");
			}

		_w=w;  _h=h;  _tilew=tilew;  _tileh=tileh;
		if(!quiet)
		{
			printf("\n%s size: %d x %d", dotile? "Tile":"Image", _tilew,
				_tileh);
			if(sf.num!=1 || sf.denom!=1)
				printf(" --> %d x %d", TJSCALED(_w, sf), TJSCALED(_h, sf));
			printf("\n");
		}
		else if(quiet==1)
		{
			printf("%s\t%s\t%s\t", pixFormatStr[pf],
				(flags&TJFLAG_BOTTOMUP)? "BU":"TD", subNameLong[subsamp]);
			printf("%-4d  %-4d\t", tilew, tileh);
		}

		_subsamp=subsamp;
		if(dotile || xformop!=TJXOP_NONE || xformopt!=0)
		{
			if((t=(tjtransform *)malloc(sizeof(tjtransform)*ntilesw*ntilesh))
				==NULL)
				_throwunix("allocating image transform array");

			if(xformop==TJXOP_TRANSPOSE || xformop==TJXOP_TRANSVERSE
				|| xformop==TJXOP_ROT90 || xformop==TJXOP_ROT270)
			{
				_w=h;  _h=w;  _tilew=tileh;  _tileh=tilew;
			}

			if(xformopt&TJXOPT_GRAY) _subsamp=TJ_GRAYSCALE;
			if(xformop==TJXOP_HFLIP || xformop==TJXOP_ROT180)
				_w=_w-(_w%tjMCUWidth[_subsamp]);
			if(xformop==TJXOP_VFLIP || xformop==TJXOP_ROT180)
				_h=_h-(_h%tjMCUHeight[_subsamp]);
			if(xformop==TJXOP_TRANSVERSE || xformop==TJXOP_ROT90)
				_w=_w-(_w%tjMCUHeight[_subsamp]);
			if(xformop==TJXOP_TRANSVERSE || xformop==TJXOP_ROT270)
				_h=_h-(_h%tjMCUWidth[_subsamp]);
			_ntilesw=(_w+_tilew-1)/_tilew;
			_ntilesh=(_h+_tileh-1)/_tileh;

			for(row=0, tile=0; row<_ntilesh; row++)
			{
				for(col=0; col<_ntilesw; col++, tile++)
				{
					t[tile].r.w=min(_tilew, _w-col*_tilew);
					t[tile].r.h=min(_tileh, _h-row*_tileh);
					t[tile].r.x=col*_tilew;
					t[tile].r.y=row*_tileh;
					t[tile].op=xformop;
					t[tile].options=xformopt|TJXOPT_TRIM;
				}
			}

			start=gettime();
			if(tjTransform(handle, srcbuf, srcsize, _ntilesw*_ntilesh, jpegbuf,
				jpegsize, t, flags)==-1)
				_throwtj("executing tjTransform()");
			elapsed=gettime()-start;

			free(t);  t=NULL;

			for(tile=0, totaljpegsize=0; tile<_ntilesw*_ntilesh; tile++)
				totaljpegsize+=jpegsize[tile];

			if(quiet)
			{
				printf("%s%c%s%c",
					sigfig((double)(w*h)/1000000./elapsed, 4, tempstr, 80),
					quiet==2? '\n':'\t',
					sigfig((double)(w*h*ps)/(double)totaljpegsize, 4, tempstr2, 80),
					quiet==2? '\n':'\t');
			}
			else if(!quiet)
			{
				printf("X--> Frame rate:           %f fps\n", 1.0/elapsed);
				printf("     Output image size:    %lu bytes\n", totaljpegsize);
				printf("     Compression ratio:    %f:1\n",
					(double)(w*h*ps)/(double)totaljpegsize);
				printf("     Source throughput:    %f Megapixels/sec\n",
					(double)(w*h)/1000000./elapsed);
				printf("     Output bit stream:    %f Megabits/sec\n",
					(double)totaljpegsize*8./1000000./elapsed);
			}
		}
		else
		{
			if(quiet==1) printf("N/A\tN/A\t");
			jpegsize[0]=srcsize;
			memcpy(jpegbuf[0], srcbuf, srcsize);
		}

		if(w==tilew) _tilew=_w;
		if(h==tileh) _tileh=_h;
		if(decomptest(NULL, jpegbuf, jpegsize, NULL, _w, _h, _subsamp, 0,
			filename, _tilew, _tileh)==-1)
			goto bailout;

		for(i=0; i<ntilesw*ntilesh; i++)
		{
			free(jpegbuf[i]);  jpegbuf[i]=NULL;
		}
		free(jpegbuf);  jpegbuf=NULL;
		if(jpegsize) {free(jpegsize);  jpegsize=NULL;}

		if(tilew==w && tileh==h) break;
	}

	bailout:
	if(file) {fclose(file);  file=NULL;}
	if(jpegbuf)
	{
		for(i=0; i<ntilesw*ntilesh; i++)
		{
			if(jpegbuf[i]) free(jpegbuf[i]);  jpegbuf[i]=NULL;
		}
		free(jpegbuf);  jpegbuf=NULL;
	}
	if(jpegsize) {free(jpegsize);  jpegsize=NULL;}
	if(srcbuf) {free(srcbuf);  srcbuf=NULL;}
	if(t) {free(t);  t=NULL;}
	if(handle) {tjDestroy(handle);  handle=NULL;}
	return;
}