gfx/2d/convolver.h

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/gfx/2d/convolver.h	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,191 @@
     1.4 +// Copyright (c) 2006-2012 The Chromium Authors. All rights reserved.
     1.5 +//
     1.6 +// Redistribution and use in source and binary forms, with or without
     1.7 +// modification, are permitted provided that the following conditions
     1.8 +// are met:
     1.9 +//  * Redistributions of source code must retain the above copyright
    1.10 +//    notice, this list of conditions and the following disclaimer.
    1.11 +//  * Redistributions in binary form must reproduce the above copyright
    1.12 +//    notice, this list of conditions and the following disclaimer in
    1.13 +//    the documentation and/or other materials provided with the
    1.14 +//    distribution.
    1.15 +//  * Neither the name of Google, Inc. nor the names of its contributors
    1.16 +//    may be used to endorse or promote products derived from this
    1.17 +//    software without specific prior written permission.
    1.18 +//
    1.19 +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    1.20 +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    1.21 +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
    1.22 +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
    1.23 +// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
    1.24 +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
    1.25 +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
    1.26 +// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
    1.27 +// AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
    1.28 +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
    1.29 +// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
    1.30 +// SUCH DAMAGE.
    1.31 +
    1.32 +#ifndef SKIA_EXT_CONVOLVER_H_
    1.33 +#define SKIA_EXT_CONVOLVER_H_
    1.34 +
    1.35 +#include <cmath>
    1.36 +#include <vector>
    1.37 +
    1.38 +#include "base/basictypes.h"
    1.39 +#include "base/cpu.h"
    1.40 +#include "mozilla/Assertions.h"
    1.41 +#include "skia/SkTypes.h"
    1.42 +
    1.43 +// avoid confusion with Mac OS X's math library (Carbon)
    1.44 +#if defined(__APPLE__)
    1.45 +#undef FloatToFixed
    1.46 +#undef FixedToFloat
    1.47 +#endif
    1.48 +
    1.49 +namespace skia {
    1.50 +
    1.51 +// Represents a filter in one dimension. Each output pixel has one entry in this
    1.52 +// object for the filter values contributing to it. You build up the filter
    1.53 +// list by calling AddFilter for each output pixel (in order).
    1.54 +//
    1.55 +// We do 2-dimensional convolution by first convolving each row by one
    1.56 +// ConvolutionFilter1D, then convolving each column by another one.
    1.57 +//
    1.58 +// Entries are stored in fixed point, shifted left by kShiftBits.
    1.59 +class ConvolutionFilter1D {
    1.60 + public:
    1.61 +  typedef short Fixed;
    1.62 +
    1.63 +  // The number of bits that fixed point values are shifted by.
    1.64 +  enum { kShiftBits = 14 };
    1.65 +
    1.66 +  ConvolutionFilter1D();
    1.67 +  ~ConvolutionFilter1D();
    1.68 +
    1.69 +  // Convert between floating point and our fixed point representation.
    1.70 +  static Fixed FloatToFixed(float f) {
    1.71 +    return static_cast<Fixed>(f * (1 << kShiftBits));
    1.72 +  }
    1.73 +  static unsigned char FixedToChar(Fixed x) {
    1.74 +    return static_cast<unsigned char>(x >> kShiftBits);
    1.75 +  }
    1.76 +  static float FixedToFloat(Fixed x) {
    1.77 +    // The cast relies on Fixed being a short, implying that on
    1.78 +    // the platforms we care about all (16) bits will fit into
    1.79 +    // the mantissa of a (32-bit) float.
    1.80 +    static_assert(sizeof(Fixed) == 2,
    1.81 +                  "fixed type should fit in float mantissa");
    1.82 +    float raw = static_cast<float>(x);
    1.83 +    return ldexpf(raw, -kShiftBits);
    1.84 +  }
    1.85 +
    1.86 +  // Returns the maximum pixel span of a filter.
    1.87 +  int max_filter() const { return max_filter_; }
    1.88 +
    1.89 +  // Returns the number of filters in this filter. This is the dimension of the
    1.90 +  // output image.
    1.91 +  int num_values() const { return static_cast<int>(filters_.size()); }
    1.92 +
    1.93 +  // Appends the given list of scaling values for generating a given output
    1.94 +  // pixel. |filter_offset| is the distance from the edge of the image to where
    1.95 +  // the scaling factors start. The scaling factors apply to the source pixels
    1.96 +  // starting from this position, and going for the next |filter_length| pixels.
    1.97 +  //
    1.98 +  // You will probably want to make sure your input is normalized (that is,
    1.99 +  // all entries in |filter_values| sub to one) to prevent affecting the overall
   1.100 +  // brighness of the image.
   1.101 +  //
   1.102 +  // The filter_length must be > 0.
   1.103 +  //
   1.104 +  // This version will automatically convert your input to fixed point.
   1.105 +  void AddFilter(int filter_offset,
   1.106 +                        const float* filter_values,
   1.107 +                        int filter_length);
   1.108 +
   1.109 +  // Same as the above version, but the input is already fixed point.
   1.110 +  void AddFilter(int filter_offset,
   1.111 +                 const Fixed* filter_values,
   1.112 +                 int filter_length);
   1.113 +
   1.114 +  // Retrieves a filter for the given |value_offset|, a position in the output
   1.115 +  // image in the direction we're convolving. The offset and length of the
   1.116 +  // filter values are put into the corresponding out arguments (see AddFilter
   1.117 +  // above for what these mean), and a pointer to the first scaling factor is
   1.118 +  // returned. There will be |filter_length| values in this array.
   1.119 +  inline const Fixed* FilterForValue(int value_offset,
   1.120 +                                     int* filter_offset,
   1.121 +                                     int* filter_length) const {
   1.122 +    const FilterInstance& filter = filters_[value_offset];
   1.123 +    *filter_offset = filter.offset;
   1.124 +    *filter_length = filter.length;
   1.125 +    if (filter.length == 0) {
   1.126 +      return NULL;
   1.127 +    }
   1.128 +    return &filter_values_[filter.data_location];
   1.129 +  }
   1.130 +
   1.131 +
   1.132 +  inline void PaddingForSIMD(int padding_count) {
   1.133 +    // Padding |padding_count| of more dummy coefficients after the coefficients
   1.134 +    // of last filter to prevent SIMD instructions which load 8 or 16 bytes
   1.135 +    // together to access invalid memory areas. We are not trying to align the
   1.136 +    // coefficients right now due to the opaqueness of <vector> implementation.
   1.137 +    // This has to be done after all |AddFilter| calls.
   1.138 +    for (int i = 0; i < padding_count; ++i)
   1.139 +      filter_values_.push_back(static_cast<Fixed>(0));
   1.140 +  }
   1.141 +
   1.142 + private:
   1.143 +  struct FilterInstance {
   1.144 +    // Offset within filter_values for this instance of the filter.
   1.145 +    int data_location;
   1.146 +
   1.147 +    // Distance from the left of the filter to the center. IN PIXELS
   1.148 +    int offset;
   1.149 +
   1.150 +    // Number of values in this filter instance.
   1.151 +    int length;
   1.152 +  };
   1.153 +
   1.154 +  // Stores the information for each filter added to this class.
   1.155 +  std::vector<FilterInstance> filters_;
   1.156 +
   1.157 +  // We store all the filter values in this flat list, indexed by
   1.158 +  // |FilterInstance.data_location| to avoid the mallocs required for storing
   1.159 +  // each one separately.
   1.160 +  std::vector<Fixed> filter_values_;
   1.161 +
   1.162 +  // The maximum size of any filter we've added.
   1.163 +  int max_filter_;
   1.164 +};
   1.165 +
   1.166 +// Does a two-dimensional convolution on the given source image.
   1.167 +//
   1.168 +// It is assumed the source pixel offsets referenced in the input filters
   1.169 +// reference only valid pixels, so the source image size is not required. Each
   1.170 +// row of the source image starts |source_byte_row_stride| after the previous
   1.171 +// one (this allows you to have rows with some padding at the end).
   1.172 +//
   1.173 +// The result will be put into the given output buffer. The destination image
   1.174 +// size will be xfilter.num_values() * yfilter.num_values() pixels. It will be
   1.175 +// in rows of exactly xfilter.num_values() * 4 bytes.
   1.176 +//
   1.177 +// |source_has_alpha| is a hint that allows us to avoid doing computations on
   1.178 +// the alpha channel if the image is opaque. If you don't know, set this to
   1.179 +// true and it will work properly, but setting this to false will be a few
   1.180 +// percent faster if you know the image is opaque.
   1.181 +//
   1.182 +// The layout in memory is assumed to be 4-bytes per pixel in B-G-R-A order
   1.183 +// (this is ARGB when loaded into 32-bit words on a little-endian machine).
   1.184 +void BGRAConvolve2D(const unsigned char* source_data,
   1.185 +                    int source_byte_row_stride,
   1.186 +                    bool source_has_alpha,
   1.187 +                    const ConvolutionFilter1D& xfilter,
   1.188 +                    const ConvolutionFilter1D& yfilter,
   1.189 +                    int output_byte_row_stride,
   1.190 +                    unsigned char* output,
   1.191 +                    bool use_sse2);
   1.192 +}  // namespace skia
   1.193 +
   1.194 +#endif  // SKIA_EXT_CONVOLVER_H_

mercurial