Flutter Engine
The Flutter Engine
skdiff_utils.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 */
14#include "tools/skdiff/skdiff.h"
16
17#include <memory>
18
19bool are_buffers_equal(SkData* skdata1, SkData* skdata2) {
20 if ((nullptr == skdata1) || (nullptr == skdata2)) {
21 return false;
22 }
23 if (skdata1->size() != skdata2->size()) {
24 return false;
25 }
26 return (0 == memcmp(skdata1->data(), skdata2->data(), skdata1->size()));
27}
28
29sk_sp<SkData> read_file(const char* file_path) {
31 if (!data) {
32 SkDebugf("WARNING: could not open file <%s> for reading\n", file_path);
33 }
34 return data;
35}
36
37bool get_bitmap(sk_sp<SkData> fileBits, DiffResource& resource, bool sizeOnly,
38 bool ignoreColorSpace) {
39 static constexpr const SkCodecs::Decoder decoders[] = {
41 };
42
43 auto codec = SkCodec::MakeFromData(std::move(fileBits), decoders);
44 if (!codec) {
45 SkDebugf("ERROR: could not create codec for <%s>\n", resource.fFullPath.c_str());
47 return false;
48 }
49
50 // If we're "ignoring" color space, then we want the raw pixel values from each image, so we
51 // decode to the original color space. If we want to account for color spaces, then we want to
52 // decode each image to the same color space, so that colors that are the "same" (but encoded
53 // differently) are transformed to some canonical representation prior to comparison.
54 //
55 // TODO: Use something wider than sRGB to avoid clipping with out-of-gamut colors.
56 SkImageInfo info = codec->getInfo().makeColorType(kN32_SkColorType);
57 if (!ignoreColorSpace) {
58 info = info.makeColorSpace(SkColorSpace::MakeSRGB());
59 }
60
61 if (!resource.fBitmap.setInfo(info.makeColorType(kN32_SkColorType))) {
62 SkDebugf("ERROR: could not set bitmap info for <%s>\n", resource.fFullPath.c_str());
64 return false;
65 }
66
67 if (sizeOnly) {
68 return true;
69 }
70
71 if (!resource.fBitmap.tryAllocPixels()) {
72 SkDebugf("ERROR: could not allocate pixels for <%s>\n", resource.fFullPath.c_str());
74 return false;
75 }
76
77 if (SkCodec::kSuccess != codec->getPixels(resource.fBitmap.info(),
78 resource.fBitmap.getPixels(), resource.fBitmap.rowBytes())) {
79 SkDebugf("ERROR: codec failed for basePath <%s>\n", resource.fFullPath.c_str());
81 return false;
82 }
83
85 return true;
86}
87
88/** Thanks to PNG, we need to force all pixels 100% opaque. */
89static void force_all_opaque(const SkBitmap& bitmap) {
90 for (int y = 0; y < bitmap.height(); y++) {
91 for (int x = 0; x < bitmap.width(); x++) {
92 *bitmap.getAddr32(x, y) |= (SK_A32_MASK << SK_A32_SHIFT);
93 }
94 }
95}
96
99 if (!copy.tryAllocPixels(bitmap.info().makeColorType(kN32_SkColorType))) {
100 return false;
101 }
102 if (!bitmap.readPixels(copy.pixmap())) {
103 return false;
104 }
106
107 SkFILEWStream file(path.c_str());
108 if (!file.isValid()) {
109 return false;
110 }
111
112 return SkPngEncoder::Encode(&file, copy.pixmap(), {});
113}
114
115/// Return a copy of the "input" string, within which we have replaced all instances
116/// of oldSubstring with newSubstring.
117///
118/// TODO: If we like this, we should move it into the core SkString implementation,
119/// adding more checks and ample test cases, and paying more attention to efficiency.
120static SkString replace_all(const SkString &input,
121 const char oldSubstring[], const char newSubstring[]) {
123 const char *input_cstr = input.c_str();
124 const char *first_char = input_cstr;
125 const char *match_char;
126 size_t oldSubstringLen = strlen(oldSubstring);
127 while ((match_char = strstr(first_char, oldSubstring))) {
128 output.append(first_char, (match_char - first_char));
129 output.append(newSubstring);
130 first_char = match_char + oldSubstringLen;
131 }
132 output.append(first_char);
133 return output;
134}
135
136static SkString filename_to_derived_filename(const SkString& filename, const char *suffix) {
137 SkString diffName (filename);
138 const char* cstring = diffName.c_str();
139 size_t dotOffset = strrchr(cstring, '.') - cstring;
140 diffName.remove(dotOffset, diffName.size() - dotOffset);
141 diffName.append(suffix);
142
143 // In case we recursed into subdirectories, replace slashes with something else
144 // so the diffs will all be written into a single flat directory.
145 diffName = replace_all(diffName, PATH_DIV_STR, "_");
146 return diffName;
147}
148
150 return filename_to_derived_filename(filename, "-diff.png");
151}
152
154 return filename_to_derived_filename(filename, "-white.png");
155}
156
158 DiffMetricProc dmp,
159 const int colorThreshold,
160 const SkString& outputDir,
161 const SkString& filename) {
162 const int w = drp->fBase.fBitmap.width();
163 const int h = drp->fBase.fBitmap.height();
164
165 if (w != drp->fComparison.fBitmap.width() || h != drp->fComparison.fBitmap.height()) {
167 } else {
169
171
173 compute_diff(drp, dmp, colorThreshold);
175 }
176
177 if (outputDir.isEmpty()) {
180
181 } else {
183 drp->fDifference.fFullPath = outputDir;
186
188 drp->fWhite.fFullPath = outputDir;
191
195 } else {
197 }
198 if (write_bitmap(drp->fWhite.fFullPath, drp->fWhite.fBitmap)) {
200 } else {
202 }
203 }
204 }
205}
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
Definition: DM.cpp:213
#define SkASSERT(cond)
Definition: SkAssert.h:116
#define SK_A32_MASK
Definition: SkColorPriv.h:45
void SK_SPI SkDebugf(const char format[],...) SK_PRINTF_LIKE(1
static SkString resource(SkPDFResourceType type, int index)
static void copy(void *dst, const uint8_t *src, int width, int bpp, int deltaSrc, int offset, const SkPMColor ctable[])
Definition: SkSwizzler.cpp:31
#define SK_A32_SHIFT
Definition: SkTypes.h:54
int width() const
Definition: SkBitmap.h:149
void allocN32Pixels(int width, int height, bool isOpaque=false)
Definition: SkBitmap.cpp:232
int height() const
Definition: SkBitmap.h:158
static std::unique_ptr< SkCodec > MakeFromData(sk_sp< SkData >, SkSpan< const SkCodecs::Decoder > decoders, SkPngChunkReader *=nullptr)
Definition: SkCodec.cpp:241
@ kSuccess
Definition: SkCodec.h:80
static sk_sp< SkColorSpace > MakeSRGB()
Definition: SkData.h:25
const void * data() const
Definition: SkData.h:37
static sk_sp< SkData > MakeFromFileName(const char path[])
Definition: SkData.cpp:148
size_t size() const
Definition: SkData.h:30
void void void void void void void remove(size_t offset, size_t length)
Definition: SkString.cpp:592
size_t size() const
Definition: SkString.h:131
bool isEmpty() const
Definition: SkString.h:130
void append(const char text[])
Definition: SkString.h:203
const char * c_str() const
Definition: SkString.h:133
double y
double x
constexpr SkCodecs::Decoder Decoder()
Definition: SkPngDecoder.h:38
SK_API bool Encode(SkWStream *dst, const SkPixmap &src, const Options &options)
Definition: bitmap.py:1
Definition: copy.py:1
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir path
Definition: switches.h:57
SkScalar w
SkScalar h
void compute_diff(DiffRecord *dr, DiffMetricProc diffFunction, const int colorThreshold)
Definition: skdiff.cpp:158
SkPMColor(* DiffMetricProc)(SkPMColor, SkPMColor)
Parameterized routine to compute the color of a pixel in a difference image.
Definition: skdiff.h:255
#define PATH_DIV_STR
Definition: skdiff.h:21
SkString filename_to_white_filename(const SkString &filename)
static SkString replace_all(const SkString &input, const char oldSubstring[], const char newSubstring[])
static void force_all_opaque(const SkBitmap &bitmap)
bool are_buffers_equal(SkData *skdata1, SkData *skdata2)
static SkString filename_to_derived_filename(const SkString &filename, const char *suffix)
void create_and_write_diff_image(DiffRecord *drp, DiffMetricProc dmp, const int colorThreshold, const SkString &outputDir, const SkString &filename)
SkString filename_to_diff_filename(const SkString &filename)
sk_sp< SkData > read_file(const char *file_path)
bool write_bitmap(const SkString &path, const SkBitmap &bitmap)
bool get_bitmap(sk_sp< SkData > fileBits, DiffResource &resource, bool sizeOnly, bool ignoreColorSpace)
DiffResource fDifference
Definition: skdiff.h:132
DiffResource fComparison
Definition: skdiff.h:131
Result fResult
Which category of diff result.
Definition: skdiff.h:154
@ kUnknown_Result
Definition: skdiff.h:97
@ kDifferentSizes_Result
Definition: skdiff.h:95
@ kDifferentPixels_Result
Definition: skdiff.h:94
DiffResource fBase
Definition: skdiff.h:130
DiffResource fWhite
Definition: skdiff.h:133
SkString fFullPath
Definition: skdiff.h:81
SkBitmap fBitmap
Definition: skdiff.h:83
@ kCouldNotDecode_Status
Definition: skdiff.h:34
@ kExists_Status
Definition: skdiff.h:42
@ kDoesNotExist_Status
Definition: skdiff.h:44
@ kSpecified_Status
Definition: skdiff.h:47
@ kDecoded_Status
Definition: skdiff.h:32
@ kUnspecified_Status
Definition: skdiff.h:49
Status fStatus
Definition: skdiff.h:84
SkString fFilename
Definition: skdiff.h:79
std::shared_ptr< const fml::Mapping > data
Definition: texture_gles.cc:63