• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1  /*
2   * Copyright 2015 Google Inc.
3   *
4   * Use of this source code is governed by a BSD-style license that can be
5   * found in the LICENSE file.
6   */
7  
8  #include "gm/gm.h"
9  #include "include/core/SkBitmap.h"
10  #include "include/core/SkCanvas.h"
11  #include "include/core/SkColorSpace.h"
12  #include "include/core/SkImage.h"
13  #include "include/core/SkImageInfo.h"
14  #include "include/core/SkPaint.h"
15  #include "include/core/SkRect.h"
16  #include "include/core/SkRefCnt.h"
17  #include "include/core/SkString.h"
18  #include "include/core/SkSurface.h"
19  #include "include/core/SkTypes.h"
20  
make_image()21  static sk_sp<SkImage> make_image() {
22      const SkImageInfo info = SkImageInfo::MakeN32Premul(319, 52);
23      auto surface(SkSurface::MakeRaster(info));
24      SkCanvas* canvas = surface->getCanvas();
25      canvas->drawColor(0xFFF8F8F8);
26  
27      SkPaint paint;
28      paint.setAntiAlias(true);
29  
30      paint.setStyle(SkPaint::kStroke_Style);
31      for (int i = 0; i < 20; ++i) {
32          canvas->drawCircle(-4, 25, 20, paint);
33          canvas->translate(25, 0);
34      }
35      return surface->makeImageSnapshot();
36  }
37  
38  DEF_SIMPLE_GM(mipmap, canvas, 400, 200) {
39      sk_sp<SkImage> img(make_image());//SkImage::NewFromEncoded(data));
40  
41      const SkRect dst = SkRect::MakeWH(177, 15);
42  
43      SkString str;
44      str.printf("scale %g %g", dst.width() / img->width(), dst.height() / img->height());
45  //    canvas->drawString(str, 300, 100, SkFont(nullptr, 30), paint);
46  
47      const SkSamplingOptions samplings[] = {
48          SkSamplingOptions(SkFilterMode::kNearest),
49          SkSamplingOptions(SkFilterMode::kLinear),
50          SkSamplingOptions(SkFilterMode::kLinear, SkMipmapMode::kLinear),
51          SkSamplingOptions(SkCubicResampler::Mitchell()),
52      };
53  
54      canvas->translate(20, 20);
55      for (size_t i = 0; i < SK_ARRAY_COUNT(samplings); ++i) {
56          canvas->drawImageRect(img.get(), dst, samplings[i], nullptr);
57          canvas->translate(0, 20);
58      }
59      canvas->drawImage(img.get(), 20, 20);
60  }
61  
62  ///////////////////////////////////////////////////////////////////////////////////////////////////
63  
64  // create a circle image computed raw, so we can wrap it as a linear or srgb image
make(sk_sp<SkColorSpace> cs)65  static sk_sp<SkImage> make(sk_sp<SkColorSpace> cs) {
66      const int N = 100;
67      SkImageInfo info = SkImageInfo::Make(N, N, kN32_SkColorType, kPremul_SkAlphaType, cs);
68      SkBitmap bm;
69      bm.allocPixels(info);
70  
71      for (int y = 0; y < N; ++y) {
72          for (int x = 0; x < N; ++x) {
73              *bm.getAddr32(x, y) = (x ^ y) & 1 ? 0xFFFFFFFF : 0xFF000000;
74          }
75      }
76      bm.setImmutable();
77      return bm.asImage();
78  }
79  
show_mips(SkCanvas * canvas,SkImage * img)80  static void show_mips(SkCanvas* canvas, SkImage* img) {
81      SkSamplingOptions sampling(SkFilterMode::kLinear,
82                                 SkMipmapMode::kLinear);
83  
84      // Want to ensure we never draw fractional pixels, so we use an IRect
85      SkIRect dst = SkIRect::MakeWH(img->width(), img->height());
86      while (dst.width() > 5) {
87          canvas->drawImageRect(img, SkRect::Make(dst), sampling, nullptr);
88          dst.offset(dst.width() + 10, 0);
89          dst.fRight = dst.fLeft + dst.width()/2;
90          dst.fBottom = dst.fTop + dst.height()/2;
91      }
92  }
93  
94  /*
95   *  Ensure that in L32 drawing mode, both images/mips look the same as each other, and
96   *  their mips are darker than the original (since the mips should ignore the gamma in L32).
97   *
98   *  Ensure that in S32 drawing mode, all images/mips look the same, and look correct (i.e.
99   *  the mip levels match the original in brightness).
100   */
101  DEF_SIMPLE_GM(mipmap_srgb, canvas, 260, 230) {
102      sk_sp<SkImage> limg = make(nullptr);
103      sk_sp<SkImage> simg = make(SkColorSpace::MakeSRGB());
104  
105      canvas->translate(10, 10);
106      show_mips(canvas, limg.get());
107      canvas->translate(0, limg->height() + 10.0f);
108      show_mips(canvas, simg.get());
109  }
110  
111  ///////////////////////////////////////////////////////////////////////////////////////////////////
112  
113  // create a gradient image computed raw, so we can wrap it as a linear or srgb image
make_g8_gradient(sk_sp<SkColorSpace> cs)114  static sk_sp<SkImage> make_g8_gradient(sk_sp<SkColorSpace> cs) {
115      const int N = 100;
116      SkImageInfo info = SkImageInfo::Make(N, N, kGray_8_SkColorType, kOpaque_SkAlphaType, cs);
117      SkBitmap bm;
118      bm.allocPixels(info);
119  
120      for (int y = 0; y < N; ++y) {
121          for (int x = 0; x < N; ++x) {
122              *bm.getAddr8(x, y) = static_cast<uint8_t>(255.0f * ((x + y) / (2.0f * (N - 1))));
123          }
124      }
125      bm.setImmutable();
126      return bm.asImage();
127  }
128  
show_mips_only(SkCanvas * canvas,SkImage * img)129  static void show_mips_only(SkCanvas* canvas, SkImage* img) {
130      SkSamplingOptions sampling(SkFilterMode::kLinear,
131                                 SkMipmapMode::kLinear);
132  
133      // Want to ensure we never draw fractional pixels, so we use an IRect
134      SkIRect dst = SkIRect::MakeWH(img->width() / 2, img->height() / 2);
135      while (dst.width() > 5) {
136          canvas->drawImageRect(img, SkRect::Make(dst), sampling, nullptr);
137          dst.offset(dst.width() + 10, 0);
138          dst.fRight = dst.fLeft + dst.width() / 2;
139          dst.fBottom = dst.fTop + dst.height() / 2;
140      }
141  }
142  
143  /*
144   *  Ensure that in L32 drawing mode, both images/mips look the same as each other, and
145   *  their mips are darker than the original (since the mips should ignore the gamma in L32).
146   *
147   *  Ensure that in S32 drawing mode, all images/mips look the same, and look correct (i.e.
148   *  the mip levels match the original in brightness).
149   */
150  DEF_SIMPLE_GM(mipmap_gray8_srgb, canvas, 260, 230) {
151      sk_sp<SkImage> limg = make_g8_gradient(nullptr);
152      sk_sp<SkImage> simg = make_g8_gradient(SkColorSpace::MakeSRGB());
153  
154      canvas->translate(10, 10);
155      show_mips_only(canvas, limg.get());
156      canvas->translate(0, limg->height() + 10.0f);
157      show_mips_only(canvas, simg.get());
158  }
159