gfx/skia/trunk/src/core/SkConvolver.h

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/gfx/skia/trunk/src/core/SkConvolver.h	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,203 @@
     1.4 +// Copyright (c) 2012 The Chromium Authors. All rights reserved.
     1.5 +// Use of this source code is governed by a BSD-style license that can be
     1.6 +// found in the LICENSE file.
     1.7 +
     1.8 +#ifndef SK_CONVOLVER_H
     1.9 +#define SK_CONVOLVER_H
    1.10 +
    1.11 +#include "SkSize.h"
    1.12 +#include "SkTypes.h"
    1.13 +#include "SkTArray.h"
    1.14 +
    1.15 +// avoid confusion with Mac OS X's math library (Carbon)
    1.16 +#if defined(__APPLE__)
    1.17 +#undef FloatToConvolutionFixed
    1.18 +#undef ConvolutionFixedToFloat
    1.19 +#endif
    1.20 +
    1.21 +// Represents a filter in one dimension. Each output pixel has one entry in this
    1.22 +// object for the filter values contributing to it. You build up the filter
    1.23 +// list by calling AddFilter for each output pixel (in order).
    1.24 +//
    1.25 +// We do 2-dimensional convolution by first convolving each row by one
    1.26 +// SkConvolutionFilter1D, then convolving each column by another one.
    1.27 +//
    1.28 +// Entries are stored in ConvolutionFixed point, shifted left by kShiftBits.
    1.29 +class SkConvolutionFilter1D {
    1.30 +public:
    1.31 +    typedef short ConvolutionFixed;
    1.32 +
    1.33 +    // The number of bits that ConvolutionFixed point values are shifted by.
    1.34 +    enum { kShiftBits = 14 };
    1.35 +
    1.36 +    SK_API SkConvolutionFilter1D();
    1.37 +    SK_API ~SkConvolutionFilter1D();
    1.38 +
    1.39 +    // Convert between floating point and our ConvolutionFixed point representation.
    1.40 +    static ConvolutionFixed FloatToFixed(float f) {
    1.41 +        return static_cast<ConvolutionFixed>(f * (1 << kShiftBits));
    1.42 +    }
    1.43 +    static unsigned char FixedToChar(ConvolutionFixed x) {
    1.44 +        return static_cast<unsigned char>(x >> kShiftBits);
    1.45 +    }
    1.46 +    static float FixedToFloat(ConvolutionFixed x) {
    1.47 +        // The cast relies on ConvolutionFixed being a short, implying that on
    1.48 +        // the platforms we care about all (16) bits will fit into
    1.49 +        // the mantissa of a (32-bit) float.
    1.50 +        SK_COMPILE_ASSERT(sizeof(ConvolutionFixed) == 2, ConvolutionFixed_type_should_fit_in_float_mantissa);
    1.51 +        float raw = static_cast<float>(x);
    1.52 +        return ldexpf(raw, -kShiftBits);
    1.53 +    }
    1.54 +
    1.55 +    // Returns the maximum pixel span of a filter.
    1.56 +    int maxFilter() const { return fMaxFilter; }
    1.57 +
    1.58 +    // Returns the number of filters in this filter. This is the dimension of the
    1.59 +    // output image.
    1.60 +    int numValues() const { return static_cast<int>(fFilters.count()); }
    1.61 +
    1.62 +    // Appends the given list of scaling values for generating a given output
    1.63 +    // pixel. |filterOffset| is the distance from the edge of the image to where
    1.64 +    // the scaling factors start. The scaling factors apply to the source pixels
    1.65 +    // starting from this position, and going for the next |filterLength| pixels.
    1.66 +    //
    1.67 +    // You will probably want to make sure your input is normalized (that is,
    1.68 +    // all entries in |filterValuesg| sub to one) to prevent affecting the overall
    1.69 +    // brighness of the image.
    1.70 +    //
    1.71 +    // The filterLength must be > 0.
    1.72 +    //
    1.73 +    // This version will automatically convert your input to ConvolutionFixed point.
    1.74 +    SK_API void AddFilter(int filterOffset,
    1.75 +                          const float* filterValues,
    1.76 +                          int filterLength);
    1.77 +
    1.78 +    // Same as the above version, but the input is already ConvolutionFixed point.
    1.79 +    void AddFilter(int filterOffset,
    1.80 +                   const ConvolutionFixed* filterValues,
    1.81 +                   int filterLength);
    1.82 +
    1.83 +    // Retrieves a filter for the given |valueOffset|, a position in the output
    1.84 +    // image in the direction we're convolving. The offset and length of the
    1.85 +    // filter values are put into the corresponding out arguments (see AddFilter
    1.86 +    // above for what these mean), and a pointer to the first scaling factor is
    1.87 +    // returned. There will be |filterLength| values in this array.
    1.88 +    inline const ConvolutionFixed* FilterForValue(int valueOffset,
    1.89 +                                       int* filterOffset,
    1.90 +                                       int* filterLength) const {
    1.91 +        const FilterInstance& filter = fFilters[valueOffset];
    1.92 +        *filterOffset = filter.fOffset;
    1.93 +        *filterLength = filter.fTrimmedLength;
    1.94 +        if (filter.fTrimmedLength == 0) {
    1.95 +            return NULL;
    1.96 +        }
    1.97 +        return &fFilterValues[filter.fDataLocation];
    1.98 +    }
    1.99 +
   1.100 +  // Retrieves the filter for the offset 0, presumed to be the one and only.
   1.101 +  // The offset and length of the filter values are put into the corresponding
   1.102 +  // out arguments (see AddFilter). Note that |filterLegth| and
   1.103 +  // |specifiedFilterLength| may be different if leading/trailing zeros of the
   1.104 +  // original floating point form were clipped.
   1.105 +  // There will be |filterLength| values in the return array.
   1.106 +  // Returns NULL if the filter is 0-length (for instance when all floating
   1.107 +  // point values passed to AddFilter were clipped to 0).
   1.108 +    SK_API const ConvolutionFixed* GetSingleFilter(int* specifiedFilterLength,
   1.109 +        int* filterOffset,
   1.110 +        int* filterLength) const;
   1.111 +
   1.112 +    // Add another value to the fFilterValues array -- useful for
   1.113 +    // SIMD padding which happens outside of this class.
   1.114 +
   1.115 +    void addFilterValue( ConvolutionFixed val ) {
   1.116 +        fFilterValues.push_back( val );
   1.117 +    }
   1.118 +private:
   1.119 +    struct FilterInstance {
   1.120 +        // Offset within filterValues for this instance of the filter.
   1.121 +        int fDataLocation;
   1.122 +
   1.123 +        // Distance from the left of the filter to the center. IN PIXELS
   1.124 +        int fOffset;
   1.125 +
   1.126 +        // Number of values in this filter instance.
   1.127 +        int fTrimmedLength;
   1.128 +
   1.129 +        // Filter length as specified. Note that this may be different from
   1.130 +        // 'trimmed_length' if leading/trailing zeros of the original floating
   1.131 +        // point form were clipped differently on each tail.
   1.132 +        int fLength;
   1.133 +    };
   1.134 +
   1.135 +    // Stores the information for each filter added to this class.
   1.136 +    SkTArray<FilterInstance> fFilters;
   1.137 +
   1.138 +    // We store all the filter values in this flat list, indexed by
   1.139 +    // |FilterInstance.data_location| to avoid the mallocs required for storing
   1.140 +    // each one separately.
   1.141 +    SkTArray<ConvolutionFixed> fFilterValues;
   1.142 +
   1.143 +    // The maximum size of any filter we've added.
   1.144 +    int fMaxFilter;
   1.145 +};
   1.146 +
   1.147 +typedef void (*SkConvolveVertically_pointer)(
   1.148 +    const SkConvolutionFilter1D::ConvolutionFixed* filterValues,
   1.149 +    int filterLength,
   1.150 +    unsigned char* const* sourceDataRows,
   1.151 +    int pixelWidth,
   1.152 +    unsigned char* outRow,
   1.153 +    bool hasAlpha);
   1.154 +typedef void (*SkConvolve4RowsHorizontally_pointer)(
   1.155 +    const unsigned char* srcData[4],
   1.156 +    const SkConvolutionFilter1D& filter,
   1.157 +    unsigned char* outRow[4]);
   1.158 +typedef void (*SkConvolveHorizontally_pointer)(
   1.159 +    const unsigned char* srcData,
   1.160 +    const SkConvolutionFilter1D& filter,
   1.161 +    unsigned char* outRow,
   1.162 +    bool hasAlpha);
   1.163 +typedef void (*SkConvolveFilterPadding_pointer)(
   1.164 +    SkConvolutionFilter1D* filter);
   1.165 +
   1.166 +struct SkConvolutionProcs {
   1.167 +  // This is how many extra pixels may be read by the
   1.168 +  // conolve*horizontally functions.
   1.169 +    int fExtraHorizontalReads;
   1.170 +    SkConvolveVertically_pointer fConvolveVertically;
   1.171 +    SkConvolve4RowsHorizontally_pointer fConvolve4RowsHorizontally;
   1.172 +    SkConvolveHorizontally_pointer fConvolveHorizontally;
   1.173 +    SkConvolveFilterPadding_pointer fApplySIMDPadding;
   1.174 +};
   1.175 +
   1.176 +
   1.177 +
   1.178 +// Does a two-dimensional convolution on the given source image.
   1.179 +//
   1.180 +// It is assumed the source pixel offsets referenced in the input filters
   1.181 +// reference only valid pixels, so the source image size is not required. Each
   1.182 +// row of the source image starts |sourceByteRowStride| after the previous
   1.183 +// one (this allows you to have rows with some padding at the end).
   1.184 +//
   1.185 +// The result will be put into the given output buffer. The destination image
   1.186 +// size will be xfilter.numValues() * yfilter.numValues() pixels. It will be
   1.187 +// in rows of exactly xfilter.numValues() * 4 bytes.
   1.188 +//
   1.189 +// |sourceHasAlpha| is a hint that allows us to avoid doing computations on
   1.190 +// the alpha channel if the image is opaque. If you don't know, set this to
   1.191 +// true and it will work properly, but setting this to false will be a few
   1.192 +// percent faster if you know the image is opaque.
   1.193 +//
   1.194 +// The layout in memory is assumed to be 4-bytes per pixel in B-G-R-A order
   1.195 +// (this is ARGB when loaded into 32-bit words on a little-endian machine).
   1.196 +SK_API void BGRAConvolve2D(const unsigned char* sourceData,
   1.197 +    int sourceByteRowStride,
   1.198 +    bool sourceHasAlpha,
   1.199 +    const SkConvolutionFilter1D& xfilter,
   1.200 +    const SkConvolutionFilter1D& yfilter,
   1.201 +    int outputByteRowStride,
   1.202 +    unsigned char* output,
   1.203 +    const SkConvolutionProcs&,
   1.204 +    bool useSimdIfPossible);
   1.205 +
   1.206 +#endif  // SK_CONVOLVER_H

mercurial