skdiff_image.cpp revision 667433ff5bc65680af31ca718d4cc29cce7b7040
1e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com/*
2e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com * Copyright 2012 Google Inc.
3e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com *
4e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com * Use of this source code is governed by a BSD-style license that can be
5e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com * found in the LICENSE file.
6e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com */
7e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com#include "skdiff.h"
8e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com#include "skdiff_utils.h"
9e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com#include "SkBitmap.h"
10e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com#include "SkData.h"
11e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com#include "SkImageEncoder.h"
12e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com#include "SkOSFile.h"
13e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com#include "SkTDArray.h"
14e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com#include "SkTemplates.h"
15e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com#include "SkTypes.h"
16e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com
1716b2dd05f0c5faca90b101c28ea01ff80257408abungeman@google.com#include <stdio.h>
1816b2dd05f0c5faca90b101c28ea01ff80257408abungeman@google.com
19e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com/// If outputDir.isEmpty(), don't write out diff files.
20e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.comstatic void create_diff_images (DiffMetricProc dmp,
21e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com                                const int colorThreshold,
22e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com                                const SkString& baseFile,
23e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com                                const SkString& comparisonFile,
24e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com                                const SkString& outputDir,
25e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com                                const SkString& outputFilename,
26e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com                                DiffRecord* drp) {
27e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com    SkASSERT(!baseFile.isEmpty());
28e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com    SkASSERT(!comparisonFile.isEmpty());
29e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com
30e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com    drp->fBase.fFilename = baseFile;
31e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com    drp->fBase.fFullPath = baseFile;
32e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com    drp->fBase.fStatus = DiffResource::kSpecified_Status;
33e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com
34e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com    drp->fComparison.fFilename = comparisonFile;
35e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com    drp->fComparison.fFullPath = comparisonFile;
36e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com    drp->fComparison.fStatus = DiffResource::kSpecified_Status;
37e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com
38e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com    SkAutoDataUnref baseFileBits(read_file(drp->fBase.fFullPath.c_str()));
3949f085dddff10473b6ebf832a974288300224e60bsalomon    if (baseFileBits) {
40e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com        drp->fBase.fStatus = DiffResource::kRead_Status;
41e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com    }
42e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com    SkAutoDataUnref comparisonFileBits(read_file(drp->fComparison.fFullPath.c_str()));
4349f085dddff10473b6ebf832a974288300224e60bsalomon    if (comparisonFileBits) {
44e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com        drp->fComparison.fStatus = DiffResource::kRead_Status;
45e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com    }
4696fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == baseFileBits || nullptr == comparisonFileBits) {
4796fcdcc219d2a0d3579719b84b28bede76efba64halcanary        if (nullptr == baseFileBits) {
48e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com            drp->fBase.fStatus = DiffResource::kCouldNotRead_Status;
49e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com        }
5096fcdcc219d2a0d3579719b84b28bede76efba64halcanary        if (nullptr == comparisonFileBits) {
51e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com            drp->fComparison.fStatus = DiffResource::kCouldNotRead_Status;
52e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com        }
53e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com        drp->fResult = DiffRecord::kCouldNotCompare_Result;
54e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com        return;
55e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com    }
56e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com
57e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com    if (are_buffers_equal(baseFileBits, comparisonFileBits)) {
58e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com        drp->fResult = DiffRecord::kEqualBits_Result;
59e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com        return;
60e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com    }
61e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com
62667433ff5bc65680af31ca718d4cc29cce7b7040msarett    get_bitmap(baseFileBits, drp->fBase, false);
63667433ff5bc65680af31ca718d4cc29cce7b7040msarett    get_bitmap(comparisonFileBits, drp->fComparison, false);
64e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com    if (DiffResource::kDecoded_Status != drp->fBase.fStatus ||
65e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com        DiffResource::kDecoded_Status != drp->fComparison.fStatus)
66e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com    {
67e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com        drp->fResult = DiffRecord::kCouldNotCompare_Result;
68e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com        return;
69e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com    }
70e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com
71e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com    create_and_write_diff_image(drp, dmp, colorThreshold, outputDir, outputFilename);
72e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com    //TODO: copy fBase.fFilename and fComparison.fFilename to outputDir
73e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com    //      svn and git often present tmp files to diff tools which are promptly deleted
74e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com
75e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com    //TODO: serialize drp to outputDir
76e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com    //      write a tool to deserialize them and call print_diff_page
77e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com
78e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com    SkASSERT(DiffRecord::kUnknown_Result != drp->fResult);
79e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com}
80e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com
81e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.comstatic void usage (char * argv0) {
82e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com    SkDebugf("Skia image diff tool\n");
83e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com    SkDebugf("\n"
84e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com"Usage: \n"
85e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com"    %s <baseFile> <comparisonFile>\n" , argv0);
86e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com    SkDebugf(
87e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com"\nArguments:"
88e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com"\n    --failonresult <result>: After comparing all file pairs, exit with nonzero"
89e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com"\n                             return code (number of file pairs yielding this"
90e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com"\n                             result) if any file pairs yielded this result."
91e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com"\n                             This flag may be repeated, in which case the"
92e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com"\n                             return code will be the number of fail pairs"
93e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com"\n                             yielding ANY of these results."
94e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com"\n    --failonstatus <baseStatus> <comparisonStatus>: exit with nonzero return"
95e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com"\n                             code if any file pairs yeilded this status."
96e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com"\n    --help: display this info"
97e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com"\n    --listfilenames: list all filenames for each result type in stdout"
98e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com"\n    --nodiffs: don't write out image diffs, just generate report on stdout"
99e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com"\n    --outputdir: directory to write difference images"
100e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com"\n    --threshold <n>: only report differences > n (per color channel) [default 0]"
101e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com"\n    -u: ignored. Recognized for compatibility with svn diff."
102e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com"\n    -L: first occurrence label for base, second occurrence label for comparison."
103e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com"\n        Labels must be of the form \"<filename>(\t<specifier>)?\"."
104e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com"\n        The base <filename> will be used to create files in outputdir."
105e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com"\n"
106e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com"\n    baseFile: baseline image file."
107e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com"\n    comparisonFile: comparison image file"
108e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com"\n"
109e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com"\nIf no sort is specified, it will sort by fraction of pixels mismatching."
110e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com"\n");
111e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com}
112e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com
113e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.comconst int kNoError = 0;
114e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.comconst int kGenericError = -1;
115e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com
116e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.comint tool_main(int argc, char** argv);
117e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.comint tool_main(int argc, char** argv) {
118e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com    DiffMetricProc diffProc = compute_diff_pmcolor;
119e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com
120e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com    // Maximum error tolerated in any one color channel in any one pixel before
121e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com    // a difference is reported.
122e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com    int colorThreshold = 0;
123e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com    SkString baseFile;
124e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com    SkString baseLabel;
125e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com    SkString comparisonFile;
126e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com    SkString comparisonLabel;
127e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com    SkString outputDir;
128e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com
129e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com    bool listFilenames = false;
130e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com
131e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com    bool failOnResultType[DiffRecord::kResultCount];
132e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com    for (int i = 0; i < DiffRecord::kResultCount; i++) {
133e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com        failOnResultType[i] = false;
134e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com    }
135e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com
136e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com    bool failOnStatusType[DiffResource::kStatusCount][DiffResource::kStatusCount];
137e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com    for (int base = 0; base < DiffResource::kStatusCount; ++base) {
138e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com        for (int comparison = 0; comparison < DiffResource::kStatusCount; ++comparison) {
139e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com            failOnStatusType[base][comparison] = false;
140e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com        }
141e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com    }
142e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com
143e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com    int i;
144e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com    int numUnflaggedArguments = 0;
145e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com    int numLabelArguments = 0;
146e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com    for (i = 1; i < argc; i++) {
147e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com        if (!strcmp(argv[i], "--failonresult")) {
148e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com            if (argc == ++i) {
149e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com                SkDebugf("failonresult expects one argument.\n");
150e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com                continue;
151e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com            }
152e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com            DiffRecord::Result type = DiffRecord::getResultByName(argv[i]);
153e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com            if (type != DiffRecord::kResultCount) {
154e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com                failOnResultType[type] = true;
155e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com            } else {
156e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com                SkDebugf("ignoring unrecognized result <%s>\n", argv[i]);
157e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com            }
158e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com            continue;
159e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com        }
160e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com        if (!strcmp(argv[i], "--failonstatus")) {
161e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com            if (argc == ++i) {
162e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com                SkDebugf("failonstatus missing base status.\n");
163e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com                continue;
164e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com            }
165e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com            bool baseStatuses[DiffResource::kStatusCount];
166e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com            if (!DiffResource::getMatchingStatuses(argv[i], baseStatuses)) {
167e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com                SkDebugf("unrecognized base status <%s>\n", argv[i]);
168e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com            }
169e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com
170e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com            if (argc == ++i) {
171e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com                SkDebugf("failonstatus missing comparison status.\n");
172e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com                continue;
173e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com            }
174e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com            bool comparisonStatuses[DiffResource::kStatusCount];
175e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com            if (!DiffResource::getMatchingStatuses(argv[i], comparisonStatuses)) {
176e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com                SkDebugf("unrecognized comarison status <%s>\n", argv[i]);
177e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com            }
178e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com
179e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com            for (int base = 0; base < DiffResource::kStatusCount; ++base) {
180e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com                for (int comparison = 0; comparison < DiffResource::kStatusCount; ++comparison) {
181e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com                    failOnStatusType[base][comparison] |=
182e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com                        baseStatuses[base] && comparisonStatuses[comparison];
183e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com                }
184e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com            }
185e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com            continue;
186e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com        }
187e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com        if (!strcmp(argv[i], "--help")) {
188e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com            usage(argv[0]);
189e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com            return kNoError;
190e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com        }
191e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com        if (!strcmp(argv[i], "--listfilenames")) {
192e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com            listFilenames = true;
193e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com            continue;
194e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com        }
195e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com        if (!strcmp(argv[i], "--outputdir")) {
196e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com            if (argc == ++i) {
197e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com                SkDebugf("outputdir expects one argument.\n");
198e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com                continue;
199e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com            }
200e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com            outputDir.set(argv[i]);
201e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com            continue;
202e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com        }
203e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com        if (!strcmp(argv[i], "--threshold")) {
204e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com            colorThreshold = atoi(argv[++i]);
205e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com            continue;
206e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com        }
207e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com        if (!strcmp(argv[i], "-u")) {
208e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com            //we don't produce unified diffs, ignore parameter to work with svn diff
209e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com            continue;
210e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com        }
211e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com        if (!strcmp(argv[i], "-L")) {
212e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com            if (argc == ++i) {
213e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com                SkDebugf("label expects one argument.\n");
214e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com                continue;
215e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com            }
216e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com            switch (numLabelArguments++) {
217e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com                case 0:
218e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com                    baseLabel.set(argv[i]);
219e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com                    continue;
220e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com                case 1:
221e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com                    comparisonLabel.set(argv[i]);
222e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com                    continue;
223e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com                default:
224e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com                    SkDebugf("extra label argument <%s>\n", argv[i]);
225e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com                    usage(argv[0]);
226e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com                    return kGenericError;
227e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com            }
228e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com            continue;
229e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com        }
230e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com        if (argv[i][0] != '-') {
231e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com            switch (numUnflaggedArguments++) {
232e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com                case 0:
233e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com                    baseFile.set(argv[i]);
234e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com                    continue;
235e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com                case 1:
236e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com                    comparisonFile.set(argv[i]);
237e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com                    continue;
238e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com                default:
239e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com                    SkDebugf("extra unflagged argument <%s>\n", argv[i]);
240e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com                    usage(argv[0]);
241e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com                    return kGenericError;
242e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com            }
243e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com        }
244e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com
245e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com        SkDebugf("Unrecognized argument <%s>\n", argv[i]);
246e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com        usage(argv[0]);
247e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com        return kGenericError;
248e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com    }
249e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com
250e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com    if (numUnflaggedArguments != 2) {
251e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com        usage(argv[0]);
252e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com        return kGenericError;
253e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com    }
254e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com
255e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com    if (listFilenames) {
256e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com        printf("Base file is [%s]\n", baseFile.c_str());
257e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com    }
258e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com
259e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com    if (listFilenames) {
260e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com        printf("Comparison file is [%s]\n", comparisonFile.c_str());
261e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com    }
262e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com
263e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com    if (outputDir.isEmpty()) {
264e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com        if (listFilenames) {
265e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com            printf("Not writing any diffs. No output dir specified.\n");
266e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com        }
267e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com    } else {
268e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com        if (!outputDir.endsWith(PATH_DIV_STR)) {
269e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com            outputDir.append(PATH_DIV_STR);
270e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com        }
271e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com        if (listFilenames) {
272e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com            printf("Writing diffs. Output dir is [%s]\n", outputDir.c_str());
273e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com        }
274e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com    }
275e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com
276e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com    // Some obscure documentation about diff/patch labels:
277e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com    //
278e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com    // Posix says the format is: <filename><tab><date>
279e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com    //     It also states that if a filename contains <tab> or <newline>
280e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com    //     the result is implementation defined
281e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com    //
282e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com    // Svn diff --diff-cmd provides labels of the form: <filename><tab><revision>
283e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com    //
284e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com    // Git diff --ext-diff does not supply arguments compatible with diff.
285e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com    //     However, it does provide the filename directly.
286e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com    //     skimagediff_git.sh: skimagediff %2 %5 -L "%1\t(%3)" -L "%1\t(%6)"
287e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com    //
288e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com    // Git difftool sets $LOCAL, $REMOTE, $MERGED, and $BASE instead of command line parameters.
289e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com    //     difftool.<>.cmd: skimagediff $LOCAL $REMOTE -L "$MERGED\t(local)" -L "$MERGED\t(remote)"
290e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com    //
291e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com    // Diff will write any specified label verbatim. Without a specified label diff will write
292e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com    //     <filename><tab><date>
293e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com    //     However, diff will encode the filename as a cstring if the filename contains
294e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com    //         Any of <space> or <double quote>
295e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com    //         A char less than 32
2965b7bac5ce162eee6d73c33373029a4e5a9f94683bungeman@google.com    //         Any escapable character \\, \a, \b, \t, \n, \v, \f, \r
297e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com    //
298e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com    // Patch decodes:
299e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com    //     If first <non-white-space> is <double quote>, parse filename from cstring.
300e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com    //     If there is a <tab> after the first <non-white-space>, filename is
301e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com    //         [first <non-white-space>, the next run of <white-space> with an embedded <tab>).
302e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com    //     Otherwise the filename is [first <non-space>, the next <white-space>).
303e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com    //
304e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com    // The filename /dev/null means the file does not exist (used in adds and deletes).
305e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com
306e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com    // Considering the above, skimagediff will consider the contents of a -L parameter as
307e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com    //     <filename>(\t<specifier>)?
308e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com    SkString outputFile;
309e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com
310e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com    if (baseLabel.isEmpty()) {
311e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com        baseLabel.set(baseFile);
312e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com        outputFile = baseLabel;
313e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com    } else {
314e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com        const char* baseLabelCstr = baseLabel.c_str();
315e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com        const char* tab = strchr(baseLabelCstr, '\t');
31696fcdcc219d2a0d3579719b84b28bede76efba64halcanary        if (nullptr == tab) {
317e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com            outputFile = baseLabel;
318e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com        } else {
319e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com            outputFile.set(baseLabelCstr, tab - baseLabelCstr);
320e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com        }
321e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com    }
322e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com    if (comparisonLabel.isEmpty()) {
323e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com        comparisonLabel.set(comparisonFile);
324e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com    }
325e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com    printf("Base:       %s\n", baseLabel.c_str());
326e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com    printf("Comparison: %s\n", comparisonLabel.c_str());
327e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com
328e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com    DiffRecord dr;
329e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com    create_diff_images(diffProc, colorThreshold, baseFile, comparisonFile, outputDir, outputFile,
330e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com                       &dr);
331e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com
332e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com    if (DiffResource::isStatusFailed(dr.fBase.fStatus)) {
333e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com        printf("Base %s.\n", DiffResource::getStatusDescription(dr.fBase.fStatus));
334e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com    }
335e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com    if (DiffResource::isStatusFailed(dr.fComparison.fStatus)) {
336e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com        printf("Comparison %s.\n", DiffResource::getStatusDescription(dr.fComparison.fStatus));
337e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com    }
338e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com    printf("Base and Comparison %s.\n", DiffRecord::getResultDescription(dr.fResult));
339e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com
340e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com    if (DiffRecord::kDifferentPixels_Result == dr.fResult) {
341e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com        printf("%.4f%% of pixels differ", 100 * dr.fFractionDifference);
342e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com        printf(" (%.4f%%  weighted)", 100 * dr.fWeightedFraction);
343e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com        if (dr.fFractionDifference < 0.01) {
344e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com            printf(" %d pixels", static_cast<int>(dr.fFractionDifference *
345e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com                                                  dr.fBase.fBitmap.width() *
346e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com                                                  dr.fBase.fBitmap.height()));
347e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com        }
348e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com
349e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com        printf("\nAverage color mismatch: ");
350e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com        printf("%d", static_cast<int>(MAX3(dr.fAverageMismatchR,
351e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com                                           dr.fAverageMismatchG,
352e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com                                           dr.fAverageMismatchB)));
353e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com        printf("\nMax color mismatch: ");
354e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com        printf("%d", MAX3(dr.fMaxMismatchR,
355e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com                          dr.fMaxMismatchG,
356e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com                          dr.fMaxMismatchB));
357e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com        printf("\n");
358e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com    }
359e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com    printf("\n");
360e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com
361e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com    int num_failing_results = 0;
362e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com    if (failOnResultType[dr.fResult]) {
363e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com        ++num_failing_results;
364e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com    }
365e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com    if (failOnStatusType[dr.fBase.fStatus][dr.fComparison.fStatus]) {
366e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com        ++num_failing_results;
367e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com    }
368e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com
369e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com    return num_failing_results;
370e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com}
371e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com
372e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com#if !defined SK_BUILD_FOR_IOS
373e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.comint main(int argc, char * const argv[]) {
374e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com    return tool_main(argc, (char**) argv);
375e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com}
376e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com#endif
377