| 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 |