| Index: src/core/SkBitmapFilter.h
|
| diff --git a/src/core/SkBitmapFilter.h b/src/core/SkBitmapFilter.h
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..4e4778876c6e8a1491d83186afda157e49f167f7
|
| --- /dev/null
|
| +++ b/src/core/SkBitmapFilter.h
|
| @@ -0,0 +1,150 @@
|
| +
|
| +/*
|
| + * Copyright 2013 Google Inc.
|
| + *
|
| + * Use of this source code is governed by a BSD-style license that can be
|
| + * found in the LICENSE file.
|
| + */
|
| +
|
| +
|
| +#ifndef SkBitmapFilter_DEFINED
|
| +#define SkBitmapFilter_DEFINED
|
| +
|
| +#include "SkMath.h"
|
| +
|
| +// size of the precomputed bitmap filter tables for high quality filtering.
|
| +// Used to precompute the shape of the filter kernel.
|
| +// Table size chosen from experiments to see where I could start to see a difference.
|
| +
|
| +#define SKBITMAP_FILTER_TABLE_SIZE 32
|
| +
|
| +class SkBitmapFilter {
|
| + public:
|
| + SkBitmapFilter(float width)
|
| + : fWidth(width), fInvWidth(1.f/width) {
|
| + precomputed = false;
|
| + }
|
| +
|
| + SkFixed lookup( float x ) const {
|
| + if (!precomputed) {
|
| + precomputeTable();
|
| + }
|
| + int filter_idx = int(fabsf(x * invWidth() * SKBITMAP_FILTER_TABLE_SIZE));
|
| + return fFilterTable[ SkTMin(filter_idx, SKBITMAP_FILTER_TABLE_SIZE-1) ];
|
| + }
|
| +
|
| + SkFixed lookupFloat( float x ) const {
|
| + if (!precomputed) {
|
| + precomputeTable();
|
| + }
|
| + int filter_idx = int(fabsf(x * invWidth() * SKBITMAP_FILTER_TABLE_SIZE));
|
| + return fFilterTableFloat[ SkTMin(filter_idx, SKBITMAP_FILTER_TABLE_SIZE-1) ];
|
| + }
|
| +
|
| + float width() const { return fWidth; }
|
| + float invWidth() const { return fInvWidth; }
|
| + virtual float evaluate(float x) const = 0;
|
| + protected:
|
| + float fWidth;
|
| + float fInvWidth;
|
| +
|
| + mutable bool precomputed;
|
| + mutable SkFixed fFilterTable[SKBITMAP_FILTER_TABLE_SIZE];
|
| + mutable float fFilterTableFloat[SKBITMAP_FILTER_TABLE_SIZE];
|
| + private:
|
| + void precomputeTable() const {
|
| + precomputed = true;
|
| + SkFixed *ftp = fFilterTable;
|
| + float *ftp_float = fFilterTableFloat;
|
| + for (int x = 0; x < SKBITMAP_FILTER_TABLE_SIZE; ++x) {
|
| + float fx = ((float)x + .5f) * this->width() / SKBITMAP_FILTER_TABLE_SIZE;
|
| + float filter_value = evaluate(fx);
|
| + *ftp_float++ = filter_value;
|
| + *ftp++ = SkFloatToFixed(filter_value);
|
| + }
|
| + }
|
| +};
|
| +
|
| +class SkMitchellFilter: public SkBitmapFilter {
|
| + public:
|
| + SkMitchellFilter(float b, float c, float width=2.0f)
|
| + : SkBitmapFilter(width), B(b), C(c) {
|
| + }
|
| +
|
| + virtual float evaluate(float x) const SK_OVERRIDE {
|
| + x = fabsf(x);
|
| + float ret;
|
| + if (x > 2.f) {
|
| + return 0;
|
| + } else if (x > 1.f) {
|
| + return ((-B - 6*C) * x*x*x + (6*B + 30*C) * x*x +
|
| + (-12*B - 48*C) * x + (8*B + 24*C)) * (1.f/6.f);
|
| + } else {
|
| + return ((12 - 9*B - 6*C) * x*x*x +
|
| + (-18 + 12*B + 6*C) * x*x +
|
| + (6 - 2*B)) * (1.f/6.f);
|
| + }
|
| + }
|
| + protected:
|
| + float B, C;
|
| +};
|
| +
|
| +class SkGaussianFilter: public SkBitmapFilter {
|
| + public:
|
| + SkGaussianFilter(float a, float width=2.0f)
|
| + : SkBitmapFilter(width), alpha(a), expWidth(expf(-alpha * width * width)) {
|
| + }
|
| +
|
| + virtual float evaluate(float x) const SK_OVERRIDE {
|
| + return SkTMax(0.f, float(expf(-alpha*x*x) - expWidth));
|
| + }
|
| + protected:
|
| + float alpha, expWidth;
|
| +};
|
| +
|
| +class SkTriangleFilter: public SkBitmapFilter {
|
| + public:
|
| + SkTriangleFilter(float width=1)
|
| + : SkBitmapFilter(width) {
|
| + }
|
| +
|
| + virtual float evaluate(float x) const SK_OVERRIDE {
|
| + return SkTMax(0.f, fWidth - fabsf(x));
|
| + }
|
| + protected:
|
| +};
|
| +
|
| +class SkBoxFilter: public SkBitmapFilter {
|
| + public:
|
| + SkBoxFilter(float width=0.5f)
|
| + : SkBitmapFilter(width) {
|
| + }
|
| +
|
| + virtual float evaluate(float x) const SK_OVERRIDE {
|
| + return 1;
|
| + }
|
| + protected:
|
| +};
|
| +
|
| +
|
| +class SkSincFilter: public SkBitmapFilter {
|
| + public:
|
| + SkSincFilter(float t, float width=3.f)
|
| + : SkBitmapFilter(width), tau(t) {
|
| + }
|
| +
|
| + virtual float evaluate(float x) const SK_OVERRIDE {
|
| + x = sk_float_abs(x * fInvWidth);
|
| + if (x < 1e-5f) return 1.f;
|
| + if (x > 1.f) return 0.f;
|
| + x *= M_PI;
|
| + float sinc = sk_float_sin(x) / x;
|
| + float lanczos = sk_float_sin(x * tau) / (x * tau);
|
| + return sinc * lanczos;
|
| + }
|
| + protected:
|
| + float tau;
|
| +};
|
| +
|
| +
|
| +#endif
|
|
|