xref: /aosp_15_r20/external/skia/include/core/SkSamplingOptions.h (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1 /*
2  * Copyright 2020 Google Inc.
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #ifndef SkImageSampling_DEFINED
9 #define SkImageSampling_DEFINED
10 
11 #include "include/core/SkTypes.h"
12 
13 #include <algorithm>
14 #include <new>
15 
16 enum class SkFilterMode {
17     kNearest,   // single sample point (nearest neighbor)
18     kLinear,    // interporate between 2x2 sample points (bilinear interpolation)
19 
20     kLast = kLinear,
21 };
22 static constexpr int kSkFilterModeCount = static_cast<int>(SkFilterMode::kLast) + 1;
23 
24 enum class SkMipmapMode {
25     kNone,      // ignore mipmap levels, sample from the "base"
26     kNearest,   // sample from the nearest level
27     kLinear,    // interpolate between the two nearest levels
28 
29     kLast = kLinear,
30 };
31 static constexpr int kSkMipmapModeCount = static_cast<int>(SkMipmapMode::kLast) + 1;
32 
33 /*
34  *  Specify B and C (each between 0...1) to create a shader that applies the corresponding
35  *  cubic reconstruction filter to the image.
36  *
37  *  Example values:
38  *      B = 1/3, C = 1/3        "Mitchell" filter
39  *      B = 0,   C = 1/2        "Catmull-Rom" filter
40  *
41  *  See "Reconstruction Filters in Computer Graphics"
42  *          Don P. Mitchell
43  *          Arun N. Netravali
44  *          1988
45  *  https://www.cs.utexas.edu/~fussell/courses/cs384g-fall2013/lectures/mitchell/Mitchell.pdf
46  *
47  *  Desmos worksheet https://www.desmos.com/calculator/aghdpicrvr
48  *  Nice overview https://entropymine.com/imageworsener/bicubic/
49  */
50 struct SkCubicResampler {
51     float B, C;
52 
53     // Historic default for kHigh_SkFilterQuality
MitchellSkCubicResampler54     static constexpr SkCubicResampler Mitchell() { return {1/3.0f, 1/3.0f}; }
CatmullRomSkCubicResampler55     static constexpr SkCubicResampler CatmullRom() { return {0.0f, 1/2.0f}; }
56 };
57 
58 struct SK_API SkSamplingOptions {
59     const int              maxAniso = 0;
60     const bool             useCubic = false;
61     const SkCubicResampler cubic    = {0, 0};
62     const SkFilterMode     filter   = SkFilterMode::kNearest;
63     const SkMipmapMode     mipmap   = SkMipmapMode::kNone;
64 
65     constexpr SkSamplingOptions() = default;
66     SkSamplingOptions(const SkSamplingOptions&) = default;
67     SkSamplingOptions& operator=(const SkSamplingOptions& that) {
68         this->~SkSamplingOptions();   // A pedantic no-op.
69         new (this) SkSamplingOptions(that);
70         return *this;
71     }
72 
SkSamplingOptionsSkSamplingOptions73     constexpr SkSamplingOptions(SkFilterMode fm, SkMipmapMode mm)
74         : filter(fm)
75         , mipmap(mm) {}
76 
77     // These are intentionally implicit because the single parameter clearly conveys what the
78     // implicitly created SkSamplingOptions will be.
SkSamplingOptionsSkSamplingOptions79     constexpr SkSamplingOptions(SkFilterMode fm)
80         : filter(fm)
81         , mipmap(SkMipmapMode::kNone) {}
82 
SkSamplingOptionsSkSamplingOptions83     constexpr SkSamplingOptions(const SkCubicResampler& c)
84         : useCubic(true)
85         , cubic(c) {}
86 
AnisoSkSamplingOptions87     static constexpr SkSamplingOptions Aniso(int maxAniso) {
88         return SkSamplingOptions{std::max(maxAniso, 1)};
89     }
90 
91     bool operator==(const SkSamplingOptions& other) const {
92         return maxAniso == other.maxAniso
93             && useCubic == other.useCubic
94             && cubic.B  == other.cubic.B
95             && cubic.C  == other.cubic.C
96             && filter   == other.filter
97             && mipmap   == other.mipmap;
98     }
99     bool operator!=(const SkSamplingOptions& other) const { return !(*this == other); }
100 
isAnisoSkSamplingOptions101     bool isAniso() const { return maxAniso != 0; }
102 
103 private:
SkSamplingOptionsSkSamplingOptions104     constexpr SkSamplingOptions(int maxAniso) : maxAniso(maxAniso) {}
105 };
106 
107 #endif
108