| 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 "SkMath.h" | 13 #include "SkMath.h" |
| 14 | 14 |
| 15 // size of the precomputed bitmap filter tables for high quality filtering. | 15 // size of the precomputed bitmap filter tables for high quality filtering. |
| 16 // Used to precompute the shape of the filter kernel. | 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 differ
ence. | 17 // Table size chosen from experiments to see where I could start to see a differ
ence. |
| 18 | 18 |
| 19 #define SKBITMAP_FILTER_TABLE_SIZE 128 | 19 #define SKBITMAP_FILTER_TABLE_SIZE 128 |
| 20 | 20 |
| 21 class SkBitmapFilter { | 21 class SkBitmapFilter { |
| 22 public: | 22 public: |
| 23 SkBitmapFilter(float width) | 23 SkBitmapFilter(float width) |
| 24 : fWidth(width), fInvWidth(1.f/width) { | 24 : fWidth(width), fInvWidth(1.f/width) { |
| 25 fPrecomputed = false; | 25 fPrecomputed = false; |
| 26 fLookupMultiplier = this->invWidth() * (SKBITMAP_FILTER_TABLE_SIZE-1); | 26 fLookupMultiplier = this->invWidth() * (SKBITMAP_FILTER_TABLE_SIZE-1); |
| 27 } | 27 } |
| 28 | 28 |
| 29 SkFixed lookup( float x ) const { | 29 SkFixed lookup(float x) const { |
| 30 if (!fPrecomputed) { | 30 if (!fPrecomputed) { |
| 31 precomputeTable(); | 31 precomputeTable(); |
| 32 } | 32 } |
| 33 int filter_idx = int(sk_float_abs(x * fLookupMultiplier)); | 33 int filter_idx = int(sk_float_abs(x * fLookupMultiplier)); |
| 34 SkASSERT(filter_idx < SKBITMAP_FILTER_TABLE_SIZE); | 34 SkASSERT(filter_idx < SKBITMAP_FILTER_TABLE_SIZE); |
| 35 return fFilterTable[ filter_idx ]; | 35 return fFilterTable[filter_idx]; |
| 36 } | 36 } |
| 37 | 37 |
| 38 SkScalar lookupScalar( float x ) const { | 38 SkScalar lookupScalar(float x) const { |
| 39 if (!fPrecomputed) { | 39 if (!fPrecomputed) { |
| 40 precomputeTable(); | 40 precomputeTable(); |
| 41 } | 41 } |
| 42 int filter_idx = int(sk_float_abs(x * fLookupMultiplier)); | 42 int filter_idx = int(sk_float_abs(x * fLookupMultiplier)); |
| 43 SkASSERT(filter_idx < SKBITMAP_FILTER_TABLE_SIZE); | 43 SkASSERT(filter_idx < SKBITMAP_FILTER_TABLE_SIZE); |
| 44 return fFilterTableScalar[ filter_idx ]; | 44 return fFilterTableScalar[filter_idx]; |
| 45 } | 45 } |
| 46 | 46 |
| 47 float width() const { return fWidth; } | 47 float width() const { return fWidth; } |
| 48 float invWidth() const { return fInvWidth; } | 48 float invWidth() const { return fInvWidth; } |
| 49 virtual float evaluate(float x) const = 0; | 49 virtual float evaluate(float x) const = 0; |
| 50 virtual ~SkBitmapFilter() {} | 50 virtual ~SkBitmapFilter() {} |
| 51 |
| 52 static SkBitmapFilter* Allocate(); |
| 51 protected: | 53 protected: |
| 52 float fWidth; | 54 float fWidth; |
| 53 float fInvWidth; | 55 float fInvWidth; |
| 54 | 56 |
| 55 float fLookupMultiplier; | 57 float fLookupMultiplier; |
| 56 | 58 |
| 57 mutable bool fPrecomputed; | 59 mutable bool fPrecomputed; |
| 58 mutable SkFixed fFilterTable[SKBITMAP_FILTER_TABLE_SIZE]; | 60 mutable SkFixed fFilterTable[SKBITMAP_FILTER_TABLE_SIZE]; |
| 59 mutable SkScalar fFilterTableScalar[SKBITMAP_FILTER_TABLE_SIZE]; | 61 mutable SkScalar fFilterTableScalar[SKBITMAP_FILTER_TABLE_SIZE]; |
| 60 private: | 62 private: |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 119 protected: | 121 protected: |
| 120 }; | 122 }; |
| 121 | 123 |
| 122 class SkBoxFilter: public SkBitmapFilter { | 124 class SkBoxFilter: public SkBitmapFilter { |
| 123 public: | 125 public: |
| 124 SkBoxFilter(float width=0.5f) | 126 SkBoxFilter(float width=0.5f) |
| 125 : SkBitmapFilter(width) { | 127 : SkBitmapFilter(width) { |
| 126 } | 128 } |
| 127 | 129 |
| 128 virtual float evaluate(float x) const SK_OVERRIDE { | 130 virtual float evaluate(float x) const SK_OVERRIDE { |
| 129 return 1; | 131 return (x >= -fWidth && x < fWidth) ? 1.0f : 0.0f; |
| 130 } | 132 } |
| 131 protected: | 133 protected: |
| 132 }; | 134 }; |
| 133 | 135 |
| 136 class SkHammingFilter: public SkBitmapFilter { |
| 137 public: |
| 138 SkHammingFilter(float width=1.f) |
| 139 : SkBitmapFilter(width) { |
| 140 } |
| 141 virtual float evaluate(float x) const SK_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>(M_PI); |
| 134 | 149 |
| 135 class SkSincFilter: public SkBitmapFilter { | 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 { |
| 136 public: | 156 public: |
| 137 SkSincFilter(float t, float width=3.f) | 157 SkLanczosFilter(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 > -FLT_EPSILON && x < FLT_EPSILON) { |
| 146 float sinc = sk_float_sin(x) / x; | 166 return 1.0f; // Special case the discontinuity at the origin. |
| 147 float lanczos = sk_float_sin(x * tau) / (x * tau); | 167 } |
| 148 return sinc * lanczos; | 168 float xpi = x * static_cast<float>(M_PI); |
| 149 } | 169 return (sk_float_sin(xpi) / xpi) * // sinc(x) |
| 150 protected: | 170 sk_float_sin(xpi / fWidth) / (xpi / fWidth); // sinc(x/fWidth
) |
| 151 float tau; | 171 } |
| 152 }; | 172 }; |
| 153 | 173 |
| 154 | 174 |
| 155 #endif | 175 #endif |
| OLD | NEW |