Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
skdiff.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2012 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
12#include "tools/skdiff/skdiff.h"
13
14/*static*/ char const * const DiffRecord::ResultNames[DiffRecord::kResultCount] = {
15 "EqualBits",
16 "EqualPixels",
17 "DifferentPixels",
18 "DifferentSizes",
19 "CouldNotCompare",
20 "Unknown",
21};
22
24 for (int result = 0; result < DiffRecord::kResultCount; ++result) {
25 if (0 == strcmp(DiffRecord::ResultNames[result], name)) {
26 return static_cast<DiffRecord::Result>(result);
27 }
28 }
30}
31
32static char const * const ResultDescriptions[DiffRecord::kResultCount] = {
33 "contain exactly the same bits",
34 "contain the same pixel values, but not the same bits",
35 "have identical dimensions but some differing pixels",
36 "have differing dimensions",
37 "could not be compared",
38 "not compared yet",
39};
40
44
45/*static*/ char const * const DiffResource::StatusNames[DiffResource::kStatusCount] = {
46 "Decoded",
47 "CouldNotDecode",
48
49 "Read",
50 "CouldNotRead",
51
52 "Exists",
53 "DoesNotExist",
54
55 "Specified",
56 "Unspecified",
57
58 "Unknown",
59};
60
62 for (int status = 0; status < DiffResource::kStatusCount; ++status) {
63 if (0 == strcmp(DiffResource::StatusNames[status], name)) {
64 return static_cast<DiffResource::Status>(status);
65 }
66 }
68}
69
70static char const * const StatusDescriptions[DiffResource::kStatusCount] = {
71 "decoded",
72 "could not be decoded",
73
74 "read",
75 "could not be read",
76
77 "found",
78 "not found",
79
80 "specified",
81 "unspecified",
82
83 "unknown",
84};
85
89
97
98bool DiffResource::getMatchingStatuses(char* selector, bool statuses[kStatusCount]) {
99 if (!strcmp(selector, "any")) {
100 for (int statusIndex = 0; statusIndex < kStatusCount; ++statusIndex) {
101 statuses[statusIndex] = true;
102 }
103 return true;
104 }
105
106 for (int statusIndex = 0; statusIndex < kStatusCount; ++statusIndex) {
107 statuses[statusIndex] = false;
108 }
109
110 static const char kDelimiterChar = ',';
111 bool understood = true;
112 while (true) {
113 char* delimiterPtr = strchr(selector, kDelimiterChar);
114
115 if (delimiterPtr) {
116 *delimiterPtr = '\0';
117 }
118
119 if (!strcmp(selector, "failed")) {
120 for (int statusIndex = 0; statusIndex < kStatusCount; ++statusIndex) {
121 Status status = static_cast<Status>(statusIndex);
122 statuses[statusIndex] |= isStatusFailed(status);
123 }
124 } else {
125 Status status = getStatusByName(selector);
126 if (status == kStatusCount) {
127 understood = false;
128 } else {
129 statuses[status] = true;
130 }
131 }
132
133 if (!delimiterPtr) {
134 break;
135 }
136
137 *delimiterPtr = kDelimiterChar;
138 selector = delimiterPtr + 1;
139 }
140 return understood;
141}
142
143static inline bool colors_match_thresholded(SkPMColor c0, SkPMColor c1, const int threshold) {
144 int da = SkGetPackedA32(c0) - SkGetPackedA32(c1);
145 int dr = SkGetPackedR32(c0) - SkGetPackedR32(c1);
146 int dg = SkGetPackedG32(c0) - SkGetPackedG32(c1);
147 int db = SkGetPackedB32(c0) - SkGetPackedB32(c1);
148
149 return ((SkAbs32(da) <= threshold) &&
150 (SkAbs32(dr) <= threshold) &&
151 (SkAbs32(dg) <= threshold) &&
152 (SkAbs32(db) <= threshold));
153}
154
157
158void compute_diff(DiffRecord* dr, DiffMetricProc diffFunction, const int colorThreshold) {
159 const int w = dr->fComparison.fBitmap.width();
160 const int h = dr->fComparison.fBitmap.height();
161 if (w != dr->fBase.fBitmap.width() || h != dr->fBase.fBitmap.height()) {
163 return;
164 }
165
166 int mismatchedPixels = 0;
167 int totalMismatchA = 0;
168 int totalMismatchR = 0;
169 int totalMismatchG = 0;
170 int totalMismatchB = 0;
171
172 // Accumulate fractionally different pixels, then divide out
173 // # of pixels at the end.
174 dr->fWeightedFraction = 0;
175 for (int y = 0; y < h; y++) {
176 for (int x = 0; x < w; x++) {
177 SkPMColor c0 = *dr->fBase.fBitmap.getAddr32(x, y);
178 SkPMColor c1 = *dr->fComparison.fBitmap.getAddr32(x, y);
179 SkPMColor outputDifference = diffFunction(c0, c1);
180 uint32_t thisA = SkAbs32(SkGetPackedA32(c0) - SkGetPackedA32(c1));
181 uint32_t thisR = SkAbs32(SkGetPackedR32(c0) - SkGetPackedR32(c1));
182 uint32_t thisG = SkAbs32(SkGetPackedG32(c0) - SkGetPackedG32(c1));
183 uint32_t thisB = SkAbs32(SkGetPackedB32(c0) - SkGetPackedB32(c1));
184 totalMismatchA += thisA;
185 totalMismatchR += thisR;
186 totalMismatchG += thisG;
187 totalMismatchB += thisB;
188 // In HSV, value is defined as max RGB component.
189 int value = MAX3(thisR, thisG, thisB);
190 dr->fWeightedFraction += ((float) value) / 255;
191 if (thisA > dr->fMaxMismatchA) {
192 dr->fMaxMismatchA = thisA;
193 }
194 if (thisR > dr->fMaxMismatchR) {
195 dr->fMaxMismatchR = thisR;
196 }
197 if (thisG > dr->fMaxMismatchG) {
198 dr->fMaxMismatchG = thisG;
199 }
200 if (thisB > dr->fMaxMismatchB) {
201 dr->fMaxMismatchB = thisB;
202 }
203 if (!colors_match_thresholded(c0, c1, colorThreshold)) {
204 mismatchedPixels++;
205 *dr->fDifference.fBitmap.getAddr32(x, y) = outputDifference;
206 *dr->fWhite.fBitmap.getAddr32(x, y) = PMCOLOR_WHITE;
207 } else {
208 *dr->fDifference.fBitmap.getAddr32(x, y) = 0;
209 *dr->fWhite.fBitmap.getAddr32(x, y) = PMCOLOR_BLACK;
210 }
211 }
212 }
213 if (0 == mismatchedPixels) {
215 return;
216 }
218 int pixelCount = w * h;
219 dr->fFractionDifference = ((float) mismatchedPixels) / pixelCount;
220 dr->fWeightedFraction /= pixelCount;
221 dr->fTotalMismatchA = totalMismatchA;
222 dr->fAverageMismatchA = ((float) totalMismatchA) / pixelCount;
223 dr->fAverageMismatchR = ((float) totalMismatchR) / pixelCount;
224 dr->fAverageMismatchG = ((float) totalMismatchG) / pixelCount;
225 dr->fAverageMismatchB = ((float) totalMismatchB) / pixelCount;
226}
#define SkGetPackedB32(packed)
Definition SkColorPriv.h:95
#define SkGetPackedR32(packed)
Definition SkColorPriv.h:93
#define SkGetPackedA32(packed)
Definition SkColorPriv.h:92
#define SkGetPackedG32(packed)
Definition SkColorPriv.h:94
SK_API SkPMColor SkPreMultiplyColor(SkColor c)
Definition SkColor.cpp:21
uint32_t SkPMColor
Definition SkColor.h:205
constexpr SkColor SK_ColorBLACK
Definition SkColor.h:103
constexpr SkColor SK_ColorWHITE
Definition SkColor.h:122
static int32_t SkAbs32(int32_t value)
Definition SkSafe32.h:41
uint8_t value
GAsyncResult * result
const char * name
Definition fuchsia.cc:50
double y
double x
SkScalar w
SkScalar h
static char const *const ResultDescriptions[DiffRecord::kResultCount]
Definition skdiff.cpp:32
static bool colors_match_thresholded(SkPMColor c0, SkPMColor c1, const int threshold)
Definition skdiff.cpp:143
const SkPMColor PMCOLOR_BLACK
Definition skdiff.cpp:156
void compute_diff(DiffRecord *dr, DiffMetricProc diffFunction, const int colorThreshold)
Definition skdiff.cpp:158
static char const *const StatusDescriptions[DiffResource::kStatusCount]
Definition skdiff.cpp:70
const SkPMColor PMCOLOR_WHITE
Definition skdiff.cpp:155
#define MAX3(a, b, c)
Definition skdiff.h:26
SkPMColor(* DiffMetricProc)(SkPMColor, SkPMColor)
Parameterized routine to compute the color of a pixel in a difference image.
Definition skdiff.h:255
static char const *const ResultNames[DiffRecord::kResultCount]
Definition skdiff.h:14
static Result getResultByName(const char *name)
Definition skdiff.cpp:23
@ kResultCount
Definition skdiff.h:99
@ kDifferentSizes_Result
Definition skdiff.h:95
@ kDifferentPixels_Result
Definition skdiff.h:94
@ kEqualPixels_Result
Definition skdiff.h:93
static const char * getResultDescription(Result result)
Definition skdiff.cpp:41
static char const *const StatusNames[DiffResource::kStatusCount]
Definition skdiff.h:45
static Status getStatusByName(const char *name)
Definition skdiff.cpp:61
static const char * getStatusDescription(Status status)
Definition skdiff.cpp:86
static bool isStatusFailed(Status status)
Definition skdiff.cpp:90
static bool getMatchingStatuses(char *selector, bool statuses[kStatusCount])
Definition skdiff.cpp:98
@ kCouldNotDecode_Status
Definition skdiff.h:34
@ kCouldNotRead_Status
Definition skdiff.h:39
@ kDoesNotExist_Status
Definition skdiff.h:44
@ kStatusCount
Definition skdiff.h:55
@ kUnknown_Status
Definition skdiff.h:52
@ kUnspecified_Status
Definition skdiff.h:49