3
A simple test program for png image quantisation.
5
This program compares the pixel colors of two images and prints out
6
statistics on the differences between the images.
8
Statistics printed include:
10
standard deviation of error
13
The error is calculated as the linear distance between two colors in RGBA space.
15
Copyright (C) 2006 by Stuart Coyle
19
#define PNGCOMP_USAGE "usage: pngcomp [-vVh] image1.png image2.png\n\
20
options: v - verbose, does nothing as yet.\n\
21
V - version, prints version information.\n\
22
h - help, prionts this message.\n\
23
inputs: image1.png and image2.png are the two images that are to be compared.\n\
24
it is required that they be the same size.\n\
26
This program give some basic statistics about the difference between two images.\n\
27
It was created as a measure of various color quantization methods.\n"
29
#define MAX_COLOR_VAL 256
30
#define SQRT_3 1.73205
54
/* Image information structs */
55
static mainprog_info image1_info;
56
static mainprog_info image2_info;
58
float *imagediff(char* file1_name, char* file2_name);
59
float errval(pixel *p1, pixel *p2);
60
struct statistics *gather_stats(float *error_data);
61
void printstats(struct statistics* stats);
64
int main(int argc, char** argv)
68
char *file1_name = NULL;
69
char *file2_name = NULL;
71
int c; /* argument count */
74
float* err_image = NULL;
77
while((c = getopt(argc,argv,"hVv"))!=-1){
83
fprintf(stderr,"pngcomp %s\n",VERSION);
88
fprintf(stderr,PNGCOMP_USAGE);
93
fprintf (stderr, " unknown option `-%c'.\n", optopt);
96
" unknown option character `\\x%x'.\n",
99
fprintf(stderr,PNGCOMP_USAGE);
105
/* determine input files */
107
fprintf(stderr," pngcomp requires two input file names.\n");
111
file1_name=argv[optind];
114
fprintf(stderr," pngcomp requires two file names.\n");
118
file2_name=argv[optind];
123
err_image = imagediff(file1_name,file2_name);
124
if(err_image != NULL){
125
struct statistics *stats = gather_stats(err_image);
134
float *imagediff(char* file1_name, char* file2_name){
142
float* error_data = NULL;
144
/* Open the image files */
145
if((file1 = fopen(file1_name, "rb"))==NULL){
146
fprintf(stderr," error: cannot open %s for reading.\n",file1_name);
151
if((file2 = fopen(file2_name, "rb"))==NULL){
152
fprintf(stderr," error: cannot open %s for reading.\n",file2_name);
157
/* Read each image */
158
rwpng_read_image(file1,&image1_info);
160
if (image1_info.retval) {
161
fprintf(stderr, " rwpng_read_image() error\n");
166
rwpng_read_image(file2,&image2_info);
168
if (image2_info.retval) {
169
fprintf(stderr, " rwpng_read_image() error\n");
174
/* Can't do images that differ in size */
175
/* Is there any point? */
176
cols = image1_info.width;
177
rows= image1_info.height;
179
if(image2_info.width != cols || image2_info.height != rows){
180
fprintf(stderr, " images differ in size. cannot continue. \n");
185
if(!image1_info.rgba_data || !image2_info.rgba_data)
187
fprintf(stderr," no pixel data found.");
191
error_data = (float *)calloc(cols*rows*sizeof(float),sizeof(float));
192
if(error_data == NULL){
193
fprintf(stderr," cannot allocate error buffer.");
198
/* Calculate error value for each pixel */
199
for(row=0;(ulg)row < rows; ++row){
202
ulg offset = row*cols*4;
204
for( col=0;(ulg)col<cols;++col){
205
p1.r = image1_info.rgba_data[col*4+offset];
206
p1.g = image1_info.rgba_data[col*4+offset+1];
207
p1.b = image1_info.rgba_data[col*4+offset+2];
208
p1.a = image1_info.rgba_data[col*4+offset+3];
210
p2.r = image2_info.rgba_data[col*4+offset];
211
p2.g = image2_info.rgba_data[col*4+offset+1];
212
p2.b = image2_info.rgba_data[col*4+offset+2];
213
p2.a = image2_info.rgba_data[col*4+offset+3];
215
error_data[col*row] = errval(&p1,&p2);
223
/* Calculates cartesian distance of pixels in rgba space */
224
float errval(pixel *p1, pixel *p2){
227
long err_r = p1->r-p2->r;
228
long err_g = p1->g-p2->g;
229
long err_b = p1->b-p2->b;
230
long err_a = p1->a-p2->a;
231
err = err_r*err_r + err_g*err_g + err_b*err_b+ err_a*err_a;
232
return sqrt((double)err);
236
struct statistics *gather_stats(float *error_data){
239
struct statistics *stats = malloc(sizeof(struct statistics));
242
fprintf(stderr," Cannot allocate statistics struct.");
247
stats->max_error = 0.0;
248
stats->mean_error = 0.0;
249
stats->stddev_error = 0.0;
250
stats->n_pixels = image1_info.width*image1_info.height;
251
stats->correct_pixels = (ulg)0;
254
for(count=0;count<stats->n_pixels;count++){
255
float err = error_data[count];
256
if(err > stats->max_error) stats->max_error = err;
257
stats->mean_error += err;
258
if(err <= 0.0) stats->correct_pixels++;
260
stats->mean_error = (float)(stats->mean_error)/(float)(stats->n_pixels);
262
/* Standard deviation */
263
for(count=0;count<stats->n_pixels;count++){
264
double err= error_data[count];
265
stats->stddev_error += (err-stats->mean_error)*(err-stats->mean_error);
267
stats->stddev_error = sqrt(stats->stddev_error)/stats->n_pixels;
274
void printstats(struct statistics* stats){
275
printf("RGBA image color difference statistics.\n");
276
printf("Mean error: %f \n",stats->mean_error);
277
printf("Maximum error: %f \n",stats->max_error);
278
printf("Standard Deviation of Error: %f\n",stats->stddev_error);
279
printf("Image Dimensions %d x %d \n",image1_info.width,image1_info.height);
280
printf("Number of pixels: %d \n",stats->n_pixels);
281
printf("Number of correct pixels: %d\n",stats->correct_pixels);
282
printf("Percentage correct pixels: %f%\n",(float)stats->correct_pixels/(float)stats->n_pixels*100.0);