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