// Copyright 2012 The Chromium Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef SKIA_EXT_CONVOLVER_H_ #define SKIA_EXT_CONVOLVER_H_ #include <stdint.h> #include <cmath> #include <vector> #include "build/build_config.h" #include "third_party/skia/include/core/SkSize.h" #include "third_party/skia/include/core/SkTypes.h" // We can build SSE2 optimized versions for all x86 CPUs // except when building for the IOS emulator. #if defined(ARCH_CPU_X86_FAMILY) && !BUILDFLAG(IS_IOS) #define SIMD_SSE2 … #define SIMD_PADDING … #endif #if defined (ARCH_CPU_MIPS_FAMILY) && \ defined(__mips_dsp) && (__mips_dsp_rev >= 2) #define SIMD_MIPS_DSPR2 … #endif #if defined(ARCH_CPU_ARM_FAMILY) && \ (defined(__ARM_NEON__) || defined(__ARM_NEON)) #define SIMD_NEON … #endif #if defined(ARCH_CPU_LOONGARCH_FAMILY) && defined(__loongarch_sx) #define SIMD_LSX … #endif // avoid confusion with Mac OS X's math library (Carbon) #if defined(__APPLE__) #undef FloatToFixed #undef FixedToFloat #endif namespace skia { // Represents a filter in one dimension. Each output pixel has one entry in this // object for the filter values contributing to it. You build up the filter // list by calling AddFilter for each output pixel (in order). // // We do 2-dimensional convolution by first convolving each row by one // ConvolutionFilter1D, then convolving each column by another one. // // Entries are stored in fixed point, shifted left by kShiftBits. class ConvolutionFilter1D { … }; // Does a two-dimensional convolution on the given source image. // // It is assumed the source pixel offsets referenced in the input filters // reference only valid pixels, so the source image size is not required. Each // row of the source image starts |source_byte_row_stride| after the previous // one (this allows you to have rows with some padding at the end). // // The result will be put into the given output buffer. The destination image // size will be xfilter.num_values() * yfilter.num_values() pixels. It will be // in rows of exactly xfilter.num_values() * 4 bytes. // // |source_has_alpha| is a hint that allows us to avoid doing computations on // the alpha channel if the image is opaque. If you don't know, set this to // true and it will work properly, but setting this to false will be a few // percent faster if you know the image is opaque. // // The layout in memory is assumed to be 4-bytes per pixel in B-G-R-A order // (this is ARGB when loaded into 32-bit words on a little-endian machine). SK_API void BGRAConvolve2D(const unsigned char* source_data, int source_byte_row_stride, bool source_has_alpha, const ConvolutionFilter1D& xfilter, const ConvolutionFilter1D& yfilter, int output_byte_row_stride, unsigned char* output, bool use_simd_if_possible); // Does a 1D convolution of the given source image along the X dimension on // a single channel of the bitmap. // // The function uses the same convolution kernel for each pixel. That kernel // must be added to |filter| at offset 0. This is a most straightforward // implementation of convolution, intended chiefly for development purposes. SK_API void SingleChannelConvolveX1D(const unsigned char* source_data, int source_byte_row_stride, int input_channel_index, int input_channel_count, const ConvolutionFilter1D& filter, const SkISize& image_size, unsigned char* output, int output_byte_row_stride, int output_channel_index, int output_channel_count, bool absolute_values); // Does a 1D convolution of the given source image along the Y dimension on // a single channel of the bitmap. SK_API void SingleChannelConvolveY1D(const unsigned char* source_data, int source_byte_row_stride, int input_channel_index, int input_channel_count, const ConvolutionFilter1D& filter, const SkISize& image_size, unsigned char* output, int output_byte_row_stride, int output_channel_index, int output_channel_count, bool absolute_values); // Set up the |filter| instance with a gaussian kernel. |kernel_sigma| is the // parameter of gaussian. If |derivative| is true, the kernel will be that of // the first derivative. Intended for use with the two routines above. SK_API void SetUpGaussianConvolutionKernel(ConvolutionFilter1D* filter, float kernel_sigma, bool derivative); } // namespace skia #endif // SKIA_EXT_CONVOLVER_H_