OLD | NEW |
---|---|
1 | 1 |
2 /* | 2 /* |
3 * Copyright 2013 Google Inc. | 3 * Copyright 2013 Google Inc. |
4 * | 4 * |
5 * Use of this source code is governed by a BSD-style license that can be | 5 * Use of this source code is governed by a BSD-style license that can be |
6 * found in the LICENSE file. | 6 * found in the LICENSE file. |
7 */ | 7 */ |
8 | 8 |
9 | 9 |
10 #ifndef SkBitmapFilter_DEFINED | 10 #ifndef SkBitmapFilter_DEFINED |
11 #define SkBitmapFilter_DEFINED | 11 #define SkBitmapFilter_DEFINED |
12 | 12 |
13 #include <limits> | |
13 #include "SkMath.h" | 14 #include "SkMath.h" |
14 | 15 |
15 // size of the precomputed bitmap filter tables for high quality filtering. | 16 // size of the precomputed bitmap filter tables for high quality filtering. |
16 // Used to precompute the shape of the filter kernel. | 17 // Used to precompute the shape of the filter kernel. |
17 // Table size chosen from experiments to see where I could start to see a differ ence. | 18 // Table size chosen from experiments to see where I could start to see a differ ence. |
18 | 19 |
19 #define SKBITMAP_FILTER_TABLE_SIZE 128 | 20 #define SKBITMAP_FILTER_TABLE_SIZE 128 |
20 | 21 |
21 class SkBitmapFilter { | 22 class SkBitmapFilter { |
22 public: | 23 public: |
23 SkBitmapFilter(float width) | 24 SkBitmapFilter(float width) |
24 : fWidth(width), fInvWidth(1.f/width) { | 25 : fWidth(width), fInvWidth(1.f/width) { |
25 fPrecomputed = false; | 26 fPrecomputed = false; |
26 fLookupMultiplier = this->invWidth() * (SKBITMAP_FILTER_TABLE_SIZE-1); | 27 fLookupMultiplier = this->invWidth() * (SKBITMAP_FILTER_TABLE_SIZE-1); |
27 } | 28 } |
28 | 29 |
29 SkFixed lookup( float x ) const { | 30 SkFixed lookup(float x) const { |
30 if (!fPrecomputed) { | 31 if (!fPrecomputed) { |
31 precomputeTable(); | 32 precomputeTable(); |
32 } | 33 } |
33 int filter_idx = int(sk_float_abs(x * fLookupMultiplier)); | 34 int filter_idx = int(sk_float_abs(x * fLookupMultiplier)); |
34 SkASSERT(filter_idx < SKBITMAP_FILTER_TABLE_SIZE); | 35 SkASSERT(filter_idx < SKBITMAP_FILTER_TABLE_SIZE); |
35 return fFilterTable[ filter_idx ]; | 36 return fFilterTable[filter_idx]; |
36 } | 37 } |
37 | 38 |
38 SkScalar lookupScalar( float x ) const { | 39 SkScalar lookupScalar(float x) const { |
39 if (!fPrecomputed) { | 40 if (!fPrecomputed) { |
40 precomputeTable(); | 41 precomputeTable(); |
41 } | 42 } |
42 int filter_idx = int(sk_float_abs(x * fLookupMultiplier)); | 43 int filter_idx = int(sk_float_abs(x * fLookupMultiplier)); |
43 SkASSERT(filter_idx < SKBITMAP_FILTER_TABLE_SIZE); | 44 SkASSERT(filter_idx < SKBITMAP_FILTER_TABLE_SIZE); |
44 return fFilterTableScalar[ filter_idx ]; | 45 return fFilterTableScalar[filter_idx]; |
45 } | 46 } |
46 | 47 |
47 float width() const { return fWidth; } | 48 float width() const { return fWidth; } |
48 float invWidth() const { return fInvWidth; } | 49 float invWidth() const { return fInvWidth; } |
49 virtual float evaluate(float x) const = 0; | 50 virtual float evaluate(float x) const = 0; |
50 virtual ~SkBitmapFilter() {} | 51 virtual ~SkBitmapFilter() {} |
52 | |
53 static SkBitmapFilter *allocate(); | |
51 protected: | 54 protected: |
52 float fWidth; | 55 float fWidth; |
53 float fInvWidth; | 56 float fInvWidth; |
54 | 57 |
55 float fLookupMultiplier; | 58 float fLookupMultiplier; |
56 | 59 |
57 mutable bool fPrecomputed; | 60 mutable bool fPrecomputed; |
58 mutable SkFixed fFilterTable[SKBITMAP_FILTER_TABLE_SIZE]; | 61 mutable SkFixed fFilterTable[SKBITMAP_FILTER_TABLE_SIZE]; |
59 mutable SkScalar fFilterTableScalar[SKBITMAP_FILTER_TABLE_SIZE]; | 62 mutable SkScalar fFilterTableScalar[SKBITMAP_FILTER_TABLE_SIZE]; |
60 private: | 63 private: |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
119 protected: | 122 protected: |
120 }; | 123 }; |
121 | 124 |
122 class SkBoxFilter: public SkBitmapFilter { | 125 class SkBoxFilter: public SkBitmapFilter { |
123 public: | 126 public: |
124 SkBoxFilter(float width=0.5f) | 127 SkBoxFilter(float width=0.5f) |
125 : SkBitmapFilter(width) { | 128 : SkBitmapFilter(width) { |
126 } | 129 } |
127 | 130 |
128 virtual float evaluate(float x) const SK_OVERRIDE { | 131 virtual float evaluate(float x) const SK_OVERRIDE { |
129 return 1; | 132 return (x >= -fWidth && x < fWidth) ? 1.0f : 0.0f; |
130 } | 133 } |
131 protected: | 134 protected: |
132 }; | 135 }; |
133 | 136 |
137 class SkHammingFilter: public SkBitmapFilter { | |
138 public: | |
139 SkHammingFilter(float width=1.f) | |
140 : SkBitmapFilter(width) { | |
141 } | |
142 virtual float evaluate(float x) const { | |
143 if (x <= -fWidth || x >= fWidth) | |
144 return 0.0f; // Outside of the window. | |
145 if (x > -std::numeric_limits<float>::epsilon() && | |
146 x < std::numeric_limits<float>::epsilon()) | |
147 return 1.0f; // Special case the sinc discontinuity at the origin. | |
148 const float xpi = x * static_cast<float>(M_PI); | |
149 | |
150 return ((sin(xpi) / xpi) * // sinc(x) | |
reed1
2013/07/18 13:42:12
this is the double version of sin. Do you want sk_
humper
2013/07/18 17:11:04
Done.
| |
151 (0.54f + 0.46f * cos(xpi / fWidth))); // hamming(x) | |
152 } | |
153 }; | |
134 | 154 |
135 class SkSincFilter: public SkBitmapFilter { | 155 class SkSincFilter: public SkBitmapFilter { |
136 public: | 156 public: |
137 SkSincFilter(float t, float width=3.f) | 157 SkSincFilter(float width=3.f) |
138 : SkBitmapFilter(width), tau(t) { | 158 : SkBitmapFilter(width) { |
139 } | 159 } |
140 | 160 |
141 virtual float evaluate(float x) const SK_OVERRIDE { | 161 virtual float evaluate(float x) const SK_OVERRIDE { |
142 x = sk_float_abs(x * fInvWidth); | 162 if (x <= -fWidth || x >= fWidth) { |
143 if (x < 1e-5f) return 1.f; | 163 return 0.0f; // Outside of the window. |
144 if (x > 1.f) return 0.f; | 164 } |
145 x *= SK_ScalarPI; | 165 if (x > -std::numeric_limits<float>::epsilon() && |
146 float sinc = sk_float_sin(x) / x; | 166 x < std::numeric_limits<float>::epsilon()) { |
147 float lanczos = sk_float_sin(x * tau) / (x * tau); | 167 return 1.0f; // Special case the discontinuity at the origin. |
148 return sinc * lanczos; | 168 } |
149 } | 169 float xpi = x * static_cast<float>(M_PI); |
150 protected: | 170 return (sin(xpi) / xpi) * // sinc(x) |
reed1
2013/07/18 13:42:12
similar question about sin -vs- sk_float_sin
humper
2013/07/18 17:11:04
Done.
| |
151 float tau; | 171 sin(xpi / fWidth) / (xpi / fWidth); // sinc(x/filter_size) |
172 } | |
152 }; | 173 }; |
153 | 174 |
154 | 175 |
155 #endif | 176 #endif |
OLD | NEW |