Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(208)

Side by Side Diff: gm/rebaseline_server/imagediffdb.py

Issue 457203003: Modify skpdiff to write diffs directly to provided directories (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Fixed issue that broke windows build (hopefully) Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | gm/rebaseline_server/static/live-loader.js » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 #!/usr/bin/python 1 #!/usr/bin/python
2 2
3 """ 3 """
4 Copyright 2013 Google Inc. 4 Copyright 2013 Google Inc.
5 5
6 Use of this source code is governed by a BSD-style license that can be 6 Use of this source code is governed by a BSD-style license that can be
7 found in the LICENSE file. 7 found in the LICENSE file.
8 8
9 Calulate differences between image pairs, and store them in a database. 9 Calulate differences between image pairs, and store them in a database.
10 """ 10 """
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
118 # Return early if we do not need to generate diffs. 118 # Return early if we do not need to generate diffs.
119 if (expected_image_url == actual_image_url or 119 if (expected_image_url == actual_image_url or
120 not expected_image_url or not actual_image_url): 120 not expected_image_url or not actual_image_url):
121 return 121 return
122 122
123 # Get all diff images and values using the skpdiff binary. 123 # Get all diff images and values using the skpdiff binary.
124 skpdiff_output_dir = tempfile.mkdtemp() 124 skpdiff_output_dir = tempfile.mkdtemp()
125 try: 125 try:
126 skpdiff_summary_file = os.path.join(skpdiff_output_dir, 126 skpdiff_summary_file = os.path.join(skpdiff_output_dir,
127 'skpdiff-output.json') 127 'skpdiff-output.json')
128 skpdiff_rgbdiff_dir = os.path.join(skpdiff_output_dir, 'rgbDiff') 128 skpdiff_rgbdiff_dir = os.path.join(storage_root, RGBDIFFS_SUBDIR)
129 skpdiff_whitediff_dir = os.path.join(skpdiff_output_dir, 'whiteDiff') 129 skpdiff_whitediff_dir = os.path.join(storage_root, WHITEDIFFS_SUBDIR)
130 _mkdir_unless_exists(skpdiff_rgbdiff_dir)
131 _mkdir_unless_exists(skpdiff_rgbdiff_dir)
130 132
131 # TODO(epoger): Consider calling skpdiff ONCE for all image pairs, 133 # TODO(epoger): Consider calling skpdiff ONCE for all image pairs,
132 # instead of calling it separately for each image pair. 134 # instead of calling it separately for each image pair.
133 # Pro: we'll incur less overhead from making repeated system calls, 135 # Pro: we'll incur less overhead from making repeated system calls,
134 # spinning up the skpdiff binary, etc. 136 # spinning up the skpdiff binary, etc.
135 # Con: we would have to wait until all image pairs were loaded before 137 # Con: we would have to wait until all image pairs were loaded before
136 # generating any of the diffs? 138 # generating any of the diffs?
139 # Note(stephana): '--longnames' was added to allow for this
140 # case (multiple files at once) versus specifying output diffs
141 # directly.
137 find_run_binary.run_command( 142 find_run_binary.run_command(
138 [SKPDIFF_BINARY, '-p', expected_image_file, actual_image_file, 143 [SKPDIFF_BINARY, '-p', expected_image_file, actual_image_file,
139 '--jsonp', 'false', 144 '--jsonp', 'false',
145 '--longnames', 'true',
140 '--output', skpdiff_summary_file, 146 '--output', skpdiff_summary_file,
141 '--differs', 'perceptual', 'different_pixels', 147 '--differs', 'perceptual', 'different_pixels',
142 '--rgbDiffDir', skpdiff_rgbdiff_dir, 148 '--rgbDiffDir', skpdiff_rgbdiff_dir,
143 '--whiteDiffDir', skpdiff_whitediff_dir, 149 '--whiteDiffDir', skpdiff_whitediff_dir,
144 ]) 150 ])
145 151
146 # Get information out of the skpdiff_summary_file. 152 # Get information out of the skpdiff_summary_file.
147 with contextlib.closing(open(skpdiff_summary_file)) as fp: 153 with contextlib.closing(open(skpdiff_summary_file)) as fp:
148 data = json.load(fp) 154 data = json.load(fp)
149 155
150 # For now, we can assume there is only one record in the output summary, 156 # For now, we can assume there is only one record in the output summary,
151 # since we passed skpdiff only one pair of images. 157 # since we passed skpdiff only one pair of images.
152 record = data['records'][0] 158 record = data['records'][0]
153 self._width = record['width'] 159 self._width = record['width']
154 self._height = record['height'] 160 self._height = record['height']
155 # TODO: make max_diff_per_channel a tuple instead of a list, because the 161 # TODO: make max_diff_per_channel a tuple instead of a list, because the
156 # structure is meaningful (first element is red, second is green, etc.) 162 # structure is meaningful (first element is red, second is green, etc.)
157 # See http://stackoverflow.com/a/626871 163 # See http://stackoverflow.com/a/626871
158 self._max_diff_per_channel = [ 164 self._max_diff_per_channel = [
159 record['maxRedDiff'], record['maxGreenDiff'], record['maxBlueDiff']] 165 record['maxRedDiff'], record['maxGreenDiff'], record['maxBlueDiff']]
160 rgb_diff_path = record['rgbDiffPath']
161 white_diff_path = record['whiteDiffPath']
162 per_differ_stats = record['diffs'] 166 per_differ_stats = record['diffs']
163 for stats in per_differ_stats: 167 for stats in per_differ_stats:
164 differ_name = stats['differName'] 168 differ_name = stats['differName']
165 if differ_name == 'different_pixels': 169 if differ_name == 'different_pixels':
166 self._num_pixels_differing = stats['pointsOfInterest'] 170 self._num_pixels_differing = stats['pointsOfInterest']
167 elif differ_name == 'perceptual': 171 elif differ_name == 'perceptual':
168 perceptual_similarity = stats['result'] 172 perceptual_similarity = stats['result']
169 173
170 # skpdiff returns the perceptual similarity; convert it to get the 174 # skpdiff returns the perceptual similarity; convert it to get the
171 # perceptual difference percentage. 175 # perceptual difference percentage.
172 # skpdiff outputs -1 if the images are different sizes. Treat any 176 # skpdiff outputs -1 if the images are different sizes. Treat any
173 # output that does not lie in [0, 1] as having 0% perceptual 177 # output that does not lie in [0, 1] as having 0% perceptual
174 # similarity. 178 # similarity.
175 if not 0 <= perceptual_similarity <= 1: 179 if not 0 <= perceptual_similarity <= 1:
176 perceptual_similarity = 0 180 perceptual_similarity = 0
177 self._perceptual_difference = 100 - (perceptual_similarity * 100) 181 self._perceptual_difference = 100 - (perceptual_similarity * 100)
178
179 # Store the rgbdiff and whitediff images generated above.
180 diff_image_locator = _get_difference_locator(
181 expected_image_locator=expected_image_locator,
182 actual_image_locator=actual_image_locator)
183 basename = str(diff_image_locator) + image_suffix
184 _mkdir_unless_exists(os.path.join(storage_root, RGBDIFFS_SUBDIR))
185 _mkdir_unless_exists(os.path.join(storage_root, WHITEDIFFS_SUBDIR))
186 # TODO: Modify skpdiff's behavior so we can tell it exactly where to
187 # write the image files into, rather than having to move them around
188 # after skpdiff writes them out.
189 shutil.copyfile(rgb_diff_path,
190 os.path.join(storage_root, RGBDIFFS_SUBDIR, basename))
191 shutil.copyfile(white_diff_path,
192 os.path.join(storage_root, WHITEDIFFS_SUBDIR, basename))
193
194 finally: 182 finally:
195 shutil.rmtree(skpdiff_output_dir) 183 shutil.rmtree(skpdiff_output_dir)
196 184
197 # TODO(epoger): Use properties instead of getters throughout. 185 # TODO(epoger): Use properties instead of getters throughout.
198 # See http://stackoverflow.com/a/6618176 186 # See http://stackoverflow.com/a/6618176
199 def get_num_pixels_differing(self): 187 def get_num_pixels_differing(self):
200 """Returns the absolute number of pixels that differ.""" 188 """Returns the absolute number of pixels that differ."""
201 return self._num_pixels_differing 189 return self._num_pixels_differing
202 190
203 def get_percent_pixels_differing(self): 191 def get_percent_pixels_differing(self):
(...skipping 268 matching lines...) Expand 10 before | Expand all | Expand 10 after
472 460
473 Args: 461 Args:
474 locator: string, or something that can be represented as a string. 462 locator: string, or something that can be represented as a string.
475 If None or '', it is returned without modification, because empty 463 If None or '', it is returned without modification, because empty
476 locators have a particular meaning ("there is no image for this") 464 locators have a particular meaning ("there is no image for this")
477 """ 465 """
478 if locator: 466 if locator:
479 return DISALLOWED_FILEPATH_CHAR_REGEX.sub('_', str(locator)) 467 return DISALLOWED_FILEPATH_CHAR_REGEX.sub('_', str(locator))
480 else: 468 else:
481 return locator 469 return locator
482
483 def _get_difference_locator(expected_image_locator, actual_image_locator):
484 """Returns the locator string used to look up the diffs between expected_image
485 and actual_image.
486
487 We must keep this function in sync with getImageDiffRelativeUrl() in
488 static/loader.js
489
490 Args:
491 expected_image_locator: locator string pointing at expected image
492 actual_image_locator: locator string pointing at actual image
493
494 Returns: already-sanitized locator where the diffs between expected and
495 actual images can be found
496 """
497 return "%s-vs-%s" % (_sanitize_locator(expected_image_locator),
498 _sanitize_locator(actual_image_locator))
OLDNEW
« no previous file with comments | « no previous file | gm/rebaseline_server/static/live-loader.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698