| /* |
| * Copyright 2020 Google Inc. |
| * |
| * Use of this source code is governed by a BSD-style license that can be |
| * found in the LICENSE file. |
| */ |
| |
| #ifndef SkImageSampling_DEFINED |
| #define SkImageSampling_DEFINED |
| |
| #include "include/core/SkTypes.h" |
| |
| #include <algorithm> |
| #include <new> |
| |
| enum class SkFilterMode { |
| kNearest, // single sample point (nearest neighbor) |
| kLinear, // interporate between 2x2 sample points (bilinear interpolation) |
| |
| kLast = kLinear, |
| }; |
| static constexpr int kSkFilterModeCount = static_cast<int>(SkFilterMode::kLast) + 1; |
| |
| enum class SkMipmapMode { |
| kNone, // ignore mipmap levels, sample from the "base" |
| kNearest, // sample from the nearest level |
| kLinear, // interpolate between the two nearest levels |
| |
| kLast = kLinear, |
| }; |
| static constexpr int kSkMipmapModeCount = static_cast<int>(SkMipmapMode::kLast) + 1; |
| |
| /* |
| * Specify B and C (each between 0...1) to create a shader that applies the corresponding |
| * cubic reconstruction filter to the image. |
| * |
| * Example values: |
| * B = 1/3, C = 1/3 "Mitchell" filter |
| * B = 0, C = 1/2 "Catmull-Rom" filter |
| * |
| * See "Reconstruction Filters in Computer Graphics" |
| * Don P. Mitchell |
| * Arun N. Netravali |
| * 1988 |
| * https://www.cs.utexas.edu/~fussell/courses/cs384g-fall2013/lectures/mitchell/Mitchell.pdf |
| * |
| * Desmos worksheet https://www.desmos.com/calculator/aghdpicrvr |
| * Nice overview https://entropymine.com/imageworsener/bicubic/ |
| */ |
| struct SkCubicResampler { |
| float B, C; |
| |
| // Historic default for kHigh_SkFilterQuality |
| static constexpr SkCubicResampler Mitchell() { return {1/3.0f, 1/3.0f}; } |
| static constexpr SkCubicResampler CatmullRom() { return {0.0f, 1/2.0f}; } |
| }; |
| |
| struct SK_API SkSamplingOptions { |
| const int maxAniso = 0; |
| const bool useCubic = false; |
| const SkCubicResampler cubic = {0, 0}; |
| const SkFilterMode filter = SkFilterMode::kNearest; |
| const SkMipmapMode mipmap = SkMipmapMode::kNone; |
| |
| constexpr SkSamplingOptions() = default; |
| SkSamplingOptions(const SkSamplingOptions&) = default; |
| SkSamplingOptions& operator=(const SkSamplingOptions& that) { |
| this->~SkSamplingOptions(); // A pedantic no-op. |
| new (this) SkSamplingOptions(that); |
| return *this; |
| } |
| |
| constexpr SkSamplingOptions(SkFilterMode fm, SkMipmapMode mm) |
| : filter(fm) |
| , mipmap(mm) {} |
| |
| // These are intentionally implicit because the single parameter clearly conveys what the |
| // implicitly created SkSamplingOptions will be. |
| constexpr SkSamplingOptions(SkFilterMode fm) |
| : filter(fm) |
| , mipmap(SkMipmapMode::kNone) {} |
| |
| constexpr SkSamplingOptions(const SkCubicResampler& c) |
| : useCubic(true) |
| , cubic(c) {} |
| |
| static constexpr SkSamplingOptions Aniso(int maxAniso) { |
| return SkSamplingOptions{std::max(maxAniso, 1)}; |
| } |
| |
| bool operator==(const SkSamplingOptions& other) const { |
| return maxAniso == other.maxAniso |
| && useCubic == other.useCubic |
| && cubic.B == other.cubic.B |
| && cubic.C == other.cubic.C |
| && filter == other.filter |
| && mipmap == other.mipmap; |
| } |
| bool operator!=(const SkSamplingOptions& other) const { return !(*this == other); } |
| |
| bool isAniso() const { return maxAniso != 0; } |
| |
| private: |
| constexpr SkSamplingOptions(int maxAniso) : maxAniso(maxAniso) {} |
| }; |
| |
| #endif |