Home | History | Annotate | Download | only in core
      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:
     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 
     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 
     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 
     47       float width() const { return fWidth; }
     48       float invWidth() const { return fInvWidth; }
     49       virtual float evaluate(float x) const = 0;
     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:
     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++ = SkFloatToScalar(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)
     79       : SkBitmapFilter(width), B(b), C(c) {
     80       }
     81 
     82       virtual float evaluate(float x) const SK_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)
    102       : SkBitmapFilter(width), alpha(a), expWidth(expf(-alpha * width * width)) {
    103       }
    104 
    105       virtual float evaluate(float x) const SK_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)
    115       : SkBitmapFilter(width) {
    116       }
    117 
    118       virtual float evaluate(float x) const SK_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)
    127       : SkBitmapFilter(width) {
    128       }
    129 
    130       virtual float evaluate(float x) const SK_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)
    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>(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)
    158       : SkBitmapFilter(width) {
    159       }
    160 
    161       virtual float evaluate(float x) const SK_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