skia2/gm/encode-alpha-jpeg.cpp
Matt Sarett 2e61b182da Add jpeg encoder alpha handling option
This instructs us on how to encode jpegs when the src
image has alpha.  The original behavior is to ignore
the alpha channel.  This CL adds the option to blend
the pixels onto opaque black.

Note that kBlendOnBlack and kIgnore are identical
unless the input alpha type is kUnpremul.

Bug: 713862
Bug: skia:1501
Change-Id: I4891c70bb0ccd83f7974c359bd40a2143b5c49ac
Reviewed-on: https://skia-review.googlesource.com/15817
Reviewed-by: Leon Scroggins <scroggo@google.com>
Commit-Queue: Matt Sarett <msarett@google.com>
2017-05-09 18:32:04 +00:00

106 lines
3.9 KiB
C++

/*
* Copyright 2017 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "gm.h"
#include "SkImage.h"
#include "SkJpegEncoder.h"
#include "Resources.h"
namespace skiagm {
static inline void read_into_pixmap(SkPixmap* dst, SkImageInfo dstInfo, void* dstPixels,
sk_sp<SkImage> src) {
dst->reset(dstInfo, dstPixels, dstInfo.minRowBytes());
src->readPixels(*dst, 0, 0, SkImage::CachingHint::kDisallow_CachingHint);
}
static inline sk_sp<SkImage> encode_pixmap_and_make_image(const SkPixmap& src,
SkJpegEncoder::AlphaOption alphaOption, SkTransferFunctionBehavior blendBehavior) {
SkDynamicMemoryWStream dst;
SkJpegEncoder::Options options;
options.fAlphaOption = alphaOption;
options.fBlendBehavior = blendBehavior;
SkJpegEncoder::Encode(&dst, src, options);
return SkImage::MakeFromEncoded(dst.detachAsData());
}
class EncodeJpegAlphaOptsGM : public GM {
public:
EncodeJpegAlphaOptsGM() {}
protected:
SkString onShortName() override {
return SkString("encode-alpha-jpeg");
}
SkISize onISize() override {
return SkISize::Make(400, 200);
}
void onDraw(SkCanvas* canvas) override {
sk_sp<SkImage> srcImg = GetResourceAsImage("rainbow-gradient.png");
fStorage.reset(srcImg->width() * srcImg->height() *
SkColorTypeBytesPerPixel(kRGBA_F16_SkColorType));
SkPixmap src;
SkImageInfo info = SkImageInfo::MakeN32Premul(srcImg->width(), srcImg->height(),
canvas->imageInfo().colorSpace() ? SkColorSpace::MakeSRGB() : nullptr);
read_into_pixmap(&src, info, fStorage.get(), srcImg);
SkTransferFunctionBehavior behavior = canvas->imageInfo().colorSpace() ?
SkTransferFunctionBehavior::kRespect : SkTransferFunctionBehavior::kIgnore;
// Encode 8888 premul.
sk_sp<SkImage> img0 = encode_pixmap_and_make_image(src, SkJpegEncoder::AlphaOption::kIgnore,
behavior);
sk_sp<SkImage> img1 = encode_pixmap_and_make_image(src,
SkJpegEncoder::AlphaOption::kBlendOnBlack, behavior);
canvas->drawImage(img0, 0.0f, 0.0f);
canvas->drawImage(img1, 0.0f, 100.0f);
// Encode 8888 unpremul
info = info.makeAlphaType(kUnpremul_SkAlphaType);
read_into_pixmap(&src, info, fStorage.get(), srcImg);
img0 = encode_pixmap_and_make_image(src, SkJpegEncoder::AlphaOption::kIgnore, behavior);
img1 = encode_pixmap_and_make_image(src, SkJpegEncoder::AlphaOption::kBlendOnBlack,
behavior);
canvas->drawImage(img0, 100.0f, 0.0f);
canvas->drawImage(img1, 100.0f, 100.0f);
if (canvas->imageInfo().colorSpace()) {
// Encode F16 premul
info = SkImageInfo::Make(srcImg->width(), srcImg->height(), kRGBA_F16_SkColorType,
kPremul_SkAlphaType, SkColorSpace::MakeSRGBLinear());
read_into_pixmap(&src, info, fStorage.get(), srcImg);
img0 = encode_pixmap_and_make_image(src, SkJpegEncoder::AlphaOption::kIgnore, behavior);
img1 = encode_pixmap_and_make_image(src, SkJpegEncoder::AlphaOption::kBlendOnBlack,
behavior);
canvas->drawImage(img0, 200.0f, 0.0f);
canvas->drawImage(img1, 200.0f, 100.0f);
// Encode F16 unpremul
info = info.makeAlphaType(kUnpremul_SkAlphaType);
read_into_pixmap(&src, info, fStorage.get(), srcImg);
img0 = encode_pixmap_and_make_image(src, SkJpegEncoder::AlphaOption::kIgnore, behavior);
img1 = encode_pixmap_and_make_image(src, SkJpegEncoder::AlphaOption::kBlendOnBlack,
behavior);
canvas->drawImage(img0, 300.0f, 0.0f);
canvas->drawImage(img1, 300.0f, 100.0f);
}
}
private:
SkAutoTMalloc<uint8_t> fStorage;
typedef GM INHERITED;
};
DEF_GM( return new EncodeJpegAlphaOptsGM; )
};