From: DRC Date: Sat, 26 Feb 2011 22:02:37 +0000 (+0000) Subject: Expose libjpeg lossless transform feature in TurboJPEG/OSS X-Git-Tag: 1.1.90~196 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=890f1e0413b54c40b663208779d4ea9dae20eaef;p=libjpeg-turbo Expose libjpeg lossless transform feature in TurboJPEG/OSS git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@464 632fc199-4ca6-4c93-a231-07263d6284db --- diff --git a/Makefile.am b/Makefile.am index 30c9c6d..3131953 100644 --- a/Makefile.am +++ b/Makefile.am @@ -34,7 +34,8 @@ libjpeg_la_SOURCES += jdarith.c endif -libturbojpeg_la_SOURCES = $(libjpeg_la_SOURCES) turbojpegl.c turbojpeg.h +libturbojpeg_la_SOURCES = $(libjpeg_la_SOURCES) turbojpegl.c turbojpeg.h \ + transupp.c transupp.h if WITH_JNI diff --git a/jpgtest.c b/jpgtest.c index 0ec2a15..c60cd2a 100644 --- a/jpgtest.c +++ b/jpgtest.c @@ -119,7 +119,8 @@ int decomptest(unsigned char *srcbuf, unsigned char **jpegbuf, { for(j=0; j>>>> JPEG --> YUV %s <<<<<\n", _subnamel[jpegsub]); - else + tilesizex=tilesizey=512; + if(quiet==1) + { + printf("All performance values in Mpixels/sec\n\n"); + printf("Bitmap\tBitmap\tJPEG\tTile Size\tXform\tCompr\tDecomp\n"); + printf("Format\tOrder\tFormat\t X Y \tPerf \tRatio\tPerf\n\n"); + } + else if(!quiet) + { 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); - printf("\n"); + } + do + { + tilesizex*=2; if(tilesizex>w) tilesizex=w; + tilesizey*=2; if(tilesizey>h) tilesizey=h; + numtilesx=(w+tilesizex-1)/tilesizex; + numtilesy=(h+tilesizey-1)/tilesizey; + if((comptilesize=(unsigned long *)malloc(sizeof(unsigned long) + *numtilesx*numtilesy))==NULL + || (jpegbuf=(unsigned char **)malloc(sizeof(unsigned char *) + *numtilesx*numtilesy))==NULL) + _throwunix("allocating image buffers"); + memset(jpegbuf, 0, sizeof(unsigned char *)*numtilesx*numtilesy); + + for(i=0; i Frame rate: %f fps\n", 1.0/elapsed); + printf(" Output image size: %lu bytes\n", jpgbufsize); + printf(" Compression ratio: %f:1\n", + (double)(w*h*ps)/(double)jpgbufsize); + printf(" Source throughput: %f Megapixels/sec\n", + (double)(w*h)/1000000./elapsed); + printf(" Output bit stream: %f Megabits/sec\n", + (double)jpgbufsize*8./1000000./elapsed); + } + + if(decomptest(NULL, jpegbuf, comptilesize, NULL, w, h, jpegsub, 0, + filename, tilesizex, tilesizey)==-1) + goto bailout; + + // Cleanup + for(i=0; i>>>> JPEG --> YUV %s <<<<<\n", _subnamel[jpegsub]); + else + 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); + printf("\n"); + } - decomptest(NULL, &jpegbuf, &jpgbufsize, NULL, w, h, jpegsub, 0, filename, w, - h); + decomptest(NULL, &srcbuf, &srcbufsize, NULL, w, h, jpegsub, 0, filename, + w, h); + } bailout: if(file) {fclose(file); file=NULL;} - if(jpegbuf) {free(jpegbuf); jpegbuf=NULL;} + if(jpegbuf) + { + for(i=0; i #include #include "./turbojpeg.h" +#include "transupp.h" #ifndef min #define min(a,b) ((a)<(b)?(a):(b)) @@ -69,6 +70,10 @@ typedef struct _jpgstruct static const int hsampfactor[NUMSUBOPT]={1, 2, 2, 1}; static const int vsampfactor[NUMSUBOPT]={1, 1, 2, 1}; static const int pixelsize[NUMSUBOPT]={3, 3, 3, 1}; +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 _throw(c) {sprintf(lasterror, "%s", c); retval=-1; goto bailout;} #define checkhandle(h) jpgstruct *j=(jpgstruct *)h; \ @@ -87,12 +92,8 @@ static void destination_noop(struct jpeg_compress_struct *cinfo) { } -DLLEXPORT tjhandle DLLCALL tjInitCompress(void) +static tjhandle _tjInitCompress(jpgstruct *j) { - jpgstruct *j=NULL; - if((j=(jpgstruct *)malloc(sizeof(jpgstruct)))==NULL) - {sprintf(lasterror, "Memory allocation failure"); return NULL;} - memset(j, 0, sizeof(jpgstruct)); j->cinfo.err=jpeg_std_error(&j->jerr.pub); j->jerr.pub.error_exit=my_error_exit; j->jerr.pub.output_message=my_output_message; @@ -112,6 +113,15 @@ DLLEXPORT tjhandle DLLCALL tjInitCompress(void) return (tjhandle)j; } +DLLEXPORT tjhandle DLLCALL tjInitCompress(void) +{ + jpgstruct *j=NULL; + if((j=(jpgstruct *)malloc(sizeof(jpgstruct)))==NULL) + {sprintf(lasterror, "Memory allocation failure"); return NULL;} + memset(j, 0, sizeof(jpgstruct)); + return _tjInitCompress(j); +} + DLLEXPORT unsigned long DLLCALL TJBUFSIZE(int width, int height) { @@ -364,12 +374,8 @@ static void source_noop (struct jpeg_decompress_struct *dinfo) { } -DLLEXPORT tjhandle DLLCALL tjInitDecompress(void) +static tjhandle _tjInitDecompress(jpgstruct *j) { - jpgstruct *j; - if((j=(jpgstruct *)malloc(sizeof(jpgstruct)))==NULL) - {sprintf(lasterror, "Memory allocation failure"); return NULL;} - memset(j, 0, sizeof(jpgstruct)); j->dinfo.err=jpeg_std_error(&j->jerr.pub); j->jerr.pub.error_exit=my_error_exit; j->jerr.pub.output_message=my_output_message; @@ -391,6 +397,15 @@ DLLEXPORT tjhandle DLLCALL tjInitDecompress(void) return (tjhandle)j; } +DLLEXPORT tjhandle DLLCALL tjInitDecompress(void) +{ + jpgstruct *j; + if((j=(jpgstruct *)malloc(sizeof(jpgstruct)))==NULL) + {sprintf(lasterror, "Memory allocation failure"); return NULL;} + memset(j, 0, sizeof(jpgstruct)); + return _tjInitDecompress(j); +} + DLLEXPORT int DLLCALL tjDecompressHeader2(tjhandle h, unsigned char *srcbuf, unsigned long size, @@ -682,6 +697,120 @@ DLLEXPORT int DLLCALL tjDecompressToYUV(tjhandle h, } +// Transformation + +DLLEXPORT tjhandle DLLCALL tjInitTransform(void) +{ + jpgstruct *j=NULL; tjhandle tj=NULL; + if((j=(jpgstruct *)malloc(sizeof(jpgstruct)))==NULL) + {sprintf(lasterror, "Memory allocation failure"); return NULL;} + memset(j, 0, sizeof(jpgstruct)); + tj=_tjInitCompress(j); + if(!tj) return NULL; + tj=_tjInitDecompress(j); + return tj; +} + + +DLLEXPORT int DLLCALL tjTransform(tjhandle hnd, + unsigned char *srcbuf, unsigned long srcsize, + unsigned char *dstbuf, unsigned long *dstsize, + int x, int y, int w, int h, int op, int options, int flags) +{ + jpeg_transform_info xinfo; + jvirt_barray_ptr *srccoefs, *dstcoefs; + int retval=0; + + checkhandle(hnd); + + if(srcbuf==NULL || srcsize<=0 || dstbuf==NULL || dstsize==NULL + || x<0 || y<0 || w<0 || h<0 || op<0 || op>=NUMXFORMOPT + || flags<0) + _throw("Invalid argument in tjTransform()"); + if(!j->initc || !j->initd) + _throw("Instance has not been initialized for transformation"); + + 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"); + + if(setjmp(j->jerr.jb)) + { // this will execute if LIBJPEG has an error + retval=-1; + goto bailout; + } + + j->jsms.bytes_in_buffer=srcsize; + j->jsms.next_input_byte=srcbuf; + + xinfo.transform=xformtypes[op]; + xinfo.perfect=(options&TJXFORM_PERFECT)? 1:0; + xinfo.trim=(options&TJXFORM_TRIM)? 1:0; + xinfo.force_grayscale=(options&TJXFORM_GRAY)? 1:0; + xinfo.crop=(options&TJXFORM_CROP)? 1:0; + + if(xinfo.crop) + { + xinfo.crop_xoffset=x; xinfo.crop_xoffset_set=JCROP_POS; + xinfo.crop_yoffset=y; xinfo.crop_yoffset_set=JCROP_POS; + if(w!=0) + { + xinfo.crop_width=w; xinfo.crop_width_set=JCROP_POS; + } + if(h!=0) + { + xinfo.crop_height=h; xinfo.crop_height_set=JCROP_POS; + } + } + + jcopy_markers_setup(&j->dinfo, JCOPYOPT_NONE); + jpeg_read_header(&j->dinfo, TRUE); + + if(!jtransform_request_workspace(&j->dinfo, &xinfo)) + _throw("Transform is not perfect"); + + if(!xinfo.crop) + { + w=j->dinfo.image_width; h=j->dinfo.image_height; + } + else + { + w=xinfo.crop_width; h=xinfo.crop_height; + } + + j->jdms.next_output_byte=dstbuf; + j->jdms.free_in_buffer=TJBUFSIZE(w, h); + + if(xinfo.crop) + { + if((x%xinfo.iMCU_sample_width)!=0 || (y%xinfo.iMCU_sample_height)!=0) + { + sprintf(lasterror, "To crop this JPEG image, x must be a multiple of %d and y must be a multiple\n" + "of %d.\n", xinfo.iMCU_sample_width, xinfo.iMCU_sample_height); + retval=-1; goto bailout; + } + } + + srccoefs=jpeg_read_coefficients(&j->dinfo); + jpeg_copy_critical_parameters(&j->dinfo, &j->cinfo); + dstcoefs=jtransform_adjust_parameters(&j->dinfo, &j->cinfo, srccoefs, + &xinfo); + jpeg_write_coefficients(&j->cinfo, dstcoefs); + jcopy_markers_execute(&j->dinfo, &j->cinfo, JCOPYOPT_ALL); + jtransform_execute_transformation(&j->dinfo, &j->cinfo, srccoefs, &xinfo); + + jpeg_finish_compress(&j->cinfo); + jpeg_finish_decompress(&j->dinfo); + + *dstsize=TJBUFSIZE(w, h)-(unsigned long)(j->jdms.free_in_buffer); + + bailout: + if(j->cinfo.global_state>CSTATE_START) jpeg_abort_compress(&j->cinfo); + if(j->dinfo.global_state>DSTATE_START) jpeg_abort_decompress(&j->dinfo); + return retval; +} + + // General DLLEXPORT char* DLLCALL tjGetErrorStr(void)