Flutter Engine
The Flutter Engine
Functions
skdiff_utils.cpp File Reference
#include "include/codec/SkPngDecoder.h"
#include "include/core/SkBitmap.h"
#include "include/core/SkData.h"
#include "include/core/SkPixelRef.h"
#include "include/core/SkStream.h"
#include "include/core/SkTypes.h"
#include "include/encode/SkPngEncoder.h"
#include "tools/skdiff/skdiff.h"
#include "tools/skdiff/skdiff_utils.h"
#include <memory>

Go to the source code of this file.

Functions

bool are_buffers_equal (SkData *skdata1, SkData *skdata2)
 
sk_sp< SkDataread_file (const char *file_path)
 
bool get_bitmap (sk_sp< SkData > fileBits, DiffResource &resource, bool sizeOnly, bool ignoreColorSpace)
 
static void force_all_opaque (const SkBitmap &bitmap)
 
bool write_bitmap (const SkString &path, const SkBitmap &bitmap)
 
static SkString replace_all (const SkString &input, const char oldSubstring[], const char newSubstring[])
 
static SkString filename_to_derived_filename (const SkString &filename, const char *suffix)
 
SkString filename_to_diff_filename (const SkString &filename)
 
SkString filename_to_white_filename (const SkString &filename)
 
void create_and_write_diff_image (DiffRecord *drp, DiffMetricProc dmp, const int colorThreshold, const SkString &outputDir, const SkString &filename)
 

Function Documentation

◆ are_buffers_equal()

bool are_buffers_equal ( SkData skdata1,
SkData skdata2 
)

Returns true if the two buffers passed in are both non-nullptr, have the same length, and contain exactly the same byte values.

Definition at line 19 of file skdiff_utils.cpp.

19 {
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}
const void * data() const
Definition: SkData.h:37
size_t size() const
Definition: SkData.h:30

◆ create_and_write_diff_image()

void create_and_write_diff_image ( DiffRecord drp,
DiffMetricProc  dmp,
const int  colorThreshold,
const SkString outputDir,
const SkString filename 
)

Calls compute_diff and handles the difference and white diff resources. If !outputDir.isEmpty(), writes out difference and white images.

Definition at line 157 of file skdiff_utils.cpp.

161 {
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}
#define SkASSERT(cond)
Definition: SkAssert.h:116
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
bool isEmpty() const
Definition: SkString.h:130
void append(const char text[])
Definition: SkString.h:203
SkScalar w
SkScalar h
void compute_diff(DiffRecord *dr, DiffMetricProc diffFunction, const int colorThreshold)
Definition: skdiff.cpp:158
SkString filename_to_white_filename(const SkString &filename)
SkString filename_to_diff_filename(const SkString &filename)
bool write_bitmap(const SkString &path, const SkBitmap &bitmap)
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
@ kExists_Status
Definition: skdiff.h:42
@ kDoesNotExist_Status
Definition: skdiff.h:44
@ kSpecified_Status
Definition: skdiff.h:47
@ kUnspecified_Status
Definition: skdiff.h:49
Status fStatus
Definition: skdiff.h:84
SkString fFilename
Definition: skdiff.h:79

◆ filename_to_derived_filename()

static SkString filename_to_derived_filename ( const SkString filename,
const char *  suffix 
)
static

Definition at line 136 of file skdiff_utils.cpp.

136 {
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}
#define PATH_DIV_STR
Definition: skdiff.h:21
static SkString replace_all(const SkString &input, const char oldSubstring[], const char newSubstring[])

◆ filename_to_diff_filename()

SkString filename_to_diff_filename ( const SkString filename)

Given an image filename, returns the name of the file containing the associated difference image.

Definition at line 149 of file skdiff_utils.cpp.

149 {
150 return filename_to_derived_filename(filename, "-diff.png");
151}
static SkString filename_to_derived_filename(const SkString &filename, const char *suffix)

◆ filename_to_white_filename()

SkString filename_to_white_filename ( const SkString filename)

Given an image filename, returns the name of the file containing the "white" difference image.

Definition at line 153 of file skdiff_utils.cpp.

153 {
154 return filename_to_derived_filename(filename, "-white.png");
155}

◆ force_all_opaque()

static void force_all_opaque ( const SkBitmap bitmap)
static

Thanks to PNG, we need to force all pixels 100% opaque.

Definition at line 89 of file skdiff_utils.cpp.

89 {
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}
#define SK_A32_MASK
Definition: SkColorPriv.h:45
#define SK_A32_SHIFT
Definition: SkTypes.h:54
double y
double x
Definition: bitmap.py:1

◆ get_bitmap()

bool get_bitmap ( sk_sp< SkData fileBits,
DiffResource resource,
bool  sizeOnly,
bool  ignoreColorSpace 
)

Decodes the fileBits into the resource.fBitmap. Returns false on failure.

Definition at line 37 of file skdiff_utils.cpp.

38 {
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}
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
Definition: DM.cpp:213
void SK_SPI SkDebugf(const char format[],...) SK_PRINTF_LIKE(1
static SkString resource(SkPDFResourceType type, int index)
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()
const char * c_str() const
Definition: SkString.h:133
constexpr SkCodecs::Decoder Decoder()
Definition: SkPngDecoder.h:38
@ kCouldNotDecode_Status
Definition: skdiff.h:34
@ kDecoded_Status
Definition: skdiff.h:32

◆ read_file()

sk_sp< SkData > read_file ( const char *  file_path)

Reads the file at the given path and returns its complete contents as an SkData object (or returns nullptr on error).

Definition at line 29 of file skdiff_utils.cpp.

29 {
31 if (!data) {
32 SkDebugf("WARNING: could not open file <%s> for reading\n", file_path);
33 }
34 return data;
35}
static sk_sp< SkData > MakeFromFileName(const char path[])
Definition: SkData.cpp:148
std::shared_ptr< const fml::Mapping > data
Definition: texture_gles.cc:63

◆ replace_all()

static SkString replace_all ( const SkString input,
const char  oldSubstring[],
const char  newSubstring[] 
)
static

Return a copy of the "input" string, within which we have replaced all instances of oldSubstring with newSubstring.

TODO: If we like this, we should move it into the core SkString implementation, adding more checks and ample test cases, and paying more attention to efficiency.

Definition at line 120 of file skdiff_utils.cpp.

121 {
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}

◆ write_bitmap()

bool write_bitmap ( const SkString path,
const SkBitmap bitmap 
)

Writes the bitmap as a PNG to the path specified.

Definition at line 97 of file skdiff_utils.cpp.

97 {
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}
static void copy(void *dst, const uint8_t *src, int width, int bpp, int deltaSrc, int offset, const SkPMColor ctable[])
Definition: SkSwizzler.cpp:31
SK_API bool Encode(SkWStream *dst, const SkPixmap &src, const Options &options)
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
static void force_all_opaque(const SkBitmap &bitmap)