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 "SkCodecPriv.h"
9 #include "SkColorPriv.h"
10 #include "SkOpts.h"
11 #include "SkSwizzler.h"
12 #include "SkTemplates.h"
13
copy(void * dst,const uint8_t * src,int width,int bpp,int deltaSrc,int offset,const SkPMColor ctable[])14 static void copy(void* dst, const uint8_t* src, int width, int bpp, int deltaSrc, int offset,
15 const SkPMColor ctable[]) {
16 // This function must not be called if we are sampling. If we are not
17 // sampling, deltaSrc should equal bpp.
18 SkASSERT(deltaSrc == bpp);
19
20 memcpy(dst, src + offset, width * bpp);
21 }
22
sample1(void * dst,const uint8_t * src,int width,int bpp,int deltaSrc,int offset,const SkPMColor ctable[])23 static void sample1(void* dst, const uint8_t* src, int width, int bpp, int deltaSrc, int offset,
24 const SkPMColor ctable[]) {
25 src += offset;
26 uint8_t* dst8 = (uint8_t*) dst;
27 for (int x = 0; x < width; x++) {
28 dst8[x] = *src;
29 src += deltaSrc;
30 }
31 }
32
sample2(void * dst,const uint8_t * src,int width,int bpp,int deltaSrc,int offset,const SkPMColor ctable[])33 static void sample2(void* dst, const uint8_t* src, int width, int bpp, int deltaSrc, int offset,
34 const SkPMColor ctable[]) {
35 src += offset;
36 uint16_t* dst16 = (uint16_t*) dst;
37 for (int x = 0; x < width; x++) {
38 dst16[x] = *((const uint16_t*) src);
39 src += deltaSrc;
40 }
41 }
42
sample4(void * dst,const uint8_t * src,int width,int bpp,int deltaSrc,int offset,const SkPMColor ctable[])43 static void sample4(void* dst, const uint8_t* src, int width, int bpp, int deltaSrc, int offset,
44 const SkPMColor ctable[]) {
45 src += offset;
46 uint32_t* dst32 = (uint32_t*) dst;
47 for (int x = 0; x < width; x++) {
48 dst32[x] = *((const uint32_t*) src);
49 src += deltaSrc;
50 }
51 }
52
53 // kBit
54 // These routines exclusively choose between white and black
55
56 #define GRAYSCALE_BLACK 0
57 #define GRAYSCALE_WHITE 0xFF
58
59
60 // 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 *)61 static void swizzle_bit_to_grayscale(
62 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
63 int bpp, int deltaSrc, int offset, const SkPMColor* /*ctable*/) {
64
65 uint8_t* SK_RESTRICT dst = (uint8_t*) dstRow;
66
67 // increment src by byte offset and bitIndex by bit offset
68 src += offset / 8;
69 int bitIndex = offset % 8;
70 uint8_t currByte = *src;
71
72 dst[0] = ((currByte >> (7-bitIndex)) & 1) ? GRAYSCALE_WHITE : GRAYSCALE_BLACK;
73
74 for (int x = 1; x < dstWidth; x++) {
75 int bitOffset = bitIndex + deltaSrc;
76 bitIndex = bitOffset % 8;
77 currByte = *(src += bitOffset / 8);
78 dst[x] = ((currByte >> (7-bitIndex)) & 1) ? GRAYSCALE_WHITE : GRAYSCALE_BLACK;
79 }
80 }
81
82 #undef GRAYSCALE_BLACK
83 #undef GRAYSCALE_WHITE
84
85 // same as swizzle_bit_to_grayscale and swizzle_bit_to_n32 except for value assigned to dst[x]
swizzle_bit_to_index(void * SK_RESTRICT dstRow,const uint8_t * SK_RESTRICT src,int dstWidth,int bpp,int deltaSrc,int offset,const SkPMColor *)86 static void swizzle_bit_to_index(
87 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
88 int bpp, int deltaSrc, int offset, const SkPMColor* /*ctable*/) {
89 uint8_t* SK_RESTRICT dst = (uint8_t*) dstRow;
90
91 // increment src by byte offset and bitIndex by bit offset
92 src += offset / 8;
93 int bitIndex = offset % 8;
94 uint8_t currByte = *src;
95
96 dst[0] = ((currByte >> (7-bitIndex)) & 1);
97
98 for (int x = 1; x < dstWidth; x++) {
99 int bitOffset = bitIndex + deltaSrc;
100 bitIndex = bitOffset % 8;
101 currByte = *(src += bitOffset / 8);
102 dst[x] = ((currByte >> (7-bitIndex)) & 1);
103 }
104 }
105
106 // 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 *)107 static void swizzle_bit_to_n32(
108 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
109 int bpp, int deltaSrc, int offset, const SkPMColor* /*ctable*/) {
110 SkPMColor* SK_RESTRICT dst = (SkPMColor*) dstRow;
111
112 // increment src by byte offset and bitIndex by bit offset
113 src += offset / 8;
114 int bitIndex = offset % 8;
115 uint8_t currByte = *src;
116
117 dst[0] = ((currByte >> (7 - bitIndex)) & 1) ? SK_ColorWHITE : SK_ColorBLACK;
118
119 for (int x = 1; x < dstWidth; x++) {
120 int bitOffset = bitIndex + deltaSrc;
121 bitIndex = bitOffset % 8;
122 currByte = *(src += bitOffset / 8);
123 dst[x] = ((currByte >> (7 - bitIndex)) & 1) ? SK_ColorWHITE : SK_ColorBLACK;
124 }
125 }
126
127 #define RGB565_BLACK 0
128 #define RGB565_WHITE 0xFFFF
129
swizzle_bit_to_565(void * SK_RESTRICT dstRow,const uint8_t * SK_RESTRICT src,int dstWidth,int bpp,int deltaSrc,int offset,const SkPMColor *)130 static void swizzle_bit_to_565(
131 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
132 int bpp, int deltaSrc, int offset, const SkPMColor* /*ctable*/) {
133 uint16_t* SK_RESTRICT dst = (uint16_t*) dstRow;
134
135 // increment src by byte offset and bitIndex by bit offset
136 src += offset / 8;
137 int bitIndex = offset % 8;
138 uint8_t currByte = *src;
139
140 dst[0] = ((currByte >> (7 - bitIndex)) & 1) ? RGB565_WHITE : RGB565_BLACK;
141
142 for (int x = 1; x < dstWidth; x++) {
143 int bitOffset = bitIndex + deltaSrc;
144 bitIndex = bitOffset % 8;
145 currByte = *(src += bitOffset / 8);
146 dst[x] = ((currByte >> (7 - bitIndex)) & 1) ? RGB565_WHITE : RGB565_BLACK;
147 }
148 }
149
150 #undef RGB565_BLACK
151 #undef RGB565_WHITE
152
153 // kIndex1, kIndex2, kIndex4
154
swizzle_small_index_to_index(void * SK_RESTRICT dstRow,const uint8_t * SK_RESTRICT src,int dstWidth,int bpp,int deltaSrc,int offset,const SkPMColor ctable[])155 static void swizzle_small_index_to_index(
156 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
157 int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) {
158
159 uint8_t* dst = (uint8_t*) dstRow;
160 src += offset / 8;
161 int bitIndex = offset % 8;
162 uint8_t currByte = *src;
163 const uint8_t mask = (1 << bpp) - 1;
164 uint8_t index = (currByte >> (8 - bpp - bitIndex)) & mask;
165 dst[0] = index;
166
167 for (int x = 1; x < dstWidth; x++) {
168 int bitOffset = bitIndex + deltaSrc;
169 bitIndex = bitOffset % 8;
170 currByte = *(src += bitOffset / 8);
171 index = (currByte >> (8 - bpp - bitIndex)) & mask;
172 dst[x] = index;
173 }
174 }
175
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[])176 static void swizzle_small_index_to_565(
177 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
178 int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) {
179
180 uint16_t* dst = (uint16_t*) dstRow;
181 src += offset / 8;
182 int bitIndex = offset % 8;
183 uint8_t currByte = *src;
184 const uint8_t mask = (1 << bpp) - 1;
185 uint8_t index = (currByte >> (8 - bpp - bitIndex)) & mask;
186 dst[0] = SkPixel32ToPixel16(ctable[index]);
187
188 for (int x = 1; x < dstWidth; x++) {
189 int bitOffset = bitIndex + deltaSrc;
190 bitIndex = bitOffset % 8;
191 currByte = *(src += bitOffset / 8);
192 index = (currByte >> (8 - bpp - bitIndex)) & mask;
193 dst[x] = SkPixel32ToPixel16(ctable[index]);
194 }
195 }
196
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[])197 static void swizzle_small_index_to_n32(
198 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
199 int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) {
200
201 SkPMColor* dst = (SkPMColor*) dstRow;
202 src += offset / 8;
203 int bitIndex = offset % 8;
204 uint8_t currByte = *src;
205 const uint8_t mask = (1 << bpp) - 1;
206 uint8_t index = (currByte >> (8 - bpp - bitIndex)) & mask;
207 dst[0] = ctable[index];
208
209 for (int x = 1; x < dstWidth; x++) {
210 int bitOffset = bitIndex + deltaSrc;
211 bitIndex = bitOffset % 8;
212 currByte = *(src += bitOffset / 8);
213 index = (currByte >> (8 - bpp - bitIndex)) & mask;
214 dst[x] = ctable[index];
215 }
216 }
217
218 // kIndex
219
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[])220 static void swizzle_index_to_n32(
221 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
222 int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) {
223
224 src += offset;
225 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
226 for (int x = 0; x < dstWidth; x++) {
227 SkPMColor c = ctable[*src];
228 dst[x] = c;
229 src += deltaSrc;
230 }
231 }
232
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[])233 static void swizzle_index_to_n32_skipZ(
234 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
235 int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) {
236
237 src += offset;
238 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
239 for (int x = 0; x < dstWidth; x++) {
240 SkPMColor c = ctable[*src];
241 if (c != 0) {
242 dst[x] = c;
243 }
244 src += deltaSrc;
245 }
246 }
247
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[])248 static void swizzle_index_to_565(
249 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
250 int bytesPerPixel, int deltaSrc, int offset, const SkPMColor ctable[]) {
251 src += offset;
252 uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow;
253 for (int x = 0; x < dstWidth; x++) {
254 dst[x] = SkPixel32ToPixel16(ctable[*src]);
255 src += deltaSrc;
256 }
257 }
258
259 // kGray
260
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[])261 static void swizzle_gray_to_n32(
262 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
263 int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) {
264
265 src += offset;
266 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
267 for (int x = 0; x < dstWidth; x++) {
268 dst[x] = SkPackARGB32NoCheck(0xFF, *src, *src, *src);
269 src += deltaSrc;
270 }
271 }
272
fast_swizzle_gray_to_n32(void * dst,const uint8_t * src,int width,int bpp,int deltaSrc,int offset,const SkPMColor ctable[])273 static void fast_swizzle_gray_to_n32(
274 void* dst, const uint8_t* src, int width, int bpp, int deltaSrc, int offset,
275 const SkPMColor ctable[]) {
276
277 // This function must not be called if we are sampling. If we are not
278 // sampling, deltaSrc should equal bpp.
279 SkASSERT(deltaSrc == bpp);
280
281 // Note that there is no need to distinguish between RGB and BGR.
282 // Each color channel will get the same value.
283 SkOpts::gray_to_RGB1((uint32_t*) dst, src + offset, width);
284 }
285
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[])286 static void swizzle_gray_to_565(
287 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
288 int bytesPerPixel, int deltaSrc, int offset, const SkPMColor ctable[]) {
289
290 src += offset;
291 uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow;
292 for (int x = 0; x < dstWidth; x++) {
293 dst[x] = SkPack888ToRGB16(src[0], src[0], src[0]);
294 src += deltaSrc;
295 }
296 }
297
298 // kGrayAlpha
299
swizzle_grayalpha_to_n32_unpremul(void * dst,const uint8_t * src,int width,int bpp,int deltaSrc,int offset,const SkPMColor ctable[])300 static void swizzle_grayalpha_to_n32_unpremul(
301 void* dst, const uint8_t* src, int width, int bpp, int deltaSrc, int offset,
302 const SkPMColor ctable[]) {
303
304 src += offset;
305 SkPMColor* dst32 = (SkPMColor*) dst;
306 for (int x = 0; x < width; x++) {
307 dst32[x] = SkPackARGB32NoCheck(src[1], src[0], src[0], src[0]);
308 src += deltaSrc;
309 }
310 }
311
fast_swizzle_grayalpha_to_n32_unpremul(void * dst,const uint8_t * src,int width,int bpp,int deltaSrc,int offset,const SkPMColor ctable[])312 static void fast_swizzle_grayalpha_to_n32_unpremul(
313 void* dst, const uint8_t* src, int width, int bpp, int deltaSrc, int offset,
314 const SkPMColor ctable[]) {
315
316 // This function must not be called if we are sampling. If we are not
317 // sampling, deltaSrc should equal bpp.
318 SkASSERT(deltaSrc == bpp);
319
320 // Note that there is no need to distinguish between RGB and BGR.
321 // Each color channel will get the same value.
322 SkOpts::grayA_to_RGBA((uint32_t*) dst, src + offset, width);
323 }
324
swizzle_grayalpha_to_n32_premul(void * dst,const uint8_t * src,int width,int bpp,int deltaSrc,int offset,const SkPMColor ctable[])325 static void swizzle_grayalpha_to_n32_premul(
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 uint8_t pmgray = SkMulDiv255Round(src[1], src[0]);
333 dst32[x] = SkPackARGB32NoCheck(src[1], pmgray, pmgray, pmgray);
334 src += deltaSrc;
335 }
336 }
337
fast_swizzle_grayalpha_to_n32_premul(void * dst,const uint8_t * src,int width,int bpp,int deltaSrc,int offset,const SkPMColor ctable[])338 static void fast_swizzle_grayalpha_to_n32_premul(
339 void* dst, const uint8_t* src, int width, int bpp, int deltaSrc, int offset,
340 const SkPMColor ctable[]) {
341
342 // This function must not be called if we are sampling. If we are not
343 // sampling, deltaSrc should equal bpp.
344 SkASSERT(deltaSrc == bpp);
345
346 // Note that there is no need to distinguish between rgb and bgr.
347 // Each color channel will get the same value.
348 SkOpts::grayA_to_rgbA((uint32_t*) dst, src + offset, width);
349 }
350
351 // kBGRX
352
swizzle_bgrx_to_n32(void * SK_RESTRICT dstRow,const uint8_t * SK_RESTRICT src,int dstWidth,int bpp,int deltaSrc,int offset,const SkPMColor ctable[])353 static void swizzle_bgrx_to_n32(
354 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
355 int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) {
356
357 src += offset;
358 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
359 for (int x = 0; x < dstWidth; x++) {
360 dst[x] = SkPackARGB32NoCheck(0xFF, src[2], src[1], src[0]);
361 src += deltaSrc;
362 }
363 }
364
swizzle_bgrx_to_565(void * SK_RESTRICT dstRow,const uint8_t * SK_RESTRICT src,int dstWidth,int bpp,int deltaSrc,int offset,const SkPMColor ctable[])365 static void swizzle_bgrx_to_565(
366 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
367 int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) {
368
369 src += offset;
370 uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow;
371 for (int x = 0; x < dstWidth; x++) {
372 dst[x] = SkPack888ToRGB16(src[2], src[1], src[0]);
373 src += deltaSrc;
374 }
375 }
376
377 // kBGRA
378
swizzle_bgra_to_n32_unpremul(void * SK_RESTRICT dstRow,const uint8_t * SK_RESTRICT src,int dstWidth,int bpp,int deltaSrc,int offset,const SkPMColor ctable[])379 static void swizzle_bgra_to_n32_unpremul(
380 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
381 int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) {
382
383 src += offset;
384 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
385 for (int x = 0; x < dstWidth; x++) {
386 uint8_t alpha = src[3];
387 dst[x] = SkPackARGB32NoCheck(alpha, src[2], src[1], src[0]);
388 src += deltaSrc;
389 }
390 }
391
fast_swizzle_bgra_to_n32_unpremul(void * dst,const uint8_t * src,int width,int bpp,int deltaSrc,int offset,const SkPMColor ctable[])392 static void fast_swizzle_bgra_to_n32_unpremul(
393 void* dst, const uint8_t* src, int width, int bpp, int deltaSrc, int offset,
394 const SkPMColor ctable[]) {
395
396 // This function must not be called if we are sampling. If we are not
397 // sampling, deltaSrc should equal bpp.
398 SkASSERT(deltaSrc == bpp);
399
400 #ifdef SK_PMCOLOR_IS_RGBA
401 SkOpts::RGBA_to_BGRA((uint32_t*) dst, src + offset, width);
402 #else
403 memcpy(dst, src + offset, width * bpp);
404 #endif
405 }
406
swizzle_bgra_to_n32_premul(void * SK_RESTRICT dstRow,const uint8_t * SK_RESTRICT src,int dstWidth,int bpp,int deltaSrc,int offset,const SkPMColor ctable[])407 static void swizzle_bgra_to_n32_premul(
408 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
409 int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) {
410
411 src += offset;
412 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
413 for (int x = 0; x < dstWidth; x++) {
414 uint8_t alpha = src[3];
415 dst[x] = SkPremultiplyARGBInline(alpha, src[2], src[1], src[0]);
416 src += deltaSrc;
417 }
418 }
419
fast_swizzle_bgra_to_n32_premul(void * dst,const uint8_t * src,int width,int bpp,int deltaSrc,int offset,const SkPMColor ctable[])420 static void fast_swizzle_bgra_to_n32_premul(
421 void* dst, const uint8_t* src, int width, int bpp, int deltaSrc, int offset,
422 const SkPMColor ctable[]) {
423
424 // This function must not be called if we are sampling. If we are not
425 // sampling, deltaSrc should equal bpp.
426 SkASSERT(deltaSrc == bpp);
427
428 #ifdef SK_PMCOLOR_IS_RGBA
429 SkOpts::RGBA_to_bgrA((uint32_t*) dst, src + offset, width);
430 #else
431 SkOpts::RGBA_to_rgbA((uint32_t*) dst, src + offset, width);
432 #endif
433 }
434
435 // kRGB
436
swizzle_rgb_to_n32(void * SK_RESTRICT dstRow,const uint8_t * SK_RESTRICT src,int dstWidth,int bpp,int deltaSrc,int offset,const SkPMColor ctable[])437 static void swizzle_rgb_to_n32(
438 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
439 int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) {
440
441 src += offset;
442 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
443 for (int x = 0; x < dstWidth; x++) {
444 dst[x] = SkPackARGB32NoCheck(0xFF, src[0], src[1], src[2]);
445 src += deltaSrc;
446 }
447 }
448
fast_swizzle_rgb_to_n32(void * dst,const uint8_t * src,int width,int bpp,int deltaSrc,int offset,const SkPMColor ctable[])449 static void fast_swizzle_rgb_to_n32(
450 void* dst, const uint8_t* src, int width, int bpp, int deltaSrc,
451 int offset, const SkPMColor ctable[]) {
452
453 // This function must not be called if we are sampling. If we are not
454 // sampling, deltaSrc should equal bpp.
455 SkASSERT(deltaSrc == bpp);
456
457 #ifdef SK_PMCOLOR_IS_RGBA
458 SkOpts::RGB_to_RGB1((uint32_t*) dst, src + offset, width);
459 #else
460 SkOpts::RGB_to_BGR1((uint32_t*) dst, src + offset, width);
461 #endif
462 }
463
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[])464 static void swizzle_rgb_to_565(
465 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
466 int bytesPerPixel, int deltaSrc, int offset, const SkPMColor ctable[]) {
467
468 src += offset;
469 uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow;
470 for (int x = 0; x < dstWidth; x++) {
471 dst[x] = SkPack888ToRGB16(src[0], src[1], src[2]);
472 src += deltaSrc;
473 }
474 }
475
476 // kRGBA
477
swizzle_rgba_to_n32_premul(void * SK_RESTRICT dstRow,const uint8_t * SK_RESTRICT src,int dstWidth,int bpp,int deltaSrc,int offset,const SkPMColor ctable[])478 static void swizzle_rgba_to_n32_premul(
479 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
480 int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) {
481
482 src += offset;
483 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
484 for (int x = 0; x < dstWidth; x++) {
485 unsigned alpha = src[3];
486 dst[x] = SkPremultiplyARGBInline(alpha, src[0], src[1], src[2]);
487 src += deltaSrc;
488 }
489 }
490
fast_swizzle_rgba_to_n32_premul(void * dst,const uint8_t * src,int width,int bpp,int deltaSrc,int offset,const SkPMColor ctable[])491 static void fast_swizzle_rgba_to_n32_premul(
492 void* dst, const uint8_t* src, int width, int bpp, int deltaSrc,
493 int offset, const SkPMColor ctable[]) {
494
495 // This function must not be called if we are sampling. If we are not
496 // sampling, deltaSrc should equal bpp.
497 SkASSERT(deltaSrc == bpp);
498
499 #ifdef SK_PMCOLOR_IS_RGBA
500 SkOpts::RGBA_to_rgbA((uint32_t*) dst, src + offset, width);
501 #else
502 SkOpts::RGBA_to_bgrA((uint32_t*) dst, src + offset, width);
503 #endif
504 }
505
swizzle_rgba_to_n32_unpremul(void * SK_RESTRICT dstRow,const uint8_t * SK_RESTRICT src,int dstWidth,int bpp,int deltaSrc,int offset,const SkPMColor ctable[])506 static void swizzle_rgba_to_n32_unpremul(
507 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
508 int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) {
509
510 src += offset;
511 uint32_t* SK_RESTRICT dst = reinterpret_cast<uint32_t*>(dstRow);
512 for (int x = 0; x < dstWidth; x++) {
513 unsigned alpha = src[3];
514 dst[x] = SkPackARGB32NoCheck(alpha, src[0], src[1], src[2]);
515 src += deltaSrc;
516 }
517 }
518
fast_swizzle_rgba_to_n32_unpremul(void * dst,const uint8_t * src,int width,int bpp,int deltaSrc,int offset,const SkPMColor ctable[])519 static void fast_swizzle_rgba_to_n32_unpremul(
520 void* dst, const uint8_t* src, int width, int bpp, int deltaSrc, int offset,
521 const SkPMColor ctable[]) {
522
523 // This function must not be called if we are sampling. If we are not
524 // sampling, deltaSrc should equal bpp.
525 SkASSERT(deltaSrc == bpp);
526
527 #ifdef SK_PMCOLOR_IS_RGBA
528 memcpy(dst, src + offset, width * bpp);
529 #else
530 SkOpts::RGBA_to_BGRA((uint32_t*) dst, src + offset, width);
531 #endif
532 }
533
534 // kCMYK
535 //
536 // CMYK is stored as four bytes per pixel.
537 //
538 // We will implement a crude conversion from CMYK -> RGB using formulas
539 // from easyrgb.com.
540 //
541 // CMYK -> CMY
542 // C = C * (1 - K) + K
543 // M = M * (1 - K) + K
544 // Y = Y * (1 - K) + K
545 //
546 // libjpeg actually gives us inverted CMYK, so we must subtract the
547 // original terms from 1.
548 // CMYK -> CMY
549 // C = (1 - C) * (1 - (1 - K)) + (1 - K)
550 // M = (1 - M) * (1 - (1 - K)) + (1 - K)
551 // Y = (1 - Y) * (1 - (1 - K)) + (1 - K)
552 //
553 // Simplifying the above expression.
554 // CMYK -> CMY
555 // C = 1 - CK
556 // M = 1 - MK
557 // Y = 1 - YK
558 //
559 // CMY -> RGB
560 // R = (1 - C) * 255
561 // G = (1 - M) * 255
562 // B = (1 - Y) * 255
563 //
564 // Therefore the full conversion is below. This can be verified at
565 // www.rapidtables.com (assuming inverted CMYK).
566 // CMYK -> RGB
567 // R = C * K * 255
568 // G = M * K * 255
569 // B = Y * K * 255
570 //
571 // As a final note, we have treated the CMYK values as if they were on
572 // a scale from 0-1, when in fact they are 8-bit ints scaling from 0-255.
573 // We must divide each CMYK component by 255 to obtain the true conversion
574 // we should perform.
575 // CMYK -> RGB
576 // R = C * K / 255
577 // G = M * K / 255
578 // B = Y * K / 255
swizzle_cmyk_to_n32(void * SK_RESTRICT dstRow,const uint8_t * SK_RESTRICT src,int dstWidth,int bpp,int deltaSrc,int offset,const SkPMColor ctable[])579 static void swizzle_cmyk_to_n32(
580 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
581 int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) {
582
583 src += offset;
584 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
585 for (int x = 0; x < dstWidth; x++) {
586 const uint8_t r = SkMulDiv255Round(src[0], src[3]);
587 const uint8_t g = SkMulDiv255Round(src[1], src[3]);
588 const uint8_t b = SkMulDiv255Round(src[2], src[3]);
589
590 dst[x] = SkPackARGB32NoCheck(0xFF, r, g, b);
591 src += deltaSrc;
592 }
593 }
594
fast_swizzle_cmyk_to_n32(void * dst,const uint8_t * src,int width,int bpp,int deltaSrc,int offset,const SkPMColor ctable[])595 static void fast_swizzle_cmyk_to_n32(
596 void* dst, const uint8_t* src, int width, int bpp, int deltaSrc, int offset,
597 const SkPMColor ctable[]) {
598
599 // This function must not be called if we are sampling. If we are not
600 // sampling, deltaSrc should equal bpp.
601 SkASSERT(deltaSrc == bpp);
602
603 #ifdef SK_PMCOLOR_IS_RGBA
604 SkOpts::inverted_CMYK_to_RGB1((uint32_t*) dst, src + offset, width);
605 #else
606 SkOpts::inverted_CMYK_to_BGR1((uint32_t*) dst, src + offset, width);
607 #endif
608 }
609
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[])610 static void swizzle_cmyk_to_565(
611 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
612 int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) {
613
614 src += offset;
615 uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow;
616 for (int x = 0; x < dstWidth; x++) {
617 const uint8_t r = SkMulDiv255Round(src[0], src[3]);
618 const uint8_t g = SkMulDiv255Round(src[1], src[3]);
619 const uint8_t b = SkMulDiv255Round(src[2], src[3]);
620
621 dst[x] = SkPack888ToRGB16(r, g, b);
622 src += deltaSrc;
623 }
624 }
625
626 template <SkSwizzler::RowProc proc>
SkipLeadingGrayAlphaZerosThen(void * dst,const uint8_t * src,int width,int bpp,int deltaSrc,int offset,const SkPMColor ctable[])627 void SkSwizzler::SkipLeadingGrayAlphaZerosThen(
628 void* dst, const uint8_t* src, int width,
629 int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) {
630 SkASSERT(!ctable);
631
632 const uint16_t* src16 = (const uint16_t*) (src + offset);
633 uint32_t* dst32 = (uint32_t*) dst;
634
635 // This may miss opportunities to skip when the output is premultiplied,
636 // e.g. for a src pixel 0x00FF which is not zero but becomes zero after premultiplication.
637 while (width > 0 && *src16 == 0x0000) {
638 width--;
639 dst32++;
640 src16 += deltaSrc / 2;
641 }
642 proc(dst32, (const uint8_t*)src16, width, bpp, deltaSrc, 0, ctable);
643 }
644
645 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[])646 void SkSwizzler::SkipLeading8888ZerosThen(
647 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
648 int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) {
649 SkASSERT(!ctable);
650
651 auto src32 = (const uint32_t*)(src+offset);
652 auto dst32 = (uint32_t*)dstRow;
653
654 // This may miss opportunities to skip when the output is premultiplied,
655 // e.g. for a src pixel 0x00FFFFFF which is not zero but becomes zero after premultiplication.
656 while (dstWidth > 0 && *src32 == 0x00000000) {
657 dstWidth--;
658 dst32++;
659 src32 += deltaSrc/4;
660 }
661 proc(dst32, (const uint8_t*)src32, dstWidth, bpp, deltaSrc, 0, ctable);
662 }
663
CreateSwizzler(SkSwizzler::SrcConfig sc,const SkPMColor * ctable,const SkImageInfo & dstInfo,const SkCodec::Options & options,const SkIRect * frame)664 SkSwizzler* SkSwizzler::CreateSwizzler(SkSwizzler::SrcConfig sc,
665 const SkPMColor* ctable,
666 const SkImageInfo& dstInfo,
667 const SkCodec::Options& options,
668 const SkIRect* frame) {
669 if (dstInfo.colorType() == kUnknown_SkColorType || kUnknown == sc) {
670 return nullptr;
671 }
672 if ((kIndex == sc || kIndex4 == sc || kIndex2 == sc || kIndex1 == sc)
673 && nullptr == ctable) {
674 return nullptr;
675 }
676 RowProc fastProc = nullptr;
677 RowProc proc = nullptr;
678 SkCodec::ZeroInitialized zeroInit = options.fZeroInitialized;
679 switch (sc) {
680 case kBit:
681 switch (dstInfo.colorType()) {
682 case kN32_SkColorType:
683 proc = &swizzle_bit_to_n32;
684 break;
685 case kIndex_8_SkColorType:
686 proc = &swizzle_bit_to_index;
687 break;
688 case kRGB_565_SkColorType:
689 proc = &swizzle_bit_to_565;
690 break;
691 case kGray_8_SkColorType:
692 proc = &swizzle_bit_to_grayscale;
693 break;
694 default:
695 break;
696 }
697 break;
698 case kIndex1:
699 case kIndex2:
700 case kIndex4:
701 switch (dstInfo.colorType()) {
702 case kN32_SkColorType:
703 proc = &swizzle_small_index_to_n32;
704 break;
705 case kRGB_565_SkColorType:
706 proc = &swizzle_small_index_to_565;
707 break;
708 case kIndex_8_SkColorType:
709 proc = &swizzle_small_index_to_index;
710 break;
711 default:
712 break;
713 }
714 break;
715 case kIndex:
716 switch (dstInfo.colorType()) {
717 case kN32_SkColorType:
718 // We assume the color premultiplied ctable (or not) as desired.
719 if (SkCodec::kYes_ZeroInitialized == zeroInit) {
720 proc = &swizzle_index_to_n32_skipZ;
721 break;
722 } else {
723 proc = &swizzle_index_to_n32;
724 break;
725 }
726 break;
727 case kRGB_565_SkColorType:
728 proc = &swizzle_index_to_565;
729 break;
730 case kIndex_8_SkColorType:
731 proc = &sample1;
732 fastProc = ©
733 break;
734 default:
735 break;
736 }
737 break;
738 case kGray:
739 switch (dstInfo.colorType()) {
740 case kN32_SkColorType:
741 proc = &swizzle_gray_to_n32;
742 fastProc = &fast_swizzle_gray_to_n32;
743 break;
744 case kGray_8_SkColorType:
745 proc = &sample1;
746 fastProc = ©
747 break;
748 case kRGB_565_SkColorType:
749 proc = &swizzle_gray_to_565;
750 break;
751 default:
752 break;
753 }
754 break;
755 case kGrayAlpha:
756 switch (dstInfo.colorType()) {
757 case kN32_SkColorType:
758 if (dstInfo.alphaType() == kUnpremul_SkAlphaType) {
759 if (SkCodec::kYes_ZeroInitialized == zeroInit) {
760 proc = &SkipLeadingGrayAlphaZerosThen
761 <swizzle_grayalpha_to_n32_unpremul>;
762 fastProc = &SkipLeadingGrayAlphaZerosThen
763 <fast_swizzle_grayalpha_to_n32_unpremul>;
764 } else {
765 proc = &swizzle_grayalpha_to_n32_unpremul;
766 fastProc = &fast_swizzle_grayalpha_to_n32_unpremul;
767 }
768 } else {
769 if (SkCodec::kYes_ZeroInitialized == zeroInit) {
770 proc = &SkipLeadingGrayAlphaZerosThen<swizzle_grayalpha_to_n32_premul>;
771 fastProc = &SkipLeadingGrayAlphaZerosThen
772 <fast_swizzle_grayalpha_to_n32_premul>;
773 } else {
774 proc = &swizzle_grayalpha_to_n32_premul;
775 fastProc = &fast_swizzle_grayalpha_to_n32_premul;
776 }
777 }
778 break;
779 default:
780 break;
781 }
782 break;
783 case kBGR:
784 case kBGRX:
785 switch (dstInfo.colorType()) {
786 case kN32_SkColorType:
787 proc = &swizzle_bgrx_to_n32;
788 break;
789 case kRGB_565_SkColorType:
790 proc = &swizzle_bgrx_to_565;
791 break;
792 default:
793 break;
794 }
795 break;
796 case kBGRA:
797 switch (dstInfo.colorType()) {
798 case kN32_SkColorType:
799 if (dstInfo.alphaType() == kUnpremul_SkAlphaType) {
800 if (SkCodec::kYes_ZeroInitialized == zeroInit) {
801 proc = &SkipLeading8888ZerosThen<swizzle_bgra_to_n32_unpremul>;
802 fastProc = &SkipLeading8888ZerosThen<fast_swizzle_bgra_to_n32_unpremul>;
803 } else {
804 proc = &swizzle_bgra_to_n32_unpremul;
805 fastProc = &fast_swizzle_bgra_to_n32_unpremul;
806 }
807 } else {
808 if (SkCodec::kYes_ZeroInitialized == zeroInit) {
809 proc = &SkipLeading8888ZerosThen<swizzle_bgra_to_n32_premul>;
810 fastProc = &SkipLeading8888ZerosThen<fast_swizzle_bgra_to_n32_premul>;
811 } else {
812 proc = &swizzle_bgra_to_n32_premul;
813 fastProc = &fast_swizzle_bgra_to_n32_premul;
814 }
815 }
816 break;
817 default:
818 break;
819 }
820 break;
821 case kRGB:
822 switch (dstInfo.colorType()) {
823 case kN32_SkColorType:
824 proc = &swizzle_rgb_to_n32;
825 fastProc = &fast_swizzle_rgb_to_n32;
826 break;
827 case kRGB_565_SkColorType:
828 proc = &swizzle_rgb_to_565;
829 break;
830 default:
831 break;
832 }
833 break;
834 case kRGBA:
835 switch (dstInfo.colorType()) {
836 case kN32_SkColorType:
837 if (dstInfo.alphaType() == kUnpremul_SkAlphaType) {
838 if (SkCodec::kYes_ZeroInitialized == zeroInit) {
839 proc = &SkipLeading8888ZerosThen<swizzle_rgba_to_n32_unpremul>;
840 fastProc = &SkipLeading8888ZerosThen<fast_swizzle_rgba_to_n32_unpremul>;
841 } else {
842 proc = &swizzle_rgba_to_n32_unpremul;
843 fastProc = &fast_swizzle_rgba_to_n32_unpremul;
844 }
845 } else {
846 if (SkCodec::kYes_ZeroInitialized == zeroInit) {
847 proc = &SkipLeading8888ZerosThen<swizzle_rgba_to_n32_premul>;
848 fastProc = &SkipLeading8888ZerosThen<fast_swizzle_rgba_to_n32_premul>;
849 } else {
850 proc = &swizzle_rgba_to_n32_premul;
851 fastProc = &fast_swizzle_rgba_to_n32_premul;
852 }
853 }
854 break;
855 default:
856 break;
857 }
858 break;
859 case kCMYK:
860 switch (dstInfo.colorType()) {
861 case kN32_SkColorType:
862 proc = &swizzle_cmyk_to_n32;
863 fastProc = &fast_swizzle_cmyk_to_n32;
864 break;
865 case kRGB_565_SkColorType:
866 proc = &swizzle_cmyk_to_565;
867 break;
868 default:
869 break;
870 }
871 break;
872 case kNoOp8:
873 proc = &sample1;
874 fastProc = ©
875 break;
876 case kNoOp16:
877 proc = sample2;
878 fastProc = ©
879 break;
880 case kNoOp32:
881 proc = &sample4;
882 fastProc = ©
883 break;
884 default:
885 break;
886 }
887
888 // Store bpp in bytes if it is an even multiple, otherwise use bits
889 int srcBPP = SkIsAlign8(BitsPerPixel(sc)) ? BytesPerPixel(sc) : BitsPerPixel(sc);
890 int dstBPP = SkColorTypeBytesPerPixel(dstInfo.colorType());
891
892 int srcOffset = 0;
893 int srcWidth = dstInfo.width();
894 int dstOffset = 0;
895 int dstWidth = srcWidth;
896 if (options.fSubset) {
897 // We do not currently support subset decodes for image types that may have
898 // frames (gif).
899 SkASSERT(!frame);
900 srcOffset = options.fSubset->left();
901 srcWidth = options.fSubset->width();
902 dstWidth = srcWidth;
903 } else if (frame) {
904 dstOffset = frame->left();
905 srcWidth = frame->width();
906 }
907
908 return new SkSwizzler(fastProc, proc, ctable, srcOffset, srcWidth, dstOffset, dstWidth,
909 srcBPP, dstBPP);
910 }
911
SkSwizzler(RowProc fastProc,RowProc proc,const SkPMColor * ctable,int srcOffset,int srcWidth,int dstOffset,int dstWidth,int srcBPP,int dstBPP)912 SkSwizzler::SkSwizzler(RowProc fastProc, RowProc proc, const SkPMColor* ctable, int srcOffset,
913 int srcWidth, int dstOffset, int dstWidth, int srcBPP, int dstBPP)
914 : fFastProc(fastProc)
915 , fSlowProc(proc)
916 , fActualProc(fFastProc ? fFastProc : fSlowProc)
917 , fColorTable(ctable)
918 , fSrcOffset(srcOffset)
919 , fDstOffset(dstOffset)
920 , fSrcOffsetUnits(srcOffset * srcBPP)
921 , fDstOffsetBytes(dstOffset * dstBPP)
922 , fSrcWidth(srcWidth)
923 , fDstWidth(dstWidth)
924 , fSwizzleWidth(srcWidth)
925 , fAllocatedWidth(dstWidth)
926 , fSampleX(1)
927 , fSrcBPP(srcBPP)
928 , fDstBPP(dstBPP)
929 {}
930
onSetSampleX(int sampleX)931 int SkSwizzler::onSetSampleX(int sampleX) {
932 SkASSERT(sampleX > 0);
933
934 fSampleX = sampleX;
935 fSrcOffsetUnits = (get_start_coord(sampleX) + fSrcOffset) * fSrcBPP;
936 fDstOffsetBytes = (fDstOffset / sampleX) * fDstBPP;
937 fSwizzleWidth = get_scaled_dimension(fSrcWidth, sampleX);
938 fAllocatedWidth = get_scaled_dimension(fDstWidth, sampleX);
939
940 // The optimized swizzler functions do not support sampling. Sampled swizzles
941 // are already fast because they skip pixels. We haven't seen a situation
942 // where speeding up sampling has a significant impact on total decode time.
943 if (1 == fSampleX && fFastProc) {
944 fActualProc = fFastProc;
945 } else {
946 fActualProc = fSlowProc;
947 }
948
949 return fAllocatedWidth;
950 }
951
swizzle(void * dst,const uint8_t * SK_RESTRICT src)952 void SkSwizzler::swizzle(void* dst, const uint8_t* SK_RESTRICT src) {
953 SkASSERT(nullptr != dst && nullptr != src);
954 fActualProc(SkTAddOffset<void>(dst, fDstOffsetBytes), src, fSwizzleWidth, fSrcBPP,
955 fSampleX * fSrcBPP, fSrcOffsetUnits, fColorTable);
956 }
957