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