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 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
115 # Return early if we do not need to generate diffs. | 115 # Return early if we do not need to generate diffs. |
116 if (expected_image_url == actual_image_url or | 116 if (expected_image_url == actual_image_url or |
117 not expected_image_url or not actual_image_url): | 117 not expected_image_url or not actual_image_url): |
118 return | 118 return |
119 | 119 |
120 # Get all diff images and values using the skpdiff binary. | 120 # Get all diff images and values using the skpdiff binary. |
121 skpdiff_output_dir = tempfile.mkdtemp() | 121 skpdiff_output_dir = tempfile.mkdtemp() |
122 try: | 122 try: |
123 skpdiff_summary_file = os.path.join(skpdiff_output_dir, | 123 skpdiff_summary_file = os.path.join(skpdiff_output_dir, |
124 'skpdiff-output.json') | 124 'skpdiff-output.json') |
125 skpdiff_rgbdiff_dir = os.path.join(skpdiff_output_dir, 'rgbDiff') | 125 skpdiff_rgbdiff_dir = os.path.join(storage_root, RGBDIFFS_SUBDIR) |
126 skpdiff_whitediff_dir = os.path.join(skpdiff_output_dir, 'whiteDiff') | 126 skpdiff_whitediff_dir = os.path.join(storage_root, WHITEDIFFS_SUBDIR) |
127 _mkdir_unless_exists(skpdiff_rgbdiff_dir) | |
128 _mkdir_unless_exists(skpdiff_rgbdiff_dir) | |
127 | 129 |
128 # TODO(epoger): Consider calling skpdiff ONCE for all image pairs, | 130 # TODO(epoger): Consider calling skpdiff ONCE for all image pairs, |
129 # instead of calling it separately for each image pair. | 131 # instead of calling it separately for each image pair. |
130 # Pro: we'll incur less overhead from making repeated system calls, | 132 # Pro: we'll incur less overhead from making repeated system calls, |
131 # spinning up the skpdiff binary, etc. | 133 # spinning up the skpdiff binary, etc. |
132 # Con: we would have to wait until all image pairs were loaded before | 134 # Con: we would have to wait until all image pairs were loaded before |
133 # generating any of the diffs? | 135 # generating any of the diffs? |
134 find_run_binary.run_command( | 136 find_run_binary.run_command( |
135 [SKPDIFF_BINARY, '-p', expected_image_file, actual_image_file, | 137 [SKPDIFF_BINARY, '-p', expected_image_file, actual_image_file, |
136 '--jsonp', 'false', | 138 '--jsonp', 'false', |
139 '--longnames', 'true', | |
137 '--output', skpdiff_summary_file, | 140 '--output', skpdiff_summary_file, |
138 '--differs', 'perceptual', 'different_pixels', | 141 '--differs', 'perceptual', 'different_pixels', |
139 '--rgbDiffDir', skpdiff_rgbdiff_dir, | 142 '--rgbDiffDir', skpdiff_rgbdiff_dir, |
epoger
2014/08/11 19:33:27
Instead of adding the --longnames parameter and al
stephana
2014/08/11 20:03:57
That was going to be my first approach (namely to
| |
140 '--whiteDiffDir', skpdiff_whitediff_dir, | 143 '--whiteDiffDir', skpdiff_whitediff_dir, |
141 ]) | 144 ]) |
142 | 145 |
143 # Get information out of the skpdiff_summary_file. | 146 # Get information out of the skpdiff_summary_file. |
144 with contextlib.closing(open(skpdiff_summary_file)) as fp: | 147 with contextlib.closing(open(skpdiff_summary_file)) as fp: |
145 data = json.load(fp) | 148 data = json.load(fp) |
146 | 149 |
147 # For now, we can assume there is only one record in the output summary, | 150 # For now, we can assume there is only one record in the output summary, |
148 # since we passed skpdiff only one pair of images. | 151 # since we passed skpdiff only one pair of images. |
149 record = data['records'][0] | 152 record = data['records'][0] |
150 self._width = record['width'] | 153 self._width = record['width'] |
151 self._height = record['height'] | 154 self._height = record['height'] |
152 # TODO: make max_diff_per_channel a tuple instead of a list, because the | 155 # TODO: make max_diff_per_channel a tuple instead of a list, because the |
153 # structure is meaningful (first element is red, second is green, etc.) | 156 # structure is meaningful (first element is red, second is green, etc.) |
154 # See http://stackoverflow.com/a/626871 | 157 # See http://stackoverflow.com/a/626871 |
155 self._max_diff_per_channel = [ | 158 self._max_diff_per_channel = [ |
156 record['maxRedDiff'], record['maxGreenDiff'], record['maxBlueDiff']] | 159 record['maxRedDiff'], record['maxGreenDiff'], record['maxBlueDiff']] |
157 rgb_diff_path = record['rgbDiffPath'] | |
158 white_diff_path = record['whiteDiffPath'] | |
159 per_differ_stats = record['diffs'] | 160 per_differ_stats = record['diffs'] |
160 for stats in per_differ_stats: | 161 for stats in per_differ_stats: |
161 differ_name = stats['differName'] | 162 differ_name = stats['differName'] |
162 if differ_name == 'different_pixels': | 163 if differ_name == 'different_pixels': |
163 self._num_pixels_differing = stats['pointsOfInterest'] | 164 self._num_pixels_differing = stats['pointsOfInterest'] |
164 elif differ_name == 'perceptual': | 165 elif differ_name == 'perceptual': |
165 perceptual_similarity = stats['result'] | 166 perceptual_similarity = stats['result'] |
166 | 167 |
167 # skpdiff returns the perceptual similarity; convert it to get the | 168 # skpdiff returns the perceptual similarity; convert it to get the |
168 # perceptual difference percentage. | 169 # perceptual difference percentage. |
169 # skpdiff outputs -1 if the images are different sizes. Treat any | 170 # skpdiff outputs -1 if the images are different sizes. Treat any |
170 # output that does not lie in [0, 1] as having 0% perceptual | 171 # output that does not lie in [0, 1] as having 0% perceptual |
171 # similarity. | 172 # similarity. |
172 if not 0 <= perceptual_similarity <= 1: | 173 if not 0 <= perceptual_similarity <= 1: |
173 perceptual_similarity = 0 | 174 perceptual_similarity = 0 |
174 self._perceptual_difference = 100 - (perceptual_similarity * 100) | 175 self._perceptual_difference = 100 - (perceptual_similarity * 100) |
175 | |
176 # Store the rgbdiff and whitediff images generated above. | |
177 diff_image_locator = _get_difference_locator( | |
epoger
2014/08/11 19:33:27
I *think* this is the only call to _get_difference
stephana
2014/08/11 20:03:57
Agreed.
On 2014/08/11 19:33:27, epoger wrote:
| |
178 expected_image_locator=expected_image_locator, | |
179 actual_image_locator=actual_image_locator) | |
180 basename = str(diff_image_locator) + image_suffix | |
181 _mkdir_unless_exists(os.path.join(storage_root, RGBDIFFS_SUBDIR)) | |
182 _mkdir_unless_exists(os.path.join(storage_root, WHITEDIFFS_SUBDIR)) | |
183 # TODO: Modify skpdiff's behavior so we can tell it exactly where to | |
184 # write the image files into, rather than having to move them around | |
185 # after skpdiff writes them out. | |
186 shutil.copyfile(rgb_diff_path, | |
187 os.path.join(storage_root, RGBDIFFS_SUBDIR, basename)) | |
188 shutil.copyfile(white_diff_path, | |
189 os.path.join(storage_root, WHITEDIFFS_SUBDIR, basename)) | |
190 | |
191 finally: | 176 finally: |
192 shutil.rmtree(skpdiff_output_dir) | 177 shutil.rmtree(skpdiff_output_dir) |
193 | 178 |
194 # TODO(epoger): Use properties instead of getters throughout. | 179 # TODO(epoger): Use properties instead of getters throughout. |
195 # See http://stackoverflow.com/a/6618176 | 180 # See http://stackoverflow.com/a/6618176 |
196 def get_num_pixels_differing(self): | 181 def get_num_pixels_differing(self): |
197 """Returns the absolute number of pixels that differ.""" | 182 """Returns the absolute number of pixels that differ.""" |
198 return self._num_pixels_differing | 183 return self._num_pixels_differing |
199 | 184 |
200 def get_percent_pixels_differing(self): | 185 def get_percent_pixels_differing(self): |
(...skipping 256 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
457 | 442 |
458 Args: | 443 Args: |
459 expected_image_locator: locator string pointing at expected image | 444 expected_image_locator: locator string pointing at expected image |
460 actual_image_locator: locator string pointing at actual image | 445 actual_image_locator: locator string pointing at actual image |
461 | 446 |
462 Returns: already-sanitized locator where the diffs between expected and | 447 Returns: already-sanitized locator where the diffs between expected and |
463 actual images can be found | 448 actual images can be found |
464 """ | 449 """ |
465 return "%s-vs-%s" % (_sanitize_locator(expected_image_locator), | 450 return "%s-vs-%s" % (_sanitize_locator(expected_image_locator), |
466 _sanitize_locator(actual_image_locator)) | 451 _sanitize_locator(actual_image_locator)) |
OLD | NEW |