Make the scaling API a bit more friendly

git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@422 632fc199-4ca6-4c93-a231-07263d6284db
This commit is contained in:
DRC
2011-02-22 06:41:29 +00:00
parent 45bd1f2bd4
commit b28fc5710a
9 changed files with 135 additions and 73 deletions

View File

@@ -98,8 +98,8 @@ public class TJExample {
byte [] tmpbuf=new byte[tji.width*tji.height*3];
tjd.decompress(inputbuf, inputsize, tmpbuf, tji.width*3,
3, 1, scalefactor, TJ.BOTTOMUP);
tjd.decompress(inputbuf, inputsize, tmpbuf, tji.width, tji.width*3,
tji.height, 3, TJ.BOTTOMUP);
tjd.close();
TJCompressor tjc=new TJCompressor();

View File

@@ -56,7 +56,7 @@ public class TJDecompressor {
throws Exception;
public native void decompress(byte [] srcbuf, long size, byte [] dstbuf,
int pitch, int pixelsize, int scale_num, int scale_denom, int flags)
int width, int pitch, int height, int pixelsize, int flags)
throws Exception;
static {

View File

@@ -410,7 +410,8 @@ void _gentestbmp(tjhandle hnd, unsigned char *jpegbuf, unsigned long jpegsize,
{
unsigned char *bmpbuf=NULL;
const char *pixformat; int _hdrw=0, _hdrh=0, _hdrsubsamp=-1; double t;
int _w=(w+scalefactor-1)/scalefactor, _h=(h+scalefactor-1)/scalefactor;
int scaledw=(w+scalefactor-1)/scalefactor, scaledh=(h+scalefactor-1)/scalefactor;
int temp1, temp2;
unsigned long size=0;
if(yuv==YUVDECODE) flags|=TJ_YUV;
@@ -444,10 +445,17 @@ void _gentestbmp(tjhandle hnd, unsigned char *jpegbuf, unsigned long jpegsize,
printf("Incorrect JPEG header\n"); bailout();
}
temp1=scaledw; temp2=scaledh;
_catch(tjScaledSize(w, h, &temp1, &temp2));
if(temp1!=scaledw || temp2!=scaledh)
{
printf("Scaled size mismatch\n"); bailout();
}
if(yuv==YUVDECODE)
size=TJBUFSIZEYUV(w, h, subsamp);
else
size=_w*_h*ps;
size=scaledw*scaledh*ps;
if((bmpbuf=(unsigned char *)malloc(size+1))==NULL)
{
printf("ERROR: Could not allocate buffer\n"); bailout();
@@ -455,8 +463,8 @@ void _gentestbmp(tjhandle hnd, unsigned char *jpegbuf, unsigned long jpegsize,
memset(bmpbuf, 0, size+1);
t=rrtime();
_catch(tjDecompress2(hnd, jpegbuf, jpegsize, bmpbuf, 0, ps, 1,
scalefactor, flags));
_catch(tjDecompress(hnd, jpegbuf, jpegsize, bmpbuf, scaledw, 0, scaledh, ps,
flags));
t=rrtime()-t;
if(yuv==YUVDECODE)
@@ -467,12 +475,12 @@ void _gentestbmp(tjhandle hnd, unsigned char *jpegbuf, unsigned long jpegsize,
}
else
{
if(checkbuf(bmpbuf, _w, _h, ps, subsamp, scalefactor, flags))
if(checkbuf(bmpbuf, scaledw, scaledh, ps, subsamp, scalefactor, flags))
printf("Passed.");
else
{
printf("FAILED!"); exitstatus=-1;
dumpbuf(bmpbuf, _w, _h, ps, scalefactor, flags);
dumpbuf(bmpbuf, scaledw, scaledh, ps, scalefactor, flags);
}
}
printf(" %f ms\n", t*1000.);

View File

@@ -83,8 +83,9 @@ int decomptest(unsigned char *srcbuf, unsigned char **jpegbuf,
int cw=pw/hsf, ch=ph/vsf;
int ypitch=PAD(pw, 4), uvpitch=PAD(cw, 4);
int yuvsize=ypitch*ph + (jpegsub==TJ_GRAYSCALE? 0:uvpitch*ch*2);
int _w=(w+scalefactor-1)/scalefactor, _h=(h+scalefactor-1)/scalefactor;
int pitch=_w*ps;
int scaledw=(flags&TJ_YUV)? w : (w+scalefactor-1)/scalefactor;
int scaledh=(flags&TJ_YUV)? h : (h+scalefactor-1)/scalefactor;
int pitch=scaledw*ps;
if(qual>0)
{
@@ -100,14 +101,15 @@ int decomptest(unsigned char *srcbuf, unsigned char **jpegbuf,
if(rgbbuf==NULL)
{
if((rgbbuf=(unsigned char *)malloc(max(yuvsize, pitch*_h))) == NULL)
if((rgbbuf=(unsigned char *)malloc(max(yuvsize, pitch*scaledh))) == NULL)
_throwunix("allocating image buffer");
rgbbufalloc=1;
}
memset(rgbbuf, 127, max(yuvsize, pitch*_h)); // Grey image means decompressor did nothing
// Grey image means decompressor did nothing
memset(rgbbuf, 127, max(yuvsize, pitch*scaledh));
if(tjDecompress2(hnd, jpegbuf[0], comptilesize[0], rgbbuf, pitch, ps, 1,
(flags&TJ_YUV)? 1:scalefactor, flags)==-1)
if(tjDecompress(hnd, jpegbuf[0], comptilesize[0], rgbbuf, scaledw, pitch,
scaledh, ps, flags)==-1)
_throwtj("executing tjDecompress()");
ITER=0;
start=rrtime();
@@ -119,10 +121,9 @@ int decomptest(unsigned char *srcbuf, unsigned char **jpegbuf,
for(j=0; j<w; j+=tilesizex)
{
int tempw=min(tilesizex, w-j), temph=min(tilesizey, h-i);
if(tjDecompress2(hnd, jpegbuf[tilen], comptilesize[tilen],
&rgbbuf[pitch*i+ps*j], pitch, ps, 1, (flags&TJ_YUV)? 1:scalefactor,
flags)==-1)
_throwtj("executing tjDecompress2()");
if(tjDecompress(hnd, jpegbuf[tilen], comptilesize[tilen],
&rgbbuf[pitch*i+ps*j], scaledw, pitch, scaledh, ps, flags)==-1)
_throwtj("executing tjDecompress()");
tilen++;
}
}
@@ -162,7 +163,7 @@ int decomptest(unsigned char *srcbuf, unsigned char **jpegbuf,
}
else sprintf(tempstr, "%s_%s%s_%dx%d.%s", filename, _subnames[jpegsub],
qualstr, tilesizex, tilesizey, useppm?"ppm":"bmp");
if(savebmp(tempstr, rgbbuf, _w, _h, pf, pitch, bu)==-1)
if(savebmp(tempstr, rgbbuf, scaledw, scaledh, pf, pitch, bu)==-1)
_throwbmp("saving bitmap");
sprintf(strrchr(tempstr, '.'), "-err.%s", useppm?"ppm":"bmp");
if(srcbuf && scalefactor==1)

View File

@@ -169,7 +169,7 @@ JNIEXPORT jobject JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompr
JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompress
(JNIEnv *env, jobject obj, jbyteArray src, jlong size, jbyteArray dst,
jint pitch, jint pixelsize, jint scale_num, jint scale_denom, jint flags)
jint width, jint pitch, jint height, jint pixelsize, jint flags)
{
tjhandle handle=0;
unsigned char *srcbuf=NULL, *dstbuf=NULL;
@@ -179,8 +179,8 @@ JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompress
bailif0(srcbuf=(*env)->GetPrimitiveArrayCritical(env, src, 0));
bailif0(dstbuf=(*env)->GetPrimitiveArrayCritical(env, dst, 0));
if(tjDecompress2(handle, srcbuf, (unsigned long)size, dstbuf, pitch,
pixelsize, scale_num, scale_denom, flags)==-1)
if(tjDecompress(handle, srcbuf, (unsigned long)size, dstbuf, width, pitch,
height, pixelsize, flags)==-1)
{
(*env)->ReleasePrimitiveArrayCritical(env, dst, dstbuf, 0);
(*env)->ReleasePrimitiveArrayCritical(env, src, srcbuf, 0);

View File

@@ -7,7 +7,6 @@
tjDecompressHeader;
tjDecompressHeader2;
tjDecompress;
tjDecompress2;
tjDestroy;
tjGetErrorStr;
local:

View File

@@ -7,7 +7,6 @@
tjDecompressHeader;
tjDecompressHeader2;
tjDecompress;
tjDecompress2;
tjDestroy;
tjGetErrorStr;
Java_org_libjpegturbo_turbojpeg_TJ_bufSize;

View File

@@ -153,6 +153,7 @@ DLLEXPORT int DLLCALL tjCompress(tjhandle j,
unsigned char *dstbuf, unsigned long *size,
int jpegsubsamp, int jpegqual, int flags);
/*
unsigned long TJBUFSIZE(int width, int height)
@@ -163,6 +164,7 @@ DLLEXPORT int DLLCALL tjCompress(tjhandle j,
*/
DLLEXPORT unsigned long DLLCALL TJBUFSIZE(int width, int height);
/*
unsigned long TJBUFSIZEYUV(int width, int height, int subsamp)
@@ -175,6 +177,7 @@ DLLEXPORT unsigned long DLLCALL TJBUFSIZE(int width, int height);
DLLEXPORT unsigned long DLLCALL TJBUFSIZEYUV(int width, int height,
int subsamp);
/*
tjhandle tjInitDecompress(void)
@@ -196,8 +199,7 @@ DLLEXPORT tjhandle DLLCALL tjInitDecompress(void);
[INPUT] j = instance handle previously returned from a call to
tjInitDecompress()
[INPUT] srcbuf = pointer to a user-allocated buffer containing the JPEG image
to decompress
[INPUT] srcbuf = pointer to a user-allocated buffer containing a JPEG image
[INPUT] size = size of the JPEG image buffer (in bytes)
[OUTPUT] width = width (in pixels) of the JPEG image
[OUTPUT] height = height (in pixels) of the JPEG image
@@ -219,10 +221,30 @@ DLLEXPORT int DLLCALL tjDecompressHeader(tjhandle j,
/*
int tjDecompress2(tjhandle j,
int tjScaledSize(int input_width, int input_height,
int *output_width, int *output_height)
[INPUT] input_width = width (in pixels) of the JPEG image
[INPUT] input_height = height (in pixels) of the JPEG image
[INPUT/OUTPUT] output_width, output_height = Before calling this function,
*output_width and *output_height should be set to the desired dimensions
of the output image. Upon returning from this function, they will be set
to the dimensions of the largest scaled down image that TurboJPEG can
produce without exceeding the desired dimensions. If either *output_width
or *output_height is set to 0, then the corresponding dimension will not
be considered when determining the scaled image size.
RETURNS: 0 on success, -1 if arguments are out of bounds
*/
DLLEXPORT int DLLCALL tjScaledSize(int input_width, int input_height,
int *output_width, int *output_height);
/*
int tjDecompress(tjhandle j,
unsigned char *srcbuf, unsigned long size,
unsigned char *dstbuf, int pitch, int pixelsize,
int scale_num, int scale_denom, int flags)
unsigned char *dstbuf, int width, int pitch, int height, int pixelsize,
int flags)
[INPUT] j = instance handle previously returned from a call to
tjInitDecompress()
@@ -231,33 +253,36 @@ DLLEXPORT int DLLCALL tjDecompressHeader(tjhandle j,
[INPUT] size = size of the JPEG image buffer (in bytes)
[INPUT] dstbuf = pointer to user-allocated image buffer which will receive
the bitmap image. This buffer should normally be pitch*scaled_height
bytes in size, where scaled_height=ceil(JPEG image height/scale_denom).
However, this pointer may also be used to decompress into a specific
region of a larger buffer.
bytes in size, where scaled_height is determined by calling
tjScaledSize() with the height of the desired output image. This pointer
may also be used to decompress into a specific region of a
larger buffer.
[INPUT] width = desired width (in pixels) of the destination image. If this
is smaller than the width of the JPEG image being decompressed, then
TurboJPEG will use scaling in the JPEG decompressor to generate the
largest possible image that will fit within the desired width. If width
is set to 0, then only the height will be considered when determining the
scaled image size.
[INPUT] pitch = bytes per line of the destination image. Normally, this is
scaled_width*pixelsize if the bitmap is unpadded, else
scaled_width*pixelsize if the bitmap image is unpadded, else
TJPAD(scaled_width*pixelsize) if each line of the bitmap is padded to the
nearest 32-bit boundary, such as is the case for Windows bitmaps.
NOTE: scaled_width=ceil(JPEG image width/scale_denom). You can also be
clever and use this parameter to skip lines, etc. Setting this parameter
to 0 is the equivalent of setting it to scaled_width*pixelsize.
(NOTE: scaled_width can be determined by calling tjScaledSize().) You can
also be clever and use this parameter to skip lines, etc. Setting this
parameter to 0 is the equivalent of setting it to scaled_width*pixelsize.
[INPUT] height = desired height (in pixels) of the destination image. If
this is smaller than the height of the JPEG image being decompressed, then
TurboJPEG will use scaling in the JPEG decompressor to generate the
largest possible image that will fit within the desired height. If
height is set to 0, then only the width will be considered when
determining the scaled image size.
[INPUT] pixelsize = size (in bytes) of each pixel in the destination image
RGBX/BGRX/XRGB/XBGR: 4, RGB/BGR: 3, Grayscale: 1
[INPUT] scale_num = numerator of scaling factor (currently must be 1)
[INPUT] scale_denom = denominator of scaling factor (1, 2, 4, or 8)
[INPUT] flags = the bitwise OR of one or more of the flags described in the
"Flags" section above.
RETURNS: 0 on success, -1 on error
*/
DLLEXPORT int DLLCALL tjDecompress2(tjhandle j,
unsigned char *srcbuf, unsigned long size,
unsigned char *dstbuf, int pitch, int pixelsize,
int scale_num, int scale_denom, int flags);
/*
Legacy version of the above function
*/
DLLEXPORT int DLLCALL tjDecompress(tjhandle j,
unsigned char *srcbuf, unsigned long size,
unsigned char *dstbuf, int width, int pitch, int height, int pixelsize,

View File

@@ -120,7 +120,7 @@ DLLEXPORT unsigned long DLLCALL TJBUFSIZE(int width, int height)
// This allows for rare corner cases in which a JPEG image can actually be
// larger than the uncompressed input (we wouldn't mention it if it hadn't
// happened.)
// happened before.)
retval=((width+15)&(~15)) * ((height+15)&(~15)) * 6 + 2048;
bailout:
@@ -319,6 +319,7 @@ DLLEXPORT int DLLCALL tjCompress(tjhandle h,
-(unsigned long)(j->jdms.free_in_buffer);
bailout:
if(j->cinfo.global_state>CSTATE_START) jpeg_abort_compress(&j->cinfo);
if(row_pointer) free(row_pointer);
for(i=0; i<MAX_COMPONENTS; i++)
{
@@ -443,15 +444,44 @@ DLLEXPORT int DLLCALL tjDecompressHeader(tjhandle h,
}
DLLEXPORT int DLLCALL tjDecompress2(tjhandle h,
DLLEXPORT int DLLCALL tjScaledSize(int input_width, int input_height,
int *output_width, int *output_height)
{
int i, retval=0, scaledw=0, scaledh=0;
if(input_width<1 || input_height<1 || output_width==NULL
|| output_height==NULL || *output_width<0 || *output_height<0)
_throw("Invalid argument in tjScaledSize()");
if(*output_width==0) *output_width=input_width;
if(*output_height==0) *output_height=input_height;
if(*output_width<input_width || *output_height<input_height)
{
for(i=1; i<=8; i*=2)
{
scaledw=(input_width+i-1)/i;
scaledh=(input_height+i-1)/i;
if(scaledw<=*output_width && scaledh<=*output_height)
break;
}
*output_width=scaledw; *output_height=scaledh;
}
bailout:
return retval;
}
DLLEXPORT int DLLCALL tjDecompress(tjhandle h,
unsigned char *srcbuf, unsigned long size,
unsigned char *dstbuf, int pitch, int ps,
int scale_num, int scale_denom, int flags)
unsigned char *dstbuf, int width, int pitch, int height, int ps,
int flags)
{
int i, row, retval=0; JSAMPROW *row_pointer=NULL, *outbuf[MAX_COMPONENTS];
int cw[MAX_COMPONENTS], ch[MAX_COMPONENTS], iw[MAX_COMPONENTS],
tmpbufsize=0, usetmpbuf=0, th[MAX_COMPONENTS];
JSAMPLE *_tmpbuf=NULL; JSAMPROW *tmpbuf[MAX_COMPONENTS];
int scale_num=1, scale_denom=1, jpegwidth, jpegheight, scaledw, scaledh;
checkhandle(h);
@@ -460,16 +490,13 @@ DLLEXPORT int DLLCALL tjDecompress2(tjhandle h,
tmpbuf[i]=NULL; outbuf[i]=NULL;
}
if(srcbuf==NULL || size<=0 || dstbuf==NULL || pitch<0)
_throw("Invalid argument in tjDecompress2()");
if(srcbuf==NULL || size<=0
|| dstbuf==NULL || width<0 || pitch<0 || height<0)
_throw("Invalid argument in tjDecompress()");
if(ps!=3 && ps!=4 && ps!=1)
_throw("This decompressor can only handle 24-bit and 32-bit RGB or 8-bit grayscale output");
if(!j->initd) _throw("Instance has not been initialized for decompression");
if(scale_num!=1 || scale_denom<1 || scale_denom>8
|| (scale_denom&(scale_denom-1))!=0)
_throw("Unsupported scaling factor");
if(flags&TJ_FORCEMMX) putenv("JSIMD_FORCEMMX=1");
else if(flags&TJ_FORCESSE) putenv("JSIMD_FORCESSE=1");
else if(flags&TJ_FORCESSE2) putenv("JSIMD_FORCESSE2=1");
@@ -485,6 +512,24 @@ DLLEXPORT int DLLCALL tjDecompress2(tjhandle h,
jpeg_read_header(&j->dinfo, TRUE);
jpegwidth=j->dinfo.image_width; jpegheight=j->dinfo.image_height;
if(width==0) width=jpegwidth;
if(height==0) height=jpegheight;
if(width<jpegwidth || height<jpegheight)
{
for(i=1; i<=8; i*=2)
{
scaledw=(jpegwidth+i-1)/i;
scaledh=(jpegheight+i-1)/i;
if(scaledw<=width && scaledh<=height)
break;
}
if(scaledw>width || scaledh>height)
_throw("Could not scale down to desired image dimensions");
width=scaledw; height=scaledh;
scale_denom=i;
}
if(flags&TJ_YUV)
{
j_decompress_ptr dinfo=&j->dinfo;
@@ -591,10 +636,7 @@ DLLEXPORT int DLLCALL tjDecompress2(tjhandle h,
if(pitch==0) pitch=j->dinfo.output_width*ps;
if((row_pointer=(JSAMPROW *)malloc(sizeof(JSAMPROW)
*j->dinfo.output_height))==NULL)
{
jpeg_finish_decompress(&j->dinfo);
_throw("Memory allocation failed in tjInitDecompress()");
}
for(i=0; i<j->dinfo.output_height; i++)
{
if(flags&TJ_BOTTOMUP)
@@ -610,6 +652,7 @@ DLLEXPORT int DLLCALL tjDecompress2(tjhandle h,
jpeg_finish_decompress(&j->dinfo);
bailout:
if(j->dinfo.global_state>DSTATE_START) jpeg_abort_decompress(&j->dinfo);
for(i=0; i<MAX_COMPONENTS; i++)
{
if(tmpbuf[i]) free(tmpbuf[i]);
@@ -621,19 +664,6 @@ DLLEXPORT int DLLCALL tjDecompress2(tjhandle h,
}
DLLEXPORT int DLLCALL tjDecompress(tjhandle h,
unsigned char *srcbuf, unsigned long size,
unsigned char *dstbuf, int width, int pitch, int height, int ps,
int flags)
{
if(width<=0 || height<=0)
{
sprintf(lasterror, "Invalid argument in tjDecompress()");
return -1;
}
return tjDecompress2(h, srcbuf, size, dstbuf, pitch, ps, 1, 1, flags);
}
// General
DLLEXPORT char* DLLCALL tjGetErrorStr(void)