| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C)2009-2014 D. R. Commander. All Rights Reserved. | 2 * Copyright (C)2009-2016 D. R. Commander. All Rights Reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions are met: | 5 * modification, are permitted provided that the following conditions are met: |
| 6 * | 6 * |
| 7 * - Redistributions of source code must retain the above copyright notice, | 7 * - Redistributions of source code must retain the above copyright notice, |
| 8 * this list of conditions and the following disclaimer. | 8 * this list of conditions and the following disclaimer. |
| 9 * - Redistributions in binary form must reproduce the above copyright notice, | 9 * - Redistributions in binary form must reproduce the above copyright notice, |
| 10 * this list of conditions and the following disclaimer in the documentation | 10 * this list of conditions and the following disclaimer in the documentation |
| 11 * and/or other materials provided with the distribution. | 11 * and/or other materials provided with the distribution. |
| 12 * - Neither the name of the libjpeg-turbo Project nor the names of its | 12 * - Neither the name of the libjpeg-turbo Project nor the names of its |
| (...skipping 25 matching lines...) Expand all Loading... |
| 38 #include "./turbojpeg.h" | 38 #include "./turbojpeg.h" |
| 39 | 39 |
| 40 | 40 |
| 41 #define _throw(op, err) { \ | 41 #define _throw(op, err) { \ |
| 42 printf("ERROR in line %d while %s:\n%s\n", __LINE__, op, err); \ | 42 printf("ERROR in line %d while %s:\n%s\n", __LINE__, op, err); \ |
| 43 retval=-1; goto bailout;} | 43 retval=-1; goto bailout;} |
| 44 #define _throwunix(m) _throw(m, strerror(errno)) | 44 #define _throwunix(m) _throw(m, strerror(errno)) |
| 45 #define _throwtj(m) _throw(m, tjGetErrorStr()) | 45 #define _throwtj(m) _throw(m, tjGetErrorStr()) |
| 46 #define _throwbmp(m) _throw(m, bmpgeterr()) | 46 #define _throwbmp(m) _throw(m, bmpgeterr()) |
| 47 | 47 |
| 48 enum {YUVENCODE=1, YUVDECODE}; | 48 int flags=TJFLAG_NOREALLOC, componly=0, decomponly=0, doyuv=0, quiet=0, |
| 49 int flags=TJFLAG_NOREALLOC, decomponly=0, yuv=0, quiet=0, dotile=0, | 49 » dotile=0, pf=TJPF_BGR, yuvpad=1, warmup=1, dowrite=1; |
| 50 » pf=TJPF_BGR; | |
| 51 char *ext="ppm"; | 50 char *ext="ppm"; |
| 52 const char *pixFormatStr[TJ_NUMPF]= | 51 const char *pixFormatStr[TJ_NUMPF]= |
| 53 { | 52 { |
| 54 » "RGB", "BGR", "RGBX", "BGRX", "XBGR", "XRGB", "GRAY" | 53 » "RGB", "BGR", "RGBX", "BGRX", "XBGR", "XRGB", "GRAY", "", "", "", "", "C
MYK" |
| 55 }; | 54 }; |
| 56 const char *subNameLong[TJ_NUMSAMP]= | 55 const char *subNameLong[TJ_NUMSAMP]= |
| 57 { | 56 { |
| 58 » "4:4:4", "4:2:2", "4:2:0", "GRAY", "4:4:0" | 57 » "4:4:4", "4:2:2", "4:2:0", "GRAY", "4:4:0", "4:1:1" |
| 59 }; | 58 }; |
| 60 const char *subName[NUMSUBOPT]={"444", "422", "420", "GRAY", "440"}; | 59 const char *csName[TJ_NUMCS]= |
| 60 { |
| 61 » "RGB", "YCbCr", "GRAY", "CMYK", "YCCK" |
| 62 }; |
| 63 const char *subName[TJ_NUMSAMP]={"444", "422", "420", "GRAY", "440", "411"}; |
| 61 tjscalingfactor *scalingfactors=NULL, sf={1, 1}; int nsf=0; | 64 tjscalingfactor *scalingfactors=NULL, sf={1, 1}; int nsf=0; |
| 62 int xformop=TJXOP_NONE, xformopt=0; | 65 int xformop=TJXOP_NONE, xformopt=0; |
| 63 int (*customFilter)(short *, tjregion, tjregion, int, int, tjtransform *); | 66 int (*customFilter)(short *, tjregion, tjregion, int, int, tjtransform *); |
| 64 double benchtime=5.0; | 67 double benchtime=5.0; |
| 65 | 68 |
| 66 | 69 |
| 70 char *formatName(int subsamp, int cs, char *buf) |
| 71 { |
| 72 if(cs==TJCS_YCbCr) return (char *)subNameLong[subsamp]; |
| 73 else if(cs==TJCS_YCCK) |
| 74 { |
| 75 snprintf(buf, 80, "%s %s", csName[cs], subNameLong[subsamp]); |
| 76 return buf; |
| 77 } |
| 78 else return (char *)csName[cs]; |
| 79 } |
| 80 |
| 81 |
| 67 char *sigfig(double val, int figs, char *buf, int len) | 82 char *sigfig(double val, int figs, char *buf, int len) |
| 68 { | 83 { |
| 69 char format[80]; | 84 char format[80]; |
| 70 int digitsafterdecimal=figs-(int)ceil(log10(fabs(val))); | 85 int digitsafterdecimal=figs-(int)ceil(log10(fabs(val))); |
| 71 if(digitsafterdecimal<1) snprintf(format, 80, "%%.0f"); | 86 if(digitsafterdecimal<1) snprintf(format, 80, "%%.0f"); |
| 72 else snprintf(format, 80, "%%.%df", digitsafterdecimal); | 87 else snprintf(format, 80, "%%.%df", digitsafterdecimal); |
| 73 snprintf(buf, len, format, val); | 88 snprintf(buf, len, format, val); |
| 74 return buf; | 89 return buf; |
| 75 } | 90 } |
| 76 | 91 |
| 77 | 92 |
| 78 /* Custom DCT filter which produces a negative of the image */ | 93 /* Custom DCT filter which produces a negative of the image */ |
| 79 int dummyDCTFilter(short *coeffs, tjregion arrayRegion, tjregion planeRegion, | 94 int dummyDCTFilter(short *coeffs, tjregion arrayRegion, tjregion planeRegion, |
| 80 int componentIndex, int transformIndex, tjtransform *transform) | 95 int componentIndex, int transformIndex, tjtransform *transform) |
| 81 { | 96 { |
| 82 int i; | 97 int i; |
| 83 for(i=0; i<arrayRegion.w*arrayRegion.h; i++) coeffs[i]=-coeffs[i]; | 98 for(i=0; i<arrayRegion.w*arrayRegion.h; i++) coeffs[i]=-coeffs[i]; |
| 84 return 0; | 99 return 0; |
| 85 } | 100 } |
| 86 | 101 |
| 87 | 102 |
| 88 /* Decompression test */ | 103 /* Decompression test */ |
| 89 int decomptest(unsigned char *srcbuf, unsigned char **jpegbuf, | 104 int decomp(unsigned char *srcbuf, unsigned char **jpegbuf, |
| 90 unsigned long *jpegsize, unsigned char *dstbuf, int w, int h, | 105 unsigned long *jpegsize, unsigned char *dstbuf, int w, int h, |
| 91 int subsamp, int jpegqual, char *filename, int tilew, int tileh) | 106 int subsamp, int jpegqual, char *filename, int tilew, int tileh) |
| 92 { | 107 { |
| 93 char tempstr[1024], sizestr[20]="\0", qualstr[6]="\0", *ptr; | 108 char tempstr[1024], sizestr[20]="\0", qualstr[6]="\0", *ptr; |
| 94 FILE *file=NULL; tjhandle handle=NULL; | 109 FILE *file=NULL; tjhandle handle=NULL; |
| 95 » int row, col, i, dstbufalloc=0, retval=0; | 110 » int row, col, iter=0, dstbufalloc=0, retval=0; |
| 96 » double start, elapsed; | 111 » double elapsed, elapsedDecode; |
| 97 int ps=tjPixelSize[pf]; | 112 int ps=tjPixelSize[pf]; |
| 98 » int yuvsize=tjBufSizeYUV(w, h, subsamp), bufsize; | 113 » int scaledw=TJSCALED(w, sf); |
| 99 » int scaledw=(yuv==YUVDECODE)? w : TJSCALED(w, sf); | 114 » int scaledh=TJSCALED(h, sf); |
| 100 » int scaledh=(yuv==YUVDECODE)? h : TJSCALED(h, sf); | |
| 101 int pitch=scaledw*ps; | 115 int pitch=scaledw*ps; |
| 102 int ntilesw=(w+tilew-1)/tilew, ntilesh=(h+tileh-1)/tileh; | 116 int ntilesw=(w+tilew-1)/tilew, ntilesh=(h+tileh-1)/tileh; |
| 103 » unsigned char *dstptr, *dstptr2; | 117 » unsigned char *dstptr, *dstptr2, *yuvbuf=NULL; |
| 104 | 118 |
| 105 if(jpegqual>0) | 119 if(jpegqual>0) |
| 106 { | 120 { |
| 107 snprintf(qualstr, 6, "_Q%d", jpegqual); | 121 snprintf(qualstr, 6, "_Q%d", jpegqual); |
| 108 qualstr[5]=0; | 122 qualstr[5]=0; |
| 109 } | 123 } |
| 110 | 124 |
| 111 if((handle=tjInitDecompress())==NULL) | 125 if((handle=tjInitDecompress())==NULL) |
| 112 _throwtj("executing tjInitDecompress()"); | 126 _throwtj("executing tjInitDecompress()"); |
| 113 | 127 |
| 114 bufsize=(yuv==YUVDECODE? yuvsize:pitch*scaledh); | |
| 115 if(dstbuf==NULL) | 128 if(dstbuf==NULL) |
| 116 { | 129 { |
| 117 » » if((dstbuf=(unsigned char *)malloc(bufsize)) == NULL) | 130 » » if((dstbuf=(unsigned char *)malloc(pitch*scaledh))==NULL) |
| 118 » » » _throwunix("allocating image buffer"); | 131 » » » _throwunix("allocating destination buffer"); |
| 119 dstbufalloc=1; | 132 dstbufalloc=1; |
| 120 } | 133 } |
| 121 /* Set the destination buffer to gray so we know whether the decompresso
r | 134 /* Set the destination buffer to gray so we know whether the decompresso
r |
| 122 attempted to write to it */ | 135 attempted to write to it */ |
| 123 » memset(dstbuf, 127, bufsize); | 136 » memset(dstbuf, 127, pitch*scaledh); |
| 124 | 137 |
| 125 » /* Execute once to preload cache */ | 138 » if(doyuv) |
| 126 » if(yuv==YUVDECODE) | |
| 127 { | 139 { |
| 128 » » if(tjDecompressToYUV(handle, jpegbuf[0], jpegsize[0], dstbuf, fl
ags)==-1) | 140 » » int width=dotile? tilew:scaledw; |
| 129 » » » _throwtj("executing tjDecompressToYUV()"); | 141 » » int height=dotile? tileh:scaledh; |
| 142 » » int yuvsize=tjBufSizeYUV2(width, yuvpad, height, subsamp); |
| 143 » » if((yuvbuf=(unsigned char *)malloc(yuvsize))==NULL) |
| 144 » » » _throwunix("allocating YUV buffer"); |
| 145 » » memset(yuvbuf, 127, yuvsize); |
| 130 } | 146 } |
| 131 else if(tjDecompress2(handle, jpegbuf[0], jpegsize[0], dstbuf, scaledw, | |
| 132 pitch, scaledh, pf, flags)==-1) | |
| 133 _throwtj("executing tjDecompress2()"); | |
| 134 | 147 |
| 135 /* Benchmark */ | 148 /* Benchmark */ |
| 136 » for(i=0, start=gettime(); (elapsed=gettime()-start)<benchtime; i++) | 149 » iter=-warmup; |
| 150 » elapsed=elapsedDecode=0.; |
| 151 » while(1) |
| 137 { | 152 { |
| 138 int tile=0; | 153 int tile=0; |
| 139 » » if(yuv==YUVDECODE) | 154 » » double start=gettime(); |
| 140 » » { | 155 » » for(row=0, dstptr=dstbuf; row<ntilesh; row++, dstptr+=pitch*tile
h) |
| 141 » » » if(tjDecompressToYUV(handle, jpegbuf[0], jpegsize[0], ds
tbuf, flags)==-1) | |
| 142 » » » » _throwtj("executing tjDecompressToYUV()"); | |
| 143 » » } | |
| 144 » » else for(row=0, dstptr=dstbuf; row<ntilesh; row++, dstptr+=pitch
*tileh) | |
| 145 { | 156 { |
| 146 for(col=0, dstptr2=dstptr; col<ntilesw; col++, tile++, d
stptr2+=ps*tilew) | 157 for(col=0, dstptr2=dstptr; col<ntilesw; col++, tile++, d
stptr2+=ps*tilew) |
| 147 { | 158 { |
| 148 int width=dotile? min(tilew, w-col*tilew):scaled
w; | 159 int width=dotile? min(tilew, w-col*tilew):scaled
w; |
| 149 int height=dotile? min(tileh, h-row*tileh):scale
dh; | 160 int height=dotile? min(tileh, h-row*tileh):scale
dh; |
| 150 » » » » if(tjDecompress2(handle, jpegbuf[tile], jpegsize
[tile], dstptr2, width, | 161 » » » » if(doyuv) |
| 151 » » » » » pitch, height, pf, flags)==-1) | 162 » » » » { |
| 152 » » » » » _throwtj("executing tjDecompress2()"); | 163 » » » » » double startDecode; |
| 164 » » » » » if(tjDecompressToYUV2(handle, jpegbuf[ti
le], jpegsize[tile], yuvbuf, |
| 165 » » » » » » width, yuvpad, height, flags)==-
1) |
| 166 » » » » » » _throwtj("executing tjDecompress
ToYUV2()"); |
| 167 » » » » » startDecode=gettime(); |
| 168 » » » » » if(tjDecodeYUV(handle, yuvbuf, yuvpad, s
ubsamp, dstptr2, width, |
| 169 » » » » » » pitch, height, pf, flags)==-1) |
| 170 » » » » » » _throwtj("executing tjDecodeYUV(
)"); |
| 171 » » » » » if(iter>=0) elapsedDecode+=gettime()-sta
rtDecode; |
| 172 » » » » } |
| 173 » » » » else |
| 174 » » » » » if(tjDecompress2(handle, jpegbuf[tile],
jpegsize[tile], dstptr2, |
| 175 » » » » » » width, pitch, height, pf, flags)
==-1) |
| 176 » » » » » » _throwtj("executing tjDecompress
2()"); |
| 153 } | 177 } |
| 154 } | 178 } |
| 179 iter++; |
| 180 if(iter>=1) |
| 181 { |
| 182 elapsed+=gettime()-start; |
| 183 if(elapsed>=benchtime) break; |
| 184 } |
| 155 } | 185 } |
| 186 if(doyuv) elapsed-=elapsedDecode; |
| 156 | 187 |
| 157 if(tjDestroy(handle)==-1) _throwtj("executing tjDestroy()"); | 188 if(tjDestroy(handle)==-1) _throwtj("executing tjDestroy()"); |
| 158 handle=NULL; | 189 handle=NULL; |
| 159 | 190 |
| 160 if(quiet) | 191 if(quiet) |
| 161 { | 192 { |
| 162 » » printf("%s\n", | 193 » » printf("%-6s%s", |
| 163 » » » sigfig((double)(w*h)/1000000.*(double)i/elapsed, 4, temp
str, 1024)); | 194 » » » sigfig((double)(w*h)/1000000.*(double)iter/elapsed, 4, t
empstr, 1024), |
| 195 » » » quiet==2? "\n":" "); |
| 196 » » if(doyuv) |
| 197 » » » printf("%s\n", |
| 198 » » » » sigfig((double)(w*h)/1000000.*(double)iter/elaps
edDecode, 4, tempstr, |
| 199 » » » » » 1024)); |
| 200 » » else if(quiet!=2) printf("\n"); |
| 164 } | 201 } |
| 165 else | 202 else |
| 166 { | 203 { |
| 167 » » printf("D--> Frame rate: %f fps\n", (double)i/elapsed)
; | 204 » » printf("%s --> Frame rate: %f fps\n", |
| 168 » » printf(" Dest. throughput: %f Megapixels/sec\n", | 205 » » » doyuv? "Decomp to YUV":"Decompress ", (double)iter/ela
psed); |
| 169 » » » (double)(w*h)/1000000.*(double)i/elapsed); | 206 » » printf(" Throughput: %f Megapixels/sec\
n", |
| 170 » } | 207 » » » (double)(w*h)/1000000.*(double)iter/elapsed); |
| 171 » if(yuv==YUVDECODE) | 208 » » if(doyuv) |
| 172 » { | |
| 173 » » snprintf(tempstr, 1024, "%s_%s%s.yuv", filename, subName[subsamp
], | |
| 174 » » » qualstr); | |
| 175 » » if((file=fopen(tempstr, "wb"))==NULL) | |
| 176 » » » _throwunix("opening YUV image for output"); | |
| 177 » » if(fwrite(dstbuf, yuvsize, 1, file)!=1) | |
| 178 » » » _throwunix("writing YUV image"); | |
| 179 » » fclose(file); file=NULL; | |
| 180 » } | |
| 181 » else | |
| 182 » { | |
| 183 » » if(sf.num!=1 || sf.denom!=1) | |
| 184 » » » snprintf(sizestr, 20, "%d_%d", sf.num, sf.denom); | |
| 185 » » else if(tilew!=w || tileh!=h) | |
| 186 » » » snprintf(sizestr, 20, "%dx%d", tilew, tileh); | |
| 187 » » else snprintf(sizestr, 20, "full"); | |
| 188 » » if(decomponly) | |
| 189 » » » snprintf(tempstr, 1024, "%s_%s.%s", filename, sizestr, e
xt); | |
| 190 » » else | |
| 191 » » » snprintf(tempstr, 1024, "%s_%s%s_%s.%s", filename, subNa
me[subsamp], | |
| 192 » » » » qualstr, sizestr, ext); | |
| 193 » » if(savebmp(tempstr, dstbuf, scaledw, scaledh, pf, | |
| 194 » » » (flags&TJFLAG_BOTTOMUP)!=0)==-1) | |
| 195 » » » _throwbmp("saving bitmap"); | |
| 196 » » ptr=strrchr(tempstr, '.'); | |
| 197 » » snprintf(ptr, 1024-(ptr-tempstr), "-err.%s", ext); | |
| 198 » » if(srcbuf && sf.num==1 && sf.denom==1) | |
| 199 { | 209 { |
| 200 » » » if(!quiet) printf("Compression error written to %s.\n",
tempstr); | 210 » » » printf("YUV Decode --> Frame rate: %f fps\n"
, |
| 201 » » » if(subsamp==TJ_GRAYSCALE) | 211 » » » » (double)iter/elapsedDecode); |
| 202 » » » { | 212 » » » printf(" Throughput: %f Megapix
els/sec\n", |
| 203 » » » » int index, index2; | 213 » » » » (double)(w*h)/1000000.*(double)iter/elapsedDecod
e); |
| 204 » » » » for(row=0, index=0; row<h; row++, index+=pitch) | |
| 205 » » » » { | |
| 206 » » » » » for(col=0, index2=index; col<w; col++, i
ndex2+=ps) | |
| 207 » » » » » { | |
| 208 » » » » » » int rindex=index2+tjRedOffset[pf
]; | |
| 209 » » » » » » int gindex=index2+tjGreenOffset[
pf]; | |
| 210 » » » » » » int bindex=index2+tjBlueOffset[p
f]; | |
| 211 » » » » » » int y=(int)((double)srcbuf[rinde
x]*0.299 | |
| 212 » » » » » » » + (double)srcbuf[gindex]
*0.587 | |
| 213 » » » » » » » + (double)srcbuf[bindex]
*0.114 + 0.5); | |
| 214 » » » » » » if(y>255) y=255; if(y<0) y=0; | |
| 215 » » » » » » dstbuf[rindex]=abs(dstbuf[rindex
]-y); | |
| 216 » » » » » » dstbuf[gindex]=abs(dstbuf[gindex
]-y); | |
| 217 » » » » » » dstbuf[bindex]=abs(dstbuf[bindex
]-y); | |
| 218 » » » » » } | |
| 219 » » » » } | |
| 220 » » » }» » | |
| 221 » » » else | |
| 222 » » » { | |
| 223 » » » » for(row=0; row<h; row++) | |
| 224 » » » » » for(col=0; col<w*ps; col++) | |
| 225 » » » » » » dstbuf[pitch*row+col] | |
| 226 » » » » » » » =abs(dstbuf[pitch*row+co
l]-srcbuf[pitch*row+col]); | |
| 227 » » » } | |
| 228 » » » if(savebmp(tempstr, dstbuf, w, h, pf, | |
| 229 » » » » (flags&TJFLAG_BOTTOMUP)!=0)==-1) | |
| 230 » » » » _throwbmp("saving bitmap"); | |
| 231 } | 214 } |
| 232 } | 215 } |
| 233 | 216 |
| 217 if (!dowrite) goto bailout; |
| 218 |
| 219 if(sf.num!=1 || sf.denom!=1) |
| 220 snprintf(sizestr, 20, "%d_%d", sf.num, sf.denom); |
| 221 else if(tilew!=w || tileh!=h) |
| 222 snprintf(sizestr, 20, "%dx%d", tilew, tileh); |
| 223 else snprintf(sizestr, 20, "full"); |
| 224 if(decomponly) |
| 225 snprintf(tempstr, 1024, "%s_%s.%s", filename, sizestr, ext); |
| 226 else |
| 227 snprintf(tempstr, 1024, "%s_%s%s_%s.%s", filename, subName[subsa
mp], |
| 228 qualstr, sizestr, ext); |
| 229 |
| 230 if(savebmp(tempstr, dstbuf, scaledw, scaledh, pf, |
| 231 (flags&TJFLAG_BOTTOMUP)!=0)==-1) |
| 232 _throwbmp("saving bitmap"); |
| 233 ptr=strrchr(tempstr, '.'); |
| 234 snprintf(ptr, 1024-(ptr-tempstr), "-err.%s", ext); |
| 235 if(srcbuf && sf.num==1 && sf.denom==1) |
| 236 { |
| 237 if(!quiet) printf("Compression error written to %s.\n", tempstr)
; |
| 238 if(subsamp==TJ_GRAYSCALE) |
| 239 { |
| 240 int index, index2; |
| 241 for(row=0, index=0; row<h; row++, index+=pitch) |
| 242 { |
| 243 for(col=0, index2=index; col<w; col++, index2+=p
s) |
| 244 { |
| 245 int rindex=index2+tjRedOffset[pf]; |
| 246 int gindex=index2+tjGreenOffset[pf]; |
| 247 int bindex=index2+tjBlueOffset[pf]; |
| 248 int y=(int)((double)srcbuf[rindex]*0.299 |
| 249 + (double)srcbuf[gindex]*0.587 |
| 250 + (double)srcbuf[bindex]*0.114 +
0.5); |
| 251 if(y>255) y=255; if(y<0) y=0; |
| 252 dstbuf[rindex]=abs(dstbuf[rindex]-y); |
| 253 dstbuf[gindex]=abs(dstbuf[gindex]-y); |
| 254 dstbuf[bindex]=abs(dstbuf[bindex]-y); |
| 255 } |
| 256 } |
| 257 } |
| 258 else |
| 259 { |
| 260 for(row=0; row<h; row++) |
| 261 for(col=0; col<w*ps; col++) |
| 262 dstbuf[pitch*row+col] |
| 263 =abs(dstbuf[pitch*row+col]-srcbu
f[pitch*row+col]); |
| 264 } |
| 265 if(savebmp(tempstr, dstbuf, w, h, pf, |
| 266 (flags&TJFLAG_BOTTOMUP)!=0)==-1) |
| 267 _throwbmp("saving bitmap"); |
| 268 } |
| 269 |
| 234 bailout: | 270 bailout: |
| 235 » if(file) {fclose(file); file=NULL;} | 271 » if(file) fclose(file); |
| 236 » if(handle) {tjDestroy(handle); handle=NULL;} | 272 » if(handle) tjDestroy(handle); |
| 237 » if(dstbuf && dstbufalloc) {free(dstbuf); dstbuf=NULL;} | 273 » if(dstbuf && dstbufalloc) free(dstbuf); |
| 274 » if(yuvbuf) free(yuvbuf); |
| 238 return retval; | 275 return retval; |
| 239 } | 276 } |
| 240 | 277 |
| 241 | 278 |
| 242 void dotestyuv(unsigned char *srcbuf, int w, int h, int subsamp, | 279 int fullTest(unsigned char *srcbuf, int w, int h, int subsamp, int jpegqual, |
| 243 char *filename) | 280 char *filename) |
| 244 { | 281 { |
| 245 char tempstr[1024], tempstr2[80]; | 282 char tempstr[1024], tempstr2[80]; |
| 246 FILE *file=NULL; tjhandle handle=NULL; | 283 FILE *file=NULL; tjhandle handle=NULL; |
| 247 » unsigned char *dstbuf=NULL; | 284 » unsigned char **jpegbuf=NULL, *yuvbuf=NULL, *tmpbuf=NULL, *srcptr, *srcp
tr2; |
| 248 » double start, elapsed; | 285 » double start, elapsed, elapsedEncode; |
| 249 » int i, retval=0, ps=tjPixelSize[pf]; | |
| 250 » int yuvsize=0; | |
| 251 | |
| 252 » yuvsize=tjBufSizeYUV(w, h, subsamp); | |
| 253 » if((dstbuf=(unsigned char *)malloc(yuvsize)) == NULL) | |
| 254 » » _throwunix("allocating image buffer"); | |
| 255 | |
| 256 » if(!quiet) | |
| 257 » » printf(">>>>> %s (%s) <--> YUV %s <<<<<\n", pixFormatStr[pf], | |
| 258 » » » (flags&TJFLAG_BOTTOMUP)? "Bottom-up":"Top-down", subName
Long[subsamp]); | |
| 259 | |
| 260 » if(quiet==1) | |
| 261 » » printf("%s\t%s\t%s\tN/A\t", pixFormatStr[pf], | |
| 262 » » » (flags&TJFLAG_BOTTOMUP)? "BU":"TD", subNameLong[subsamp]
); | |
| 263 | |
| 264 » if((handle=tjInitCompress())==NULL) | |
| 265 » » _throwtj("executing tjInitCompress()"); | |
| 266 | |
| 267 » /* Execute once to preload cache */ | |
| 268 » if(tjEncodeYUV2(handle, srcbuf, w, 0, h, pf, dstbuf, subsamp, flags)==-1
) | |
| 269 » » _throwtj("executing tjEncodeYUV2()"); | |
| 270 | |
| 271 » /* Benchmark */ | |
| 272 » for(i=0, start=gettime(); (elapsed=gettime()-start)<benchtime; i++) | |
| 273 » { | |
| 274 » » if(tjEncodeYUV2(handle, srcbuf, w, 0, h, pf, dstbuf, subsamp, fl
ags)==-1) | |
| 275 » » » _throwtj("executing tjEncodeYUV2()"); | |
| 276 » } | |
| 277 | |
| 278 » if(tjDestroy(handle)==-1) _throwtj("executing tjDestroy()"); | |
| 279 » handle=NULL; | |
| 280 | |
| 281 » if(quiet==1) printf("%-4d %-4d\t", w, h); | |
| 282 » if(quiet) | |
| 283 » { | |
| 284 » » printf("%s%c%s%c", | |
| 285 » » » sigfig((double)(w*h)/1000000.*(double)i/elapsed, 4, temp
str, 1024), | |
| 286 » » » quiet==2? '\n':'\t', | |
| 287 » » » sigfig((double)(w*h*ps)/(double)yuvsize, 4, tempstr2, 80
), | |
| 288 » » » quiet==2? '\n':'\t'); | |
| 289 » } | |
| 290 » else | |
| 291 » { | |
| 292 » » printf("\n%s size: %d x %d\n", "Image", w, h); | |
| 293 » » printf("C--> Frame rate: %f fps\n", (double)i/elapsed)
; | |
| 294 » » printf(" Output image size: %d bytes\n", yuvsize); | |
| 295 » » printf(" Compression ratio: %f:1\n", | |
| 296 » » » (double)(w*h*ps)/(double)yuvsize); | |
| 297 » » printf(" Source throughput: %f Megapixels/sec\n", | |
| 298 » » » (double)(w*h)/1000000.*(double)i/elapsed); | |
| 299 » » printf(" Output bit stream: %f Megabits/sec\n", | |
| 300 » » » (double)yuvsize*8./1000000.*(double)i/elapsed); | |
| 301 » } | |
| 302 » snprintf(tempstr, 1024, "%s_%s.yuv", filename, subName[subsamp]); | |
| 303 » if((file=fopen(tempstr, "wb"))==NULL) | |
| 304 » » _throwunix("opening reference image"); | |
| 305 » if(fwrite(dstbuf, yuvsize, 1, file)!=1) | |
| 306 » » _throwunix("writing reference image"); | |
| 307 » fclose(file); file=NULL; | |
| 308 » if(!quiet) printf("Reference image written to %s\n", tempstr); | |
| 309 | |
| 310 » bailout: | |
| 311 » if(file) {fclose(file); file=NULL;} | |
| 312 » if(dstbuf) {free(dstbuf); dstbuf=NULL;} | |
| 313 » if(handle) {tjDestroy(handle); handle=NULL;} | |
| 314 » return; | |
| 315 } | |
| 316 | |
| 317 | |
| 318 void dotest(unsigned char *srcbuf, int w, int h, int subsamp, int jpegqual, | |
| 319 » char *filename) | |
| 320 { | |
| 321 » char tempstr[1024], tempstr2[80]; | |
| 322 » FILE *file=NULL; tjhandle handle=NULL; | |
| 323 » unsigned char **jpegbuf=NULL, *tmpbuf=NULL, *srcptr, *srcptr2; | |
| 324 » double start, elapsed; | |
| 325 int totaljpegsize=0, row, col, i, tilew=w, tileh=h, retval=0; | 286 int totaljpegsize=0, row, col, i, tilew=w, tileh=h, retval=0; |
| 287 int iter, yuvsize=0; |
| 326 unsigned long *jpegsize=NULL; | 288 unsigned long *jpegsize=NULL; |
| 327 » int ps=tjPixelSize[pf], ntilesw=1, ntilesh=1, pitch=w*ps; | 289 » int ps=tjPixelSize[pf]; |
| 328 | 290 » int ntilesw=1, ntilesh=1, pitch=w*ps; |
| 329 » if(yuv==YUVENCODE) {dotestyuv(srcbuf, w, h, subsamp, filename); return;
} | 291 » const char *pfStr=pixFormatStr[pf]; |
| 330 | 292 |
| 331 if((tmpbuf=(unsigned char *)malloc(pitch*h)) == NULL) | 293 if((tmpbuf=(unsigned char *)malloc(pitch*h)) == NULL) |
| 332 _throwunix("allocating temporary image buffer"); | 294 _throwunix("allocating temporary image buffer"); |
| 333 | 295 |
| 334 if(!quiet) | 296 if(!quiet) |
| 335 » » printf(">>>>> %s (%s) <--> JPEG %s Q%d <<<<<\n", pixFormatStr[
pf], | 297 » » printf(">>>>> %s (%s) <--> JPEG %s Q%d <<<<<\n", pfStr, |
| 336 (flags&TJFLAG_BOTTOMUP)? "Bottom-up":"Top-down", subName
Long[subsamp], | 298 (flags&TJFLAG_BOTTOMUP)? "Bottom-up":"Top-down", subName
Long[subsamp], |
| 337 jpegqual); | 299 jpegqual); |
| 338 | 300 |
| 339 for(tilew=dotile? 8:w, tileh=dotile? 8:h; ; tilew*=2, tileh*=2) | 301 for(tilew=dotile? 8:w, tileh=dotile? 8:h; ; tilew*=2, tileh*=2) |
| 340 { | 302 { |
| 341 if(tilew>w) tilew=w; if(tileh>h) tileh=h; | 303 if(tilew>w) tilew=w; if(tileh>h) tileh=h; |
| 342 ntilesw=(w+tilew-1)/tilew; ntilesh=(h+tileh-1)/tileh; | 304 ntilesw=(w+tilew-1)/tilew; ntilesh=(h+tileh-1)/tileh; |
| 343 | 305 |
| 344 if((jpegbuf=(unsigned char **)malloc(sizeof(unsigned char *) | 306 if((jpegbuf=(unsigned char **)malloc(sizeof(unsigned char *) |
| 345 *ntilesw*ntilesh))==NULL) | 307 *ntilesw*ntilesh))==NULL) |
| 346 _throwunix("allocating JPEG tile array"); | 308 _throwunix("allocating JPEG tile array"); |
| 347 memset(jpegbuf, 0, sizeof(unsigned char *)*ntilesw*ntilesh); | 309 memset(jpegbuf, 0, sizeof(unsigned char *)*ntilesw*ntilesh); |
| 348 if((jpegsize=(unsigned long *)malloc(sizeof(unsigned long) | 310 if((jpegsize=(unsigned long *)malloc(sizeof(unsigned long) |
| 349 *ntilesw*ntilesh))==NULL) | 311 *ntilesw*ntilesh))==NULL) |
| 350 _throwunix("allocating JPEG size array"); | 312 _throwunix("allocating JPEG size array"); |
| 351 memset(jpegsize, 0, sizeof(unsigned long)*ntilesw*ntilesh); | 313 memset(jpegsize, 0, sizeof(unsigned long)*ntilesw*ntilesh); |
| 352 | 314 |
| 353 if((flags&TJFLAG_NOREALLOC)!=0) | 315 if((flags&TJFLAG_NOREALLOC)!=0) |
| 354 for(i=0; i<ntilesw*ntilesh; i++) | 316 for(i=0; i<ntilesw*ntilesh; i++) |
| 355 { | 317 { |
| 356 » » » » if((jpegbuf[i]=(unsigned char *)malloc(tjBufSize
(tilew, tileh, | 318 » » » » if((jpegbuf[i]=(unsigned char *)tjAlloc(tjBufSiz
e(tilew, tileh, |
| 357 subsamp)))==NULL) | 319 subsamp)))==NULL) |
| 358 _throwunix("allocating JPEG tiles"); | 320 _throwunix("allocating JPEG tiles"); |
| 359 } | 321 } |
| 360 | 322 |
| 361 /* Compression test */ | 323 /* Compression test */ |
| 362 if(quiet==1) | 324 if(quiet==1) |
| 363 » » » printf("%s\t%s\t%s\t%d\t", pixFormatStr[pf], | 325 » » » printf("%-4s (%s) %-5s %-3d ", pfStr, |
| 364 (flags&TJFLAG_BOTTOMUP)? "BU":"TD", subNameLong[
subsamp], jpegqual); | 326 (flags&TJFLAG_BOTTOMUP)? "BU":"TD", subNameLong[
subsamp], jpegqual); |
| 365 for(i=0; i<h; i++) | 327 for(i=0; i<h; i++) |
| 366 memcpy(&tmpbuf[pitch*i], &srcbuf[w*ps*i], w*ps); | 328 memcpy(&tmpbuf[pitch*i], &srcbuf[w*ps*i], w*ps); |
| 367 if((handle=tjInitCompress())==NULL) | 329 if((handle=tjInitCompress())==NULL) |
| 368 _throwtj("executing tjInitCompress()"); | 330 _throwtj("executing tjInitCompress()"); |
| 369 | 331 |
| 370 » » /* Execute once to preload cache */ | 332 » » if(doyuv) |
| 371 » » if(tjCompress2(handle, srcbuf, tilew, pitch, tileh, pf, &jpegbuf
[0], | 333 » » { |
| 372 » » » &jpegsize[0], subsamp, jpegqual, flags)==-1) | 334 » » » yuvsize=tjBufSizeYUV2(tilew, yuvpad, tileh, subsamp); |
| 373 » » » _throwtj("executing tjCompress2()"); | 335 » » » if((yuvbuf=(unsigned char *)malloc(yuvsize))==NULL) |
| 336 » » » » _throwunix("allocating YUV buffer"); |
| 337 » » » memset(yuvbuf, 127, yuvsize); |
| 338 » » } |
| 374 | 339 |
| 375 /* Benchmark */ | 340 /* Benchmark */ |
| 376 » » for(i=0, start=gettime(); (elapsed=gettime()-start)<benchtime; i
++) | 341 » » iter=-warmup; |
| 342 » » elapsed=elapsedEncode=0.; |
| 343 » » while(1) |
| 377 { | 344 { |
| 378 int tile=0; | 345 int tile=0; |
| 379 totaljpegsize=0; | 346 totaljpegsize=0; |
| 347 start=gettime(); |
| 380 for(row=0, srcptr=srcbuf; row<ntilesh; row++, srcptr+=pi
tch*tileh) | 348 for(row=0, srcptr=srcbuf; row<ntilesh; row++, srcptr+=pi
tch*tileh) |
| 381 { | 349 { |
| 382 for(col=0, srcptr2=srcptr; col<ntilesw; col++, t
ile++, | 350 for(col=0, srcptr2=srcptr; col<ntilesw; col++, t
ile++, |
| 383 srcptr2+=ps*tilew) | 351 srcptr2+=ps*tilew) |
| 384 { | 352 { |
| 385 int width=min(tilew, w-col*tilew); | 353 int width=min(tilew, w-col*tilew); |
| 386 int height=min(tileh, h-row*tileh); | 354 int height=min(tileh, h-row*tileh); |
| 387 » » » » » if(tjCompress2(handle, srcptr2, width, p
itch, height, pf, | 355 » » » » » if(doyuv) |
| 388 » » » » » » &jpegbuf[tile], &jpegsize[tile],
subsamp, jpegqual, flags)==-1) | 356 » » » » » { |
| 389 » » » » » » _throwtj("executing tjCompress()
2"); | 357 » » » » » » double startEncode=gettime(); |
| 358 » » » » » » if(tjEncodeYUV3(handle, srcptr2,
width, pitch, height, pf, yuvbuf, |
| 359 » » » » » » » yuvpad, subsamp, flags)=
=-1) |
| 360 » » » » » » » _throwtj("executing tjEn
codeYUV3()"); |
| 361 » » » » » » if(iter>=0) elapsedEncode+=getti
me()-startEncode; |
| 362 » » » » » » if(tjCompressFromYUV(handle, yuv
buf, width, yuvpad, height, |
| 363 » » » » » » » subsamp, &jpegbuf[tile],
&jpegsize[tile], jpegqual, flags)==-1) |
| 364 » » » » » » » _throwtj("executing tjCo
mpressFromYUV()"); |
| 365 » » » » » } |
| 366 » » » » » else |
| 367 » » » » » { |
| 368 » » » » » » if(tjCompress2(handle, srcptr2,
width, pitch, height, pf, |
| 369 » » » » » » » &jpegbuf[tile], &jpegsiz
e[tile], subsamp, jpegqual, flags)==-1) |
| 370 » » » » » » » _throwtj("executing tjCo
mpress2()"); |
| 371 » » » » » } |
| 390 totaljpegsize+=jpegsize[tile]; | 372 totaljpegsize+=jpegsize[tile]; |
| 391 } | 373 } |
| 392 } | 374 } |
| 375 iter++; |
| 376 if(iter>=1) |
| 377 { |
| 378 elapsed+=gettime()-start; |
| 379 if(elapsed>=benchtime) break; |
| 380 } |
| 393 } | 381 } |
| 382 if(doyuv) elapsed-=elapsedEncode; |
| 394 | 383 |
| 395 if(tjDestroy(handle)==-1) _throwtj("executing tjDestroy()"); | 384 if(tjDestroy(handle)==-1) _throwtj("executing tjDestroy()"); |
| 396 handle=NULL; | 385 handle=NULL; |
| 397 | 386 |
| 398 » » if(quiet==1) printf("%-4d %-4d\t", tilew, tileh); | 387 » » if(quiet==1) printf("%-5d %-5d ", tilew, tileh); |
| 399 if(quiet) | 388 if(quiet) |
| 400 { | 389 { |
| 401 » » » printf("%s%c%s%c", | 390 » » » if(doyuv) |
| 402 » » » » sigfig((double)(w*h)/1000000.*(double)i/elapsed,
4, tempstr, 1024), | 391 » » » » printf("%-6s%s", |
| 403 » » » » quiet==2? '\n':'\t', | 392 » » » » » sigfig((double)(w*h)/1000000.*(double)it
er/elapsedEncode, 4, tempstr, |
| 393 » » » » » » 1024), quiet==2? "\n":" "); |
| 394 » » » printf("%-6s%s", |
| 395 » » » » sigfig((double)(w*h)/1000000.*(double)iter/elaps
ed, 4,» tempstr, 1024), |
| 396 » » » » quiet==2? "\n":" "); |
| 397 » » » printf("%-6s%s", |
| 404 sigfig((double)(w*h*ps)/(double)totaljpegsize, 4
, tempstr2, 80), | 398 sigfig((double)(w*h*ps)/(double)totaljpegsize, 4
, tempstr2, 80), |
| 405 » » » » quiet==2? '\n':'\t'); | 399 » » » » quiet==2? "\n":" "); |
| 406 } | 400 } |
| 407 else | 401 else |
| 408 { | 402 { |
| 409 printf("\n%s size: %d x %d\n", dotile? "Tile":"Image", t
ilew, | 403 printf("\n%s size: %d x %d\n", dotile? "Tile":"Image", t
ilew, |
| 410 tileh); | 404 tileh); |
| 411 » » » printf("C--> Frame rate: %f fps\n", (double)i/
elapsed); | 405 » » » if(doyuv) |
| 412 » » » printf(" Output image size: %d bytes\n", totaljpe
gsize); | 406 » » » { |
| 413 » » » printf(" Compression ratio: %f:1\n", | 407 » » » » printf("Encode YUV --> Frame rate: %f
fps\n", |
| 408 » » » » » (double)iter/elapsedEncode); |
| 409 » » » » printf(" Output image size: %d
bytes\n", yuvsize); |
| 410 » » » » printf(" Compression ratio: %f
:1\n", |
| 411 » » » » » (double)(w*h*ps)/(double)yuvsize); |
| 412 » » » » printf(" Throughput: %f
Megapixels/sec\n", |
| 413 » » » » » (double)(w*h)/1000000.*(double)iter/elap
sedEncode); |
| 414 » » » » printf(" Output bit stream: %f
Megabits/sec\n", |
| 415 » » » » » (double)yuvsize*8./1000000.*(double)iter
/elapsedEncode); |
| 416 » » » } |
| 417 » » » printf("%s --> Frame rate: %f fps\n", |
| 418 » » » » doyuv? "Comp from YUV":"Compress ", (double)
iter/elapsed); |
| 419 » » » printf(" Output image size: %d bytes\n
", |
| 420 » » » » totaljpegsize); |
| 421 » » » printf(" Compression ratio: %f:1\n", |
| 414 (double)(w*h*ps)/(double)totaljpegsize); | 422 (double)(w*h*ps)/(double)totaljpegsize); |
| 415 » » » printf(" Source throughput: %f Megapixels/sec\n", | 423 » » » printf(" Throughput: %f Megapix
els/sec\n", |
| 416 » » » » (double)(w*h)/1000000.*(double)i/elapsed); | 424 » » » » (double)(w*h)/1000000.*(double)iter/elapsed); |
| 417 » » » printf(" Output bit stream: %f Megabits/sec\n", | 425 » » » printf(" Output bit stream: %f Megabit
s/sec\n", |
| 418 » » » » (double)totaljpegsize*8./1000000.*(double)i/elap
sed); | 426 » » » » (double)totaljpegsize*8./1000000.*(double)iter/e
lapsed); |
| 419 } | 427 } |
| 420 » » if(tilew==w && tileh==h) | 428 » » if(tilew==w && tileh==h && dowrite) |
| 421 { | 429 { |
| 422 snprintf(tempstr, 1024, "%s_%s_Q%d.jpg", filename, subNa
me[subsamp], | 430 snprintf(tempstr, 1024, "%s_%s_Q%d.jpg", filename, subNa
me[subsamp], |
| 423 jpegqual); | 431 jpegqual); |
| 424 if((file=fopen(tempstr, "wb"))==NULL) | 432 if((file=fopen(tempstr, "wb"))==NULL) |
| 425 _throwunix("opening reference image"); | 433 _throwunix("opening reference image"); |
| 426 if(fwrite(jpegbuf[0], jpegsize[0], 1, file)!=1) | 434 if(fwrite(jpegbuf[0], jpegsize[0], 1, file)!=1) |
| 427 _throwunix("writing reference image"); | 435 _throwunix("writing reference image"); |
| 428 fclose(file); file=NULL; | 436 fclose(file); file=NULL; |
| 429 if(!quiet) printf("Reference image written to %s\n", tem
pstr); | 437 if(!quiet) printf("Reference image written to %s\n", tem
pstr); |
| 430 } | 438 } |
| 431 | 439 |
| 432 /* Decompression test */ | 440 /* Decompression test */ |
| 433 » » if(decomptest(srcbuf, jpegbuf, jpegsize, tmpbuf, w, h, subsamp,
jpegqual, | 441 » » if(!componly) |
| 434 » » » filename, tilew, tileh)==-1) | 442 » » { |
| 435 » » » goto bailout; | 443 » » » if(decomp(srcbuf, jpegbuf, jpegsize, tmpbuf, w, h, subsa
mp, jpegqual, |
| 444 » » » » filename, tilew, tileh)==-1) |
| 445 » » » » goto bailout; |
| 446 » » } |
| 436 | 447 |
| 437 for(i=0; i<ntilesw*ntilesh; i++) | 448 for(i=0; i<ntilesw*ntilesh; i++) |
| 438 { | 449 { |
| 439 » » » if(jpegbuf[i]) free(jpegbuf[i]); jpegbuf[i]=NULL; | 450 » » » if(jpegbuf[i]) tjFree(jpegbuf[i]); jpegbuf[i]=NULL; |
| 440 } | 451 } |
| 441 free(jpegbuf); jpegbuf=NULL; | 452 free(jpegbuf); jpegbuf=NULL; |
| 442 free(jpegsize); jpegsize=NULL; | 453 free(jpegsize); jpegsize=NULL; |
| 454 if(doyuv) |
| 455 { |
| 456 free(yuvbuf); yuvbuf=NULL; |
| 457 } |
| 443 | 458 |
| 444 if(tilew==w && tileh==h) break; | 459 if(tilew==w && tileh==h) break; |
| 445 } | 460 } |
| 446 | 461 |
| 447 bailout: | 462 bailout: |
| 448 if(file) {fclose(file); file=NULL;} | 463 if(file) {fclose(file); file=NULL;} |
| 449 if(jpegbuf) | 464 if(jpegbuf) |
| 450 { | 465 { |
| 451 for(i=0; i<ntilesw*ntilesh; i++) | 466 for(i=0; i<ntilesw*ntilesh; i++) |
| 452 { | 467 { |
| 453 » » » if(jpegbuf[i]) free(jpegbuf[i]); jpegbuf[i]=NULL; | 468 » » » if(jpegbuf[i]) tjFree(jpegbuf[i]); jpegbuf[i]=NULL; |
| 454 } | 469 } |
| 455 free(jpegbuf); jpegbuf=NULL; | 470 free(jpegbuf); jpegbuf=NULL; |
| 456 } | 471 } |
| 472 if(yuvbuf) {free(yuvbuf); yuvbuf=NULL;} |
| 457 if(jpegsize) {free(jpegsize); jpegsize=NULL;} | 473 if(jpegsize) {free(jpegsize); jpegsize=NULL;} |
| 458 if(tmpbuf) {free(tmpbuf); tmpbuf=NULL;} | 474 if(tmpbuf) {free(tmpbuf); tmpbuf=NULL;} |
| 459 if(handle) {tjDestroy(handle); handle=NULL;} | 475 if(handle) {tjDestroy(handle); handle=NULL;} |
| 460 » return; | 476 » return retval; |
| 461 } | 477 } |
| 462 | 478 |
| 463 | 479 |
| 464 void dodecomptest(char *filename) | 480 int decompTest(char *filename) |
| 465 { | 481 { |
| 466 FILE *file=NULL; tjhandle handle=NULL; | 482 FILE *file=NULL; tjhandle handle=NULL; |
| 467 unsigned char **jpegbuf=NULL, *srcbuf=NULL; | 483 unsigned char **jpegbuf=NULL, *srcbuf=NULL; |
| 468 unsigned long *jpegsize=NULL, srcsize, totaljpegsize; | 484 unsigned long *jpegsize=NULL, srcsize, totaljpegsize; |
| 469 tjtransform *t=NULL; | 485 tjtransform *t=NULL; |
| 470 » int w=0, h=0, subsamp=-1, _w, _h, _tilew, _tileh, | 486 » int w=0, h=0, subsamp=-1, cs=-1, _w, _h, _tilew, _tileh, |
| 471 _ntilesw, _ntilesh, _subsamp; | 487 _ntilesw, _ntilesh, _subsamp; |
| 472 char *temp=NULL, tempstr[80], tempstr2[80]; | 488 char *temp=NULL, tempstr[80], tempstr2[80]; |
| 473 » int row, col, i, tilew, tileh, ntilesw=1, ntilesh=1, retval=0; | 489 » int row, col, i, iter, tilew, tileh, ntilesw=1, ntilesh=1, retval=0; |
| 474 double start, elapsed; | 490 double start, elapsed; |
| 475 int ps=tjPixelSize[pf], tile; | 491 int ps=tjPixelSize[pf], tile; |
| 476 | 492 |
| 477 if((file=fopen(filename, "rb"))==NULL) | 493 if((file=fopen(filename, "rb"))==NULL) |
| 478 _throwunix("opening file"); | 494 _throwunix("opening file"); |
| 479 if(fseek(file, 0, SEEK_END)<0 || (srcsize=ftell(file))==(unsigned long)-
1) | 495 if(fseek(file, 0, SEEK_END)<0 || (srcsize=ftell(file))==(unsigned long)-
1) |
| 480 _throwunix("determining file size"); | 496 _throwunix("determining file size"); |
| 481 if((srcbuf=(unsigned char *)malloc(srcsize))==NULL) | 497 if((srcbuf=(unsigned char *)malloc(srcsize))==NULL) |
| 482 _throwunix("allocating memory"); | 498 _throwunix("allocating memory"); |
| 483 if(fseek(file, 0, SEEK_SET)<0) | 499 if(fseek(file, 0, SEEK_SET)<0) |
| 484 _throwunix("setting file position"); | 500 _throwunix("setting file position"); |
| 485 if(fread(srcbuf, srcsize, 1, file)<1) | 501 if(fread(srcbuf, srcsize, 1, file)<1) |
| 486 _throwunix("reading JPEG data"); | 502 _throwunix("reading JPEG data"); |
| 487 fclose(file); file=NULL; | 503 fclose(file); file=NULL; |
| 488 | 504 |
| 489 temp=strrchr(filename, '.'); | 505 temp=strrchr(filename, '.'); |
| 490 if(temp!=NULL) *temp='\0'; | 506 if(temp!=NULL) *temp='\0'; |
| 491 | 507 |
| 492 if((handle=tjInitTransform())==NULL) | 508 if((handle=tjInitTransform())==NULL) |
| 493 _throwtj("executing tjInitTransform()"); | 509 _throwtj("executing tjInitTransform()"); |
| 494 » if(tjDecompressHeader2(handle, srcbuf, srcsize, &w, &h, &subsamp)==-1) | 510 » if(tjDecompressHeader3(handle, srcbuf, srcsize, &w, &h, &subsamp, &cs)==
-1) |
| 495 » » _throwtj("executing tjDecompressHeader2()"); | 511 » » _throwtj("executing tjDecompressHeader3()"); |
| 512 » if(cs==TJCS_YCCK || cs==TJCS_CMYK) |
| 513 » { |
| 514 » » pf=TJPF_CMYK; ps=tjPixelSize[pf]; |
| 515 » } |
| 496 | 516 |
| 497 if(quiet==1) | 517 if(quiet==1) |
| 498 { | 518 { |
| 499 printf("All performance values in Mpixels/sec\n\n"); | 519 printf("All performance values in Mpixels/sec\n\n"); |
| 500 » » printf("Bitmap\tBitmap\tJPEG\t%s %s \tXform\tComp\tDecomp\n", | 520 » » printf("Bitmap JPEG JPEG %s %s Xform Comp Deco
mp ", |
| 501 dotile? "Tile ":"Image", dotile? "Tile ":"Image"); | 521 dotile? "Tile ":"Image", dotile? "Tile ":"Image"); |
| 502 » » printf("Format\tOrder\tSubsamp\tWidth Height\tPerf \tRatio\tPerf
\n\n"); | 522 » » if(doyuv) printf("Decode"); |
| 523 » » printf("\n"); |
| 524 » » printf("Format CS Subsamp Width Height Perf Ratio
Perf "); |
| 525 » » if(doyuv) printf("Perf"); |
| 526 » » printf("\n\n"); |
| 503 } | 527 } |
| 504 else if(!quiet) | 528 else if(!quiet) |
| 505 » { | 529 » » printf(">>>>> JPEG %s --> %s (%s) <<<<<\n", |
| 506 » » printf(">>>>> JPEG %s --> %s (%s) <<<<<\n", subNameLong[subsam
p], | 530 » » » formatName(subsamp, cs, tempstr), pixFormatStr[pf], |
| 507 » » » pixFormatStr[pf], (flags&TJFLAG_BOTTOMUP)? "Bottom-up":"
Top-down"); | 531 » » » (flags&TJFLAG_BOTTOMUP)? "Bottom-up":"Top-down"); |
| 508 » } | |
| 509 | 532 |
| 510 for(tilew=dotile? 16:w, tileh=dotile? 16:h; ; tilew*=2, tileh*=2) | 533 for(tilew=dotile? 16:w, tileh=dotile? 16:h; ; tilew*=2, tileh*=2) |
| 511 { | 534 { |
| 512 if(tilew>w) tilew=w; if(tileh>h) tileh=h; | 535 if(tilew>w) tilew=w; if(tileh>h) tileh=h; |
| 513 ntilesw=(w+tilew-1)/tilew; ntilesh=(h+tileh-1)/tileh; | 536 ntilesw=(w+tilew-1)/tilew; ntilesh=(h+tileh-1)/tileh; |
| 514 | 537 |
| 515 if((jpegbuf=(unsigned char **)malloc(sizeof(unsigned char *) | 538 if((jpegbuf=(unsigned char **)malloc(sizeof(unsigned char *) |
| 516 *ntilesw*ntilesh))==NULL) | 539 *ntilesw*ntilesh))==NULL) |
| 517 _throwunix("allocating JPEG tile array"); | 540 _throwunix("allocating JPEG tile array"); |
| 518 memset(jpegbuf, 0, sizeof(unsigned char *)*ntilesw*ntilesh); | 541 memset(jpegbuf, 0, sizeof(unsigned char *)*ntilesw*ntilesh); |
| 519 if((jpegsize=(unsigned long *)malloc(sizeof(unsigned long) | 542 if((jpegsize=(unsigned long *)malloc(sizeof(unsigned long) |
| 520 *ntilesw*ntilesh))==NULL) | 543 *ntilesw*ntilesh))==NULL) |
| 521 _throwunix("allocating JPEG size array"); | 544 _throwunix("allocating JPEG size array"); |
| 522 memset(jpegsize, 0, sizeof(unsigned long)*ntilesw*ntilesh); | 545 memset(jpegsize, 0, sizeof(unsigned long)*ntilesw*ntilesh); |
| 523 | 546 |
| 524 if((flags&TJFLAG_NOREALLOC)!=0 || !dotile) | 547 if((flags&TJFLAG_NOREALLOC)!=0 || !dotile) |
| 525 for(i=0; i<ntilesw*ntilesh; i++) | 548 for(i=0; i<ntilesw*ntilesh; i++) |
| 526 { | 549 { |
| 527 » » » » if((jpegbuf[i]=(unsigned char *)malloc(tjBufSize
(tilew, tileh, | 550 » » » » if((jpegbuf[i]=(unsigned char *)tjAlloc(tjBufSiz
e(tilew, tileh, |
| 528 subsamp)))==NULL) | 551 subsamp)))==NULL) |
| 529 _throwunix("allocating JPEG tiles"); | 552 _throwunix("allocating JPEG tiles"); |
| 530 } | 553 } |
| 531 | 554 |
| 532 _w=w; _h=h; _tilew=tilew; _tileh=tileh; | 555 _w=w; _h=h; _tilew=tilew; _tileh=tileh; |
| 533 if(!quiet) | 556 if(!quiet) |
| 534 { | 557 { |
| 535 printf("\n%s size: %d x %d", dotile? "Tile":"Image", _ti
lew, | 558 printf("\n%s size: %d x %d", dotile? "Tile":"Image", _ti
lew, |
| 536 _tileh); | 559 _tileh); |
| 537 if(sf.num!=1 || sf.denom!=1) | 560 if(sf.num!=1 || sf.denom!=1) |
| 538 printf(" --> %d x %d", TJSCALED(_w, sf), TJSCALE
D(_h, sf)); | 561 printf(" --> %d x %d", TJSCALED(_w, sf), TJSCALE
D(_h, sf)); |
| 539 printf("\n"); | 562 printf("\n"); |
| 540 } | 563 } |
| 541 else if(quiet==1) | 564 else if(quiet==1) |
| 542 { | 565 { |
| 543 » » » printf("%s\t%s\t%s\t", pixFormatStr[pf], | 566 » » » printf("%-4s (%s) %-5s %-5s ", pixFormatStr[pf], |
| 544 » » » » (flags&TJFLAG_BOTTOMUP)? "BU":"TD", subNameLong[
subsamp]); | 567 » » » » (flags&TJFLAG_BOTTOMUP)? "BU":"TD", csName[cs],
subNameLong[subsamp]); |
| 545 » » » printf("%-4d %-4d\t", tilew, tileh); | 568 » » » printf("%-5d %-5d ", tilew, tileh); |
| 546 } | 569 } |
| 547 | 570 |
| 548 _subsamp=subsamp; | 571 _subsamp=subsamp; |
| 549 if(dotile || xformop!=TJXOP_NONE || xformopt!=0 || customFilter) | 572 if(dotile || xformop!=TJXOP_NONE || xformopt!=0 || customFilter) |
| 550 { | 573 { |
| 551 if((t=(tjtransform *)malloc(sizeof(tjtransform)*ntilesw*
ntilesh)) | 574 if((t=(tjtransform *)malloc(sizeof(tjtransform)*ntilesw*
ntilesh)) |
| 552 ==NULL) | 575 ==NULL) |
| 553 _throwunix("allocating image transform array"); | 576 _throwunix("allocating image transform array"); |
| 554 | 577 |
| 555 if(xformop==TJXOP_TRANSPOSE || xformop==TJXOP_TRANSVERSE | 578 if(xformop==TJXOP_TRANSPOSE || xformop==TJXOP_TRANSVERSE |
| 556 || xformop==TJXOP_ROT90 || xformop==TJXOP_ROT270
) | 579 || xformop==TJXOP_ROT90 || xformop==TJXOP_ROT270
) |
| 557 { | 580 { |
| 558 _w=h; _h=w; _tilew=tileh; _tileh=tilew; | 581 _w=h; _h=w; _tilew=tileh; _tileh=tilew; |
| 559 } | 582 } |
| 560 | 583 |
| 561 if(xformopt&TJXOPT_GRAY) _subsamp=TJ_GRAYSCALE; | 584 if(xformopt&TJXOPT_GRAY) _subsamp=TJ_GRAYSCALE; |
| 562 if(xformop==TJXOP_HFLIP || xformop==TJXOP_ROT180) | 585 if(xformop==TJXOP_HFLIP || xformop==TJXOP_ROT180) |
| 563 _w=_w-(_w%tjMCUWidth[_subsamp]); | 586 _w=_w-(_w%tjMCUWidth[_subsamp]); |
| 564 if(xformop==TJXOP_VFLIP || xformop==TJXOP_ROT180) | 587 if(xformop==TJXOP_VFLIP || xformop==TJXOP_ROT180) |
| 565 _h=_h-(_h%tjMCUHeight[_subsamp]); | 588 _h=_h-(_h%tjMCUHeight[_subsamp]); |
| 566 if(xformop==TJXOP_TRANSVERSE || xformop==TJXOP_ROT90) | 589 if(xformop==TJXOP_TRANSVERSE || xformop==TJXOP_ROT90) |
| 567 _w=_w-(_w%tjMCUHeight[_subsamp]); | 590 _w=_w-(_w%tjMCUHeight[_subsamp]); |
| 568 if(xformop==TJXOP_TRANSVERSE || xformop==TJXOP_ROT270) | 591 if(xformop==TJXOP_TRANSVERSE || xformop==TJXOP_ROT270) |
| 569 _h=_h-(_h%tjMCUWidth[_subsamp]); | 592 _h=_h-(_h%tjMCUWidth[_subsamp]); |
| 570 _ntilesw=(_w+_tilew-1)/_tilew; | 593 _ntilesw=(_w+_tilew-1)/_tilew; |
| 571 _ntilesh=(_h+_tileh-1)/_tileh; | 594 _ntilesh=(_h+_tileh-1)/_tileh; |
| 572 | 595 |
| 596 if(xformop==TJXOP_TRANSPOSE || xformop==TJXOP_TRANSVERSE |
| 597 || xformop==TJXOP_ROT90 || xformop==TJXOP_ROT270
) |
| 598 { |
| 599 if(_subsamp==TJSAMP_422) _subsamp=TJSAMP_440; |
| 600 else if(_subsamp==TJSAMP_440) _subsamp=TJSAMP_42
2; |
| 601 } |
| 602 |
| 573 for(row=0, tile=0; row<_ntilesh; row++) | 603 for(row=0, tile=0; row<_ntilesh; row++) |
| 574 { | 604 { |
| 575 for(col=0; col<_ntilesw; col++, tile++) | 605 for(col=0; col<_ntilesw; col++, tile++) |
| 576 { | 606 { |
| 577 t[tile].r.w=min(_tilew, _w-col*_tilew); | 607 t[tile].r.w=min(_tilew, _w-col*_tilew); |
| 578 t[tile].r.h=min(_tileh, _h-row*_tileh); | 608 t[tile].r.h=min(_tileh, _h-row*_tileh); |
| 579 t[tile].r.x=col*_tilew; | 609 t[tile].r.x=col*_tilew; |
| 580 t[tile].r.y=row*_tileh; | 610 t[tile].r.y=row*_tileh; |
| 581 t[tile].op=xformop; | 611 t[tile].op=xformop; |
| 582 t[tile].options=xformopt|TJXOPT_TRIM; | 612 t[tile].options=xformopt|TJXOPT_TRIM; |
| 583 t[tile].customFilter=customFilter; | 613 t[tile].customFilter=customFilter; |
| 584 if(t[tile].options&TJXOPT_NOOUTPUT && jp
egbuf[tile]) | 614 if(t[tile].options&TJXOPT_NOOUTPUT && jp
egbuf[tile]) |
| 585 { | 615 { |
| 586 » » » » » » free(jpegbuf[tile]); jpegbuf[ti
le]=NULL; | 616 » » » » » » tjFree(jpegbuf[tile]); jpegbuf[
tile]=NULL; |
| 587 } | 617 } |
| 588 } | 618 } |
| 589 } | 619 } |
| 590 | 620 |
| 591 » » » start=gettime(); | 621 » » » iter=-warmup; |
| 592 » » » if(tjTransform(handle, srcbuf, srcsize, _ntilesw*_ntiles
h, jpegbuf, | 622 » » » elapsed=0.; |
| 593 » » » » jpegsize, t, flags)==-1) | 623 » » » while(1) |
| 594 » » » » _throwtj("executing tjTransform()"); | 624 » » » { |
| 595 » » » elapsed=gettime()-start; | 625 » » » » start=gettime(); |
| 626 » » » » if(tjTransform(handle, srcbuf, srcsize, _ntilesw
*_ntilesh, jpegbuf, |
| 627 » » » » » jpegsize, t, flags)==-1) |
| 628 » » » » » _throwtj("executing tjTransform()"); |
| 629 » » » » iter++; |
| 630 » » » » if(iter>=1) |
| 631 » » » » { |
| 632 » » » » » elapsed+=gettime()-start; |
| 633 » » » » » if(elapsed>=benchtime) break; |
| 634 » » » » } |
| 635 » » » } |
| 596 | 636 |
| 597 free(t); t=NULL; | 637 free(t); t=NULL; |
| 598 | 638 |
| 599 for(tile=0, totaljpegsize=0; tile<_ntilesw*_ntilesh; til
e++) | 639 for(tile=0, totaljpegsize=0; tile<_ntilesw*_ntilesh; til
e++) |
| 600 totaljpegsize+=jpegsize[tile]; | 640 totaljpegsize+=jpegsize[tile]; |
| 601 | 641 |
| 602 if(quiet) | 642 if(quiet) |
| 603 { | 643 { |
| 604 » » » » printf("%s%c%s%c", | 644 » » » » printf("%-6s%s%-6s%s", |
| 605 sigfig((double)(w*h)/1000000./elapsed, 4
, tempstr, 80), | 645 sigfig((double)(w*h)/1000000./elapsed, 4
, tempstr, 80), |
| 606 » » » » » quiet==2? '\n':'\t', | 646 » » » » » quiet==2? "\n":" ", |
| 607 sigfig((double)(w*h*ps)/(double)totaljpe
gsize, 4, tempstr2, 80), | 647 sigfig((double)(w*h*ps)/(double)totaljpe
gsize, 4, tempstr2, 80), |
| 608 » » » » » quiet==2? '\n':'\t'); | 648 » » » » » quiet==2? "\n":" "); |
| 609 } | 649 } |
| 610 else if(!quiet) | 650 else if(!quiet) |
| 611 { | 651 { |
| 612 » » » » printf("X--> Frame rate: %f fps\n", 1.
0/elapsed); | 652 » » » » printf("Transform --> Frame rate: %f
fps\n", 1.0/elapsed); |
| 613 » » » » printf(" Output image size: %lu bytes\n",
totaljpegsize); | 653 » » » » printf(" Output image size: %l
u bytes\n", totaljpegsize); |
| 614 » » » » printf(" Compression ratio: %f:1\n", | 654 » » » » printf(" Compression ratio: %f
:1\n", |
| 615 (double)(w*h*ps)/(double)totaljpegsize); | 655 (double)(w*h*ps)/(double)totaljpegsize); |
| 616 » » » » printf(" Source throughput: %f Megapixels
/sec\n", | 656 » » » » printf(" Throughput: %f
Megapixels/sec\n", |
| 617 (double)(w*h)/1000000./elapsed); | 657 (double)(w*h)/1000000./elapsed); |
| 618 » » » » printf(" Output bit stream: %f Megabits/s
ec\n", | 658 » » » » printf(" Output bit stream: %f
Megabits/sec\n", |
| 619 (double)totaljpegsize*8./1000000./elapse
d); | 659 (double)totaljpegsize*8./1000000./elapse
d); |
| 620 } | 660 } |
| 621 } | 661 } |
| 622 else | 662 else |
| 623 { | 663 { |
| 624 » » » if(quiet==1) printf("N/A\tN/A\t"); | 664 » » » if(quiet==1) printf("N/A N/A "); |
| 625 jpegsize[0]=srcsize; | 665 jpegsize[0]=srcsize; |
| 626 memcpy(jpegbuf[0], srcbuf, srcsize); | 666 memcpy(jpegbuf[0], srcbuf, srcsize); |
| 627 } | 667 } |
| 628 | 668 |
| 629 if(w==tilew) _tilew=_w; | 669 if(w==tilew) _tilew=_w; |
| 630 if(h==tileh) _tileh=_h; | 670 if(h==tileh) _tileh=_h; |
| 631 if(!(xformopt&TJXOPT_NOOUTPUT)) | 671 if(!(xformopt&TJXOPT_NOOUTPUT)) |
| 632 { | 672 { |
| 633 » » » if(decomptest(NULL, jpegbuf, jpegsize, NULL, _w, _h, _su
bsamp, 0, | 673 » » » if(decomp(NULL, jpegbuf, jpegsize, NULL, _w, _h, _subsam
p, 0, |
| 634 filename, _tilew, _tileh)==-1) | 674 filename, _tilew, _tileh)==-1) |
| 635 goto bailout; | 675 goto bailout; |
| 636 } | 676 } |
| 637 else if(quiet==1) printf("N/A\n"); | 677 else if(quiet==1) printf("N/A\n"); |
| 638 | 678 |
| 639 for(i=0; i<ntilesw*ntilesh; i++) | 679 for(i=0; i<ntilesw*ntilesh; i++) |
| 640 { | 680 { |
| 641 » » » free(jpegbuf[i]); jpegbuf[i]=NULL; | 681 » » » tjFree(jpegbuf[i]); jpegbuf[i]=NULL; |
| 642 } | 682 } |
| 643 free(jpegbuf); jpegbuf=NULL; | 683 free(jpegbuf); jpegbuf=NULL; |
| 644 if(jpegsize) {free(jpegsize); jpegsize=NULL;} | 684 if(jpegsize) {free(jpegsize); jpegsize=NULL;} |
| 645 | 685 |
| 646 if(tilew==w && tileh==h) break; | 686 if(tilew==w && tileh==h) break; |
| 647 } | 687 } |
| 648 | 688 |
| 649 bailout: | 689 bailout: |
| 650 if(file) {fclose(file); file=NULL;} | 690 if(file) {fclose(file); file=NULL;} |
| 651 if(jpegbuf) | 691 if(jpegbuf) |
| 652 { | 692 { |
| 653 for(i=0; i<ntilesw*ntilesh; i++) | 693 for(i=0; i<ntilesw*ntilesh; i++) |
| 654 { | 694 { |
| 655 » » » if(jpegbuf[i]) free(jpegbuf[i]); jpegbuf[i]=NULL; | 695 » » » if(jpegbuf[i]) tjFree(jpegbuf[i]); jpegbuf[i]=NULL; |
| 656 } | 696 } |
| 657 free(jpegbuf); jpegbuf=NULL; | 697 free(jpegbuf); jpegbuf=NULL; |
| 658 } | 698 } |
| 659 if(jpegsize) {free(jpegsize); jpegsize=NULL;} | 699 if(jpegsize) {free(jpegsize); jpegsize=NULL;} |
| 660 if(srcbuf) {free(srcbuf); srcbuf=NULL;} | 700 if(srcbuf) {free(srcbuf); srcbuf=NULL;} |
| 661 if(t) {free(t); t=NULL;} | 701 if(t) {free(t); t=NULL;} |
| 662 if(handle) {tjDestroy(handle); handle=NULL;} | 702 if(handle) {tjDestroy(handle); handle=NULL;} |
| 663 » return; | 703 » return retval; |
| 664 } | 704 } |
| 665 | 705 |
| 666 | 706 |
| 667 void usage(char *progname) | 707 void usage(char *progname) |
| 668 { | 708 { |
| 669 int i; | 709 int i; |
| 670 printf("USAGE: %s\n", progname); | 710 printf("USAGE: %s\n", progname); |
| 671 printf(" <Inputfile (BMP|PPM)> <Quality> [options]\n\n"); | 711 printf(" <Inputfile (BMP|PPM)> <Quality> [options]\n\n"); |
| 672 printf(" %s\n", progname); | 712 printf(" %s\n", progname); |
| 673 printf(" <Inputfile (JPG)> [options]\n\n"); | 713 printf(" <Inputfile (JPG)> [options]\n\n"); |
| 674 printf("Options:\n\n"); | 714 printf("Options:\n\n"); |
| 675 printf("-alloc = Dynamically allocate JPEG image buffers\n"); | 715 printf("-alloc = Dynamically allocate JPEG image buffers\n"); |
| 676 » printf("-bmp = Generate output images in Windows Bitmap format (default=
PPM)\n"); | 716 » printf("-bmp = Generate output images in Windows Bitmap format (default
= PPM)\n"); |
| 677 printf("-bottomup = Test bottom-up compression/decompression\n"); | 717 printf("-bottomup = Test bottom-up compression/decompression\n"); |
| 678 printf("-tile = Test performance of the codec when the image is encoded
as separate\n"); | 718 printf("-tile = Test performance of the codec when the image is encoded
as separate\n"); |
| 679 printf(" tiles of varying sizes.\n"); | 719 printf(" tiles of varying sizes.\n"); |
| 680 printf("-forcemmx, -forcesse, -forcesse2, -forcesse3 =\n"); | |
| 681 printf(" Force MMX, SSE, SSE2, or SSE3 code paths in the underlying
codec\n"); | |
| 682 printf("-rgb, -bgr, -rgbx, -bgrx, -xbgr, -xrgb =\n"); | 720 printf("-rgb, -bgr, -rgbx, -bgrx, -xbgr, -xrgb =\n"); |
| 683 » printf(" Test the specified color conversion path in the codec (defa
ult: BGR)\n"); | 721 » printf(" Test the specified color conversion path in the codec (defa
ult = BGR)\n"); |
| 722 » printf("-cmyk = Indirectly test YCCK JPEG compression/decompression (the
source\n"); |
| 723 » printf(" and destination bitmaps are still RGB. The conversion is d
one\n"); |
| 724 » printf(" internally prior to compression or after decompression.)\n"
); |
| 684 printf("-fastupsample = Use the fastest chrominance upsampling algorithm
available in\n"); | 725 printf("-fastupsample = Use the fastest chrominance upsampling algorithm
available in\n"); |
| 685 printf(" the underlying codec\n"); | 726 printf(" the underlying codec\n"); |
| 686 printf("-fastdct = Use the fastest DCT/IDCT algorithms available in the
underlying\n"); | 727 printf("-fastdct = Use the fastest DCT/IDCT algorithms available in the
underlying\n"); |
| 687 printf(" codec\n"); | 728 printf(" codec\n"); |
| 688 printf("-accuratedct = Use the most accurate DCT/IDCT algorithms availab
le in the\n"); | 729 printf("-accuratedct = Use the most accurate DCT/IDCT algorithms availab
le in the\n"); |
| 689 printf(" underlying codec\n"); | 730 printf(" underlying codec\n"); |
| 690 printf("-subsamp <s> = When testing JPEG compression, this option specif
ies the level\n"); | 731 printf("-subsamp <s> = When testing JPEG compression, this option specif
ies the level\n"); |
| 691 » printf(" of chrominance subsampling to use (<s> = 444, 422, 440, 420
, or GRAY).\n"); | 732 » printf(" of chrominance subsampling to use (<s> = 444, 422, 440, 420
, 411, or\n"); |
| 692 » printf(" The default is to test Grayscale, 4:2:0, 4:2:2, and 4:4:4 i
n sequence.\n"); | 733 » printf(" GRAY). The default is to test Grayscale, 4:2:0, 4:2:2, and
4:4:4 in\n"); |
| 734 » printf(" sequence.\n"); |
| 693 printf("-quiet = Output results in tabular rather than verbose format\n"
); | 735 printf("-quiet = Output results in tabular rather than verbose format\n"
); |
| 694 » printf("-yuvencode = Encode RGB input as planar YUV rather than compress
ing as JPEG\n"); | 736 » printf("-yuv = Test YUV encoding/decoding functions\n"); |
| 695 » printf("-yuvdecode = Decode JPEG image to planar YUV rather than RGB\n")
; | 737 » printf("-yuvpad <p> = If testing YUV encoding/decoding, this specifies t
he number of\n"); |
| 696 » printf("-scale M/N = scale down the width/height of the decompressed JPE
G image by a\n"); | 738 » printf(" bytes to which each row of each plane in the intermediate Y
UV image is\n"); |
| 739 » printf(" padded (default = 1)\n"); |
| 740 » printf("-scale M/N = Scale down the width/height of the decompressed JPE
G image by a\n"); |
| 697 printf(" factor of M/N (M/N = "); | 741 printf(" factor of M/N (M/N = "); |
| 698 for(i=0; i<nsf; i++) | 742 for(i=0; i<nsf; i++) |
| 699 { | 743 { |
| 700 printf("%d/%d", scalingfactors[i].num, scalingfactors[i].denom); | 744 printf("%d/%d", scalingfactors[i].num, scalingfactors[i].denom); |
| 701 if(nsf==2 && i!=nsf-1) printf(" or "); | 745 if(nsf==2 && i!=nsf-1) printf(" or "); |
| 702 else if(nsf>2) | 746 else if(nsf>2) |
| 703 { | 747 { |
| 704 if(i!=nsf-1) printf(", "); | 748 if(i!=nsf-1) printf(", "); |
| 705 if(i==nsf-2) printf("or "); | 749 if(i==nsf-2) printf("or "); |
| 706 } | 750 } |
| 707 if(i%8==0 && i!=0) printf("\n "); | 751 if(i%8==0 && i!=0) printf("\n "); |
| 708 } | 752 } |
| 709 printf(")\n"); | 753 printf(")\n"); |
| 710 printf("-hflip, -vflip, -transpose, -transverse, -rot90, -rot180, -rot27
0 =\n"); | 754 printf("-hflip, -vflip, -transpose, -transverse, -rot90, -rot180, -rot27
0 =\n"); |
| 711 printf(" Perform the corresponding lossless transform prior to\n"); | 755 printf(" Perform the corresponding lossless transform prior to\n"); |
| 712 printf(" decompression (these options are mutually exclusive)\n"); | 756 printf(" decompression (these options are mutually exclusive)\n"); |
| 713 printf("-grayscale = Perform lossless grayscale conversion prior to deco
mpression\n"); | 757 printf("-grayscale = Perform lossless grayscale conversion prior to deco
mpression\n"); |
| 714 printf(" test (can be combined with the other transforms above)\n"); | 758 printf(" test (can be combined with the other transforms above)\n"); |
| 715 » printf("-benchtime <t> = Run each benchmark for at least <t> seconds (de
fault = 5.0)\n\n"); | 759 » printf("-benchtime <t> = Run each benchmark for at least <t> seconds (de
fault = 5.0)\n"); |
| 760 » printf("-warmup <w> = Execute each benchmark <w> times to prime the cach
e before\n"); |
| 761 » printf(" taking performance measurements (default = 1)\n"); |
| 762 » printf("-componly = Stop after running compression tests. Do not test d
ecompression.\n"); |
| 763 » printf("-nowrite = Do not write reference or output images (improves con
sistency of\n"); |
| 764 » printf(" performance measurements.)\n\n"); |
| 716 printf("NOTE: If the quality is specified as a range (e.g. 90-100), a s
eparate\n"); | 765 printf("NOTE: If the quality is specified as a range (e.g. 90-100), a s
eparate\n"); |
| 717 printf("test will be performed for all quality values in the range.\n\n"
); | 766 printf("test will be performed for all quality values in the range.\n\n"
); |
| 718 exit(1); | 767 exit(1); |
| 719 } | 768 } |
| 720 | 769 |
| 721 | 770 |
| 722 int main(int argc, char *argv[]) | 771 int main(int argc, char *argv[]) |
| 723 { | 772 { |
| 724 » unsigned char *srcbuf=NULL; int w, h, i, j; | 773 » unsigned char *srcbuf=NULL; int w=0, h=0, i, j; |
| 725 int minqual=-1, maxqual=-1; char *temp; | 774 int minqual=-1, maxqual=-1; char *temp; |
| 726 int minarg=2, retval=0, subsamp=-1; | 775 int minarg=2, retval=0, subsamp=-1; |
| 727 | 776 |
| 728 if((scalingfactors=tjGetScalingFactors(&nsf))==NULL || nsf==0) | 777 if((scalingfactors=tjGetScalingFactors(&nsf))==NULL || nsf==0) |
| 729 _throwtj("executing tjGetScalingFactors()"); | 778 _throwtj("executing tjGetScalingFactors()"); |
| 730 | 779 |
| 731 if(argc<minarg) usage(argv[0]); | 780 if(argc<minarg) usage(argv[0]); |
| 732 | 781 |
| 733 temp=strrchr(argv[1], '.'); | 782 temp=strrchr(argv[1], '.'); |
| 734 if(temp!=NULL) | 783 if(temp!=NULL) |
| 735 { | 784 { |
| 736 if(!strcasecmp(temp, ".bmp")) ext="bmp"; | 785 if(!strcasecmp(temp, ".bmp")) ext="bmp"; |
| 737 if(!strcasecmp(temp, ".jpg") || !strcasecmp(temp, ".jpeg")) deco
mponly=1; | 786 if(!strcasecmp(temp, ".jpg") || !strcasecmp(temp, ".jpeg")) deco
mponly=1; |
| 738 } | 787 } |
| 739 | 788 |
| 740 printf("\n"); | 789 printf("\n"); |
| 741 | 790 |
| 742 » if(argc>minarg) | 791 » if(!decomponly) |
| 743 » { | |
| 744 » » for(i=minarg; i<argc; i++) | |
| 745 » » { | |
| 746 » » » if(!strcasecmp(argv[i], "-yuvencode")) | |
| 747 » » » { | |
| 748 » » » » printf("Testing YUV planar encoding\n\n"); | |
| 749 » » » » yuv=YUVENCODE; maxqual=minqual=100; | |
| 750 » » » } | |
| 751 » » » if(!strcasecmp(argv[i], "-yuvdecode")) | |
| 752 » » » { | |
| 753 » » » » printf("Testing YUV planar decoding\n\n"); | |
| 754 » » » » yuv=YUVDECODE; | |
| 755 » » » } | |
| 756 » » } | |
| 757 » } | |
| 758 | |
| 759 » if(!decomponly && yuv!=YUVENCODE) | |
| 760 { | 792 { |
| 761 minarg=3; | 793 minarg=3; |
| 762 if(argc<minarg) usage(argv[0]); | 794 if(argc<minarg) usage(argv[0]); |
| 763 if((minqual=atoi(argv[2]))<1 || minqual>100) | 795 if((minqual=atoi(argv[2]))<1 || minqual>100) |
| 764 { | 796 { |
| 765 puts("ERROR: Quality must be between 1 and 100."); | 797 puts("ERROR: Quality must be between 1 and 100."); |
| 766 exit(1); | 798 exit(1); |
| 767 } | 799 } |
| 768 if((temp=strchr(argv[2], '-'))!=NULL && strlen(temp)>1 | 800 if((temp=strchr(argv[2], '-'))!=NULL && strlen(temp)>1 |
| 769 && sscanf(&temp[1], "%d", &maxqual)==1 && maxqual>minqua
l && maxqual>=1 | 801 && sscanf(&temp[1], "%d", &maxqual)==1 && maxqual>minqua
l && maxqual>=1 |
| 770 && maxqual<=100) {} | 802 && maxqual<=100) {} |
| 771 else maxqual=minqual; | 803 else maxqual=minqual; |
| 772 } | 804 } |
| 773 | 805 |
| 774 if(argc>minarg) | 806 if(argc>minarg) |
| 775 { | 807 { |
| 776 for(i=minarg; i<argc; i++) | 808 for(i=minarg; i<argc; i++) |
| 777 { | 809 { |
| 778 if(!strcasecmp(argv[i], "-tile")) | 810 if(!strcasecmp(argv[i], "-tile")) |
| 779 { | 811 { |
| 780 dotile=1; xformopt|=TJXOPT_CROP; | 812 dotile=1; xformopt|=TJXOPT_CROP; |
| 781 } | 813 } |
| 782 if(!strcasecmp(argv[i], "-forcesse3")) | |
| 783 { | |
| 784 printf("Forcing SSE3 code\n\n"); | |
| 785 flags|=TJFLAG_FORCESSE3; | |
| 786 } | |
| 787 if(!strcasecmp(argv[i], "-forcesse2")) | |
| 788 { | |
| 789 printf("Forcing SSE2 code\n\n"); | |
| 790 flags|=TJFLAG_FORCESSE2; | |
| 791 } | |
| 792 if(!strcasecmp(argv[i], "-forcesse")) | |
| 793 { | |
| 794 printf("Forcing SSE code\n\n"); | |
| 795 flags|=TJFLAG_FORCESSE; | |
| 796 } | |
| 797 if(!strcasecmp(argv[i], "-forcemmx")) | |
| 798 { | |
| 799 printf("Forcing MMX code\n\n"); | |
| 800 flags|=TJFLAG_FORCEMMX; | |
| 801 } | |
| 802 if(!strcasecmp(argv[i], "-fastupsample")) | 814 if(!strcasecmp(argv[i], "-fastupsample")) |
| 803 { | 815 { |
| 804 printf("Using fast upsampling code\n\n"); | 816 printf("Using fast upsampling code\n\n"); |
| 805 flags|=TJFLAG_FASTUPSAMPLE; | 817 flags|=TJFLAG_FASTUPSAMPLE; |
| 806 } | 818 } |
| 807 if(!strcasecmp(argv[i], "-fastdct")) | 819 if(!strcasecmp(argv[i], "-fastdct")) |
| 808 { | 820 { |
| 809 printf("Using fastest DCT/IDCT algorithm\n\n"); | 821 printf("Using fastest DCT/IDCT algorithm\n\n"); |
| 810 flags|=TJFLAG_FASTDCT; | 822 flags|=TJFLAG_FASTDCT; |
| 811 } | 823 } |
| 812 if(!strcasecmp(argv[i], "-accuratedct")) | 824 if(!strcasecmp(argv[i], "-accuratedct")) |
| 813 { | 825 { |
| 814 printf("Using most accurate DCT/IDCT algorithm\n
\n"); | 826 printf("Using most accurate DCT/IDCT algorithm\n
\n"); |
| 815 flags|=TJFLAG_ACCURATEDCT; | 827 flags|=TJFLAG_ACCURATEDCT; |
| 816 } | 828 } |
| 817 if(!strcasecmp(argv[i], "-rgb")) pf=TJPF_RGB; | 829 if(!strcasecmp(argv[i], "-rgb")) pf=TJPF_RGB; |
| 818 if(!strcasecmp(argv[i], "-rgbx")) pf=TJPF_RGBX; | 830 if(!strcasecmp(argv[i], "-rgbx")) pf=TJPF_RGBX; |
| 819 if(!strcasecmp(argv[i], "-bgr")) pf=TJPF_BGR; | 831 if(!strcasecmp(argv[i], "-bgr")) pf=TJPF_BGR; |
| 820 if(!strcasecmp(argv[i], "-bgrx")) pf=TJPF_BGRX; | 832 if(!strcasecmp(argv[i], "-bgrx")) pf=TJPF_BGRX; |
| 821 if(!strcasecmp(argv[i], "-xbgr")) pf=TJPF_XBGR; | 833 if(!strcasecmp(argv[i], "-xbgr")) pf=TJPF_XBGR; |
| 822 if(!strcasecmp(argv[i], "-xrgb")) pf=TJPF_XRGB; | 834 if(!strcasecmp(argv[i], "-xrgb")) pf=TJPF_XRGB; |
| 835 if(!strcasecmp(argv[i], "-cmyk")) pf=TJPF_CMYK; |
| 823 if(!strcasecmp(argv[i], "-bottomup")) flags|=TJFLAG_BOTT
OMUP; | 836 if(!strcasecmp(argv[i], "-bottomup")) flags|=TJFLAG_BOTT
OMUP; |
| 824 if(!strcasecmp(argv[i], "-quiet")) quiet=1; | 837 if(!strcasecmp(argv[i], "-quiet")) quiet=1; |
| 825 if(!strcasecmp(argv[i], "-qq")) quiet=2; | 838 if(!strcasecmp(argv[i], "-qq")) quiet=2; |
| 826 if(!strcasecmp(argv[i], "-scale") && i<argc-1) | 839 if(!strcasecmp(argv[i], "-scale") && i<argc-1) |
| 827 { | 840 { |
| 828 int temp1=0, temp2=0, match=0; | 841 int temp1=0, temp2=0, match=0; |
| 829 if(sscanf(argv[++i], "%d/%d", &temp1, &temp2)==2
) | 842 if(sscanf(argv[++i], "%d/%d", &temp1, &temp2)==2
) |
| 830 { | 843 { |
| 831 for(j=0; j<nsf; j++) | 844 for(j=0; j<nsf; j++) |
| 832 { | 845 { |
| (...skipping 17 matching lines...) Expand all Loading... |
| 850 if(!strcasecmp(argv[i], "-rot270")) xformop=TJXOP_ROT270
; | 863 if(!strcasecmp(argv[i], "-rot270")) xformop=TJXOP_ROT270
; |
| 851 if(!strcasecmp(argv[i], "-grayscale")) xformopt|=TJXOPT_
GRAY; | 864 if(!strcasecmp(argv[i], "-grayscale")) xformopt|=TJXOPT_
GRAY; |
| 852 if(!strcasecmp(argv[i], "-custom")) customFilter=dummyDC
TFilter; | 865 if(!strcasecmp(argv[i], "-custom")) customFilter=dummyDC
TFilter; |
| 853 if(!strcasecmp(argv[i], "-nooutput")) xformopt|=TJXOPT_N
OOUTPUT; | 866 if(!strcasecmp(argv[i], "-nooutput")) xformopt|=TJXOPT_N
OOUTPUT; |
| 854 if(!strcasecmp(argv[i], "-benchtime") && i<argc-1) | 867 if(!strcasecmp(argv[i], "-benchtime") && i<argc-1) |
| 855 { | 868 { |
| 856 double temp=atof(argv[++i]); | 869 double temp=atof(argv[++i]); |
| 857 if(temp>0.0) benchtime=temp; | 870 if(temp>0.0) benchtime=temp; |
| 858 else usage(argv[0]); | 871 else usage(argv[0]); |
| 859 } | 872 } |
| 873 if(!strcasecmp(argv[i], "-warmup") && i<argc-1) |
| 874 { |
| 875 int temp=atoi(argv[++i]); |
| 876 if(temp>=0) |
| 877 { |
| 878 warmup=temp; |
| 879 printf("Warmup runs = %d\n\n", warmup); |
| 880 } |
| 881 else usage(argv[0]); |
| 882 } |
| 860 if(!strcmp(argv[i], "-?")) usage(argv[0]); | 883 if(!strcmp(argv[i], "-?")) usage(argv[0]); |
| 861 if(!strcasecmp(argv[i], "-alloc")) flags&=(~TJFLAG_NOREA
LLOC); | 884 if(!strcasecmp(argv[i], "-alloc")) flags&=(~TJFLAG_NOREA
LLOC); |
| 862 if(!strcasecmp(argv[i], "-bmp")) ext="bmp"; | 885 if(!strcasecmp(argv[i], "-bmp")) ext="bmp"; |
| 886 if(!strcasecmp(argv[i], "-yuv")) |
| 887 { |
| 888 printf("Testing YUV planar encoding/decoding\n\n
"); |
| 889 doyuv=1; |
| 890 } |
| 891 if(!strcasecmp(argv[i], "-yuvpad") && i<argc-1) |
| 892 { |
| 893 int temp=atoi(argv[++i]); |
| 894 if(temp>=1) yuvpad=temp; |
| 895 } |
| 863 if(!strcasecmp(argv[i], "-subsamp") && i<argc-1) | 896 if(!strcasecmp(argv[i], "-subsamp") && i<argc-1) |
| 864 { | 897 { |
| 865 i++; | 898 i++; |
| 866 if(toupper(argv[i][0])=='G') subsamp=TJSAMP_GRAY
; | 899 if(toupper(argv[i][0])=='G') subsamp=TJSAMP_GRAY
; |
| 867 else | 900 else |
| 868 { | 901 { |
| 869 int temp=atoi(argv[i]); | 902 int temp=atoi(argv[i]); |
| 870 switch(temp) | 903 switch(temp) |
| 871 { | 904 { |
| 872 case 444: subsamp=TJSAMP_444;
break; | 905 case 444: subsamp=TJSAMP_444;
break; |
| 873 case 422: subsamp=TJSAMP_422;
break; | 906 case 422: subsamp=TJSAMP_422;
break; |
| 874 case 440: subsamp=TJSAMP_440;
break; | 907 case 440: subsamp=TJSAMP_440;
break; |
| 875 case 420: subsamp=TJSAMP_420;
break; | 908 case 420: subsamp=TJSAMP_420;
break; |
| 909 case 411: subsamp=TJSAMP_411;
break; |
| 876 } | 910 } |
| 877 } | 911 } |
| 878 } | 912 } |
| 913 if(!strcasecmp(argv[i], "-componly")) componly=1; |
| 914 if(!strcasecmp(argv[i], "-nowrite")) dowrite=0; |
| 879 } | 915 } |
| 880 } | 916 } |
| 881 | 917 |
| 882 if((sf.num!=1 || sf.denom!=1) && dotile) | 918 if((sf.num!=1 || sf.denom!=1) && dotile) |
| 883 { | 919 { |
| 884 printf("Disabling tiled compression/decompression tests, because
those tests do not\n"); | 920 printf("Disabling tiled compression/decompression tests, because
those tests do not\n"); |
| 885 printf("work when scaled decompression is enabled.\n"); | 921 printf("work when scaled decompression is enabled.\n"); |
| 886 dotile=0; | 922 dotile=0; |
| 887 } | 923 } |
| 888 | 924 |
| 889 » if(yuv && dotile) | 925 » if((flags&TJFLAG_NOREALLOC)==0 && dotile) |
| 890 { | 926 { |
| 891 printf("Disabling tiled compression/decompression tests, because
those tests do not\n"); | 927 printf("Disabling tiled compression/decompression tests, because
those tests do not\n"); |
| 892 » » printf("work when YUV encoding or decoding is enabled.\n\n"); | 928 » » printf("work when dynamic JPEG buffer allocation is enabled.\n\n
"); |
| 893 dotile=0; | 929 dotile=0; |
| 894 } | 930 } |
| 895 | 931 |
| 896 if(!decomponly) | 932 if(!decomponly) |
| 897 { | 933 { |
| 898 if(loadbmp(argv[1], &srcbuf, &w, &h, pf, (flags&TJFLAG_BOTTOMUP)
!=0)==-1) | 934 if(loadbmp(argv[1], &srcbuf, &w, &h, pf, (flags&TJFLAG_BOTTOMUP)
!=0)==-1) |
| 899 _throwbmp("loading bitmap"); | 935 _throwbmp("loading bitmap"); |
| 900 temp=strrchr(argv[1], '.'); | 936 temp=strrchr(argv[1], '.'); |
| 901 if(temp!=NULL) *temp='\0'; | 937 if(temp!=NULL) *temp='\0'; |
| 902 } | 938 } |
| 903 | 939 |
| 904 if(quiet==1 && !decomponly) | 940 if(quiet==1 && !decomponly) |
| 905 { | 941 { |
| 906 printf("All performance values in Mpixels/sec\n\n"); | 942 printf("All performance values in Mpixels/sec\n\n"); |
| 907 » » printf("Bitmap\tBitmap\tJPEG\tJPEG\t%s %s \tComp\tComp\tDecomp\n
", | 943 » » printf("Bitmap JPEG JPEG %s %s ", |
| 908 dotile? "Tile ":"Image", dotile? "Tile ":"Image"); | 944 dotile? "Tile ":"Image", dotile? "Tile ":"Image"); |
| 909 » » printf("Format\tOrder\tSubsamp\tQual\tWidth Height\tPerf \tRatio
\tPerf\n\n"); | 945 » » if(doyuv) printf("Encode "); |
| 946 » » printf("Comp Comp Decomp "); |
| 947 » » if(doyuv) printf("Decode"); |
| 948 » » printf("\n"); |
| 949 » » printf("Format Subsamp Qual Width Height "); |
| 950 » » if(doyuv) printf("Perf "); |
| 951 » » printf("Perf Ratio Perf "); |
| 952 » » if(doyuv) printf("Perf"); |
| 953 » » printf("\n\n"); |
| 910 } | 954 } |
| 911 | 955 |
| 912 if(decomponly) | 956 if(decomponly) |
| 913 { | 957 { |
| 914 » » dodecomptest(argv[1]); | 958 » » decompTest(argv[1]); |
| 915 printf("\n"); | 959 printf("\n"); |
| 916 goto bailout; | 960 goto bailout; |
| 917 } | 961 } |
| 918 if(subsamp>=0 && subsamp<TJ_NUMSAMP) | 962 if(subsamp>=0 && subsamp<TJ_NUMSAMP) |
| 919 { | 963 { |
| 920 for(i=maxqual; i>=minqual; i--) | 964 for(i=maxqual; i>=minqual; i--) |
| 921 » » » dotest(srcbuf, w, h, subsamp, i, argv[1]); | 965 » » » fullTest(srcbuf, w, h, subsamp, i, argv[1]); |
| 922 printf("\n"); | 966 printf("\n"); |
| 923 } | 967 } |
| 924 else | 968 else |
| 925 { | 969 { |
| 970 if(pf!=TJPF_CMYK) |
| 971 { |
| 972 for(i=maxqual; i>=minqual; i--) |
| 973 fullTest(srcbuf, w, h, TJSAMP_GRAY, i, argv[1]); |
| 974 printf("\n"); |
| 975 } |
| 926 for(i=maxqual; i>=minqual; i--) | 976 for(i=maxqual; i>=minqual; i--) |
| 927 » » » dotest(srcbuf, w, h, TJSAMP_GRAY, i, argv[1]); | 977 » » » fullTest(srcbuf, w, h, TJSAMP_420, i, argv[1]); |
| 928 printf("\n"); | 978 printf("\n"); |
| 929 for(i=maxqual; i>=minqual; i--) | 979 for(i=maxqual; i>=minqual; i--) |
| 930 » » » dotest(srcbuf, w, h, TJSAMP_420, i, argv[1]); | 980 » » » fullTest(srcbuf, w, h, TJSAMP_422, i, argv[1]); |
| 931 printf("\n"); | 981 printf("\n"); |
| 932 for(i=maxqual; i>=minqual; i--) | 982 for(i=maxqual; i>=minqual; i--) |
| 933 » » » dotest(srcbuf, w, h, TJSAMP_422, i, argv[1]); | 983 » » » fullTest(srcbuf, w, h, TJSAMP_444, i, argv[1]); |
| 934 » » printf("\n"); | |
| 935 » » for(i=maxqual; i>=minqual; i--) | |
| 936 » » » dotest(srcbuf, w, h, TJSAMP_444, i, argv[1]); | |
| 937 printf("\n"); | 984 printf("\n"); |
| 938 } | 985 } |
| 939 | 986 |
| 940 bailout: | 987 bailout: |
| 941 if(srcbuf) free(srcbuf); | 988 if(srcbuf) free(srcbuf); |
| 942 return retval; | 989 return retval; |
| 943 } | 990 } |
| OLD | NEW |