diff options
author | Chris Blume <cblume@chromium.org> | 2019-03-01 01:09:50 -0800 |
---|---|---|
committer | Chris Blume <cblume@chromium.org> | 2019-03-01 01:09:50 -0800 |
commit | cca8c4dec783a048da6933c86028556622d7c355 (patch) | |
tree | 8a7ff526cd8cbe3bf1bfaa4ec1c29fe3268ed51b /tjbench.c | |
parent | 61a2bbaa9aec89cb2c882d87ace6aba9aee49bb9 (diff) |
Update libjpeg-turbo to v2.0.1
In order to apply some performance updates from ARM, we need to update
libjpeg-turbo. These performance updates have yielded a 50% speedup on
some devices.
This CL updates our copy of libjpeg-turbo to v2.0.1 and re-applies our
local patches. This patch also deletes some extra files which were not
being used locally.
Update our local patch that was applied to fix http://crbug.com/398235
(https://codereview.appspot.com/229430043/). The original patch
incorrectly removed "& 0xFF" which limited an array index to within
that array's bounds (effectively reverting
https://github.com/libjpeg-turbo/libjpeg-turbo/commit/fa1d18385d904d530b4aec83ab7757a33397de6e).
Restore the mask, making the array access safe and fixing a graphical
glitch which would otherwise be introduced by this change.
Bug:922430
Change-Id: I3860fdb424deecf7a17818ed09a640e632e71f8d
Diffstat (limited to 'tjbench.c')
-rw-r--r-- | tjbench.c | 1841 |
1 files changed, 931 insertions, 910 deletions
@@ -1,5 +1,5 @@ /* - * Copyright (C)2009-2016 D. R. Commander. All Rights Reserved. + * Copyright (C)2009-2018 D. R. Commander. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -33,958 +33,979 @@ #include <math.h> #include <errno.h> #include <cdjpeg.h> -#include "./bmp.h" #include "./tjutil.h" #include "./turbojpeg.h" -#define _throw(op, err) { \ - printf("ERROR in line %d while %s:\n%s\n", __LINE__, op, err); \ - retval=-1; goto bailout;} -#define _throwunix(m) _throw(m, strerror(errno)) -#define _throwtj(m) _throw(m, tjGetErrorStr()) -#define _throwbmp(m) _throw(m, bmpgeterr()) +#define _throw(op, err) { \ + printf("ERROR in line %d while %s:\n%s\n", __LINE__, op, err); \ + retval = -1; goto bailout; \ +} +#define _throwunix(m) _throw(m, strerror(errno)) -int flags=TJFLAG_NOREALLOC, componly=0, decomponly=0, doyuv=0, quiet=0, - dotile=0, pf=TJPF_BGR, yuvpad=1, warmup=1, dowrite=1; -char *ext="ppm"; -const char *pixFormatStr[TJ_NUMPF]= -{ - "RGB", "BGR", "RGBX", "BGRX", "XBGR", "XRGB", "GRAY", "", "", "", "", "CMYK" +char tjErrorStr[JMSG_LENGTH_MAX] = "\0", tjErrorMsg[JMSG_LENGTH_MAX] = "\0"; +int tjErrorLine = -1, tjErrorCode = -1; + +#define _throwtjg(m) { \ + printf("ERROR in line %d while %s:\n%s\n", __LINE__, m, \ + tjGetErrorStr2(NULL)); \ + retval = -1; goto bailout; \ +} + +#define _throwtj(m) { \ + int _tjErrorCode = tjGetErrorCode(handle); \ + char *_tjErrorStr = tjGetErrorStr2(handle); \ + \ + if (!(flags & TJFLAG_STOPONWARNING) && _tjErrorCode == TJERR_WARNING) { \ + if (strncmp(tjErrorStr, _tjErrorStr, JMSG_LENGTH_MAX) || \ + strncmp(tjErrorMsg, m, JMSG_LENGTH_MAX) || \ + tjErrorCode != _tjErrorCode || tjErrorLine != __LINE__) { \ + strncpy(tjErrorStr, _tjErrorStr, JMSG_LENGTH_MAX - 1); \ + strncpy(tjErrorMsg, m, JMSG_LENGTH_MAX - 1); \ + tjErrorCode = _tjErrorCode; \ + tjErrorLine = __LINE__; \ + printf("WARNING in line %d while %s:\n%s\n", __LINE__, m, _tjErrorStr); \ + } \ + } else { \ + printf("%s in line %d while %s:\n%s\n", \ + _tjErrorCode == TJERR_WARNING ? "WARNING" : "ERROR", __LINE__, m, \ + _tjErrorStr); \ + retval = -1; goto bailout; \ + } \ +} + +int flags = TJFLAG_NOREALLOC, compOnly = 0, decompOnly = 0, doYUV = 0, + quiet = 0, doTile = 0, pf = TJPF_BGR, yuvPad = 1, doWrite = 1; +char *ext = "ppm"; +const char *pixFormatStr[TJ_NUMPF] = { + "RGB", "BGR", "RGBX", "BGRX", "XBGR", "XRGB", "GRAY", "", "", "", "", "CMYK" }; -const char *subNameLong[TJ_NUMSAMP]= -{ - "4:4:4", "4:2:2", "4:2:0", "GRAY", "4:4:0", "4:1:1" +const char *subNameLong[TJ_NUMSAMP] = { + "4:4:4", "4:2:2", "4:2:0", "GRAY", "4:4:0", "4:1:1" }; -const char *csName[TJ_NUMCS]= -{ - "RGB", "YCbCr", "GRAY", "CMYK", "YCCK" +const char *csName[TJ_NUMCS] = { + "RGB", "YCbCr", "GRAY", "CMYK", "YCCK" }; -const char *subName[TJ_NUMSAMP]={"444", "422", "420", "GRAY", "440", "411"}; -tjscalingfactor *scalingfactors=NULL, sf={1, 1}; int nsf=0; -int xformop=TJXOP_NONE, xformopt=0; -int (*customFilter)(short *, tjregion, tjregion, int, int, tjtransform *); -double benchtime=5.0; +const char *subName[TJ_NUMSAMP] = { + "444", "422", "420", "GRAY", "440", "411" +}; +tjscalingfactor *scalingFactors = NULL, sf = { 1, 1 }; +int nsf = 0, xformOp = TJXOP_NONE, xformOpt = 0; +int (*customFilter) (short *, tjregion, tjregion, int, int, tjtransform *); +double benchTime = 5.0, warmup = 1.0; char *formatName(int subsamp, int cs, char *buf) { - if(cs==TJCS_YCbCr) return (char *)subNameLong[subsamp]; - else if(cs==TJCS_YCCK) - { - snprintf(buf, 80, "%s %s", csName[cs], subNameLong[subsamp]); - return buf; - } - else return (char *)csName[cs]; + if (cs == TJCS_YCbCr) + return (char *)subNameLong[subsamp]; + else if (cs == TJCS_YCCK || cs == TJCS_CMYK) { + snprintf(buf, 80, "%s %s", csName[cs], subNameLong[subsamp]); + return buf; + } else + return (char *)csName[cs]; } char *sigfig(double val, int figs, char *buf, int len) { - char format[80]; - int digitsafterdecimal=figs-(int)ceil(log10(fabs(val))); - if(digitsafterdecimal<1) snprintf(format, 80, "%%.0f"); - else snprintf(format, 80, "%%.%df", digitsafterdecimal); - snprintf(buf, len, format, val); - return buf; + char format[80]; + int digitsAfterDecimal = figs - (int)ceil(log10(fabs(val))); + + if (digitsAfterDecimal < 1) + snprintf(format, 80, "%%.0f"); + else + snprintf(format, 80, "%%.%df", digitsAfterDecimal); + snprintf(buf, len, format, val); + return buf; } /* Custom DCT filter which produces a negative of the image */ int dummyDCTFilter(short *coeffs, tjregion arrayRegion, tjregion planeRegion, - int componentIndex, int transformIndex, tjtransform *transform) + int componentIndex, int transformIndex, + tjtransform *transform) { - int i; - for(i=0; i<arrayRegion.w*arrayRegion.h; i++) coeffs[i]=-coeffs[i]; - return 0; + int i; + + for (i = 0; i < arrayRegion.w * arrayRegion.h; i++) + coeffs[i] = -coeffs[i]; + return 0; } /* Decompression test */ -int decomp(unsigned char *srcbuf, unsigned char **jpegbuf, - unsigned long *jpegsize, unsigned char *dstbuf, int w, int h, - int subsamp, int jpegqual, char *filename, int tilew, int tileh) +int decomp(unsigned char *srcBuf, unsigned char **jpegBuf, + unsigned long *jpegSize, unsigned char *dstBuf, int w, int h, + int subsamp, int jpegQual, char *fileName, int tilew, int tileh) { - char tempstr[1024], sizestr[20]="\0", qualstr[6]="\0", *ptr; - FILE *file=NULL; tjhandle handle=NULL; - int row, col, iter=0, dstbufalloc=0, retval=0; - double elapsed, elapsedDecode; - int ps=tjPixelSize[pf]; - int scaledw=TJSCALED(w, sf); - int scaledh=TJSCALED(h, sf); - int pitch=scaledw*ps; - int ntilesw=(w+tilew-1)/tilew, ntilesh=(h+tileh-1)/tileh; - unsigned char *dstptr, *dstptr2, *yuvbuf=NULL; - - if(jpegqual>0) - { - snprintf(qualstr, 6, "_Q%d", jpegqual); - qualstr[5]=0; - } - - if((handle=tjInitDecompress())==NULL) - _throwtj("executing tjInitDecompress()"); - - if(dstbuf==NULL) - { - if((dstbuf=(unsigned char *)malloc(pitch*scaledh))==NULL) - _throwunix("allocating destination buffer"); - dstbufalloc=1; - } - /* Set the destination buffer to gray so we know whether the decompressor - attempted to write to it */ - memset(dstbuf, 127, pitch*scaledh); - - if(doyuv) - { - int width=dotile? tilew:scaledw; - int height=dotile? tileh:scaledh; - int yuvsize=tjBufSizeYUV2(width, yuvpad, height, subsamp); - if((yuvbuf=(unsigned char *)malloc(yuvsize))==NULL) - _throwunix("allocating YUV buffer"); - memset(yuvbuf, 127, yuvsize); - } - - /* Benchmark */ - iter=-warmup; - elapsed=elapsedDecode=0.; - while(1) - { - int tile=0; - double start=gettime(); - for(row=0, dstptr=dstbuf; row<ntilesh; row++, dstptr+=pitch*tileh) - { - for(col=0, dstptr2=dstptr; col<ntilesw; col++, tile++, dstptr2+=ps*tilew) - { - int width=dotile? min(tilew, w-col*tilew):scaledw; - int height=dotile? min(tileh, h-row*tileh):scaledh; - if(doyuv) - { - double startDecode; - if(tjDecompressToYUV2(handle, jpegbuf[tile], jpegsize[tile], yuvbuf, - width, yuvpad, height, flags)==-1) - _throwtj("executing tjDecompressToYUV2()"); - startDecode=gettime(); - if(tjDecodeYUV(handle, yuvbuf, yuvpad, subsamp, dstptr2, width, - pitch, height, pf, flags)==-1) - _throwtj("executing tjDecodeYUV()"); - if(iter>=0) elapsedDecode+=gettime()-startDecode; - } - else - if(tjDecompress2(handle, jpegbuf[tile], jpegsize[tile], dstptr2, - width, pitch, height, pf, flags)==-1) - _throwtj("executing tjDecompress2()"); - } - } - iter++; - if(iter>=1) - { - elapsed+=gettime()-start; - if(elapsed>=benchtime) break; - } - } - if(doyuv) elapsed-=elapsedDecode; - - if(tjDestroy(handle)==-1) _throwtj("executing tjDestroy()"); - handle=NULL; - - if(quiet) - { - printf("%-6s%s", - sigfig((double)(w*h)/1000000.*(double)iter/elapsed, 4, tempstr, 1024), - quiet==2? "\n":" "); - if(doyuv) - printf("%s\n", - sigfig((double)(w*h)/1000000.*(double)iter/elapsedDecode, 4, tempstr, - 1024)); - else if(quiet!=2) printf("\n"); - } - else - { - printf("%s --> Frame rate: %f fps\n", - doyuv? "Decomp to YUV":"Decompress ", (double)iter/elapsed); - printf(" Throughput: %f Megapixels/sec\n", - (double)(w*h)/1000000.*(double)iter/elapsed); - if(doyuv) - { - printf("YUV Decode --> Frame rate: %f fps\n", - (double)iter/elapsedDecode); - printf(" Throughput: %f Megapixels/sec\n", - (double)(w*h)/1000000.*(double)iter/elapsedDecode); - } - } - - if (!dowrite) goto bailout; - - if(sf.num!=1 || sf.denom!=1) - snprintf(sizestr, 20, "%d_%d", sf.num, sf.denom); - else if(tilew!=w || tileh!=h) - snprintf(sizestr, 20, "%dx%d", tilew, tileh); - else snprintf(sizestr, 20, "full"); - if(decomponly) - snprintf(tempstr, 1024, "%s_%s.%s", filename, sizestr, ext); - else - snprintf(tempstr, 1024, "%s_%s%s_%s.%s", filename, subName[subsamp], - qualstr, sizestr, ext); - - if(savebmp(tempstr, dstbuf, scaledw, scaledh, pf, - (flags&TJFLAG_BOTTOMUP)!=0)==-1) - _throwbmp("saving bitmap"); - ptr=strrchr(tempstr, '.'); - snprintf(ptr, 1024-(ptr-tempstr), "-err.%s", ext); - if(srcbuf && sf.num==1 && sf.denom==1) - { - if(!quiet) printf("Compression error written to %s.\n", tempstr); - if(subsamp==TJ_GRAYSCALE) - { - int index, index2; - for(row=0, index=0; row<h; row++, index+=pitch) - { - for(col=0, index2=index; col<w; col++, index2+=ps) - { - int rindex=index2+tjRedOffset[pf]; - int gindex=index2+tjGreenOffset[pf]; - int bindex=index2+tjBlueOffset[pf]; - int y=(int)((double)srcbuf[rindex]*0.299 - + (double)srcbuf[gindex]*0.587 - + (double)srcbuf[bindex]*0.114 + 0.5); - if(y>255) y=255; if(y<0) y=0; - dstbuf[rindex]=abs(dstbuf[rindex]-y); - dstbuf[gindex]=abs(dstbuf[gindex]-y); - dstbuf[bindex]=abs(dstbuf[bindex]-y); - } - } - } - else - { - for(row=0; row<h; row++) - for(col=0; col<w*ps; col++) - dstbuf[pitch*row+col] - =abs(dstbuf[pitch*row+col]-srcbuf[pitch*row+col]); - } - if(savebmp(tempstr, dstbuf, w, h, pf, - (flags&TJFLAG_BOTTOMUP)!=0)==-1) - _throwbmp("saving bitmap"); - } - - bailout: - if(file) fclose(file); - if(handle) tjDestroy(handle); - if(dstbuf && dstbufalloc) free(dstbuf); - if(yuvbuf) free(yuvbuf); - return retval; + char tempStr[1024], sizeStr[20] = "\0", qualStr[6] = "\0", *ptr; + FILE *file = NULL; + tjhandle handle = NULL; + int row, col, iter = 0, dstBufAlloc = 0, retval = 0; + double elapsed, elapsedDecode; + int ps = tjPixelSize[pf]; + int scaledw = TJSCALED(w, sf); + int scaledh = TJSCALED(h, sf); + int pitch = scaledw * ps; + int ntilesw = (w + tilew - 1) / tilew, ntilesh = (h + tileh - 1) / tileh; + unsigned char *dstPtr, *dstPtr2, *yuvBuf = NULL; + + if (jpegQual > 0) { + snprintf(qualStr, 6, "_Q%d", jpegQual); + qualStr[5] = 0; + } + + if ((handle = tjInitDecompress()) == NULL) + _throwtj("executing tjInitDecompress()"); + + if (dstBuf == NULL) { + if ((dstBuf = (unsigned char *)malloc(pitch * scaledh)) == NULL) + _throwunix("allocating destination buffer"); + dstBufAlloc = 1; + } + /* Set the destination buffer to gray so we know whether the decompressor + attempted to write to it */ + memset(dstBuf, 127, pitch * scaledh); + + if (doYUV) { + int width = doTile ? tilew : scaledw; + int height = doTile ? tileh : scaledh; + int yuvSize = tjBufSizeYUV2(width, yuvPad, height, subsamp); + + if ((yuvBuf = (unsigned char *)malloc(yuvSize)) == NULL) + _throwunix("allocating YUV buffer"); + memset(yuvBuf, 127, yuvSize); + } + + /* Benchmark */ + iter = -1; + elapsed = elapsedDecode = 0.; + while (1) { + int tile = 0; + double start = getTime(); + + for (row = 0, dstPtr = dstBuf; row < ntilesh; + row++, dstPtr += pitch * tileh) { + for (col = 0, dstPtr2 = dstPtr; col < ntilesw; + col++, tile++, dstPtr2 += ps * tilew) { + int width = doTile ? min(tilew, w - col * tilew) : scaledw; + int height = doTile ? min(tileh, h - row * tileh) : scaledh; + + if (doYUV) { + double startDecode; + + if (tjDecompressToYUV2(handle, jpegBuf[tile], jpegSize[tile], yuvBuf, + width, yuvPad, height, flags) == -1) + _throwtj("executing tjDecompressToYUV2()"); + startDecode = getTime(); + if (tjDecodeYUV(handle, yuvBuf, yuvPad, subsamp, dstPtr2, width, + pitch, height, pf, flags) == -1) + _throwtj("executing tjDecodeYUV()"); + if (iter >= 0) elapsedDecode += getTime() - startDecode; + } else if (tjDecompress2(handle, jpegBuf[tile], jpegSize[tile], + dstPtr2, width, pitch, height, pf, + flags) == -1) + _throwtj("executing tjDecompress2()"); + } + } + elapsed += getTime() - start; + if (iter >= 0) { + iter++; + if (elapsed >= benchTime) break; + } else if (elapsed >= warmup) { + iter = 0; + elapsed = elapsedDecode = 0.; + } + } + if (doYUV) elapsed -= elapsedDecode; + + if (tjDestroy(handle) == -1) _throwtj("executing tjDestroy()"); + handle = NULL; + + if (quiet) { + printf("%-6s%s", + sigfig((double)(w * h) / 1000000. * (double)iter / elapsed, 4, + tempStr, 1024), + quiet == 2 ? "\n" : " "); + if (doYUV) + printf("%s\n", + sigfig((double)(w * h) / 1000000. * (double)iter / elapsedDecode, + 4, tempStr, 1024)); + else if (quiet != 2) printf("\n"); + } else { + printf("%s --> Frame rate: %f fps\n", + doYUV ? "Decomp to YUV" : "Decompress ", (double)iter / elapsed); + printf(" Throughput: %f Megapixels/sec\n", + (double)(w * h) / 1000000. * (double)iter / elapsed); + if (doYUV) { + printf("YUV Decode --> Frame rate: %f fps\n", + (double)iter / elapsedDecode); + printf(" Throughput: %f Megapixels/sec\n", + (double)(w * h) / 1000000. * (double)iter / elapsedDecode); + } + } + + if (!doWrite) goto bailout; + + if (sf.num != 1 || sf.denom != 1) + snprintf(sizeStr, 20, "%d_%d", sf.num, sf.denom); + else if (tilew != w || tileh != h) + snprintf(sizeStr, 20, "%dx%d", tilew, tileh); + else snprintf(sizeStr, 20, "full"); + if (decompOnly) + snprintf(tempStr, 1024, "%s_%s.%s", fileName, sizeStr, ext); + else + snprintf(tempStr, 1024, "%s_%s%s_%s.%s", fileName, subName[subsamp], + qualStr, sizeStr, ext); + + if (tjSaveImage(tempStr, dstBuf, scaledw, 0, scaledh, pf, flags) == -1) + _throwtjg("saving bitmap"); + ptr = strrchr(tempStr, '.'); + snprintf(ptr, 1024 - (ptr - tempStr), "-err.%s", ext); + if (srcBuf && sf.num == 1 && sf.denom == 1) { + if (!quiet) printf("Compression error written to %s.\n", tempStr); + if (subsamp == TJ_GRAYSCALE) { + int index, index2; + + for (row = 0, index = 0; row < h; row++, index += pitch) { + for (col = 0, index2 = index; col < w; col++, index2 += ps) { + int rindex = index2 + tjRedOffset[pf]; + int gindex = index2 + tjGreenOffset[pf]; + int bindex = index2 + tjBlueOffset[pf]; + int y = (int)((double)srcBuf[rindex] * 0.299 + + (double)srcBuf[gindex] * 0.587 + + (double)srcBuf[bindex] * 0.114 + 0.5); + + if (y > 255) y = 255; + if (y < 0) y = 0; + dstBuf[rindex] = abs(dstBuf[rindex] - y); + dstBuf[gindex] = abs(dstBuf[gindex] - y); + dstBuf[bindex] = abs(dstBuf[bindex] - y); + } + } + } else { + for (row = 0; row < h; row++) + for (col = 0; col < w * ps; col++) + dstBuf[pitch * row + col] = + abs(dstBuf[pitch * row + col] - srcBuf[pitch * row + col]); + } + if (tjSaveImage(tempStr, dstBuf, w, 0, h, pf, flags) == -1) + _throwtjg("saving bitmap"); + } + +bailout: + if (file) fclose(file); + if (handle) tjDestroy(handle); + if (dstBuf && dstBufAlloc) free(dstBuf); + if (yuvBuf) free(yuvBuf); + return retval; } -int fullTest(unsigned char *srcbuf, int w, int h, int subsamp, int jpegqual, - char *filename) +int fullTest(unsigned char *srcBuf, int w, int h, int subsamp, int jpegQual, + char *fileName) { - char tempstr[1024], tempstr2[80]; - FILE *file=NULL; tjhandle handle=NULL; - unsigned char **jpegbuf=NULL, *yuvbuf=NULL, *tmpbuf=NULL, *srcptr, *srcptr2; - double start, elapsed, elapsedEncode; - int totaljpegsize=0, row, col, i, tilew=w, tileh=h, retval=0; - int iter, yuvsize=0; - unsigned long *jpegsize=NULL; - int ps=tjPixelSize[pf]; - int ntilesw=1, ntilesh=1, pitch=w*ps; - const char *pfStr=pixFormatStr[pf]; - - if((tmpbuf=(unsigned char *)malloc(pitch*h)) == NULL) - _throwunix("allocating temporary image buffer"); - - if(!quiet) - printf(">>>>> %s (%s) <--> JPEG %s Q%d <<<<<\n", pfStr, - (flags&TJFLAG_BOTTOMUP)? "Bottom-up":"Top-down", subNameLong[subsamp], - jpegqual); - - for(tilew=dotile? 8:w, tileh=dotile? 8:h; ; tilew*=2, tileh*=2) - { - if(tilew>w) tilew=w; if(tileh>h) tileh=h; - ntilesw=(w+tilew-1)/tilew; ntilesh=(h+tileh-1)/tileh; - - if((jpegbuf=(unsigned char **)malloc(sizeof(unsigned char *) - *ntilesw*ntilesh))==NULL) - _throwunix("allocating JPEG tile array"); - memset(jpegbuf, 0, sizeof(unsigned char *)*ntilesw*ntilesh); - if((jpegsize=(unsigned long *)malloc(sizeof(unsigned long) - *ntilesw*ntilesh))==NULL) - _throwunix("allocating JPEG size array"); - memset(jpegsize, 0, sizeof(unsigned long)*ntilesw*ntilesh); - - if((flags&TJFLAG_NOREALLOC)!=0) - for(i=0; i<ntilesw*ntilesh; i++) - { - if((jpegbuf[i]=(unsigned char *)tjAlloc(tjBufSize(tilew, tileh, - subsamp)))==NULL) - _throwunix("allocating JPEG tiles"); - } - - /* Compression test */ - if(quiet==1) - printf("%-4s (%s) %-5s %-3d ", pfStr, - (flags&TJFLAG_BOTTOMUP)? "BU":"TD", subNameLong[subsamp], jpegqual); - for(i=0; i<h; i++) - memcpy(&tmpbuf[pitch*i], &srcbuf[w*ps*i], w*ps); - if((handle=tjInitCompress())==NULL) - _throwtj("executing tjInitCompress()"); - - if(doyuv) - { - yuvsize=tjBufSizeYUV2(tilew, yuvpad, tileh, subsamp); - if((yuvbuf=(unsigned char *)malloc(yuvsize))==NULL) - _throwunix("allocating YUV buffer"); - memset(yuvbuf, 127, yuvsize); - } - - /* Benchmark */ - iter=-warmup; - elapsed=elapsedEncode=0.; - while(1) - { - int tile=0; - totaljpegsize=0; - start=gettime(); - for(row=0, srcptr=srcbuf; row<ntilesh; row++, srcptr+=pitch*tileh) - { - for(col=0, srcptr2=srcptr; col<ntilesw; col++, tile++, - srcptr2+=ps*tilew) - { - int width=min(tilew, w-col*tilew); - int height=min(tileh, h-row*tileh); - if(doyuv) - { - double startEncode=gettime(); - if(tjEncodeYUV3(handle, srcptr2, width, pitch, height, pf, yuvbuf, - yuvpad, subsamp, flags)==-1) - _throwtj("executing tjEncodeYUV3()"); - if(iter>=0) elapsedEncode+=gettime()-startEncode; - if(tjCompressFromYUV(handle, yuvbuf, width, yuvpad, height, - subsamp, &jpegbuf[tile], &jpegsize[tile], jpegqual, flags)==-1) - _throwtj("executing tjCompressFromYUV()"); - } - else - { - if(tjCompress2(handle, srcptr2, width, pitch, height, pf, - &jpegbuf[tile], &jpegsize[tile], subsamp, jpegqual, flags)==-1) - _throwtj("executing tjCompress2()"); - } - totaljpegsize+=jpegsize[tile]; - } - } - iter++; - if(iter>=1) - { - elapsed+=gettime()-start; - if(elapsed>=benchtime) break; - } - } - if(doyuv) elapsed-=elapsedEncode; - - if(tjDestroy(handle)==-1) _throwtj("executing tjDestroy()"); - handle=NULL; - - if(quiet==1) printf("%-5d %-5d ", tilew, tileh); - if(quiet) - { - if(doyuv) - printf("%-6s%s", - sigfig((double)(w*h)/1000000.*(double)iter/elapsedEncode, 4, tempstr, - 1024), quiet==2? "\n":" "); - printf("%-6s%s", - sigfig((double)(w*h)/1000000.*(double)iter/elapsed, 4, tempstr, 1024), - quiet==2? "\n":" "); - printf("%-6s%s", - sigfig((double)(w*h*ps)/(double)totaljpegsize, 4, tempstr2, 80), - quiet==2? "\n":" "); - } - else - { - printf("\n%s size: %d x %d\n", dotile? "Tile":"Image", tilew, - tileh); - if(doyuv) - { - printf("Encode YUV --> Frame rate: %f fps\n", - (double)iter/elapsedEncode); - printf(" Output image size: %d bytes\n", yuvsize); - printf(" Compression ratio: %f:1\n", - (double)(w*h*ps)/(double)yuvsize); - printf(" Throughput: %f Megapixels/sec\n", - (double)(w*h)/1000000.*(double)iter/elapsedEncode); - printf(" Output bit stream: %f Megabits/sec\n", - (double)yuvsize*8./1000000.*(double)iter/elapsedEncode); - } - printf("%s --> Frame rate: %f fps\n", - doyuv? "Comp from YUV":"Compress ", (double)iter/elapsed); - printf(" Output image size: %d bytes\n", - totaljpegsize); - printf(" Compression ratio: %f:1\n", - (double)(w*h*ps)/(double)totaljpegsize); - printf(" Throughput: %f Megapixels/sec\n", - (double)(w*h)/1000000.*(double)iter/elapsed); - printf(" Output bit stream: %f Megabits/sec\n", - (double)totaljpegsize*8./1000000.*(double)iter/elapsed); - } - if(tilew==w && tileh==h && dowrite) - { - snprintf(tempstr, 1024, "%s_%s_Q%d.jpg", filename, subName[subsamp], - jpegqual); - if((file=fopen(tempstr, "wb"))==NULL) - _throwunix("opening reference image"); - if(fwrite(jpegbuf[0], jpegsize[0], 1, file)!=1) - _throwunix("writing reference image"); - fclose(file); file=NULL; - if(!quiet) printf("Reference image written to %s\n", tempstr); - } - - /* Decompression test */ - if(!componly) - { - if(decomp(srcbuf, jpegbuf, jpegsize, tmpbuf, w, h, subsamp, jpegqual, - filename, tilew, tileh)==-1) - goto bailout; - } - - for(i=0; i<ntilesw*ntilesh; i++) - { - if(jpegbuf[i]) tjFree(jpegbuf[i]); jpegbuf[i]=NULL; - } - free(jpegbuf); jpegbuf=NULL; - free(jpegsize); jpegsize=NULL; - if(doyuv) - { - free(yuvbuf); yuvbuf=NULL; - } - - if(tilew==w && tileh==h) break; - } - - bailout: - if(file) {fclose(file); file=NULL;} - if(jpegbuf) - { - for(i=0; i<ntilesw*ntilesh; i++) - { - if(jpegbuf[i]) tjFree(jpegbuf[i]); jpegbuf[i]=NULL; - } - free(jpegbuf); jpegbuf=NULL; - } - if(yuvbuf) {free(yuvbuf); yuvbuf=NULL;} - if(jpegsize) {free(jpegsize); jpegsize=NULL;} - if(tmpbuf) {free(tmpbuf); tmpbuf=NULL;} - if(handle) {tjDestroy(handle); handle=NULL;} - return retval; + char tempStr[1024], tempStr2[80]; + FILE *file = NULL; + tjhandle handle = NULL; + unsigned char **jpegBuf = NULL, *yuvBuf = NULL, *tmpBuf = NULL, *srcPtr, + *srcPtr2; + double start, elapsed, elapsedEncode; + int totalJpegSize = 0, row, col, i, tilew = w, tileh = h, retval = 0; + int iter, yuvSize = 0; + unsigned long *jpegSize = NULL; + int ps = tjPixelSize[pf]; + int ntilesw = 1, ntilesh = 1, pitch = w * ps; + const char *pfStr = pixFormatStr[pf]; + + if ((tmpBuf = (unsigned char *)malloc(pitch * h)) == NULL) + _throwunix("allocating temporary image buffer"); + + if (!quiet) + printf(">>>>> %s (%s) <--> JPEG %s Q%d <<<<<\n", pfStr, + (flags & TJFLAG_BOTTOMUP) ? "Bottom-up" : "Top-down", + subNameLong[subsamp], jpegQual); + + for (tilew = doTile ? 8 : w, tileh = doTile ? 8 : h; ; + tilew *= 2, tileh *= 2) { + if (tilew > w) tilew = w; + if (tileh > h) tileh = h; + ntilesw = (w + tilew - 1) / tilew; + ntilesh = (h + tileh - 1) / tileh; + + if ((jpegBuf = (unsigned char **)malloc(sizeof(unsigned char *) * + ntilesw * ntilesh)) == NULL) + _throwunix("allocating JPEG tile array"); + memset(jpegBuf, 0, sizeof(unsigned char *) * ntilesw * ntilesh); + if ((jpegSize = (unsigned long *)malloc(sizeof(unsigned long) * + ntilesw * ntilesh)) == NULL) + _throwunix("allocating JPEG size array"); + memset(jpegSize, 0, sizeof(unsigned long) * ntilesw * ntilesh); + + if ((flags & TJFLAG_NOREALLOC) != 0) + for (i = 0; i < ntilesw * ntilesh; i++) { + if ((jpegBuf[i] = (unsigned char *) + tjAlloc(tjBufSize(tilew, tileh, subsamp))) == NULL) + _throwunix("allocating JPEG tiles"); + } + + /* Compression test */ + if (quiet == 1) + printf("%-4s (%s) %-5s %-3d ", pfStr, + (flags & TJFLAG_BOTTOMUP) ? "BU" : "TD", subNameLong[subsamp], + jpegQual); + for (i = 0; i < h; i++) + memcpy(&tmpBuf[pitch * i], &srcBuf[w * ps * i], w * ps); + if ((handle = tjInitCompress()) == NULL) + _throwtj("executing tjInitCompress()"); + + if (doYUV) { + yuvSize = tjBufSizeYUV2(tilew, yuvPad, tileh, subsamp); + if ((yuvBuf = (unsigned char *)malloc(yuvSize)) == NULL) + _throwunix("allocating YUV buffer"); + memset(yuvBuf, 127, yuvSize); + } + + /* Benchmark */ + iter = -1; + elapsed = elapsedEncode = 0.; + while (1) { + int tile = 0; + + totalJpegSize = 0; + start = getTime(); + for (row = 0, srcPtr = srcBuf; row < ntilesh; + row++, srcPtr += pitch * tileh) { + for (col = 0, srcPtr2 = srcPtr; col < ntilesw; + col++, tile++, srcPtr2 += ps * tilew) { + int width = min(tilew, w - col * tilew); + int height = min(tileh, h - row * tileh); + + if (doYUV) { + double startEncode = getTime(); + + if (tjEncodeYUV3(handle, srcPtr2, width, pitch, height, pf, yuvBuf, + yuvPad, subsamp, flags) == -1) + _throwtj("executing tjEncodeYUV3()"); + if (iter >= 0) elapsedEncode += getTime() - startEncode; + if (tjCompressFromYUV(handle, yuvBuf, width, yuvPad, height, + subsamp, &jpegBuf[tile], &jpegSize[tile], + jpegQual, flags) == -1) + _throwtj("executing tjCompressFromYUV()"); + } else { + if (tjCompress2(handle, srcPtr2, width, pitch, height, pf, + &jpegBuf[tile], &jpegSize[tile], subsamp, jpegQual, + flags) == -1) + _throwtj("executing tjCompress2()"); + } + totalJpegSize += jpegSize[tile]; + } + } + elapsed += getTime() - start; + if (iter >= 0) { + iter++; + if (elapsed >= benchTime) break; + } else if (elapsed >= warmup) { + iter = 0; + elapsed = elapsedEncode = 0.; + } + } + if (doYUV) elapsed -= elapsedEncode; + + if (tjDestroy(handle) == -1) _throwtj("executing tjDestroy()"); + handle = NULL; + + if (quiet == 1) printf("%-5d %-5d ", tilew, tileh); + if (quiet) { + if (doYUV) + printf("%-6s%s", + sigfig((double)(w * h) / 1000000. * + (double)iter / elapsedEncode, 4, tempStr, 1024), + quiet == 2 ? "\n" : " "); + printf("%-6s%s", + sigfig((double)(w * h) / 1000000. * (double)iter / elapsed, 4, + tempStr, 1024), + quiet == 2 ? "\n" : " "); + printf("%-6s%s", + sigfig((double)(w * h * ps) / (double)totalJpegSize, 4, tempStr2, + 80), + quiet == 2 ? "\n" : " "); + } else { + printf("\n%s size: %d x %d\n", doTile ? "Tile" : "Image", tilew, tileh); + if (doYUV) { + printf("Encode YUV --> Frame rate: %f fps\n", + (double)iter / elapsedEncode); + printf(" Output image size: %d bytes\n", yuvSize); + printf(" Compression ratio: %f:1\n", + (double)(w * h * ps) / (double)yuvSize); + printf(" Throughput: %f Megapixels/sec\n", + (double)(w * h) / 1000000. * (double)iter / elapsedEncode); + printf(" Output bit stream: %f Megabits/sec\n", + (double)yuvSize * 8. / 1000000. * (double)iter / elapsedEncode); + } + printf("%s --> Frame rate: %f fps\n", + doYUV ? "Comp from YUV" : "Compress ", + (double)iter / elapsed); + printf(" Output image size: %d bytes\n", + totalJpegSize); + printf(" Compression ratio: %f:1\n", + (double)(w * h * ps) / (double)totalJpegSize); + printf(" Throughput: %f Megapixels/sec\n", + (double)(w * h) / 1000000. * (double)iter / elapsed); + printf(" Output bit stream: %f Megabits/sec\n", + (double)totalJpegSize * 8. / 1000000. * (double)iter / elapsed); + } + if (tilew == w && tileh == h && doWrite) { + snprintf(tempStr, 1024, "%s_%s_Q%d.jpg", fileName, subName[subsamp], + jpegQual); + if ((file = fopen(tempStr, "wb")) == NULL) + _throwunix("opening reference image"); + if (fwrite(jpegBuf[0], jpegSize[0], 1, file) != 1) + _throwunix("writing reference image"); + fclose(file); file = NULL; + if (!quiet) printf("Reference image written to %s\n", tempStr); + } + + /* Decompression test */ + if (!compOnly) { + if (decomp(srcBuf, jpegBuf, jpegSize, tmpBuf, w, h, subsamp, jpegQual, + fileName, tilew, tileh) == -1) + goto bailout; + } + + for (i = 0; i < ntilesw * ntilesh; i++) { + if (jpegBuf[i]) tjFree(jpegBuf[i]); + jpegBuf[i] = NULL; + } + free(jpegBuf); jpegBuf = NULL; + free(jpegSize); jpegSize = NULL; + if (doYUV) { + free(yuvBuf); yuvBuf = NULL; + } + + if (tilew == w && tileh == h) break; + } + +bailout: + if (file) { fclose(file); file = NULL; } + if (jpegBuf) { + for (i = 0; i < ntilesw * ntilesh; i++) { + if (jpegBuf[i]) tjFree(jpegBuf[i]); + jpegBuf[i] = NULL; + } + free(jpegBuf); jpegBuf = NULL; + } + if (yuvBuf) { free(yuvBuf); yuvBuf = NULL; } + if (jpegSize) { free(jpegSize); jpegSize = NULL; } + if (tmpBuf) { free(tmpBuf); tmpBuf = NULL; } + if (handle) { tjDestroy(handle); handle = NULL; } + return retval; } -int decompTest(char *filename) +int decompTest(char *fileName) { - FILE *file=NULL; tjhandle handle=NULL; - unsigned char **jpegbuf=NULL, *srcbuf=NULL; - unsigned long *jpegsize=NULL, srcsize, totaljpegsize; - tjtransform *t=NULL; - int w=0, h=0, subsamp=-1, cs=-1, _w, _h, _tilew, _tileh, - _ntilesw, _ntilesh, _subsamp; - char *temp=NULL, tempstr[80], tempstr2[80]; - int row, col, i, iter, tilew, tileh, ntilesw=1, ntilesh=1, retval=0; - double start, elapsed; - int ps=tjPixelSize[pf], tile; - - if((file=fopen(filename, "rb"))==NULL) - _throwunix("opening file"); - if(fseek(file, 0, SEEK_END)<0 || (srcsize=ftell(file))==(unsigned long)-1) - _throwunix("determining file size"); - if((srcbuf=(unsigned char *)malloc(srcsize))==NULL) - _throwunix("allocating memory"); - if(fseek(file, 0, SEEK_SET)<0) - _throwunix("setting file position"); - if(fread(srcbuf, srcsize, 1, file)<1) - _throwunix("reading JPEG data"); - fclose(file); file=NULL; - - temp=strrchr(filename, '.'); - if(temp!=NULL) *temp='\0'; - - if((handle=tjInitTransform())==NULL) - _throwtj("executing tjInitTransform()"); - if(tjDecompressHeader3(handle, srcbuf, srcsize, &w, &h, &subsamp, &cs)==-1) - _throwtj("executing tjDecompressHeader3()"); - if(cs==TJCS_YCCK || cs==TJCS_CMYK) - { - pf=TJPF_CMYK; ps=tjPixelSize[pf]; - } - - if(quiet==1) - { - printf("All performance values in Mpixels/sec\n\n"); - printf("Bitmap JPEG JPEG %s %s Xform Comp Decomp ", - dotile? "Tile ":"Image", dotile? "Tile ":"Image"); - if(doyuv) printf("Decode"); - printf("\n"); - printf("Format CS Subsamp Width Height Perf Ratio Perf "); - if(doyuv) printf("Perf"); - printf("\n\n"); - } - else if(!quiet) - printf(">>>>> JPEG %s --> %s (%s) <<<<<\n", - formatName(subsamp, cs, tempstr), pixFormatStr[pf], - (flags&TJFLAG_BOTTOMUP)? "Bottom-up":"Top-down"); - - for(tilew=dotile? 16:w, tileh=dotile? 16:h; ; tilew*=2, tileh*=2) - { - if(tilew>w) tilew=w; if(tileh>h) tileh=h; - ntilesw=(w+tilew-1)/tilew; ntilesh=(h+tileh-1)/tileh; - - if((jpegbuf=(unsigned char **)malloc(sizeof(unsigned char *) - *ntilesw*ntilesh))==NULL) - _throwunix("allocating JPEG tile array"); - memset(jpegbuf, 0, sizeof(unsigned char *)*ntilesw*ntilesh); - if((jpegsize=(unsigned long *)malloc(sizeof(unsigned long) - *ntilesw*ntilesh))==NULL) - _throwunix("allocating JPEG size array"); - memset(jpegsize, 0, sizeof(unsigned long)*ntilesw*ntilesh); - - if((flags&TJFLAG_NOREALLOC)!=0 || !dotile) - for(i=0; i<ntilesw*ntilesh; i++) - { - if((jpegbuf[i]=(unsigned char *)tjAlloc(tjBufSize(tilew, tileh, - subsamp)))==NULL) - _throwunix("allocating JPEG tiles"); - } - - _w=w; _h=h; _tilew=tilew; _tileh=tileh; - if(!quiet) - { - printf("\n%s size: %d x %d", dotile? "Tile":"Image", _tilew, - _tileh); - if(sf.num!=1 || sf.denom!=1) - printf(" --> %d x %d", TJSCALED(_w, sf), TJSCALED(_h, sf)); - printf("\n"); - } - else if(quiet==1) - { - printf("%-4s (%s) %-5s %-5s ", pixFormatStr[pf], - (flags&TJFLAG_BOTTOMUP)? "BU":"TD", csName[cs], subNameLong[subsamp]); - printf("%-5d %-5d ", tilew, tileh); - } - - _subsamp=subsamp; - if(dotile || xformop!=TJXOP_NONE || xformopt!=0 || customFilter) - { - if((t=(tjtransform *)malloc(sizeof(tjtransform)*ntilesw*ntilesh)) - ==NULL) - _throwunix("allocating image transform array"); - - if(xformop==TJXOP_TRANSPOSE || xformop==TJXOP_TRANSVERSE - || xformop==TJXOP_ROT90 || xformop==TJXOP_ROT270) - { - _w=h; _h=w; _tilew=tileh; _tileh=tilew; - } - - if(xformopt&TJXOPT_GRAY) _subsamp=TJ_GRAYSCALE; - if(xformop==TJXOP_HFLIP || xformop==TJXOP_ROT180) - _w=_w-(_w%tjMCUWidth[_subsamp]); - if(xformop==TJXOP_VFLIP || xformop==TJXOP_ROT180) - _h=_h-(_h%tjMCUHeight[_subsamp]); - if(xformop==TJXOP_TRANSVERSE || xformop==TJXOP_ROT90) - _w=_w-(_w%tjMCUHeight[_subsamp]); - if(xformop==TJXOP_TRANSVERSE || xformop==TJXOP_ROT270) - _h=_h-(_h%tjMCUWidth[_subsamp]); - _ntilesw=(_w+_tilew-1)/_tilew; - _ntilesh=(_h+_tileh-1)/_tileh; - - if(xformop==TJXOP_TRANSPOSE || xformop==TJXOP_TRANSVERSE - || xformop==TJXOP_ROT90 || xformop==TJXOP_ROT270) - { - if(_subsamp==TJSAMP_422) _subsamp=TJSAMP_440; - else if(_subsamp==TJSAMP_440) _subsamp=TJSAMP_422; - } - - for(row=0, tile=0; row<_ntilesh; row++) - { - for(col=0; col<_ntilesw; col++, tile++) - { - t[tile].r.w=min(_tilew, _w-col*_tilew); - t[tile].r.h=min(_tileh, _h-row*_tileh); - t[tile].r.x=col*_tilew; - t[tile].r.y=row*_tileh; - t[tile].op=xformop; - t[tile].options=xformopt|TJXOPT_TRIM; - t[tile].customFilter=customFilter; - if(t[tile].options&TJXOPT_NOOUTPUT && jpegbuf[tile]) - { - tjFree(jpegbuf[tile]); jpegbuf[tile]=NULL; - } - } - } - - iter=-warmup; - elapsed=0.; - while(1) - { - start=gettime(); - if(tjTransform(handle, srcbuf, srcsize, _ntilesw*_ntilesh, jpegbuf, - jpegsize, t, flags)==-1) - _throwtj("executing tjTransform()"); - iter++; - if(iter>=1) - { - elapsed+=gettime()-start; - if(elapsed>=benchtime) break; - } - } - - free(t); t=NULL; - - for(tile=0, totaljpegsize=0; tile<_ntilesw*_ntilesh; tile++) - totaljpegsize+=jpegsize[tile]; - - if(quiet) - { - printf("%-6s%s%-6s%s", - sigfig((double)(w*h)/1000000./elapsed, 4, tempstr, 80), - quiet==2? "\n":" ", - sigfig((double)(w*h*ps)/(double)totaljpegsize, 4, tempstr2, 80), - quiet==2? "\n":" "); - } - else if(!quiet) - { - printf("Transform --> Frame rate: %f fps\n", 1.0/elapsed); - printf(" Output image size: %lu bytes\n", totaljpegsize); - printf(" Compression ratio: %f:1\n", - (double)(w*h*ps)/(double)totaljpegsize); - printf(" Throughput: %f Megapixels/sec\n", - (double)(w*h)/1000000./elapsed); - printf(" Output bit stream: %f Megabits/sec\n", - (double)totaljpegsize*8./1000000./elapsed); - } - } - else - { - if(quiet==1) printf("N/A N/A "); - jpegsize[0]=srcsize; - memcpy(jpegbuf[0], srcbuf, srcsize); - } - - if(w==tilew) _tilew=_w; - if(h==tileh) _tileh=_h; - if(!(xformopt&TJXOPT_NOOUTPUT)) - { - if(decomp(NULL, jpegbuf, jpegsize, NULL, _w, _h, _subsamp, 0, - filename, _tilew, _tileh)==-1) - goto bailout; - } - else if(quiet==1) printf("N/A\n"); - - for(i=0; i<ntilesw*ntilesh; i++) - { - tjFree(jpegbuf[i]); jpegbuf[i]=NULL; - } - free(jpegbuf); jpegbuf=NULL; - if(jpegsize) {free(jpegsize); jpegsize=NULL;} - - if(tilew==w && tileh==h) break; - } - - bailout: - if(file) {fclose(file); file=NULL;} - if(jpegbuf) - { - for(i=0; i<ntilesw*ntilesh; i++) - { - if(jpegbuf[i]) tjFree(jpegbuf[i]); jpegbuf[i]=NULL; - } - free(jpegbuf); jpegbuf=NULL; - } - if(jpegsize) {free(jpegsize); jpegsize=NULL;} - if(srcbuf) {free(srcbuf); srcbuf=NULL;} - if(t) {free(t); t=NULL;} - if(handle) {tjDestroy(handle); handle=NULL;} - return retval; + FILE *file = NULL; + tjhandle handle = NULL; + unsigned char **jpegBuf = NULL, *srcBuf = NULL; + unsigned long *jpegSize = NULL, srcSize, totalJpegSize; + tjtransform *t = NULL; + double start, elapsed; + int ps = tjPixelSize[pf], tile, row, col, i, iter, retval = 0, decompsrc = 0; + char *temp = NULL, tempStr[80], tempStr2[80]; + /* Original image */ + int w = 0, h = 0, tilew, tileh, ntilesw = 1, ntilesh = 1, subsamp = -1, + cs = -1; + /* Transformed image */ + int tw, th, ttilew, ttileh, tntilesw, tntilesh, tsubsamp; + + if ((file = fopen(fileName, "rb")) == NULL) + _throwunix("opening file"); + if (fseek(file, 0, SEEK_END) < 0 || + (srcSize = ftell(file)) == (unsigned long)-1) + _throwunix("determining file size"); + if ((srcBuf = (unsigned char *)malloc(srcSize)) == NULL) + _throwunix("allocating memory"); + if (fseek(file, 0, SEEK_SET) < 0) + _throwunix("setting file position"); + if (fread(srcBuf, srcSize, 1, file) < 1) + _throwunix("reading JPEG data"); + fclose(file); file = NULL; + + temp = strrchr(fileName, '.'); + if (temp != NULL) *temp = '\0'; + + if ((handle = tjInitTransform()) == NULL) + _throwtj("executing tjInitTransform()"); + if (tjDecompressHeader3(handle, srcBuf, srcSize, &w, &h, &subsamp, + &cs) == -1) + _throwtj("executing tjDecompressHeader3()"); + if (cs == TJCS_YCCK || cs == TJCS_CMYK) { + pf = TJPF_CMYK; ps = tjPixelSize[pf]; + } + + if (quiet == 1) { + printf("All performance values in Mpixels/sec\n\n"); + printf("Bitmap JPEG JPEG %s %s Xform Comp Decomp ", + doTile ? "Tile " : "Image", doTile ? "Tile " : "Image"); + if (doYUV) printf("Decode"); + printf("\n"); + printf("Format CS Subsamp Width Height Perf Ratio Perf "); + if (doYUV) printf("Perf"); + printf("\n\n"); + } else if (!quiet) + printf(">>>>> JPEG %s --> %s (%s) <<<<<\n", + formatName(subsamp, cs, tempStr), pixFormatStr[pf], + (flags & TJFLAG_BOTTOMUP) ? "Bottom-up" : "Top-down"); + + for (tilew = doTile ? 16 : w, tileh = doTile ? 16 : h; ; + tilew *= 2, tileh *= 2) { + if (tilew > w) tilew = w; + if (tileh > h) tileh = h; + ntilesw = (w + tilew - 1) / tilew; + ntilesh = (h + tileh - 1) / tileh; + + if ((jpegBuf = (unsigned char **)malloc(sizeof(unsigned char *) * + ntilesw * ntilesh)) == NULL) + _throwunix("allocating JPEG tile array"); + memset(jpegBuf, 0, sizeof(unsigned char *) * ntilesw * ntilesh); + if ((jpegSize = (unsigned long *)malloc(sizeof(unsigned long) * + ntilesw * ntilesh)) == NULL) + _throwunix("allocating JPEG size array"); + memset(jpegSize, 0, sizeof(unsigned long) * ntilesw * ntilesh); + + if ((flags & TJFLAG_NOREALLOC) != 0 || !doTile) + for (i = 0; i < ntilesw * ntilesh; i++) { + if ((jpegBuf[i] = (unsigned char *) + tjAlloc(tjBufSize(tilew, tileh, subsamp))) == NULL) + _throwunix("allocating JPEG tiles"); + } + + tw = w; th = h; ttilew = tilew; ttileh = tileh; + if (!quiet) { + printf("\n%s size: %d x %d", doTile ? "Tile" : "Image", ttilew, ttileh); + if (sf.num != 1 || sf.denom != 1) + printf(" --> %d x %d", TJSCALED(tw, sf), TJSCALED(th, sf)); + printf("\n"); + } else if (quiet == 1) { + printf("%-4s (%s) %-5s %-5s ", pixFormatStr[pf], + (flags & TJFLAG_BOTTOMUP) ? "BU" : "TD", csName[cs], + subNameLong[subsamp]); + printf("%-5d %-5d ", tilew, tileh); + } + + tsubsamp = subsamp; + if (doTile || xformOp != TJXOP_NONE || xformOpt != 0 || customFilter) { + if ((t = (tjtransform *)malloc(sizeof(tjtransform) * ntilesw * + ntilesh)) == NULL) + _throwunix("allocating image transform array"); + + if (xformOp == TJXOP_TRANSPOSE || xformOp == TJXOP_TRANSVERSE || + xformOp == TJXOP_ROT90 || xformOp == TJXOP_ROT270) { + tw = h; th = w; ttilew = tileh; ttileh = tilew; + } + + if (xformOpt & TJXOPT_GRAY) tsubsamp = TJ_GRAYSCALE; + if (xformOp == TJXOP_HFLIP || xformOp == TJXOP_ROT180) + tw = tw - (tw % tjMCUWidth[tsubsamp]); + if (xformOp == TJXOP_VFLIP || xformOp == TJXOP_ROT180) + th = th - (th % tjMCUHeight[tsubsamp]); + if (xformOp == TJXOP_TRANSVERSE || xformOp == TJXOP_ROT90) + tw = tw - (tw % tjMCUHeight[tsubsamp]); + if (xformOp == TJXOP_TRANSVERSE || xformOp == TJXOP_ROT270) + th = th - (th % tjMCUWidth[tsubsamp]); + tntilesw = (tw + ttilew - 1) / ttilew; + tntilesh = (th + ttileh - 1) / ttileh; + + if (xformOp == TJXOP_TRANSPOSE || xformOp == TJXOP_TRANSVERSE || + xformOp == TJXOP_ROT90 || xformOp == TJXOP_ROT270) { + if (tsubsamp == TJSAMP_422) tsubsamp = TJSAMP_440; + else if (tsubsamp == TJSAMP_440) tsubsamp = TJSAMP_422; + } + + for (row = 0, tile = 0; row < tntilesh; row++) { + for (col = 0; col < tntilesw; col++, tile++) { + t[tile].r.w = min(ttilew, tw - col * ttilew); + t[tile].r.h = min(ttileh, th - row * ttileh); + t[tile].r.x = col * ttilew; + t[tile].r.y = row * ttileh; + t[tile].op = xformOp; + t[tile].options = xformOpt | TJXOPT_TRIM; + t[tile].customFilter = customFilter; + if (t[tile].options & TJXOPT_NOOUTPUT && jpegBuf[tile]) { + tjFree(jpegBuf[tile]); jpegBuf[tile] = NULL; + } + } + } + + iter = -1; + elapsed = 0.; + while (1) { + start = getTime(); + if (tjTransform(handle, srcBuf, srcSize, tntilesw * tntilesh, jpegBuf, + jpegSize, t, flags) == -1) + _throwtj("executing tjTransform()"); + elapsed += getTime() - start; + if (iter >= 0) { + iter++; + if (elapsed >= benchTime) break; + } else if (elapsed >= warmup) { + iter = 0; + elapsed = 0.; + } + } + + free(t); t = NULL; + + for (tile = 0, totalJpegSize = 0; tile < tntilesw * tntilesh; tile++) + totalJpegSize += jpegSize[tile]; + + if (quiet) { + printf("%-6s%s%-6s%s", + sigfig((double)(w * h) / 1000000. / elapsed, 4, tempStr, 80), + quiet == 2 ? "\n" : " ", + sigfig((double)(w * h * ps) / (double)totalJpegSize, 4, + tempStr2, 80), + quiet == 2 ? "\n" : " "); + } else if (!quiet) { + printf("Transform --> Frame rate: %f fps\n", + 1.0 / elapsed); + printf(" Output image size: %lu bytes\n", + totalJpegSize); + printf(" Compression ratio: %f:1\n", + (double)(w * h * ps) / (double)totalJpegSize); + printf(" Throughput: %f Megapixels/sec\n", + (double)(w * h) / 1000000. / elapsed); + printf(" Output bit stream: %f Megabits/sec\n", + (double)totalJpegSize * 8. / 1000000. / elapsed); + } + } else { + if (quiet == 1) printf("N/A N/A "); + tjFree(jpegBuf[0]); + jpegBuf[0] = NULL; + decompsrc = 1; + } + + if (w == tilew) ttilew = tw; + if (h == tileh) ttileh = th; + if (!(xformOpt & TJXOPT_NOOUTPUT)) { + if (decomp(NULL, decompsrc ? &srcBuf : jpegBuf, + decompsrc ? &srcSize : jpegSize, NULL, tw, th, tsubsamp, 0, + fileName, ttilew, ttileh) == -1) + goto bailout; + } else if (quiet == 1) printf("N/A\n"); + + for (i = 0; i < ntilesw * ntilesh; i++) { + tjFree(jpegBuf[i]); jpegBuf[i] = NULL; + } + free(jpegBuf); jpegBuf = NULL; + if (jpegSize) { free(jpegSize); jpegSize = NULL; } + + if (tilew == w && tileh == h) break; + } + +bailout: + if (file) { fclose(file); file = NULL; } + if (jpegBuf) { + for (i = 0; i < ntilesw * ntilesh; i++) { + if (jpegBuf[i]) tjFree(jpegBuf[i]); + jpegBuf[i] = NULL; + } + free(jpegBuf); jpegBuf = NULL; + } + if (jpegSize) { free(jpegSize); jpegSize = NULL; } + if (srcBuf) { free(srcBuf); srcBuf = NULL; } + if (t) { free(t); t = NULL; } + if (handle) { tjDestroy(handle); handle = NULL; } + return retval; } -void usage(char *progname) +void usage(char *progName) { - int i; - printf("USAGE: %s\n", progname); - printf(" <Inputfile (BMP|PPM)> <Quality> [options]\n\n"); - printf(" %s\n", progname); - printf(" <Inputfile (JPG)> [options]\n\n"); - printf("Options:\n\n"); - printf("-alloc = Dynamically allocate JPEG image buffers\n"); - printf("-bmp = Generate output images in Windows Bitmap format (default = PPM)\n"); - printf("-bottomup = Test bottom-up compression/decompression\n"); - printf("-tile = Test performance of the codec when the image is encoded as separate\n"); - printf(" tiles of varying sizes.\n"); - printf("-rgb, -bgr, -rgbx, -bgrx, -xbgr, -xrgb =\n"); - printf(" Test the specified color conversion path in the codec (default = BGR)\n"); - printf("-cmyk = Indirectly test YCCK JPEG compression/decompression (the source\n"); - printf(" and destination bitmaps are still RGB. The conversion is done\n"); - printf(" internally prior to compression or after decompression.)\n"); - printf("-fastupsample = Use the fastest chrominance upsampling algorithm available in\n"); - printf(" the underlying codec\n"); - printf("-fastdct = Use the fastest DCT/IDCT algorithms available in the underlying\n"); - printf(" codec\n"); - printf("-accuratedct = Use the most accurate DCT/IDCT algorithms available in the\n"); - printf(" underlying codec\n"); - printf("-subsamp <s> = When testing JPEG compression, this option specifies the level\n"); - printf(" of chrominance subsampling to use (<s> = 444, 422, 440, 420, 411, or\n"); - printf(" GRAY). The default is to test Grayscale, 4:2:0, 4:2:2, and 4:4:4 in\n"); - printf(" sequence.\n"); - printf("-quiet = Output results in tabular rather than verbose format\n"); - printf("-yuv = Test YUV encoding/decoding functions\n"); - printf("-yuvpad <p> = If testing YUV encoding/decoding, this specifies the number of\n"); - printf(" bytes to which each row of each plane in the intermediate YUV image is\n"); - printf(" padded (default = 1)\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", scalingfactors[i].num, scalingfactors[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 "); - } - if(i%8==0 && i!=0) printf("\n "); - } - printf(")\n"); - printf("-hflip, -vflip, -transpose, -transverse, -rot90, -rot180, -rot270 =\n"); - printf(" Perform the corresponding lossless transform prior to\n"); - printf(" decompression (these options are mutually exclusive)\n"); - printf("-grayscale = Perform lossless grayscale conversion prior to decompression\n"); - printf(" test (can be combined with the other transforms above)\n"); - printf("-benchtime <t> = Run each benchmark for at least <t> seconds (default = 5.0)\n"); - printf("-warmup <w> = Execute each benchmark <w> times to prime the cache before\n"); - printf(" taking performance measurements (default = 1)\n"); - printf("-componly = Stop after running compression tests. Do not test decompression.\n"); - printf("-nowrite = Do not write reference or output images (improves consistency of\n"); - printf(" performance measurements.)\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); + int i; + + printf("USAGE: %s\n", progName); + printf(" <Inputfile (BMP|PPM)> <Quality> [options]\n\n"); + printf(" %s\n", progName); + printf(" <Inputfile (JPG)> [options]\n\n"); + printf("Options:\n\n"); + printf("-alloc = Dynamically allocate JPEG image buffers\n"); + printf("-bmp = Generate output images in Windows Bitmap format (default = PPM)\n"); + printf("-bottomup = Test bottom-up compression/decompression\n"); + printf("-tile = Test performance of the codec when the image is encoded as separate\n"); + printf(" tiles of varying sizes.\n"); + printf("-rgb, -bgr, -rgbx, -bgrx, -xbgr, -xrgb =\n"); + printf(" Test the specified color conversion path in the codec (default = BGR)\n"); + printf("-cmyk = Indirectly test YCCK JPEG compression/decompression (the source\n"); + printf(" and destination bitmaps are still RGB. The conversion is done\n"); + printf(" internally prior to compression or after decompression.)\n"); + printf("-fastupsample = Use the fastest chrominance upsampling algorithm available in\n"); + printf(" the underlying codec\n"); + printf("-fastdct = Use the fastest DCT/IDCT algorithms available in the underlying\n"); + printf(" codec\n"); + printf("-accuratedct = Use the most accurate DCT/IDCT algorithms available in the\n"); + printf(" underlying codec\n"); + printf("-progressive = Use progressive entropy coding in JPEG images generated by\n"); + printf(" compression and transform operations.\n"); + printf("-subsamp <s> = When testing JPEG compression, this option specifies the level\n"); + printf(" of chrominance subsampling to use (<s> = 444, 422, 440, 420, 411, or\n"); + printf(" GRAY). The default is to test Grayscale, 4:2:0, 4:2:2, and 4:4:4 in\n"); + printf(" sequence.\n"); + printf("-quiet = Output results in tabular rather than verbose format\n"); + printf("-yuv = Test YUV encoding/decoding functions\n"); + printf("-yuvpad <p> = If testing YUV encoding/decoding, this specifies the number of\n"); + printf(" bytes to which each row of each plane in the intermediate YUV image is\n"); + printf(" padded (default = 1)\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", scalingFactors[i].num, scalingFactors[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 "); + } + if (i % 8 == 0 && i != 0) printf("\n "); + } + printf(")\n"); + printf("-hflip, -vflip, -transpose, -transverse, -rot90, -rot180, -rot270 =\n"); + printf(" Perform the corresponding lossless transform prior to\n"); + printf(" decompression (these options are mutually exclusive)\n"); + printf("-grayscale = Perform lossless grayscale conversion prior to decompression\n"); + printf(" test (can be combined with the other transforms above)\n"); + printf("-copynone = Do not copy any extra markers (including EXIF and ICC profile data)\n"); + printf(" when transforming the image.\n"); + printf("-benchtime <t> = Run each benchmark for at least <t> seconds (default = 5.0)\n"); + printf("-warmup <t> = Run each benchmark for <t> seconds (default = 1.0) prior to\n"); + printf(" starting the timer, in order to prime the caches and thus improve the\n"); + printf(" consistency of the results.\n"); + printf("-componly = Stop after running compression tests. Do not test decompression.\n"); + printf("-nowrite = Do not write reference or output images (improves consistency of\n"); + printf(" performance measurements.)\n"); + printf("-stoponwarning = Immediately discontinue the current\n"); + printf(" compression/decompression/transform operation if the underlying codec\n"); + printf(" throws a warning (non-fatal error)\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); } int main(int argc, char *argv[]) { - unsigned char *srcbuf=NULL; int w=0, h=0, i, j; - int minqual=-1, maxqual=-1; char *temp; - int minarg=2, retval=0, subsamp=-1; - - if((scalingfactors=tjGetScalingFactors(&nsf))==NULL || nsf==0) - _throwtj("executing tjGetScalingFactors()"); - - if(argc<minarg) usage(argv[0]); - - temp=strrchr(argv[1], '.'); - if(temp!=NULL) - { - if(!strcasecmp(temp, ".bmp")) ext="bmp"; - if(!strcasecmp(temp, ".jpg") || !strcasecmp(temp, ".jpeg")) decomponly=1; - } - - printf("\n"); - - if(!decomponly) - { - minarg=3; - if(argc<minarg) usage(argv[0]); - if((minqual=atoi(argv[2]))<1 || minqual>100) - { - puts("ERROR: Quality must be between 1 and 100."); - exit(1); - } - if((temp=strchr(argv[2], '-'))!=NULL && strlen(temp)>1 - && sscanf(&temp[1], "%d", &maxqual)==1 && maxqual>minqual && maxqual>=1 - && maxqual<=100) {} - else maxqual=minqual; - } - - if(argc>minarg) - { - for(i=minarg; i<argc; i++) - { - if(!strcasecmp(argv[i], "-tile")) - { - dotile=1; xformopt|=TJXOPT_CROP; - } - if(!strcasecmp(argv[i], "-fastupsample")) - { - printf("Using fast upsampling code\n\n"); - flags|=TJFLAG_FASTUPSAMPLE; - } - if(!strcasecmp(argv[i], "-fastdct")) - { - printf("Using fastest DCT/IDCT algorithm\n\n"); - flags|=TJFLAG_FASTDCT; - } - if(!strcasecmp(argv[i], "-accuratedct")) - { - printf("Using most accurate DCT/IDCT algorithm\n\n"); - flags|=TJFLAG_ACCURATEDCT; - } - if(!strcasecmp(argv[i], "-rgb")) pf=TJPF_RGB; - if(!strcasecmp(argv[i], "-rgbx")) pf=TJPF_RGBX; - if(!strcasecmp(argv[i], "-bgr")) pf=TJPF_BGR; - if(!strcasecmp(argv[i], "-bgrx")) pf=TJPF_BGRX; - if(!strcasecmp(argv[i], "-xbgr")) pf=TJPF_XBGR; - if(!strcasecmp(argv[i], "-xrgb")) pf=TJPF_XRGB; - if(!strcasecmp(argv[i], "-cmyk")) pf=TJPF_CMYK; - if(!strcasecmp(argv[i], "-bottomup")) flags|=TJFLAG_BOTTOMUP; - if(!strcasecmp(argv[i], "-quiet")) quiet=1; - if(!strcasecmp(argv[i], "-qq")) quiet=2; - if(!strcasecmp(argv[i], "-scale") && i<argc-1) - { - int temp1=0, temp2=0, match=0; - if(sscanf(argv[++i], "%d/%d", &temp1, &temp2)==2) - { - for(j=0; j<nsf; j++) - { - if((double)temp1/(double)temp2 - == (double)scalingfactors[j].num/(double)scalingfactors[j].denom) - { - sf=scalingfactors[j]; - match=1; break; - } - } - if(!match) usage(argv[0]); - } - else usage(argv[0]); - } - if(!strcasecmp(argv[i], "-hflip")) xformop=TJXOP_HFLIP; - if(!strcasecmp(argv[i], "-vflip")) xformop=TJXOP_VFLIP; - if(!strcasecmp(argv[i], "-transpose")) xformop=TJXOP_TRANSPOSE; - if(!strcasecmp(argv[i], "-transverse")) xformop=TJXOP_TRANSVERSE; - if(!strcasecmp(argv[i], "-rot90")) xformop=TJXOP_ROT90; - if(!strcasecmp(argv[i], "-rot180")) xformop=TJXOP_ROT180; - if(!strcasecmp(argv[i], "-rot270")) xformop=TJXOP_ROT270; - if(!strcasecmp(argv[i], "-grayscale")) xformopt|=TJXOPT_GRAY; - if(!strcasecmp(argv[i], "-custom")) customFilter=dummyDCTFilter; - if(!strcasecmp(argv[i], "-nooutput")) xformopt|=TJXOPT_NOOUTPUT; - if(!strcasecmp(argv[i], "-benchtime") && i<argc-1) - { - double temp=atof(argv[++i]); - if(temp>0.0) benchtime=temp; - else usage(argv[0]); - } - if(!strcasecmp(argv[i], "-warmup") && i<argc-1) - { - int temp=atoi(argv[++i]); - if(temp>=0) - { - warmup=temp; - printf("Warmup runs = %d\n\n", warmup); - } - else usage(argv[0]); - } - if(!strcmp(argv[i], "-?")) usage(argv[0]); - if(!strcasecmp(argv[i], "-alloc")) flags&=(~TJFLAG_NOREALLOC); - if(!strcasecmp(argv[i], "-bmp")) ext="bmp"; - if(!strcasecmp(argv[i], "-yuv")) - { - printf("Testing YUV planar encoding/decoding\n\n"); - doyuv=1; - } - if(!strcasecmp(argv[i], "-yuvpad") && i<argc-1) - { - int temp=atoi(argv[++i]); - if(temp>=1) yuvpad=temp; - } - if(!strcasecmp(argv[i], "-subsamp") && i<argc-1) - { - i++; - if(toupper(argv[i][0])=='G') subsamp=TJSAMP_GRAY; - else - { - int temp=atoi(argv[i]); - switch(temp) - { - case 444: subsamp=TJSAMP_444; break; - case 422: subsamp=TJSAMP_422; break; - case 440: subsamp=TJSAMP_440; break; - case 420: subsamp=TJSAMP_420; break; - case 411: subsamp=TJSAMP_411; break; - } - } - } - if(!strcasecmp(argv[i], "-componly")) componly=1; - if(!strcasecmp(argv[i], "-nowrite")) dowrite=0; - } - } - - if((sf.num!=1 || sf.denom!=1) && dotile) - { - printf("Disabling tiled compression/decompression tests, because those tests do not\n"); - printf("work when scaled decompression is enabled.\n"); - dotile=0; - } - - if((flags&TJFLAG_NOREALLOC)==0 && dotile) - { - printf("Disabling tiled compression/decompression tests, because those tests do not\n"); - printf("work when dynamic JPEG buffer allocation is enabled.\n\n"); - dotile=0; - } - - if(!decomponly) - { - if(loadbmp(argv[1], &srcbuf, &w, &h, pf, (flags&TJFLAG_BOTTOMUP)!=0)==-1) - _throwbmp("loading bitmap"); - temp=strrchr(argv[1], '.'); - if(temp!=NULL) *temp='\0'; - } - - if(quiet==1 && !decomponly) - { - printf("All performance values in Mpixels/sec\n\n"); - printf("Bitmap JPEG JPEG %s %s ", - dotile? "Tile ":"Image", dotile? "Tile ":"Image"); - if(doyuv) printf("Encode "); - printf("Comp Comp Decomp "); - if(doyuv) printf("Decode"); - printf("\n"); - printf("Format Subsamp Qual Width Height "); - if(doyuv) printf("Perf "); - printf("Perf Ratio Perf "); - if(doyuv) printf("Perf"); - printf("\n\n"); - } - - if(decomponly) - { - decompTest(argv[1]); - printf("\n"); - goto bailout; - } - if(subsamp>=0 && subsamp<TJ_NUMSAMP) - { - for(i=maxqual; i>=minqual; i--) - fullTest(srcbuf, w, h, subsamp, i, argv[1]); - printf("\n"); - } - else - { - if(pf!=TJPF_CMYK) - { - for(i=maxqual; i>=minqual; i--) - fullTest(srcbuf, w, h, TJSAMP_GRAY, i, argv[1]); - printf("\n"); - } - for(i=maxqual; i>=minqual; i--) - fullTest(srcbuf, w, h, TJSAMP_420, i, argv[1]); - printf("\n"); - for(i=maxqual; i>=minqual; i--) - fullTest(srcbuf, w, h, TJSAMP_422, i, argv[1]); - printf("\n"); - for(i=maxqual; i>=minqual; i--) - fullTest(srcbuf, w, h, TJSAMP_444, i, argv[1]); - printf("\n"); - } - - bailout: - if(srcbuf) free(srcbuf); - return retval; + unsigned char *srcBuf = NULL; + int w = 0, h = 0, i, j, minQual = -1, maxQual = -1; + char *temp; + int minArg = 2, retval = 0, subsamp = -1; + + if ((scalingFactors = tjGetScalingFactors(&nsf)) == NULL || nsf == 0) + _throw("executing tjGetScalingFactors()", tjGetErrorStr()); + + if (argc < minArg) usage(argv[0]); + + temp = strrchr(argv[1], '.'); + if (temp != NULL) { + if (!strcasecmp(temp, ".bmp")) ext = "bmp"; + if (!strcasecmp(temp, ".jpg") || !strcasecmp(temp, ".jpeg")) + decompOnly = 1; + } + + printf("\n"); + + if (!decompOnly) { + minArg = 3; + if (argc < minArg) usage(argv[0]); + if ((minQual = atoi(argv[2])) < 1 || minQual > 100) { + puts("ERROR: Quality must be between 1 and 100."); + exit(1); + } + if ((temp = strchr(argv[2], '-')) != NULL && strlen(temp) > 1 && + sscanf(&temp[1], "%d", &maxQual) == 1 && maxQual > minQual && + maxQual >= 1 && maxQual <= 100) {} + else maxQual = minQual; + } + + if (argc > minArg) { + for (i = minArg; i < argc; i++) { + if (!strcasecmp(argv[i], "-tile")) { + doTile = 1; xformOpt |= TJXOPT_CROP; + } else if (!strcasecmp(argv[i], "-fastupsample")) { + printf("Using fast upsampling code\n\n"); + flags |= TJFLAG_FASTUPSAMPLE; + } else if (!strcasecmp(argv[i], "-fastdct")) { + printf("Using fastest DCT/IDCT algorithm\n\n"); + flags |= TJFLAG_FASTDCT; + } else if (!strcasecmp(argv[i], "-accuratedct")) { + printf("Using most accurate DCT/IDCT algorithm\n\n"); + flags |= TJFLAG_ACCURATEDCT; + } else if (!strcasecmp(argv[i], "-progressive")) { + printf("Using progressive entropy coding\n\n"); + flags |= TJFLAG_PROGRESSIVE; + } else if (!strcasecmp(argv[i], "-rgb")) + pf = TJPF_RGB; + else if (!strcasecmp(argv[i], "-rgbx")) + pf = TJPF_RGBX; + else if (!strcasecmp(argv[i], "-bgr")) + pf = TJPF_BGR; + else if (!strcasecmp(argv[i], "-bgrx")) + pf = TJPF_BGRX; + else if (!strcasecmp(argv[i], "-xbgr")) + pf = TJPF_XBGR; + else if (!strcasecmp(argv[i], "-xrgb")) + pf = TJPF_XRGB; + else if (!strcasecmp(argv[i], "-cmyk")) + pf = TJPF_CMYK; + else if (!strcasecmp(argv[i], "-bottomup")) + flags |= TJFLAG_BOTTOMUP; + else if (!strcasecmp(argv[i], "-quiet")) + quiet = 1; + else if (!strcasecmp(argv[i], "-qq")) + quiet = 2; + else if (!strcasecmp(argv[i], "-scale") && i < argc - 1) { + int temp1 = 0, temp2 = 0, match = 0; + + if (sscanf(argv[++i], "%d/%d", &temp1, &temp2) == 2) { + for (j = 0; j < nsf; j++) { + if ((double)temp1 / (double)temp2 == + (double)scalingFactors[j].num / + (double)scalingFactors[j].denom) { + sf = scalingFactors[j]; + match = 1; break; + } + } + if (!match) usage(argv[0]); + } else usage(argv[0]); + } else if (!strcasecmp(argv[i], "-hflip")) + xformOp = TJXOP_HFLIP; + else if (!strcasecmp(argv[i], "-vflip")) + xformOp = TJXOP_VFLIP; + else if (!strcasecmp(argv[i], "-transpose")) + xformOp = TJXOP_TRANSPOSE; + else if (!strcasecmp(argv[i], "-transverse")) + xformOp = TJXOP_TRANSVERSE; + else if (!strcasecmp(argv[i], "-rot90")) + xformOp = TJXOP_ROT90; + else if (!strcasecmp(argv[i], "-rot180")) + xformOp = TJXOP_ROT180; + else if (!strcasecmp(argv[i], "-rot270")) + xformOp = TJXOP_ROT270; + else if (!strcasecmp(argv[i], "-grayscale")) + xformOpt |= TJXOPT_GRAY; + else if (!strcasecmp(argv[i], "-custom")) + customFilter = dummyDCTFilter; + else if (!strcasecmp(argv[i], "-nooutput")) + xformOpt |= TJXOPT_NOOUTPUT; + else if (!strcasecmp(argv[i], "-copynone")) + xformOpt |= TJXOPT_COPYNONE; + else if (!strcasecmp(argv[i], "-benchtime") && i < argc - 1) { + double temp = atof(argv[++i]); + + if (temp > 0.0) benchTime = temp; + else usage(argv[0]); + } else if (!strcasecmp(argv[i], "-warmup") && i < argc - 1) { + double temp = atof(argv[++i]); + + if (temp >= 0.0) warmup = temp; + else usage(argv[0]); + printf("Warmup time = %.1f seconds\n\n", warmup); + } else if (!strcasecmp(argv[i], "-alloc")) + flags &= (~TJFLAG_NOREALLOC); + else if (!strcasecmp(argv[i], "-bmp")) + ext = "bmp"; + else if (!strcasecmp(argv[i], "-yuv")) { + printf("Testing YUV planar encoding/decoding\n\n"); + doYUV = 1; + } else if (!strcasecmp(argv[i], "-yuvpad") && i < argc - 1) { + int temp = atoi(argv[++i]); + + if (temp >= 1) yuvPad = temp; + } else if (!strcasecmp(argv[i], "-subsamp") && i < argc - 1) { + i++; + if (toupper(argv[i][0]) == 'G') subsamp = TJSAMP_GRAY; + else { + int temp = atoi(argv[i]); + + switch (temp) { + case 444: subsamp = TJSAMP_444; break; + case 422: subsamp = TJSAMP_422; break; + case 440: subsamp = TJSAMP_440; break; + case 420: subsamp = TJSAMP_420; break; + case 411: subsamp = TJSAMP_411; break; + } + } + } else if (!strcasecmp(argv[i], "-componly")) + compOnly = 1; + else if (!strcasecmp(argv[i], "-nowrite")) + doWrite = 0; + else if (!strcasecmp(argv[i], "-stoponwarning")) + flags |= TJFLAG_STOPONWARNING; + else usage(argv[0]); + } + } + + if ((sf.num != 1 || sf.denom != 1) && doTile) { + printf("Disabling tiled compression/decompression tests, because those tests do not\n"); + printf("work when scaled decompression is enabled.\n"); + doTile = 0; + } + + if ((flags & TJFLAG_NOREALLOC) == 0 && doTile) { + printf("Disabling tiled compression/decompression tests, because those tests do not\n"); + printf("work when dynamic JPEG buffer allocation is enabled.\n\n"); + doTile = 0; + } + + if (!decompOnly) { + if ((srcBuf = tjLoadImage(argv[1], &w, 1, &h, &pf, flags)) == NULL) + _throwtjg("loading bitmap"); + temp = strrchr(argv[1], '.'); + if (temp != NULL) *temp = '\0'; + } + + if (quiet == 1 && !decompOnly) { + printf("All performance values in Mpixels/sec\n\n"); + printf("Bitmap JPEG JPEG %s %s ", + doTile ? "Tile " : "Image", doTile ? "Tile " : "Image"); + if (doYUV) printf("Encode "); + printf("Comp Comp Decomp "); + if (doYUV) printf("Decode"); + printf("\n"); + printf("Format Subsamp Qual Width Height "); + if (doYUV) printf("Perf "); + printf("Perf Ratio Perf "); + if (doYUV) printf("Perf"); + printf("\n\n"); + } + + if (decompOnly) { + decompTest(argv[1]); + printf("\n"); + goto bailout; + } + if (subsamp >= 0 && subsamp < TJ_NUMSAMP) { + for (i = maxQual; i >= minQual; i--) + fullTest(srcBuf, w, h, subsamp, i, argv[1]); + printf("\n"); + } else { + if (pf != TJPF_CMYK) { + for (i = maxQual; i >= minQual; i--) + fullTest(srcBuf, w, h, TJSAMP_GRAY, i, argv[1]); + printf("\n"); + } + for (i = maxQual; i >= minQual; i--) + fullTest(srcBuf, w, h, TJSAMP_420, i, argv[1]); + printf("\n"); + for (i = maxQual; i >= minQual; i--) + fullTest(srcBuf, w, h, TJSAMP_422, i, argv[1]); + printf("\n"); + for (i = maxQual; i >= minQual; i--) + fullTest(srcBuf, w, h, TJSAMP_444, i, argv[1]); + printf("\n"); + } + +bailout: + if (srcBuf) tjFree(srcBuf); + return retval; } |