~ubuntu-branches/ubuntu/vivid/pngnq/vivid

« back to all changes in this revision

Viewing changes to 0.4.1/pngcomp.c

  • Committer: Bazaar Package Importer
  • Author(s): Nelson A. de Oliveira
  • Date: 2006-07-15 00:24:51 UTC
  • mfrom: (1.1.1 upstream) (2.1.1 edgy)
  • Revision ID: james.westby@ubuntu.com-20060715002451-bbdi09ckv5rn0e7g
Tags: 0.4.1-1
New upstream release (Closes: #378148).

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* pngcomp.c
 
2
 
 
3
A simple test program for png image quantisation. 
 
4
  
 
5
This program compares the pixel colors of two images and prints out 
 
6
statistics on the differences between the images. 
 
7
 
 
8
Statistics printed include:
 
9
mean error
 
10
standard deviation of error
 
11
maximum error
 
12
             
 
13
The error is calculated as the linear distance between two colors in RGBA space.
 
14
 
 
15
Copyright (C) 2006 by Stuart Coyle
 
16
 
 
17
*/
 
18
#define VERSION "0.1"
 
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\
 
25
\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"
 
28
 
 
29
#define MAX_COLOR_VAL 256
 
30
#define SQRT_3 1.73205
 
31
 
 
32
#include <stdlib.h>
 
33
#include <stdio.h>
 
34
#include <string.h>
 
35
#include <unistd.h>
 
36
#include <math.h>
 
37
#include <ctype.h>
 
38
 
 
39
#include "png.h"
 
40
#include "rwpng.h"
 
41
 
 
42
typedef struct {
 
43
  uch r, g, b, a;
 
44
} pixel;
 
45
 
 
46
struct statistics {
 
47
  double max_error;
 
48
  double mean_error;
 
49
  double stddev_error;
 
50
  ulg   n_pixels;
 
51
  ulg   correct_pixels;
 
52
};
 
53
 
 
54
/* Image information structs */
 
55
static mainprog_info image1_info;
 
56
static mainprog_info image2_info;
 
57
 
 
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);
 
62
 
 
63
 
 
64
int main(int argc, char** argv)
 
65
{
 
66
  int verbose = 0;
 
67
 
 
68
  char *file1_name = NULL;
 
69
  char *file2_name = NULL;
 
70
 
 
71
  int c; /* argument count */
 
72
 
 
73
  int retval = 0;
 
74
  float* err_image = NULL;
 
75
 
 
76
  /* Parse arguments */
 
77
  while((c = getopt(argc,argv,"hVv"))!=-1){
 
78
    switch(c){
 
79
    case 'v':
 
80
      verbose = 1;
 
81
      break;
 
82
    case 'V':
 
83
      fprintf(stderr,"pngcomp %s\n",VERSION);
 
84
      rwpng_version_info();
 
85
      exit(EXIT_SUCCESS);
 
86
      break;
 
87
    case 'h':
 
88
      fprintf(stderr,PNGCOMP_USAGE);
 
89
      exit(EXIT_SUCCESS);
 
90
      break;
 
91
    case '?':      
 
92
      if (isprint(optopt))
 
93
        fprintf (stderr, "  unknown option `-%c'.\n", optopt);
 
94
      else
 
95
        fprintf (stderr,
 
96
                 "  unknown option character `\\x%x'.\n",
 
97
                 optopt);
 
98
    default:
 
99
      fprintf(stderr,PNGCOMP_USAGE);
 
100
      exit(EXIT_FAILURE);
 
101
    }
 
102
  }
 
103
 
 
104
 
 
105
  /* determine input files */
 
106
  if(optind == argc){
 
107
    fprintf(stderr,"  pngcomp requires two input file names.\n");
 
108
    exit(EXIT_FAILURE);
 
109
  }
 
110
  else{
 
111
    file1_name=argv[optind];
 
112
    optind++;
 
113
    if(optind == argc){
 
114
      fprintf(stderr,"  pngcomp requires two file names.\n");
 
115
      exit(EXIT_FAILURE);
 
116
    }
 
117
    else{
 
118
      file2_name=argv[optind];
 
119
      optind++;
 
120
    }
 
121
  }
 
122
 
 
123
  err_image = imagediff(file1_name,file2_name);
 
124
  if(err_image != NULL){
 
125
    struct statistics *stats = gather_stats(err_image);
 
126
    printstats(stats);
 
127
  }
 
128
 
 
129
  exit(retval);
 
130
 
 
131
}
 
