skia2/fuzz/FuzzEncoders.cpp
Kevin Lubick f60584eb0f [includes] Remove link between SkImage.h and SkImageEncoder.h
According to go/chrome-includes [1], this will save about
210MB (0.09%) off the Chrome build. http://screen/GVdDaRRneTRuroL

[1] https://commondatastorage.googleapis.com/chromium-browser-clang/include-analysis.html#view=edges&filter=%5Ethird_party%2Fskia%2Finclude%2Fcore%2FSkImage%5C.h%24&sort=asize&reverse=&includer=%5Ethird_party%2Fskia%2Finclude%2Fcore%2FSkImage%5C.h%24&included=&limit=1000

Canary-Android-Topic: image-encoder-2
Change-Id: If911ec283a9ce2b07c8509768a6a05446573a215
Bug: 242216
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/512416
Reviewed-by: Leon Scroggins <scroggo@google.com>
Reviewed-by: Brian Osman <brianosman@google.com>
Commit-Queue: Kevin Lubick <kjlubick@google.com>
2022-03-07 21:32:13 +00:00

120 lines
3.5 KiB
C++

/*
* Copyright 2018 Google LLC
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "fuzz/Fuzz.h"
#include "include/core/SkBitmap.h"
#include "include/core/SkImage.h"
#include "include/core/SkImageInfo.h"
#include "include/core/SkPixmap.h"
#include "include/core/SkStream.h"
#include "include/encode/SkJpegEncoder.h"
#include "include/encode/SkPngEncoder.h"
#include "include/encode/SkWebpEncoder.h"
#include "include/utils/SkRandom.h"
#include "src/core/SkOSFile.h"
#include <vector>
// These values were picked arbitrarily to hopefully limit the size of the
// serialized SkPixmaps.
constexpr int MAX_WIDTH = 512;
constexpr int MAX_HEIGHT = 512;
static SkBitmap make_fuzzed_bitmap(Fuzz* fuzz) {
SkBitmap bm;
uint32_t w, h;
fuzz->nextRange(&w, 1, MAX_WIDTH);
fuzz->nextRange(&h, 1, MAX_HEIGHT);
if (!bm.tryAllocPixels(SkImageInfo::MakeN32Premul(w, h))) {
return bm;
}
uint32_t n = w * h;
fuzz->nextN((SkPMColor*)bm.getPixels(), n);
return bm;
}
DEF_FUZZ(PNGEncoder, fuzz) {
auto bm = make_fuzzed_bitmap(fuzz);
auto opts = SkPngEncoder::Options{};
fuzz->nextRange(&opts.fZLibLevel, 0, 9);
SkDynamicMemoryWStream dest;
SkPngEncoder::Encode(&dest, bm.pixmap(), opts);
}
DEF_FUZZ(JPEGEncoder, fuzz) {
auto bm = make_fuzzed_bitmap(fuzz);
auto opts = SkJpegEncoder::Options{};
fuzz->nextRange(&opts.fQuality, 0, 100);
SkDynamicMemoryWStream dest;
(void)SkJpegEncoder::Encode(&dest, bm.pixmap(), opts);
}
DEF_FUZZ(WEBPEncoder, fuzz) {
auto bm = make_fuzzed_bitmap(fuzz);
auto opts = SkWebpEncoder::Options{};
fuzz->nextRange(&opts.fQuality, 0.0f, 100.0f);
bool lossy;
fuzz->next(&lossy);
if (lossy) {
opts.fCompression = SkWebpEncoder::Compression::kLossy;
} else {
opts.fCompression = SkWebpEncoder::Compression::kLossless;
}
SkDynamicMemoryWStream dest;
(void)SkWebpEncoder::Encode(&dest, bm.pixmap(), opts);
}
// Not a real fuzz endpoint, but a helper to take in real, good images
// and dump out a corpus for this fuzzer.
DEF_FUZZ(_MakeEncoderCorpus, fuzz) {
auto bytes = fuzz->fBytes;
SkDebugf("bytes %zu\n", bytes->size());
auto img = SkImage::MakeFromEncoded(bytes);
if (nullptr == img.get()) {
SkDebugf("invalid image, could not decode\n");
return;
}
if (img->width() > MAX_WIDTH || img->height() > MAX_HEIGHT) {
SkDebugf("Too big (%d x %d)\n", img->width(), img->height());
return;
}
std::vector<int32_t> dstPixels;
int rowBytes = img->width() * 4;
dstPixels.resize(img->height() * rowBytes);
SkPixmap pm(SkImageInfo::MakeN32Premul(img->width(), img->height()),
&dstPixels.front(), rowBytes);
if (!img->readPixels(nullptr, pm, 0, 0)) {
SkDebugf("Could not read pixmap\n");
return;
}
SkString s("./encoded_corpus/enc_");
static SkRandom rand;
s.appendU32(rand.nextU());
auto file = sk_fopen(s.c_str(), SkFILE_Flags::kWrite_SkFILE_Flag);
if (!file) {
SkDebugf("Can't initialize file\n");
return;
}
auto total = pm.info().bytesPerPixel() * pm.width() * pm.height();
SkDebugf("Writing %d (%d x %d) bytes\n", total, pm.width(), pm.height());
// Write out the size in two bytes since that's what the fuzzer will
// read first.
uint32_t w = pm.width();
sk_fwrite(&w, sizeof(uint32_t), file);
uint32_t h = pm.height();
sk_fwrite(&h, sizeof(uint32_t), file);
sk_fwrite(pm.addr(), total, file);
sk_fclose(file);
}