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

Side by Side Diff: tools/skdiff_main.cpp

Issue 833223002: add --listfailingbase option (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Created 5 years, 11 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 | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright 2011 Google Inc. 2 * Copyright 2011 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 #include "skdiff.h" 7 #include "skdiff.h"
8 #include "skdiff_html.h" 8 #include "skdiff_html.h"
9 #include "skdiff_utils.h" 9 #include "skdiff_utils.h"
10 #include "SkBitmap.h" 10 #include "SkBitmap.h"
11 #include "SkData.h" 11 #include "SkData.h"
12 #include "SkForceLinking.h" 12 #include "SkForceLinking.h"
13 #include "SkImageDecoder.h" 13 #include "SkImageDecoder.h"
14 #include "SkImageEncoder.h" 14 #include "SkImageEncoder.h"
15 #include "SkOSFile.h" 15 #include "SkOSFile.h"
16 #include "SkStream.h" 16 #include "SkStream.h"
17 #include "SkTDArray.h" 17 #include "SkTDArray.h"
18 #include "SkTemplates.h" 18 #include "SkTemplates.h"
19 #include "SkTSearch.h" 19 #include "SkTSearch.h"
20 #include "SkTypes.h"
21 20
22 __SK_FORCE_IMAGE_DECODER_LINKING; 21 __SK_FORCE_IMAGE_DECODER_LINKING;
23 22
24 /** 23 /**
25 * skdiff 24 * skdiff
26 * 25 *
27 * Given three directory names, expects to find identically-named files in 26 * Given three directory names, expects to find identically-named files in
28 * each of the first two; the first are treated as a set of baseline, 27 * each of the first two; the first are treated as a set of baseline,
29 * the second a set of variant images, and a diff image is written into the 28 * the second a set of variant images, and a diff image is written into the
30 * third directory for each pair. 29 * third directory for each pair.
31 * Creates an index.html in the current third directory to compare each 30 * Creates an index.html in the current third directory to compare each
32 * pair that does not match exactly. 31 * pair that does not match exactly.
33 * Recursively descends directories, unless run with --norecurse. 32 * Recursively descends directories, unless run with --norecurse.
34 * 33 *
35 * Returns zero exit code if all images match across baseDir and comparisonDir. 34 * Returns zero exit code if all images match across baseDir and comparisonDir.
36 */ 35 */
37 36
38 typedef SkTDArray<SkString*> StringArray; 37 typedef SkTDArray<SkString*> StringArray;
39 typedef StringArray FileArray; 38 typedef StringArray FileArray;
40 39
40 static void add_unique_basename(StringArray* array, const SkString& filename) {
41 // trim off dirs
42 const char* src = filename.c_str();
43 const char* trimmed = strrchr(src, SkPATH_SEPARATOR);
44 if (trimmed) {
45 trimmed += 1; // skip the separator
46 } else {
47 trimmed = src;
48 }
49 const char* end = strrchr(trimmed, '.');
50 if (!end) {
51 end = trimmed + strlen(trimmed);
52 }
53 SkString result(trimmed, end - trimmed);
54
55 // only add unique entries
56 for (int i = 0; i < array->count(); ++i) {
57 if (*array->getAt(i) == result) {
58 return;
59 }
60 }
61 *array->append() = new SkString(result);
62 }
63
41 struct DiffSummary { 64 struct DiffSummary {
42 DiffSummary () 65 DiffSummary ()
43 : fNumMatches(0) 66 : fNumMatches(0)
44 , fNumMismatches(0) 67 , fNumMismatches(0)
45 , fMaxMismatchV(0) 68 , fMaxMismatchV(0)
46 , fMaxMismatchPercent(0) { }; 69 , fMaxMismatchPercent(0) { };
47 70
48 ~DiffSummary() { 71 ~DiffSummary() {
49 for (int i = 0; i < DiffRecord::kResultCount; ++i) { 72 for (int i = 0; i < DiffRecord::kResultCount; ++i) {
50 fResultsOfType[i].deleteAll(); 73 fResultsOfType[i].deleteAll();
51 } 74 }
52 for (int base = 0; base < DiffResource::kStatusCount; ++base) { 75 for (int base = 0; base < DiffResource::kStatusCount; ++base) {
53 for (int comparison = 0; comparison < DiffResource::kStatusCount; ++ comparison) { 76 for (int comparison = 0; comparison < DiffResource::kStatusCount; ++ comparison) {
54 fStatusOfType[base][comparison].deleteAll(); 77 fStatusOfType[base][comparison].deleteAll();
55 } 78 }
56 } 79 }
57 } 80 }
58 81
59 uint32_t fNumMatches; 82 uint32_t fNumMatches;
60 uint32_t fNumMismatches; 83 uint32_t fNumMismatches;
61 uint32_t fMaxMismatchV; 84 uint32_t fMaxMismatchV;
62 float fMaxMismatchPercent; 85 float fMaxMismatchPercent;
63 86
64 FileArray fResultsOfType[DiffRecord::kResultCount]; 87 FileArray fResultsOfType[DiffRecord::kResultCount];
65 FileArray fStatusOfType[DiffResource::kStatusCount][DiffResource::kStatusCou nt]; 88 FileArray fStatusOfType[DiffResource::kStatusCount][DiffResource::kStatusCou nt];
66 89
90 StringArray fFailedBaseNames[DiffRecord::kResultCount];
91
67 void printContents(const FileArray& fileArray, 92 void printContents(const FileArray& fileArray,
68 const char* baseStatus, const char* comparisonStatus, 93 const char* baseStatus, const char* comparisonStatus,
69 bool listFilenames) { 94 bool listFilenames) {
70 int n = fileArray.count(); 95 int n = fileArray.count();
71 printf("%d file pairs %s in baseDir and %s in comparisonDir", 96 printf("%d file pairs %s in baseDir and %s in comparisonDir",
72 n, baseStatus, comparisonStatus); 97 n, baseStatus, comparisonStatus);
73 if (listFilenames) { 98 if (listFilenames) {
74 printf(": "); 99 printf(": ");
75 for (int i = 0; i < n; ++i) { 100 for (int i = 0; i < n; ++i) {
76 printf("%s ", fileArray[i]->c_str()); 101 printf("%s ", fileArray[i]->c_str());
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
135 } 160 }
136 } 161 }
137 printf("(results marked with [*] will cause nonzero return value)\n"); 162 printf("(results marked with [*] will cause nonzero return value)\n");
138 printf("\nnumber of mismatching file pairs: %d\n", fNumMismatches); 163 printf("\nnumber of mismatching file pairs: %d\n", fNumMismatches);
139 if (fNumMismatches > 0) { 164 if (fNumMismatches > 0) {
140 printf("Maximum pixel intensity mismatch %d\n", fMaxMismatchV); 165 printf("Maximum pixel intensity mismatch %d\n", fMaxMismatchV);
141 printf("Largest area mismatch was %.2f%% of pixels\n",fMaxMismatchPe rcent); 166 printf("Largest area mismatch was %.2f%% of pixels\n",fMaxMismatchPe rcent);
142 } 167 }
143 } 168 }
144 169
170 void printfFailingBaseNames(const char separator[]) {
171 for (int resultInt = 0; resultInt < DiffRecord::kResultCount; ++resultIn t) {
172 const StringArray& array = fFailedBaseNames[resultInt];
173 if (array.count()) {
174 printf("%s [%d]%s", DiffRecord::ResultNames[resultInt], array.co unt(), separator);
175 for (int j = 0; j < array.count(); ++j) {
176 printf("%s%s", array[j]->c_str(), separator);
177 }
178 printf("\n");
179 }
180 }
181 }
182
145 void add (DiffRecord* drp) { 183 void add (DiffRecord* drp) {
146 uint32_t mismatchValue; 184 uint32_t mismatchValue;
147 185
148 if (drp->fBase.fFilename.equals(drp->fComparison.fFilename)) { 186 if (drp->fBase.fFilename.equals(drp->fComparison.fFilename)) {
149 fResultsOfType[drp->fResult].push(new SkString(drp->fBase.fFilename) ); 187 fResultsOfType[drp->fResult].push(new SkString(drp->fBase.fFilename) );
150 } else { 188 } else {
151 SkString* blame = new SkString("("); 189 SkString* blame = new SkString("(");
152 blame->append(drp->fBase.fFilename); 190 blame->append(drp->fBase.fFilename);
153 blame->append(", "); 191 blame->append(", ");
154 blame->append(drp->fComparison.fFilename); 192 blame->append(drp->fComparison.fFilename);
(...skipping 26 matching lines...) Expand all
181 fStatusOfType[drp->fBase.fStatus][drp->fComparison.fStatus].push( 219 fStatusOfType[drp->fBase.fStatus][drp->fComparison.fStatus].push(
182 new SkString(drp->fBase.fFilename)); 220 new SkString(drp->fBase.fFilename));
183 break; 221 break;
184 case DiffRecord::kUnknown_Result: 222 case DiffRecord::kUnknown_Result:
185 SkDEBUGFAIL("adding uncategorized DiffRecord"); 223 SkDEBUGFAIL("adding uncategorized DiffRecord");
186 break; 224 break;
187 default: 225 default:
188 SkDEBUGFAIL("adding DiffRecord with unhandled fResult value"); 226 SkDEBUGFAIL("adding DiffRecord with unhandled fResult value");
189 break; 227 break;
190 } 228 }
229
230 switch (drp->fResult) {
231 case DiffRecord::kEqualBits_Result:
232 case DiffRecord::kEqualPixels_Result:
233 break;
234 default:
235 add_unique_basename(&fFailedBaseNames[drp->fResult], drp->fBase. fFilename);
236 break;
237 }
191 } 238 }
192 }; 239 };
193 240
194 /// Returns true if string contains any of these substrings. 241 /// Returns true if string contains any of these substrings.
195 static bool string_contains_any_of(const SkString& string, 242 static bool string_contains_any_of(const SkString& string,
196 const StringArray& substrings) { 243 const StringArray& substrings) {
197 for (int i = 0; i < substrings.count(); i++) { 244 for (int i = 0; i < substrings.count(); i++) {
198 if (string.contains(substrings[i]->c_str())) { 245 if (string.contains(substrings[i]->c_str())) {
199 return true; 246 return true;
200 } 247 }
(...skipping 373 matching lines...) Expand 10 before | Expand all | Expand 10 after
574 SkString outputDir; 621 SkString outputDir;
575 622
576 StringArray matchSubstrings; 623 StringArray matchSubstrings;
577 StringArray nomatchSubstrings; 624 StringArray nomatchSubstrings;
578 625
579 bool generateDiffs = true; 626 bool generateDiffs = true;
580 bool listFilenames = false; 627 bool listFilenames = false;
581 bool printDirNames = true; 628 bool printDirNames = true;
582 bool recurseIntoSubdirs = true; 629 bool recurseIntoSubdirs = true;
583 bool verbose = false; 630 bool verbose = false;
631 bool listFailingBase = false;
584 632
585 RecordArray differences; 633 RecordArray differences;
586 DiffSummary summary; 634 DiffSummary summary;
587 635
588 bool failOnResultType[DiffRecord::kResultCount]; 636 bool failOnResultType[DiffRecord::kResultCount];
589 for (int i = 0; i < DiffRecord::kResultCount; i++) { 637 for (int i = 0; i < DiffRecord::kResultCount; i++) {
590 failOnResultType[i] = false; 638 failOnResultType[i] = false;
591 } 639 }
592 640
593 bool failOnStatusType[DiffResource::kStatusCount][DiffResource::kStatusCount ]; 641 bool failOnStatusType[DiffResource::kStatusCount][DiffResource::kStatusCount ];
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
698 continue; 746 continue;
699 case 2: 747 case 2:
700 outputDir.set(argv[i]); 748 outputDir.set(argv[i]);
701 continue; 749 continue;
702 default: 750 default:
703 SkDebugf("extra unflagged argument <%s>\n", argv[i]); 751 SkDebugf("extra unflagged argument <%s>\n", argv[i]);
704 usage(argv[0]); 752 usage(argv[0]);
705 return kGenericError; 753 return kGenericError;
706 } 754 }
707 } 755 }
756 if (!strcmp(argv[i], "--listFailingBase")) {
757 listFailingBase = true;
758 continue;
759 }
708 760
709 SkDebugf("Unrecognized argument <%s>\n", argv[i]); 761 SkDebugf("Unrecognized argument <%s>\n", argv[i]);
710 usage(argv[0]); 762 usage(argv[0]);
711 return kGenericError; 763 return kGenericError;
712 } 764 }
713 765
714 if (numUnflaggedArguments == 2) { 766 if (numUnflaggedArguments == 2) {
715 outputDir = comparisonDir; 767 outputDir = comparisonDir;
716 } else if (numUnflaggedArguments != 3) { 768 } else if (numUnflaggedArguments != 3) {
717 usage(argv[0]); 769 usage(argv[0]);
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
751 if (matchSubstrings.isEmpty()) { 803 if (matchSubstrings.isEmpty()) {
752 matchSubstrings.push(new SkString("")); 804 matchSubstrings.push(new SkString(""));
753 } 805 }
754 806
755 create_diff_images(diffProc, colorThreshold, &differences, 807 create_diff_images(diffProc, colorThreshold, &differences,
756 baseDir, comparisonDir, outputDir, 808 baseDir, comparisonDir, outputDir,
757 matchSubstrings, nomatchSubstrings, recurseIntoSubdirs, g enerateDiffs, 809 matchSubstrings, nomatchSubstrings, recurseIntoSubdirs, g enerateDiffs,
758 verbose, &summary); 810 verbose, &summary);
759 summary.print(listFilenames, failOnResultType, failOnStatusType); 811 summary.print(listFilenames, failOnResultType, failOnStatusType);
760 812
813 if (listFailingBase) {
814 summary.printfFailingBaseNames("\n");
815 }
816
761 if (differences.count()) { 817 if (differences.count()) {
762 qsort(differences.begin(), differences.count(), 818 qsort(differences.begin(), differences.count(),
763 sizeof(DiffRecord*), sortProc); 819 sizeof(DiffRecord*), sortProc);
764 } 820 }
765 821
766 if (generateDiffs) { 822 if (generateDiffs) {
767 print_diff_page(summary.fNumMatches, colorThreshold, differences, 823 print_diff_page(summary.fNumMatches, colorThreshold, differences,
768 baseDir, comparisonDir, outputDir); 824 baseDir, comparisonDir, outputDir);
769 } 825 }
770 826
(...skipping 23 matching lines...) Expand all
794 // range [0...255] are wrapped (mod 256). Do the conversion ourselves, to 850 // range [0...255] are wrapped (mod 256). Do the conversion ourselves, to
795 // make sure that we only return 0 when there were no failures. 851 // make sure that we only return 0 when there were no failures.
796 return (num_failing_results > 255) ? 255 : num_failing_results; 852 return (num_failing_results > 255) ? 255 : num_failing_results;
797 } 853 }
798 854
799 #if !defined SK_BUILD_FOR_IOS 855 #if !defined SK_BUILD_FOR_IOS
800 int main(int argc, char * const argv[]) { 856 int main(int argc, char * const argv[]) {
801 return tool_main(argc, (char**) argv); 857 return tool_main(argc, (char**) argv);
802 } 858 }
803 #endif 859 #endif
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698