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/SkFilterQuality.h"
12 #include <new>
13 
14 enum class SkFilterMode {
15     kNearest,   // single sample point (nearest neighbor)
16     kLinear,    // interporate between 2x2 sample points (bilinear interpolation)
17 
18     kLast = kLinear,
19 };
20 
21 enum class SkMipmapMode {
22     kNone,      // ignore mipmap levels, sample from the "base"
23     kNearest,   // sample from the nearest level
24     kLinear,    // interpolate between the two nearest levels
25 
26     kLast = kLinear,
27 };
28 
29 /*
30  *  Specify B and C (each between 0...1) to create a shader that applies the corresponding
31  *  cubic reconstruction filter to the image.
32  *
33  *  Example values:
34  *      B = 1/3, C = 1/3        "Mitchell" filter
35  *      B = 0,   C = 1/2        "Catmull-Rom" filter
36  *
37  *  See "Reconstruction Filters in Computer Graphics"
38  *          Don P. Mitchell
39  *          Arun N. Netravali
40  *          1988
41  *  https://www.cs.utexas.edu/~fussell/courses/cs384g-fall2013/lectures/mitchell/Mitchell.pdf
42  *
43  *  Desmos worksheet https://www.desmos.com/calculator/aghdpicrvr
44  *  Nice overview https://entropymine.com/imageworsener/bicubic/
45  */
46 struct SkCubicResampler {
47     float B, C;
48 
49     // Historic default for kHigh_SkFilterQuality
MitchellSkCubicResampler50     static constexpr SkCubicResampler Mitchell() { return {1/3.0f, 1/3.0f}; }
CatmullRomSkCubicResampler51     static constexpr SkCubicResampler CatmullRom() { return {0.0f, 1/2.0f}; }
52 };
53 
54 struct SK_API SkSamplingOptions {
55     const bool             useCubic = false;
56     const SkCubicResampler cubic    = {0, 0};
57     const SkFilterMode     filter   = SkFilterMode::kNearest;
58     const SkMipmapMode     mipmap   = SkMipmapMode::kNone;
59 
60     SkSamplingOptions() = default;
61     SkSamplingOptions(const SkSamplingOptions&) = default;
62     SkSamplingOptions& operator=(const SkSamplingOptions& that) {
63         this->~SkSamplingOptions();   // A pedantic no-op.
64         new (this) SkSamplingOptions(that);
65         return *this;
66     }
67 
SkSamplingOptionsSkSamplingOptions68     SkSamplingOptions(SkFilterMode fm, SkMipmapMode mm)
69         : useCubic(false)
70         , filter(fm)
71         , mipmap(mm) {}
72 
SkSamplingOptionsSkSamplingOptions73     explicit SkSamplingOptions(SkFilterMode fm)
74         : useCubic(false)
75         , filter(fm)
76         , mipmap(SkMipmapMode::kNone) {}
77 
SkSamplingOptionsSkSamplingOptions78     explicit SkSamplingOptions(const SkCubicResampler& c)
79         : useCubic(true)
80         , cubic(c) {}
81 
82     enum MediumBehavior {
83         kMedium_asMipmapNearest,    // historic cpu behavior
84         kMedium_asMipmapLinear,     // historic gpu behavior
85     };
86     explicit SkSamplingOptions(SkFilterQuality, MediumBehavior = kMedium_asMipmapNearest);
87 
88     bool operator==(const SkSamplingOptions& other) const {
89         return useCubic == other.useCubic
90             && cubic.B  == other.cubic.B
91             && cubic.C  == other.cubic.C
92             && filter   == other.filter
93             && mipmap   == other.mipmap;
94     }
95     bool operator!=(const SkSamplingOptions& other) const { return !(*this == other); }
96 };
97 
98 #endif
99