/* * Copyright 2016 Google Inc. * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "Benchmark.h" #include "Resources.h" #include "SkBitmap.h" #include "SkJpegEncoder.h" #include "SkPngEncoder.h" #include "SkWebpEncoder.h" #include "SkStream.h" class EncodeBench : public Benchmark { public: using Encoder = bool (*)(SkWStream*, const SkPixmap&); EncodeBench(const char* filename, Encoder encoder, const char* encoderName) : fSourceFilename(filename) , fEncoder(encoder) , fName(SkStringPrintf("Encode_%s_%s", filename, encoderName)) {} bool isSuitableFor(Backend backend) override { return backend == kNonRendering_Backend; } const char* onGetName() override { return fName.c_str(); } void onPreDraw(SkCanvas*) override { SkAssertResult(GetResourceAsBitmap(fSourceFilename, &fBitmap)); } void onDraw(int loops, SkCanvas*) override { while (loops-- > 0) { SkPixmap pixmap; SkAssertResult(fBitmap.peekPixels(&pixmap)); SkNullWStream dst; SkAssertResult(fEncoder(&dst, pixmap)); SkASSERT(dst.bytesWritten() > 0); } } private: const char* fSourceFilename; Encoder fEncoder; SkString fName; SkBitmap fBitmap; }; static bool encode_jpeg(SkWStream* dst, const SkPixmap& src) { SkJpegEncoder::Options opts; opts.fQuality = 90; return SkJpegEncoder::Encode(dst, src, opts); } static bool encode_webp_lossy(SkWStream* dst, const SkPixmap& src) { SkWebpEncoder::Options opts; opts.fCompression = SkWebpEncoder::Compression::kLossy; opts.fQuality = 90; return SkWebpEncoder::Encode(dst, src, opts); } static bool encode_webp_lossless(SkWStream* dst, const SkPixmap& src) { SkWebpEncoder::Options opts; opts.fCompression = SkWebpEncoder::Compression::kLossless; opts.fQuality = 90; return SkWebpEncoder::Encode(dst, src, opts); } static bool encode_png(SkWStream* dst, const SkPixmap& src, SkPngEncoder::FilterFlag filters, int zlibLevel) { SkPngEncoder::Options opts; opts.fFilterFlags = filters; opts.fZLibLevel = zlibLevel; return SkPngEncoder::Encode(dst, src, opts); } #define PNG(FLAG, ZLIBLEVEL) [](SkWStream* d, const SkPixmap& s) { \ return encode_png(d, s, SkPngEncoder::FilterFlag::FLAG, ZLIBLEVEL); } static const char* srcs[2] = {"images/mandrill_512.png", "images/color_wheel.jpg"}; // The Android Photos app uses a quality of 90 on JPEG encodes DEF_BENCH(return new EncodeBench(srcs[0], &encode_jpeg, "JPEG")); DEF_BENCH(return new EncodeBench(srcs[1], &encode_jpeg, "JPEG")); // TODO: What is the appropriate quality to use to benchmark WEBP encodes? DEF_BENCH(return new EncodeBench(srcs[0], encode_webp_lossy, "WEBP")); DEF_BENCH(return new EncodeBench(srcs[1], encode_webp_lossy, "WEBP")); DEF_BENCH(return new EncodeBench(srcs[0], encode_webp_lossless, "WEBP_LL")); DEF_BENCH(return new EncodeBench(srcs[1], encode_webp_lossless, "WEBP_LL")); DEF_BENCH(return new EncodeBench(srcs[0], PNG(kAll, 6), "PNG")); DEF_BENCH(return new EncodeBench(srcs[0], PNG(kAll, 3), "PNG_3")); DEF_BENCH(return new EncodeBench(srcs[0], PNG(kAll, 1), "PNG_1")); DEF_BENCH(return new EncodeBench(srcs[0], PNG(kSub, 6), "PNG_6s")); DEF_BENCH(return new EncodeBench(srcs[0], PNG(kSub, 3), "PNG_3s")); DEF_BENCH(return new EncodeBench(srcs[0], PNG(kSub, 1), "PNG_1s")); DEF_BENCH(return new EncodeBench(srcs[0], PNG(kNone, 6), "PNG_6n")); DEF_BENCH(return new EncodeBench(srcs[0], PNG(kNone, 3), "PNG_3n")); DEF_BENCH(return new EncodeBench(srcs[0], PNG(kNone, 1), "PNG_1n")); DEF_BENCH(return new EncodeBench(srcs[1], PNG(kAll, 6), "PNG")); DEF_BENCH(return new EncodeBench(srcs[1], PNG(kAll, 3), "PNG_3")); DEF_BENCH(return new EncodeBench(srcs[1], PNG(kAll, 1), "PNG_1")); DEF_BENCH(return new EncodeBench(srcs[1], PNG(kSub, 6), "PNG_6s")); DEF_BENCH(return new EncodeBench(srcs[1], PNG(kSub, 3), "PNG_3s")); DEF_BENCH(return new EncodeBench(srcs[1], PNG(kSub, 1), "PNG_1s")); DEF_BENCH(return new EncodeBench(srcs[1], PNG(kNone, 6), "PNG_6n")); DEF_BENCH(return new EncodeBench(srcs[1], PNG(kNone, 3), "PNG_3n")); DEF_BENCH(return new EncodeBench(srcs[1], PNG(kNone, 1), "PNG_1n")); #undef PNG