| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2013 Google Inc. | 2 * Copyright 2013 Google Inc. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
| 5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
| 6 */ | 6 */ |
| 7 | 7 |
| 8 #ifndef SkBitmapFilter_DEFINED | 8 #ifndef SkBitmapFilter_DEFINED |
| 9 #define SkBitmapFilter_DEFINED | 9 #define SkBitmapFilter_DEFINED |
| 10 | 10 |
| 11 #include "SkFixed.h" | 11 #include "SkFixed.h" |
| 12 #include "SkMath.h" | 12 #include "SkMath.h" |
| 13 #include "SkScalar.h" | 13 #include "SkScalar.h" |
| 14 | 14 |
| 15 #ifndef SK_SUPPORT_LEGACY_BITMAP_FILTER |
| 16 #include "SkNx.h" |
| 17 #endif |
| 18 |
| 15 // size of the precomputed bitmap filter tables for high quality filtering. | 19 // size of the precomputed bitmap filter tables for high quality filtering. |
| 16 // Used to precompute the shape of the filter kernel. | 20 // 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. | 21 // Table size chosen from experiments to see where I could start to see a differ
ence. |
| 18 | 22 |
| 19 #define SKBITMAP_FILTER_TABLE_SIZE 128 | 23 #define SKBITMAP_FILTER_TABLE_SIZE 128 |
| 20 | 24 |
| 21 class SkBitmapFilter { | 25 class SkBitmapFilter { |
| 22 public: | 26 public: |
| 23 SkBitmapFilter(float width) | 27 SkBitmapFilter(float width) |
| 24 : fWidth(width), fInvWidth(1.f/width) { | 28 : fWidth(width), fInvWidth(1.f/width) { |
| (...skipping 15 matching lines...) Expand all Loading... |
| 40 precomputeTable(); | 44 precomputeTable(); |
| 41 } | 45 } |
| 42 int filter_idx = int(sk_float_abs(x * fLookupMultiplier)); | 46 int filter_idx = int(sk_float_abs(x * fLookupMultiplier)); |
| 43 SkASSERT(filter_idx < SKBITMAP_FILTER_TABLE_SIZE); | 47 SkASSERT(filter_idx < SKBITMAP_FILTER_TABLE_SIZE); |
| 44 return fFilterTableScalar[filter_idx]; | 48 return fFilterTableScalar[filter_idx]; |
| 45 } | 49 } |
| 46 | 50 |
| 47 float width() const { return fWidth; } | 51 float width() const { return fWidth; } |
| 48 float invWidth() const { return fInvWidth; } | 52 float invWidth() const { return fInvWidth; } |
| 49 virtual float evaluate(float x) const = 0; | 53 virtual float evaluate(float x) const = 0; |
| 54 |
| 55 #ifndef SK_SUPPORT_LEGACY_BITMAP_FILTER |
| 56 virtual float evaluate_n(float val, float diff, int count, float* output)
const { |
| 57 float sum = 0; |
| 58 for (int index = 0; index < count; index++) { |
| 59 float filterValue = evaluate(val); |
| 60 *output++ = filterValue; |
| 61 sum += filterValue; |
| 62 val += diff; |
| 63 } |
| 64 return sum; |
| 65 } |
| 66 #endif |
| 67 |
| 50 virtual ~SkBitmapFilter() {} | 68 virtual ~SkBitmapFilter() {} |
| 51 | 69 |
| 52 static SkBitmapFilter* Allocate(); | 70 static SkBitmapFilter* Allocate(); |
| 53 protected: | 71 protected: |
| 54 float fWidth; | 72 float fWidth; |
| 55 float fInvWidth; | 73 float fInvWidth; |
| 56 | 74 |
| 57 float fLookupMultiplier; | 75 float fLookupMultiplier; |
| 58 | 76 |
| 59 mutable bool fPrecomputed; | 77 mutable bool fPrecomputed; |
| 60 mutable SkFixed fFilterTable[SKBITMAP_FILTER_TABLE_SIZE]; | 78 mutable SkFixed fFilterTable[SKBITMAP_FILTER_TABLE_SIZE]; |
| 61 mutable SkScalar fFilterTableScalar[SKBITMAP_FILTER_TABLE_SIZE]; | 79 mutable SkScalar fFilterTableScalar[SKBITMAP_FILTER_TABLE_SIZE]; |
| 62 private: | 80 private: |
| 63 void precomputeTable() const { | 81 void precomputeTable() const { |
| 64 fPrecomputed = true; | 82 fPrecomputed = true; |
| 65 SkFixed *ftp = fFilterTable; | 83 SkFixed *ftp = fFilterTable; |
| 66 SkScalar *ftpScalar = fFilterTableScalar; | 84 SkScalar *ftpScalar = fFilterTableScalar; |
| 67 for (int x = 0; x < SKBITMAP_FILTER_TABLE_SIZE; ++x) { | 85 for (int x = 0; x < SKBITMAP_FILTER_TABLE_SIZE; ++x) { |
| 68 float fx = ((float)x + .5f) * this->width() / SKBITMAP_FILTER_TABL
E_SIZE; | 86 float fx = ((float)x + .5f) * this->width() / SKBITMAP_FILTER_TABL
E_SIZE; |
| 69 float filter_value = evaluate(fx); | 87 float filter_value = evaluate(fx); |
| 70 *ftpScalar++ = filter_value; | 88 *ftpScalar++ = filter_value; |
| 71 *ftp++ = SkFloatToFixed(filter_value); | 89 *ftp++ = SkFloatToFixed(filter_value); |
| 72 } | 90 } |
| 73 } | 91 } |
| 74 }; | 92 }; |
| 75 | 93 |
| 76 class SkMitchellFilter: public SkBitmapFilter { | 94 class SkMitchellFilter : public SkBitmapFilter { |
| 77 public: | 95 public: |
| 78 SkMitchellFilter(float b, float c, float width=2.0f) | 96 #ifdef SK_SUPPORT_LEGACY_BITMAP_FILTER |
| 79 : SkBitmapFilter(width), B(b), C(c) { | 97 SkMitchellFilter() |
| 98 : INHERITED(2), B(1.f / 3), C(1.f / 3) { |
| 80 } | 99 } |
| 100 #else |
| 101 SkMitchellFilter() |
| 102 : INHERITED(2) |
| 103 , fB(1.f / 3.f) |
| 104 , fC(1.f / 3.f) |
| 105 , fA1(-fB - 6*fC) |
| 106 , fB1(6*fB + 30*fC) |
| 107 , fC1(-12*fB - 48*fC) |
| 108 , fD1(8*fB + 24*fC) |
| 109 , fA2(12 - 9*fB - 6*fC) |
| 110 , fB2(-18 + 12*fB + 6*fC) |
| 111 , fD2(6 - 2*fB) { |
| 112 } |
| 113 #endif |
| 81 | 114 |
| 82 float evaluate(float x) const override { | 115 float evaluate(float x) const override { |
| 83 x = fabsf(x); | 116 x = fabsf(x); |
| 84 if (x > 2.f) { | 117 if (x > 2.f) { |
| 85 return 0; | 118 return 0; |
| 86 } else if (x > 1.f) { | 119 } else if (x > 1.f) { |
| 120 #ifdef SK_SUPPORT_LEGACY_BITMAP_FILTER |
| 87 return ((-B - 6*C) * x*x*x + (6*B + 30*C) * x*x + | 121 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); | 122 (-12*B - 48*C) * x + (8*B + 24*C)) * (1.f/6.f); |
| 123 #else |
| 124 return (((fA1 * x + fB1) * x + fC1) * x + fD1) * (1.f/6.f); |
| 125 #endif |
| 89 } else { | 126 } else { |
| 127 #ifdef SK_SUPPORT_LEGACY_BITMAP_FILTER |
| 90 return ((12 - 9*B - 6*C) * x*x*x + | 128 return ((12 - 9*B - 6*C) * x*x*x + |
| 91 (-18 + 12*B + 6*C) * x*x + | 129 (-18 + 12*B + 6*C) * x*x + |
| 92 (6 - 2*B)) * (1.f/6.f); | 130 (6 - 2*B)) * (1.f/6.f); |
| 131 #else |
| 132 return ((fA2 * x + fB2) * x*x + fD2) * (1.f/6.f); |
| 133 #endif |
| 93 } | 134 } |
| 94 } | 135 } |
| 136 |
| 137 #ifndef SK_SUPPORT_LEGACY_BITMAP_FILTER |
| 138 // TODO : native Sk4f abs |
| 139 static Sk4f abs(const Sk4f& x) { |
| 140 Sk4f neg = x < Sk4f(0); |
| 141 return neg.thenElse(Sk4f(0) - x, x); |
| 142 } |
| 143 |
| 144 Sk4f evalcore_n(const Sk4f& val) const { |
| 145 Sk4f x = abs(val); |
| 146 Sk4f over2 = x > Sk4f(2); |
| 147 Sk4f over1 = x > Sk4f(1); |
| 148 Sk4f poly1 = (((Sk4f(fA1) * x + Sk4f(fB1)) * x + Sk4f(fC1)) * x + Sk4f
(fD1)) |
| 149 * Sk4f(1.f/6.f); |
| 150 Sk4f poly0 = ((Sk4f(fA2) * x + Sk4f(fB2)) * x*x + Sk4f(fD2)) * Sk4f(1.
f/6.f); |
| 151 return over2.thenElse(Sk4f(0), over1.thenElse(poly1, poly0)); |
| 152 } |
| 153 |
| 154 float evaluate_n(float val, float diff, int count, float* output) const ov
erride { |
| 155 Sk4f sum(0); |
| 156 while (count >= 4) { |
| 157 float v0 = val; |
| 158 float v1 = val += diff; |
| 159 float v2 = val += diff; |
| 160 float v3 = val += diff; |
| 161 val += diff; |
| 162 Sk4f filterValue = evalcore_n(Sk4f(v0, v1, v2, v3)); |
| 163 filterValue.store(output); |
| 164 output += 4; |
| 165 sum = sum + filterValue; |
| 166 count -= 4; |
| 167 } |
| 168 float sums[4]; |
| 169 sum.store(sums); |
| 170 float result = sums[0] + sums[1] + sums[2] + sums[3]; |
| 171 result += INHERITED::evaluate_n(val, diff, count, output); |
| 172 return result; |
| 173 } |
| 174 #endif |
| 175 |
| 95 protected: | 176 protected: |
| 177 #ifdef SK_SUPPORT_LEGACY_BITMAP_FILTER |
| 96 float B, C; | 178 float B, C; |
| 179 #else |
| 180 float fB, fC; |
| 181 float fA1, fB1, fC1, fD1; |
| 182 float fA2, fB2, fD2; |
| 183 #endif |
| 184 private: |
| 185 typedef SkBitmapFilter INHERITED; |
| 97 }; | 186 }; |
| 98 | 187 |
| 99 class SkGaussianFilter: public SkBitmapFilter { | 188 class SkGaussianFilter: public SkBitmapFilter { |
| 100 public: | 189 public: |
| 101 SkGaussianFilter(float a, float width=2.0f) | 190 SkGaussianFilter(float a, float width=2.0f) |
| 102 : SkBitmapFilter(width), alpha(a), expWidth(expf(-alpha * width * width))
{ | 191 : SkBitmapFilter(width), alpha(a), expWidth(expf(-alpha * width * width))
{ |
| 103 } | 192 } |
| 104 | 193 |
| 105 float evaluate(float x) const override { | 194 float evaluate(float x) const override { |
| 106 return SkTMax(0.f, float(expf(-alpha*x*x) - expWidth)); | 195 return SkTMax(0.f, float(expf(-alpha*x*x) - expWidth)); |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 166 return 1.0f; // Special case the discontinuity at the origin. | 255 return 1.0f; // Special case the discontinuity at the origin. |
| 167 } | 256 } |
| 168 float xpi = x * static_cast<float>(SK_ScalarPI); | 257 float xpi = x * static_cast<float>(SK_ScalarPI); |
| 169 return (sk_float_sin(xpi) / xpi) * // sinc(x) | 258 return (sk_float_sin(xpi) / xpi) * // sinc(x) |
| 170 sk_float_sin(xpi / fWidth) / (xpi / fWidth); // sinc(x/fWidth
) | 259 sk_float_sin(xpi / fWidth) / (xpi / fWidth); // sinc(x/fWidth
) |
| 171 } | 260 } |
| 172 }; | 261 }; |
| 173 | 262 |
| 174 | 263 |
| 175 #endif | 264 #endif |
| OLD | NEW |