showmiplevels.cpp revision a40be09c443d15fcb080adde0ab9625e8a5af73d
1a40be09c443d15fcb080adde0ab9625e8a5af73dreed/*
2a40be09c443d15fcb080adde0ab9625e8a5af73dreed * Copyright 2016 Google Inc.
3a40be09c443d15fcb080adde0ab9625e8a5af73dreed *
4a40be09c443d15fcb080adde0ab9625e8a5af73dreed * Use of this source code is governed by a BSD-style license that can be
5a40be09c443d15fcb080adde0ab9625e8a5af73dreed * found in the LICENSE file.
6a40be09c443d15fcb080adde0ab9625e8a5af73dreed */
7a40be09c443d15fcb080adde0ab9625e8a5af73dreed
8a40be09c443d15fcb080adde0ab9625e8a5af73dreed#include "gm.h"
9a40be09c443d15fcb080adde0ab9625e8a5af73dreed
10a40be09c443d15fcb080adde0ab9625e8a5af73dreed#include "Resources.h"
11a40be09c443d15fcb080adde0ab9625e8a5af73dreed#include "SkBitmapScaler.h"
12a40be09c443d15fcb080adde0ab9625e8a5af73dreed#include "SkGradientShader.h"
13a40be09c443d15fcb080adde0ab9625e8a5af73dreed#include "SkTypeface.h"
14a40be09c443d15fcb080adde0ab9625e8a5af73dreed#include "SkImageDecoder.h"
15a40be09c443d15fcb080adde0ab9625e8a5af73dreed#include "SkStream.h"
16a40be09c443d15fcb080adde0ab9625e8a5af73dreed#include "SkPaint.h"
17a40be09c443d15fcb080adde0ab9625e8a5af73dreed#include "SkMipMap.h"
18a40be09c443d15fcb080adde0ab9625e8a5af73dreed#include "Resources.h"
19a40be09c443d15fcb080adde0ab9625e8a5af73dreed#include "sk_tool_utils.h"
20a40be09c443d15fcb080adde0ab9625e8a5af73dreed
21a40be09c443d15fcb080adde0ab9625e8a5af73dreedstatic SkBitmap make_bitmap(int size) {
22a40be09c443d15fcb080adde0ab9625e8a5af73dreed    SkBitmap bm;
23a40be09c443d15fcb080adde0ab9625e8a5af73dreed    bm.allocN32Pixels(size, size);
24a40be09c443d15fcb080adde0ab9625e8a5af73dreed    SkCanvas canvas(bm);
25a40be09c443d15fcb080adde0ab9625e8a5af73dreed    canvas.clear(0xFFFFFFFF);
26a40be09c443d15fcb080adde0ab9625e8a5af73dreed    SkPaint paint;
27a40be09c443d15fcb080adde0ab9625e8a5af73dreed    paint.setStyle(SkPaint::kStroke_Style);
28a40be09c443d15fcb080adde0ab9625e8a5af73dreed    paint.setStrokeWidth(size / 16.0f);
29a40be09c443d15fcb080adde0ab9625e8a5af73dreed    canvas.drawCircle(size/2.0f, size/2.0f, size/3.0f, paint);
30a40be09c443d15fcb080adde0ab9625e8a5af73dreed    return bm;
31a40be09c443d15fcb080adde0ab9625e8a5af73dreed}
32a40be09c443d15fcb080adde0ab9625e8a5af73dreed
33a40be09c443d15fcb080adde0ab9625e8a5af73dreedstatic SkBitmap make_bitmap2(int size) {
34a40be09c443d15fcb080adde0ab9625e8a5af73dreed    SkBitmap bm;
35a40be09c443d15fcb080adde0ab9625e8a5af73dreed    bm.allocN32Pixels(size, size);
36a40be09c443d15fcb080adde0ab9625e8a5af73dreed    SkCanvas canvas(bm);
37a40be09c443d15fcb080adde0ab9625e8a5af73dreed    canvas.clear(0xFFFFFFFF);
38a40be09c443d15fcb080adde0ab9625e8a5af73dreed    SkPaint paint;
39a40be09c443d15fcb080adde0ab9625e8a5af73dreed    paint.setStyle(SkPaint::kStroke_Style);
40a40be09c443d15fcb080adde0ab9625e8a5af73dreed
41a40be09c443d15fcb080adde0ab9625e8a5af73dreed    SkScalar inset = 2;
42a40be09c443d15fcb080adde0ab9625e8a5af73dreed    SkRect r = SkRect::MakeIWH(size, size).makeInset(0.5f, 0.5f);
43a40be09c443d15fcb080adde0ab9625e8a5af73dreed    while (r.width() > 4) {
44a40be09c443d15fcb080adde0ab9625e8a5af73dreed        canvas.drawRect(r, paint);
45a40be09c443d15fcb080adde0ab9625e8a5af73dreed        r.inset(inset, inset);
46a40be09c443d15fcb080adde0ab9625e8a5af73dreed        inset += 1;
47a40be09c443d15fcb080adde0ab9625e8a5af73dreed    }
48a40be09c443d15fcb080adde0ab9625e8a5af73dreed    return bm;
49a40be09c443d15fcb080adde0ab9625e8a5af73dreed}
50a40be09c443d15fcb080adde0ab9625e8a5af73dreed
51a40be09c443d15fcb080adde0ab9625e8a5af73dreed#include "SkNx.h"
52a40be09c443d15fcb080adde0ab9625e8a5af73dreedstatic SkBitmap make_bitmap3(int size) {
53a40be09c443d15fcb080adde0ab9625e8a5af73dreed    SkBitmap bm;
54a40be09c443d15fcb080adde0ab9625e8a5af73dreed    bm.allocN32Pixels(size, size);
55a40be09c443d15fcb080adde0ab9625e8a5af73dreed    SkCanvas canvas(bm);
56a40be09c443d15fcb080adde0ab9625e8a5af73dreed    canvas.clear(0xFFFFFFFF);
57a40be09c443d15fcb080adde0ab9625e8a5af73dreed    SkPaint paint;
58a40be09c443d15fcb080adde0ab9625e8a5af73dreed    paint.setStyle(SkPaint::kStroke_Style);
59a40be09c443d15fcb080adde0ab9625e8a5af73dreed    paint.setStrokeWidth(2.1f);
60a40be09c443d15fcb080adde0ab9625e8a5af73dreed
61a40be09c443d15fcb080adde0ab9625e8a5af73dreed    SkScalar s = SkIntToScalar(size);
62a40be09c443d15fcb080adde0ab9625e8a5af73dreed    Sk4f p(s, -s, -s, s);
63a40be09c443d15fcb080adde0ab9625e8a5af73dreed    Sk4f d(5);
64a40be09c443d15fcb080adde0ab9625e8a5af73dreed    while (p.kth<1>() < s) {
65a40be09c443d15fcb080adde0ab9625e8a5af73dreed        canvas.drawLine(p.kth<0>(),p.kth<1>(), p.kth<2>(), p.kth<3>(), paint);
66a40be09c443d15fcb080adde0ab9625e8a5af73dreed        p = p + d;
67a40be09c443d15fcb080adde0ab9625e8a5af73dreed    }
68a40be09c443d15fcb080adde0ab9625e8a5af73dreed    return bm;
69a40be09c443d15fcb080adde0ab9625e8a5af73dreed}
70a40be09c443d15fcb080adde0ab9625e8a5af73dreed
71a40be09c443d15fcb080adde0ab9625e8a5af73dreedclass ShowMipLevels : public skiagm::GM {
72a40be09c443d15fcb080adde0ab9625e8a5af73dreed    const int fN;
73a40be09c443d15fcb080adde0ab9625e8a5af73dreed    SkBitmap  fBM[4];
74a40be09c443d15fcb080adde0ab9625e8a5af73dreed
75a40be09c443d15fcb080adde0ab9625e8a5af73dreedpublic:
76a40be09c443d15fcb080adde0ab9625e8a5af73dreed    static unsigned gamma(unsigned n) {
77a40be09c443d15fcb080adde0ab9625e8a5af73dreed        float x = n / 255.0f;
78a40be09c443d15fcb080adde0ab9625e8a5af73dreed#if 0
79a40be09c443d15fcb080adde0ab9625e8a5af73dreed        x = sqrtf(x);
80a40be09c443d15fcb080adde0ab9625e8a5af73dreed#else
81a40be09c443d15fcb080adde0ab9625e8a5af73dreed        if (x > 0.0031308f) {
82a40be09c443d15fcb080adde0ab9625e8a5af73dreed            x = 1.055f * (powf(x, (1.0f / 2.4f))) - 0.055f;
83a40be09c443d15fcb080adde0ab9625e8a5af73dreed        } else {
84a40be09c443d15fcb080adde0ab9625e8a5af73dreed            x = 12.92f * x;
85a40be09c443d15fcb080adde0ab9625e8a5af73dreed        }
86a40be09c443d15fcb080adde0ab9625e8a5af73dreed#endif
87a40be09c443d15fcb080adde0ab9625e8a5af73dreed        return (int)(x * 255);
88a40be09c443d15fcb080adde0ab9625e8a5af73dreed    }
89a40be09c443d15fcb080adde0ab9625e8a5af73dreed
90a40be09c443d15fcb080adde0ab9625e8a5af73dreed    static void apply_gamma(const SkBitmap& bm) {
91a40be09c443d15fcb080adde0ab9625e8a5af73dreed        return; // below is our experiment for sRGB correction
92a40be09c443d15fcb080adde0ab9625e8a5af73dreed        bm.lockPixels();
93a40be09c443d15fcb080adde0ab9625e8a5af73dreed        for (int y = 0; y < bm.height(); ++y) {
94a40be09c443d15fcb080adde0ab9625e8a5af73dreed            for (int x = 0; x < bm.width(); ++x) {
95a40be09c443d15fcb080adde0ab9625e8a5af73dreed                SkPMColor c = *bm.getAddr32(x, y);
96a40be09c443d15fcb080adde0ab9625e8a5af73dreed                unsigned r = gamma(SkGetPackedR32(c));
97a40be09c443d15fcb080adde0ab9625e8a5af73dreed                unsigned g = gamma(SkGetPackedG32(c));
98a40be09c443d15fcb080adde0ab9625e8a5af73dreed                unsigned b = gamma(SkGetPackedB32(c));
99a40be09c443d15fcb080adde0ab9625e8a5af73dreed                *bm.getAddr32(x, y) = SkPackARGB32(0xFF, r, g, b);
100a40be09c443d15fcb080adde0ab9625e8a5af73dreed            }
101a40be09c443d15fcb080adde0ab9625e8a5af73dreed        }
102a40be09c443d15fcb080adde0ab9625e8a5af73dreed    }
103a40be09c443d15fcb080adde0ab9625e8a5af73dreed
104a40be09c443d15fcb080adde0ab9625e8a5af73dreed    ShowMipLevels(int N) : fN(N) {
105a40be09c443d15fcb080adde0ab9625e8a5af73dreed        fBM[0] = sk_tool_utils::create_checkerboard_bitmap(N, N, SK_ColorBLACK, SK_ColorWHITE, 2);
106a40be09c443d15fcb080adde0ab9625e8a5af73dreed        fBM[1] = make_bitmap(N);
107a40be09c443d15fcb080adde0ab9625e8a5af73dreed        fBM[2] = make_bitmap2(N);
108a40be09c443d15fcb080adde0ab9625e8a5af73dreed        fBM[3] = make_bitmap3(N);
109a40be09c443d15fcb080adde0ab9625e8a5af73dreed    }
110a40be09c443d15fcb080adde0ab9625e8a5af73dreed
111a40be09c443d15fcb080adde0ab9625e8a5af73dreedprotected:
112a40be09c443d15fcb080adde0ab9625e8a5af73dreed
113a40be09c443d15fcb080adde0ab9625e8a5af73dreed    SkString onShortName() override {
114a40be09c443d15fcb080adde0ab9625e8a5af73dreed        SkString str;
115a40be09c443d15fcb080adde0ab9625e8a5af73dreed        str.printf("showmiplevels_%d", fN);
116a40be09c443d15fcb080adde0ab9625e8a5af73dreed        return str;
117a40be09c443d15fcb080adde0ab9625e8a5af73dreed    }
118a40be09c443d15fcb080adde0ab9625e8a5af73dreed
119a40be09c443d15fcb080adde0ab9625e8a5af73dreed    SkISize onISize() override {
120a40be09c443d15fcb080adde0ab9625e8a5af73dreed        return { 824, 862 };
121a40be09c443d15fcb080adde0ab9625e8a5af73dreed    }
122a40be09c443d15fcb080adde0ab9625e8a5af73dreed
123a40be09c443d15fcb080adde0ab9625e8a5af73dreed    static void DrawAndFrame(SkCanvas* canvas, const SkBitmap& orig, SkScalar x, SkScalar y) {
124a40be09c443d15fcb080adde0ab9625e8a5af73dreed        SkBitmap bm;
125a40be09c443d15fcb080adde0ab9625e8a5af73dreed        orig.copyTo(&bm);
126a40be09c443d15fcb080adde0ab9625e8a5af73dreed        apply_gamma(bm);
127a40be09c443d15fcb080adde0ab9625e8a5af73dreed
128a40be09c443d15fcb080adde0ab9625e8a5af73dreed        canvas->drawBitmap(bm, x, y, nullptr);
129a40be09c443d15fcb080adde0ab9625e8a5af73dreed        SkPaint paint;
130a40be09c443d15fcb080adde0ab9625e8a5af73dreed        paint.setStyle(SkPaint::kStroke_Style);
131a40be09c443d15fcb080adde0ab9625e8a5af73dreed        paint.setColor(0xFFFFCCCC);
132a40be09c443d15fcb080adde0ab9625e8a5af73dreed        canvas->drawRect(SkRect::MakeIWH(bm.width(), bm.height()).makeOffset(x, y).makeOutset(0.5f, 0.5f), paint);
133a40be09c443d15fcb080adde0ab9625e8a5af73dreed    }
134a40be09c443d15fcb080adde0ab9625e8a5af73dreed
135a40be09c443d15fcb080adde0ab9625e8a5af73dreed    template <typename F> void drawLevels(SkCanvas* canvas, const SkBitmap& baseBM, F func) {
136a40be09c443d15fcb080adde0ab9625e8a5af73dreed        SkScalar x = 4;
137a40be09c443d15fcb080adde0ab9625e8a5af73dreed        SkScalar y = 4;
138a40be09c443d15fcb080adde0ab9625e8a5af73dreed
139a40be09c443d15fcb080adde0ab9625e8a5af73dreed        SkPixmap prevPM;
140a40be09c443d15fcb080adde0ab9625e8a5af73dreed        baseBM.lockPixels();
141a40be09c443d15fcb080adde0ab9625e8a5af73dreed        baseBM.peekPixels(&prevPM);
142a40be09c443d15fcb080adde0ab9625e8a5af73dreed
143a40be09c443d15fcb080adde0ab9625e8a5af73dreed        SkAutoTUnref<SkMipMap> mm(SkMipMap::Build(baseBM, nullptr));
144a40be09c443d15fcb080adde0ab9625e8a5af73dreed
145a40be09c443d15fcb080adde0ab9625e8a5af73dreed        int index = 0;
146a40be09c443d15fcb080adde0ab9625e8a5af73dreed        SkMipMap::Level level;
147a40be09c443d15fcb080adde0ab9625e8a5af73dreed        SkScalar scale = 0.5f;
148a40be09c443d15fcb080adde0ab9625e8a5af73dreed        while (mm->extractLevel(scale, &level)) {
149a40be09c443d15fcb080adde0ab9625e8a5af73dreed            SkImageInfo info = SkImageInfo::MakeN32Premul(level.fWidth, level.fHeight);
150a40be09c443d15fcb080adde0ab9625e8a5af73dreed            SkPixmap levelPM{ info, level.fPixels, level.fRowBytes };
151a40be09c443d15fcb080adde0ab9625e8a5af73dreed
152a40be09c443d15fcb080adde0ab9625e8a5af73dreed            SkBitmap bm = func(prevPM, levelPM);
153a40be09c443d15fcb080adde0ab9625e8a5af73dreed            DrawAndFrame(canvas, bm, x, y);
154a40be09c443d15fcb080adde0ab9625e8a5af73dreed
155a40be09c443d15fcb080adde0ab9625e8a5af73dreed            if (info.width() <= 2 || info.height() <= 2) {
156a40be09c443d15fcb080adde0ab9625e8a5af73dreed                break;
157a40be09c443d15fcb080adde0ab9625e8a5af73dreed            }
158a40be09c443d15fcb080adde0ab9625e8a5af73dreed            if (index & 1) {
159a40be09c443d15fcb080adde0ab9625e8a5af73dreed                x += info.width() + 4;
160a40be09c443d15fcb080adde0ab9625e8a5af73dreed            } else {
161a40be09c443d15fcb080adde0ab9625e8a5af73dreed                y += info.height() + 4;
162a40be09c443d15fcb080adde0ab9625e8a5af73dreed            }
163a40be09c443d15fcb080adde0ab9625e8a5af73dreed            scale /= 2;
164a40be09c443d15fcb080adde0ab9625e8a5af73dreed            prevPM = levelPM;
165a40be09c443d15fcb080adde0ab9625e8a5af73dreed            index += 1;
166a40be09c443d15fcb080adde0ab9625e8a5af73dreed        }
167a40be09c443d15fcb080adde0ab9625e8a5af73dreed    }
168a40be09c443d15fcb080adde0ab9625e8a5af73dreed
169a40be09c443d15fcb080adde0ab9625e8a5af73dreed    void drawSet(SkCanvas* canvas, const SkBitmap& orig) {
170a40be09c443d15fcb080adde0ab9625e8a5af73dreed        SkAutoCanvasRestore acr(canvas, true);
171a40be09c443d15fcb080adde0ab9625e8a5af73dreed
172a40be09c443d15fcb080adde0ab9625e8a5af73dreed        drawLevels(canvas, orig, [](const SkPixmap& prev, const SkPixmap& curr) {
173a40be09c443d15fcb080adde0ab9625e8a5af73dreed            SkBitmap bm;
174a40be09c443d15fcb080adde0ab9625e8a5af73dreed            bm.installPixels(curr);
175a40be09c443d15fcb080adde0ab9625e8a5af73dreed            return bm;
176a40be09c443d15fcb080adde0ab9625e8a5af73dreed        });
177a40be09c443d15fcb080adde0ab9625e8a5af73dreed
178a40be09c443d15fcb080adde0ab9625e8a5af73dreed        const SkBitmapScaler::ResizeMethod methods[] = {
179a40be09c443d15fcb080adde0ab9625e8a5af73dreed            SkBitmapScaler::RESIZE_BOX,
180a40be09c443d15fcb080adde0ab9625e8a5af73dreed            SkBitmapScaler::RESIZE_TRIANGLE,
181a40be09c443d15fcb080adde0ab9625e8a5af73dreed            SkBitmapScaler::RESIZE_LANCZOS3,
182a40be09c443d15fcb080adde0ab9625e8a5af73dreed            SkBitmapScaler::RESIZE_HAMMING,
183a40be09c443d15fcb080adde0ab9625e8a5af73dreed            SkBitmapScaler::RESIZE_MITCHELL,
184a40be09c443d15fcb080adde0ab9625e8a5af73dreed        };
185a40be09c443d15fcb080adde0ab9625e8a5af73dreed
186a40be09c443d15fcb080adde0ab9625e8a5af73dreed        SkPixmap basePM;
187a40be09c443d15fcb080adde0ab9625e8a5af73dreed        orig.lockPixels();
188a40be09c443d15fcb080adde0ab9625e8a5af73dreed        orig.peekPixels(&basePM);
189a40be09c443d15fcb080adde0ab9625e8a5af73dreed        for (auto method : methods) {
190a40be09c443d15fcb080adde0ab9625e8a5af73dreed            canvas->translate(orig.width()/2 + 8.0f, 0);
191a40be09c443d15fcb080adde0ab9625e8a5af73dreed            drawLevels(canvas, orig, [basePM, method](const SkPixmap& prev, const SkPixmap& curr) {
192a40be09c443d15fcb080adde0ab9625e8a5af73dreed                SkBitmap bm;
193a40be09c443d15fcb080adde0ab9625e8a5af73dreed                SkBitmapScaler::Resize(&bm, prev, method, curr.width(), curr.height());
194a40be09c443d15fcb080adde0ab9625e8a5af73dreed                return bm;
195a40be09c443d15fcb080adde0ab9625e8a5af73dreed            });
196a40be09c443d15fcb080adde0ab9625e8a5af73dreed        }
197a40be09c443d15fcb080adde0ab9625e8a5af73dreed    }
198a40be09c443d15fcb080adde0ab9625e8a5af73dreed
199a40be09c443d15fcb080adde0ab9625e8a5af73dreed    void onDraw(SkCanvas* canvas) override {
200a40be09c443d15fcb080adde0ab9625e8a5af73dreed        canvas->translate(4, 4);
201a40be09c443d15fcb080adde0ab9625e8a5af73dreed        for (const auto& bm : fBM) {
202a40be09c443d15fcb080adde0ab9625e8a5af73dreed            this->drawSet(canvas, bm);
203a40be09c443d15fcb080adde0ab9625e8a5af73dreed            canvas->translate(0, bm.height() * 0.85f);
204a40be09c443d15fcb080adde0ab9625e8a5af73dreed        }
205a40be09c443d15fcb080adde0ab9625e8a5af73dreed    }
206a40be09c443d15fcb080adde0ab9625e8a5af73dreed
207a40be09c443d15fcb080adde0ab9625e8a5af73dreedprivate:
208a40be09c443d15fcb080adde0ab9625e8a5af73dreed    typedef skiagm::GM INHERITED;
209a40be09c443d15fcb080adde0ab9625e8a5af73dreed};
210a40be09c443d15fcb080adde0ab9625e8a5af73dreedDEF_GM( return new ShowMipLevels(255); )
211a40be09c443d15fcb080adde0ab9625e8a5af73dreedDEF_GM( return new ShowMipLevels(256); )
212a40be09c443d15fcb080adde0ab9625e8a5af73dreed
213