Index: tools/get_images_from_skps.cpp |
diff --git a/tools/get_images_from_skps.cpp b/tools/get_images_from_skps.cpp |
index e6bb6e2012190698ebda8359826f7d36be275861..f963b9a86b59bd08d8d6a04afe27e2de824df30f 100644 |
--- a/tools/get_images_from_skps.cpp |
+++ b/tools/get_images_from_skps.cpp |
@@ -5,9 +5,11 @@ |
* found in the LICENSE file. |
*/ |
+#include "SkBitmap.h" |
#include "SkCodec.h" |
#include "SkCommandLineFlags.h" |
#include "SkData.h" |
+#include "SkJSONCPP.h" |
#include "SkMD5.h" |
#include "SkOSFile.h" |
#include "SkPicture.h" |
@@ -15,17 +17,31 @@ |
#include "SkStream.h" |
#include "SkTHash.h" |
+ |
+#include <map> |
+ |
DEFINE_string2(skps, s, "skps", "A path to a directory of skps."); |
DEFINE_string2(out, o, "img-out", "A path to an output directory."); |
+DEFINE_bool(testDecode, false, "Indicates if we want to test that the images decode successfully."); |
+DEFINE_bool(writeImages, true, "Indicates if we want to write out images."); |
+DEFINE_string2(failuresJsonPath, j, "", |
+ "Dump SKP and count of unknown images to the specified JSON file. Will not be " |
+ "written anywhere if empty."); |
static int gKnown; |
-static int gUnknown; |
static const char* gOutputDir; |
+static std::map<std::string, unsigned int> gSkpToUnknownCount = {}; |
static SkTHashSet<SkMD5::Digest> gSeen; |
struct Sniffer : public SkPixelSerializer { |
+ std::string skpName; |
+ |
+ Sniffer(std::string name) { |
+ skpName = name; |
+ } |
+ |
void sniff(const void* ptr, size_t len) { |
SkMD5 md5; |
md5.write(ptr, len); |
@@ -40,7 +56,10 @@ struct Sniffer : public SkPixelSerializer { |
SkAutoTUnref<SkData> data(SkData::NewWithoutCopy(ptr, len)); |
SkAutoTDelete<SkCodec> codec(SkCodec::NewFromData(data)); |
if (!codec) { |
- gUnknown++; |
+ // FIXME: This code is currently unreachable because we create an empty generator when |
+ // we fail to create a codec. |
+ SkDebugf("Codec could not be created for %s\n", skpName.c_str()); |
+ gSkpToUnknownCount[skpName]++; |
return; |
} |
SkString ext; |
@@ -53,16 +72,34 @@ struct Sniffer : public SkPixelSerializer { |
case SkEncodedFormat::kDNG_SkEncodedFormat: ext = "dng"; break; |
case SkEncodedFormat::kWBMP_SkEncodedFormat: ext = "wbmp"; break; |
case SkEncodedFormat::kWEBP_SkEncodedFormat: ext = "webp"; break; |
- default: gUnknown++; return; |
+ default: |
+ // This should be unreachable because we cannot create a codec if we do not know |
+ // the image type. |
+ SkASSERT(false); |
} |
- SkString path; |
- path.appendf("%s/%d.%s", gOutputDir, gKnown++, ext.c_str()); |
+ if (FLAGS_testDecode) { |
+ SkBitmap bitmap; |
+ SkImageInfo info = codec->getInfo().makeColorType(kN32_SkColorType); |
+ bitmap.allocPixels(info); |
+ if (SkCodec::kSuccess != codec->getPixels(info, bitmap.getPixels(), bitmap.rowBytes())) |
+ { |
+ SkDebugf("Decoding failed for %s\n", skpName.c_str()); |
+ gSkpToUnknownCount[skpName]++; |
+ return; |
+ } |
+ } |
+ |
+ if (FLAGS_writeImages) { |
+ SkString path; |
+ path.appendf("%s/%d.%s", gOutputDir, gKnown, ext.c_str()); |
- SkFILEWStream file(path.c_str()); |
- file.write(ptr, len); |
+ SkFILEWStream file(path.c_str()); |
+ file.write(ptr, len); |
- SkDebugf("%s\n", path.c_str()); |
+ SkDebugf("%s\n", path.c_str()); |
+ } |
+ gKnown++; |
} |
bool onUseEncodedData(const void* ptr, size_t len) override { |
@@ -75,7 +112,8 @@ struct Sniffer : public SkPixelSerializer { |
int main(int argc, char** argv) { |
SkCommandLineFlags::SetUsage( |
- "Usage: get_images_from_skps -s <dir of skps> -o <dir for output images>\n"); |
+ "Usage: get_images_from_skps -s <dir of skps> -o <dir for output images> --testDecode " |
+ "-j <output JSON path>\n"); |
SkCommandLineFlags::Parse(argc, argv); |
const char* inputs = FLAGS_skps[0]; |
@@ -93,10 +131,38 @@ int main(int argc, char** argv) { |
sk_sp<SkPicture> picture(SkPicture::MakeFromStream(stream)); |
SkDynamicMemoryWStream scratch; |
- Sniffer sniff; |
+ Sniffer sniff(file.c_str()); |
picture->serialize(&scratch, &sniff); |
} |
- SkDebugf("%d known, %d unknown\n", gKnown, gUnknown); |
+ int totalUnknowns = 0; |
+ /** |
+ JSON results are written out in the following format: |
+ { |
+ "failures": { |
+ "skp1": 12, |
+ "skp4": 2, |
+ ... |
+ }, |
+ "totalFailures": 32, |
+ "totalSuccesses": 21, |
+ } |
+ */ |
+ Json::Value fRoot; |
+ for(auto it = gSkpToUnknownCount.cbegin(); it != gSkpToUnknownCount.cend(); ++it) |
+ { |
+ SkDebugf("%s %d\n", it->first.c_str(), it->second); |
+ totalUnknowns += it->second; |
+ fRoot["failures"][it->first.c_str()] = it->second; |
+ } |
+ SkDebugf("%d known, %d unknown\n", gKnown, totalUnknowns); |
+ fRoot["totalFailures"] = totalUnknowns; |
+ fRoot["totalSuccesses"] = gKnown; |
+ if (totalUnknowns > 0 && !FLAGS_failuresJsonPath.isEmpty()) { |
+ SkDebugf("Writing failures to %s\n", FLAGS_failuresJsonPath[0]); |
+ SkFILEWStream stream(FLAGS_failuresJsonPath[0]); |
+ stream.writeText(Json::StyledWriter().write(fRoot).c_str()); |
+ stream.flush(); |
+ } |
return 0; |
} |