• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 = &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 
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