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 |