1 /*
2 * Copyright 2015 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 #include "src/codec/SkSwizzler.h"
9
10 #include "include/core/SkAlphaType.h"
11 #include "include/core/SkColorPriv.h"
12 #include "include/core/SkColorType.h"
13 #include "include/core/SkImageInfo.h"
14 #include "include/core/SkRect.h"
15 #include "include/private/SkColorData.h"
16 #include "include/private/SkEncodedInfo.h"
17 #include "include/private/base/SkAlign.h"
18 #include "include/private/base/SkCPUTypes.h"
19 #include "include/private/base/SkMath.h"
20 #include "src/base/SkHalf.h"
21 #include "include/private/base/SkTemplates.h"
22 #include "src/codec/SkCodecPriv.h"
23 #include "src/core/SkOpts.h"
24
25 #ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
26 #include "include/android/SkAndroidFrameworkUtils.h"
27 #endif
28
29 #include <cstring>
30
copy(void * dst,const uint8_t * src,int width,int bpp,int deltaSrc,int offset,const SkPMColor ctable[])31 static void copy(void* dst, const uint8_t* src, int width, int bpp, int deltaSrc, int offset,
32 const SkPMColor ctable[]) {
33 // This function must not be called if we are sampling. If we are not
34 // sampling, deltaSrc should equal bpp.
35 SkASSERT(deltaSrc == bpp);
36
37 memcpy(dst, src + offset, width * bpp);
38 }
39
sample1(void * dst,const uint8_t * src,int width,int bpp,int deltaSrc,int offset,const SkPMColor ctable[])40 static void sample1(void* dst, const uint8_t* src, int width, int bpp, int deltaSrc, int offset,
41 const SkPMColor ctable[]) {
42 src += offset;
43 uint8_t* dst8 = (uint8_t*) dst;
44 for (int x = 0; x < width; x++) {
45 dst8[x] = *src;
46 src += deltaSrc;
47 }
48 }
49
sample2(void * dst,const uint8_t * src,int width,int bpp,int deltaSrc,int offset,const SkPMColor ctable[])50 static void sample2(void* dst, const uint8_t* src, int width, int bpp, int deltaSrc, int offset,
51 const SkPMColor ctable[]) {
52 src += offset;
53 uint16_t* dst16 = (uint16_t*) dst;
54 for (int x = 0; x < width; x++) {
55 dst16[x] = *((const uint16_t*) src);
56 src += deltaSrc;
57 }
58 }
59
sample4(void * dst,const uint8_t * src,int width,int bpp,int deltaSrc,int offset,const SkPMColor ctable[])60 static void sample4(void* dst, const uint8_t* src, int width, int bpp, int deltaSrc, int offset,
61 const SkPMColor ctable[]) {
62 src += offset;
63 uint32_t* dst32 = (uint32_t*) dst;
64 for (int x = 0; x < width; x++) {
65 dst32[x] = *((const uint32_t*) src);
66 src += deltaSrc;
67 }
68 }
69
sample6(void * dst,const uint8_t * src,int width,int bpp,int deltaSrc,int offset,const SkPMColor ctable[])70 static void sample6(void* dst, const uint8_t* src, int width, int bpp, int deltaSrc, int offset,
71 const SkPMColor ctable[]) {
72 src += offset;
73 uint8_t* dst8 = (uint8_t*) dst;
74 for (int x = 0; x < width; x++) {
75 memcpy(dst8, src, 6);
76 dst8 += 6;
77 src += deltaSrc;
78 }
79 }
80
sample8(void * dst,const uint8_t * src,int width,int bpp,int deltaSrc,int offset,const SkPMColor ctable[])81 static void sample8(void* dst, const uint8_t* src, int width, int bpp, int deltaSrc, int offset,
82 const SkPMColor ctable[]) {
83 src += offset;
84 uint64_t* dst64 = (uint64_t*) dst;
85 for (int x = 0; x < width; x++) {
86 dst64[x] = *((const uint64_t*) src);
87 src += deltaSrc;
88 }
89 }
90
91 // kBit
92 // These routines exclusively choose between white and black
93
94 #define GRAYSCALE_BLACK 0
95 #define GRAYSCALE_WHITE 0xFF
96
97
98 // same as swizzle_bit_to_index and swizzle_bit_to_n32 except for value assigned to dst[x]
swizzle_bit_to_grayscale(void * SK_RESTRICT dstRow,const uint8_t * SK_RESTRICT src,int dstWidth,int bpp,int deltaSrc,int offset,const SkPMColor *)99 static void swizzle_bit_to_grayscale(
100 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
101 int bpp, int deltaSrc, int offset, const SkPMColor* /*ctable*/) {
102
103 uint8_t* SK_RESTRICT dst = (uint8_t*) dstRow;
104
105 // increment src by byte offset and bitIndex by bit offset
106 src += offset / 8;
107 int bitIndex = offset % 8;
108 uint8_t currByte = *src;
109
110 dst[0] = ((currByte >> (7-bitIndex)) & 1) ? GRAYSCALE_WHITE : GRAYSCALE_BLACK;
111
112 for (int x = 1; x < dstWidth; x++) {
113 int bitOffset = bitIndex + deltaSrc;
114 bitIndex = bitOffset % 8;
115 currByte = *(src += bitOffset / 8);
116 dst[x] = ((currByte >> (7-bitIndex)) & 1) ? GRAYSCALE_WHITE : GRAYSCALE_BLACK;
117 }
118 }
119
120 #undef GRAYSCALE_BLACK
121 #undef GRAYSCALE_WHITE
122
123 // same as swizzle_bit_to_grayscale and swizzle_bit_to_index except for value assigned to dst[x]
swizzle_bit_to_n32(void * SK_RESTRICT dstRow,const uint8_t * SK_RESTRICT src,int dstWidth,int bpp,int deltaSrc,int offset,const SkPMColor *)124 static void swizzle_bit_to_n32(
125 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
126 int bpp, int deltaSrc, int offset, const SkPMColor* /*ctable*/) {
127 SkPMColor* SK_RESTRICT dst = (SkPMColor*) dstRow;
128
129 // increment src by byte offset and bitIndex by bit offset
130 src += offset / 8;
131 int bitIndex = offset % 8;
132 uint8_t currByte = *src;
133
134 dst[0] = ((currByte >> (7 - bitIndex)) & 1) ? SK_ColorWHITE : SK_ColorBLACK;
135
136 for (int x = 1; x < dstWidth; x++) {
137 int bitOffset = bitIndex + deltaSrc;
138 bitIndex = bitOffset % 8;
139 currByte = *(src += bitOffset / 8);
140 dst[x] = ((currByte >> (7 - bitIndex)) & 1) ? SK_ColorWHITE : SK_ColorBLACK;
141 }
142 }
143
144 #define RGB565_BLACK 0
145 #define RGB565_WHITE 0xFFFF
146
swizzle_bit_to_565(void * SK_RESTRICT dstRow,const uint8_t * SK_RESTRICT src,int dstWidth,int bpp,int deltaSrc,int offset,const SkPMColor *)147 static void swizzle_bit_to_565(
148 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
149 int bpp, int deltaSrc, int offset, const SkPMColor* /*ctable*/) {
150 uint16_t* SK_RESTRICT dst = (uint16_t*) dstRow;
151
152 // increment src by byte offset and bitIndex by bit offset
153 src += offset / 8;
154 int bitIndex = offset % 8;
155 uint8_t currByte = *src;
156
157 dst[0] = ((currByte >> (7 - bitIndex)) & 1) ? RGB565_WHITE : RGB565_BLACK;
158
159 for (int x = 1; x < dstWidth; x++) {
160 int bitOffset = bitIndex + deltaSrc;
161 bitIndex = bitOffset % 8;
162 currByte = *(src += bitOffset / 8);
163 dst[x] = ((currByte >> (7 - bitIndex)) & 1) ? RGB565_WHITE : RGB565_BLACK;
164 }
165 }
166
167 #undef RGB565_BLACK
168 #undef RGB565_WHITE
169
swizzle_bit_to_f16(void * SK_RESTRICT dstRow,const uint8_t * SK_RESTRICT src,int dstWidth,int bpp,int deltaSrc,int offset,const SkPMColor *)170 static void swizzle_bit_to_f16(
171 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
172 int bpp, int deltaSrc, int offset, const SkPMColor* /*ctable*/) {
173 constexpr uint64_t kWhite = (((uint64_t) SK_Half1) << 0) |
174 (((uint64_t) SK_Half1) << 16) |
175 (((uint64_t) SK_Half1) << 32) |
176 (((uint64_t) SK_Half1) << 48);
177 constexpr uint64_t kBlack = (((uint64_t) 0) << 0) |
178 (((uint64_t) 0) << 16) |
179 (((uint64_t) 0) << 32) |
180 (((uint64_t) SK_Half1) << 48);
181
182 uint64_t* SK_RESTRICT dst = (uint64_t*) dstRow;
183
184 // increment src by byte offset and bitIndex by bit offset
185 src += offset / 8;
186 int bitIndex = offset % 8;
187 uint8_t currByte = *src;
188
189 dst[0] = ((currByte >> (7 - bitIndex)) & 1) ? kWhite : kBlack;
190
191 for (int x = 1; x < dstWidth; x++) {
192 int bitOffset = bitIndex + deltaSrc;
193 bitIndex = bitOffset % 8;
194 currByte = *(src += bitOffset / 8);
195 dst[x] = ((currByte >> (7 - bitIndex)) & 1) ? kWhite : kBlack;
196 }
197 }
198
199 // kIndex1, kIndex2, kIndex4
200
swizzle_small_index_to_565(void * SK_RESTRICT dstRow,const uint8_t * SK_RESTRICT src,int dstWidth,int bpp,int deltaSrc,int offset,const SkPMColor ctable[])201 static void swizzle_small_index_to_565(
202 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
203 int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) {
204
205 uint16_t* dst = (uint16_t*) dstRow;
206 src += offset / 8;
207 int bitIndex = offset % 8;
208 uint8_t currByte = *src;
209 const uint8_t mask = (1 << bpp) - 1;
210 uint8_t index = (currByte >> (8 - bpp - bitIndex)) & mask;
211 dst[0] = SkPixel32ToPixel16(ctable[index]);
212
213 for (int x = 1; x < dstWidth; x++) {
214 int bitOffset = bitIndex + deltaSrc;
215 bitIndex = bitOffset % 8;
216 currByte = *(src += bitOffset / 8);
217 index = (currByte >> (8 - bpp - bitIndex)) & mask;
218 dst[x] = SkPixel32ToPixel16(ctable[index]);
219 }
220 }
221
swizzle_small_index_to_n32(void * SK_RESTRICT dstRow,const uint8_t * SK_RESTRICT src,int dstWidth,int bpp,int deltaSrc,int offset,const SkPMColor ctable[])222 static void swizzle_small_index_to_n32(
223 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
224 int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) {
225
226 SkPMColor* dst = (SkPMColor*) dstRow;
227 src += offset / 8;
228 int bitIndex = offset % 8;
229 uint8_t currByte = *src;
230 const uint8_t mask = (1 << bpp) - 1;
231 uint8_t index = (currByte >> (8 - bpp - bitIndex)) & mask;
232 dst[0] = ctable[index];
233
234 for (int x = 1; x < dstWidth; x++) {
235 int bitOffset = bitIndex + deltaSrc;
236 bitIndex = bitOffset % 8;
237 currByte = *(src += bitOffset / 8);
238 index = (currByte >> (8 - bpp - bitIndex)) & mask;
239 dst[x] = ctable[index];
240 }
241 }
242
243 // kIndex
244
swizzle_index_to_n32(void * SK_RESTRICT dstRow,const uint8_t * SK_RESTRICT src,int dstWidth,int bpp,int deltaSrc,int offset,const SkPMColor ctable[])245 static void swizzle_index_to_n32(
246 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
247 int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) {
248
249 src += offset;
250 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
251 for (int x = 0; x < dstWidth; x++) {
252 SkPMColor c = ctable[*src];
253 dst[x] = c;
254 src += deltaSrc;
255 }
256 }
257
swizzle_index_to_n32_skipZ(void * SK_RESTRICT dstRow,const uint8_t * SK_RESTRICT src,int dstWidth,int bpp,int deltaSrc,int offset,const SkPMColor ctable[])258 static void swizzle_index_to_n32_skipZ(
259 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
260 int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) {
261
262 src += offset;
263 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
264 for (int x = 0; x < dstWidth; x++) {
265 SkPMColor c = ctable[*src];
266 if (c != 0) {
267 dst[x] = c;
268 }
269 src += deltaSrc;
270 }
271 }
272
swizzle_index_to_565(void * SK_RESTRICT dstRow,const uint8_t * SK_RESTRICT src,int dstWidth,int bytesPerPixel,int deltaSrc,int offset,const SkPMColor ctable[])273 static void swizzle_index_to_565(
274 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
275 int bytesPerPixel, int deltaSrc, int offset, const SkPMColor ctable[]) {
276 src += offset;
277 uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow;
278 for (int x = 0; x < dstWidth; x++) {
279 dst[x] = SkPixel32ToPixel16(ctable[*src]);
280 src += deltaSrc;
281 }
282 }
283
284 // kGray
285
swizzle_gray_to_n32(void * SK_RESTRICT dstRow,const uint8_t * SK_RESTRICT src,int dstWidth,int bpp,int deltaSrc,int offset,const SkPMColor ctable[])286 static void swizzle_gray_to_n32(
287 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
288 int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) {
289
290 src += offset;
291 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
292 for (int x = 0; x < dstWidth; x++) {
293 dst[x] = SkPackARGB32NoCheck(0xFF, *src, *src, *src);
294 src += deltaSrc;
295 }
296 }
297
fast_swizzle_gray_to_n32(void * dst,const uint8_t * src,int width,int bpp,int deltaSrc,int offset,const SkPMColor ctable[])298 static void fast_swizzle_gray_to_n32(
299 void* dst, const uint8_t* src, int width, int bpp, int deltaSrc, int offset,
300 const SkPMColor ctable[]) {
301
302 // This function must not be called if we are sampling. If we are not
303 // sampling, deltaSrc should equal bpp.
304 SkASSERT(deltaSrc == bpp);
305
306 // Note that there is no need to distinguish between RGB and BGR.
307 // Each color channel will get the same value.
308 SkOpts::gray_to_RGB1((uint32_t*) dst, src + offset, width);
309 }
310
swizzle_gray_to_565(void * SK_RESTRICT dstRow,const uint8_t * SK_RESTRICT src,int dstWidth,int bytesPerPixel,int deltaSrc,int offset,const SkPMColor ctable[])311 static void swizzle_gray_to_565(
312 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
313 int bytesPerPixel, int deltaSrc, int offset, const SkPMColor ctable[]) {
314
315 src += offset;
316 uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow;
317 for (int x = 0; x < dstWidth; x++) {
318 dst[x] = SkPack888ToRGB16(src[0], src[0], src[0]);
319 src += deltaSrc;
320 }
321 }
322
323 // kGrayAlpha
324
swizzle_grayalpha_to_n32_unpremul(void * dst,const uint8_t * src,int width,int bpp,int deltaSrc,int offset,const SkPMColor ctable[])325 static void swizzle_grayalpha_to_n32_unpremul(
326 void* dst, const uint8_t* src, int width, int bpp, int deltaSrc, int offset,
327 const SkPMColor ctable[]) {
328
329 src += offset;
330 SkPMColor* dst32 = (SkPMColor*) dst;
331 for (int x = 0; x < width; x++) {
332 dst32[x] = SkPackARGB32NoCheck(src[1], src[0], src[0], src[0]);
333 src += deltaSrc;
334 }
335 }
336
fast_swizzle_grayalpha_to_n32_unpremul(void * dst,const uint8_t * src,int width,int bpp,int deltaSrc,int offset,const SkPMColor ctable[])337 static void fast_swizzle_grayalpha_to_n32_unpremul(
338 void* dst, const uint8_t* src, int width, int bpp, int deltaSrc, int offset,
339 const SkPMColor ctable[]) {
340
341 // This function must not be called if we are sampling. If we are not
342 // sampling, deltaSrc should equal bpp.
343 SkASSERT(deltaSrc == bpp);
344
345 // Note that there is no need to distinguish between RGB and BGR.
346 // Each color channel will get the same value.
347 SkOpts::grayA_to_RGBA((uint32_t*) dst, src + offset, width);
348 }
349
swizzle_grayalpha_to_n32_premul(void * dst,const uint8_t * src,int width,int bpp,int deltaSrc,int offset,const SkPMColor ctable[])350 static void swizzle_grayalpha_to_n32_premul(
351 void* dst, const uint8_t* src, int width, int bpp, int deltaSrc, int offset,
352 const SkPMColor ctable[]) {
353
354 src += offset;
355 SkPMColor* dst32 = (SkPMColor*) dst;
356 for (int x = 0; x < width; x++) {
357 uint8_t pmgray = SkMulDiv255Round(src[1], src[0]);
358 dst32[x] = SkPackARGB32NoCheck(src[1], pmgray, pmgray, pmgray);
359 src += deltaSrc;
360 }
361 }
362
fast_swizzle_grayalpha_to_n32_premul(void * dst,const uint8_t * src,int width,int bpp,int deltaSrc,int offset,const SkPMColor ctable[])363 static void fast_swizzle_grayalpha_to_n32_premul(
364 void* dst, const uint8_t* src, int width, int bpp, int deltaSrc, int offset,
365 const SkPMColor ctable[]) {
366
367 // This function must not be called if we are sampling. If we are not
368 // sampling, deltaSrc should equal bpp.
369 SkASSERT(deltaSrc == bpp);
370
371 // Note that there is no need to distinguish between rgb and bgr.
372 // Each color channel will get the same value.
373 SkOpts::grayA_to_rgbA((uint32_t*) dst, src + offset, width);
374 }
375
swizzle_grayalpha_to_a8(void * dst,const uint8_t * src,int width,int bpp,int deltaSrc,int offset,const SkPMColor[])376 static void swizzle_grayalpha_to_a8(void* dst, const uint8_t* src, int width, int bpp,
377 int deltaSrc, int offset, const SkPMColor[]) {
378 src += offset;
379 uint8_t* dst8 = (uint8_t*)dst;
380 for (int x = 0; x < width; ++x) {
381 dst8[x] = src[1]; // src[0] is gray, ignored
382 src += deltaSrc;
383 }
384 }
385
386 // kBGR
387
swizzle_bgr_to_565(void * SK_RESTRICT dstRow,const uint8_t * SK_RESTRICT src,int dstWidth,int bpp,int deltaSrc,int offset,const SkPMColor ctable[])388 static void swizzle_bgr_to_565(
389 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
390 int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) {
391
392 src += offset;
393 uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow;
394 for (int x = 0; x < dstWidth; x++) {
395 dst[x] = SkPack888ToRGB16(src[2], src[1], src[0]);
396 src += deltaSrc;
397 }
398 }
399
400 // kRGB
401
swizzle_rgb_to_rgba(void * SK_RESTRICT dstRow,const uint8_t * SK_RESTRICT src,int dstWidth,int bpp,int deltaSrc,int offset,const SkPMColor ctable[])402 static void swizzle_rgb_to_rgba(
403 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
404 int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) {
405
406 src += offset;
407 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
408 for (int x = 0; x < dstWidth; x++) {
409 dst[x] = SkPackARGB_as_RGBA(0xFF, src[0], src[1], src[2]);
410 src += deltaSrc;
411 }
412 }
413
swizzle_rgb_to_bgra(void * SK_RESTRICT dstRow,const uint8_t * SK_RESTRICT src,int dstWidth,int bpp,int deltaSrc,int offset,const SkPMColor ctable[])414 static void swizzle_rgb_to_bgra(
415 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
416 int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) {
417
418 src += offset;
419 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
420 for (int x = 0; x < dstWidth; x++) {
421 dst[x] = SkPackARGB_as_BGRA(0xFF, src[0], src[1], src[2]);
422 src += deltaSrc;
423 }
424 }
425
fast_swizzle_rgb_to_rgba(void * dst,const uint8_t * src,int width,int bpp,int deltaSrc,int offset,const SkPMColor ctable[])426 static void fast_swizzle_rgb_to_rgba(
427 void* dst, const uint8_t* src, int width, int bpp, int deltaSrc,
428 int offset, const SkPMColor ctable[]) {
429
430 // This function must not be called if we are sampling. If we are not
431 // sampling, deltaSrc should equal bpp.
432 SkASSERT(deltaSrc == bpp);
433
434 SkOpts::RGB_to_RGB1((uint32_t*) dst, src + offset, width);
435 }
436
fast_swizzle_rgb_to_bgra(void * dst,const uint8_t * src,int width,int bpp,int deltaSrc,int offset,const SkPMColor ctable[])437 static void fast_swizzle_rgb_to_bgra(
438 void* dst, const uint8_t* src, int width, int bpp, int deltaSrc,
439 int offset, const SkPMColor ctable[]) {
440
441 // This function must not be called if we are sampling. If we are not
442 // sampling, deltaSrc should equal bpp.
443 SkASSERT(deltaSrc == bpp);
444
445 SkOpts::RGB_to_BGR1((uint32_t*) dst, src + offset, width);
446 }
447
swizzle_rgb_to_565(void * SK_RESTRICT dstRow,const uint8_t * SK_RESTRICT src,int dstWidth,int bytesPerPixel,int deltaSrc,int offset,const SkPMColor ctable[])448 static void swizzle_rgb_to_565(
449 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
450 int bytesPerPixel, int deltaSrc, int offset, const SkPMColor ctable[]) {
451
452 src += offset;
453 uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow;
454 for (int x = 0; x < dstWidth; x++) {
455 dst[x] = SkPack888ToRGB16(src[0], src[1], src[2]);
456 src += deltaSrc;
457 }
458 }
459
460 // kRGBA
461
swizzle_rgba_to_rgba_premul(void * SK_RESTRICT dstRow,const uint8_t * SK_RESTRICT src,int dstWidth,int bpp,int deltaSrc,int offset,const SkPMColor ctable[])462 static void swizzle_rgba_to_rgba_premul(
463 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
464 int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) {
465
466 src += offset;
467 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
468 for (int x = 0; x < dstWidth; x++) {
469 dst[x] = premultiply_argb_as_rgba(src[3], src[0], src[1], src[2]);
470 src += deltaSrc;
471 }
472 }
473
swizzle_rgba_to_bgra_premul(void * SK_RESTRICT dstRow,const uint8_t * SK_RESTRICT src,int dstWidth,int bpp,int deltaSrc,int offset,const SkPMColor ctable[])474 static void swizzle_rgba_to_bgra_premul(
475 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
476 int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) {
477
478 src += offset;
479 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
480 for (int x = 0; x < dstWidth; x++) {
481 dst[x] = premultiply_argb_as_bgra(src[3], src[0], src[1], src[2]);
482 src += deltaSrc;
483 }
484 }
485
fast_swizzle_rgba_to_rgba_premul(void * dst,const uint8_t * src,int width,int bpp,int deltaSrc,int offset,const SkPMColor ctable[])486 static void fast_swizzle_rgba_to_rgba_premul(
487 void* dst, const uint8_t* src, int width, int bpp, int deltaSrc,
488 int offset, const SkPMColor ctable[]) {
489
490 // This function must not be called if we are sampling. If we are not
491 // sampling, deltaSrc should equal bpp.
492 SkASSERT(deltaSrc == bpp);
493
494 SkOpts::RGBA_to_rgbA((uint32_t*) dst, (const uint32_t*)(src + offset), width);
495 }
496
fast_swizzle_rgba_to_bgra_premul(void * dst,const uint8_t * src,int width,int bpp,int deltaSrc,int offset,const SkPMColor ctable[])497 static void fast_swizzle_rgba_to_bgra_premul(
498 void* dst, const uint8_t* src, int width, int bpp, int deltaSrc,
499 int offset, const SkPMColor ctable[]) {
500
501 // This function must not be called if we are sampling. If we are not
502 // sampling, deltaSrc should equal bpp.
503 SkASSERT(deltaSrc == bpp);
504
505 SkOpts::RGBA_to_bgrA((uint32_t*) dst, (const uint32_t*)(src + offset), width);
506 }
507
swizzle_rgba_to_bgra_unpremul(void * SK_RESTRICT dstRow,const uint8_t * SK_RESTRICT src,int dstWidth,int bpp,int deltaSrc,int offset,const SkPMColor ctable[])508 static void swizzle_rgba_to_bgra_unpremul(
509 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
510 int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) {
511
512 src += offset;
513 uint32_t* SK_RESTRICT dst = reinterpret_cast<uint32_t*>(dstRow);
514 for (int x = 0; x < dstWidth; x++) {
515 unsigned alpha = src[3];
516 dst[x] = SkPackARGB_as_BGRA(alpha, src[0], src[1], src[2]);
517 src += deltaSrc;
518 }
519 }
520
fast_swizzle_rgba_to_bgra_unpremul(void * dst,const uint8_t * src,int width,int bpp,int deltaSrc,int offset,const SkPMColor ctable[])521 static void fast_swizzle_rgba_to_bgra_unpremul(
522 void* dst, const uint8_t* src, int width, int bpp, int deltaSrc, int offset,
523 const SkPMColor ctable[]) {
524
525 // This function must not be called if we are sampling. If we are not
526 // sampling, deltaSrc should equal bpp.
527 SkASSERT(deltaSrc == bpp);
528
529 SkOpts::RGBA_to_BGRA((uint32_t*) dst, (const uint32_t*)(src + offset), width);
530 }
531
532 // 16-bits per component kRGB and kRGBA
533
swizzle_rgb16_to_rgba(void * dst,const uint8_t * src,int width,int bpp,int deltaSrc,int offset,const SkPMColor ctable[])534 static void swizzle_rgb16_to_rgba(
535 void* dst, const uint8_t* src, int width, int bpp, int deltaSrc, int offset,
536 const SkPMColor ctable[]) {
537 auto strip16to8 = [](const uint8_t* ptr) {
538 return 0xFF000000 | (ptr[4] << 16) | (ptr[2] << 8) | ptr[0];
539 };
540
541 src += offset;
542 uint32_t* dst32 = (uint32_t*) dst;
543 for (int x = 0; x < width; x++) {
544 dst32[x] = strip16to8(src);
545 src += deltaSrc;
546 }
547 }
548
swizzle_rgb16_to_bgra(void * dst,const uint8_t * src,int width,int bpp,int deltaSrc,int offset,const SkPMColor ctable[])549 static void swizzle_rgb16_to_bgra(
550 void* dst, const uint8_t* src, int width, int bpp, int deltaSrc, int offset,
551 const SkPMColor ctable[]) {
552 auto strip16to8 = [](const uint8_t* ptr) {
553 return 0xFF000000 | (ptr[0] << 16) | (ptr[2] << 8) | ptr[4];
554 };
555
556 src += offset;
557 uint32_t* dst32 = (uint32_t*) dst;
558 for (int x = 0; x < width; x++) {
559 dst32[x] = strip16to8(src);
560 src += deltaSrc;
561 }
562 }
563
swizzle_rgb16_to_565(void * dst,const uint8_t * src,int width,int bpp,int deltaSrc,int offset,const SkPMColor ctable[])564 static void swizzle_rgb16_to_565(
565 void* dst, const uint8_t* src, int width, int bpp, int deltaSrc, int offset,
566 const SkPMColor ctable[]) {
567 auto strip16to565 = [](const uint8_t* ptr) {
568 return SkPack888ToRGB16(ptr[0], ptr[2], ptr[4]);
569 };
570
571 src += offset;
572 uint16_t* dst16 = (uint16_t*) dst;
573 for (int x = 0; x < width; x++) {
574 dst16[x] = strip16to565(src);
575 src += deltaSrc;
576 }
577 }
578
swizzle_rgba16_to_rgba_unpremul(void * dst,const uint8_t * src,int width,int bpp,int deltaSrc,int offset,const SkPMColor ctable[])579 static void swizzle_rgba16_to_rgba_unpremul(
580 void* dst, const uint8_t* src, int width, int bpp, int deltaSrc, int offset,
581 const SkPMColor ctable[]) {
582 auto strip16to8 = [](const uint8_t* ptr) {
583 return (ptr[6] << 24) | (ptr[4] << 16) | (ptr[2] << 8) | ptr[0];
584 };
585
586 src += offset;
587 uint32_t* dst32 = (uint32_t*) dst;
588 for (int x = 0; x < width; x++) {
589 dst32[x] = strip16to8(src);
590 src += deltaSrc;
591 }
592 }
593
swizzle_rgba16_to_rgba_premul(void * dst,const uint8_t * src,int width,int bpp,int deltaSrc,int offset,const SkPMColor ctable[])594 static void swizzle_rgba16_to_rgba_premul(
595 void* dst, const uint8_t* src, int width, int bpp, int deltaSrc, int offset,
596 const SkPMColor ctable[]) {
597 auto stripAndPremul16to8 = [](const uint8_t* ptr) {
598 return premultiply_argb_as_rgba(ptr[6], ptr[0], ptr[2], ptr[4]);
599 };
600
601 src += offset;
602 uint32_t* dst32 = (uint32_t*) dst;
603 for (int x = 0; x < width; x++) {
604 dst32[x] = stripAndPremul16to8(src);
605 src += deltaSrc;
606 }
607 }
608
swizzle_rgba16_to_bgra_unpremul(void * dst,const uint8_t * src,int width,int bpp,int deltaSrc,int offset,const SkPMColor ctable[])609 static void swizzle_rgba16_to_bgra_unpremul(
610 void* dst, const uint8_t* src, int width, int bpp, int deltaSrc, int offset,
611 const SkPMColor ctable[]) {
612 auto strip16to8 = [](const uint8_t* ptr) {
613 return (ptr[6] << 24) | (ptr[0] << 16) | (ptr[2] << 8) | ptr[4];
614 };
615
616 src += offset;
617 uint32_t* dst32 = (uint32_t*) dst;
618 for (int x = 0; x < width; x++) {
619 dst32[x] = strip16to8(src);
620 src += deltaSrc;
621 }
622 }
623
swizzle_rgba16_to_bgra_premul(void * dst,const uint8_t * src,int width,int bpp,int deltaSrc,int offset,const SkPMColor ctable[])624 static void swizzle_rgba16_to_bgra_premul(
625 void* dst, const uint8_t* src, int width, int bpp, int deltaSrc, int offset,
626 const SkPMColor ctable[]) {
627 auto stripAndPremul16to8 = [](const uint8_t* ptr) {
628 return premultiply_argb_as_bgra(ptr[6], ptr[0], ptr[2], ptr[4]);
629 };
630
631 src += offset;
632 uint32_t* dst32 = (uint32_t*) dst;
633 for (int x = 0; x < width; x++) {
634 dst32[x] = stripAndPremul16to8(src);
635 src += deltaSrc;
636 }
637 }
638
639 // kCMYK
640 //
641 // CMYK is stored as four bytes per pixel.
642 //
643 // We will implement a crude conversion from CMYK -> RGB using formulas
644 // from easyrgb.com.
645 //
646 // CMYK -> CMY
647 // C = C * (1 - K) + K
648 // M = M * (1 - K) + K
649 // Y = Y * (1 - K) + K
650 //
651 // libjpeg actually gives us inverted CMYK, so we must subtract the
652 // original terms from 1.
653 // CMYK -> CMY
654 // C = (1 - C) * (1 - (1 - K)) + (1 - K)
655 // M = (1 - M) * (1 - (1 - K)) + (1 - K)
656 // Y = (1 - Y) * (1 - (1 - K)) + (1 - K)
657 //
658 // Simplifying the above expression.
659 // CMYK -> CMY
660 // C = 1 - CK
661 // M = 1 - MK
662 // Y = 1 - YK
663 //
664 // CMY -> RGB
665 // R = (1 - C) * 255
666 // G = (1 - M) * 255
667 // B = (1 - Y) * 255
668 //
669 // Therefore the full conversion is below. This can be verified at
670 // www.rapidtables.com (assuming inverted CMYK).
671 // CMYK -> RGB
672 // R = C * K * 255
673 // G = M * K * 255
674 // B = Y * K * 255
675 //
676 // As a final note, we have treated the CMYK values as if they were on
677 // a scale from 0-1, when in fact they are 8-bit ints scaling from 0-255.
678 // We must divide each CMYK component by 255 to obtain the true conversion
679 // we should perform.
680 // CMYK -> RGB
681 // R = C * K / 255
682 // G = M * K / 255
683 // B = Y * K / 255
swizzle_cmyk_to_rgba(void * SK_RESTRICT dstRow,const uint8_t * SK_RESTRICT src,int dstWidth,int bpp,int deltaSrc,int offset,const SkPMColor ctable[])684 static void swizzle_cmyk_to_rgba(
685 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
686 int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) {
687
688 src += offset;
689 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
690 for (int x = 0; x < dstWidth; x++) {
691 const uint8_t r = SkMulDiv255Round(src[0], src[3]);
692 const uint8_t g = SkMulDiv255Round(src[1], src[3]);
693 const uint8_t b = SkMulDiv255Round(src[2], src[3]);
694
695 dst[x] = SkPackARGB_as_RGBA(0xFF, r, g, b);
696 src += deltaSrc;
697 }
698 }
699
swizzle_cmyk_to_bgra(void * SK_RESTRICT dstRow,const uint8_t * SK_RESTRICT src,int dstWidth,int bpp,int deltaSrc,int offset,const SkPMColor ctable[])700 static void swizzle_cmyk_to_bgra(
701 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
702 int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) {
703
704 src += offset;
705 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
706 for (int x = 0; x < dstWidth; x++) {
707 const uint8_t r = SkMulDiv255Round(src[0], src[3]);
708 const uint8_t g = SkMulDiv255Round(src[1], src[3]);
709 const uint8_t b = SkMulDiv255Round(src[2], src[3]);
710
711 dst[x] = SkPackARGB_as_BGRA(0xFF, r, g, b);
712 src += deltaSrc;
713 }
714 }
715
fast_swizzle_cmyk_to_rgba(void * dst,const uint8_t * src,int width,int bpp,int deltaSrc,int offset,const SkPMColor ctable[])716 static void fast_swizzle_cmyk_to_rgba(
717 void* dst, const uint8_t* src, int width, int bpp, int deltaSrc, int offset,
718 const SkPMColor ctable[]) {
719
720 // This function must not be called if we are sampling. If we are not
721 // sampling, deltaSrc should equal bpp.
722 SkASSERT(deltaSrc == bpp);
723
724 SkOpts::inverted_CMYK_to_RGB1((uint32_t*) dst, (const uint32_t*)(src + offset), width);
725 }
726
fast_swizzle_cmyk_to_bgra(void * dst,const uint8_t * src,int width,int bpp,int deltaSrc,int offset,const SkPMColor ctable[])727 static void fast_swizzle_cmyk_to_bgra(
728 void* dst, const uint8_t* src, int width, int bpp, int deltaSrc, int offset,
729 const SkPMColor ctable[]) {
730
731 // This function must not be called if we are sampling. If we are not
732 // sampling, deltaSrc should equal bpp.
733 SkASSERT(deltaSrc == bpp);
734
735 SkOpts::inverted_CMYK_to_BGR1((uint32_t*) dst, (const uint32_t*)(src + offset), width);
736 }
737
swizzle_cmyk_to_565(void * SK_RESTRICT dstRow,const uint8_t * SK_RESTRICT src,int dstWidth,int bpp,int deltaSrc,int offset,const SkPMColor ctable[])738 static void swizzle_cmyk_to_565(
739 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
740 int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) {
741
742 src += offset;
743 uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow;
744 for (int x = 0; x < dstWidth; x++) {
745 const uint8_t r = SkMulDiv255Round(src[0], src[3]);
746 const uint8_t g = SkMulDiv255Round(src[1], src[3]);
747 const uint8_t b = SkMulDiv255Round(src[2], src[3]);
748
749 dst[x] = SkPack888ToRGB16(r, g, b);
750 src += deltaSrc;
751 }
752 }
753
754 template <SkSwizzler::RowProc proc>
SkipLeadingGrayAlphaZerosThen(void * dst,const uint8_t * src,int width,int bpp,int deltaSrc,int offset,const SkPMColor ctable[])755 void SkSwizzler::SkipLeadingGrayAlphaZerosThen(
756 void* dst, const uint8_t* src, int width,
757 int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) {
758 SkASSERT(!ctable);
759
760 const uint16_t* src16 = (const uint16_t*) (src + offset);
761 uint32_t* dst32 = (uint32_t*) dst;
762
763 // This may miss opportunities to skip when the output is premultiplied,
764 // e.g. for a src pixel 0x00FF which is not zero but becomes zero after premultiplication.
765 while (width > 0 && *src16 == 0x0000) {
766 width--;
767 dst32++;
768 src16 += deltaSrc / 2;
769 }
770 proc(dst32, (const uint8_t*)src16, width, bpp, deltaSrc, 0, ctable);
771 }
772
773 template <SkSwizzler::RowProc proc>
SkipLeading8888ZerosThen(void * SK_RESTRICT dstRow,const uint8_t * SK_RESTRICT src,int dstWidth,int bpp,int deltaSrc,int offset,const SkPMColor ctable[])774 void SkSwizzler::SkipLeading8888ZerosThen(
775 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
776 int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) {
777 SkASSERT(!ctable);
778
779 auto src32 = (const uint32_t*)(src+offset);
780 auto dst32 = (uint32_t*)dstRow;
781
782 // This may miss opportunities to skip when the output is premultiplied,
783 // e.g. for a src pixel 0x00FFFFFF which is not zero but becomes zero after premultiplication.
784 while (dstWidth > 0 && *src32 == 0x00000000) {
785 dstWidth--;
786 dst32++;
787 src32 += deltaSrc/4;
788 }
789 proc(dst32, (const uint8_t*)src32, dstWidth, bpp, deltaSrc, 0, ctable);
790 }
791
MakeSimple(int srcBPP,const SkImageInfo & dstInfo,const SkCodec::Options & options)792 std::unique_ptr<SkSwizzler> SkSwizzler::MakeSimple(int srcBPP, const SkImageInfo& dstInfo,
793 const SkCodec::Options& options) {
794 RowProc proc = nullptr;
795 switch (srcBPP) {
796 case 1: // kGray_8_SkColorType
797 proc = &sample1;
798 break;
799 case 2: // kRGB_565_SkColorType
800 proc = &sample2;
801 break;
802 case 4: // kRGBA_8888_SkColorType
803 // kBGRA_8888_SkColorType
804 // kRGBA_1010102_SkColorType
805 proc = &sample4;
806 break;
807 case 6: // 16 bit PNG no alpha
808 proc = &sample6;
809 break;
810 case 8: // 16 bit PNG with alpha
811 proc = &sample8;
812 break;
813 default:
814 return nullptr;
815 }
816
817 return Make(dstInfo, ©, proc, nullptr /*ctable*/, srcBPP,
818 dstInfo.bytesPerPixel(), options, nullptr /*frame*/);
819 }
820
Make(const SkEncodedInfo & encodedInfo,const SkPMColor * ctable,const SkImageInfo & dstInfo,const SkCodec::Options & options,const SkIRect * frame)821 std::unique_ptr<SkSwizzler> SkSwizzler::Make(const SkEncodedInfo& encodedInfo,
822 const SkPMColor* ctable,
823 const SkImageInfo& dstInfo,
824 const SkCodec::Options& options,
825 const SkIRect* frame) {
826 if (SkEncodedInfo::kPalette_Color == encodedInfo.color() && nullptr == ctable) {
827 return nullptr;
828 }
829
830 RowProc fastProc = nullptr;
831 RowProc proc = nullptr;
832 SkCodec::ZeroInitialized zeroInit = options.fZeroInitialized;
833 const bool premultiply = (SkEncodedInfo::kOpaque_Alpha != encodedInfo.alpha()) &&
834 (kPremul_SkAlphaType == dstInfo.alphaType());
835
836 switch (encodedInfo.color()) {
837 case SkEncodedInfo::kGray_Color:
838 switch (encodedInfo.bitsPerComponent()) {
839 case 1:
840 switch (dstInfo.colorType()) {
841 case kRGBA_8888_SkColorType:
842 case kBGRA_8888_SkColorType:
843 proc = &swizzle_bit_to_n32;
844 break;
845 case kRGB_565_SkColorType:
846 proc = &swizzle_bit_to_565;
847 break;
848 case kGray_8_SkColorType:
849 proc = &swizzle_bit_to_grayscale;
850 break;
851 case kRGBA_F16_SkColorType:
852 proc = &swizzle_bit_to_f16;
853 break;
854 default:
855 return nullptr;
856 }
857 break;
858 case 8:
859 switch (dstInfo.colorType()) {
860 case kRGBA_8888_SkColorType:
861 case kBGRA_8888_SkColorType:
862 proc = &swizzle_gray_to_n32;
863 fastProc = &fast_swizzle_gray_to_n32;
864 break;
865 case kGray_8_SkColorType:
866 proc = &sample1;
867 fastProc = ©
868 break;
869 case kRGB_565_SkColorType:
870 proc = &swizzle_gray_to_565;
871 break;
872 default:
873 return nullptr;
874 }
875 break;
876 default:
877 return nullptr;
878 }
879 break;
880 case SkEncodedInfo::kXAlpha_Color:
881 case SkEncodedInfo::kGrayAlpha_Color:
882 switch (dstInfo.colorType()) {
883 case kRGBA_8888_SkColorType:
884 case kBGRA_8888_SkColorType:
885 if (premultiply) {
886 if (SkCodec::kYes_ZeroInitialized == zeroInit) {
887 proc = &SkipLeadingGrayAlphaZerosThen
888 <swizzle_grayalpha_to_n32_premul>;
889 fastProc = &SkipLeadingGrayAlphaZerosThen
890 <fast_swizzle_grayalpha_to_n32_premul>;
891 } else {
892 proc = &swizzle_grayalpha_to_n32_premul;
893 fastProc = &fast_swizzle_grayalpha_to_n32_premul;
894 }
895 } else {
896 if (SkCodec::kYes_ZeroInitialized == zeroInit) {
897 proc = &SkipLeadingGrayAlphaZerosThen
898 <swizzle_grayalpha_to_n32_unpremul>;
899 fastProc = &SkipLeadingGrayAlphaZerosThen
900 <fast_swizzle_grayalpha_to_n32_unpremul>;
901 } else {
902 proc = &swizzle_grayalpha_to_n32_unpremul;
903 fastProc = &fast_swizzle_grayalpha_to_n32_unpremul;
904 }
905 }
906 break;
907 case kAlpha_8_SkColorType:
908 proc = &swizzle_grayalpha_to_a8;
909 break;
910 default:
911 return nullptr;
912 }
913 break;
914 case SkEncodedInfo::kPalette_Color:
915 // We assume that the color table is premultiplied and swizzled
916 // as desired.
917 switch (encodedInfo.bitsPerComponent()) {
918 case 1:
919 case 2:
920 case 4:
921 switch (dstInfo.colorType()) {
922 case kRGBA_8888_SkColorType:
923 case kBGRA_8888_SkColorType:
924 proc = &swizzle_small_index_to_n32;
925 break;
926 case kRGB_565_SkColorType:
927 proc = &swizzle_small_index_to_565;
928 break;
929 default:
930 return nullptr;
931 }
932 break;
933 case 8:
934 switch (dstInfo.colorType()) {
935 case kRGBA_8888_SkColorType:
936 case kBGRA_8888_SkColorType:
937 if (SkCodec::kYes_ZeroInitialized == zeroInit) {
938 proc = &swizzle_index_to_n32_skipZ;
939 } else {
940 proc = &swizzle_index_to_n32;
941 }
942 break;
943 case kRGB_565_SkColorType:
944 proc = &swizzle_index_to_565;
945 break;
946 default:
947 return nullptr;
948 }
949 break;
950 default:
951 return nullptr;
952 }
953 break;
954 case SkEncodedInfo::k565_Color:
955 // Treat 565 exactly like RGB (since it's still encoded as 8 bits per component).
956 // We just mark as 565 when we have a hint that there are only 5/6/5 "significant"
957 // bits in each channel.
958 case SkEncodedInfo::kRGB_Color:
959 switch (dstInfo.colorType()) {
960 case kRGBA_8888_SkColorType:
961 if (16 == encodedInfo.bitsPerComponent()) {
962 proc = &swizzle_rgb16_to_rgba;
963 break;
964 }
965
966 SkASSERT(8 == encodedInfo.bitsPerComponent());
967 proc = &swizzle_rgb_to_rgba;
968 fastProc = &fast_swizzle_rgb_to_rgba;
969 break;
970 case kBGRA_8888_SkColorType:
971 if (16 == encodedInfo.bitsPerComponent()) {
972 proc = &swizzle_rgb16_to_bgra;
973 break;
974 }
975
976 SkASSERT(8 == encodedInfo.bitsPerComponent());
977 proc = &swizzle_rgb_to_bgra;
978 fastProc = &fast_swizzle_rgb_to_bgra;
979 break;
980 case kRGB_565_SkColorType:
981 if (16 == encodedInfo.bitsPerComponent()) {
982 proc = &swizzle_rgb16_to_565;
983 break;
984 }
985
986 proc = &swizzle_rgb_to_565;
987 break;
988 default:
989 return nullptr;
990 }
991 break;
992 case SkEncodedInfo::kRGBA_Color:
993 switch (dstInfo.colorType()) {
994 case kRGBA_8888_SkColorType:
995 if (16 == encodedInfo.bitsPerComponent()) {
996 proc = premultiply ? &swizzle_rgba16_to_rgba_premul :
997 &swizzle_rgba16_to_rgba_unpremul;
998 break;
999 }
1000
1001 SkASSERT(8 == encodedInfo.bitsPerComponent());
1002 if (premultiply) {
1003 if (SkCodec::kYes_ZeroInitialized == zeroInit) {
1004 proc = &SkipLeading8888ZerosThen<swizzle_rgba_to_rgba_premul>;
1005 fastProc = &SkipLeading8888ZerosThen
1006 <fast_swizzle_rgba_to_rgba_premul>;
1007 } else {
1008 proc = &swizzle_rgba_to_rgba_premul;
1009 fastProc = &fast_swizzle_rgba_to_rgba_premul;
1010 }
1011 } else {
1012 if (SkCodec::kYes_ZeroInitialized == zeroInit) {
1013 proc = &SkipLeading8888ZerosThen<sample4>;
1014 fastProc = &SkipLeading8888ZerosThen<copy>;
1015 } else {
1016 proc = &sample4;
1017 fastProc = ©
1018 }
1019 }
1020 break;
1021 case kBGRA_8888_SkColorType:
1022 if (16 == encodedInfo.bitsPerComponent()) {
1023 proc = premultiply ? &swizzle_rgba16_to_bgra_premul :
1024 &swizzle_rgba16_to_bgra_unpremul;
1025 break;
1026 }
1027
1028 SkASSERT(8 == encodedInfo.bitsPerComponent());
1029 if (premultiply) {
1030 if (SkCodec::kYes_ZeroInitialized == zeroInit) {
1031 proc = &SkipLeading8888ZerosThen<swizzle_rgba_to_bgra_premul>;
1032 fastProc = &SkipLeading8888ZerosThen
1033 <fast_swizzle_rgba_to_bgra_premul>;
1034 } else {
1035 proc = &swizzle_rgba_to_bgra_premul;
1036 fastProc = &fast_swizzle_rgba_to_bgra_premul;
1037 }
1038 } else {
1039 if (SkCodec::kYes_ZeroInitialized == zeroInit) {
1040 proc = &SkipLeading8888ZerosThen<swizzle_rgba_to_bgra_unpremul>;
1041 fastProc = &SkipLeading8888ZerosThen
1042 <fast_swizzle_rgba_to_bgra_unpremul>;
1043 } else {
1044 proc = &swizzle_rgba_to_bgra_unpremul;
1045 fastProc = &fast_swizzle_rgba_to_bgra_unpremul;
1046 }
1047 }
1048 break;
1049 default:
1050 return nullptr;
1051 }
1052 break;
1053 case SkEncodedInfo::kBGR_Color:
1054 switch (dstInfo.colorType()) {
1055 case kBGRA_8888_SkColorType:
1056 proc = &swizzle_rgb_to_rgba;
1057 fastProc = &fast_swizzle_rgb_to_rgba;
1058 break;
1059 case kRGBA_8888_SkColorType:
1060 proc = &swizzle_rgb_to_bgra;
1061 fastProc = &fast_swizzle_rgb_to_bgra;
1062 break;
1063 case kRGB_565_SkColorType:
1064 proc = &swizzle_bgr_to_565;
1065 break;
1066 default:
1067 return nullptr;
1068 }
1069 break;
1070 case SkEncodedInfo::kBGRX_Color:
1071 switch (dstInfo.colorType()) {
1072 case kBGRA_8888_SkColorType:
1073 proc = &swizzle_rgb_to_rgba;
1074 break;
1075 case kRGBA_8888_SkColorType:
1076 proc = &swizzle_rgb_to_bgra;
1077 break;
1078 case kRGB_565_SkColorType:
1079 proc = &swizzle_bgr_to_565;
1080 break;
1081 default:
1082 return nullptr;
1083 }
1084 break;
1085 case SkEncodedInfo::kBGRA_Color:
1086 switch (dstInfo.colorType()) {
1087 case kBGRA_8888_SkColorType:
1088 if (premultiply) {
1089 if (SkCodec::kYes_ZeroInitialized == zeroInit) {
1090 proc = &SkipLeading8888ZerosThen<swizzle_rgba_to_rgba_premul>;
1091 fastProc = &SkipLeading8888ZerosThen
1092 <fast_swizzle_rgba_to_rgba_premul>;
1093 } else {
1094 proc = &swizzle_rgba_to_rgba_premul;
1095 fastProc = &fast_swizzle_rgba_to_rgba_premul;
1096 }
1097 } else {
1098 if (SkCodec::kYes_ZeroInitialized == zeroInit) {
1099 proc = &SkipLeading8888ZerosThen<sample4>;
1100 fastProc = &SkipLeading8888ZerosThen<copy>;
1101 } else {
1102 proc = &sample4;
1103 fastProc = ©
1104 }
1105 }
1106 break;
1107 case kRGBA_8888_SkColorType:
1108 if (premultiply) {
1109 if (SkCodec::kYes_ZeroInitialized == zeroInit) {
1110 proc = &SkipLeading8888ZerosThen<swizzle_rgba_to_bgra_premul>;
1111 fastProc = &SkipLeading8888ZerosThen
1112 <fast_swizzle_rgba_to_bgra_premul>;
1113 } else {
1114 proc = &swizzle_rgba_to_bgra_premul;
1115 fastProc = &fast_swizzle_rgba_to_bgra_premul;
1116 }
1117 } else {
1118 if (SkCodec::kYes_ZeroInitialized == zeroInit) {
1119 proc = &SkipLeading8888ZerosThen<swizzle_rgba_to_bgra_unpremul>;
1120 fastProc = &SkipLeading8888ZerosThen
1121 <fast_swizzle_rgba_to_bgra_unpremul>;
1122 } else {
1123 proc = &swizzle_rgba_to_bgra_unpremul;
1124 fastProc = &fast_swizzle_rgba_to_bgra_unpremul;
1125 }
1126 }
1127 break;
1128 default:
1129 return nullptr;
1130 }
1131 break;
1132 case SkEncodedInfo::kInvertedCMYK_Color:
1133 switch (dstInfo.colorType()) {
1134 case kRGBA_8888_SkColorType:
1135 proc = &swizzle_cmyk_to_rgba;
1136 fastProc = &fast_swizzle_cmyk_to_rgba;
1137 break;
1138 case kBGRA_8888_SkColorType:
1139 proc = &swizzle_cmyk_to_bgra;
1140 fastProc = &fast_swizzle_cmyk_to_bgra;
1141 break;
1142 case kRGB_565_SkColorType:
1143 proc = &swizzle_cmyk_to_565;
1144 break;
1145 default:
1146 return nullptr;
1147 }
1148 break;
1149 default:
1150 return nullptr;
1151 }
1152
1153 // Store bpp in bytes if it is an even multiple, otherwise use bits
1154 uint8_t bitsPerPixel = encodedInfo.bitsPerPixel();
1155 int srcBPP = SkIsAlign8(bitsPerPixel) ? bitsPerPixel / 8 : bitsPerPixel;
1156 int dstBPP = dstInfo.bytesPerPixel();
1157 return Make(dstInfo, fastProc, proc, ctable, srcBPP, dstBPP, options, frame);
1158 }
1159
Make(const SkImageInfo & dstInfo,RowProc fastProc,RowProc proc,const SkPMColor * ctable,int srcBPP,int dstBPP,const SkCodec::Options & options,const SkIRect * frame)1160 std::unique_ptr<SkSwizzler> SkSwizzler::Make(const SkImageInfo& dstInfo,
1161 RowProc fastProc, RowProc proc, const SkPMColor* ctable, int srcBPP,
1162 int dstBPP, const SkCodec::Options& options, const SkIRect* frame) {
1163 int srcOffset = 0;
1164 int srcWidth = dstInfo.width();
1165 int dstOffset = 0;
1166 int dstWidth = srcWidth;
1167 if (options.fSubset) {
1168 // We do not currently support subset decodes for image types that may have
1169 // frames (gif).
1170 SkASSERT(!frame);
1171 srcOffset = options.fSubset->left();
1172 srcWidth = options.fSubset->width();
1173 dstWidth = srcWidth;
1174 } else if (frame) {
1175 dstOffset = frame->left();
1176 srcWidth = frame->width();
1177 }
1178
1179 return std::unique_ptr<SkSwizzler>(new SkSwizzler(fastProc, proc, ctable, srcOffset, srcWidth,
1180 dstOffset, dstWidth, srcBPP, dstBPP));
1181 }
1182
SkSwizzler(RowProc fastProc,RowProc proc,const SkPMColor * ctable,int srcOffset,int srcWidth,int dstOffset,int dstWidth,int srcBPP,int dstBPP)1183 SkSwizzler::SkSwizzler(RowProc fastProc, RowProc proc, const SkPMColor* ctable, int srcOffset,
1184 int srcWidth, int dstOffset, int dstWidth, int srcBPP, int dstBPP)
1185 : fFastProc(fastProc)
1186 , fSlowProc(proc)
1187 , fActualProc(fFastProc ? fFastProc : fSlowProc)
1188 , fColorTable(ctable)
1189 , fSrcOffset(srcOffset)
1190 , fDstOffset(dstOffset)
1191 , fSrcOffsetUnits(srcOffset * srcBPP)
1192 , fDstOffsetBytes(dstOffset * dstBPP)
1193 , fSrcWidth(srcWidth)
1194 , fDstWidth(dstWidth)
1195 , fSwizzleWidth(srcWidth)
1196 , fAllocatedWidth(dstWidth)
1197 , fSampleX(1)
1198 , fSrcBPP(srcBPP)
1199 , fDstBPP(dstBPP)
1200 {}
1201
onSetSampleX(int sampleX)1202 int SkSwizzler::onSetSampleX(int sampleX) {
1203 SkASSERT(sampleX > 0);
1204
1205 fSampleX = sampleX;
1206 fDstOffsetBytes = (fDstOffset / sampleX) * fDstBPP;
1207 fSwizzleWidth = get_scaled_dimension(fSrcWidth, sampleX);
1208 fAllocatedWidth = get_scaled_dimension(fDstWidth, sampleX);
1209
1210 int frameSampleX = sampleX;
1211 if (fSrcWidth < fDstWidth) {
1212 // Although SkSampledCodec adjusted sampleX so that it will never be
1213 // larger than the width of the image (or subset, if applicable), it
1214 // doesn't account for the width of a subset frame (i.e. gif). As a
1215 // result, get_start_coord(sampleX) could result in fSrcOffsetUnits
1216 // being wider than fSrcWidth. Compute a sampling rate based on the
1217 // frame width to ensure that fSrcOffsetUnits is sensible.
1218 frameSampleX = fSrcWidth / fSwizzleWidth;
1219 }
1220 fSrcOffsetUnits = (get_start_coord(frameSampleX) + fSrcOffset) * fSrcBPP;
1221
1222 if (fDstOffsetBytes > 0) {
1223 const size_t dstSwizzleBytes = fSwizzleWidth * fDstBPP;
1224 const size_t dstAllocatedBytes = fAllocatedWidth * fDstBPP;
1225 if (fDstOffsetBytes + dstSwizzleBytes > dstAllocatedBytes) {
1226 #ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
1227 SkAndroidFrameworkUtils::SafetyNetLog("118143775");
1228 #endif
1229 SkASSERT(dstSwizzleBytes <= dstAllocatedBytes);
1230 fDstOffsetBytes = dstAllocatedBytes - dstSwizzleBytes;
1231 }
1232 }
1233
1234 // The optimized swizzler functions do not support sampling. Sampled swizzles
1235 // are already fast because they skip pixels. We haven't seen a situation
1236 // where speeding up sampling has a significant impact on total decode time.
1237 if (1 == fSampleX && fFastProc) {
1238 fActualProc = fFastProc;
1239 } else {
1240 fActualProc = fSlowProc;
1241 }
1242
1243 return fAllocatedWidth;
1244 }
1245
swizzle(void * dst,const uint8_t * SK_RESTRICT src)1246 void SkSwizzler::swizzle(void* dst, const uint8_t* SK_RESTRICT src) {
1247 SkASSERT(nullptr != dst && nullptr != src);
1248 fActualProc(SkTAddOffset<void>(dst, fDstOffsetBytes), src, fSwizzleWidth, fSrcBPP,
1249 fSampleX * fSrcBPP, fSrcOffsetUnits, fColorTable);
1250 }
1251