]> granicus.if.org Git - libjpeg-turbo/commitdiff
tjGetScaledSize() would never be able to accommodate scaling factors > 1, so replace...
authorDRC <dcommander@users.sourceforge.net>
Tue, 1 Mar 2011 09:53:07 +0000 (09:53 +0000)
committerDRC <dcommander@users.sourceforge.net>
Tue, 1 Mar 2011 09:53:07 +0000 (09:53 +0000)
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@477 632fc199-4ca6-4c93-a231-07263d6284db

12 files changed:
java/TJUnitTest.java
java/org/libjpegturbo/turbojpeg/TJ.java
java/org/libjpegturbo/turbojpeg/TJDecompressor.java
java/org_libjpegturbo_turbojpeg_TJ.h
java/org_libjpegturbo_turbojpeg_TJDecompressor.h
jpegut.c
jpgtest.c
turbojpeg-jni.c
turbojpeg-mapfile
turbojpeg-mapfile.jni
turbojpeg.h
turbojpegl.c

index 8bd07d1cfdc1e66c3015afb7647967915371cdf6..bdfecfc5c8f06aec4f7b2a371a6e5c8897dfbd27 100644 (file)
@@ -253,14 +253,14 @@ public class TJUnitTest {
        }
 
        private static int checkbuf(byte [] buf, int w, int pitch, int h, int pf,
-               int subsamp, int scalefactor, int flags) throws Exception
+               int subsamp, int scale_num, int scale_denom, int flags) throws Exception
        {
                int roffset=TJ.getRedShift(pf)/8;
                int goffset=TJ.getGreenShift(pf)/8;
                int boffset=TJ.getBlueShift(pf)/8;
                int ps=TJ.getPixelSize(pf);
                int i, _i, j, retval=1;
-               int halfway=16/scalefactor, blocksize=8/scalefactor;
+               int halfway=16*scale_num/scale_denom, blocksize=8*scale_num/scale_denom;
 
                try
                {
@@ -350,13 +350,13 @@ public class TJUnitTest {
        }
 
        private static int checkintbuf(int [] buf, int w, int pitch, int h, int pf,
-               int subsamp, int scalefactor, int flags) throws Exception
+               int subsamp, int scale_num, int scale_denom, int flags) throws Exception
        {
                int rshift=TJ.getRedShift(pf);
                int gshift=TJ.getGreenShift(pf);
                int bshift=TJ.getBlueShift(pf);
                int i, _i, j, retval=1;
-               int halfway=16/scalefactor, blocksize=8/scalefactor;
+               int halfway=16*scale_num/scale_denom, blocksize=8*scale_num/scale_denom;
 
                try
                {
@@ -448,7 +448,7 @@ public class TJUnitTest {
        }
 
        private static int checkimg(BufferedImage img, int pf,
-               int subsamp, int scalefactor, int flags) throws Exception
+               int subsamp, int scale_num, int scale_denom, int flags) throws Exception
        {
                WritableRaster wr=img.getRaster();
                int imgtype=img.getType();
@@ -461,7 +461,7 @@ public class TJUnitTest {
                        DataBufferInt db=(DataBufferInt)wr.getDataBuffer();
                        int [] buf = db.getData();
                        return checkintbuf(buf, img.getWidth(), pitch, img.getHeight(), pf,
-                               subsamp, scalefactor, flags);
+                               subsamp, scale_num, scale_denom, flags);
                }
                else
                {
@@ -471,7 +471,7 @@ public class TJUnitTest {
                        DataBufferByte db=(DataBufferByte)wr.getDataBuffer();
                        byte [] buf = db.getData();
                        return checkbuf(buf, img.getWidth(), pitch, img.getHeight(), pf, subsamp,
-                               scalefactor, flags);
+                               scale_num, scale_denom, flags);
                }
        }
 
@@ -681,12 +681,12 @@ public class TJUnitTest {
 
        private static void _gentestbmp(TJDecompressor tjd, byte [] jpegbuf,
                int jpegsize, int w, int h, int pf, String basefilename, int subsamp,
-               int flags, int scalefactor) throws Exception
+               int flags, int scale_num, int scale_denom) throws Exception
        {
                String pixformat, tempstr;  int _hdrw=0, _hdrh=0, _hdrsubsamp=-1;
                double t;
-               int scaledw=(w+scalefactor-1)/scalefactor;
-               int scaledh=(h+scalefactor-1)/scalefactor;
+               int scaledw=(w*scale_num+scale_denom-1)/scale_denom;
+               int scaledh=(h*scale_num+scale_denom-1)/scale_denom;
                int temp1, temp2;
                BufferedImage img=null;  byte [] bmpbuf=null;
 
@@ -701,7 +701,8 @@ public class TJUnitTest {
                        System.out.print(pixformat+" ");
                        if((flags&TJ.BOTTOMUP)!=0) System.out.print("Bottom-Up ");
                        else System.out.print("Top-Down  ");
-                       if(scalefactor!=1) System.out.print("1/"+scalefactor+" ... ");
+                       if(scale_num!=1 || scale_denom!=1)
+                               System.out.print(scale_num+"/"+scale_denom+" ... ");
                        else System.out.print("... ");
                }
 
@@ -728,7 +729,7 @@ public class TJUnitTest {
                {
                        tempstr=basefilename+"_dec_"+pixformat+"_"
                                +(((flags&TJ.BOTTOMUP)!=0)? "BU":"TD")+"_"+_subnames[subsamp]
-                               +"_"+scalefactor+"x"+".png";
+                               +"_"+(double)scale_num/(double)scale_denom+"x"+".png";
                        File file=new File(tempstr);
                        ImageIO.write(img, "png", file);
                }
@@ -741,9 +742,9 @@ public class TJUnitTest {
                }
                else
                {
-                       if((bi && checkimg(img, pf, subsamp, scalefactor, flags)==1)
+                       if((bi && checkimg(img, pf, subsamp, scale_num, scale_denom, flags)==1)
                                || (!bi && checkbuf(bmpbuf, scaledw, scaledw*TJ.getPixelSize(pf),
-                                       scaledh, pf, subsamp, scalefactor, flags)==1))
+                                       scaledh, pf, subsamp, scale_num, scale_denom, flags)==1))
                                System.out.print("Passed.");
                        else
                        {
@@ -760,13 +761,14 @@ public class TJUnitTest {
                int i;
                if((subsamp==TJ.SAMP_444 || subsamp==TJ.SAMP_GRAY) && yuv==0)
                {
-                       for(i=1; i<=8; i*=2)
+                       TJ.ScalingFactor sf []=TJ.getScalingFactors();
+                       for(i=0; i<sf.length; i++)
                                _gentestbmp(tjd, jpegbuf, jpegsize, w, h, pf, basefilename, subsamp,
-                                       flags, i);
+                                       flags, sf[i].num, sf[i].denom);
                }
                else
                        _gentestbmp(tjd, jpegbuf, jpegsize, w, h, pf, basefilename, subsamp,
-                               flags, 1);
+                               flags, 1, 1);
                System.out.print("\n");
        }
 
index 332426a919f71dde8720514fda4dea06988cd33d..9cc0b8b64be8cf5fa86caf85d7640575bd907d05 100644 (file)
@@ -30,6 +30,11 @@ package org.libjpegturbo.turbojpeg;
 
 final public class TJ {
 
+  final public class ScalingFactor {
+    public int num = 1;
+    public int denom = 1;
+  };
+
   // Chrominance subsampling options
   final public static int
     NUMSAMPOPT = 4,
@@ -105,6 +110,9 @@ final public class TJ {
     int subsamp)
     throws Exception;
 
+  public native final static ScalingFactor [] getScalingFactors()
+    throws Exception;
+
   static {
     System.loadLibrary("turbojpeg");
   }
index fdc1e4eb93ae458667627af665f63244d57b4c14..8f3d634d3b63c0a7ef199906b0fd60deb23381ef 100644 (file)
@@ -76,8 +76,19 @@ public class TJDecompressor {
       throw new Exception("JPEG buffer not initialized");
     if(desiredWidth < 0 || desiredHeight < 0)
       throw new Exception("Invalid argument in getScaledWidth()");
-    return getScaledWidth(jpegWidth, jpegHeight, desiredWidth,
-      desiredHeight);
+    TJ.ScalingFactor sf [] = TJ.getScalingFactors();
+    if(desiredWidth == 0) desiredWidth = jpegWidth;
+    if(desiredHeight == 0) desiredHeight = jpegHeight;
+    int scaledWidth = jpegWidth, scaledHeight = jpegHeight;
+    for(int i=0; i<sf.length; i++) {
+      scaledWidth = (jpegWidth * sf[i].num + sf[i].denom - 1) / sf[i].denom;
+      scaledHeight = (jpegHeight * sf[i].num + sf[i].denom - 1) / sf[i].denom;
+      if(scaledWidth <= desiredWidth && scaledHeight <= desiredHeight)
+        break;
+    }
+    if(scaledWidth > desiredWidth || scaledHeight > desiredHeight)
+      throw new Exception("Could not scale down to desired image dimensions");
+    return scaledWidth;
   }
 
   public int getScaledHeight(int desiredWidth, int desiredHeight)
@@ -86,8 +97,19 @@ public class TJDecompressor {
       throw new Exception("JPEG buffer not initialized");
     if(desiredWidth < 0 || desiredHeight < 0)
       throw new Exception("Invalid argument in getScaledHeight()");
-    return getScaledHeight(jpegWidth, jpegHeight, desiredWidth,
-      desiredHeight);
+    TJ.ScalingFactor sf [] = TJ.getScalingFactors();
+    if(desiredWidth == 0) desiredWidth = jpegWidth;
+    if(desiredHeight == 0) desiredHeight = jpegHeight;
+    int scaledWidth = jpegWidth, scaledHeight = jpegHeight;
+    for(int i=0; i<sf.length; i++) {
+      scaledWidth = (jpegWidth * sf[i].num + sf[i].denom - 1) / sf[i].denom;
+      scaledHeight = (jpegHeight * sf[i].num + sf[i].denom - 1) / sf[i].denom;
+      if(scaledWidth <= desiredWidth && scaledHeight <= desiredHeight)
+        break;
+    }
+    if(scaledWidth > desiredWidth || scaledHeight > desiredHeight)
+      throw new Exception("Could not scale down to desired image dimensions");
+    return scaledHeight;
   }
 
   public void decompress(byte [] dstBuf, int desiredWidth, int pitch,
@@ -224,12 +246,6 @@ public class TJDecompressor {
     int flags)
     throws Exception;
 
-  private native int getScaledWidth(int jpegWidth, int jpegHeight,
-    int desiredWidth, int desiredHeight) throws Exception;
-
-  private native int getScaledHeight(int jpegWidth, int jpegHeight,
-    int desiredWidth, int desiredHeight) throws Exception;
-
   static {
     System.loadLibrary("turbojpeg");
   }
index b2be5d83d914277464452ccce26c6fd71c2b5a02..7efaf4964e0bbf614a037cda9b0867542025ef70 100644 (file)
@@ -61,6 +61,14 @@ JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJ_bufSize
 JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJ_bufSizeYUV
   (JNIEnv *, jclass, jint, jint, jint);
 
+/*
+ * Class:     org_libjpegturbo_turbojpeg_TJ
+ * Method:    getScalingFactors
+ * Signature: ()[Lorg/libjpegturbo/turbojpeg/TJ/ScalingFactor;
+ */
+JNIEXPORT jobjectArray JNICALL Java_org_libjpegturbo_turbojpeg_TJ_getScalingFactors
+  (JNIEnv *, jclass);
+
 #ifdef __cplusplus
 }
 #endif
index 695190645a80a51971bc5e0dea8109376ff60f26..6b67296ba6aeb7e19151343e5c1b895201790485 100644 (file)
@@ -55,22 +55,6 @@ JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompress
 JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompressToYUV
   (JNIEnv *, jobject, jbyteArray, jint, jbyteArray, jint);
 
-/*
- * Class:     org_libjpegturbo_turbojpeg_TJDecompressor
- * Method:    getScaledWidth
- * Signature: (IIII)I
- */
-JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_getScaledWidth
-  (JNIEnv *, jobject, jint, jint, jint, jint);
-
-/*
- * Class:     org_libjpegturbo_turbojpeg_TJDecompressor
- * Method:    getScaledHeight
- * Signature: (IIII)I
- */
-JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_getScaledHeight
-  (JNIEnv *, jobject, jint, jint, jint, jint);
-
 #ifdef __cplusplus
 }
 #endif
index 0cf45339cce25d9cb12373ad26e55f9eec9d739e..6393cf69cfd8c438526f7c717727cb8e40ec41d4 100644 (file)
--- a/jpegut.c
+++ b/jpegut.c
@@ -103,130 +103,101 @@ void initbuf(unsigned char *buf, int w, int h, int ps, int flags)
        }
 }
 