132
 
 
133
 
 
134
float *imagediff(char* file1_name, char* file2_name){
 
135
  
 
136
  FILE *file1 = NULL;
 
137
  FILE *file2 = NULL;  
 
138
    
 
139
  ulg cols, rows;
 
140
  ulg row;
 
141
 
 
142
  float* error_data = NULL;
 
143
 
 
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);
 
147
    fflush(stderr);
 
148
    return NULL;
 
149
  }
 
150
 
 
151
  if((file2 = fopen(file2_name, "rb"))==NULL){
 
152
    fprintf(stderr,"  error: cannot open %s for reading.\n",file2_name);
 
153
    fflush(stderr);
 
154
    return NULL;
 
155
  }
 
156
 
 
157
  /* Read each image */
 
158
  rwpng_read_image(file1,&image1_info);
 
159
  fclose(file1);
 
160
  if (image1_info.retval) {
 
161
    fprintf(stderr, "  rwpng_read_image() error\n");
 
162
    fflush(stderr);
 
163
    return NULL; 
 
164
  }
 
165
 
 
166
  rwpng_read_image(file2,&image2_info);
 
167
  fclose(file2);
 
168
  if (image2_info.retval) {
 
169
    fprintf(stderr, "  rwpng_read_image() error\n");
 
170
    fflush(stderr);
 
171
    return NULL; 
 
172
  }
 
173
 
 
174
  /* Can't do images that differ in size */
 
175
  /* Is there any point? */
 
176
  cols = image1_info.width;
 
177
  rows= image1_info.height;
 
178
 
 
179
  if(image2_info.width != cols || image2_info.height != rows){
 
180
    fprintf(stderr, "  images differ in size. cannot continue. \n");
 
181
    return(NULL);
 
182
  }
 
183
  
 
184
   
 
185
  if(!image1_info.rgba_data || !image2_info.rgba_data)
 
186
    {
 
187
      fprintf(stderr,"  no pixel data found.");
 
188
      return(NULL);
 
189
    }
 
190
 
 
191
  error_data = (float *)calloc(cols*rows*sizeof(float),sizeof(float));
 
192
  if(error_data == NULL){
 
193
    fprintf(stderr,"  cannot allocate error buffer.");
 
194
    return(NULL);
 
195
  }
 
196
 
 
197
  
 
198
  /* Calculate error value for each pixel */
 
199
  for(row=0;(ulg)row < rows; ++row){
 
200
    int col;
 
201
    pixel p1, p2;
 
202
    ulg offset = row*cols*4;
 
203
 
 
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];
 
209
 
 
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];
 
214
 
 
215
      error_data[col*row] = errval(&p1,&p2);
 
216
      
 
217
    }
 
218
  }
 
219
  return error_data;
 
220
}
 
221
 
 
222
 
 
223
/* Calculates cartesian distance of pixels in rgba space */
 
224
float errval(pixel *p1, pixel *p2){
 
225
  long err;
 
226
 
 
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);
 
233
}
 
234
 
 
235
 
 
236
struct statistics *gather_stats(float *error_data){
 
237
 
 
238
  int count;
 
239
  struct statistics *stats = malloc(sizeof(struct statistics));
 
240
  
 
241
  if(stats == NULL){
 
242
    fprintf(stderr,"  Cannot allocate statistics struct.");
 
243
    return(NULL);
 
244
  }
 
245
  
 
246
 
 
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;
 
252
 
 
253
  /* Basic stats */
 
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++;
 
259
  }
 
260
  stats->mean_error = (float)(stats->mean_error)/(float)(stats->n_pixels);
 
261
  
 
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);
 
266
 }
 
267
 stats->stddev_error = sqrt(stats->stddev_error)/stats->n_pixels;
 
268
 
 
269
 return stats;
 
270
 
 
271
}
 
272
 
 
273
 
 
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);
 
283
 
 
284
}
 
285