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
14static 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
23static 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
33static 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
43static 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]
61static 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]
86static 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]
107static 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
130static 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
155static 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
176static 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
197static 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
220static 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
233static 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
248static 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
261static 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
273static 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
286static 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
300static 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
312static 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
325static 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
338static 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
353static 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
365static 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
379static 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
392static 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
407static 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
420static 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
437static 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
449static 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
464static 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
478static 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
491static 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
506static 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
519static 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
579static 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
595static 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
610static 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
626template <SkSwizzler::RowProc proc>
627void 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
645template <SkSwizzler::RowProc proc>
646void 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
664SkSwizzler* 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 = &copy;
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 = &copy;
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 = &copy;
875            break;
876        case kNoOp16:
877            proc = sample2;
878            fastProc = &copy;
879            break;
880        case kNoOp32:
881            proc = &sample4;
882            fastProc = &copy;
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
912SkSwizzler::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
931int 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
952void 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