-void dumpbuf(unsigned char *buf, int w, int h, int ps, int scalefactor,
-       int flags)
-{
-       int roffset=(flags&TJ_BGR)?2:0, goffset=1, boffset=(flags&TJ_BGR)?0:2, i,
-               j;
-       printf("\n");
-       for(i=0; i<h; i++)
-       {
-               for(j=0; j<w; j++)
-               {
-                       printf("%.3d/%.3d/%.3d ", buf[(w*i+j)*ps+roffset],
-                               buf[(w*i+j)*ps+goffset], buf[(w*i+j)*ps+boffset]);
-               }
-               printf("\n");
-       }
-}
+#define checkval(v, cv) { \
+       if(v<cv-1 || v>cv+1) { \
+               printf("\nComp. %s at %d,%d should be %d, not %d\n", #v, i, j, cv, v); \
+               retval=0;  goto bailout; \
+       }}
+
+#define checkval0(v) { \
+       if(v>1) { \
+               printf("\nComp. %s at %d,%d should be 0, not %d\n", #v, i, j, v); \
+               retval=0;  goto bailout; \
+       }}
+
+#define checkval255(v) { \
+       if(v<254) { \
+               printf("\nComp. %s at %d,%d should be 255, not %d\n", #v, i, j, v); \
+               retval=0;  goto bailout; \
+       }}
 
 int checkbuf(unsigned char *buf, int w, int h, int ps, int subsamp,
-       int scalefactor, int flags)
+       int scale_num, int scale_denom, int flags)
 {
        int roffset=(flags&TJ_BGR)?2:0, goffset=1, boffset=(flags&TJ_BGR)?0:2, i,
-               _i, j;
+               _i, j, retval=1;
        if(flags&TJ_ALPHAFIRST) {roffset++;  goffset++;  boffset++;}
        if(ps==1) roffset=goffset=boffset=0;
-       int halfway=16/scalefactor, blocksize=8/scalefactor;
-       if(subsamp==TJ_GRAYSCALE)
+       int halfway=16*scale_num/scale_denom, blocksize=8*scale_num/scale_denom;
+
+       for(_i=0; _i<halfway; _i++)
        {
-               for(_i=0; _i<halfway; _i++)
+               if(flags&TJ_BOTTOMUP) i=h-_i-1;  else i=_i;
+               for(j=0; j<w; j++)
                {
-                       if(flags&TJ_BOTTOMUP) i=h-_i-1;  else i=_i;
-                       for(j=0; j<w; j++)
+                       unsigned char r=buf[(w*i+j)*ps+roffset],
+                               g=buf[(w*i+j)*ps+goffset],
+                               b=buf[(w*i+j)*ps+boffset];
+                       if(((_i/blocksize)+(j/blocksize))%2==0)
                        {
-                               unsigned char r=buf[(w*i+j)*ps+roffset],
-                                       g=buf[(w*i+j)*ps+goffset],
-                                       b=buf[(w*i+j)*ps+boffset];
-                               if(((_i/blocksize)+(j/blocksize))%2==0)
-                               {
-                                       if(r<253 || g<253 || b<253) return 0;
-                               }
-                               else
-                               {
-                                       if(r<74 || r>78 || g<74 || g>78 || b<74 || b>78) return 0;
-                               }
+                               checkval255(r);  checkval255(g);  checkval255(b);
                        }
-               }
-               for(_i=halfway; _i<h; _i++)
-               {
-                       if(flags&TJ_BOTTOMUP) i=h-_i-1;  else i=_i;
-                       for(j=0; j<w; j++)
+                       else
                        {
-                               unsigned char r=buf[(w*i+j)*ps+roffset],
-                                       g=buf[(w*i+j)*ps+goffset],
-                                       b=buf[(w*i+j)*ps+boffset];
-                               if(((_i/blocksize)+(j/blocksize))%2==0)
+                               if(subsamp==TJ_GRAYSCALE)
                                {
-                                       if(r>2 || g>2 || b>2) return 0;
+                                       checkval(r, 76);  checkval(g, 76);  checkval(b, 76);
                                }
                                else
                                {
-                                       if(r<224 || r>228 || g<224 || g>228 || b<224 || b>228) return 0;
+                                       checkval255(r);  checkval0(g);  checkval0(b);
                                }
                        }
                }
        }
-       else
+       for(_i=halfway; _i<h; _i++)
        {
-               for(_i=0; _i<halfway; _i++)
+               if(flags&TJ_BOTTOMUP) i=h-_i-1;  else i=_i;
+               for(j=0; j<w; j++)
                {
-                       if(flags&TJ_BOTTOMUP) i=h-_i-1;  else i=_i;
-                       for(j=0; j<w; j++)
+                       unsigned char r=buf[(w*i+j)*ps+roffset],
+                               g=buf[(w*i+j)*ps+goffset],
+                               b=buf[(w*i+j)*ps+boffset];
+                       if(((_i/blocksize)+(j/blocksize))%2==0)
                        {
-                               if(buf[(w*i+j)*ps+roffset]<253) return 0;
-                               if(((_i/blocksize)+(j/blocksize))%2==0)
+                               checkval0(r);  checkval0(g);  checkval0(b);
+                       }
+                       else
+                       {
+                               if(subsamp==TJ_GRAYSCALE)
                                {
-                                       if(buf[(w*i+j)*ps+goffset]<253) return 0;
-                                       if(buf[(w*i+j)*ps+boffset]<253) return 0;
+                                       checkval(r, 226);  checkval(g, 226);  checkval(b, 226);
                                }
                                else
                                {
-                                       if(buf[(w*i+j)*ps+goffset]>2) return 0;
-                                       if(buf[(w*i+j)*ps+boffset]>2) return 0;
+                                       checkval255(r);  checkval255(g);  checkval0(b);
                                }
                        }
                }
-               for(_i=halfway; _i<h; _i++)
+       }
+
+       bailout:
+       if(retval==0)
+       {
+               printf("\n");
+               for(i=0; i<h; i++)
                {
-                       if(flags&TJ_BOTTOMUP) i=h-_i-1;  else i=_i;
                        for(j=0; j<w; j++)
                        {
-                               if(buf[(w*i+j)*ps+boffset]>2) return 0;
-                               if(((_i/blocksize)+(j/blocksize))%2==0)
-                               {
-                                       if(buf[(w*i+j)*ps+roffset]>2) return 0;
-                                       if(buf[(w*i+j)*ps+goffset]>2) return 0;
-                               }
-                               else
-                               {
-                                       if(buf[(w*i+j)*ps+roffset]<253) return 0;
-                                       if(buf[(w*i+j)*ps+goffset]<253) return 0;
-                               }
+                               printf("%.3d/%.3d/%.3d ", buf[(w*i+j)*ps+roffset],
+                                       buf[(w*i+j)*ps+goffset], buf[(w*i+j)*ps+boffset]);
                        }
+                       printf("\n");
                }
        }
-       return 1;
+       return retval;
 }
 
