OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright 2016 Google Inc. | 2 * Copyright 2016 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "SkBitmap.h" | |
8 #include "SkCodec.h" | 9 #include "SkCodec.h" |
9 #include "SkCommandLineFlags.h" | 10 #include "SkCommandLineFlags.h" |
10 #include "SkData.h" | 11 #include "SkData.h" |
12 #include "SkJSONCPP.h" | |
11 #include "SkMD5.h" | 13 #include "SkMD5.h" |
12 #include "SkOSFile.h" | 14 #include "SkOSFile.h" |
13 #include "SkPicture.h" | 15 #include "SkPicture.h" |
14 #include "SkPixelSerializer.h" | 16 #include "SkPixelSerializer.h" |
15 #include "SkStream.h" | 17 #include "SkStream.h" |
16 #include "SkTHash.h" | 18 #include "SkTHash.h" |
17 | 19 |
20 | |
21 #include <map> | |
22 | |
18 DEFINE_string2(skps, s, "skps", "A path to a directory of skps."); | 23 DEFINE_string2(skps, s, "skps", "A path to a directory of skps."); |
19 DEFINE_string2(out, o, "img-out", "A path to an output directory."); | 24 DEFINE_string2(out, o, "img-out", "A path to an output directory."); |
25 DEFINE_bool(testDecode, false, "Indicates if we want to test that the images dec ode successfully."); | |
26 DEFINE_bool(writeImages, true, "Indicates if we want to write out images."); | |
27 DEFINE_string2(failuresJsonPath, j, "", | |
28 "Dump SKP and count of unknown images to the specified JSON file. Wll not be " | |
msarett
2016/04/25 15:29:53
nit: *Will
rmistry
2016/04/25 17:11:45
Oops. Done.
| |
29 "written anywhere if empty."); | |
20 | 30 |
21 static int gKnown; | 31 static int gKnown; |
22 static int gUnknown; | |
23 static const char* gOutputDir; | 32 static const char* gOutputDir; |
33 static std::map<std::string, unsigned int> gSkpToUnknownCount = {}; | |
24 | 34 |
25 static SkTHashSet<SkMD5::Digest> gSeen; | 35 static SkTHashSet<SkMD5::Digest> gSeen; |
26 | 36 |
27 struct Sniffer : public SkPixelSerializer { | 37 struct Sniffer : public SkPixelSerializer { |
28 | 38 |
39 std::string skpName; | |
40 | |
41 Sniffer(std::string name) { | |
42 skpName = name; | |
43 } | |
44 | |
29 void sniff(const void* ptr, size_t len) { | 45 void sniff(const void* ptr, size_t len) { |
30 SkMD5 md5; | 46 SkMD5 md5; |
31 md5.write(ptr, len); | 47 md5.write(ptr, len); |
32 SkMD5::Digest digest; | 48 SkMD5::Digest digest; |
33 md5.finish(digest); | 49 md5.finish(digest); |
34 | 50 |
35 if (gSeen.contains(digest)) { | 51 if (gSeen.contains(digest)) { |
36 return; | 52 return; |
37 } | 53 } |
38 gSeen.add(digest); | 54 gSeen.add(digest); |
39 | 55 |
40 SkAutoTUnref<SkData> data(SkData::NewWithoutCopy(ptr, len)); | 56 SkAutoTUnref<SkData> data(SkData::NewWithoutCopy(ptr, len)); |
41 SkAutoTDelete<SkCodec> codec(SkCodec::NewFromData(data)); | 57 SkAutoTDelete<SkCodec> codec(SkCodec::NewFromData(data)); |
42 if (!codec) { | 58 if (!codec) { |
43 gUnknown++; | 59 SkDebugf("Codec could not be created for %s\n", skpName.c_str()); |
msarett
2016/04/25 15:29:53
I believe this is unreachable... Looks like we cr
rmistry
2016/04/25 17:11:45
Done.
| |
60 gSkpToUnknownCount[skpName]++; | |
44 return; | 61 return; |
45 } | 62 } |
46 SkString ext; | 63 SkString ext; |
47 switch (codec->getEncodedFormat()) { | 64 switch (codec->getEncodedFormat()) { |
48 case SkEncodedFormat::kBMP_SkEncodedFormat: ext = "bmp"; break; | 65 case SkEncodedFormat::kBMP_SkEncodedFormat: ext = "bmp"; break; |
49 case SkEncodedFormat::kGIF_SkEncodedFormat: ext = "gif"; break; | 66 case SkEncodedFormat::kGIF_SkEncodedFormat: ext = "gif"; break; |
50 case SkEncodedFormat::kICO_SkEncodedFormat: ext = "ico"; break; | 67 case SkEncodedFormat::kICO_SkEncodedFormat: ext = "ico"; break; |
51 case SkEncodedFormat::kJPEG_SkEncodedFormat: ext = "jpg"; break; | 68 case SkEncodedFormat::kJPEG_SkEncodedFormat: ext = "jpg"; break; |
52 case SkEncodedFormat::kPNG_SkEncodedFormat: ext = "png"; break; | 69 case SkEncodedFormat::kPNG_SkEncodedFormat: ext = "png"; break; |
53 case SkEncodedFormat::kDNG_SkEncodedFormat: ext = "dng"; break; | 70 case SkEncodedFormat::kDNG_SkEncodedFormat: ext = "dng"; break; |
54 case SkEncodedFormat::kWBMP_SkEncodedFormat: ext = "wbmp"; break; | 71 case SkEncodedFormat::kWBMP_SkEncodedFormat: ext = "wbmp"; break; |
55 case SkEncodedFormat::kWEBP_SkEncodedFormat: ext = "webp"; break; | 72 case SkEncodedFormat::kWEBP_SkEncodedFormat: ext = "webp"; break; |
56 default: gUnknown++; return; | 73 default: |
74 SkDebugf("Unrecognized encoded format for %s\n", skpName.c_str() ); | |
msarett
2016/04/25 15:29:53
I think this is also unreachable - just because we
rmistry
2016/04/25 17:11:45
Done.
| |
75 gSkpToUnknownCount[skpName]++; | |
76 return; | |
57 } | 77 } |
58 | 78 |
59 SkString path; | 79 if (FLAGS_testDecode) { |
60 path.appendf("%s/%d.%s", gOutputDir, gKnown++, ext.c_str()); | 80 SkBitmap bitmap; |
81 SkImageInfo info = codec->getInfo().makeColorType(kN32_SkColorType); | |
82 bitmap.allocPixels(info); | |
83 if (SkCodec::kSuccess != codec->getPixels(info, bitmap.getPixels(), bitmap.rowBytes())) | |
msarett
2016/04/25 15:29:53
Our dm tests treat kSuccess and kIncompleteInput a
rmistry
2016/04/25 17:11:45
k, lets leave this in for now. I am guessing we wi
| |
84 { | |
85 SkDebugf("Decoding failed for %s\n", skpName.c_str()); | |
86 gSkpToUnknownCount[skpName]++; | |
87 return; | |
88 } | |
89 } | |
61 | 90 |
62 SkFILEWStream file(path.c_str()); | 91 if (FLAGS_writeImages) { |
63 file.write(ptr, len); | 92 SkString path; |
93 path.appendf("%s/%d.%s", gOutputDir, gKnown, ext.c_str()); | |
64 | 94 |
65 SkDebugf("%s\n", path.c_str()); | 95 SkFILEWStream file(path.c_str()); |
96 file.write(ptr, len); | |
97 | |
98 SkDebugf("%s\n", path.c_str()); | |
99 } | |
100 gKnown++; | |
66 } | 101 } |
67 | 102 |
68 bool onUseEncodedData(const void* ptr, size_t len) override { | 103 bool onUseEncodedData(const void* ptr, size_t len) override { |
69 this->sniff(ptr, len); | 104 this->sniff(ptr, len); |
70 return true; | 105 return true; |
71 } | 106 } |
72 SkData* onEncode(const SkPixmap&) override { return nullptr; } | 107 SkData* onEncode(const SkPixmap&) override { return nullptr; } |
73 }; | 108 }; |
74 | 109 |
75 | 110 |
76 int main(int argc, char** argv) { | 111 int main(int argc, char** argv) { |
77 SkCommandLineFlags::SetUsage( | 112 SkCommandLineFlags::SetUsage( |
78 "Usage: get_images_from_skps -s <dir of skps> -o <dir for output ima ges>\n"); | 113 "Usage: get_images_from_skps -s <dir of skps> -o <dir for output ima ges> --testDecode " |
114 "-j <output JSON path>\n"); | |
79 | 115 |
80 SkCommandLineFlags::Parse(argc, argv); | 116 SkCommandLineFlags::Parse(argc, argv); |
81 const char* inputs = FLAGS_skps[0]; | 117 const char* inputs = FLAGS_skps[0]; |
82 gOutputDir = FLAGS_out[0]; | 118 gOutputDir = FLAGS_out[0]; |
83 | 119 |
84 if (!sk_isdir(inputs) || !sk_isdir(gOutputDir)) { | 120 if (!sk_isdir(inputs) || !sk_isdir(gOutputDir)) { |
85 SkCommandLineFlags::PrintUsage(); | 121 SkCommandLineFlags::PrintUsage(); |
86 return 1; | 122 return 1; |
87 } | 123 } |
88 | 124 |
89 SkOSFile::Iter iter(inputs, "skp"); | 125 SkOSFile::Iter iter(inputs, "skp"); |
90 for (SkString file; iter.next(&file); ) { | 126 for (SkString file; iter.next(&file); ) { |
91 SkAutoTDelete<SkStream> stream = | 127 SkAutoTDelete<SkStream> stream = |
92 SkStream::NewFromFile(SkOSPath::Join(inputs, file.c_str()).c_str ()); | 128 SkStream::NewFromFile(SkOSPath::Join(inputs, file.c_str()).c_str ()); |
93 sk_sp<SkPicture> picture(SkPicture::MakeFromStream(stream)); | 129 sk_sp<SkPicture> picture(SkPicture::MakeFromStream(stream)); |
94 | 130 |
95 SkDynamicMemoryWStream scratch; | 131 SkDynamicMemoryWStream scratch; |
96 Sniffer sniff; | 132 Sniffer sniff(file.c_str()); |
97 picture->serialize(&scratch, &sniff); | 133 picture->serialize(&scratch, &sniff); |
98 } | 134 } |
99 SkDebugf("%d known, %d unknown\n", gKnown, gUnknown); | 135 int totalUnknowns = 0; |
136 /** | |
137 JSON results are written out in the following format: | |
138 { | |
139 "failures": { | |
140 "skp1": 12, | |
141 "skp4": 2, | |
142 ... | |
143 }, | |
144 "totalFailures": 32, | |
145 "totalSuccesses": 21, | |
146 } | |
147 */ | |
148 Json::Value fRoot; | |
149 for(auto it = gSkpToUnknownCount.cbegin(); it != gSkpToUnknownCount.cend(); ++it) | |
150 { | |
151 SkDebugf("%s %d\n", it->first.c_str(), it->second); | |
152 totalUnknowns += it->second; | |
153 fRoot["failures"][it->first.c_str()] = it->second; | |
154 } | |
155 SkDebugf("%d known, %d unknown\n", gKnown, totalUnknowns); | |
156 fRoot["totalFailures"] = totalUnknowns; | |
157 fRoot["totalSuccesses"] = gKnown; | |
158 if (totalUnknowns > 0 && !FLAGS_failuresJsonPath.isEmpty()) { | |
159 SkDebugf("Writing failures to %s\n", FLAGS_failuresJsonPath[0]); | |
160 SkFILEWStream stream(FLAGS_failuresJsonPath[0]); | |
161 stream.writeText(Json::StyledWriter().write(fRoot).c_str()); | |
162 stream.flush(); | |
163 } | |
100 | 164 |
101 return 0; | 165 return 0; |
102 } | 166 } |
OLD | NEW |