From 109a578e89ea8cd2c39d50b012698148dd11dedb Mon Sep 17 00:00:00 2001 From: DRC Date: Tue, 1 Mar 2011 09:53:07 +0000 Subject: [PATCH] tjGetScaledSize() would never be able to accommodate scaling factors > 1, so replace it with a function that returns a list of fractional scaling factors that TurboJPEG supports. git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@477 632fc199-4ca6-4c93-a231-07263d6284db --- java/TJUnitTest.java | 36 ++-- java/org/libjpegturbo/turbojpeg/TJ.java | 8 + .../turbojpeg/TJDecompressor.java | 36 +++- java/org_libjpegturbo_turbojpeg_TJ.h | 8 + ...rg_libjpegturbo_turbojpeg_TJDecompressor.h | 16 -- jpegut.c | 188 ++++++++---------- jpgtest.c | 61 ++++-- turbojpeg-jni.c | 36 ++-- turbojpeg-mapfile | 2 +- turbojpeg-mapfile.jni | 2 +- turbojpeg.h | 46 ++--- turbojpegl.c | 58 +++--- 12 files changed, 252 insertions(+), 245 deletions(-) diff --git a/java/TJUnitTest.java b/java/TJUnitTest.java index 8bd07d1..bdfecfc 100644 --- a/java/TJUnitTest.java +++ b/java/TJUnitTest.java @@ -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 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 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"); } diff --git a/java/org_libjpegturbo_turbojpeg_TJ.h b/java/org_libjpegturbo_turbojpeg_TJ.h index b2be5d8..7efaf49 100644 --- a/java/org_libjpegturbo_turbojpeg_TJ.h +++ b/java/org_libjpegturbo_turbojpeg_TJ.h @@ -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 diff --git a/java/org_libjpegturbo_turbojpeg_TJDecompressor.h b/java/org_libjpegturbo_turbojpeg_TJDecompressor.h index 6951906..6b67296 100644 --- a/java/org_libjpegturbo_turbojpeg_TJDecompressor.h +++ b/java/org_libjpegturbo_turbojpeg_TJDecompressor.h @@ -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 diff --git a/jpegut.c b/jpegut.c index 0cf4533..6393cf6 100644 --- 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; icv+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; _i78 || g<74 || g>78 || b<74 || b>78) return 0; - } + checkval255(r); checkval255(g); checkval255(b); } - } - for(_i=halfway; _i2 || 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; _i2) return 0; - if(buf[(w*i+j)*ps+boffset]>2) return 0; + checkval255(r); checkval255(g); checkval0(b); } } } - for(_i=halfway; _i2) 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(vcv+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; i0) @@ -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(" <%% 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; i2) + { + 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(argc8 || (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; jFindClass(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; iAllocObject(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 diff --git a/turbojpeg-mapfile b/turbojpeg-mapfile index 32bfbab..293bd42 100755 --- a/turbojpeg-mapfile +++ b/turbojpeg-mapfile @@ -25,7 +25,7 @@ TURBOJPEG_1.1 TURBOJPEG_1.2 { global: - tjGetScaledSize; + tjGetScalingFactors; tjInitTransform; tjTransform; } TURBOJPEG_1.1; diff --git a/turbojpeg-mapfile.jni b/turbojpeg-mapfile.jni index 0d5d1db..367158b 100755 --- a/turbojpeg-mapfile.jni +++ b/turbojpeg-mapfile.jni @@ -25,7 +25,7 @@ TURBOJPEG_1.1 TURBOJPEG_1.2 { global: - tjGetScaledSize; + tjGetScalingFactors; tjInitTransform; tjTransform; Java_org_libjpegturbo_turbojpeg_TJ_bufSize; diff --git a/turbojpeg.h b/turbojpeg.h index a08a434..78ed073 100644 --- a/turbojpeg.h +++ b/turbojpeg.h @@ -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 diff --git a/turbojpegl.c b/turbojpegl.c index e06bc1a..c2f776f 100644 --- a/turbojpegl.c +++ b/turbojpegl.c @@ -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_widthdinfo.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; } - 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); -- 2.40.0