• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 
2 /*
3  * Copyright 2013 Google Inc.
4  *
5  * Use of this source code is governed by a BSD-style license that can be
6  * found in the LICENSE file.
7  */
8 
9 
10 #ifndef SkBitmapFilter_DEFINED
11 #define SkBitmapFilter_DEFINED
12 
13 #include "SkMath.h"
14 
15 // size of the precomputed bitmap filter tables for high quality filtering.
16 // Used to precompute the shape of the filter kernel.
17 // Table size chosen from experiments to see where I could start to see a difference.
18 
19 #define SKBITMAP_FILTER_TABLE_SIZE 128
20 
21 class SkBitmapFilter {
22   public:
SkBitmapFilter(float width)23       SkBitmapFilter(float width)
24       : fWidth(width), fInvWidth(1.f/width) {
25           fPrecomputed = false;
26           fLookupMultiplier = this->invWidth() * (SKBITMAP_FILTER_TABLE_SIZE-1);
27       }
28 
lookup(float x)29       SkFixed lookup(float x) const {
30           if (!fPrecomputed) {
31               precomputeTable();
32           }
33           int filter_idx = int(sk_float_abs(x * fLookupMultiplier));
34           SkASSERT(filter_idx < SKBITMAP_FILTER_TABLE_SIZE);
35           return fFilterTable[filter_idx];
36       }
37 
lookupScalar(float x)38       SkScalar lookupScalar(float x) const {
39           if (!fPrecomputed) {
40               precomputeTable();
41           }
42           int filter_idx = int(sk_float_abs(x * fLookupMultiplier));
43           SkASSERT(filter_idx < SKBITMAP_FILTER_TABLE_SIZE);
44           return fFilterTableScalar[filter_idx];
45       }
46 
width()47       float width() const { return fWidth; }
invWidth()48       float invWidth() const { return fInvWidth; }
49       virtual float evaluate(float x) const = 0;
~SkBitmapFilter()50       virtual ~SkBitmapFilter() {}
51 
52       static SkBitmapFilter* Allocate();
53   protected:
54       float fWidth;
55       float fInvWidth;
56 
57       float fLookupMultiplier;
58 
59       mutable bool fPrecomputed;
60       mutable SkFixed fFilterTable[SKBITMAP_FILTER_TABLE_SIZE];
61       mutable SkScalar fFilterTableScalar[SKBITMAP_FILTER_TABLE_SIZE];
62   private:
precomputeTable()63       void precomputeTable() const {
64           fPrecomputed = true;
65           SkFixed *ftp = fFilterTable;
66           SkScalar *ftpScalar = fFilterTableScalar;
67           for (int x = 0; x < SKBITMAP_FILTER_TABLE_SIZE; ++x) {
68               float fx = ((float)x + .5f) * this->width() / SKBITMAP_FILTER_TABLE_SIZE;
69               float filter_value = evaluate(fx);
70               *ftpScalar++ = filter_value;
71               *ftp++ = SkFloatToFixed(filter_value);
72           }
73       }
74 };
75 
76 class SkMitchellFilter: public SkBitmapFilter {
77   public:
78       SkMitchellFilter(float b, float c, float width=2.0f)
SkBitmapFilter(width)79       : SkBitmapFilter(width), B(b), C(c) {
80       }
81 
evaluate(float x)82       float evaluate(float x) const override {
83           x = fabsf(x);
84           if (x > 2.f) {
85               return 0;
86           } else if (x > 1.f) {
87               return ((-B - 6*C) * x*x*x + (6*B + 30*C) * x*x +
88                       (-12*B - 48*C) * x + (8*B + 24*C)) * (1.f/6.f);
89           } else {
90               return ((12 - 9*B - 6*C) * x*x*x +
91                       (-18 + 12*B + 6*C) * x*x +
92                       (6 - 2*B)) * (1.f/6.f);
93           }
94       }
95   protected:
96       float B, C;
97 };
98 
99 class SkGaussianFilter: public SkBitmapFilter {
100   public:
101       SkGaussianFilter(float a, float width=2.0f)
SkBitmapFilter(width)102       : SkBitmapFilter(width), alpha(a), expWidth(expf(-alpha * width * width)) {
103       }
104 
evaluate(float x)105       float evaluate(float x) const override {
106           return SkTMax(0.f, float(expf(-alpha*x*x) - expWidth));
107       }
108   protected:
109       float alpha, expWidth;
110 };
111 
112 class SkTriangleFilter: public SkBitmapFilter {
113   public:
114       SkTriangleFilter(float width=1)
SkBitmapFilter(width)115       : SkBitmapFilter(width) {
116       }
117 
evaluate(float x)118       float evaluate(float x) const override {
119           return SkTMax(0.f, fWidth - fabsf(x));
120       }
121   protected:
122 };
123 
124 class SkBoxFilter: public SkBitmapFilter {
125   public:
126       SkBoxFilter(float width=0.5f)
SkBitmapFilter(width)127       : SkBitmapFilter(width) {
128       }
129 
evaluate(float x)130       float evaluate(float x) const override {
131           return (x >= -fWidth && x < fWidth) ? 1.0f : 0.0f;
132       }
133   protected:
134 };
135 
136 class SkHammingFilter: public SkBitmapFilter {
137 public:
138     SkHammingFilter(float width=1.f)
SkBitmapFilter(width)139     : SkBitmapFilter(width) {
140     }
evaluate(float x)141     float evaluate(float x) const override {
142         if (x <= -fWidth || x >= fWidth) {
143             return 0.0f;  // Outside of the window.
144         }
145         if (x > -FLT_EPSILON && x < FLT_EPSILON) {
146             return 1.0f;  // Special case the sinc discontinuity at the origin.
147         }
148         const float xpi = x * static_cast<float>(SK_ScalarPI);
149 
150         return ((sk_float_sin(xpi) / xpi) *  // sinc(x)
151                 (0.54f + 0.46f * sk_float_cos(xpi / fWidth)));  // hamming(x)
152     }
153 };
154 
155 class SkLanczosFilter: public SkBitmapFilter {
156   public:
157       SkLanczosFilter(float width=3.f)
SkBitmapFilter(width)158       : SkBitmapFilter(width) {
159       }
160 
evaluate(float x)161       float evaluate(float x) const override {
162           if (x <= -fWidth || x >= fWidth) {
163               return 0.0f;  // Outside of the window.
164           }
165           if (x > -FLT_EPSILON && x < FLT_EPSILON) {
166               return 1.0f;  // Special case the discontinuity at the origin.
167           }
168           float xpi = x * static_cast<float>(SK_ScalarPI);
169           return (sk_float_sin(xpi) / xpi) *  // sinc(x)
170                   sk_float_sin(xpi / fWidth) / (xpi / fWidth);  // sinc(x/fWidth)
171       }
172 };
173 
174 
175 #endif
176