]> git.cworth.org Git - apitrace/blob - scripts/snapdiff.py
Remove dead ImageMagick's compare invocation code.
[apitrace] / scripts / snapdiff.py
1 #!/usr/bin/env python
2 ##########################################################################
3 #
4 # Copyright 2011 Jose Fonseca
5 # Copyright 2008-2009 VMware, Inc.
6 # All Rights Reserved.
7 #
8 # Permission is hereby granted, free of charge, to any person obtaining a copy
9 # of this software and associated documentation files (the "Software"), to deal
10 # in the Software without restriction, including without limitation the rights
11 # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 # copies of the Software, and to permit persons to whom the Software is
13 # furnished to do so, subject to the following conditions:
14 #
15 # The above copyright notice and this permission notice shall be included in
16 # all copies or substantial portions of the Software.
17 #
18 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 # THE SOFTWARE.
25 #
26 ##########################################################################/
27
28
29 '''Snapshot (image) comparison script.
30 '''
31
32
33 import sys
34 import os.path
35 import optparse
36 import math
37 import operator
38
39 import Image
40 import ImageChops
41 import ImageEnhance
42
43
44 thumb_size = 320, 320
45
46
47 def compare(ref_image, src_image, delta_image):
48     ref_im = Image.open(ref_image)
49     src_im = Image.open(src_image)
50
51     ref_im = ref_im.convert('RGB')
52     src_im = src_im.convert('RGB')
53
54     diff = ImageChops.difference(src_im, ref_im)
55
56     # make a difference image similar to ImageMagick's compare utility
57     mask = ImageEnhance.Brightness(diff).enhance(1.0/options.fuzz)
58     mask = mask.convert('L')
59
60     lowlight = Image.new('RGB', src_im.size, (0xff, 0xff, 0xff))
61     highlight = Image.new('RGB', src_im.size, (0xf1, 0x00, 0x1e))
62     delta_im = Image.composite(highlight, lowlight, mask)
63
64     delta_im = Image.blend(src_im, delta_im, 0xcc/255.0)
65     delta_im.save(delta_image)
66
67     # See also http://effbot.org/zone/pil-comparing-images.htm
68     # TODO: this is approximate due to the grayscale conversion
69     h = diff.convert('L').histogram()
70     ae = sum(h[int(255 * options.fuzz) + 1 : 256])
71     return ae
72
73
74 def surface(html, image):
75     if True:
76         name, ext = os.path.splitext(image)
77         thumb = name + '.thumb' + ext
78         if os.path.exists(image) \
79            and (not os.path.exists(thumb) \
80                 or os.path.getmtime(thumb) < os.path.getmtime(image)):
81             im = Image.open(image)
82             im.thumbnail(thumb_size)
83             im.save(thumb)
84     else:
85         thumb = image
86     html.write('        <td><a href="%s"><img src="%s"/></a></td>\n' % (image, thumb))
87
88
89 def is_image(path):
90     return \
91         path.endswith('.png') \
92         and not path.endswith('.diff.png') \
93         and not path.endswith('.thumb.png')
94
95
96 def find_images(prefix):
97     prefix = os.path.abspath(prefix)
98     if os.path.isdir(prefix):
99         prefix_dir = prefix
100     else:
101         prefix_dir = os.path.dirname(prefix)
102
103     images = []
104     for dirname, dirnames, filenames in os.walk(prefix_dir, followlinks=True):
105         for filename in filenames:
106             filepath = os.path.join(dirname, filename)
107             if filepath.startswith(prefix) and is_image(filepath):
108                 images.append(filepath[len(prefix):])
109
110     return images
111
112
113 def main():
114     global options
115
116     optparser = optparse.OptionParser(
117         usage="\n\t%prog [options] <ref_prefix> <src_prefix>",
118         version="%%prog")
119     optparser.add_option(
120         '-o', '--output', metavar='FILE',
121         type="string", dest="output", default='index.html',
122         help="output filename [default: %default]")
123     optparser.add_option(
124         '-f', '--fuzz',
125         type="float", dest="fuzz", default=.05,
126         help="fuzz ratio [default: %default]")
127     optparser.add_option(
128         '--overwrite',
129         action="store_true", dest="overwrite", default=False,
130         help="overwrite")
131
132     (options, args) = optparser.parse_args(sys.argv[1:])
133
134     if len(args) != 2:
135         optparser.error('incorrect number of arguments')
136
137     ref_prefix = args[0]
138     src_prefix = args[1]
139
140     ref_images = find_images(ref_prefix)
141     src_images = find_images(src_prefix)
142     images = list(set(ref_images).intersection(set(src_images)))
143     images.sort()
144
145     if options.output:
146         html = open(options.output, 'wt')
147     else:
148         html = sys.stdout
149     html.write('<html>\n')
150     html.write('  <body>\n')
151     html.write('    <table border="1">\n')
152     html.write('      <tr><th>%s</th><th>%s</th><th>&Delta;</th></tr>\n' % (ref_prefix, src_prefix))
153     for image in images:
154         ref_image = ref_prefix + image
155         src_image = src_prefix + image
156         root, ext = os.path.splitext(src_image)
157         delta_image = "%s.diff.png" % (root, )
158         if os.path.exists(ref_image) and os.path.exists(src_image):
159             if options.overwrite \
160                or not os.path.exists(delta_image) \
161                or (os.path.getmtime(delta_image) < os.path.getmtime(ref_image) \
162                    and os.path.getmtime(delta_image) < os.path.getmtime(src_image)):
163                 compare(ref_image, src_image, delta_image)
164
165             html.write('      <tr>\n')
166             surface(html, ref_image)
167             surface(html, src_image)
168             surface(html, delta_image)
169             html.write('      </tr>\n')
170             html.flush()
171     html.write('    </table>\n')
172     html.write('  </body>\n')
173     html.write('</html>\n')
174
175
176 if __name__ == '__main__':
177     main()