skia2/gm/showmiplevels.cpp
Brian Osman 7b8400dad2 Rename SkSourceGammaTreatment to SkDestinationSurfaceColorMode
This is much more explicit about what that type represents (are we in
legacy mode or not), which also makes it suitable for other (upcoming)
usage.

BUG=skia:

GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=4529

Change-Id: Iacb397c34e7765f1ca86c0195bc622b2be4d9acf
Reviewed-on: https://skia-review.googlesource.com/4529
Commit-Queue: Brian Osman <brianosman@google.com>
Reviewed-by: Brian Salomon <bsalomon@google.com>
2016-11-09 01:05:07 +00:00

318 lines
9.1 KiB
C++

/*
* Copyright 2016 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 "Resources.h"
#include "SkBitmapScaler.h"
#include "SkGradientShader.h"
#include "SkTypeface.h"
#include "SkStream.h"
#include "SkPaint.h"
#include "SkMipMap.h"
#include "Resources.h"
#include "sk_tool_utils.h"
#define SHOW_MIP_COLOR 0xFF000000
static SkBitmap make_bitmap(int w, int h) {
SkBitmap bm;
bm.allocN32Pixels(w, h);
SkCanvas canvas(bm);
canvas.clear(0xFFFFFFFF);
SkPaint paint;
paint.setStyle(SkPaint::kStroke_Style);
paint.setStrokeWidth(w / 16.0f);
paint.setColor(SHOW_MIP_COLOR);
canvas.drawCircle(w/2.0f, h/2.0f, w/3.0f, paint);
return bm;
}
static SkBitmap make_bitmap2(int w, int h) {
SkBitmap bm;
bm.allocN32Pixels(w, h);
SkCanvas canvas(bm);
canvas.clear(0xFFFFFFFF);
SkPaint paint;
paint.setColor(SHOW_MIP_COLOR);
paint.setStyle(SkPaint::kStroke_Style);
SkScalar inset = 2;
SkRect r = SkRect::MakeIWH(w, h).makeInset(0.5f, 0.5f);
while (r.width() > 4) {
canvas.drawRect(r, paint);
r.inset(inset, inset);
inset += 1;
}
return bm;
}
#include "SkNx.h"
static SkBitmap make_bitmap3(int w, int h) {
SkBitmap bm;
bm.allocN32Pixels(w, h);
SkCanvas canvas(bm);
canvas.clear(0xFFFFFFFF);
SkPaint paint;
paint.setStyle(SkPaint::kStroke_Style);
paint.setStrokeWidth(2.1f);
paint.setColor(SHOW_MIP_COLOR);
SkScalar s = SkIntToScalar(w);
Sk4f p(s, -s, -s, s);
Sk4f d(5);
while (p[1] < s) {
canvas.drawLine(p[0],p[1], p[2], p[3], paint);
p = p + d;
}
return bm;
}
class ShowMipLevels : public skiagm::GM {
const int fN;
SkBitmap fBM[4];
public:
static unsigned gamma(unsigned n) {
float x = n / 255.0f;
#if 0
x = sqrtf(x);
#else
if (x > 0.0031308f) {
x = 1.055f * (powf(x, (1.0f / 2.4f))) - 0.055f;
} else {
x = 12.92f * x;
}
#endif
return (int)(x * 255);
}
static void apply_gamma(const SkBitmap& bm) {
return; // below is our experiment for sRGB correction
bm.lockPixels();
for (int y = 0; y < bm.height(); ++y) {
for (int x = 0; x < bm.width(); ++x) {
SkPMColor c = *bm.getAddr32(x, y);
unsigned r = gamma(SkGetPackedR32(c));
unsigned g = gamma(SkGetPackedG32(c));
unsigned b = gamma(SkGetPackedB32(c));
*bm.getAddr32(x, y) = SkPackARGB32(0xFF, r, g, b);
}
}
}
ShowMipLevels(int N) : fN(N) { }
protected:
SkString onShortName() override {
SkString str;
str.printf("showmiplevels_%d", fN);
return str;
}
SkISize onISize() override {
return { 824, 862 };
}
static void DrawAndFrame(SkCanvas* canvas, const SkBitmap& orig, SkScalar x, SkScalar y) {
SkBitmap bm;
orig.copyTo(&bm);
apply_gamma(bm);
canvas->drawBitmap(bm, x, y, nullptr);
SkPaint paint;
paint.setStyle(SkPaint::kStroke_Style);
paint.setColor(0xFFFFCCCC);
canvas->drawRect(SkRect::MakeIWH(bm.width(), bm.height()).makeOffset(x, y).makeOutset(0.5f, 0.5f), paint);
}
template <typename F> void drawLevels(SkCanvas* canvas, const SkBitmap& baseBM, F func) {
SkScalar x = 4;
SkScalar y = 4;
SkPixmap prevPM;
baseBM.lockPixels();
baseBM.peekPixels(&prevPM);
SkDestinationSurfaceColorMode colorMode = SkDestinationSurfaceColorMode::kLegacy;
sk_sp<SkMipMap> mm(SkMipMap::Build(baseBM, colorMode, nullptr));
int index = 0;
SkMipMap::Level level;
SkScalar scale = 0.5f;
while (mm->extractLevel(SkSize::Make(scale, scale), &level)) {
SkBitmap bm = func(prevPM, level.fPixmap);
DrawAndFrame(canvas, bm, x, y);
if (level.fPixmap.width() <= 2 || level.fPixmap.height() <= 2) {
break;
}
if (index & 1) {
x += level.fPixmap.width() + 4;
} else {
y += level.fPixmap.height() + 4;
}
scale /= 2;
prevPM = level.fPixmap;
index += 1;
}
}
void drawSet(SkCanvas* canvas, const SkBitmap& orig) {
SkAutoCanvasRestore acr(canvas, true);
drawLevels(canvas, orig, [](const SkPixmap& prev, const SkPixmap& curr) {
SkBitmap bm;
bm.installPixels(curr);
return bm;
});
const SkBitmapScaler::ResizeMethod methods[] = {
SkBitmapScaler::RESIZE_BOX,
SkBitmapScaler::RESIZE_TRIANGLE,
SkBitmapScaler::RESIZE_LANCZOS3,
SkBitmapScaler::RESIZE_HAMMING,
SkBitmapScaler::RESIZE_MITCHELL,
};
SkPixmap basePM;
orig.lockPixels();
orig.peekPixels(&basePM);
for (auto method : methods) {
canvas->translate(orig.width()/2 + 8.0f, 0);
drawLevels(canvas, orig, [basePM, method](const SkPixmap& prev, const SkPixmap& curr) {
SkBitmap bm;
SkBitmapScaler::Resize(&bm, prev, method, curr.width(), curr.height());
return bm;
});
}
}
void onOnceBeforeDraw() override {
fBM[0] = sk_tool_utils::create_checkerboard_bitmap(fN, fN, SK_ColorBLACK, SK_ColorWHITE, 2);
fBM[1] = make_bitmap(fN, fN);
fBM[2] = make_bitmap2(fN, fN);
fBM[3] = make_bitmap3(fN, fN);
}
void onDraw(SkCanvas* canvas) override {
canvas->translate(4, 4);
for (const auto& bm : fBM) {
this->drawSet(canvas, bm);
canvas->translate(0, bm.height() * 0.85f);
}
}
private:
typedef skiagm::GM INHERITED;
};
DEF_GM( return new ShowMipLevels(255); )
DEF_GM( return new ShowMipLevels(256); )
///////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Show mip levels that were built, for all supported colortypes
*/
class ShowMipLevels2 : public skiagm::GM {
const int fW, fH;
SkBitmap fBM[4];
public:
ShowMipLevels2(int w, int h) : fW(w), fH(h) { }
protected:
SkString onShortName() override {
SkString str;
str.printf("showmiplevels2_%dx%d", fW, fH);
return str;
}
SkISize onISize() override {
return { 824, 862 };
}
static void DrawAndFrame(SkCanvas* canvas, const SkBitmap& bm, SkScalar x, SkScalar y) {
canvas->drawBitmap(bm, x, y, nullptr);
SkPaint paint;
paint.setStyle(SkPaint::kStroke_Style);
paint.setColor(0xFFFFCCCC);
canvas->drawRect(SkRect::MakeIWH(bm.width(), bm.height()).makeOffset(x, y).makeOutset(0.5f, 0.5f), paint);
}
void drawLevels(SkCanvas* canvas, const SkBitmap& baseBM) {
SkScalar x = 4;
SkScalar y = 4;
SkDestinationSurfaceColorMode colorMode = SkDestinationSurfaceColorMode::kLegacy;
sk_sp<SkMipMap> mm(SkMipMap::Build(baseBM, colorMode, nullptr));
int index = 0;
SkMipMap::Level level;
SkScalar scale = 0.5f;
while (mm->extractLevel(SkSize::Make(scale, scale), &level)) {
SkBitmap bm;
bm.installPixels(level.fPixmap);
DrawAndFrame(canvas, bm, x, y);
if (level.fPixmap.width() <= 2 || level.fPixmap.height() <= 2) {
break;
}
if (index & 1) {
x += level.fPixmap.width() + 4;
} else {
y += level.fPixmap.height() + 4;
}
scale /= 2;
index += 1;
}
}
void drawSet(SkCanvas* canvas, const SkBitmap& orig) {
const SkColorType ctypes[] = {
kN32_SkColorType, kRGB_565_SkColorType, kARGB_4444_SkColorType, kGray_8_SkColorType
};
SkAutoCanvasRestore acr(canvas, true);
for (auto ctype : ctypes) {
SkBitmap bm;
orig.copyTo(&bm, ctype);
drawLevels(canvas, bm);
canvas->translate(orig.width()/2 + 8.0f, 0);
}
}
void onOnceBeforeDraw() override {
fBM[0] = sk_tool_utils::create_checkerboard_bitmap(fW, fH,
SHOW_MIP_COLOR, SK_ColorWHITE, 2);
fBM[1] = make_bitmap(fW, fH);
fBM[2] = make_bitmap2(fW, fH);
fBM[3] = make_bitmap3(fW, fH);
}
void onDraw(SkCanvas* canvas) override {
canvas->translate(4, 4);
for (const auto& bm : fBM) {
this->drawSet(canvas, bm);
// round so we always produce an integral translate, so the GOLD tool won't show
// unimportant diffs if this is drawn on a GPU with different rounding rules
// since we draw the bitmaps using nearest-neighbor
canvas->translate(0, SkScalarRoundToScalar(bm.height() * 0.85f));
}
}
private:
typedef skiagm::GM INHERITED;
};
DEF_GM( return new ShowMipLevels2(255, 255); )
DEF_GM( return new ShowMipLevels2(256, 255); )
DEF_GM( return new ShowMipLevels2(255, 256); )
DEF_GM( return new ShowMipLevels2(256, 256); )