tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

SkConvolver.h (6247B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
      3 // Copyright (c) 2011-2016 Google Inc.
      4 // Use of this source code is governed by a BSD-style license that can be
      5 // found in the gfx/skia/LICENSE file.
      6 
      7 #ifndef MOZILLA_GFX_SKCONVOLVER_H_
      8 #define MOZILLA_GFX_SKCONVOLVER_H_
      9 
     10 #include <cfloat>
     11 #include <cmath>
     12 #include "mozilla/Vector.h"
     13 #include "Types.h"
     14 
     15 namespace skia {
     16 
     17 class SkBitmapFilter {
     18 public:
     19  explicit SkBitmapFilter(float width) : fWidth(width) {}
     20  virtual ~SkBitmapFilter() = default;
     21 
     22  float width() const { return fWidth; }
     23  virtual float evaluate(float x) const = 0;
     24 
     25 protected:
     26  float fWidth;
     27 };
     28 
     29 class SkBoxFilter final : public SkBitmapFilter {
     30 public:
     31  explicit SkBoxFilter(float width = 0.5f) : SkBitmapFilter(width) {}
     32 
     33  float evaluate(float x) const override {
     34    return (x >= -fWidth && x < fWidth) ? 1.0f : 0.0f;
     35  }
     36 };
     37 
     38 class SkLanczosFilter final : public SkBitmapFilter {
     39 public:
     40  explicit SkLanczosFilter(float width = 3.0f) : SkBitmapFilter(width) {}
     41 
     42  float evaluate(float x) const override {
     43    if (x <= -fWidth || x >= fWidth) {
     44      return 0.0f;  // Outside of the window.
     45    }
     46    if (x > -FLT_EPSILON && x < FLT_EPSILON) {
     47      return 1.0f;  // Special case the discontinuity at the origin.
     48    }
     49    float xpi = x * float(M_PI);
     50    return (sinf(xpi) / xpi) *                   // sinc(x)
     51           sinf(xpi / fWidth) / (xpi / fWidth);  // sinc(x/fWidth)
     52  }
     53 };
     54 
     55 // Represents a filter in one dimension. Each output pixel has one entry in this
     56 // object for the filter values contributing to it. You build up the filter
     57 // list by calling AddFilter for each output pixel (in order).
     58 //
     59 // We do 2-dimensional convolution by first convolving each row by one
     60 // SkConvolutionFilter1D, then convolving each column by another one.
     61 //
     62 // Entries are stored in ConvolutionFixed point, shifted left by kShiftBits.
     63 class SkConvolutionFilter1D {
     64 public:
     65  using ConvolutionFixed = short;
     66 
     67  // The number of bits that ConvolutionFixed point values are shifted by.
     68  enum { kShiftBits = 14 };
     69 
     70  SkConvolutionFilter1D();
     71  ~SkConvolutionFilter1D();
     72 
     73  // Convert between floating point and our ConvolutionFixed point
     74  // representation.
     75  static ConvolutionFixed ToFixed(float f) {
     76    return static_cast<ConvolutionFixed>(f * (1 << kShiftBits));
     77  }
     78 
     79  // Returns the maximum pixel span of a filter.
     80  int maxFilter() const { return fMaxFilter; }
     81 
     82  // Returns the number of filters in this filter. This is the dimension of the
     83  // output image.
     84  int numValues() const { return static_cast<int>(fFilters.length()); }
     85 
     86  bool reserveAdditional(int filterCount, int filterValueCount) {
     87    return fFilters.reserve(fFilters.length() + filterCount) &&
     88           fFilterValues.reserve(fFilterValues.length() + filterValueCount);
     89  }
     90 
     91  // Appends the given list of scaling values for generating a given output
     92  // pixel. |filterOffset| is the distance from the edge of the image to where
     93  // the scaling factors start. The scaling factors apply to the source pixels
     94  // starting from this position, and going for the next |filterLength| pixels.
     95  //
     96  // You will probably want to make sure your input is normalized (that is,
     97  // all entries in |filterValuesg| sub to one) to prevent affecting the overall
     98  // brighness of the image.
     99  //
    100  // The filterLength must be > 0.
    101  bool AddFilter(int filterOffset, const ConvolutionFixed* filterValues,
    102                 int filterLength);
    103 
    104  // Retrieves a filter for the given |valueOffset|, a position in the output
    105  // image in the direction we're convolving. The offset and length of the
    106  // filter values are put into the corresponding out arguments (see AddFilter
    107  // above for what these mean), and a pointer to the first scaling factor is
    108  // returned. There will be |filterLength| values in this array.
    109  inline const ConvolutionFixed* FilterForValue(int valueOffset,
    110                                                int* filterOffset,
    111                                                int* filterLength) const {
    112    const FilterInstance& filter = fFilters[valueOffset];
    113    *filterOffset = filter.fOffset;
    114    *filterLength = filter.fTrimmedLength;
    115    if (filter.fTrimmedLength == 0) {
    116      return nullptr;
    117    }
    118    return &fFilterValues[filter.fDataLocation];
    119  }
    120 
    121  bool ComputeFilterValues(const SkBitmapFilter& aBitmapFilter,
    122                           int32_t aSrcSize, int32_t aDstSize);
    123 
    124 private:
    125  struct FilterInstance {
    126    // Offset within filterValues for this instance of the filter.
    127    int fDataLocation;
    128 
    129    // Distance from the left of the filter to the center. IN PIXELS
    130    int fOffset;
    131 
    132    // Number of values in this filter instance.
    133    int fTrimmedLength;
    134 
    135    // Filter length as specified. Note that this may be different from
    136    // 'trimmed_length' if leading/trailing zeros of the original floating
    137    // point form were clipped differently on each tail.
    138    int fLength;
    139  };
    140 
    141  // Stores the information for each filter added to this class.
    142  mozilla::Vector<FilterInstance> fFilters;
    143 
    144  // We store all the filter values in this flat list, indexed by
    145  // |FilterInstance.data_location| to avoid the mallocs required for storing
    146  // each one separately.
    147  mozilla::Vector<ConvolutionFixed> fFilterValues;
    148 
    149  // The maximum size of any filter we've added.
    150  int fMaxFilter;
    151 };
    152 
    153 void convolve_horizontally(const unsigned char* srcData,
    154                           const SkConvolutionFilter1D& filter,
    155                           unsigned char* outRow,
    156                           mozilla::gfx::SurfaceFormat format);
    157 
    158 void convolve_vertically(
    159    const SkConvolutionFilter1D::ConvolutionFixed* filterValues,
    160    int filterLength, unsigned char* const* sourceDataRows, int pixelWidth,
    161    unsigned char* outRow, mozilla::gfx::SurfaceFormat format);
    162 
    163 bool BGRAConvolve2D(const unsigned char* sourceData, int sourceByteRowStride,
    164                    mozilla::gfx::SurfaceFormat format,
    165                    const SkConvolutionFilter1D& filterX,
    166                    const SkConvolutionFilter1D& filterY,
    167                    int outputByteRowStride, unsigned char* output);
    168 
    169 }  // namespace skia
    170 
    171 #endif /* MOZILLA_GFX_SKCONVOLVER_H_ */