aboutsummaryrefslogtreecommitdiffhomepage
path: root/tools/test_pictures.py
blob: d26d3b9c0c333e367c56cbb4341cc7c427add51f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
'''
Compares the rendererings of serialized SkPictures to expected images.

Launch with --help to see more information.


Copyright 2012 Google Inc.

Use of this source code is governed by a BSD-style license that can be
found in the LICENSE file.
'''
# common Python modules
import os
import optparse
import sys
import shutil
import tempfile

USAGE_STRING = 'Usage: %s input... expectedDir'
HELP_STRING = '''

Compares the renderings of serialized SkPicture files and directories specified
by input with the images in expectedDir. Note, files in directoriers are
expected to end with .skp.
'''

def RunCommand(command):
    """Run a command.

    @param command the command as a single string
    """
    print 'running command [%s]...' % command
    os.system(command)


def FindPathToProgram(program):
    """Return path to an existing program binary, or raise an exception if we
    cannot find one.

    @param program the name of the program that is being looked for
    """
    trunk_path = os.path.abspath(os.path.join(os.path.dirname(__file__),
                                              os.pardir))
    possible_paths = [os.path.join(trunk_path, 'out', 'Release', program),
                      os.path.join(trunk_path, 'out', 'Debug', program),
                      os.path.join(trunk_path, 'out', 'Release',
                                   program + ".exe"),
                      os.path.join(trunk_path, 'out', 'Debug',
                                   program + ".exe")]
    for try_path in possible_paths:
        if os.path.isfile(try_path):
            return try_path
    raise Exception('cannot find %s in paths %s; maybe you need to '
                    'build %s?' % (program, possible_paths, program))


def RenderImages(inputs, render_dir, options):
    """Renders the serialized SkPictures.

    Uses the render_pictures program to do the rendering.

    @param inputs the location(s) to read the serlialized SkPictures
    @param render_dir the location to write out the rendered images
    """
    renderer_path = FindPathToProgram('render_pictures')
    inputs_as_string = " ".join(inputs)
    command = '%s %s %s' % (renderer_path, inputs_as_string, render_dir)

    if (options.mode is not None):
        command += ' --mode %s' % ' '.join(options.mode)

    if (options.device is not None):
        command += ' --device %s' % options.device

    RunCommand(command)


def DiffImages(expected_dir, comparison_dir, diff_dir):
    """Diffs the rendered SkPicture images with the baseline images.

    Uses the skdiff program to do the diffing.

    @param expected_dir the location of the baseline images.
    @param comparison_dir the location of the images to comapre with the
           baseline
    @param diff_dir the location to write out the diff results
    """
    skdiff_path = FindPathToProgram('skdiff')
    RunCommand('%s %s %s %s %s' %
               (skdiff_path, expected_dir, comparison_dir, diff_dir,
                '--noprintdirs'))


def Cleanup(options, render_dir, diff_dir):
    """Deletes any temporary folders and files created.

    @param options The OptionParser object that parsed if render_dir or diff_dir
           was set
    @param render_dir the directory where the rendered images were written
    @param diff_dir the directory where the diff results were written
    """
    if (not options.render_dir):
        if (os.path.isdir(render_dir)):
            shutil.rmtree(render_dir)
    if (not options.diff_dir):
        if (os.path.isdir(diff_dir)):
            shutil.rmtree(diff_dir)


def ModeParse(option, opt_str, value, parser):
    """Parses the --mode option of the commandline.

    The --mode option will either take in three parameters (if tile or
    pow2tile) or a single parameter (otherwise).
    """
    result = [value]
    if value == "tile":
          if (len(parser.rargs) < 2):
              raise optparse.OptionValueError(("--mode tile mising width"
                                               " and/or height parameters"))
          result.extend(parser.rargs[:2])
          del parser.rargs[:2]
    elif value == "pow2tile":
          if (len(parser.rargs) < 2):
              raise optparse.OptionValueError(("--mode pow2tile mising minWidth"
                                               " and/or height parameters"))
          result.extend(parser.rargs[:2])
          del parser.rargs[:2]

    setattr(parser.values, option.dest, result)


def Main(args):
    """Allow other scripts to call this script with fake command-line args.

    @param The commandline argument list
    """
    parser = optparse.OptionParser(USAGE_STRING % '%prog' + HELP_STRING)
    parser.add_option('--render_dir', dest='render_dir',
                    help = ("specify the location to output the rendered files."
                              " Default is a temp directory."))
    parser.add_option('--diff_dir', dest='diff_dir',
                    help = ("specify the location to output the diff files."
                              " Default is a temp directory."))
    parser.add_option('--mode', dest='mode', type='string',
                      action="callback", callback=ModeParse,
                      help = ("specify how rendering is to be done."))
    parser.add_option('--device', dest='device',
                      help = ("specify the device to render to."))

    options, arguments = parser.parse_args(args)

    if (len(arguments) < 3):
        print("Expected at least one input and one ouput folder.")
        parser.print_help()
        sys.exit(-1)

    inputs = arguments[1:-1]
    expected_dir = arguments[-1]

    if (options.render_dir):
        render_dir = options.render_dir
    else:
        render_dir = tempfile.mkdtemp()

    if (options.diff_dir):
        diff_dir = options.diff_dir
    else:
        diff_dir = tempfile.mkdtemp()

    try:
        RenderImages(inputs, render_dir, options)
        DiffImages(expected_dir, render_dir, diff_dir)
    finally:
        Cleanup(options, render_dir, diff_dir)

if __name__ == '__main__':
    Main(sys.argv)