OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2016 Google Inc. | 2 * Copyright 2016 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #ifndef SkLinearBitmapPipeline_sampler_DEFINED | 8 #ifndef SkLinearBitmapPipeline_sampler_DEFINED |
9 #define SkLinearBitmapPipeline_sampler_DEFINED | 9 #define SkLinearBitmapPipeline_sampler_DEFINED |
10 | 10 |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
48 Sk4f sum = px11 * fxys; | 48 Sk4f sum = px11 * fxys; |
49 sum = sum + px01 * (fys - fxys); | 49 sum = sum + px01 * (fys - fxys); |
50 sum = sum + px10 * (fxs - fxys); | 50 sum = sum + px10 * (fxs - fxys); |
51 sum = sum + px00 * (Sk4f{1.0f} - fxs - fys + fxys); | 51 sum = sum + px00 * (Sk4f{1.0f} - fxs - fys + fxys); |
52 return sum; | 52 return sum; |
53 } | 53 } |
54 | 54 |
55 ////////////////////////////////////////////////////////////////////////////////
//////////////////// | 55 ////////////////////////////////////////////////////////////////////////////////
//////////////////// |
56 // PixelGetter is the lowest level interface to the source data. There is a Pixe
lGetter for each | 56 // PixelGetter is the lowest level interface to the source data. There is a Pixe
lGetter for each |
57 // of the different SkColorTypes. | 57 // of the different SkColorTypes. |
58 template <SkColorType colorType, SkColorProfileType colorProfile> class PixelGet
ter; | 58 template <SkColorType, SkGammaType> class PixelGetter; |
59 | 59 |
60 // Alpha handling: | 60 // Alpha handling: |
61 // The alpha from the paint (tintColor) is used in the blend part of the pipel
ine to modulate | 61 // The alpha from the paint (tintColor) is used in the blend part of the pipel
ine to modulate |
62 // the entire bitmap. So, the tint color is given an alpha of 1.0 so that the la
ter alpha can | 62 // the entire bitmap. So, the tint color is given an alpha of 1.0 so that the la
ter alpha can |
63 // modulate this color later. | 63 // modulate this color later. |
64 template <> | 64 template <> |
65 class PixelGetter<kAlpha_8_SkColorType, kLinear_SkColorProfileType> { | 65 class PixelGetter<kAlpha_8_SkColorType, kLinear_SkGammaType> { |
66 public: | 66 public: |
67 using Element = uint8_t; | 67 using Element = uint8_t; |
68 PixelGetter(const SkPixmap& srcPixmap, SkColor tintColor) | 68 PixelGetter(const SkPixmap& srcPixmap, SkColor tintColor) |
69 : fTintColor{set_alpha(Sk4f_from_SkColor(tintColor), 1.0f)} { } | 69 : fTintColor{set_alpha(Sk4f_from_SkColor(tintColor), 1.0f)} { } |
70 | 70 |
71 Sk4f getPixelAt(const uint8_t* src) { | 71 Sk4f getPixelAt(const uint8_t* src) { |
72 return fTintColor * (*src * (1.0f/255.0f)); | 72 return fTintColor * (*src * (1.0f/255.0f)); |
73 } | 73 } |
74 | 74 |
75 private: | 75 private: |
76 const Sk4f fTintColor; | 76 const Sk4f fTintColor; |
77 }; | 77 }; |
78 | 78 |
79 template <SkColorProfileType colorProfile> | 79 template <SkGammaType gammaType> |
80 class PixelGetter<kRGB_565_SkColorType, colorProfile> { | 80 class PixelGetter<kRGB_565_SkColorType, gammaType> { |
81 public: | 81 public: |
82 using Element = uint16_t; | 82 using Element = uint16_t; |
83 PixelGetter(const SkPixmap& srcPixmap) { } | 83 PixelGetter(const SkPixmap& srcPixmap) { } |
84 | 84 |
85 Sk4f getPixelAt(const uint16_t* src) { | 85 Sk4f getPixelAt(const uint16_t* src) { |
86 SkPMColor pixel = SkPixel16ToPixel32(*src); | 86 SkPMColor pixel = SkPixel16ToPixel32(*src); |
87 return colorProfile == kSRGB_SkColorProfileType | 87 return gammaType == kSRGB_SkGammaType |
88 ? Sk4f_fromS32(pixel) | 88 ? Sk4f_fromS32(pixel) |
89 : Sk4f_fromL32(pixel); | 89 : Sk4f_fromL32(pixel); |
90 } | 90 } |
91 }; | 91 }; |
92 | 92 |
93 template <SkColorProfileType colorProfile> | 93 template <SkGammaType gammaType> |
94 class PixelGetter<kARGB_4444_SkColorType, colorProfile> { | 94 class PixelGetter<kARGB_4444_SkColorType, gammaType> { |
95 public: | 95 public: |
96 using Element = uint16_t; | 96 using Element = uint16_t; |
97 PixelGetter(const SkPixmap& srcPixmap) { } | 97 PixelGetter(const SkPixmap& srcPixmap) { } |
98 | 98 |
99 Sk4f getPixelAt(const uint16_t* src) { | 99 Sk4f getPixelAt(const uint16_t* src) { |
100 SkPMColor pixel = SkPixel4444ToPixel32(*src); | 100 SkPMColor pixel = SkPixel4444ToPixel32(*src); |
101 return colorProfile == kSRGB_SkColorProfileType | 101 return gammaType == kSRGB_SkGammaType |
102 ? Sk4f_fromS32(pixel) | 102 ? Sk4f_fromS32(pixel) |
103 : Sk4f_fromL32(pixel); | 103 : Sk4f_fromL32(pixel); |
104 } | 104 } |
105 }; | 105 }; |
106 | 106 |
107 template <SkColorProfileType colorProfile> | 107 template <SkGammaType gammaType> |
108 class PixelGetter<kRGBA_8888_SkColorType, colorProfile> { | 108 class PixelGetter<kRGBA_8888_SkColorType, gammaType> { |
109 public: | 109 public: |
110 using Element = uint32_t; | 110 using Element = uint32_t; |
111 PixelGetter(const SkPixmap& srcPixmap) { } | 111 PixelGetter(const SkPixmap& srcPixmap) { } |
112 | 112 |
113 Sk4f getPixelAt(const uint32_t* src) { | 113 Sk4f getPixelAt(const uint32_t* src) { |
114 return colorProfile == kSRGB_SkColorProfileType | 114 return gammaType == kSRGB_SkGammaType |
115 ? Sk4f_fromS32(*src) | 115 ? Sk4f_fromS32(*src) |
116 : Sk4f_fromL32(*src); | 116 : Sk4f_fromL32(*src); |
117 } | 117 } |
118 }; | 118 }; |
119 | 119 |
120 template <SkColorProfileType colorProfile> | 120 template <SkGammaType gammaType> |
121 class PixelGetter<kBGRA_8888_SkColorType, colorProfile> { | 121 class PixelGetter<kBGRA_8888_SkColorType, gammaType> { |
122 public: | 122 public: |
123 using Element = uint32_t; | 123 using Element = uint32_t; |
124 PixelGetter(const SkPixmap& srcPixmap) { } | 124 PixelGetter(const SkPixmap& srcPixmap) { } |
125 | 125 |
126 Sk4f getPixelAt(const uint32_t* src) { | 126 Sk4f getPixelAt(const uint32_t* src) { |
127 Sk4f pixel = colorProfile == kSRGB_SkColorProfileType | 127 Sk4f pixel = gammaType == kSRGB_SkGammaType |
128 ? Sk4f_fromS32(*src) | 128 ? Sk4f_fromS32(*src) |
129 : Sk4f_fromL32(*src); | 129 : Sk4f_fromL32(*src); |
130 return swizzle_rb(pixel); | 130 return swizzle_rb(pixel); |
131 } | 131 } |
132 }; | 132 }; |
133 | 133 |
134 template <SkColorProfileType colorProfile> | 134 template <SkGammaType gammaType> |
135 class PixelGetter<kIndex_8_SkColorType, colorProfile> { | 135 class PixelGetter<kIndex_8_SkColorType, gammaType> { |
136 public: | 136 public: |
137 using Element = uint8_t; | 137 using Element = uint8_t; |
138 PixelGetter(const SkPixmap& srcPixmap) { | 138 PixelGetter(const SkPixmap& srcPixmap) { |
139 SkColorTable* skColorTable = srcPixmap.ctable(); | 139 SkColorTable* skColorTable = srcPixmap.ctable(); |
140 SkASSERT(skColorTable != nullptr); | 140 SkASSERT(skColorTable != nullptr); |
141 | 141 |
142 fColorTable = (Sk4f*)SkAlign16((intptr_t)fColorTableStorage.get()); | 142 fColorTable = (Sk4f*)SkAlign16((intptr_t)fColorTableStorage.get()); |
143 for (int i = 0; i < skColorTable->count(); i++) { | 143 for (int i = 0; i < skColorTable->count(); i++) { |
144 fColorTable[i] = this->convertPixel((*skColorTable)[i]); | 144 fColorTable[i] = this->convertPixel((*skColorTable)[i]); |
145 } | 145 } |
(...skipping 13 matching lines...) Expand all Loading... |
159 | 159 |
160 private: | 160 private: |
161 static const size_t kColorTableSize = sizeof(Sk4f[256]) + 12; | 161 static const size_t kColorTableSize = sizeof(Sk4f[256]) + 12; |
162 Sk4f convertPixel(SkPMColor pmColor) { | 162 Sk4f convertPixel(SkPMColor pmColor) { |
163 Sk4f pixel = to_4f(pmColor); | 163 Sk4f pixel = to_4f(pmColor); |
164 float alpha = get_alpha(pixel); | 164 float alpha = get_alpha(pixel); |
165 if (alpha != 0.0f) { | 165 if (alpha != 0.0f) { |
166 float invAlpha = 1.0f / alpha; | 166 float invAlpha = 1.0f / alpha; |
167 Sk4f normalize = {invAlpha, invAlpha, invAlpha, 1.0f / 255.0f}; | 167 Sk4f normalize = {invAlpha, invAlpha, invAlpha, 1.0f / 255.0f}; |
168 pixel = pixel * normalize; | 168 pixel = pixel * normalize; |
169 if (colorProfile == kSRGB_SkColorProfileType) { | 169 if (gammaType == kSRGB_SkGammaType) { |
170 pixel = linear_to_srgb(pixel); | 170 pixel = linear_to_srgb(pixel); |
171 } | 171 } |
172 return pixel; | 172 return pixel; |
173 } else { | 173 } else { |
174 return Sk4f{0.0f}; | 174 return Sk4f{0.0f}; |
175 } | 175 } |
176 } | 176 } |
177 SkAutoMalloc fColorTableStorage{kColorTableSize}; | 177 SkAutoMalloc fColorTableStorage{kColorTableSize}; |
178 Sk4f* fColorTable; | 178 Sk4f* fColorTable; |
179 }; | 179 }; |
180 | 180 |
181 template <SkColorProfileType colorProfile> | 181 template <SkGammaType gammaType> |
182 class PixelGetter<kGray_8_SkColorType, colorProfile> { | 182 class PixelGetter<kGray_8_SkColorType, gammaType> { |
183 public: | 183 public: |
184 using Element = uint8_t; | 184 using Element = uint8_t; |
185 PixelGetter(const SkPixmap& srcPixmap) { } | 185 PixelGetter(const SkPixmap& srcPixmap) { } |
186 | 186 |
187 Sk4f getPixelAt(const uint8_t* src) { | 187 Sk4f getPixelAt(const uint8_t* src) { |
188 float gray = *src * (1.0f/255.0f); | 188 float gray = *src * (1.0f/255.0f); |
189 Sk4f pixel = Sk4f{gray, gray, gray, 1.0f}; | 189 Sk4f pixel = Sk4f{gray, gray, gray, 1.0f}; |
190 return colorProfile == kSRGB_SkColorProfileType | 190 return gammaType == kSRGB_SkGammaType |
191 ? srgb_to_linear(pixel) | 191 ? srgb_to_linear(pixel) |
192 : pixel; | 192 : pixel; |
193 } | 193 } |
194 }; | 194 }; |
195 | 195 |
196 template <> | 196 template <> |
197 class PixelGetter<kRGBA_F16_SkColorType, kLinear_SkColorProfileType> { | 197 class PixelGetter<kRGBA_F16_SkColorType, kLinear_SkGammaType> { |
198 public: | 198 public: |
199 using Element = uint64_t; | 199 using Element = uint64_t; |
200 PixelGetter(const SkPixmap& srcPixmap) { } | 200 PixelGetter(const SkPixmap& srcPixmap) { } |
201 | 201 |
202 Sk4f getPixelAt(const uint64_t* src) { | 202 Sk4f getPixelAt(const uint64_t* src) { |
203 return SkHalfToFloat_01(*src); | 203 return SkHalfToFloat_01(*src); |
204 } | 204 } |
205 }; | 205 }; |
206 | 206 |
207 ////////////////////////////////////////////////////////////////////////////////
//////////////////// | 207 ////////////////////////////////////////////////////////////////////////////////
//////////////////// |
208 // PixelAccessor handles all the same plumbing for all the PixelGetters. | 208 // PixelAccessor handles all the same plumbing for all the PixelGetters. |
209 template <SkColorType colorType, SkColorProfileType colorProfile> | 209 template <SkColorType colorType, SkGammaType gammaType> |
210 class PixelAccessor { | 210 class PixelAccessor { |
211 using Element = typename PixelGetter<colorType, colorProfile>::Element; | 211 using Element = typename PixelGetter<colorType, gammaType>::Element; |
212 public: | 212 public: |
213 template <typename... Args> | 213 template <typename... Args> |
214 PixelAccessor(const SkPixmap& srcPixmap, Args&&... args) | 214 PixelAccessor(const SkPixmap& srcPixmap, Args&&... args) |
215 : fSrc{static_cast<const Element*>(srcPixmap.addr())} | 215 : fSrc{static_cast<const Element*>(srcPixmap.addr())} |
216 , fWidth{srcPixmap.rowBytesAsPixels()} | 216 , fWidth{srcPixmap.rowBytesAsPixels()} |
217 , fGetter{srcPixmap, std::move<Args>(args)...} { } | 217 , fGetter{srcPixmap, std::move<Args>(args)...} { } |
218 | 218 |
219 void VECTORCALL getFewPixels(int n, Sk4s xs, Sk4s ys, Sk4f* px0, Sk4f* px1,
Sk4f* px2) { | 219 void VECTORCALL getFewPixels(int n, Sk4s xs, Sk4s ys, Sk4f* px0, Sk4f* px1,
Sk4f* px2) { |
220 Sk4i XIs = SkNx_cast<int, SkScalar>(xs); | 220 Sk4i XIs = SkNx_cast<int, SkScalar>(xs); |
221 Sk4i YIs = SkNx_cast<int, SkScalar>(ys); | 221 Sk4i YIs = SkNx_cast<int, SkScalar>(ys); |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
256 | 256 |
257 Sk4f getPixelAt(int index) { | 257 Sk4f getPixelAt(int index) { |
258 return this->getPixelFromRow(fSrc, index); | 258 return this->getPixelFromRow(fSrc, index); |
259 } | 259 } |
260 | 260 |
261 const void* row(int y) const { return fSrc + y * fWidth[0]; } | 261 const void* row(int y) const { return fSrc + y * fWidth[0]; } |
262 | 262 |
263 private: | 263 private: |
264 const Element* const fSrc; | 264 const Element* const fSrc; |
265 const Sk4i fWidth; | 265 const Sk4i fWidth; |
266 PixelGetter<colorType, colorProfile> fGetter; | 266 PixelGetter<colorType, gammaType> fGetter; |
267 }; | 267 }; |
268 | 268 |
269 // We're moving through source space at a rate of 1 source pixel per 1 dst pixel
. | 269 // We're moving through source space at a rate of 1 source pixel per 1 dst pixel
. |
270 // We'll never re-use pixels, but we can at least load contiguous pixels. | 270 // We'll never re-use pixels, but we can at least load contiguous pixels. |
271 template <typename Next, typename Strategy> | 271 template <typename Next, typename Strategy> |
272 static void src_strategy_blend(Span span, Next* next, Strategy* strategy) { | 272 static void src_strategy_blend(Span span, Next* next, Strategy* strategy) { |
273 SkPoint start; | 273 SkPoint start; |
274 SkScalar length; | 274 SkScalar length; |
275 int count; | 275 int count; |
276 std::tie(start, length, count) = span; | 276 std::tie(start, length, count) = span; |
(...skipping 24 matching lines...) Expand all Loading... |
301 | 301 |
302 while (count > 0) { | 302 while (count > 0) { |
303 next->blendPixel(strategy->getPixelFromRow(row, ix)); | 303 next->blendPixel(strategy->getPixelFromRow(row, ix)); |
304 ix -= 1; | 304 ix -= 1; |
305 count -= 1; | 305 count -= 1; |
306 } | 306 } |
307 } | 307 } |
308 } | 308 } |
309 | 309 |
310 // NearestNeighborSampler - use nearest neighbor filtering to create runs of des
tination pixels. | 310 // NearestNeighborSampler - use nearest neighbor filtering to create runs of des
tination pixels. |
311 template<SkColorType colorType, SkColorProfileType colorProfile, typename Next> | 311 template<SkColorType colorType, SkGammaType gammaType, typename Next> |
312 class NearestNeighborSampler : public SkLinearBitmapPipeline::SampleProcessorInt
erface { | 312 class NearestNeighborSampler : public SkLinearBitmapPipeline::SampleProcessorInt
erface { |
313 public: | 313 public: |
314 template<typename... Args> | 314 template<typename... Args> |
315 NearestNeighborSampler(SkLinearBitmapPipeline::BlendProcessorInterface* next
, Args&& ... args) | 315 NearestNeighborSampler(SkLinearBitmapPipeline::BlendProcessorInterface* next
, Args&& ... args) |
316 : fNext{next}, fStrategy{std::forward<Args>(args)...} { } | 316 : fNext{next}, fStrategy{std::forward<Args>(args)...} { } |
317 | 317 |
318 NearestNeighborSampler(SkLinearBitmapPipeline::BlendProcessorInterface* next
, | 318 NearestNeighborSampler(SkLinearBitmapPipeline::BlendProcessorInterface* next
, |
319 const NearestNeighborSampler& sampler) | 319 const NearestNeighborSampler& sampler) |
320 : fNext{next}, fStrategy{sampler.fStrategy} { } | 320 : fNext{next}, fStrategy{sampler.fStrategy} { } |
321 | 321 |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
417 void spanUnitRate(Span span) { | 417 void spanUnitRate(Span span) { |
418 src_strategy_blend(span, fNext, &fStrategy); | 418 src_strategy_blend(span, fNext, &fStrategy); |
419 } | 419 } |
420 | 420 |
421 // We're moving through source space faster than dst (zoomed out), | 421 // We're moving through source space faster than dst (zoomed out), |
422 // so we'll never reuse a source pixel or be able to do contiguous loads. | 422 // so we'll never reuse a source pixel or be able to do contiguous loads. |
423 void spanFastRate(Span span) { | 423 void spanFastRate(Span span) { |
424 span_fallback(span, this); | 424 span_fallback(span, this); |
425 } | 425 } |
426 | 426 |
427 Next* const fNext; | 427 Next* const fNext; |
428 PixelAccessor<colorType, colorProfile> fStrategy; | 428 PixelAccessor<colorType, gammaType> fStrategy; |
429 }; | 429 }; |
430 | 430 |
431 // -- BilerpSampler ------------------------------------------------------------
-------------------- | 431 // -- BilerpSampler ------------------------------------------------------------
-------------------- |
432 // BilerpSampler - use a bilerp filter to create runs of destination pixels. | 432 // BilerpSampler - use a bilerp filter to create runs of destination pixels. |
433 template<SkColorType colorType, SkColorProfileType colorProfile, typename Next> | 433 template<SkColorType colorType, SkGammaType gammaType, typename Next> |
434 class BilerpSampler : public SkLinearBitmapPipeline::SampleProcessorInterface { | 434 class BilerpSampler : public SkLinearBitmapPipeline::SampleProcessorInterface { |
435 public: | 435 public: |
436 template<typename... Args> | 436 template<typename... Args> |
437 BilerpSampler(SkLinearBitmapPipeline::BlendProcessorInterface* next, Args&&
... args) | 437 BilerpSampler(SkLinearBitmapPipeline::BlendProcessorInterface* next, Args&&
... args) |
438 : fNext{next}, fStrategy{std::forward<Args>(args)...} { } | 438 : fNext{next}, fStrategy{std::forward<Args>(args)...} { } |
439 | 439 |
440 BilerpSampler(SkLinearBitmapPipeline::BlendProcessorInterface* next, | 440 BilerpSampler(SkLinearBitmapPipeline::BlendProcessorInterface* next, |
441 const BilerpSampler& sampler) | 441 const BilerpSampler& sampler) |
442 : fNext{next}, fStrategy{sampler.fStrategy} { } | 442 : fNext{next}, fStrategy{sampler.fStrategy} { } |
443 | 443 |
(...skipping 350 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
794 Sk4f ys = {y - 0.5f, y - 0.5f, y1 + 0.5f, y1 + 0.5f}; | 794 Sk4f ys = {y - 0.5f, y - 0.5f, y1 + 0.5f, y1 + 0.5f}; |
795 while (count > 0) { | 795 while (count > 0) { |
796 Sk4f xs = Sk4f{-0.5f, 0.5f, -0.5f, 0.5f} + Sk4f{x}; | 796 Sk4f xs = Sk4f{-0.5f, 0.5f, -0.5f, 0.5f} + Sk4f{x}; |
797 this->bilerpEdge(xs, ys); | 797 this->bilerpEdge(xs, ys); |
798 x += dx; | 798 x += dx; |
799 count -= 1; | 799 count -= 1; |
800 } | 800 } |
801 } | 801 } |
802 } | 802 } |
803 | 803 |
804 Next* const fNext; | 804 Next* const fNext; |
805 PixelAccessor<colorType, colorProfile> fStrategy; | 805 PixelAccessor<colorType, gammaType> fStrategy; |
806 }; | 806 }; |
807 | 807 |
808 } // namespace | 808 } // namespace |
809 | 809 |
810 #endif // SkLinearBitmapPipeline_sampler_DEFINED | 810 #endif // SkLinearBitmapPipeline_sampler_DEFINED |
OLD | NEW |