skia2/samplecode/SampleUnpremul.cpp
Mike Reed 9dc0b9e2f8 remove code now that loopers are dead (w.r.t. canvas and paint)
We can't remove the loopers themselves, as they are still used
by android and chrome (they just don't ever pass them to skia).

Eventually each of those clients will resolve this, but for now
we just keep the classes (and tests) in skia.

Bug: skia:4783
Change-Id: I5f507e6bb82280f2bc7c0b21eebe59c287aa9265
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/230579
Reviewed-by: Florin Malita <fmalita@chromium.org>
Commit-Queue: Mike Reed <reed@google.com>
2019-07-30 12:49:28 +00:00

167 lines
5.2 KiB
C++

/*
* Copyright 2013 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "include/core/SkCanvas.h"
#include "include/core/SkColorPriv.h"
#include "include/core/SkStream.h"
#include "include/core/SkString.h"
#include "include/core/SkTypes.h"
#include "samplecode/DecodeFile.h"
#include "samplecode/Sample.h"
#include "src/core/SkBlurMask.h"
#include "src/core/SkOSFile.h"
#include "src/utils/SkOSPath.h"
#include "src/utils/SkUTF.h"
#include "tools/Resources.h"
#include "tools/ToolUtils.h"
/**
* Interprets c as an unpremultiplied color, and returns the
* premultiplied equivalent.
*/
static SkPMColor premultiply_unpmcolor(SkPMColor c) {
U8CPU a = SkGetPackedA32(c);
U8CPU r = SkGetPackedR32(c);
U8CPU g = SkGetPackedG32(c);
U8CPU b = SkGetPackedB32(c);
return SkPreMultiplyARGB(a, r, g, b);
}
class UnpremulView : public Sample {
public:
UnpremulView(SkString res)
: fResPath(res)
, fPremul(true)
, fDecodeSucceeded(false) {
this->nextImage();
}
protected:
SkString name() override { return SkString("unpremul"); }
bool onChar(SkUnichar uni) override {
char utf8[SkUTF::kMaxBytesInUTF8Sequence];
size_t size = SkUTF::ToUTF8(uni, utf8);
// Only consider events for single char keys
if (1 == size) {
switch (utf8[0]) {
case fNextImageChar:
this->nextImage();
return true;
case fTogglePremulChar:
this->togglePremul();
return true;
default:
break;
}
}
return false;
}
void onDrawBackground(SkCanvas* canvas) override {
ToolUtils::draw_checkerboard(canvas, 0xFFCCCCCC, 0xFFFFFFFF, 12);
}
void onDrawContent(SkCanvas* canvas) override {
SkPaint paint;
paint.setAntiAlias(true);
SkFont font;
font.setSize(24);
SkScalar height = font.getMetrics(nullptr);
if (!fDecodeSucceeded) {
SkString failure;
if (fResPath.size() == 0) {
failure.printf("resource path is required!");
} else {
failure.printf("Failed to decode %s", fCurrFile.c_str());
}
canvas->drawString(failure, 0, height, font, paint);
return;
}
// Name, size of the file, and whether or not it is premultiplied.
SkString header(SkOSPath::Basename(fCurrFile.c_str()));
header.appendf(" [%dx%d] %s", fBitmap.width(), fBitmap.height(),
(fPremul ? "premultiplied" : "unpremultiplied"));
canvas->drawString(header, 0, height, font, paint);
canvas->translate(0, height);
// Help messages
header.printf("Press '%c' to move to the next image.'", fNextImageChar);
canvas->drawString(header, 0, height, font, paint);
canvas->translate(0, height);
header.printf("Press '%c' to toggle premultiplied decode.", fTogglePremulChar);
canvas->drawString(header, 0, height, font, paint);
// Now draw the image itself.
canvas->translate(height * 2, height * 2);
if (!fPremul) {
// A premultiplied bitmap cannot currently be drawn.
// Copy it to a bitmap which can be drawn, converting
// to premultiplied:
SkBitmap bm;
bm.allocN32Pixels(fBitmap.width(), fBitmap.height());
for (int i = 0; i < fBitmap.width(); ++i) {
for (int j = 0; j < fBitmap.height(); ++j) {
*bm.getAddr32(i, j) = premultiply_unpmcolor(*fBitmap.getAddr32(i, j));
}
}
canvas->drawBitmap(bm, 0, 0);
} else {
canvas->drawBitmap(fBitmap, 0, 0);
}
}
private:
const SkString fResPath;
SkString fCurrFile;
bool fPremul;
bool fDecodeSucceeded;
SkBitmap fBitmap;
SkOSFile::Iter fFileIter;
static const char fNextImageChar = 'j';
static const char fTogglePremulChar = 'h';
void nextImage() {
if (fResPath.size() == 0) {
return;
}
SkString basename;
if (!fFileIter.next(&basename)) {
fFileIter.reset(fResPath.c_str());
if (!fFileIter.next(&basename)) {
// Perhaps this should draw some error message?
return;
}
}
fCurrFile = SkOSPath::Join(fResPath.c_str(), basename.c_str());
this->decodeCurrFile();
}
void decodeCurrFile() {
if (fCurrFile.size() == 0) {
fDecodeSucceeded = false;
return;
}
fDecodeSucceeded = decode_file(fCurrFile.c_str(), &fBitmap, kN32_SkColorType, !fPremul);
}
void togglePremul() {
fPremul = !fPremul;
this->decodeCurrFile();
}
typedef Sample INHERITED;
};
//////////////////////////////////////////////////////////////////////////////
DEF_SAMPLE( return new UnpremulView(GetResourcePath("images")); )