SkSwizzler.cpp revision 93e613d6bdea05d96e232ed261d7bf886c91bb8e
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 swizzle_grayalpha_to_n32_premul(
313        void* dst, const uint8_t* src, int width, int bpp, int deltaSrc, int offset,
314        const SkPMColor ctable[]) {
315
316    src += offset;
317    SkPMColor* dst32 = (SkPMColor*) dst;
318    for (int x = 0; x < width; x++) {
319        uint8_t pmgray = SkMulDiv255Round(src[1], src[0]);
320        dst32[x] = SkPackARGB32NoCheck(src[1], pmgray, pmgray, pmgray);
321        src += deltaSrc;
322    }
323}
324
325// kBGRX
326
327static void swizzle_bgrx_to_n32(
328        void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
329        int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) {
330
331    src += offset;
332    SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
333    for (int x = 0; x < dstWidth; x++) {
334        dst[x] = SkPackARGB32NoCheck(0xFF, src[2], src[1], src[0]);
335        src += deltaSrc;
336    }
337}
338
339static void swizzle_bgrx_to_565(
340        void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
341        int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) {
342
343    src += offset;
344    uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow;
345    for (int x = 0; x < dstWidth; x++) {
346        dst[x] = SkPack888ToRGB16(src[2], src[1], src[0]);
347        src += deltaSrc;
348    }
349}
350
351// kBGRA
352
353static void swizzle_bgra_to_n32_unpremul(
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        uint8_t alpha = src[3];
361        dst[x] = SkPackARGB32NoCheck(alpha, src[2], src[1], src[0]);
362        src += deltaSrc;
363    }
364}
365
366static void fast_swizzle_bgra_to_n32_unpremul(
367        void* dst, const uint8_t* src, int width, int bpp, int deltaSrc, int offset,
368        const SkPMColor ctable[]) {
369
370    // This function must not be called if we are sampling.  If we are not
371    // sampling, deltaSrc should equal bpp.
372    SkASSERT(deltaSrc == bpp);
373
374#ifdef SK_PMCOLOR_IS_RGBA
375    SkOpts::RGBA_to_BGRA((uint32_t*) dst, src + offset, width);
376#else
377    memcpy(dst, src + offset, width * bpp);
378#endif
379}
380
381static void swizzle_bgra_to_n32_premul(
382        void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
383        int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) {
384
385    src += offset;
386    SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
387    for (int x = 0; x < dstWidth; x++) {
388        uint8_t alpha = src[3];
389        dst[x] = SkPremultiplyARGBInline(alpha, src[2], src[1], src[0]);
390        src += deltaSrc;
391    }
392}
393
394static void fast_swizzle_bgra_to_n32_premul(
395        void* dst, const uint8_t* src, int width, int bpp, int deltaSrc, int offset,
396        const SkPMColor ctable[]) {
397
398    // This function must not be called if we are sampling.  If we are not
399    // sampling, deltaSrc should equal bpp.
400    SkASSERT(deltaSrc == bpp);
401
402#ifdef SK_PMCOLOR_IS_RGBA
403    SkOpts::RGBA_to_bgrA((uint32_t*) dst, src + offset, width);
404#else
405    SkOpts::RGBA_to_rgbA((uint32_t*) dst, src + offset, width);
406#endif
407}
408
409// kRGB
410
411static void swizzle_rgb_to_n32(
412        void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
413        int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) {
414
415    src += offset;
416    SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
417    for (int x = 0; x < dstWidth; x++) {
418        dst[x] = SkPackARGB32NoCheck(0xFF, src[0], src[1], src[2]);
419        src += deltaSrc;
420    }
421}
422
423static void fast_swizzle_rgb_to_n32(
424        void* dst, const uint8_t* src, int width, int bpp, int deltaSrc,
425        int offset, const SkPMColor ctable[]) {
426
427    // This function must not be called if we are sampling.  If we are not
428    // sampling, deltaSrc should equal bpp.
429    SkASSERT(deltaSrc == bpp);
430
431#ifdef SK_PMCOLOR_IS_RGBA
432    SkOpts::RGB_to_RGB1((uint32_t*) dst, src + offset, width);
433#else
434    SkOpts::RGB_to_BGR1((uint32_t*) dst, src + offset, width);
435#endif
436}
437
438static void swizzle_rgb_to_565(
439       void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
440       int bytesPerPixel, int deltaSrc, int offset, const SkPMColor ctable[]) {
441
442    src += offset;
443    uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow;
444    for (int x = 0; x < dstWidth; x++) {
445        dst[x] = SkPack888ToRGB16(src[0], src[1], src[2]);
446        src += deltaSrc;
447    }
448}
449
450// kRGBA
451
452static void swizzle_rgba_to_n32_premul(
453        void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
454        int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) {
455
456    src += offset;
457    SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
458    for (int x = 0; x < dstWidth; x++) {
459        unsigned alpha = src[3];
460        dst[x] = SkPremultiplyARGBInline(alpha, src[0], src[1], src[2]);
461        src += deltaSrc;
462    }
463}
464
465static void fast_swizzle_rgba_to_n32_premul(
466        void* dst, const uint8_t* src, int width, int bpp, int deltaSrc,
467        int offset, const SkPMColor ctable[]) {
468
469    // This function must not be called if we are sampling.  If we are not
470    // sampling, deltaSrc should equal bpp.
471    SkASSERT(deltaSrc == bpp);
472
473#ifdef SK_PMCOLOR_IS_RGBA
474    SkOpts::RGBA_to_rgbA((uint32_t*) dst, src + offset, width);
475#else
476    SkOpts::RGBA_to_bgrA((uint32_t*) dst, src + offset, width);
477#endif
478}
479
480static void swizzle_rgba_to_n32_unpremul(
481        void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
482        int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) {
483
484    src += offset;
485    uint32_t* SK_RESTRICT dst = reinterpret_cast<uint32_t*>(dstRow);
486    for (int x = 0; x < dstWidth; x++) {
487        unsigned alpha = src[3];
488        dst[x] = SkPackARGB32NoCheck(alpha, src[0], src[1], src[2]);
489        src += deltaSrc;
490    }
491}
492
493static void fast_swizzle_rgba_to_n32_unpremul(
494        void* dst, const uint8_t* src, int width, int bpp, int deltaSrc, int offset,
495        const SkPMColor ctable[]) {
496
497    // This function must not be called if we are sampling.  If we are not
498    // sampling, deltaSrc should equal bpp.
499    SkASSERT(deltaSrc == bpp);
500
501#ifdef SK_PMCOLOR_IS_RGBA
502    memcpy(dst, src + offset, width * bpp);
503#else
504    SkOpts::RGBA_to_BGRA((uint32_t*) dst, src + offset, width);
505#endif
506}
507
508// kCMYK
509//
510// CMYK is stored as four bytes per pixel.
511//
512// We will implement a crude conversion from CMYK -> RGB using formulas
513// from easyrgb.com.
514//
515// CMYK -> CMY
516// C = C * (1 - K) + K
517// M = M * (1 - K) + K
518// Y = Y * (1 - K) + K
519//
520// libjpeg actually gives us inverted CMYK, so we must subtract the
521// original terms from 1.
522// CMYK -> CMY
523// C = (1 - C) * (1 - (1 - K)) + (1 - K)
524// M = (1 - M) * (1 - (1 - K)) + (1 - K)
525// Y = (1 - Y) * (1 - (1 - K)) + (1 - K)
526//
527// Simplifying the above expression.
528// CMYK -> CMY
529// C = 1 - CK
530// M = 1 - MK
531// Y = 1 - YK
532//
533// CMY -> RGB
534// R = (1 - C) * 255
535// G = (1 - M) * 255
536// B = (1 - Y) * 255
537//
538// Therefore the full conversion is below.  This can be verified at
539// www.rapidtables.com (assuming inverted CMYK).
540// CMYK -> RGB
541// R = C * K * 255
542// G = M * K * 255
543// B = Y * K * 255
544//
545// As a final note, we have treated the CMYK values as if they were on
546// a scale from 0-1, when in fact they are 8-bit ints scaling from 0-255.
547// We must divide each CMYK component by 255 to obtain the true conversion
548// we should perform.
549// CMYK -> RGB
550// R = C * K / 255
551// G = M * K / 255
552// B = Y * K / 255
553static void swizzle_cmyk_to_n32(
554        void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
555        int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) {
556
557    src += offset;
558    SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
559    for (int x = 0; x < dstWidth; x++) {
560        const uint8_t r = SkMulDiv255Round(src[0], src[3]);
561        const uint8_t g = SkMulDiv255Round(src[1], src[3]);
562        const uint8_t b = SkMulDiv255Round(src[2], src[3]);
563
564        dst[x] = SkPackARGB32NoCheck(0xFF, r, g, b);
565        src += deltaSrc;
566    }
567}
568
569static void swizzle_cmyk_to_565(
570        void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
571        int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) {
572
573    src += offset;
574    uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow;
575    for (int x = 0; x < dstWidth; x++) {
576        const uint8_t r = SkMulDiv255Round(src[0], src[3]);
577        const uint8_t g = SkMulDiv255Round(src[1], src[3]);
578        const uint8_t b = SkMulDiv255Round(src[2], src[3]);
579
580        dst[x] = SkPack888ToRGB16(r, g, b);
581        src += deltaSrc;
582    }
583}
584
585template <SkSwizzler::RowProc proc>
586void SkSwizzler::SkipLeadingGrayAlphaZerosThen(
587        void* dst, const uint8_t* src, int width,
588        int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) {
589    SkASSERT(!ctable);
590
591    const uint16_t* src16 = (const uint16_t*) (src + offset);
592    uint32_t* dst32 = (uint32_t*) dst;
593
594    // This may miss opportunities to skip when the output is premultiplied,
595    // e.g. for a src pixel 0x00FF which is not zero but becomes zero after premultiplication.
596    while (width > 0 && *src16 == 0x0000) {
597        width--;
598        dst32++;
599        src16 += deltaSrc / 2;
600    }
601    proc(dst32, (const uint8_t*)src16, width, bpp, deltaSrc, 0, ctable);
602}
603
604template <SkSwizzler::RowProc proc>
605void SkSwizzler::SkipLeading8888ZerosThen(
606        void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
607        int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) {
608    SkASSERT(!ctable);
609
610    auto src32 = (const uint32_t*)(src+offset);
611    auto dst32 = (uint32_t*)dstRow;
612
613    // This may miss opportunities to skip when the output is premultiplied,
614    // e.g. for a src pixel 0x00FFFFFF which is not zero but becomes zero after premultiplication.
615    while (dstWidth > 0 && *src32 == 0x00000000) {
616        dstWidth--;
617        dst32++;
618        src32 += deltaSrc/4;
619    }
620    proc(dst32, (const uint8_t*)src32, dstWidth, bpp, deltaSrc, 0, ctable);
621}
622
623SkSwizzler* SkSwizzler::CreateSwizzler(SkSwizzler::SrcConfig sc,
624                                       const SkPMColor* ctable,
625                                       const SkImageInfo& dstInfo,
626                                       const SkCodec::Options& options,
627                                       const SkIRect* frame) {
628    if (dstInfo.colorType() == kUnknown_SkColorType || kUnknown == sc) {
629        return nullptr;
630    }
631    if ((kIndex == sc || kIndex4 == sc || kIndex2 == sc || kIndex1 == sc)
632            && nullptr == ctable) {
633        return nullptr;
634    }
635    RowProc fastProc = nullptr;
636    RowProc proc = nullptr;
637    SkCodec::ZeroInitialized zeroInit = options.fZeroInitialized;
638    switch (sc) {
639        case kBit:
640            switch (dstInfo.colorType()) {
641                case kN32_SkColorType:
642                    proc = &swizzle_bit_to_n32;
643                    break;
644                case kIndex_8_SkColorType:
645                    proc = &swizzle_bit_to_index;
646                    break;
647                case kRGB_565_SkColorType:
648                    proc = &swizzle_bit_to_565;
649                    break;
650                case kGray_8_SkColorType:
651                    proc = &swizzle_bit_to_grayscale;
652                    break;
653                default:
654                    break;
655            }
656            break;
657        case kIndex1:
658        case kIndex2:
659        case kIndex4:
660            switch (dstInfo.colorType()) {
661                case kN32_SkColorType:
662                    proc = &swizzle_small_index_to_n32;
663                    break;
664                case kRGB_565_SkColorType:
665                    proc = &swizzle_small_index_to_565;
666                    break;
667                case kIndex_8_SkColorType:
668                    proc = &swizzle_small_index_to_index;
669                    break;
670                default:
671                    break;
672            }
673            break;
674        case kIndex:
675            switch (dstInfo.colorType()) {
676                case kN32_SkColorType:
677                    // We assume the color premultiplied ctable (or not) as desired.
678                    if (SkCodec::kYes_ZeroInitialized == zeroInit) {
679                        proc = &swizzle_index_to_n32_skipZ;
680                        break;
681                    } else {
682                        proc = &swizzle_index_to_n32;
683                        break;
684                    }
685                    break;
686                case kRGB_565_SkColorType:
687                    proc = &swizzle_index_to_565;
688                    break;
689                case kIndex_8_SkColorType:
690                    proc = &sample1;
691                    fastProc = &copy;
692                    break;
693                default:
694                    break;
695            }
696            break;
697        case kGray:
698            switch (dstInfo.colorType()) {
699                case kN32_SkColorType:
700                    proc = &swizzle_gray_to_n32;
701                    fastProc = &fast_swizzle_gray_to_n32;
702                    break;
703                case kGray_8_SkColorType:
704                    proc = &sample1;
705                    fastProc = &copy;
706                    break;
707                case kRGB_565_SkColorType:
708                    proc = &swizzle_gray_to_565;
709                    break;
710                default:
711                    break;
712            }
713            break;
714        case kGrayAlpha:
715            switch (dstInfo.colorType()) {
716                case kN32_SkColorType:
717                    if (dstInfo.alphaType() == kUnpremul_SkAlphaType) {
718                        if (SkCodec::kYes_ZeroInitialized == zeroInit) {
719                            proc = &SkipLeadingGrayAlphaZerosThen
720                                    <swizzle_grayalpha_to_n32_unpremul>;
721                        } else {
722                            proc = &swizzle_grayalpha_to_n32_unpremul;
723                        }
724                    } else {
725                        if (SkCodec::kYes_ZeroInitialized == zeroInit) {
726                            proc = &SkipLeadingGrayAlphaZerosThen<swizzle_grayalpha_to_n32_premul>;
727                        } else {
728                            proc = &swizzle_grayalpha_to_n32_premul;
729                        }
730                    }
731                    break;
732                default:
733                    break;
734            }
735            break;
736        case kBGR:
737        case kBGRX:
738            switch (dstInfo.colorType()) {
739                case kN32_SkColorType:
740                    proc = &swizzle_bgrx_to_n32;
741                    break;
742                case kRGB_565_SkColorType:
743                    proc = &swizzle_bgrx_to_565;
744                    break;
745                default:
746                    break;
747            }
748            break;
749        case kBGRA:
750            switch (dstInfo.colorType()) {
751                case kN32_SkColorType:
752                    if (dstInfo.alphaType() == kUnpremul_SkAlphaType) {
753                        if (SkCodec::kYes_ZeroInitialized == zeroInit) {
754                            proc = &SkipLeading8888ZerosThen<swizzle_bgra_to_n32_unpremul>;
755                            fastProc = &SkipLeading8888ZerosThen<fast_swizzle_bgra_to_n32_unpremul>;
756                        } else {
757                            proc = &swizzle_bgra_to_n32_unpremul;
758                            fastProc = &fast_swizzle_bgra_to_n32_unpremul;
759                        }
760                    } else {
761                        if (SkCodec::kYes_ZeroInitialized == zeroInit) {
762                            proc = &SkipLeading8888ZerosThen<swizzle_bgra_to_n32_premul>;
763                            fastProc = &SkipLeading8888ZerosThen<fast_swizzle_bgra_to_n32_premul>;
764                        } else {
765                            proc = &swizzle_bgra_to_n32_premul;
766                            fastProc = &fast_swizzle_bgra_to_n32_premul;
767                        }
768                    }
769                    break;
770                default:
771                    break;
772            }
773            break;
774        case kRGB:
775            switch (dstInfo.colorType()) {
776                case kN32_SkColorType:
777                    proc = &swizzle_rgb_to_n32;
778                    fastProc = &fast_swizzle_rgb_to_n32;
779                    break;
780                case kRGB_565_SkColorType:
781                    proc = &swizzle_rgb_to_565;
782                default:
783                    break;
784            }
785            break;
786        case kRGBA:
787            switch (dstInfo.colorType()) {
788                case kN32_SkColorType:
789                    if (dstInfo.alphaType() == kUnpremul_SkAlphaType) {
790                        if (SkCodec::kYes_ZeroInitialized == zeroInit) {
791                            proc = &SkipLeading8888ZerosThen<swizzle_rgba_to_n32_unpremul>;
792                            fastProc = &SkipLeading8888ZerosThen<fast_swizzle_rgba_to_n32_unpremul>;
793                        } else {
794                            proc = &swizzle_rgba_to_n32_unpremul;
795                            fastProc = &fast_swizzle_rgba_to_n32_unpremul;
796                        }
797                    } else {
798                        if (SkCodec::kYes_ZeroInitialized == zeroInit) {
799                            proc = &SkipLeading8888ZerosThen<swizzle_rgba_to_n32_premul>;
800                            fastProc = &SkipLeading8888ZerosThen<fast_swizzle_rgba_to_n32_premul>;
801                        } else {
802                            proc = &swizzle_rgba_to_n32_premul;
803                            fastProc = &fast_swizzle_rgba_to_n32_premul;
804                        }
805                    }
806                    break;
807                default:
808                    break;
809            }
810            break;
811        case kCMYK:
812            switch (dstInfo.colorType()) {
813                case kN32_SkColorType:
814                    proc = &swizzle_cmyk_to_n32;
815                    break;
816                case kRGB_565_SkColorType:
817                    proc = &swizzle_cmyk_to_565;
818                    break;
819                default:
820                    break;
821            }
822            break;
823        case kNoOp8:
824            proc = &sample1;
825            fastProc = &copy;
826            break;
827        case kNoOp16:
828            proc = sample2;
829            fastProc = &copy;
830            break;
831        case kNoOp32:
832            proc = &sample4;
833            fastProc = &copy;
834            break;
835        default:
836            break;
837    }
838
839    // Store bpp in bytes if it is an even multiple, otherwise use bits
840    int srcBPP = SkIsAlign8(BitsPerPixel(sc)) ? BytesPerPixel(sc) : BitsPerPixel(sc);
841    int dstBPP = SkColorTypeBytesPerPixel(dstInfo.colorType());
842
843    int srcOffset = 0;
844    int srcWidth = dstInfo.width();
845    int dstOffset = 0;
846    int dstWidth = srcWidth;
847    if (options.fSubset) {
848        // We do not currently support subset decodes for image types that may have
849        // frames (gif).
850        SkASSERT(!frame);
851        srcOffset = options.fSubset->left();
852        srcWidth = options.fSubset->width();
853        dstWidth = srcWidth;
854    } else if (frame) {
855        dstOffset = frame->left();
856        srcWidth = frame->width();
857    }
858
859    return new SkSwizzler(fastProc, proc, ctable, srcOffset, srcWidth, dstOffset, dstWidth,
860            srcBPP, dstBPP);
861}
862
863SkSwizzler::SkSwizzler(RowProc fastProc, RowProc proc, const SkPMColor* ctable, int srcOffset,
864        int srcWidth, int dstOffset, int dstWidth, int srcBPP, int dstBPP)
865    : fFastProc(fastProc)
866    , fSlowProc(proc)
867    , fActualProc(fFastProc ? fFastProc : fSlowProc)
868    , fColorTable(ctable)
869    , fSrcOffset(srcOffset)
870    , fDstOffset(dstOffset)
871    , fSrcOffsetUnits(srcOffset * srcBPP)
872    , fDstOffsetBytes(dstOffset * dstBPP)
873    , fSrcWidth(srcWidth)
874    , fDstWidth(dstWidth)
875    , fSwizzleWidth(srcWidth)
876    , fAllocatedWidth(dstWidth)
877    , fSampleX(1)
878    , fSrcBPP(srcBPP)
879    , fDstBPP(dstBPP)
880{}
881
882int SkSwizzler::onSetSampleX(int sampleX) {
883    SkASSERT(sampleX > 0); // Surely there is an upper limit? Should there be
884                           // way to report failure?
885    fSampleX = sampleX;
886    fSrcOffsetUnits = (get_start_coord(sampleX) + fSrcOffset) * fSrcBPP;
887    fDstOffsetBytes = (fDstOffset / sampleX) * fDstBPP;
888    fSwizzleWidth = get_scaled_dimension(fSrcWidth, sampleX);
889    fAllocatedWidth = get_scaled_dimension(fDstWidth, sampleX);
890
891    // The optimized swizzler routines do not (yet) support sampling.
892    if (1 == fSampleX && fFastProc) {
893        fActualProc = fFastProc;
894    } else {
895        fActualProc = fSlowProc;
896    }
897
898    return fAllocatedWidth;
899}
900
901void SkSwizzler::swizzle(void* dst, const uint8_t* SK_RESTRICT src) {
902    SkASSERT(nullptr != dst && nullptr != src);
903    fActualProc(SkTAddOffset<void>(dst, fDstOffsetBytes), src, fSwizzleWidth, fSrcBPP,
904            fSampleX * fSrcBPP, fSrcOffsetUnits, fColorTable);
905}
906