OLD | NEW |
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 25 matching lines...) Expand all Loading... |
36 DEFAULT_IMAGE_SUFFIX = '.png' | 36 DEFAULT_IMAGE_SUFFIX = '.png' |
37 DEFAULT_IMAGES_SUBDIR = 'images' | 37 DEFAULT_IMAGES_SUBDIR = 'images' |
38 | 38 |
39 DISALLOWED_FILEPATH_CHAR_REGEX = re.compile('[^\w\-]') | 39 DISALLOWED_FILEPATH_CHAR_REGEX = re.compile('[^\w\-]') |
40 | 40 |
41 DIFFS_SUBDIR = 'diffs' | 41 DIFFS_SUBDIR = 'diffs' |
42 WHITEDIFFS_SUBDIR = 'whitediffs' | 42 WHITEDIFFS_SUBDIR = 'whitediffs' |
43 | 43 |
44 VALUES_PER_BAND = 256 | 44 VALUES_PER_BAND = 256 |
45 | 45 |
| 46 # Keys used within DiffRecord dictionary representations. |
| 47 # Keep these in sync with static/constants.js |
| 48 KEY__DIFFERENCE_DATA__MAX_DIFF_PER_CHANNEL = 'maxDiffPerChannel' |
| 49 KEY__DIFFERENCE_DATA__NUM_DIFF_PIXELS = 'numDifferingPixels' |
| 50 KEY__DIFFERENCE_DATA__PERCENT_DIFF_PIXELS = 'percentDifferingPixels' |
| 51 KEY__DIFFERENCE_DATA__PERCEPTUAL_DIFF = 'perceptualDifference' |
| 52 KEY__DIFFERENCE_DATA__WEIGHTED_DIFF = 'weightedDiffMeasure' |
| 53 |
46 | 54 |
47 class DiffRecord(object): | 55 class DiffRecord(object): |
48 """ Record of differences between two images. """ | 56 """ Record of differences between two images. """ |
49 | 57 |
50 def __init__(self, storage_root, | 58 def __init__(self, storage_root, |
51 expected_image_url, expected_image_locator, | 59 expected_image_url, expected_image_locator, |
52 actual_image_url, actual_image_locator, | 60 actual_image_url, actual_image_locator, |
53 expected_images_subdir=DEFAULT_IMAGES_SUBDIR, | 61 expected_images_subdir=DEFAULT_IMAGES_SUBDIR, |
54 actual_images_subdir=DEFAULT_IMAGES_SUBDIR, | 62 actual_images_subdir=DEFAULT_IMAGES_SUBDIR, |
55 image_suffix=DEFAULT_IMAGE_SUFFIX): | 63 image_suffix=DEFAULT_IMAGE_SUFFIX): |
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
179 | 187 |
180 def get_max_diff_per_channel(self): | 188 def get_max_diff_per_channel(self): |
181 """Returns the maximum difference between the expected and actual images | 189 """Returns the maximum difference between the expected and actual images |
182 for each R/G/B channel, as a list.""" | 190 for each R/G/B channel, as a list.""" |
183 return self._max_diff_per_channel | 191 return self._max_diff_per_channel |
184 | 192 |
185 def as_dict(self): | 193 def as_dict(self): |
186 """Returns a dictionary representation of this DiffRecord, as needed when | 194 """Returns a dictionary representation of this DiffRecord, as needed when |
187 constructing the JSON representation.""" | 195 constructing the JSON representation.""" |
188 return { | 196 return { |
189 'numDifferingPixels': self._num_pixels_differing, | 197 KEY__DIFFERENCE_DATA__NUM_DIFF_PIXELS: self._num_pixels_differing, |
190 'percentDifferingPixels': self.get_percent_pixels_differing(), | 198 KEY__DIFFERENCE_DATA__PERCENT_DIFF_PIXELS: |
191 'weightedDiffMeasure': self.get_weighted_diff_measure(), | 199 self.get_percent_pixels_differing(), |
192 'maxDiffPerChannel': self._max_diff_per_channel, | 200 KEY__DIFFERENCE_DATA__WEIGHTED_DIFF: self.get_weighted_diff_measure(), |
| 201 KEY__DIFFERENCE_DATA__MAX_DIFF_PER_CHANNEL: self._max_diff_per_channel, |
| 202 KEY__DIFFERENCE_DATA__PERCEPTUAL_DIFF: self._perceptual_difference, |
193 } | 203 } |
194 | 204 |
195 | 205 |
196 class ImageDiffDB(object): | 206 class ImageDiffDB(object): |
197 """ Calculates differences between image pairs, maintaining a database of | 207 """ Calculates differences between image pairs, maintaining a database of |
198 them for download.""" | 208 them for download.""" |
199 | 209 |
200 def __init__(self, storage_root): | 210 def __init__(self, storage_root): |
201 """ | 211 """ |
202 Args: | 212 Args: |
(...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
391 | 401 |
392 Args: | 402 Args: |
393 locator: string, or something that can be represented as a string | 403 locator: string, or something that can be represented as a string |
394 """ | 404 """ |
395 return DISALLOWED_FILEPATH_CHAR_REGEX.sub('_', str(locator)) | 405 return DISALLOWED_FILEPATH_CHAR_REGEX.sub('_', str(locator)) |
396 | 406 |
397 def _get_difference_locator(expected_image_locator, actual_image_locator): | 407 def _get_difference_locator(expected_image_locator, actual_image_locator): |
398 """Returns the locator string used to look up the diffs between expected_image | 408 """Returns the locator string used to look up the diffs between expected_image |
399 and actual_image. | 409 and actual_image. |
400 | 410 |
| 411 We must keep this function in sync with getImageDiffRelativeUrl() in |
| 412 static/loader.js |
| 413 |
401 Args: | 414 Args: |
402 expected_image_locator: locator string pointing at expected image | 415 expected_image_locator: locator string pointing at expected image |
403 actual_image_locator: locator string pointing at actual image | 416 actual_image_locator: locator string pointing at actual image |
404 | 417 |
405 Returns: already-sanitized locator where the diffs between expected and | 418 Returns: already-sanitized locator where the diffs between expected and |
406 actual images can be found | 419 actual images can be found |
407 """ | 420 """ |
408 return "%s-vs-%s" % (_sanitize_locator(expected_image_locator), | 421 return "%s-vs-%s" % (_sanitize_locator(expected_image_locator), |
409 _sanitize_locator(actual_image_locator)) | 422 _sanitize_locator(actual_image_locator)) |
OLD | NEW |