| 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;
|
| }
|
|
|