diff options
Diffstat (limited to 'chromium/third_party/skia/tools/skdiff.h')
-rw-r--r-- | chromium/third_party/skia/tools/skdiff.h | 272 |
1 files changed, 272 insertions, 0 deletions
diff --git a/chromium/third_party/skia/tools/skdiff.h b/chromium/third_party/skia/tools/skdiff.h new file mode 100644 index 00000000000..6abaf6c4056 --- /dev/null +++ b/chromium/third_party/skia/tools/skdiff.h @@ -0,0 +1,272 @@ +/* + * Copyright 2012 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef skdiff_DEFINED +#define skdiff_DEFINED + +#include "SkBitmap.h" +#include "SkColor.h" +#include "SkColorPriv.h" +#include "SkString.h" +#include "SkTDArray.h" + +#if SK_BUILD_FOR_WIN32 + #define PATH_DIV_STR "\\" + #define PATH_DIV_CHAR '\\' +#else + #define PATH_DIV_STR "/" + #define PATH_DIV_CHAR '/' +#endif + +#define MAX2(a,b) (((b) < (a)) ? (a) : (b)) +#define MAX3(a,b,c) (((b) < (a)) ? MAX2((a), (c)) : MAX2((b), (c))) + + +struct DiffResource { + enum Status { + /** The resource was specified, exists, read, and decoded. */ + kDecoded_Status, + /** The resource was specified, exists, read, but could not be decoded. */ + kCouldNotDecode_Status, + + /** The resource was specified, exists, and read. */ + kRead_Status, + /** The resource was specified, exists, but could not be read. */ + kCouldNotRead_Status, + + /** The resource was specified and exists. */ + kExists_Status, + /** The resource was specified, but does not exist. */ + kDoesNotExist_Status, + + /** The resource was specified. */ + kSpecified_Status, + /** The resource was not specified. */ + kUnspecified_Status, + + /** Nothing is yet known about the resource. */ + kUnknown_Status, + + /** NOT A VALID VALUE -- used to set up arrays and to represent an unknown value. */ + kStatusCount + }; + static char const * const StatusNames[DiffResource::kStatusCount]; + + /** Returns the Status with this name. + * If there is no Status with this name, returns kStatusCount. + */ + static Status getStatusByName(const char *name); + + /** Returns a text description of the given Status type. */ + static const char *getStatusDescription(Status status); + + /** Returns true if the Status indicates some kind of failure. */ + static bool isStatusFailed(Status status); + + /** Sets statuses[i] if it is implied by selector, unsets it if not. + * Selector may be a comma delimited list of status names, "any", or "failed". + * Returns true if the selector was entirely understood, false otherwise. + */ + static bool getMatchingStatuses(char* selector, bool statuses[kStatusCount]); + + DiffResource() : fFilename(), fFullPath(), fBitmap(), fStatus(kUnknown_Status) { }; + + /** If isEmpty() indicates no filename available. */ + SkString fFilename; + /** If isEmpty() indicates no path available. */ + SkString fFullPath; + /** If empty() indicates the bitmap could not be created. */ + SkBitmap fBitmap; + Status fStatus; +}; + +struct DiffRecord { + + // Result of comparison for each pair of files. + // Listed from "better" to "worse", for sorting of results. + enum Result { + kEqualBits_Result, + kEqualPixels_Result, + kDifferentPixels_Result, + kDifferentSizes_Result, + kCouldNotCompare_Result, + kUnknown_Result, + + kResultCount // NOT A VALID VALUE--used to set up arrays. Must be last. + }; + static char const * const ResultNames[DiffRecord::kResultCount]; + + /** Returns the Result with this name. + * If there is no Result with this name, returns kResultCount. + */ + static Result getResultByName(const char *name); + + /** Returns a text description of the given Result type. */ + static const char *getResultDescription(Result result); + + DiffRecord() + : fBase() + , fComparison() + , fDifference() + , fWhite() + , fFractionDifference(0) + , fWeightedFraction(0) + , fAverageMismatchA(0) + , fAverageMismatchR(0) + , fAverageMismatchG(0) + , fAverageMismatchB(0) + , fTotalMismatchA(0) + , fMaxMismatchA(0) + , fMaxMismatchR(0) + , fMaxMismatchG(0) + , fMaxMismatchB(0) + , fResult(kUnknown_Result) { + }; + + DiffResource fBase; + DiffResource fComparison; + DiffResource fDifference; + DiffResource fWhite; + + /// Arbitrary floating-point metric to be used to sort images from most + /// to least different from baseline; values of 0 will be omitted from the + /// summary webpage. + float fFractionDifference; + float fWeightedFraction; + + float fAverageMismatchA; + float fAverageMismatchR; + float fAverageMismatchG; + float fAverageMismatchB; + + uint32_t fTotalMismatchA; + + uint32_t fMaxMismatchA; + uint32_t fMaxMismatchR; + uint32_t fMaxMismatchG; + uint32_t fMaxMismatchB; + + /// Which category of diff result. + Result fResult; +}; + +typedef SkTDArray<DiffRecord*> RecordArray; + +/// A wrapper for any sortProc (comparison routine) which applies a first-order +/// sort beforehand, and a tiebreaker if the sortProc returns 0. +template<typename T> static int compare(const void* untyped_lhs, const void* untyped_rhs) { + const DiffRecord* lhs = *reinterpret_cast<DiffRecord* const *>(untyped_lhs); + const DiffRecord* rhs = *reinterpret_cast<DiffRecord* const *>(untyped_rhs); + + // First-order sort... these comparisons should be applied before comparing + // pixel values, no matter what. + if (lhs->fResult != rhs->fResult) { + return (lhs->fResult < rhs->fResult) ? 1 : -1; + } + + // Passed first-order sort, so call the pixel comparison routine. + int result = T::comparePixels(lhs, rhs); + if (result != 0) { + return result; + } + + // Tiebreaker... if we got to this point, we don't really care + // which order they are sorted in, but let's at least be consistent. + return strcmp(lhs->fBase.fFilename.c_str(), rhs->fBase.fFilename.c_str()); +} + +/// Comparison routine for qsort; sorts by fFractionDifference +/// from largest to smallest. +class CompareDiffMetrics { +public: + static int comparePixels(const DiffRecord* lhs, const DiffRecord* rhs) { + if (lhs->fFractionDifference < rhs->fFractionDifference) { + return 1; + } + if (rhs->fFractionDifference < lhs->fFractionDifference) { + return -1; + } + return 0; + } +}; + +class CompareDiffWeighted { +public: + static int comparePixels(const DiffRecord* lhs, const DiffRecord* rhs) { + if (lhs->fWeightedFraction < rhs->fWeightedFraction) { + return 1; + } + if (lhs->fWeightedFraction > rhs->fWeightedFraction) { + return -1; + } + return 0; + } +}; + +/// Comparison routine for qsort; sorts by max(fAverageMismatch{RGB}) +/// from largest to smallest. +class CompareDiffMeanMismatches { +public: + static int comparePixels(const DiffRecord* lhs, const DiffRecord* rhs) { + float leftValue = MAX3(lhs->fAverageMismatchR, + lhs->fAverageMismatchG, + lhs->fAverageMismatchB); + float rightValue = MAX3(rhs->fAverageMismatchR, + rhs->fAverageMismatchG, + rhs->fAverageMismatchB); + if (leftValue < rightValue) { + return 1; + } + if (rightValue < leftValue) { + return -1; + } + return 0; + } +}; + +/// Comparison routine for qsort; sorts by max(fMaxMismatch{RGB}) +/// from largest to smallest. +class CompareDiffMaxMismatches { +public: + static int comparePixels(const DiffRecord* lhs, const DiffRecord* rhs) { + uint32_t leftValue = MAX3(lhs->fMaxMismatchR, + lhs->fMaxMismatchG, + lhs->fMaxMismatchB); + uint32_t rightValue = MAX3(rhs->fMaxMismatchR, + rhs->fMaxMismatchG, + rhs->fMaxMismatchB); + if (leftValue < rightValue) { + return 1; + } + if (rightValue < leftValue) { + return -1; + } + + return CompareDiffMeanMismatches::comparePixels(lhs, rhs); + } +}; + + +/// Parameterized routine to compute the color of a pixel in a difference image. +typedef SkPMColor (*DiffMetricProc)(SkPMColor, SkPMColor); + +// from gm +static inline SkPMColor compute_diff_pmcolor(SkPMColor c0, SkPMColor c1) { + int dr = SkGetPackedR32(c0) - SkGetPackedR32(c1); + int dg = SkGetPackedG32(c0) - SkGetPackedG32(c1); + int db = SkGetPackedB32(c0) - SkGetPackedB32(c1); + + return SkPackARGB32(0xFF, SkAbs32(dr), SkAbs32(dg), SkAbs32(db)); +} + +/** When finished, dr->fResult should have some value other than kUnknown_Result. + * Expects dr->fWhite.fBitmap and dr->fDifference.fBitmap to have the same bounds as + * dr->fBase.fBitmap and have a valid pixelref. + */ +void compute_diff(DiffRecord* dr, DiffMetricProc diffFunction, const int colorThreshold); + +#endif |