Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
get_images_from_skps.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2016 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 */
7
12#include "include/core/SkData.h"
17#include "src/core/SkMD5.h"
18#include "src/core/SkOSFile.h"
19#include "src/core/SkTHash.h"
21#include "src/utils/SkOSPath.h"
23
24#include <iostream>
25#include <map>
26
27using namespace skia_private;
28
29static DEFINE_string2(skps, s, "skps", "A path to a directory of skps or a single skp.");
30static DEFINE_string2(out, o, "img-out", "A path to an output directory.");
31static DEFINE_bool(testDecode, false,
32 "Indicates if we want to test that the images decode successfully.");
33static DEFINE_bool(writeImages, true,
34 "Indicates if we want to write out supported/decoded images.");
35static DEFINE_bool(writeFailedImages, false,
36 "Indicates if we want to write out unsupported/failed to decode images.");
37static DEFINE_string2(failuresJsonPath, j, "",
38 "Dump SKP and count of unknown images to the specified JSON file. Will not be "
39 "written anywhere if empty.");
40
41static int gKnown;
42static const char* gOutputDir;
43static std::map<std::string, unsigned int> gSkpToUnknownCount = {};
44static std::map<std::string, unsigned int> gSkpToUnsupportedCount;
45
47
48struct Sniffer {
49
50 std::string skpName;
51
52 Sniffer(std::string name) {
53 skpName = name;
54 }
55
56 void sniff(const void* ptr, size_t len) {
57 SkMD5 md5;
58 md5.write(ptr, len);
59 SkMD5::Digest digest = md5.finish();
60
61 if (gSeen.contains(digest)) {
62 return;
63 }
64 gSeen.add(digest);
65
67 std::unique_ptr<SkCodec> codec = SkCodec::MakeFromData(data);
68 if (!codec) {
69 // FIXME: This code is currently unreachable because we create an empty generator when
70 // we fail to create a codec.
71 SkDebugf("Codec could not be created for %s\n", skpName.c_str());
73 return;
74 }
75 SkString ext;
76 switch (codec->getEncodedFormat()) {
77 case SkEncodedImageFormat::kBMP: ext = "bmp"; break;
78 case SkEncodedImageFormat::kGIF: ext = "gif"; break;
79 case SkEncodedImageFormat::kICO: ext = "ico"; break;
80 case SkEncodedImageFormat::kJPEG: ext = "jpg"; break;
81 case SkEncodedImageFormat::kPNG: ext = "png"; break;
82 case SkEncodedImageFormat::kDNG: ext = "dng"; break;
83 case SkEncodedImageFormat::kWBMP: ext = "wbmp"; break;
84 case SkEncodedImageFormat::kWEBP: ext = "webp"; break;
85 default:
86 // This should be unreachable because we cannot create a codec if we do not know
87 // the image type.
88 SkASSERT(false);
89 }
90
91 auto writeImage = [&] (const char* name, int num) {
92 SkString path;
93 path.appendf("%s/%s%d.%s", gOutputDir, name, num, ext.c_str());
94
95 SkFILEWStream file(path.c_str());
96 file.write(ptr, len);
97
98 SkDebugf("%s\n", path.c_str());
99 };
100
101 if (FLAGS_testDecode) {
103 SkImageInfo info = codec->getInfo().makeColorType(kN32_SkColorType);
104 bitmap.allocPixels(info);
105 const SkCodec::Result result = codec->getPixels(
106 info, bitmap.getPixels(), bitmap.rowBytes());
107 switch (result) {
111 break;
112 default:
113 SkDebugf("Decoding failed for %s\n", skpName.c_str());
114 if (FLAGS_writeFailedImages) {
115 writeImage("unknown", gSkpToUnknownCount[skpName]);
116 }
118 return;
119 }
120 }
121
122 if (FLAGS_writeImages) {
123 writeImage("", gKnown);
124 }
125
126 gKnown++;
127 }
128};
129
130static bool get_images_from_file(const SkString& file) {
131 Sniffer sniff(file.c_str());
132 auto stream = SkStream::MakeFromFile(file.c_str());
133
134 SkDeserialProcs procs;
135 procs.fImageProc = [](const void* data, size_t size, void* ctx) -> sk_sp<SkImage> {
136 ((Sniffer*)ctx)->sniff(data, size);
137 return nullptr;
138 };
139 procs.fImageCtx = &sniff;
140 return SkPicture::MakeFromStream(stream.get(), &procs) != nullptr;
141}
142
143int main(int argc, char** argv) {
145 "Usage: get_images_from_skps -s <dir of skps> -o <dir for output images> --testDecode "
146 "-j <output JSON path> --writeImages, --writeFailedImages\n");
147
149 const char* inputs = FLAGS_skps[0];
150 gOutputDir = FLAGS_out[0];
151
152 if (!sk_isdir(gOutputDir)) {
154 return 1;
155 }
156
157 if (sk_isdir(inputs)) {
158 SkOSFile::Iter iter(inputs, "skp");
159 for (SkString file; iter.next(&file); ) {
160 if (!get_images_from_file(SkOSPath::Join(inputs, file.c_str()))) {
161 return 2;
162 }
163 }
164 } else {
165 if (!get_images_from_file(SkString(inputs))) {
166 return 2;
167 }
168 }
169 /**
170 JSON results are written out in the following format:
171 {
172 "failures": {
173 "skp1": 12,
174 "skp4": 2,
175 ...
176 },
177 "unsupported": {
178 "skp9": 13,
179 "skp17": 3,
180 ...
181 }
182 "totalFailures": 32,
183 "totalUnsupported": 9,
184 "totalSuccesses": 21,
185 }
186 */
187
188 unsigned int totalFailures = 0,
189 totalUnsupported = 0;
190 SkDynamicMemoryWStream memStream;
191 SkJSONWriter writer(&memStream, SkJSONWriter::Mode::kPretty);
192 writer.beginObject();
193 {
194 writer.beginObject("failures");
195 {
196 for (const auto& failure : gSkpToUnknownCount) {
197 SkDebugf("%s %u\n", failure.first.c_str(), failure.second);
198 totalFailures += failure.second;
199 writer.appendU32(failure.first.c_str(), failure.second);
200 }
201 }
202 writer.endObject();
203 writer.appendU32("totalFailures", totalFailures);
204
205#ifdef SK_DEBUG
206 writer.beginObject("unsupported");
207 {
208 for (const auto& unsupported : gSkpToUnsupportedCount) {
209 SkDebugf("%s %u\n", unsupported.first.c_str(), unsupported.second);
210 totalUnsupported += unsupported.second;
211 writer.appendHexU32(unsupported.first.c_str(), unsupported.second);
212 }
213 }
214 writer.endObject();
215 writer.appendU32("totalUnsupported", totalUnsupported);
216#endif
217
218 writer.appendS32("totalSuccesses", gKnown);
219 SkDebugf("%d known, %u failures, %u unsupported\n",
220 gKnown, totalFailures, totalUnsupported);
221 }
222 writer.endObject();
223 writer.flush();
224
225 if (totalFailures > 0 || totalUnsupported > 0) {
226 if (!FLAGS_failuresJsonPath.isEmpty()) {
227 SkDebugf("Writing failures to %s\n", FLAGS_failuresJsonPath[0]);
228 SkFILEWStream stream(FLAGS_failuresJsonPath[0]);
229 auto jsonStream = memStream.detachAsStream();
230 stream.writeStream(jsonStream.get(), jsonStream->getLength());
231 }
232 }
233
234 return 0;
235}
static SkMD5::Digest md5(const SkBitmap &bm)
Definition CodecTest.cpp:77
#define DEFINE_bool(name, defaultValue, helpString)
#define DEFINE_string2(name, shortName, defaultValue, helpString)
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
Definition DM.cpp:213
#define SkASSERT(cond)
Definition SkAssert.h:116
void SK_SPI SkDebugf(const char format[],...) SK_PRINTF_LIKE(1
bool sk_isdir(const char *path)
static void PrintUsage()
static void Parse(int argc, const char *const *argv)
static void SetUsage(const char *usage)
static std::unique_ptr< SkCodec > MakeFromData(sk_sp< SkData >, SkSpan< const SkCodecs::Decoder > decoders, SkPngChunkReader *=nullptr)
Definition SkCodec.cpp:241
@ kIncompleteInput
Definition SkCodec.h:84
@ kSuccess
Definition SkCodec.h:80
@ kErrorInInput
Definition SkCodec.h:91
static sk_sp< SkData > MakeWithoutCopy(const void *data, size_t length)
Definition SkData.h:116
std::unique_ptr< SkStreamAsset > detachAsStream()
Definition SkStream.cpp:876
void appendS32(int32_t value)
void appendU32(uint32_t value)
void beginObject(const char *name=nullptr, bool multiline=true)
void appendHexU32(uint32_t value)
Definition SkMD5.h:19
SK_SPI bool next(SkString *name, bool getDir=false)
static SkString Join(const char *rootPath, const char *relativePath)
Definition SkOSPath.cpp:14
static sk_sp< SkPicture > MakeFromStream(SkStream *stream, const SkDeserialProcs *procs=nullptr)
static std::unique_ptr< SkStreamAsset > MakeFromFile(const char path[])
Definition SkStream.cpp:922
struct MyStruct s
GAsyncResult * result
const char * name
Definition fuchsia.cc:50
static bool get_images_from_file(const SkString &file)
static std::map< std::string, unsigned int > gSkpToUnsupportedCount
static std::map< std::string, unsigned int > gSkpToUnknownCount
static int gKnown
static THashSet< SkMD5::Digest > gSeen
static const char * gOutputDir
char ** argv
Definition library.h:9
Definition main.py:1
SkDeserialImageProc fImageProc
SkImageInfo makeColorType(SkColorType newColorType) const
Sniffer(std::string name)
std::string skpName
void sniff(const void *ptr, size_t len)