-#define checkval(v, cv) { \
-       if(v<cv-1 || v>cv+1) { \
-               printf("\nComp. %s at %d,%d should be %d, not %d\n", #v, i, j, cv, v); \
-               retval=0;  goto bailout; \
-       }}
-
-#define checkval0(v) { \
-       if(v>1) { \
-               printf("\nComp. %s at %d,%d should be 0, not %d\n", #v, i, j, v); \
-               retval=0;  goto bailout; \
-       }}
-
-#define checkval255(v) { \
-       if(v<254) { \
-               printf("\nComp. %s at %d,%d should be 255, not %d\n", #v, i, j, v); \
-               retval=0;  goto bailout; \
-       }}
-
 #define PAD(v, p) ((v+(p)-1)&(~((p)-1)))
 
 int checkbufyuv(unsigned char *buf, int w, int h, int subsamp)
@@ -405,12 +376,12 @@ void gentestjpeg(tjhandle hnd, unsigned char *jpegbuf, unsigned long *size,
 
 void _gentestbmp(tjhandle hnd, unsigned char *jpegbuf, unsigned long jpegsize,
        int w, int h, int ps, char *basefilename, int subsamp, int flags,
-       int scalefactor)
+       int scale_num, int scale_denom)
 {
        unsigned char *bmpbuf=NULL;
        const char *pixformat;  int _hdrw=0, _hdrh=0, _hdrsubsamp=-1;  double t;
-       int scaledw=(w+scalefactor-1)/scalefactor, scaledh=(h+scalefactor-1)/scalefactor;
-       int temp1, temp2;
+       int scaledw=(w*scale_num+scale_denom-1)/scale_denom;
+       int scaledh=(h*scale_num+scale_denom-1)/scale_denom;
        unsigned long size=0;
 
        if(yuv==YUVENCODE) return;
@@ -432,7 +403,8 @@ void _gentestbmp(tjhandle hnd, unsigned char *jpegbuf, unsigned long jpegsize,
        {
                printf("JPEG -> %s %s ", pixformat,
                        (flags&TJ_BOTTOMUP)?"Bottom-Up":"Top-Down ");
-               if(scalefactor) printf("1/%d ... ", scalefactor);
+               if(scale_num!=1 || scale_denom!=1)
+                       printf("%d/%d ... ", scale_num, scale_denom);
                else printf("... ");
        }
 
@@ -443,13 +415,6 @@ void _gentestbmp(tjhandle hnd, unsigned char *jpegbuf, unsigned long jpegsize,
                printf("Incorrect JPEG header\n");  bailout();
        }
 
-       temp1=scaledw;  temp2=scaledh;
-       _catch(tjGetScaledSize(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=scaledw*scaledh*ps+1;
        if((bmpbuf=(unsigned char *)malloc(size))==NULL)
@@ -477,13 +442,9 @@ void _gentestbmp(tjhandle hnd, unsigned char *jpegbuf, unsigned long jpegsize,
        }
        else
        {
-               if(checkbuf(bmpbuf, scaledw, scaledh, ps, subsamp, scalefactor, flags))
-                       printf("Passed.");
-               else
-               {
-                       printf("FAILED!");  exitstatus=-1;
-                       dumpbuf(bmpbuf, scaledw, scaledh, ps, scalefactor, flags);
-               }
+               if(checkbuf(bmpbuf, scaledw, scaledh, ps, subsamp, scale_num, scale_denom,
+                       flags)) printf("Passed.");
+               else {printf("FAILED!");  exitstatus=-1;}
        }
        printf("  %f ms\n", t*1000.);
 
@@ -494,16 +455,25 @@ void _gentestbmp(tjhandle hnd, unsigned char *jpegbuf, unsigned long jpegsize,
 void gentestbmp(tjhandle hnd, unsigned char *jpegbuf, unsigned long jpegsize,
        int w, int h, int ps, char *basefilename, int subsamp, int flags)
 {
-       int i;
+       int i, n=0;
+       tjscalingfactor *sf=tjGetScalingFactors(&n);
+       if(!sf || !n) 
+       {
+               printf("Error in tjGetScalingFactors():\n%s\n", tjGetErrorStr());
+               bailout();
+       }
+
        if((subsamp==TJ_444 || subsamp==TJ_GRAYSCALE) && !yuv)
        {
-               for(i=1; i<=8; i*=2)
+               for(i=0; i<n; i++)
                        _gentestbmp(hnd, jpegbuf, jpegsize, w, h, ps, basefilename, subsamp,
-                               flags, i);
+                               flags, sf[i].num, sf[i].denom);
        }
        else
                _gentestbmp(hnd, jpegbuf, jpegsize, w, h, ps, basefilename, subsamp,
-                       flags, 1);
+                       flags, 1, 1);
+
+       finally:
        printf("\n");
 }
 
index c60cd2a7c9cf2ca5a33dbfeead581759843a4afd..e46197b761ec2400204ff86b03830adf845d714b 100644 (file)
--- a/jpgtest.c
+++ b/jpgtest.c
@@ -34,7 +34,7 @@
 enum {YUVENCODE=1, YUVDECODE};
 int forcemmx=0, forcesse=0, forcesse2=0, forcesse3=0, fastupsample=0,
        decomponly=0, yuv=0, quiet=0, dotile=0, pf=BMP_BGR, bu=0, useppm=0,
-       scalefactor=1;
+       scale_num=1, scale_denom=1;
 const int _ps[BMPPIXELFORMATS]={3, 4, 3, 4, 4, 4};
 const int _flags[BMPPIXELFORMATS]={0, 0, TJ_BGR, TJ_BGR,
        TJ_BGR|TJ_ALPHAFIRST, TJ_ALPHAFIRST};
@@ -44,6 +44,7 @@ const int _bindex[BMPPIXELFORMATS]={2, 2, 0, 0, 1, 3};
 const char *_pfname[]={"RGB", "RGBX", "BGR", "BGRX", "XBGR", "XRGB"};
 const char *_subnamel[NUMSUBOPT]={"4:4:4", "4:2:2", "4:2:0", "GRAY"};
 const char *_subnames[NUMSUBOPT]={"444", "422", "420", "GRAY"};
+tjscalingfactor *sf=NULL;  int nsf=0;
 
 void printsigfig(double val, int figs)
 {
@@ -77,8 +78,8 @@ int decomptest(unsigned char *srcbuf, unsigned char **jpegbuf,
        double start, elapsed;
        int ps=_ps[pf];
        int yuvsize=TJBUFSIZEYUV(w, h, jpegsub), bufsize;
-       int scaledw=(yuv==YUVDECODE)? w : (w+scalefactor-1)/scalefactor;
-       int scaledh=(yuv==YUVDECODE)? h : (h+scalefactor-1)/scalefactor;
+       int scaledw=(yuv==YUVDECODE)? w : (w*scale_num+scale_denom-1)/scale_denom;
+       int scaledh=(yuv==YUVDECODE)? h : (h*scale_num+scale_denom-1)/scale_denom;
        int pitch=scaledw*ps;
 
        if(qual>0)
@@ -172,7 +173,7 @@ int decomptest(unsigned char *srcbuf, unsigned char **jpegbuf,
                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)
+               if(srcbuf && scale_num==1 && scale_denom==1)
                {
                        if(!quiet)
                                printf("Computing compression error and saving to %s.\n", tempstr);
@@ -533,8 +534,9 @@ void dodecomptest(char *filename)
                                printf(">>>>>  JPEG --> %s (%s)  <<<<<\n", _pfname[pf],
                                        bu?"Bottom-up":"Top-down");
                        printf("\nImage size: %d x %d", w, h);
-                       if(scalefactor!=1) printf(" --> %d x %d", (w+scalefactor-1)/scalefactor,
-                               (h+scalefactor-1)/scalefactor);
+                       if(scale_num!=1 || scale_denom!=1)
+                               printf(" --> %d x %d", (w*scale_num+scale_denom-1)/scale_denom,
+                                       (h*scale_num+scale_denom-1)/scale_denom);
                        printf("\n");
                }
 
@@ -559,6 +561,7 @@ void dodecomptest(char *filename)
 
 void usage(char *progname)
 {
+       int i;
        printf("USAGE: %s\n", progname);
        printf("       <Inputfile (BMP|PPM)> <%% Quality> [options]\n\n");
        printf("       %s\n", progname);
@@ -575,8 +578,19 @@ void usage(char *progname)
        printf("-quiet = Output results in tabular rather than verbose format\n");
        printf("-yuvencode = Encode RGB input as planar YUV rather than compressing as JPEG\n");
        printf("-yuvdecode = Decode JPEG image to planar YUV rather than RGB\n");
-       printf("-scale 1/N = scale down the width/height of the decompressed JPEG image by a\n");
-       printf("     factor of N (N = 1, 2, 4, or 8}\n\n");
+       printf("-scale M/N = scale down the width/height of the decompressed JPEG image by a\n");
+       printf("     factor of M/N (M/N = ");
+       for(i=0; i<nsf; i++)
+       {
+               printf("%d/%d", sf[i].num, sf[i].denom);
+               if(nsf==2 && i!=nsf-1) printf(" or ");
+               else if(nsf>2)
+               {
+                       if(i!=nsf-1) printf(", ");
+                       if(i==nsf-2) printf("or ");
+               }
+       }
+       printf(")\n\n");
        printf("NOTE:  If the quality is specified as a range (e.g. 90-100), a separate\n");
        printf("test will be performed for all quality values in the range.\n\n");
        exit(1);
@@ -585,10 +599,13 @@ void usage(char *progname)
 
 int main(int argc, char *argv[])
 {
-       unsigned char *bmpbuf=NULL;  int w, h, i;
+       unsigned char *bmpbuf=NULL;  int w, h, i, j;
        int qual=-1, hiqual=-1;  char *temp;
        int minarg=2;
 
+       if((sf=tjGetScalingFactors(&nsf))==NULL || nsf==0)
+               _throwtj("executing tjGetScalingFactors()");
+
        if(argc<minarg) usage(argv[0]);
 
        temp=strrchr(argv[1], '.');
@@ -673,16 +690,25 @@ int main(int argc, char *argv[])
                        if(!stricmp(argv[i], "-qq")) quiet=2;
                        if(!stricmp(argv[i], "-scale") && i<argc-1)
                        {
-                               int temp1=0, temp2=0;
-                               if(sscanf(argv[++i], "%d/%d", &temp1, &temp2)!=2
-                                       || temp1!=1 || temp2<1 || temp2>8 || (temp2&(temp2-1))!=0)
-                                       usage(argv[0]);
-                               scalefactor=temp2;
+                               int temp1=0, temp2=0, match=0;
+                               if(sscanf(argv[++i], "%d/%d", &temp1, &temp2)==2)
+                               {
+                                       for(j=0; j<nsf; j++)
+                                       {
+                                               if(temp1==sf[j].num && temp2==sf[j].denom)
+                                               {
+                                                       scale_num=temp1;  scale_denom=temp2;
+                                                       match=1;  break;
+                                               }
+                                       }
+                                       if(!match) usage(argv[0]);
+                               }
+                               else usage(argv[0]);
                        }
                }
        }
 
-       if(scalefactor!=1 && dotile)
+       if((scale_num!=1 || scale_denom!=1) && dotile)
        {
                printf("Disabling tiled compression/decompression tests, because these tests do not\n");
                printf("work when scaled decompression is enabled.\n");
@@ -723,7 +749,10 @@ int main(int argc, char *argv[])
                dotest(bmpbuf, w, h, TJ_444, i, argv[1]);
        printf("\n");
 
-       bailout:
        if(bmpbuf) free(bmpbuf);
        return 0;
+
+       bailout:
+       if(bmpbuf) free(bmpbuf);
+       return 1;
 }
index db1118cca4d8995b2b4804a05381113251f88e2f..43cf8718017248bbc3e088848b4fe45683a27750 100644 (file)
@@ -253,28 +253,32 @@ JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_init
        return;
 }
 
-JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_getScaledWidth
-       (JNIEnv *env, jobject obj, jint input_width, jint input_height,
-               jint output_width, jint output_height)
+JNIEXPORT jobjectArray JNICALL Java_org_libjpegturbo_turbojpeg_TJ_getScalingFactors
+       (JNIEnv *env, jclass cls)
 {
-       if(tjGetScaledSize(input_width, input_height, &output_width, &output_height)
-               ==-1)
+  jclass sfcls=NULL;  jfieldID fid=0;
+       tjscalingfactor *sf=NULL;  int n=0, i;
+       jobject sfobj=NULL;
+       jobjectArray sfjava=NULL;
+
+       if((sf=tjGetScalingFactors(&n))==NULL || n==0)
                _throw(tjGetErrorStr());
 
-       bailout:
-       return output_width;
-}
+       bailif0(sfcls=(*env)->FindClass(env, "org/libjpegturbo/turbojpeg/TJ$ScalingFactor"));
+       bailif0(sfjava=(jobjectArray)(*env)->NewObjectArray(env, n, sfcls, 0));
 
-JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_getScaledHeight
-       (JNIEnv *env, jobject obj, jint input_width, jint input_height,
-               jint output_width, jint output_height)
-{
-       if(tjGetScaledSize(input_width, input_height, &output_width, &output_height)
-               ==-1)
-               _throw(tjGetErrorStr());
+       for(i=0; i<n; i++)
+       {
+               bailif0(sfobj=(*env)->AllocObject(env, sfcls));
+               bailif0(fid=(*env)->GetFieldID(env, sfcls, "num", "I"));
+               (*env)->SetIntField(env, sfobj, fid, sf[i].num);
+               bailif0(fid=(*env)->GetFieldID(env, sfcls, "denom", "I"));
+               (*env)->SetIntField(env, sfobj, fid, sf[i].denom);
+               (*env)->SetObjectArrayElement(env, sfjava, i, sfobj);
+       }
 
        bailout:
-       return output_height;
+       return sfjava;
 }
 
 JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompressHeader
index 32bfbabfc2655abc8131c4a372a09a7d762a0228..293bd42e0a795fc741d4a8c7515441b439661b20 100755 (executable)
@@ -25,7 +25,7 @@ TURBOJPEG_1.1
 TURBOJPEG_1.2
 {
        global:
-               tjGetScaledSize;
+               tjGetScalingFactors;
                tjInitTransform;
                tjTransform;
 } TURBOJPEG_1.1;
index 0d5d1db44a4aec7888a58cb12f1f2ef2a3240bd1..367158b3ba7af924a6e3089e137f0dbc9c2b0e79 100755 (executable)
@@ -25,7 +25,7 @@ TURBOJPEG_1.1
 TURBOJPEG_1.2
 {
        global:
-               tjGetScaledSize;
+               tjGetScalingFactors;
                tjInitTransform;
                tjTransform;
                Java_org_libjpegturbo_turbojpeg_TJ_bufSize;
index a08a434e7e6d5d8c62e3699198b0d46cc4f51cce..78ed07355022138744cb8880485cb64361e2c7a7 100644 (file)
@@ -56,6 +56,12 @@ enum {TJ_444=0, TJ_422, TJ_420, TJ_GRAYSCALE};
 #define TJ_YUV           512
   /* Nothing to see here.  Pay no attention to the man behind the curtain. */
 
+/* Scaling factor structure */
+typedef struct
+{
+       int num, denom;
+} tjscalingfactor;
+
 /* Transform operations for tjTransform() */
 #define NUMXFORMOPT 8
 
@@ -299,23 +305,16 @@ DLLEXPORT int DLLCALL tjDecompressHeader(tjhandle j,
 
 
 /*
-  int tjGetScaledSize(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
+  tjscalingfactor *tjGetScalingFactors(int *numscalingfactors)
+
+  Returns a list of fractional scaling factors that the JPEG decompressor in
+  this implementation of TurboJPEG supports.
+
+  [OUTPUT] numscalingfactors = the size of the list
+
+  RETURNS: NULL on error
 */
-DLLEXPORT int DLLCALL tjGetScaledSize(int input_width, int input_height,
-       int *output_width, int *output_height);
+DLLEXPORT tjscalingfactor* DLLCALL tjGetScalingFactors(int *numscalingfactors);
 
 
 /*
@@ -331,10 +330,10 @@ DLLEXPORT int DLLCALL tjGetScaledSize(int input_width, int input_height,
   [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 is determined by calling
-     tjGetScaledSize() with the height of the desired output image.  This
-     pointer may also be used to decompress into a specific region of a
-     larger buffer.
+     bytes in size, where scaled_height is ceil(jpeg_height*scaling_factor),
+     and the supported scaling factors can be determined by calling
+     tjGetScalingFactors().  The dstbuf 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
@@ -345,10 +344,9 @@ DLLEXPORT int DLLCALL tjGetScaledSize(int input_width, int input_height,
      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 can be determined by calling tjGetScaledSize().)  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 = ceil(jpeg_width*scaling_factor).)  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
index e06bc1ad5fe4a73c06be54f99c6aec130874aa00..c2f776f7800d56855696683342d8e37b88924784 100644 (file)
@@ -74,6 +74,13 @@ static const JXFORM_CODE xformtypes[NUMXFORMOPT]={
        JXFORM_NONE, JXFORM_FLIP_H, JXFORM_FLIP_V, JXFORM_TRANSPOSE,
        JXFORM_TRANSVERSE, JXFORM_ROT_90, JXFORM_ROT_180, JXFORM_ROT_270
 };
+#define NUMSF 4
+static const tjscalingfactor sf[NUMSF]={
+       {1, 1},
+       {1, 2},
+       {1, 4},
+       {1, 8}
+};
 
 #define _throw(c) {sprintf(lasterror, "%s", c);  retval=-1;  goto bailout;}
 #define checkhandle(h) jpgstruct *j=(jpgstruct *)h; \
@@ -472,31 +479,16 @@ DLLEXPORT int DLLCALL tjDecompressHeader(tjhandle h,
 }
 
 
-DLLEXPORT int DLLCALL tjGetScaledSize(int input_width, int input_height,
-       int *output_width, int *output_height)
+DLLEXPORT tjscalingfactor* DLLCALL tjGetScalingFactors(int *numscalingfactors)
 {
-       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 tjGetScaledSize()");
-
-       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)
+       if(numscalingfactors==NULL)
        {
-               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;
+               sprintf(lasterror, "Invalid argument in tjGetScalingFactors()");
+               return NULL;
        }
 
-       bailout:
-       return retval;
+       *numscalingfactors=NUMSF;
+       return (tjscalingfactor *)sf;
 }
 
 
@@ -509,7 +501,7 @@ DLLEXPORT int DLLCALL tjDecompress(tjhandle h,
        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;
+       int jpegwidth, jpegheight, scaledw, scaledh;
 
        checkhandle(h);
 
@@ -608,22 +600,18 @@ DLLEXPORT int DLLCALL tjDecompress(tjhandle h,
                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=0; i<NUMSF; i++)
                {
-                       for(i=1; i<=8; i*=2)
-                       {
-                               scaledw=(jpegwidth+i-1)/i;
-                               scaledh=(jpegheight+i-1)/i;
-                               if(scaledw<=width && scaledh<=height)
+                       scaledw=(jpegwidth*sf[i].num+sf[i].denom-1)/sf[i].denom;
+                       scaledh=(jpegheight*sf[i].num+sf[i].denom-1)/sf[i].denom;
+                       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;
                }
-               j->dinfo.scale_num=scale_num;
-               j->dinfo.scale_denom=scale_denom;
+               if(scaledw>width || scaledh>height)
+                       _throw("Could not scale down to desired image dimensions");
+               width=scaledw;  height=scaledh;
+               j->dinfo.scale_num=sf[i].num;
+               j->dinfo.scale_denom=sf[i].denom;
        }
 
        jpeg_start_decompress(&j->dinfo);