OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright 2013 Google Inc. | 2 * Copyright 2013 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "SkBitmap.h" | 8 #include "SkBitmap.h" |
9 #include "SkImageDecoder.h" | 9 #include "SkImageDecoder.h" |
10 #include "SkOSFile.h" | 10 #include "SkOSFile.h" |
(...skipping 10 matching lines...) Expand all Loading... | |
21 fDifferCount = 0; | 21 fDifferCount = 0; |
22 fThreadCount = SkThreadPool::kThreadPerCore; | 22 fThreadCount = SkThreadPool::kThreadPerCore; |
23 } | 23 } |
24 | 24 |
25 SkDiffContext::~SkDiffContext() { | 25 SkDiffContext::~SkDiffContext() { |
26 if (NULL != fDiffers) { | 26 if (NULL != fDiffers) { |
27 SkDELETE_ARRAY(fDiffers); | 27 SkDELETE_ARRAY(fDiffers); |
28 } | 28 } |
29 } | 29 } |
30 | 30 |
31 void SkDiffContext::setDifferenceDir(const SkString& path) { | 31 void SkDiffContext::setAlphaMaskDir(const SkString& path) { |
32 if (!path.isEmpty() && sk_mkdir(path.c_str())) { | 32 if (!path.isEmpty() && sk_mkdir(path.c_str())) { |
33 fDifferenceDir = path; | 33 fAlphaMaskDir = path; |
34 } | 34 } |
35 } | 35 } |
36 | 36 |
37 void SkDiffContext::setRgbDiffDir(const SkString& path) { | |
38 if (!path.isEmpty() && sk_mkdir(path.c_str())) { | |
39 fRgbDiffDir = path; | |
40 } | |
41 } | |
42 | |
43 void SkDiffContext::setWhiteDiffDir(const SkString& path) { | |
44 if (!path.isEmpty() && sk_mkdir(path.c_str())) { | |
45 fWhiteDiffDir = path; | |
46 } | |
47 } | |
48 | |
37 void SkDiffContext::setDiffers(const SkTDArray<SkImageDiffer*>& differs) { | 49 void SkDiffContext::setDiffers(const SkTDArray<SkImageDiffer*>& differs) { |
38 // Delete whatever the last array of differs was | 50 // Delete whatever the last array of differs was |
39 if (NULL != fDiffers) { | 51 if (NULL != fDiffers) { |
40 SkDELETE_ARRAY(fDiffers); | 52 SkDELETE_ARRAY(fDiffers); |
41 fDiffers = NULL; | 53 fDiffers = NULL; |
42 fDifferCount = 0; | 54 fDifferCount = 0; |
43 } | 55 } |
44 | 56 |
45 // Copy over the new differs | 57 // Copy over the new differs |
46 fDifferCount = differs.count(); | 58 fDifferCount = differs.count(); |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
83 DiffRecord* newRecord = fRecords.addToHead(DiffRecord()); | 95 DiffRecord* newRecord = fRecords.addToHead(DiffRecord()); |
84 fRecordMutex.release(); | 96 fRecordMutex.release(); |
85 | 97 |
86 // compute the common name | 98 // compute the common name |
87 SkString baseName = SkOSPath::SkBasename(baselinePath); | 99 SkString baseName = SkOSPath::SkBasename(baselinePath); |
88 SkString testName = SkOSPath::SkBasename(testPath); | 100 SkString testName = SkOSPath::SkBasename(testPath); |
89 newRecord->fCommonName = get_common_prefix(baseName, testName); | 101 newRecord->fCommonName = get_common_prefix(baseName, testName); |
90 | 102 |
91 newRecord->fBaselinePath = baselinePath; | 103 newRecord->fBaselinePath = baselinePath; |
92 newRecord->fTestPath = testPath; | 104 newRecord->fTestPath = testPath; |
105 newRecord->fWidth = baselineBitmap.width(); | |
106 newRecord->fHeight = baselineBitmap.height(); | |
93 | 107 |
94 bool alphaMaskPending = false; | 108 // only generate diff images if we have a place to store them |
95 | 109 bool alphaMaskPending = !fAlphaMaskDir.isEmpty(); |
96 // only enable alpha masks if a difference dir has been provided | 110 bool rgbDiffPending = !fRgbDiffDir.isEmpty(); |
97 if (!fDifferenceDir.isEmpty()) { | 111 bool whiteDiffPending = !fWhiteDiffDir.isEmpty(); |
98 alphaMaskPending = true; | |
99 } | |
100 | 112 |
101 // Perform each diff | 113 // Perform each diff |
102 for (int differIndex = 0; differIndex < fDifferCount; differIndex++) { | 114 for (int differIndex = 0; differIndex < fDifferCount; differIndex++) { |
103 SkImageDiffer* differ = fDiffers[differIndex]; | 115 SkImageDiffer* differ = fDiffers[differIndex]; |
104 | 116 |
105 // Copy the results into data for this record | 117 // Copy the results into data for this record |
106 DiffData& diffData = newRecord->fDiffs.push_back(); | 118 DiffData& diffData = newRecord->fDiffs.push_back(); |
107 diffData.fDiffName = differ->getName(); | 119 diffData.fDiffName = differ->getName(); |
108 | 120 |
109 if (!differ->diff(&baselineBitmap, &testBitmap, alphaMaskPending, &diffD ata.fResult)) { | 121 if (!differ->diff(&baselineBitmap, &testBitmap, alphaMaskPending, rgbDif fPending, |
110 // if the diff failed record -1 as the result | 122 whiteDiffPending, &diffData.fResult)) { |
123 // if the diff failed, record -1 as the result | |
111 diffData.fResult.result = -1; | 124 diffData.fResult.result = -1; |
112 continue; | 125 continue; |
113 } | 126 } |
114 | 127 |
115 if (alphaMaskPending | 128 if (alphaMaskPending |
116 && SkImageDiffer::RESULT_CORRECT != diffData.fResult.result | 129 && SkImageDiffer::RESULT_CORRECT != diffData.fResult.result |
117 && !diffData.fResult.poiAlphaMask.empty() | 130 && !diffData.fResult.poiAlphaMask.empty() |
118 && !newRecord->fCommonName.isEmpty()) { | 131 && !newRecord->fCommonName.isEmpty()) { |
119 | 132 |
120 newRecord->fDifferencePath = SkOSPath::SkPathJoin(fDifferenceDir.c_s tr(), | 133 newRecord->fAlphaMaskPath = SkOSPath::SkPathJoin(fAlphaMaskDir.c_str (), |
121 newRecord->fCommon Name.c_str()); | 134 newRecord->fCommonN ame.c_str()); |
122 | 135 |
123 // compute the image diff and output it | 136 // compute the image diff and output it |
124 SkBitmap copy; | 137 SkBitmap copy; |
125 diffData.fResult.poiAlphaMask.copyTo(©, kN32_SkColorType); | 138 diffData.fResult.poiAlphaMask.copyTo(©, kN32_SkColorType); |
126 SkImageEncoder::EncodeFile(newRecord->fDifferencePath.c_str(), copy, | 139 SkImageEncoder::EncodeFile(newRecord->fAlphaMaskPath.c_str(), copy, |
127 SkImageEncoder::kPNG_Type, 100); | 140 SkImageEncoder::kPNG_Type, 100); |
128 | 141 |
129 // cleanup the existing bitmap to free up resources; | 142 // cleanup the existing bitmap to free up resources; |
130 diffData.fResult.poiAlphaMask.reset(); | 143 diffData.fResult.poiAlphaMask.reset(); |
131 | 144 |
132 alphaMaskPending = false; | 145 alphaMaskPending = false; |
133 } | 146 } |
147 | |
148 if (rgbDiffPending | |
149 && SkImageDiffer::RESULT_CORRECT != diffData.fResult.result | |
150 && !diffData.fResult.rgbDiffBitmap.empty() | |
151 && !newRecord->fCommonName.isEmpty()) { | |
152 // EPOGER: This is a hack, based on the knowledge that the same | |
153 // differ which gives us rgbDiffBitmap will also give us the | |
154 // max r/g/b diffs. | |
155 newRecord->fMaxRedDiff = diffData.fResult.maxRedDiff; | |
156 newRecord->fMaxGreenDiff = diffData.fResult.maxGreenDiff; | |
157 newRecord->fMaxBlueDiff = diffData.fResult.maxBlueDiff; | |
158 | |
159 newRecord->fRgbDiffPath = SkOSPath::SkPathJoin(fRgbDiffDir.c_str(), | |
160 newRecord->fCommonNam e.c_str()); | |
161 SkImageEncoder::EncodeFile(newRecord->fRgbDiffPath.c_str(), | |
162 diffData.fResult.rgbDiffBitmap, | |
163 SkImageEncoder::kPNG_Type, 100); | |
164 diffData.fResult.rgbDiffBitmap.reset(); | |
165 rgbDiffPending = false; | |
166 } | |
167 | |
168 if (whiteDiffPending | |
169 && SkImageDiffer::RESULT_CORRECT != diffData.fResult.result | |
170 && !diffData.fResult.whiteDiffBitmap.empty() | |
171 && !newRecord->fCommonName.isEmpty()) { | |
172 newRecord->fWhiteDiffPath = SkOSPath::SkPathJoin(fWhiteDiffDir.c_str (), | |
173 newRecord->fCommonN ame.c_str()); | |
174 SkImageEncoder::EncodeFile(newRecord->fWhiteDiffPath.c_str(), | |
175 diffData.fResult.whiteDiffBitmap, | |
176 SkImageEncoder::kPNG_Type, 100); | |
177 diffData.fResult.whiteDiffBitmap.reset(); | |
178 whiteDiffPending = false; | |
179 } | |
134 } | 180 } |
135 } | 181 } |
136 | 182 |
137 class SkThreadedDiff : public SkRunnable { | 183 class SkThreadedDiff : public SkRunnable { |
138 public: | 184 public: |
139 SkThreadedDiff() : fDiffContext(NULL) { } | 185 SkThreadedDiff() : fDiffContext(NULL) { } |
140 | 186 |
141 void setup(SkDiffContext* diffContext, const SkString& baselinePath, const S kString& testPath) { | 187 void setup(SkDiffContext* diffContext, const SkString& baselinePath, const S kString& testPath) { |
142 fDiffContext = diffContext; | 188 fDiffContext = diffContext; |
143 fBaselinePath = baselinePath; | 189 fBaselinePath = baselinePath; |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
222 | 268 |
223 void SkDiffContext::outputRecords(SkWStream& stream, bool useJSONP) { | 269 void SkDiffContext::outputRecords(SkWStream& stream, bool useJSONP) { |
224 SkTLList<DiffRecord>::Iter iter(fRecords, SkTLList<DiffRecord>::Iter::kHead_ IterStart); | 270 SkTLList<DiffRecord>::Iter iter(fRecords, SkTLList<DiffRecord>::Iter::kHead_ IterStart); |
225 DiffRecord* currentRecord = iter.get(); | 271 DiffRecord* currentRecord = iter.get(); |
226 | 272 |
227 if (useJSONP) { | 273 if (useJSONP) { |
228 stream.writeText("var SkPDiffRecords = {\n"); | 274 stream.writeText("var SkPDiffRecords = {\n"); |
229 } else { | 275 } else { |
230 stream.writeText("{\n"); | 276 stream.writeText("{\n"); |
231 } | 277 } |
278 | |
279 // TODO: Would it be better to use the jsoncpp library to write out the JSON ? | |
280 // This manual approach is probably more efficient, but it sure is ugly. | |
232 stream.writeText(" \"records\": [\n"); | 281 stream.writeText(" \"records\": [\n"); |
233 while (NULL != currentRecord) { | 282 while (NULL != currentRecord) { |
234 stream.writeText(" {\n"); | 283 stream.writeText(" {\n"); |
235 | 284 |
236 SkString differenceAbsPath = get_absolute_path(currentRecord->fDiffe rencePath); | |
237 SkString baselineAbsPath = get_absolute_path(currentRecord->fBaselin ePath); | 285 SkString baselineAbsPath = get_absolute_path(currentRecord->fBaselin ePath); |
238 SkString testAbsPath = get_absolute_path(currentRecord->fTestPath); | 286 SkString testAbsPath = get_absolute_path(currentRecord->fTestPath); |
239 | 287 |
240 stream.writeText(" \"commonName\": \""); | 288 stream.writeText(" \"commonName\": \""); |
241 stream.writeText(currentRecord->fCommonName.c_str()); | 289 stream.writeText(currentRecord->fCommonName.c_str()); |
242 stream.writeText("\",\n"); | 290 stream.writeText("\",\n"); |
243 | 291 |
244 stream.writeText(" \"differencePath\": \""); | 292 stream.writeText(" \"differencePath\": \""); |
245 stream.writeText(differenceAbsPath.c_str()); | 293 stream.writeText(get_absolute_path(currentRecord->fAlphaMaskPath).c_ str()); |
294 stream.writeText("\",\n"); | |
295 | |
296 stream.writeText(" \"rgbDiffPath\": \""); | |
297 stream.writeText(get_absolute_path(currentRecord->fRgbDiffPath).c_st r()); | |
298 stream.writeText("\",\n"); | |
299 | |
300 stream.writeText(" \"whiteDiffPath\": \""); | |
301 stream.writeText(get_absolute_path(currentRecord->fWhiteDiffPath).c_ str()); | |
246 stream.writeText("\",\n"); | 302 stream.writeText("\",\n"); |
247 | 303 |
248 stream.writeText(" \"baselinePath\": \""); | 304 stream.writeText(" \"baselinePath\": \""); |
249 stream.writeText(baselineAbsPath.c_str()); | 305 stream.writeText(baselineAbsPath.c_str()); |
250 stream.writeText("\",\n"); | 306 stream.writeText("\",\n"); |
251 | 307 |
252 stream.writeText(" \"testPath\": \""); | 308 stream.writeText(" \"testPath\": \""); |
253 stream.writeText(testAbsPath.c_str()); | 309 stream.writeText(testAbsPath.c_str()); |
254 stream.writeText("\",\n"); | 310 stream.writeText("\",\n"); |
255 | 311 |
312 stream.writeText(" \"width\": "); | |
313 stream.writeDecAsText(currentRecord->fWidth); | |
314 stream.writeText(",\n"); | |
315 stream.writeText(" \"height\": "); | |
316 stream.writeDecAsText(currentRecord->fHeight); | |
317 stream.writeText(",\n"); | |
318 | |
319 stream.writeText(" \"maxRedDiff\": "); | |
epoger
2014/06/12 07:02:07
Here I jammed in the various parameters that I had
| |
320 stream.writeDecAsText(currentRecord->fMaxRedDiff); | |
321 stream.writeText(",\n"); | |
322 stream.writeText(" \"maxGreenDiff\": "); | |
323 stream.writeDecAsText(currentRecord->fMaxGreenDiff); | |
324 stream.writeText(",\n"); | |
325 stream.writeText(" \"maxBlueDiff\": "); | |
326 stream.writeDecAsText(currentRecord->fMaxBlueDiff); | |
327 stream.writeText(",\n"); | |
328 | |
256 stream.writeText(" \"diffs\": [\n"); | 329 stream.writeText(" \"diffs\": [\n"); |
257 for (int diffIndex = 0; diffIndex < currentRecord->fDiffs.count(); d iffIndex++) { | 330 for (int diffIndex = 0; diffIndex < currentRecord->fDiffs.count(); d iffIndex++) { |
258 DiffData& data = currentRecord->fDiffs[diffIndex]; | 331 DiffData& data = currentRecord->fDiffs[diffIndex]; |
259 stream.writeText(" {\n"); | 332 stream.writeText(" {\n"); |
260 | 333 |
261 stream.writeText(" \"differName\": \""); | 334 stream.writeText(" \"differName\": \""); |
262 stream.writeText(data.fDiffName); | 335 stream.writeText(data.fDiffName); |
263 stream.writeText("\",\n"); | 336 stream.writeText("\",\n"); |
264 | 337 |
265 stream.writeText(" \"result\": "); | 338 stream.writeText(" \"result\": "); |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
351 for (int i = 0; i < cntColumns; i++) { | 424 for (int i = 0; i < cntColumns; i++) { |
352 SkString str; | 425 SkString str; |
353 str.printf(", %f", values[i]); | 426 str.printf(", %f", values[i]); |
354 stream.writeText(str.c_str()); | 427 stream.writeText(str.c_str()); |
355 } | 428 } |
356 stream.writeText("\n"); | 429 stream.writeText("\n"); |
357 | 430 |
358 currentRecord = iter2.next(); | 431 currentRecord = iter2.next(); |
359 } | 432 } |
360 } | 433 } |
OLD | NEW |