aboutsummaryrefslogtreecommitdiffhomepage
path: root/tools/skpdiff/SkDiffContext.h
blob: 8f4789fea6556376dff5e3fdaa166ef5993064aa (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
/*
 * 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