1
/*
2
  PerceptualDiff - a program that compares two images using a perceptual metric
3
  based on the paper :
4
  A perceptual metric for production testing. Journal of graphics tools, 9(4):33-40, 2004, Hector Yee
5
  Copyright (C) 2006 Yangli Hector Yee
6

            
7
  This program is free software; you can redistribute it and/or modify it under the terms of the
8
  GNU General Public License as published by the Free Software Foundation; either version 2 of the License,
9
  or (at your option) any later version.
10

            
11
  This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
12
  without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13
  See the GNU General Public License for more details.
14

            
15
  You should have received a copy of the GNU General Public License along with this program;
16
  if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
17
*/
18

            
19
#include <stdio.h>
20
#include <stdint.h>
21
#include <string.h>
22
#include <math.h>
23
#include "lpyramid.h"
24
#include "args.h"
25
#include "pdiff.h"
26

            
27
static bool Yee_Compare(args_t *args)
28
{
29
    unsigned int width_a, height_a, stride_a;
30
    unsigned char *data_a, *row_a;
31
    uint32_t *pixel_a;
32
    unsigned int width_b, height_b, stride_b;
33
    unsigned char *data_b, *row_b;
34
    uint32_t *pixel_b;
35
    unsigned int x, y, pixels_failed;
36
    bool identical = true;
37

            
38
    width_a = cairo_image_surface_get_width (args->surface_a);
39
    height_a = cairo_image_surface_get_height (args->surface_a);
40
    stride_a = cairo_image_surface_get_stride (args->surface_a);
41
    data_a = cairo_image_surface_get_data (args->surface_a);
42

            
43
    width_b = cairo_image_surface_get_width (args->surface_b);
44
    height_b = cairo_image_surface_get_height (args->surface_b);
45
    stride_b = cairo_image_surface_get_stride (args->surface_b);
46
    data_b = cairo_image_surface_get_data (args->surface_b);
47

            
48
    if ((width_a != width_b) || (height_a != height_b)) {
49
	printf ("FAIL: Image dimensions do not match\n");
50
	return false;
51
    }
52

            
53
    identical = true;
54

            
55
    for (y = 0; y < height_a; y++) {
56
	row_a = data_a + y * stride_a;
57
	row_b = data_b + y * stride_b;
58
	pixel_a = (uint32_t *) row_a;
59
	pixel_b = (uint32_t *) row_b;
60
	for (x = 0; x < width_a; x++) {
61
	    if (*pixel_a != *pixel_b) {
62
		identical = false;
63
	    }
64
	    pixel_a++;
65
	    pixel_b++;
66
	}
67
    }
68
    if (identical) {
69
	printf ("PASS: Images are binary identical\n");
70
	return true;
71
    }
72

            
73
    pixels_failed = pdiff_compare (args->surface_a, args->surface_b,
74
				   args->Gamma, args->Luminance,
75
				   args->FieldOfView);
76

            
77
    if (pixels_failed < args->ThresholdPixels) {
78
	printf ("PASS: Images are perceptually indistinguishable\n");
79
	return true;
80
    }
81

            
82
    printf("FAIL: Images are visibly different\n"
83
	   "%d pixels are different\n", pixels_failed);
84

            
85
    return false;
86
}
87

            
88
int main(int argc, char **argv)
89
{
90
    args_t args;
91

            
92
    args_init (&args);
93

            
94
    if (!args_parse (&args, argc, argv)) {
95
	return -1;
96
    } else {
97
	if (args.Verbose)
98
	    args_print (&args);
99
    }
100
    return ! Yee_Compare(&args);
101
}