// 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. #include <stddef.h> #include <stdint.h> #include <algorithm> #include <limits> #include <numbers> #include "skia/ext/image_operations.h" #include "base/check.h" #include "base/metrics/histogram_macros.h" #include "base/notreached.h" #include "base/time/time.h" #include "base/trace_event/trace_event.h" #include "build/build_config.h" #include "skia/ext/convolver.h" #include "third_party/abseil-cpp/absl/container/inlined_vector.h" #include "third_party/skia/include/core/SkColorPriv.h" #include "third_party/skia/include/core/SkRect.h" namespace skia { namespace { // Returns the ceiling/floor as an integer. inline int CeilInt(float val) { … } inline int FloorInt(float val) { … } // Filter function computation ------------------------------------------------- // Evaluates the box filter, which goes from -0.5 to +0.5. float EvalBox(float x) { … } // Evaluates the Lanczos filter of the given filter size window for the given // position. // // |filter_size| is the width of the filter (the "window"), outside of which // the value of the function is 0. Inside of the window, the value is the // normalized sinc function: // lanczos(x) = sinc(x) * sinc(x / filter_size); // where // sinc(x) = sin(pi*x) / (pi*x); float EvalLanczos(int filter_size, float x) { … } // Evaluates the Hamming filter of the given filter size window for the given // position. // // The filter covers [-filter_size, +filter_size]. Outside of this window // the value of the function is 0. Inside of the window, the value is sinus // cardinal multiplied by a recentered Hamming function. The traditional // Hamming formula for a window of size N and n ranging in [0, N-1] is: // hamming(n) = 0.54 - 0.46 * cos(2 * pi * n / (N-1))) // In our case we want the function centered for x == 0 and at its minimum // on both ends of the window (x == +/- filter_size), hence the adjusted // formula: // hamming(x) = (0.54 - // 0.46 * cos(2 * pi * (x - filter_size)/ (2 * filter_size))) // = 0.54 - 0.46 * cos(pi * x / filter_size - pi) // = 0.54 + 0.46 * cos(pi * x / filter_size) float EvalHamming(int filter_size, float x) { … } // ResizeFilter ---------------------------------------------------------------- // Encapsulates computation and storage of the filters required for one complete // resize operation. class ResizeFilter { … }; ResizeFilter::ResizeFilter(ImageOperations::ResizeMethod method, int src_full_width, int src_full_height, int dest_width, int dest_height, const SkIRect& dest_subset) : … { … } // TODO(egouriou): Take advantage of periods in the convolution. // Practical resizing filters are periodic outside of the border area. // For Lanczos, a scaling by a (reduced) factor of p/q (q pixels in the // source become p pixels in the destination) will have a period of p. // A nice consequence is a period of 1 when downscaling by an integral // factor. Downscaling from typical display resolutions is also bound // to produce interesting periods as those are chosen to have multiple // small factors. // Small periods reduce computational load and improve cache usage if // the coefficients can be shared. For periods of 1 we can consider // loading the factors only once outside the borders. void ResizeFilter::ComputeFilters(int src_size, int dest_subset_lo, int dest_subset_size, float scale, ConvolutionFilter1D* output) { … } ImageOperations::ResizeMethod ResizeMethodToAlgorithmMethod( ImageOperations::ResizeMethod method) { … } } // namespace // Resize ---------------------------------------------------------------------- // static SkBitmap ImageOperations::Resize(const SkPixmap& source, ResizeMethod method, int dest_width, int dest_height, const SkIRect& dest_subset, SkBitmap::Allocator* allocator) { … } // static SkBitmap ImageOperations::Resize(const SkBitmap& source, ResizeMethod method, int dest_width, int dest_height, const SkIRect& dest_subset, SkBitmap::Allocator* allocator) { … } // static SkBitmap ImageOperations::Resize(const SkBitmap& source, ResizeMethod method, int dest_width, int dest_height, SkBitmap::Allocator* allocator) { … } } // namespace skia