44 #define DISPLAY_SCALING 255
47 typedef enum {DEFAULT_METRICS, MAX_METRIC, MSE_METRIC, RMSE_METRIC,
74 int width,
int height,
int num_channels,
float D);
75 void basic_metrics(
float *max_diff,
float *mse,
const float *A,
const float *B,
76 int width,
int height,
int num_channels,
int pad);
82 puts(
"Image difference calculator, P. Getreuer 2010-2011, 2013\n");
83 puts(
"Syntax: imdiff [options] <exact file> <distorted file>\n"
86 puts(
" -m <metric> metric to use for comparison, choices are");
87 puts(
" max Max absolute difference, max_n |A_n - B_n|");
88 puts(
" mse Mean squared error, 1/N sum |A_n - B_n|^2");
89 puts(
" rmse Root mean squared error, (MSE)^1/2");
90 puts(
" psnr Peak signal-to-noise ratio, -10 log10(MSE/255^2)");
91 puts(
" -s Compute metric separately for each channel");
92 puts(
" -p <pad> Remove a margin of <pad> pixels before comparison");
93 puts(
" -D <number> D parameter for difference image\n");
95 puts(
" -q <number> Quality for saving JPEG images (0 to 100)\n");
97 puts(
"Alternatively, a difference image is generated by the syntax\n"
98 " imdiff [-D <number>] <exact file> <distorted file> <output file>\n");
99 puts(
"The difference image is computed as\n"
100 " D_n = 255/D (A_n - B_n) + 255/2.\n"
101 "Values outside of the range [0,255] are saturated.\n");
104 " imdiff -mpsnr frog-exact.png frog-4x.png");
106 " imdiff -mpsnr frog-exact.bmp frog-4x.bmp");
110 int main(
int argc,
char *argv[])
117 } A = {NULL, 0, 0}, B = {NULL, 0, 0};
119 float max_diff, max_diff_c[3], mse, mse_c[3];
120 int channel, status = 1;
127 IMAGEIO_FLOAT | IMAGEIO_RGB | IMAGEIO_PLANAR)))
132 IMAGEIO_FLOAT | IMAGEIO_RGB | IMAGEIO_PLANAR)))
135 if(A.width != B.width || A.height != B.height)
137 fprintf(stderr,
"Image sizes don't match, %dx%d vs. %dx%d.\n",
138 A.width, A.height, B.width, B.height);
141 else if(A.width <= 2 * param.
pad || A.height <= 2 * param.
pad)
144 "Removal of %d-pixel padding removes entire %dx%d image.\n",
145 param.
pad, A.width, A.height);
154 IMAGEIO_FLOAT | IMAGEIO_RGB | IMAGEIO_PLANAR, param.
jpeg_quality)))
162 for(channel = 0; channel < 3; channel++)
165 A.data + channel*A.width*A.height,
166 B.data + channel*B.width*B.height,
167 A.width, A.height, 1, param.
pad);
169 if(max_diff_c[channel] > max_diff)
170 max_diff = max_diff_c[channel];
172 mse += mse_c[channel];
179 case DEFAULT_METRICS:
182 printf(
"Maximum absolute difference: %g\n",
184 printf(
"Root mean squared error: %.4f\n",
186 printf(
"Peak signal-to-noise ratio: %.4f\n",
191 printf(
"Maximum absolute difference: %g %g %g\n",
195 printf(
"Root mean squared error: %.4f %.4f %.4f\n",
199 printf(
"Peak signal-to-noise ratio: %.4f %.4f %.4f\n",
200 -10 * log10(mse_c[0]),
201 -10 * log10(mse_c[1]),
202 -10 * log10(mse_c[2]));
218 printf(
"%.4f %.4f %.4f\n",
227 printf(
"%.4f %.4f %.4f\n",
234 printf(
"%.4f\n", -10 * log10(mse));
236 printf(
"%.4f %.4f %.4f\n",
237 -10 * log10(mse_c[0]),
238 -10 * log10(mse_c[1]),
239 -10 * log10(mse_c[2]));
255 int width,
int height,
int num_channels,
float D)
257 const int num_el = num_channels * width * height;
262 for(n = 0; n < num_el; n++)
263 A[n] = (A[n] - B[n]) / D + 0.5f;
267 void basic_metrics(
float *max_diff,
float *mse,
const float *A,
const float *B,
268 int width,
int height,
int num_channels,
int pad)
270 float diff, cur_max = 0;
271 double accum_mse = 0;
272 int x, y, channel, n;
274 for(channel = 0; channel < num_channels; channel++)
275 for(y = pad; y < height - pad; y++)
276 for(x = pad; x < width - pad; x++)
278 n = x + width * (y + height * channel);
279 diff = (float)fabs(A[n] - B[n]);
284 accum_mse += diff*diff;
289 accum_mse / (num_channels * (width - 2 * pad) * (height - 2 * pad)));
308 param->
metric = DEFAULT_METRICS;
316 for(i = 1; i < argc;)
318 if(argv[i] && argv[i][0] ==
'-')
320 if((option_char = argv[i][1]) == 0)
322 fprintf(stderr,
"Invalid parameter format.\n");
327 option_string = &argv[i][2];
329 option_string = argv[i];
332 fprintf(stderr,
"Invalid parameter format.\n");
339 param->
pad = atoi(option_string);
343 fprintf(stderr,
"pad must be nonnegative.\n");
352 param->
D = (float)atof(option_string);
356 fprintf(stderr,
"D must be positive.\n");
361 if(!strcmp(option_string,
"max"))
362 param->
metric = MAX_METRIC;
363 else if(!strcmp(option_string,
"mse"))
364 param->
metric = MSE_METRIC;
365 else if(!strcmp(option_string,
"rmse"))
366 param->
metric = RMSE_METRIC;
367 else if(!strcmp(option_string,
"psnr"))
368 param->
metric = PSNR_METRIC;
370 fprintf(stderr,
"Unknown metric.\n");
380 "JPEG quality must be between 0 and 100.\n");
389 if(isprint(option_char))
390 fprintf(stderr,
"Unknown option \"-%c\".\n", option_char);
392 fprintf(stderr,
"Unknown option.\n");