2016-04-18 19:37:46 +00:00
|
|
|
/*
|
|
|
|
* Copyright 2016 Google Inc.
|
|
|
|
*
|
|
|
|
* Use of this source code is governed by a BSD-style license that can be
|
|
|
|
* found in the LICENSE file.
|
|
|
|
*/
|
|
|
|
|
2019-04-23 17:05:21 +00:00
|
|
|
#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"
|
2016-11-23 15:55:18 +00:00
|
|
|
|
2018-11-07 22:52:39 +00:00
|
|
|
// 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
|
|
|
|
|
2016-04-18 19:37:46 +00:00
|
|
|
class EncodeBench : public Benchmark {
|
|
|
|
public:
|
2017-06-16 20:52:10 +00:00
|
|
|
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)) {}
|
2016-04-18 19:37:46 +00:00
|
|
|
|
|
|
|
bool isSuitableFor(Backend backend) override { return backend == kNonRendering_Backend; }
|
2017-06-16 20:52:10 +00:00
|
|
|
|
2016-04-18 19:37:46 +00:00
|
|
|
const char* onGetName() override { return fName.c_str(); }
|
2017-06-16 20:52:10 +00:00
|
|
|
|
2018-10-17 23:42:28 +00:00
|
|
|
void onDelayedSetup() override {
|
2017-06-16 20:52:10 +00:00
|
|
|
SkAssertResult(GetResourceAsBitmap(fSourceFilename, &fBitmap));
|
2016-04-18 19:37:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void onDraw(int loops, SkCanvas*) override {
|
2017-06-16 20:52:10 +00:00
|
|
|
while (loops-- > 0) {
|
|
|
|
SkPixmap pixmap;
|
|
|
|
SkAssertResult(fBitmap.peekPixels(&pixmap));
|
|
|
|
SkNullWStream dst;
|
|
|
|
SkAssertResult(fEncoder(&dst, pixmap));
|
|
|
|
SkASSERT(dst.bytesWritten() > 0);
|
2016-04-18 19:37:46 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
2017-06-16 20:52:10 +00:00
|
|
|
const char* fSourceFilename;
|
|
|
|
Encoder fEncoder;
|
|
|
|
SkString fName;
|
|
|
|
SkBitmap fBitmap;
|
2016-04-18 19:37:46 +00:00
|
|
|
};
|
|
|
|
|
2017-06-16 20:52:10 +00:00
|
|
|
static bool encode_jpeg(SkWStream* dst, const SkPixmap& src) {
|
|
|
|
SkJpegEncoder::Options opts;
|
|
|
|
opts.fQuality = 90;
|
|
|
|
return SkJpegEncoder::Encode(dst, src, opts);
|
|
|
|
}
|
2016-04-18 19:37:46 +00:00
|
|
|
|
2017-06-16 20:52:10 +00:00
|
|
|
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);
|
|
|
|
}
|
2016-04-18 19:37:46 +00:00
|
|
|
|
2017-06-16 20:52:10 +00:00
|
|
|
#define PNG(FLAG, ZLIBLEVEL) [](SkWStream* d, const SkPixmap& s) { \
|
|
|
|
return encode_png(d, s, SkPngEncoder::FilterFlag::FLAG, ZLIBLEVEL); }
|
|
|
|
|
2017-12-08 15:21:31 +00:00
|
|
|
static const char* srcs[2] = {"images/mandrill_512.png", "images/color_wheel.jpg"};
|
2017-06-16 20:52:10 +00:00
|
|
|
|
|
|
|
// 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"));
|
2016-04-18 19:37:46 +00:00
|
|
|
|
|
|
|
// TODO: What is the appropriate quality to use to benchmark WEBP encodes?
|
2017-06-16 20:52:10 +00:00
|
|
|
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
|