]> granicus.if.org Git - libjpeg-turbo/commitdiff
Make the scaling API a bit more friendly
authorDRC <dcommander@users.sourceforge.net>
Tue, 22 Feb 2011 06:41:29 +0000 (06:41 +0000)
committerDRC <dcommander@users.sourceforge.net>
Tue, 22 Feb 2011 06:41:29 +0000 (06:41 +0000)
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@422 632fc199-4ca6-4c93-a231-07263d6284db

java/TJExample.java
java/org/libjpegturbo/turbojpeg/TJDecompressor.java
jpegut.c
jpgtest.c
turbojpeg-jni.c
turbojpeg-mapfile
turbojpeg-mapfile.jni
turbojpeg.h
turbojpegl.c

index 6595f63de654a15fdea978f480bc140862e4defa..b4acf1b1cbe00e2b06ea66bd32864f0d9489937a 100644 (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();
index 42b3b82f6e2df35fd3763ad5c23e4a2f3b6a0f3a..6408d588a9f6e1e3a254c0c3e952c34e6be899b0 100644 (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 {
index 10b5966a338aaae294096136f6cc2dee36210357..7eb484ea766d2daa3b1e17fa3aee383d12c46c23 100644 (file)
--- 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.);
index ced97fb28adfe3f4238d5317fdb2ed7dcca81692..773a32e7fc9076b60341455123fe3b03897c49b4 100644 (file)
--- 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; 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)
index 1ab5e28a7193a3d5f4d29e8551e9a4c7244ca3dc..892e51b2a091bb2f3edc4b7208ee65fd0426c52f 100644 (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);
index 92b3b70bd36a5146b393f586c5709fe33ff4485c..e54d59cd3a522fe9e2c715408113115c78af35a5 100755 (executable)
@@ -7,7 +7,6 @@
                tjDecompressHeader;
                tjDecompressHeader2;
                tjDecompress;
-               tjDecompress2;
                tjDestroy;
                tjGetErrorStr;
        local:
index cc11fadf58fe302a526fc02b7b27aab718fb3f75..5aaa1e0cd81a601a1a74ccf054ed8cdfe8a88aa3 100755 (executable)
@@ -7,7 +7,6 @@
                tjDecompressHeader;
                tjDecompressHeader2;
                tjDecompress;
-               tjDecompress2;
                tjDestroy;
                tjGetErrorStr;
                Java_org_libjpegturbo_turbojpeg_TJ_bufSize;
index 626fe4fc3f1cd03971daa525df742bd191daab96..5524efc2152dd3154a262b8a0aa5f91fea5b6bd9 100644 (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,
index 8ba7fccca94a6da95b24f279d18bc89e4629b650..93f4b6a6008e46c6c6aab344c9c2a1f0e73a82ba 100644 (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)