blob: 8f4789fea6556376dff5e3fdaa166ef5993064aa [file] [log] [blame]
/*
* Copyright 2013 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SkDiffContext_DEFINED
#define SkDiffContext_DEFINED
#include "SkImageDiffer.h"
#include "SkString.h"
#include "SkTArray.h"
#include "SkTDArray.h"
#include "SkTLList.h"
#include "SkThread.h"
class SkWStream;
/**
* Collects records of diffs and outputs them as JSON.
*/
class SkDiffContext {
public:
SkDiffContext();
~SkDiffContext();
void setThreadCount(int threadCount) { fThreadCount = threadCount; }
/**
* Sets the directory within which to store alphaMasks (images that
* are transparent for each pixel that differs between baseline and test).
*
* If the directory does not exist yet, it will be created.
*/
void setAlphaMaskDir(const SkString& directory);
/**
* Sets the directory within which to store rgbDiffs (images showing the
* per-channel difference between baseline and test at each pixel).
*
* If the directory does not exist yet, it will be created.
*/
void setRgbDiffDir(const SkString& directory);
/**
* Sets the directory within which to store whiteDiffs (images showing white
* for each pixel that differs between baseline and test).
*
* If the directory does not exist yet, it will be created.
*/
void setWhiteDiffDir(const SkString& directory);
/**
* Modify the pattern used to generate commonName (= the
* basename of rgb/white diff files).
*
* - true: basename is a combination of the input file names.
* - false: basename is the common prefix of the input file names.
*
* For example, for:
* baselinePath=/tmp/dir/image-before.png
* testPath=/tmp/dir/image-after.png
*
* If setLongNames(true), commonName would be:
* image-before-png-vs-image-after-png.png
*
* If setLongNames(false), commonName would be:
* image-.png
*/
void setLongNames(const bool useLongNames);
/**
* Sets the differs to be used in each diff. Already started diffs will not retroactively use
* these.
* @param differs An array of differs to use. The array is copied, but not the differs
* themselves.
*/
void setDiffers(const SkTDArray<SkImageDiffer*>& differs);
/**
* Compares two directories of images with the given differ
* @param baselinePath The baseline directory's path
* @param testPath The test directory's path
*/
void diffDirectories(const char baselinePath[], const char testPath[]);
/**
* Compares two sets of images identified by glob style patterns with the given differ
* @param baselinePattern A pattern for baseline files
* @param testPattern A pattern for test files that matches each file of the baseline file
*/
void diffPatterns(const char baselinePattern[], const char testPattern[]);
/**
* Compares the images at the given paths
* @param baselinePath The baseline file path
* @param testPath The matching test file path
*/
void addDiff(const char* baselinePath, const char* testPath);
/**
* Output the records of each diff in JSON.
*
* The format of the JSON document is one top level array named "records".
* Each record in the array is an object with the following values:
* "commonName" : string containing the output filename (basename)
* depending on the value of 'longNames'.
* (see 'setLongNames' for an explanation and example).
* "baselinePath" : string containing the path to the baseline image
* "testPath" : string containing the path to the test image
* "differencePath" : (optional) string containing the path to an alpha
* mask of the pixel difference between the baseline
* and test images
* TODO(epoger): consider renaming this "alphaMaskPath"
* to distinguish from other difference types?
* "rgbDiffPath" : (optional) string containing the path to a bitmap
* showing per-channel differences between the
* baseline and test images at each pixel
* "whiteDiffPath" : (optional) string containing the path to a bitmap
* showing every pixel that differs between the
* baseline and test images as white
*
* They also have an array named "diffs" with each element being one diff record for the two
* images indicated in the above field.
* A diff record includes:
* "differName" : string name of the diff metric used
* "result" : numerical result of the diff
*
* Here is an example:
*
* {
* "records": [
* {
* "commonName": "queue.png",
* "baselinePath": "/a/queue.png",
* "testPath": "/b/queue.png",
* "diffs": [
* {
* "differName": "different_pixels",
* "result": 1,
* }
* ]
* }
* ]
* }
*
* @param stream The stream to output the diff to
* @param useJSONP True to adding padding to the JSON output to make it cross-site requestable.
*/
void outputRecords(SkWStream& stream, bool useJSONP);
/**
* Output the records score in csv format.
*/
void outputCsv(SkWStream& stream);
private:
struct DiffData {
const char* fDiffName;
SkImageDiffer::Result fResult;
};
struct DiffRecord {
// TODO(djsollen): Some of these fields are required, while others are optional
// (e.g., fRgbDiffPath is only filled in if SkDifferentPixelsMetric
// was run). Figure out a way to note that. See http://skbug.com/2712
// ('allow skpdiff to report different sets of result fields for
// different comparison algorithms')
SkString fCommonName;
SkString fAlphaMaskPath;
SkString fRgbDiffPath;
SkString fWhiteDiffPath;
SkString fBaselinePath;
SkString fTestPath;
SkISize fSize;
int fMaxRedDiff;
int fMaxGreenDiff;
int fMaxBlueDiff;
SkTArray<DiffData> fDiffs;
};
// Used to protect access to fRecords and ensure only one thread is
// adding new entries at a time.
SkMutex fRecordMutex;
// We use linked list for the records so that their pointers remain stable. A resizable array
// might change its pointers, which would make it harder for async diffs to record their
// results.
SkTLList<DiffRecord> fRecords;
SkImageDiffer** fDiffers;
int fDifferCount;
int fThreadCount;
SkString fAlphaMaskDir;
SkString fRgbDiffDir;
SkString fWhiteDiffDir;
bool longNames;
};
#endif