Chromium Code Reviews| 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 |