]> git.cworth.org Git - apitrace/blob - scripts/snapdiff.py
Make snapdiff.py smarter and more flexible to use.
[apitrace] / scripts / snapdiff.py
1 #!/usr/bin/env python
2 ##########################################################################
3 #
4 # Copyright 2008-2009 VMware, Inc.
5 # All Rights Reserved.
6 #
7 # Permission is hereby granted, free of charge, to any person obtaining a copy
8 # of this software and associated documentation files (the "Software"), to deal
9 # in the Software without restriction, including without limitation the rights
10 # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 # copies of the Software, and to permit persons to whom the Software is
12 # furnished to do so, subject to the following conditions:
13 #
14 # The above copyright notice and this permission notice shall be included in
15 # all copies or substantial portions of the Software.
16 #
17 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 # THE SOFTWARE.
24 #
25 ##########################################################################/
26
27
28 import sys
29 import os.path
30 import subprocess
31 import optparse
32
33 import Image
34
35
36 thumb_size = 320, 320
37
38
39 def compare(im, ref):
40     import ImageMath
41     # See http://www.pythonware.com/library/pil/handbook/imagemath.htm
42     mask = ImageMath.eval("min(abs(a - b), 1)", a=im, b=ref)
43     gray = ref.convert('L')
44     # TODO
45
46
47 def surface(html, image):
48     if True:
49         name, ext = os.path.splitext(image)
50         thumb = name + '.thumb' + ext
51         if os.path.exists(image) \
52            and (not os.path.exists(thumb) \
53                 or os.path.getmtime(thumb) < os.path.getmtime(image)):
54             im = Image.open(image)
55             im.thumbnail(thumb_size)
56             im.save(thumb)
57     else:
58         thumb = image
59     html.write('        <td><a href="%s"><img src="%s"/></a></td>\n' % (image, thumb))
60
61
62 def is_image(path):
63     return \
64         path.endswith('.png') \
65         and not path.endswith('.diff.png') \
66         and not path.endswith('.thumb.png')
67
68
69 def find_images(prefix):
70     prefix = os.path.abspath(prefix)
71     if os.path.isdir(prefix):
72         prefix_dir = prefix
73     else:
74         prefix_dir = os.path.dirname(prefix)
75
76     images = []
77     for dirname, dirnames, filenames in os.walk(prefix_dir, followlinks=True):
78         for filename in filenames:
79             filepath = os.path.join(dirname, filename)
80             if filepath.startswith(prefix) and is_image(filepath):
81                 images.append(filepath[len(prefix):])
82
83     return images
84
85
86 def main():
87     optparser = optparse.OptionParser(
88         usage="\n\t%prog [options] <ref_prefix> <src_prefix>",
89         version="%%prog")
90     optparser.add_option(
91         '-o', '--output', metavar='FILE',
92         type="string", dest="output",
93         help="output filename [stdout]")
94     optparser.add_option(
95         '-f', '--fuzz',
96         type="string", dest="fuzz", default='5%',
97         help="fuzz [default: %default]")
98
99     (options, args) = optparser.parse_args(sys.argv[1:])
100
101     if len(args) != 2:
102         optparser.error('incorrect number of arguments')
103
104     ref_prefix = args[0]
105     src_prefix = args[1]
106
107     ref_images = find_images(ref_prefix)
108     src_images = find_images(src_prefix)
109     images = list(set(ref_images).intersection(set(src_images)))
110     images.sort()
111
112     if options.output:
113         html = open(options.output, 'wt')
114     else:
115         html = sys.stdout
116     html.write('<html>\n')
117     html.write('  <body>\n')
118     html.write('    <table border="1">\n')
119     html.write('      <tr><th>%s</th><th>%s</th><th>&Delta;</th></tr>\n' % (ref_prefix, src_prefix))
120     for image in images:
121         ref_image = ref_prefix + image
122         src_image = src_prefix + image
123         root, ext = os.path.splitext(src_image)
124         delta_image = "%s.diff.png" % (root, )
125         if os.path.exists(ref_image) and os.path.exists(src_image):
126             if not os.path.exists(delta_image) \
127                or (os.path.getmtime(delta_image) < os.path.getmtime(ref_image) \
128                    and os.path.getmtime(delta_image) < os.path.getmtime(src_image)):
129                 subprocess.call(["compare", '-metric', 'AE', '-fuzz', options.fuzz, ref_image, src_image, delta_image])
130
131             html.write('      <tr>\n')
132             surface(html, ref_image)
133             surface(html, src_image)
134             surface(html, delta_image)
135             html.write('      </tr>\n')
136             html.flush()
137     html.write('    </table>\n')
138     html.write('  </body>\n')
139     html.write('</html>\n')
140
141
142 if __name__ == '__main__':
143     main()