Flutter Engine
The Flutter Engine
SkConvertPixels.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2014 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 */
8
11#include "include/core/SkSize.h"
16#include "src/base/SkHalf.h"
23
24#include <cstdint>
25#include <cstring>
26#include <initializer_list>
27
28static bool rect_memcpy(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRB,
29 const SkImageInfo& srcInfo, const void* srcPixels, size_t srcRB,
30 const SkColorSpaceXformSteps& steps) {
31 // We can copy the pixels when no color type, alpha type, or color space changes.
32 if (dstInfo.colorType() != srcInfo.colorType()) {
33 return false;
34 }
35 if (dstInfo.colorType() != kAlpha_8_SkColorType
36 && steps.flags.mask() != 0b00000) {
37 return false;
38 }
39
40 SkRectMemcpy(dstPixels, dstRB,
41 srcPixels, srcRB, dstInfo.minRowBytes(), dstInfo.height());
42 return true;
43}
44
45static bool swizzle_or_premul(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRB,
46 const SkImageInfo& srcInfo, const void* srcPixels, size_t srcRB,
47 const SkColorSpaceXformSteps& steps) {
48 auto is_8888 = [](SkColorType ct) {
50 };
51 if (!is_8888(dstInfo.colorType()) ||
52 !is_8888(srcInfo.colorType()) ||
53 steps.flags.linearize ||
54 steps.flags.gamut_transform ||
55#if !defined(SK_ARM_HAS_NEON)
56 steps.flags.unpremul ||
57#endif
58 steps.flags.encode) {
59 return false;
60 }
61
62 const bool swapRB = dstInfo.colorType() != srcInfo.colorType();
63
64 void (*fn)(uint32_t*, const uint32_t*, int) = nullptr;
65
66 if (steps.flags.premul) {
67 fn = swapRB ? SkOpts::RGBA_to_bgrA
69 } else if (steps.flags.unpremul) {
70 fn = swapRB ? SkOpts::rgbA_to_BGRA
72 } else {
73 // If we're not swizzling, we ought to have used rect_memcpy().
74 SkASSERT(swapRB);
76 }
77
78 for (int y = 0; y < dstInfo.height(); y++) {
79 fn((uint32_t*)dstPixels, (const uint32_t*)srcPixels, dstInfo.width());
80 dstPixels = SkTAddOffset<void>(dstPixels, dstRB);
81 srcPixels = SkTAddOffset<const void>(srcPixels, srcRB);
82 }
83 return true;
84}
85
86static bool convert_to_alpha8(const SkImageInfo& dstInfo, void* vdst, size_t dstRB,
87 const SkImageInfo& srcInfo, const void* src, size_t srcRB,
89 if (dstInfo.colorType() != kAlpha_8_SkColorType) {
90 return false;
91 }
92 auto dst = (uint8_t*)vdst;
93
94 switch (srcInfo.colorType()) {
97 // Unknown should never happen.
98 // Alpha8 should have been handled by rect_memcpy().
99 SkASSERT(false);
100 return false;
101 }
102
104 auto src16 = (const uint16_t*) src;
105 for (int y = 0; y < srcInfo.height(); y++) {
106 for (int x = 0; x < srcInfo.width(); x++) {
107 dst[x] = src16[x] >> 8;
108 }
109 dst = SkTAddOffset<uint8_t>(dst, dstRB);
110 src16 = SkTAddOffset<const uint16_t>(src16, srcRB);
111 }
112 return true;
113 }
114
125 for (int y = 0; y < srcInfo.height(); ++y) {
126 memset(dst, 0xFF, srcInfo.width());
127 dst = SkTAddOffset<uint8_t>(dst, dstRB);
128 }
129 return true;
130 }
131
133 auto src16 = (const uint16_t*) src;
134 for (int y = 0; y < srcInfo.height(); y++) {
135 for (int x = 0; x < srcInfo.width(); x++) {
136 dst[x] = SkPacked4444ToA32(src16[x]);
137 }
138 dst = SkTAddOffset<uint8_t>(dst, dstRB);
139 src16 = SkTAddOffset<const uint16_t>(src16, srcRB);
140 }
141 return true;
142 }
143
147 auto src32 = (const uint32_t*) src;
148 for (int y = 0; y < srcInfo.height(); y++) {
149 for (int x = 0; x < srcInfo.width(); x++) {
150 dst[x] = src32[x] >> 24;
151 }
152 dst = SkTAddOffset<uint8_t>(dst, dstRB);
153 src32 = SkTAddOffset<const uint32_t>(src32, srcRB);
154 }
155 return true;
156 }
157
160 auto src32 = (const uint32_t*) src;
161 for (int y = 0; y < srcInfo.height(); y++) {
162 for (int x = 0; x < srcInfo.width(); x++) {
163 dst[x] = (src32[x] >> 30) * 0x55;
164 }
165 dst = SkTAddOffset<uint8_t>(dst, dstRB);
166 src32 = SkTAddOffset<const uint32_t>(src32, srcRB);
167 }
168 return true;
169 }
170
173 auto src64 = (const uint64_t*) src;
174 for (int y = 0; y < srcInfo.height(); y++) {
175 for (int x = 0; x < srcInfo.width(); x++) {
176 dst[x] = (uint8_t) (255.0f * SkHalfToFloat(src64[x] >> 48));
177 }
178 dst = SkTAddOffset<uint8_t>(dst, dstRB);
179 src64 = SkTAddOffset<const uint64_t>(src64, srcRB);
180 }
181 return true;
182 }
183
185 auto rgba = (const float*)src;
186 for (int y = 0; y < srcInfo.height(); y++) {
187 for (int x = 0; x < srcInfo.width(); x++) {
188 dst[x] = (uint8_t)(255.0f * rgba[4*x+3]);
189 }
190 dst = SkTAddOffset<uint8_t>(dst, dstRB);
191 rgba = SkTAddOffset<const float>(rgba, srcRB);
192 }
193 return true;
194 }
195
197 auto srcF16 = (const uint16_t*) src;
198 for (int y = 0; y < srcInfo.height(); y++) {
199 for (int x = 0; x < srcInfo.width(); x++) {
200 dst[x] = (uint8_t) (255.0f * SkHalfToFloat(srcF16[x]));
201 }
202 dst = SkTAddOffset<uint8_t>(dst, dstRB);
203 srcF16 = SkTAddOffset<const uint16_t>(srcF16, srcRB);
204 }
205 return true;
206 }
207
209 auto src64 = (const uint64_t*) src;
210 for (int y = 0; y < srcInfo.height(); y++) {
211 for (int x = 0; x < srcInfo.width(); x++) {
212 static constexpr int64_t kZero = 384;
213 static constexpr int64_t kRange = 510;
214 static constexpr int64_t kMaxU8 = 0xff;
215 static constexpr int64_t kMinU8 = 0x00;
216 static constexpr int64_t kDivisor = kRange / kMaxU8;
217 int64_t raw_alpha = src64[x] >> 54;
218 // f(384) = 0
219 // f(894) = 255
220 int64_t alpha =
221 SkTPin((raw_alpha - kZero) / kDivisor, kMinU8, kMaxU8);
222 dst[x] = static_cast<uint8_t>(alpha);
223 }
224 dst = SkTAddOffset<uint8_t>(dst, dstRB);
225 src64 = SkTAddOffset<const uint64_t>(src64, srcRB);
226 }
227 return true;
228 }
231 auto src64 = (const uint64_t*) src;
232 for (int y = 0; y < srcInfo.height(); y++) {
233 for (int x = 0; x < srcInfo.width(); x++) {
234 dst[x] = (src64[x] >> 48) >> 8;
235 }
236 dst = SkTAddOffset<uint8_t>(dst, dstRB);
237 src64 = SkTAddOffset<const uint64_t>(src64, srcRB);
238 }
239 return true;
240 }
241 }
242 return false;
243}
244
245// Default: Use the pipeline.
246static void convert_with_pipeline(const SkImageInfo& dstInfo, void* dstRow, int dstStride,
247 const SkImageInfo& srcInfo, const void* srcRow, int srcStride,
248 const SkColorSpaceXformSteps& steps) {
249 SkRasterPipeline_MemoryCtx src = { const_cast<void*>(srcRow), srcStride },
250 dst = { dstRow, dstStride };
251
252 SkRasterPipeline_<256> pipeline;
253 pipeline.appendLoad(srcInfo.colorType(), &src);
254 steps.apply(&pipeline);
255 pipeline.appendStore(dstInfo.colorType(), &dst);
256 pipeline.run(0,0, srcInfo.width(), srcInfo.height());
257}
258
259bool SkConvertPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRB,
260 const SkImageInfo& srcInfo, const void* srcPixels, size_t srcRB) {
261 SkASSERT(dstInfo.dimensions() == srcInfo.dimensions());
262 SkASSERT(SkImageInfoValidConversion(dstInfo, srcInfo));
263
264 int srcStride = (int)(srcRB / srcInfo.bytesPerPixel());
265 int dstStride = (int)(dstRB / dstInfo.bytesPerPixel());
266 if ((size_t)srcStride * srcInfo.bytesPerPixel() != srcRB ||
267 (size_t)dstStride * dstInfo.bytesPerPixel() != dstRB) {
268 return false;
269 }
270
271 SkColorSpaceXformSteps steps{srcInfo.colorSpace(), srcInfo.alphaType(),
272 dstInfo.colorSpace(), dstInfo.alphaType()};
273
275 if (fn(dstInfo, dstPixels, dstRB, srcInfo, srcPixels, srcRB, steps)) {
276 return true;
277 }
278 }
279 convert_with_pipeline(dstInfo, dstPixels, dstStride, srcInfo, srcPixels, srcStride, steps);
280 return true;
281}
static const uint32_t rgba[kNumPixels]
#define SkASSERT(cond)
Definition: SkAssert.h:116
#define SkPacked4444ToA32(c)
Definition: SkColorData.h:366
SkColorType
Definition: SkColorType.h:19
@ kR16G16B16A16_unorm_SkColorType
pixel with a little endian uint16_t for red, green, blue
Definition: SkColorType.h:50
@ kRGBA_10x6_SkColorType
pixel with 10 used bits (most significant) followed by 6 unused
Definition: SkColorType.h:33
@ kR8_unorm_SkColorType
Definition: SkColorType.h:54
@ kBGR_101010x_SkColorType
pixel with 10 bits each for blue, green, red; in 32-bit word
Definition: SkColorType.h:30
@ kARGB_4444_SkColorType
pixel with 4 bits for alpha, red, green, blue; in 16-bit word
Definition: SkColorType.h:23
@ kR8G8_unorm_SkColorType
pixel with a uint8_t for red and green
Definition: SkColorType.h:43
@ kBGRA_8888_SkColorType
pixel with 8 bits for blue, green, red, alpha; in 32-bit word
Definition: SkColorType.h:26
@ kA16_unorm_SkColorType
pixel with a little endian uint16_t for alpha
Definition: SkColorType.h:48
@ kRGBA_F16_SkColorType
pixel with half floats for red, green, blue, alpha;
Definition: SkColorType.h:38
@ kAlpha_8_SkColorType
pixel with alpha in 8-bit byte
Definition: SkColorType.h:21
@ kRGB_101010x_SkColorType
pixel with 10 bits each for red, green, blue; in 32-bit word
Definition: SkColorType.h:29
@ kSRGBA_8888_SkColorType
Definition: SkColorType.h:53
@ kGray_8_SkColorType
pixel with grayscale level in 8-bit byte
Definition: SkColorType.h:35
@ kRGB_565_SkColorType
pixel with 5 bits red, 6 bits green, 5 bits blue, in 16-bit word
Definition: SkColorType.h:22
@ kBGRA_10101010_XR_SkColorType
pixel with 10 bits each for blue, green, red, alpha; in 64-bit word, extended range
Definition: SkColorType.h:32
@ kRGBA_8888_SkColorType
pixel with 8 bits for red, green, blue, alpha; in 32-bit word
Definition: SkColorType.h:24
@ kRGB_888x_SkColorType
pixel with 8 bits each for red, green, blue; in 32-bit word
Definition: SkColorType.h:25
@ kBGRA_1010102_SkColorType
10 bits for blue, green, red; 2 bits for alpha; in 32-bit word
Definition: SkColorType.h:28
@ kA16_float_SkColorType
pixel with a half float for alpha
Definition: SkColorType.h:45
@ kRGBA_F32_SkColorType
pixel using C float for red, green, blue, alpha; in 128-bit word
Definition: SkColorType.h:40
@ kRGBA_1010102_SkColorType
10 bits for red, green, blue; 2 bits for alpha; in 32-bit word
Definition: SkColorType.h:27
@ kBGR_101010x_XR_SkColorType
pixel with 10 bits each for blue, green, red; in 32-bit word, extended range
Definition: SkColorType.h:31
@ kR16G16_unorm_SkColorType
pixel with a little endian uint16_t for red and green
Definition: SkColorType.h:49
@ kRGBA_F16Norm_SkColorType
pixel with half floats in [0,1] for red, green, blue, alpha;
Definition: SkColorType.h:36
@ kUnknown_SkColorType
uninitialized
Definition: SkColorType.h:20
@ kR16G16_float_SkColorType
pixel with a half float for red and green
Definition: SkColorType.h:46
bool SkConvertPixels(const SkImageInfo &dstInfo, void *dstPixels, size_t dstRB, const SkImageInfo &srcInfo, const void *srcPixels, size_t srcRB)
static void convert_with_pipeline(const SkImageInfo &dstInfo, void *dstRow, int dstStride, const SkImageInfo &srcInfo, const void *srcRow, int srcStride, const SkColorSpaceXformSteps &steps)
static bool swizzle_or_premul(const SkImageInfo &dstInfo, void *dstPixels, size_t dstRB, const SkImageInfo &srcInfo, const void *srcPixels, size_t srcRB, const SkColorSpaceXformSteps &steps)
static bool convert_to_alpha8(const SkImageInfo &dstInfo, void *vdst, size_t dstRB, const SkImageInfo &srcInfo, const void *src, size_t srcRB, const SkColorSpaceXformSteps &)
static bool rect_memcpy(const SkImageInfo &dstInfo, void *dstPixels, size_t dstRB, const SkImageInfo &srcInfo, const void *srcPixels, size_t srcRB, const SkColorSpaceXformSteps &steps)
float SkHalfToFloat(SkHalf h)
Definition: SkHalf.cpp:24
static bool SkImageInfoValidConversion(const SkImageInfo &dst, const SkImageInfo &src)
static void SkRectMemcpy(void *dst, size_t dstRB, const void *src, size_t srcRB, size_t trimRowBytes, int rowCount)
Definition: SkRectMemcpy.h:16
static constexpr const T & SkTPin(const T &x, const T &lo, const T &hi)
Definition: SkTPin.h:19
static bool is_8888(SkColorType colorType)
void run(size_t x, size_t y, size_t w, size_t h) const
void appendLoad(SkColorType, const SkRasterPipeline_MemoryCtx *)
void appendStore(SkColorType, const SkRasterPipeline_MemoryCtx *)
double y
double x
Swizzle_8888_u32 RGBA_to_rgbA
Definition: SkSwizzlePriv.h:20
Swizzle_8888_u32 RGBA_to_BGRA
Swizzle_8888_u32 RGBA_to_bgrA
Definition: SkSwizzlePriv.h:21
Swizzle_8888_u32 rgbA_to_BGRA
Definition: SkSwizzlePriv.h:23
Swizzle_8888_u32 rgbA_to_RGBA
Definition: SkSwizzlePriv.h:22
dst
Definition: cp.py:12
constexpr uint32_t mask() const
void apply(float rgba[4]) const
size_t minRowBytes() const
Definition: SkImageInfo.h:517
SkColorSpace * colorSpace() const
int bytesPerPixel() const
Definition: SkImageInfo.h:492
SkISize dimensions() const
Definition: SkImageInfo.h:421
int width() const
Definition: SkImageInfo.h:365
SkAlphaType alphaType() const
Definition: SkImageInfo.h:375
SkColorType colorType() const
Definition: SkImageInfo.h:373
int height() const
Definition: SkImageInfo.h:371