aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--java/TJExample.java4
-rw-r--r--java/org/libjpegturbo/turbojpeg/TJDecompressor.java2
-rw-r--r--jpegut.c20
-rw-r--r--jpgtest.c23
-rw-r--r--turbojpeg-jni.c6
-rwxr-xr-xturbojpeg-mapfile1
-rwxr-xr-xturbojpeg-mapfile.jni1
-rw-r--r--turbojpeg.h69
-rw-r--r--turbojpegl.c82
9 files changed, 135 insertions, 73 deletions
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; 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)
diff --git a/turbojpeg-jni.c b/turbojpeg-jni.c
index 1ab5e28..892e51b 100644
--- a/turbojpeg-jni.c
+++ b/turbojpeg-jni.c
@@ -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);
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; 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)