From: DRC Date: Tue, 22 Feb 2011 06:41:29 +0000 (+0000) Subject: Make the scaling API a bit more friendly X-Git-Tag: 1.1.90~221 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=b28fc5710a510410d2b498255a423dd62b353b3a;p=libjpeg-turbo 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 --- diff --git a/java/TJExample.java b/java/TJExample.java index 6595f63..b4acf1b 100644 --- a/java/TJExample.java +++ b/java/TJExample.java @@ -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(); diff --git a/java/org/libjpegturbo/turbojpeg/TJDecompressor.java b/java/org/libjpegturbo/turbojpeg/TJDecompressor.java index 42b3b82..6408d58 100644 --- a/java/org/libjpegturbo/turbojpeg/TJDecompressor.java +++ b/java/org/libjpegturbo/turbojpeg/TJDecompressor.java @@ -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 { diff --git a/jpegut.c b/jpegut.c index 10b5966..7eb484e 100644 --- a/jpegut.c +++ b/jpegut.c @@ -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.); diff --git a/jpgtest.c b/jpgtest.c index ced97fb..773a32e 100644 --- a/jpgtest.c +++ b/jpgtest.c @@ -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; jGetPrimitiveArrayCritical(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); diff --git a/turbojpeg-mapfile b/turbojpeg-mapfile index 92b3b70..e54d59c 100755 --- a/turbojpeg-mapfile +++ b/turbojpeg-mapfile @@ -7,7 +7,6 @@ tjDecompressHeader; tjDecompressHeader2; tjDecompress; - tjDecompress2; tjDestroy; tjGetErrorStr; local: diff --git a/turbojpeg-mapfile.jni b/turbojpeg-mapfile.jni index cc11fad..5aaa1e0 100755 --- a/turbojpeg-mapfile.jni +++ b/turbojpeg-mapfile.jni @@ -7,7 +7,6 @@ tjDecompressHeader; tjDecompressHeader2; tjDecompress; - tjDecompress2; tjDestroy; tjGetErrorStr; Java_org_libjpegturbo_turbojpeg_TJ_bufSize; diff --git a/turbojpeg.h b/turbojpeg.h index 626fe4f..5524efc 100644 --- a/turbojpeg.h +++ b/turbojpeg.h @@ -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, diff --git a/turbojpegl.c b/turbojpegl.c index 8ba7fcc..93f4b6a 100644 --- a/turbojpegl.c +++ b/turbojpegl.c @@ -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; iinitd) _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(widthwidth || 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; idinfo.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