1fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot/* 2fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Copyright 2016 Google Inc. 3fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * 4fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Use of this source code is governed by a BSD-style license that can be 5fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * found in the LICENSE file. 6fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot */ 7fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 8fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "Benchmark.h" 9fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "Resources.h" 10fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkBitmap.h" 11fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkJpegEncoder.h" 12fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkPngEncoder.h" 13fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkWebpEncoder.h" 14fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkStream.h" 15fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 16fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotclass EncodeBench : public Benchmark { 17fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotpublic: 18fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot using Encoder = bool (*)(SkWStream*, const SkPixmap&); 19fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot EncodeBench(const char* filename, Encoder encoder, const char* encoderName) 20fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot : fSourceFilename(filename) 21fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot , fEncoder(encoder) 22fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot , fName(SkStringPrintf("Encode_%s_%s", filename, encoderName)) {} 23fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 24fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool isSuitableFor(Backend backend) override { return backend == kNonRendering_Backend; } 25fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 26fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const char* onGetName() override { return fName.c_str(); } 27fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 28fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot void onPreDraw(SkCanvas*) override { 29fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkAssertResult(GetResourceAsBitmap(fSourceFilename, &fBitmap)); 30fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 31fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 32fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot void onDraw(int loops, SkCanvas*) override { 33fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot while (loops-- > 0) { 34fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkPixmap pixmap; 35fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkAssertResult(fBitmap.peekPixels(&pixmap)); 36fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkNullWStream dst; 37fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkAssertResult(fEncoder(&dst, pixmap)); 38fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(dst.bytesWritten() > 0); 39fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 40fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 41fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 42fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotprivate: 43fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const char* fSourceFilename; 44fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot Encoder fEncoder; 45fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkString fName; 46fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkBitmap fBitmap; 47fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}; 48fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 49fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic bool encode_jpeg(SkWStream* dst, const SkPixmap& src) { 50fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkJpegEncoder::Options opts; 51fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot opts.fQuality = 90; 52fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return SkJpegEncoder::Encode(dst, src, opts); 53fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 54fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 55fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic bool encode_webp_lossy(SkWStream* dst, const SkPixmap& src) { 56fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkWebpEncoder::Options opts; 57fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot opts.fCompression = SkWebpEncoder::Compression::kLossy; 58fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot opts.fQuality = 90; 59fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot opts.fUnpremulBehavior = SkTransferFunctionBehavior::kIgnore; 60fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return SkWebpEncoder::Encode(dst, src, opts); 61fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 62fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 63fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic bool encode_webp_lossless(SkWStream* dst, const SkPixmap& src) { 64fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkWebpEncoder::Options opts; 65fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot opts.fCompression = SkWebpEncoder::Compression::kLossless; 66fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot opts.fQuality = 90; 67fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot opts.fUnpremulBehavior = SkTransferFunctionBehavior::kIgnore; 68fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return SkWebpEncoder::Encode(dst, src, opts); 69fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 70fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 71fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic bool encode_png(SkWStream* dst, 72fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkPixmap& src, 73fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkPngEncoder::FilterFlag filters, 74fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int zlibLevel) { 75fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkPngEncoder::Options opts; 76fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot opts.fFilterFlags = filters; 77fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot opts.fUnpremulBehavior = SkTransferFunctionBehavior::kIgnore; 78fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot opts.fZLibLevel = zlibLevel; 79fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return SkPngEncoder::Encode(dst, src, opts); 80fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 81fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 82fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#define PNG(FLAG, ZLIBLEVEL) [](SkWStream* d, const SkPixmap& s) { \ 83fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return encode_png(d, s, SkPngEncoder::FilterFlag::FLAG, ZLIBLEVEL); } 84fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 85fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic const char* srcs[2] = {"images/mandrill_512.png", "images/color_wheel.jpg"}; 86fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 87fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// The Android Photos app uses a quality of 90 on JPEG encodes 88fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotDEF_BENCH(return new EncodeBench(srcs[0], &encode_jpeg, "JPEG")); 89fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotDEF_BENCH(return new EncodeBench(srcs[1], &encode_jpeg, "JPEG")); 90fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 91fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// TODO: What is the appropriate quality to use to benchmark WEBP encodes? 92fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotDEF_BENCH(return new EncodeBench(srcs[0], encode_webp_lossy, "WEBP")); 93fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotDEF_BENCH(return new EncodeBench(srcs[1], encode_webp_lossy, "WEBP")); 94fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 95fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotDEF_BENCH(return new EncodeBench(srcs[0], encode_webp_lossless, "WEBP_LL")); 96fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotDEF_BENCH(return new EncodeBench(srcs[1], encode_webp_lossless, "WEBP_LL")); 97fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 98fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotDEF_BENCH(return new EncodeBench(srcs[0], PNG(kAll, 6), "PNG")); 99fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotDEF_BENCH(return new EncodeBench(srcs[0], PNG(kAll, 3), "PNG_3")); 100fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotDEF_BENCH(return new EncodeBench(srcs[0], PNG(kAll, 1), "PNG_1")); 101fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 102fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotDEF_BENCH(return new EncodeBench(srcs[0], PNG(kSub, 6), "PNG_6s")); 103fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotDEF_BENCH(return new EncodeBench(srcs[0], PNG(kSub, 3), "PNG_3s")); 104fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotDEF_BENCH(return new EncodeBench(srcs[0], PNG(kSub, 1), "PNG_1s")); 105fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 106fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotDEF_BENCH(return new EncodeBench(srcs[0], PNG(kNone, 6), "PNG_6n")); 107fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotDEF_BENCH(return new EncodeBench(srcs[0], PNG(kNone, 3), "PNG_3n")); 108fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotDEF_BENCH(return new EncodeBench(srcs[0], PNG(kNone, 1), "PNG_1n")); 109fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 110fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotDEF_BENCH(return new EncodeBench(srcs[1], PNG(kAll, 6), "PNG")); 111fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotDEF_BENCH(return new EncodeBench(srcs[1], PNG(kAll, 3), "PNG_3")); 112fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotDEF_BENCH(return new EncodeBench(srcs[1], PNG(kAll, 1), "PNG_1")); 113fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 114fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotDEF_BENCH(return new EncodeBench(srcs[1], PNG(kSub, 6), "PNG_6s")); 115fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotDEF_BENCH(return new EncodeBench(srcs[1], PNG(kSub, 3), "PNG_3s")); 116fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotDEF_BENCH(return new EncodeBench(srcs[1], PNG(kSub, 1), "PNG_1s")); 117fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 118fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotDEF_BENCH(return new EncodeBench(srcs[1], PNG(kNone, 6), "PNG_6n")); 119fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotDEF_BENCH(return new EncodeBench(srcs[1], PNG(kNone, 3), "PNG_3n")); 120fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotDEF_BENCH(return new EncodeBench(srcs[1], PNG(kNone, 1), "PNG_1n")); 121fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 122fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#undef PNG 123