|  | /* | 
|  | * 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 "bench/Benchmark.h" | 
|  | #include "include/core/SkBitmap.h" | 
|  | #include "include/core/SkStream.h" | 
|  | #include "include/encode/SkJpegEncoder.h" | 
|  | #include "include/encode/SkPngEncoder.h" | 
|  | #include "include/encode/SkWebpEncoder.h" | 
|  | #include "tools/Resources.h" | 
|  |  | 
|  | // Like other Benchmark subclasses, Encoder benchmarks are run by: | 
|  | // nanobench --match ^Encode_ | 
|  | // | 
|  | // There is no corresponding DecodeBench class. Decoder benchmarks are run by: | 
|  | // nanobench --benchType skcodec --images your_images_directory | 
|  |  | 
|  | 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 onDelayedSetup() 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 |