in tools/skdiff/skdiff_main.cpp [598:836]
int main(int argc, char** argv) {
DiffMetricProc diffProc = compute_diff_pmcolor;
int (*sortProc)(const void*, const void*) = compare<CompareDiffMetrics>;
// Maximum error tolerated in any one color channel in any one pixel before
// a difference is reported.
int colorThreshold = 0;
SkString baseDir;
SkString comparisonDir;
SkString outputDir;
StringArray matchSubstrings;
StringArray nomatchSubstrings;
bool generateDiffs = true;
bool listFilenames = false;
bool printDirNames = true;
bool recurseIntoSubdirs = true;
bool verbose = false;
bool listFailingBase = false;
bool ignoreColorSpace = false;
RecordArray differences;
DiffSummary summary;
bool failOnResultType[DiffRecord::kResultCount];
for (int i = 0; i < DiffRecord::kResultCount; i++) {
failOnResultType[i] = false;
}
bool failOnStatusType[DiffResource::kStatusCount][DiffResource::kStatusCount];
for (int base = 0; base < DiffResource::kStatusCount; ++base) {
for (int comparison = 0; comparison < DiffResource::kStatusCount; ++comparison) {
failOnStatusType[base][comparison] = false;
}
}
int numUnflaggedArguments = 0;
for (int i = 1; i < argc; i++) {
if (!strcmp(argv[i], "--failonresult")) {
if (argc == ++i) {
SkDebugf("failonresult expects one argument.\n");
continue;
}
DiffRecord::Result type = DiffRecord::getResultByName(argv[i]);
if (type != DiffRecord::kResultCount) {
failOnResultType[type] = true;
} else {
SkDebugf("ignoring unrecognized result <%s>\n", argv[i]);
}
continue;
}
if (!strcmp(argv[i], "--failonstatus")) {
if (argc == ++i) {
SkDebugf("failonstatus missing base status.\n");
continue;
}
bool baseStatuses[DiffResource::kStatusCount];
if (!DiffResource::getMatchingStatuses(argv[i], baseStatuses)) {
SkDebugf("unrecognized base status <%s>\n", argv[i]);
}
if (argc == ++i) {
SkDebugf("failonstatus missing comparison status.\n");
continue;
}
bool comparisonStatuses[DiffResource::kStatusCount];
if (!DiffResource::getMatchingStatuses(argv[i], comparisonStatuses)) {
SkDebugf("unrecognized comarison status <%s>\n", argv[i]);
}
for (int base = 0; base < DiffResource::kStatusCount; ++base) {
for (int comparison = 0; comparison < DiffResource::kStatusCount; ++comparison) {
failOnStatusType[base][comparison] |=
baseStatuses[base] && comparisonStatuses[comparison];
}
}
continue;
}
if (!strcmp(argv[i], "--help")) {
usage(argv[0]);
return kNoError;
}
if (!strcmp(argv[i], "--listfilenames")) {
listFilenames = true;
continue;
}
if (!strcmp(argv[i], "--verbose")) {
verbose = true;
continue;
}
if (!strcmp(argv[i], "--match")) {
matchSubstrings.emplace_back(argv[++i]);
continue;
}
if (!strcmp(argv[i], "--nocolorspace")) {
ignoreColorSpace = true;
continue;
}
if (!strcmp(argv[i], "--nodiffs")) {
generateDiffs = false;
continue;
}
if (!strcmp(argv[i], "--nomatch")) {
nomatchSubstrings.emplace_back(argv[++i]);
continue;
}
if (!strcmp(argv[i], "--noprintdirs")) {
printDirNames = false;
continue;
}
if (!strcmp(argv[i], "--norecurse")) {
recurseIntoSubdirs = false;
continue;
}
if (!strcmp(argv[i], "--sortbymaxmismatch")) {
sortProc = compare<CompareDiffMaxMismatches>;
continue;
}
if (!strcmp(argv[i], "--sortbymismatch")) {
sortProc = compare<CompareDiffMeanMismatches>;
continue;
}
if (!strcmp(argv[i], "--threshold")) {
colorThreshold = atoi(argv[++i]);
continue;
}
if (!strcmp(argv[i], "--weighted")) {
sortProc = compare<CompareDiffWeighted>;
continue;
}
if (argv[i][0] != '-') {
switch (numUnflaggedArguments++) {
case 0:
baseDir.set(argv[i]);
continue;
case 1:
comparisonDir.set(argv[i]);
continue;
case 2:
outputDir.set(argv[i]);
continue;
default:
SkDebugf("extra unflagged argument <%s>\n", argv[i]);
usage(argv[0]);
return kGenericError;
}
}
if (!strcmp(argv[i], "--listFailingBase")) {
listFailingBase = true;
continue;
}
SkDebugf("Unrecognized argument <%s>\n", argv[i]);
usage(argv[0]);
return kGenericError;
}
if (numUnflaggedArguments == 2) {
outputDir = comparisonDir;
} else if (numUnflaggedArguments != 3) {
usage(argv[0]);
return kGenericError;
}
if (!baseDir.endsWith(PATH_DIV_STR)) {
baseDir.append(PATH_DIV_STR);
}
if (printDirNames) {
printf("baseDir is [%s]\n", baseDir.c_str());
}
if (!comparisonDir.endsWith(PATH_DIV_STR)) {
comparisonDir.append(PATH_DIV_STR);
}
if (printDirNames) {
printf("comparisonDir is [%s]\n", comparisonDir.c_str());
}
if (!outputDir.endsWith(PATH_DIV_STR)) {
outputDir.append(PATH_DIV_STR);
}
if (generateDiffs) {
if (printDirNames) {
printf("writing diffs to outputDir is [%s]\n", outputDir.c_str());
}
} else {
if (printDirNames) {
printf("not writing any diffs to outputDir [%s]\n", outputDir.c_str());
}
outputDir.set("");
}
// If no matchSubstrings were specified, match ALL strings
// (except for whatever nomatchSubstrings were specified, if any).
if (matchSubstrings.empty()) {
matchSubstrings.emplace_back("");
}
create_diff_images(diffProc, colorThreshold, ignoreColorSpace, &differences,
baseDir, comparisonDir, outputDir,
matchSubstrings, nomatchSubstrings, recurseIntoSubdirs, generateDiffs,
verbose, &summary);
summary.print(listFilenames, failOnResultType, failOnStatusType);
if (listFailingBase) {
summary.printfFailingBaseNames("\n");
}
if (differences.size()) {
qsort(differences.begin(), differences.size(), sizeof(DiffRecord), sortProc);
}
if (generateDiffs) {
print_diff_page(summary.fNumMatches, colorThreshold, differences,
baseDir, comparisonDir, outputDir);
}
int num_failing_results = 0;
for (int i = 0; i < DiffRecord::kResultCount; i++) {
if (failOnResultType[i]) {
num_failing_results += summary.fResultsOfType[i].size();
}
}
if (!failOnResultType[DiffRecord::kCouldNotCompare_Result]) {
for (int base = 0; base < DiffResource::kStatusCount; ++base) {
for (int comparison = 0; comparison < DiffResource::kStatusCount; ++comparison) {
if (failOnStatusType[base][comparison]) {
num_failing_results += summary.fStatusOfType[base][comparison].size();
}
}
}
}
// On Linux (and maybe other platforms too), any results outside of the
// range [0...255] are wrapped (mod 256). Do the conversion ourselves, to
// make sure that we only return 0 when there were no failures.
return (num_failing_results > 255) ? 255 : num_failing_results;
}