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