xref: /aosp_15_r20/external/skia/tools/skdiff/skdiff.h (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker  * Copyright 2012 Google Inc.
3*c8dee2aaSAndroid Build Coastguard Worker  *
4*c8dee2aaSAndroid Build Coastguard Worker  * Use of this source code is governed by a BSD-style license that can be
5*c8dee2aaSAndroid Build Coastguard Worker  * found in the LICENSE file.
6*c8dee2aaSAndroid Build Coastguard Worker  */
7*c8dee2aaSAndroid Build Coastguard Worker 
8*c8dee2aaSAndroid Build Coastguard Worker #ifndef skdiff_DEFINED
9*c8dee2aaSAndroid Build Coastguard Worker #define skdiff_DEFINED
10*c8dee2aaSAndroid Build Coastguard Worker 
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkBitmap.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkColor.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkColorPriv.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkString.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkTArray.h"
16*c8dee2aaSAndroid Build Coastguard Worker 
17*c8dee2aaSAndroid Build Coastguard Worker #if defined(SK_BUILD_FOR_WIN)
18*c8dee2aaSAndroid Build Coastguard Worker     #define PATH_DIV_STR "\\"
19*c8dee2aaSAndroid Build Coastguard Worker     #define PATH_DIV_CHAR '\\'
20*c8dee2aaSAndroid Build Coastguard Worker #else
21*c8dee2aaSAndroid Build Coastguard Worker     #define PATH_DIV_STR "/"
22*c8dee2aaSAndroid Build Coastguard Worker     #define PATH_DIV_CHAR '/'
23*c8dee2aaSAndroid Build Coastguard Worker #endif
24*c8dee2aaSAndroid Build Coastguard Worker 
25*c8dee2aaSAndroid Build Coastguard Worker #define MAX2(a,b) (((b) < (a)) ? (a) : (b))
26*c8dee2aaSAndroid Build Coastguard Worker #define MAX3(a,b,c) (((b) < (a)) ? MAX2((a), (c)) : MAX2((b), (c)))
27*c8dee2aaSAndroid Build Coastguard Worker 
28*c8dee2aaSAndroid Build Coastguard Worker 
29*c8dee2aaSAndroid Build Coastguard Worker struct DiffResource {
30*c8dee2aaSAndroid Build Coastguard Worker     enum Status {
31*c8dee2aaSAndroid Build Coastguard Worker         /** The resource was specified, exists, read, and decoded. */
32*c8dee2aaSAndroid Build Coastguard Worker         kDecoded_Status,
33*c8dee2aaSAndroid Build Coastguard Worker         /** The resource was specified, exists, read, but could not be decoded. */
34*c8dee2aaSAndroid Build Coastguard Worker         kCouldNotDecode_Status,
35*c8dee2aaSAndroid Build Coastguard Worker 
36*c8dee2aaSAndroid Build Coastguard Worker         /** The resource was specified, exists, and read. */
37*c8dee2aaSAndroid Build Coastguard Worker         kRead_Status,
38*c8dee2aaSAndroid Build Coastguard Worker         /** The resource was specified, exists, but could not be read. */
39*c8dee2aaSAndroid Build Coastguard Worker         kCouldNotRead_Status,
40*c8dee2aaSAndroid Build Coastguard Worker 
41*c8dee2aaSAndroid Build Coastguard Worker         /** The resource was specified and exists. */
42*c8dee2aaSAndroid Build Coastguard Worker         kExists_Status,
43*c8dee2aaSAndroid Build Coastguard Worker         /** The resource was specified, but does not exist. */
44*c8dee2aaSAndroid Build Coastguard Worker         kDoesNotExist_Status,
45*c8dee2aaSAndroid Build Coastguard Worker 
46*c8dee2aaSAndroid Build Coastguard Worker         /** The resource was specified. */
47*c8dee2aaSAndroid Build Coastguard Worker         kSpecified_Status,
48*c8dee2aaSAndroid Build Coastguard Worker         /** The resource was not specified. */
49*c8dee2aaSAndroid Build Coastguard Worker         kUnspecified_Status,
50*c8dee2aaSAndroid Build Coastguard Worker 
51*c8dee2aaSAndroid Build Coastguard Worker         /** Nothing is yet known about the resource. */
52*c8dee2aaSAndroid Build Coastguard Worker         kUnknown_Status,
53*c8dee2aaSAndroid Build Coastguard Worker 
54*c8dee2aaSAndroid Build Coastguard Worker         /** NOT A VALID VALUE -- used to set up arrays and to represent an unknown value. */
55*c8dee2aaSAndroid Build Coastguard Worker         kStatusCount
56*c8dee2aaSAndroid Build Coastguard Worker     };
57*c8dee2aaSAndroid Build Coastguard Worker     static char const * const StatusNames[DiffResource::kStatusCount];
58*c8dee2aaSAndroid Build Coastguard Worker 
59*c8dee2aaSAndroid Build Coastguard Worker     /** Returns the Status with this name.
60*c8dee2aaSAndroid Build Coastguard Worker      *  If there is no Status with this name, returns kStatusCount.
61*c8dee2aaSAndroid Build Coastguard Worker      */
62*c8dee2aaSAndroid Build Coastguard Worker     static Status getStatusByName(const char *name);
63*c8dee2aaSAndroid Build Coastguard Worker 
64*c8dee2aaSAndroid Build Coastguard Worker     /** Returns a text description of the given Status type. */
65*c8dee2aaSAndroid Build Coastguard Worker     static const char *getStatusDescription(Status status);
66*c8dee2aaSAndroid Build Coastguard Worker 
67*c8dee2aaSAndroid Build Coastguard Worker     /** Returns true if the Status indicates some kind of failure. */
68*c8dee2aaSAndroid Build Coastguard Worker     static bool isStatusFailed(Status status);
69*c8dee2aaSAndroid Build Coastguard Worker 
70*c8dee2aaSAndroid Build Coastguard Worker     /** Sets statuses[i] if it is implied by selector, unsets it if not.
71*c8dee2aaSAndroid Build Coastguard Worker      *  Selector may be a comma delimited list of status names, "any", or "failed".
72*c8dee2aaSAndroid Build Coastguard Worker      *  Returns true if the selector was entirely understood, false otherwise.
73*c8dee2aaSAndroid Build Coastguard Worker      */
74*c8dee2aaSAndroid Build Coastguard Worker     static bool getMatchingStatuses(char* selector, bool statuses[kStatusCount]);
75*c8dee2aaSAndroid Build Coastguard Worker 
DiffResourceDiffResource76*c8dee2aaSAndroid Build Coastguard Worker     DiffResource() : fFilename(), fFullPath(), fBitmap(), fStatus(kUnknown_Status) { }
77*c8dee2aaSAndroid Build Coastguard Worker 
78*c8dee2aaSAndroid Build Coastguard Worker     /** If isEmpty() indicates no filename available. */
79*c8dee2aaSAndroid Build Coastguard Worker     SkString fFilename;
80*c8dee2aaSAndroid Build Coastguard Worker     /** If isEmpty() indicates no path available. */
81*c8dee2aaSAndroid Build Coastguard Worker     SkString fFullPath;
82*c8dee2aaSAndroid Build Coastguard Worker     /** If empty() indicates the bitmap could not be created. */
83*c8dee2aaSAndroid Build Coastguard Worker     SkBitmap fBitmap;
84*c8dee2aaSAndroid Build Coastguard Worker     Status fStatus;
85*c8dee2aaSAndroid Build Coastguard Worker };
86*c8dee2aaSAndroid Build Coastguard Worker 
87*c8dee2aaSAndroid Build Coastguard Worker struct DiffRecord {
88*c8dee2aaSAndroid Build Coastguard Worker 
89*c8dee2aaSAndroid Build Coastguard Worker     // Result of comparison for each pair of files.
90*c8dee2aaSAndroid Build Coastguard Worker     // Listed from "better" to "worse", for sorting of results.
91*c8dee2aaSAndroid Build Coastguard Worker     enum Result {
92*c8dee2aaSAndroid Build Coastguard Worker         kEqualBits_Result,
93*c8dee2aaSAndroid Build Coastguard Worker         kEqualPixels_Result,
94*c8dee2aaSAndroid Build Coastguard Worker         kDifferentPixels_Result,
95*c8dee2aaSAndroid Build Coastguard Worker         kDifferentSizes_Result,
96*c8dee2aaSAndroid Build Coastguard Worker         kCouldNotCompare_Result,
97*c8dee2aaSAndroid Build Coastguard Worker         kUnknown_Result,
98*c8dee2aaSAndroid Build Coastguard Worker 
99*c8dee2aaSAndroid Build Coastguard Worker         kResultCount  // NOT A VALID VALUE--used to set up arrays. Must be last.
100*c8dee2aaSAndroid Build Coastguard Worker     };
101*c8dee2aaSAndroid Build Coastguard Worker     static char const * const ResultNames[DiffRecord::kResultCount];
102*c8dee2aaSAndroid Build Coastguard Worker 
103*c8dee2aaSAndroid Build Coastguard Worker     /** Returns the Result with this name.
104*c8dee2aaSAndroid Build Coastguard Worker      *  If there is no Result with this name, returns kResultCount.
105*c8dee2aaSAndroid Build Coastguard Worker      */
106*c8dee2aaSAndroid Build Coastguard Worker     static Result getResultByName(const char *name);
107*c8dee2aaSAndroid Build Coastguard Worker 
108*c8dee2aaSAndroid Build Coastguard Worker     /** Returns a text description of the given Result type. */
109*c8dee2aaSAndroid Build Coastguard Worker     static const char *getResultDescription(Result result);
110*c8dee2aaSAndroid Build Coastguard Worker 
DiffRecordDiffRecord111*c8dee2aaSAndroid Build Coastguard Worker     DiffRecord()
112*c8dee2aaSAndroid Build Coastguard Worker         : fBase()
113*c8dee2aaSAndroid Build Coastguard Worker         , fComparison()
114*c8dee2aaSAndroid Build Coastguard Worker         , fDifference()
115*c8dee2aaSAndroid Build Coastguard Worker         , fWhite()
116*c8dee2aaSAndroid Build Coastguard Worker         , fFractionDifference(0)
117*c8dee2aaSAndroid Build Coastguard Worker         , fWeightedFraction(0)
118*c8dee2aaSAndroid Build Coastguard Worker         , fAverageMismatchA(0)
119*c8dee2aaSAndroid Build Coastguard Worker         , fAverageMismatchR(0)
120*c8dee2aaSAndroid Build Coastguard Worker         , fAverageMismatchG(0)
121*c8dee2aaSAndroid Build Coastguard Worker         , fAverageMismatchB(0)
122*c8dee2aaSAndroid Build Coastguard Worker         , fTotalMismatchA(0)
123*c8dee2aaSAndroid Build Coastguard Worker         , fMaxMismatchA(0)
124*c8dee2aaSAndroid Build Coastguard Worker         , fMaxMismatchR(0)
125*c8dee2aaSAndroid Build Coastguard Worker         , fMaxMismatchG(0)
126*c8dee2aaSAndroid Build Coastguard Worker         , fMaxMismatchB(0)
127*c8dee2aaSAndroid Build Coastguard Worker         , fResult(kUnknown_Result) {
128*c8dee2aaSAndroid Build Coastguard Worker     }
129*c8dee2aaSAndroid Build Coastguard Worker 
130*c8dee2aaSAndroid Build Coastguard Worker     DiffResource fBase;
131*c8dee2aaSAndroid Build Coastguard Worker     DiffResource fComparison;
132*c8dee2aaSAndroid Build Coastguard Worker     DiffResource fDifference;
133*c8dee2aaSAndroid Build Coastguard Worker     DiffResource fWhite;
134*c8dee2aaSAndroid Build Coastguard Worker 
135*c8dee2aaSAndroid Build Coastguard Worker     /// Arbitrary floating-point metric to be used to sort images from most
136*c8dee2aaSAndroid Build Coastguard Worker     /// to least different from baseline; values of 0 will be omitted from the
137*c8dee2aaSAndroid Build Coastguard Worker     /// summary webpage.
138*c8dee2aaSAndroid Build Coastguard Worker     float fFractionDifference;
139*c8dee2aaSAndroid Build Coastguard Worker     float fWeightedFraction;
140*c8dee2aaSAndroid Build Coastguard Worker 
141*c8dee2aaSAndroid Build Coastguard Worker     float fAverageMismatchA;
142*c8dee2aaSAndroid Build Coastguard Worker     float fAverageMismatchR;
143*c8dee2aaSAndroid Build Coastguard Worker     float fAverageMismatchG;
144*c8dee2aaSAndroid Build Coastguard Worker     float fAverageMismatchB;
145*c8dee2aaSAndroid Build Coastguard Worker 
146*c8dee2aaSAndroid Build Coastguard Worker     uint32_t fTotalMismatchA;
147*c8dee2aaSAndroid Build Coastguard Worker 
148*c8dee2aaSAndroid Build Coastguard Worker     uint32_t fMaxMismatchA;
149*c8dee2aaSAndroid Build Coastguard Worker     uint32_t fMaxMismatchR;
150*c8dee2aaSAndroid Build Coastguard Worker     uint32_t fMaxMismatchG;
151*c8dee2aaSAndroid Build Coastguard Worker     uint32_t fMaxMismatchB;
152*c8dee2aaSAndroid Build Coastguard Worker 
153*c8dee2aaSAndroid Build Coastguard Worker     /// Which category of diff result.
154*c8dee2aaSAndroid Build Coastguard Worker     Result fResult;
155*c8dee2aaSAndroid Build Coastguard Worker };
156*c8dee2aaSAndroid Build Coastguard Worker 
157*c8dee2aaSAndroid Build Coastguard Worker typedef skia_private::TArray<DiffRecord> RecordArray;
158*c8dee2aaSAndroid Build Coastguard Worker 
159*c8dee2aaSAndroid Build Coastguard Worker /// A wrapper for any sortProc (comparison routine) which applies a first-order
160*c8dee2aaSAndroid Build Coastguard Worker /// sort beforehand, and a tiebreaker if the sortProc returns 0.
compare(const void * untyped_lhs,const void * untyped_rhs)161*c8dee2aaSAndroid Build Coastguard Worker template<typename T> int compare(const void* untyped_lhs, const void* untyped_rhs) {
162*c8dee2aaSAndroid Build Coastguard Worker     const DiffRecord* lhs = reinterpret_cast<DiffRecord const *>(untyped_lhs);
163*c8dee2aaSAndroid Build Coastguard Worker     const DiffRecord* rhs = reinterpret_cast<DiffRecord const *>(untyped_rhs);
164*c8dee2aaSAndroid Build Coastguard Worker 
165*c8dee2aaSAndroid Build Coastguard Worker     // First-order sort... these comparisons should be applied before comparing
166*c8dee2aaSAndroid Build Coastguard Worker     // pixel values, no matter what.
167*c8dee2aaSAndroid Build Coastguard Worker     if (lhs->fResult != rhs->fResult) {
168*c8dee2aaSAndroid Build Coastguard Worker         return (lhs->fResult < rhs->fResult) ? 1 : -1;
169*c8dee2aaSAndroid Build Coastguard Worker     }
170*c8dee2aaSAndroid Build Coastguard Worker 
171*c8dee2aaSAndroid Build Coastguard Worker     // Passed first-order sort, so call the pixel comparison routine.
172*c8dee2aaSAndroid Build Coastguard Worker     int result = T::comparePixels(lhs, rhs);
173*c8dee2aaSAndroid Build Coastguard Worker     if (result != 0) {
174*c8dee2aaSAndroid Build Coastguard Worker         return result;
175*c8dee2aaSAndroid Build Coastguard Worker     }
176*c8dee2aaSAndroid Build Coastguard Worker 
177*c8dee2aaSAndroid Build Coastguard Worker     // Tiebreaker... if we got to this point, we don't really care
178*c8dee2aaSAndroid Build Coastguard Worker     // which order they are sorted in, but let's at least be consistent.
179*c8dee2aaSAndroid Build Coastguard Worker     return strcmp(lhs->fBase.fFilename.c_str(), rhs->fBase.fFilename.c_str());
180*c8dee2aaSAndroid Build Coastguard Worker }
181*c8dee2aaSAndroid Build Coastguard Worker 
182*c8dee2aaSAndroid Build Coastguard Worker /// Comparison routine for qsort; sorts by fFractionDifference
183*c8dee2aaSAndroid Build Coastguard Worker /// from largest to smallest.
184*c8dee2aaSAndroid Build Coastguard Worker class CompareDiffMetrics {
185*c8dee2aaSAndroid Build Coastguard Worker public:
comparePixels(const DiffRecord * lhs,const DiffRecord * rhs)186*c8dee2aaSAndroid Build Coastguard Worker     static int comparePixels(const DiffRecord* lhs, const DiffRecord* rhs) {
187*c8dee2aaSAndroid Build Coastguard Worker         if (lhs->fFractionDifference < rhs->fFractionDifference) {
188*c8dee2aaSAndroid Build Coastguard Worker           return 1;
189*c8dee2aaSAndroid Build Coastguard Worker         }
190*c8dee2aaSAndroid Build Coastguard Worker         if (rhs->fFractionDifference < lhs->fFractionDifference) {
191*c8dee2aaSAndroid Build Coastguard Worker           return -1;
192*c8dee2aaSAndroid Build Coastguard Worker         }
193*c8dee2aaSAndroid Build Coastguard Worker         return 0;
194*c8dee2aaSAndroid Build Coastguard Worker     }
195*c8dee2aaSAndroid Build Coastguard Worker };
196*c8dee2aaSAndroid Build Coastguard Worker 
197*c8dee2aaSAndroid Build Coastguard Worker class CompareDiffWeighted {
198*c8dee2aaSAndroid Build Coastguard Worker public:
comparePixels(const DiffRecord * lhs,const DiffRecord * rhs)199*c8dee2aaSAndroid Build Coastguard Worker     static int comparePixels(const DiffRecord* lhs, const DiffRecord* rhs) {
200*c8dee2aaSAndroid Build Coastguard Worker         if (lhs->fWeightedFraction < rhs->fWeightedFraction) {
201*c8dee2aaSAndroid Build Coastguard Worker             return 1;
202*c8dee2aaSAndroid Build Coastguard Worker         }
203*c8dee2aaSAndroid Build Coastguard Worker         if (lhs->fWeightedFraction > rhs->fWeightedFraction) {
204*c8dee2aaSAndroid Build Coastguard Worker             return -1;
205*c8dee2aaSAndroid Build Coastguard Worker         }
206*c8dee2aaSAndroid Build Coastguard Worker         return 0;
207*c8dee2aaSAndroid Build Coastguard Worker     }
208*c8dee2aaSAndroid Build Coastguard Worker };
209*c8dee2aaSAndroid Build Coastguard Worker 
210*c8dee2aaSAndroid Build Coastguard Worker /// Comparison routine for qsort;  sorts by max(fAverageMismatch{RGB})
211*c8dee2aaSAndroid Build Coastguard Worker /// from largest to smallest.
212*c8dee2aaSAndroid Build Coastguard Worker class CompareDiffMeanMismatches {
213*c8dee2aaSAndroid Build Coastguard Worker public:
comparePixels(const DiffRecord * lhs,const DiffRecord * rhs)214*c8dee2aaSAndroid Build Coastguard Worker     static int comparePixels(const DiffRecord* lhs, const DiffRecord* rhs) {
215*c8dee2aaSAndroid Build Coastguard Worker         float leftValue = MAX3(lhs->fAverageMismatchR,
216*c8dee2aaSAndroid Build Coastguard Worker                                lhs->fAverageMismatchG,
217*c8dee2aaSAndroid Build Coastguard Worker                                lhs->fAverageMismatchB);
218*c8dee2aaSAndroid Build Coastguard Worker         float rightValue = MAX3(rhs->fAverageMismatchR,
219*c8dee2aaSAndroid Build Coastguard Worker                                 rhs->fAverageMismatchG,
220*c8dee2aaSAndroid Build Coastguard Worker                                 rhs->fAverageMismatchB);
221*c8dee2aaSAndroid Build Coastguard Worker         if (leftValue < rightValue) {
222*c8dee2aaSAndroid Build Coastguard Worker             return 1;
223*c8dee2aaSAndroid Build Coastguard Worker         }
224*c8dee2aaSAndroid Build Coastguard Worker         if (rightValue < leftValue) {
225*c8dee2aaSAndroid Build Coastguard Worker             return -1;
226*c8dee2aaSAndroid Build Coastguard Worker         }
227*c8dee2aaSAndroid Build Coastguard Worker         return 0;
228*c8dee2aaSAndroid Build Coastguard Worker     }
229*c8dee2aaSAndroid Build Coastguard Worker };
230*c8dee2aaSAndroid Build Coastguard Worker 
231*c8dee2aaSAndroid Build Coastguard Worker /// Comparison routine for qsort;  sorts by max(fMaxMismatch{RGB})
232*c8dee2aaSAndroid Build Coastguard Worker /// from largest to smallest.
233*c8dee2aaSAndroid Build Coastguard Worker class CompareDiffMaxMismatches {
234*c8dee2aaSAndroid Build Coastguard Worker public:
comparePixels(const DiffRecord * lhs,const DiffRecord * rhs)235*c8dee2aaSAndroid Build Coastguard Worker     static int comparePixels(const DiffRecord* lhs, const DiffRecord* rhs) {
236*c8dee2aaSAndroid Build Coastguard Worker         uint32_t leftValue = MAX3(lhs->fMaxMismatchR,
237*c8dee2aaSAndroid Build Coastguard Worker                                   lhs->fMaxMismatchG,
238*c8dee2aaSAndroid Build Coastguard Worker                                   lhs->fMaxMismatchB);
239*c8dee2aaSAndroid Build Coastguard Worker         uint32_t rightValue = MAX3(rhs->fMaxMismatchR,
240*c8dee2aaSAndroid Build Coastguard Worker                                    rhs->fMaxMismatchG,
241*c8dee2aaSAndroid Build Coastguard Worker                                    rhs->fMaxMismatchB);
242*c8dee2aaSAndroid Build Coastguard Worker         if (leftValue < rightValue) {
243*c8dee2aaSAndroid Build Coastguard Worker             return 1;
244*c8dee2aaSAndroid Build Coastguard Worker         }
245*c8dee2aaSAndroid Build Coastguard Worker         if (rightValue < leftValue) {
246*c8dee2aaSAndroid Build Coastguard Worker             return -1;
247*c8dee2aaSAndroid Build Coastguard Worker         }
248*c8dee2aaSAndroid Build Coastguard Worker 
249*c8dee2aaSAndroid Build Coastguard Worker         return CompareDiffMeanMismatches::comparePixels(lhs, rhs);
250*c8dee2aaSAndroid Build Coastguard Worker     }
251*c8dee2aaSAndroid Build Coastguard Worker };
252*c8dee2aaSAndroid Build Coastguard Worker 
253*c8dee2aaSAndroid Build Coastguard Worker 
254*c8dee2aaSAndroid Build Coastguard Worker /// Parameterized routine to compute the color of a pixel in a difference image.
255*c8dee2aaSAndroid Build Coastguard Worker typedef SkPMColor (*DiffMetricProc)(SkPMColor, SkPMColor);
256*c8dee2aaSAndroid Build Coastguard Worker 
257*c8dee2aaSAndroid Build Coastguard Worker // from gm
compute_diff_pmcolor(SkPMColor c0,SkPMColor c1)258*c8dee2aaSAndroid Build Coastguard Worker static inline SkPMColor compute_diff_pmcolor(SkPMColor c0, SkPMColor c1) {
259*c8dee2aaSAndroid Build Coastguard Worker     int dr = SkGetPackedR32(c0) - SkGetPackedR32(c1);
260*c8dee2aaSAndroid Build Coastguard Worker     int dg = SkGetPackedG32(c0) - SkGetPackedG32(c1);
261*c8dee2aaSAndroid Build Coastguard Worker     int db = SkGetPackedB32(c0) - SkGetPackedB32(c1);
262*c8dee2aaSAndroid Build Coastguard Worker 
263*c8dee2aaSAndroid Build Coastguard Worker     return SkPackARGB32(0xFF, SkAbs32(dr), SkAbs32(dg), SkAbs32(db));
264*c8dee2aaSAndroid Build Coastguard Worker }
265*c8dee2aaSAndroid Build Coastguard Worker 
266*c8dee2aaSAndroid Build Coastguard Worker /** When finished, dr->fResult should have some value other than kUnknown_Result.
267*c8dee2aaSAndroid Build Coastguard Worker  *  Expects dr->fWhite.fBitmap and dr->fDifference.fBitmap to have the same bounds as
268*c8dee2aaSAndroid Build Coastguard Worker  *  dr->fBase.fBitmap and have a valid pixelref.
269*c8dee2aaSAndroid Build Coastguard Worker  */
270*c8dee2aaSAndroid Build Coastguard Worker void compute_diff(DiffRecord* dr, DiffMetricProc diffFunction, const int colorThreshold);
271*c8dee2aaSAndroid Build Coastguard Worker 
272*c8dee2aaSAndroid Build Coastguard Worker #endif
273