blob: c9eb923053879809706ceec392444136181729e6 [file] [log] [blame]
scroggof24f2242015-03-03 08:59:20 -08001/*
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
msarett74114382015-03-16 11:55:18 -07008#include "SkCodecPriv.h"
scroggof24f2242015-03-03 08:59:20 -08009#include "SkColorPriv.h"
msaretta51e7782016-01-12 06:51:11 -080010#include "SkOpts.h"
scroggof24f2242015-03-03 08:59:20 -080011#include "SkSwizzler.h"
12#include "SkTemplates.h"
13
msarettbda86092016-01-19 10:40:12 -080014static 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);
emmaleer8f4ba762015-08-14 07:44:46 -070019
msarettbda86092016-01-19 10:40:12 -080020 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[]) {
emmaleer8f4ba762015-08-14 07:44:46 -070025 src += offset;
msarettbda86092016-01-19 10:40:12 -080026 uint8_t* dst8 = (uint8_t*) dst;
emmaleer8f4ba762015-08-14 07:44:46 -070027 for (int x = 0; x < width; x++) {
msarettbda86092016-01-19 10:40:12 -080028 dst8[x] = *src;
emmaleer8f4ba762015-08-14 07:44:46 -070029 src += deltaSrc;
30 }
emmaleer8f4ba762015-08-14 07:44:46 -070031}
32
msarettbda86092016-01-19 10:40:12 -080033static 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}
msarett5406d6f2015-08-31 06:55:13 -070052
msarett99f567e2015-08-05 12:58:26 -070053// kBit
54// These routines exclusively choose between white and black
55
56#define GRAYSCALE_BLACK 0
57#define GRAYSCALE_WHITE 0xFF
58
emmaleer8f4ba762015-08-14 07:44:46 -070059
60// same as swizzle_bit_to_index and swizzle_bit_to_n32 except for value assigned to dst[x]
msaretta4970dc2016-01-11 07:23:23 -080061static void swizzle_bit_to_grayscale(
emmaleer8f4ba762015-08-14 07:44:46 -070062 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
msarett5406d6f2015-08-31 06:55:13 -070063 int bpp, int deltaSrc, int offset, const SkPMColor* /*ctable*/) {
emmaleer8f4ba762015-08-14 07:44:46 -070064
msarett99f567e2015-08-05 12:58:26 -070065 uint8_t* SK_RESTRICT dst = (uint8_t*) dstRow;
66
emmaleer8f4ba762015-08-14 07:44:46 -070067 // 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;
msarett99f567e2015-08-05 12:58:26 -070079 }
msarett99f567e2015-08-05 12:58:26 -070080}
81
82#undef GRAYSCALE_BLACK
83#undef GRAYSCALE_WHITE
84
emmaleer8f4ba762015-08-14 07:44:46 -070085// same as swizzle_bit_to_grayscale and swizzle_bit_to_n32 except for value assigned to dst[x]
msaretta4970dc2016-01-11 07:23:23 -080086static void swizzle_bit_to_index(
emmaleer8f4ba762015-08-14 07:44:46 -070087 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
msarett5406d6f2015-08-31 06:55:13 -070088 int bpp, int deltaSrc, int offset, const SkPMColor* /*ctable*/) {
msarett99f567e2015-08-05 12:58:26 -070089 uint8_t* SK_RESTRICT dst = (uint8_t*) dstRow;
90
emmaleer8f4ba762015-08-14 07:44:46 -070091 // 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);
msarett99f567e2015-08-05 12:58:26 -0700103 }
msarett99f567e2015-08-05 12:58:26 -0700104}
105
emmaleer8f4ba762015-08-14 07:44:46 -0700106// same as swizzle_bit_to_grayscale and swizzle_bit_to_index except for value assigned to dst[x]
msaretta4970dc2016-01-11 07:23:23 -0800107static void swizzle_bit_to_n32(
emmaleer8f4ba762015-08-14 07:44:46 -0700108 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
msarett5406d6f2015-08-31 06:55:13 -0700109 int bpp, int deltaSrc, int offset, const SkPMColor* /*ctable*/) {
msarett99f567e2015-08-05 12:58:26 -0700110 SkPMColor* SK_RESTRICT dst = (SkPMColor*) dstRow;
111
emmaleer8f4ba762015-08-14 07:44:46 -0700112 // 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;
msarett99f567e2015-08-05 12:58:26 -0700124 }
msarett99f567e2015-08-05 12:58:26 -0700125}
126
scroggocc2feb12015-08-14 08:32:46 -0700127#define RGB565_BLACK 0
128#define RGB565_WHITE 0xFFFF
129
msaretta4970dc2016-01-11 07:23:23 -0800130static void swizzle_bit_to_565(
scroggocc2feb12015-08-14 08:32:46 -0700131 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
msarett5406d6f2015-08-31 06:55:13 -0700132 int bpp, int deltaSrc, int offset, const SkPMColor* /*ctable*/) {
scroggocc2feb12015-08-14 08:32:46 -0700133 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 }
scroggocc2feb12015-08-14 08:32:46 -0700148}
149
150#undef RGB565_BLACK
151#undef RGB565_WHITE
152
msarett74114382015-03-16 11:55:18 -0700153// kIndex1, kIndex2, kIndex4
154
msaretta4970dc2016-01-11 07:23:23 -0800155static void swizzle_small_index_to_index(
emmaleer8f4ba762015-08-14 07:44:46 -0700156 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
msarett5406d6f2015-08-31 06:55:13 -0700157 int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) {
msarett438b2ad2015-04-09 12:43:10 -0700158
msarett5406d6f2015-08-31 06:55:13 -0700159 uint8_t* dst = (uint8_t*) dstRow;
msarett5406d6f2015-08-31 06:55:13 -0700160 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;
msarett5406d6f2015-08-31 06:55:13 -0700166
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;
msarett438b2ad2015-04-09 12:43:10 -0700173 }
msarett438b2ad2015-04-09 12:43:10 -0700174}
175
msaretta4970dc2016-01-11 07:23:23 -0800176static void swizzle_small_index_to_565(
scroggocc2feb12015-08-14 08:32:46 -0700177 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
msarett5406d6f2015-08-31 06:55:13 -0700178 int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) {
scroggocc2feb12015-08-14 08:32:46 -0700179
msarett5406d6f2015-08-31 06:55:13 -0700180 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]);
scroggocc2feb12015-08-14 08:32:46 -0700194 }
scroggocc2feb12015-08-14 08:32:46 -0700195}
196
msaretta4970dc2016-01-11 07:23:23 -0800197static void swizzle_small_index_to_n32(
emmaleer8f4ba762015-08-14 07:44:46 -0700198 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
msarett5406d6f2015-08-31 06:55:13 -0700199 int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) {
msarett74114382015-03-16 11:55:18 -0700200
msarett5406d6f2015-08-31 06:55:13 -0700201 SkPMColor* dst = (SkPMColor*) dstRow;
msarett5406d6f2015-08-31 06:55:13 -0700202 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];
msarett5406d6f2015-08-31 06:55:13 -0700208
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];
msarett74114382015-03-16 11:55:18 -0700215 }
msarett74114382015-03-16 11:55:18 -0700216}
217
msarette16b04a2015-04-15 07:32:19 -0700218// kIndex
219
msaretta4970dc2016-01-11 07:23:23 -0800220static void swizzle_index_to_n32(
emmaleer8f4ba762015-08-14 07:44:46 -0700221 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
msarett5406d6f2015-08-31 06:55:13 -0700222 int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) {
emmaleer8f4ba762015-08-14 07:44:46 -0700223
224 src += offset;
225 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
emmaleer8f4ba762015-08-14 07:44:46 -0700226 for (int x = 0; x < dstWidth; x++) {
227 SkPMColor c = ctable[*src];
emmaleer8f4ba762015-08-14 07:44:46 -0700228 dst[x] = c;
229 src += deltaSrc;
230 }
emmaleer8f4ba762015-08-14 07:44:46 -0700231}
232
msaretta4970dc2016-01-11 07:23:23 -0800233static void swizzle_index_to_n32_skipZ(
emmaleer8f4ba762015-08-14 07:44:46 -0700234 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
msarett5406d6f2015-08-31 06:55:13 -0700235 int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) {
emmaleer8f4ba762015-08-14 07:44:46 -0700236
237 src += offset;
238 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
emmaleer8f4ba762015-08-14 07:44:46 -0700239 for (int x = 0; x < dstWidth; x++) {
240 SkPMColor c = ctable[*src];
emmaleer8f4ba762015-08-14 07:44:46 -0700241 if (c != 0) {
242 dst[x] = c;
243 }
244 src += deltaSrc;
245 }
emmaleer8f4ba762015-08-14 07:44:46 -0700246}
247
msaretta4970dc2016-01-11 07:23:23 -0800248static void swizzle_index_to_565(
emmaleer8f4ba762015-08-14 07:44:46 -0700249 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
msarett5406d6f2015-08-31 06:55:13 -0700250 int bytesPerPixel, int deltaSrc, int offset, const SkPMColor ctable[]) {
emmaleer8f4ba762015-08-14 07:44:46 -0700251 src += offset;
scroggoab60c5b2015-08-06 06:08:18 -0700252 uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow;
emmaleer8f4ba762015-08-14 07:44:46 -0700253 for (int x = 0; x < dstWidth; x++) {
scroggoab60c5b2015-08-06 06:08:18 -0700254 dst[x] = SkPixel32ToPixel16(ctable[*src]);
msarett5406d6f2015-08-31 06:55:13 -0700255 src += deltaSrc;
scroggoab60c5b2015-08-06 06:08:18 -0700256 }
scroggoab60c5b2015-08-06 06:08:18 -0700257}
258
msarette16b04a2015-04-15 07:32:19 -0700259// kGray
260
msaretta4970dc2016-01-11 07:23:23 -0800261static void swizzle_gray_to_n32(
emmaleer8f4ba762015-08-14 07:44:46 -0700262 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
msarett5406d6f2015-08-31 06:55:13 -0700263 int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) {
msarette16b04a2015-04-15 07:32:19 -0700264
emmaleer8f4ba762015-08-14 07:44:46 -0700265 src += offset;
msarette16b04a2015-04-15 07:32:19 -0700266 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
emmaleer8f4ba762015-08-14 07:44:46 -0700267 for (int x = 0; x < dstWidth; x++) {
268 dst[x] = SkPackARGB32NoCheck(0xFF, *src, *src, *src);
269 src += deltaSrc;
msarette16b04a2015-04-15 07:32:19 -0700270 }
msarette16b04a2015-04-15 07:32:19 -0700271}
272
msarett2eff71c2016-02-02 12:59:45 -0800273static 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
msaretta4970dc2016-01-11 07:23:23 -0800286static void swizzle_gray_to_565(
emmaleer8f4ba762015-08-14 07:44:46 -0700287 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
msarett5406d6f2015-08-31 06:55:13 -0700288 int bytesPerPixel, int deltaSrc, int offset, const SkPMColor ctable[]) {
msaretta4970dc2016-01-11 07:23:23 -0800289
emmaleer8f4ba762015-08-14 07:44:46 -0700290 src += offset;
scroggoab60c5b2015-08-06 06:08:18 -0700291 uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow;
emmaleer8f4ba762015-08-14 07:44:46 -0700292 for (int x = 0; x < dstWidth; x++) {
scroggoab60c5b2015-08-06 06:08:18 -0700293 dst[x] = SkPack888ToRGB16(src[0], src[0], src[0]);
msarett5406d6f2015-08-31 06:55:13 -0700294 src += deltaSrc;
scroggoab60c5b2015-08-06 06:08:18 -0700295 }
scroggoab60c5b2015-08-06 06:08:18 -0700296}
297
msarett93e613d2016-02-03 10:44:46 -0800298// 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
msarett1e060792016-02-03 11:17:43 -0800312static 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
msarett93e613d2016-02-03 10:44:46 -0800325static 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
msarett1e060792016-02-03 11:17:43 -0800338static 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
msarett34e0ec42016-04-22 16:27:24 -0700351// kBGR
msarette16b04a2015-04-15 07:32:19 -0700352
msarett34e0ec42016-04-22 16:27:24 -0700353static void swizzle_bgr_to_565(
scroggocc2feb12015-08-14 08:32:46 -0700354 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
msarett5406d6f2015-08-31 06:55:13 -0700355 int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) {
msaretta4970dc2016-01-11 07:23:23 -0800356
scroggocc2feb12015-08-14 08:32:46 -0700357 src += offset;
358 uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow;
359 for (int x = 0; x < dstWidth; x++) {
360 dst[x] = SkPack888ToRGB16(src[2], src[1], src[0]);
361 src += deltaSrc;
362 }
scroggocc2feb12015-08-14 08:32:46 -0700363}
364
msarettbda86092016-01-19 10:40:12 -0800365// kRGB
msarett03108de2016-01-15 11:02:36 -0800366
msarett34e0ec42016-04-22 16:27:24 -0700367static void swizzle_rgb_to_rgba(
emmaleer8f4ba762015-08-14 07:44:46 -0700368 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
msarett5406d6f2015-08-31 06:55:13 -0700369 int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) {
msarett74114382015-03-16 11:55:18 -0700370
emmaleer8f4ba762015-08-14 07:44:46 -0700371 src += offset;
scroggof24f2242015-03-03 08:59:20 -0800372 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
emmaleer8f4ba762015-08-14 07:44:46 -0700373 for (int x = 0; x < dstWidth; x++) {
msarett34e0ec42016-04-22 16:27:24 -0700374 dst[x] = SkPackARGB_as_RGBA(0xFF, src[0], src[1], src[2]);
emmaleer8f4ba762015-08-14 07:44:46 -0700375 src += deltaSrc;
scroggof24f2242015-03-03 08:59:20 -0800376 }
scroggof24f2242015-03-03 08:59:20 -0800377}
378
msarett34e0ec42016-04-22 16:27:24 -0700379static void swizzle_rgb_to_bgra(
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 dst[x] = SkPackARGB_as_BGRA(0xFF, src[0], src[1], src[2]);
387 src += deltaSrc;
388 }
389}
390
391static void fast_swizzle_rgb_to_rgba(
msarettf1b8b6a2016-01-22 09:54:21 -0800392 void* dst, const uint8_t* src, int width, int bpp, int deltaSrc,
393 int offset, const SkPMColor ctable[]) {
msarett03108de2016-01-15 11:02:36 -0800394
msarettf1b8b6a2016-01-22 09:54:21 -0800395 // This function must not be called if we are sampling. If we are not
396 // sampling, deltaSrc should equal bpp.
397 SkASSERT(deltaSrc == bpp);
398
msarettf1b8b6a2016-01-22 09:54:21 -0800399 SkOpts::RGB_to_RGB1((uint32_t*) dst, src + offset, width);
msarett34e0ec42016-04-22 16:27:24 -0700400}
401
402static void fast_swizzle_rgb_to_bgra(
403 void* dst, const uint8_t* src, int width, int bpp, int deltaSrc,
404 int offset, const SkPMColor ctable[]) {
405
406 // This function must not be called if we are sampling. If we are not
407 // sampling, deltaSrc should equal bpp.
408 SkASSERT(deltaSrc == bpp);
409
msarettf1b8b6a2016-01-22 09:54:21 -0800410 SkOpts::RGB_to_BGR1((uint32_t*) dst, src + offset, width);
msarettf1b8b6a2016-01-22 09:54:21 -0800411}
msarett03108de2016-01-15 11:02:36 -0800412
msarettbda86092016-01-19 10:40:12 -0800413static void swizzle_rgb_to_565(
emmaleer8f4ba762015-08-14 07:44:46 -0700414 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
msarett5406d6f2015-08-31 06:55:13 -0700415 int bytesPerPixel, int deltaSrc, int offset, const SkPMColor ctable[]) {
msaretta4970dc2016-01-11 07:23:23 -0800416
emmaleer8f4ba762015-08-14 07:44:46 -0700417 src += offset;
scroggoab60c5b2015-08-06 06:08:18 -0700418 uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow;
emmaleer8f4ba762015-08-14 07:44:46 -0700419 for (int x = 0; x < dstWidth; x++) {
scroggoab60c5b2015-08-06 06:08:18 -0700420 dst[x] = SkPack888ToRGB16(src[0], src[1], src[2]);
msarett5406d6f2015-08-31 06:55:13 -0700421 src += deltaSrc;
scroggoab60c5b2015-08-06 06:08:18 -0700422 }
scroggoab60c5b2015-08-06 06:08:18 -0700423}
424
scroggoab60c5b2015-08-06 06:08:18 -0700425// kRGBA
msarett03108de2016-01-15 11:02:36 -0800426
msarett34e0ec42016-04-22 16:27:24 -0700427static void swizzle_rgba_to_rgba_premul(
emmaleer8f4ba762015-08-14 07:44:46 -0700428 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
msarett5406d6f2015-08-31 06:55:13 -0700429 int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) {
msarett74114382015-03-16 11:55:18 -0700430
emmaleer8f4ba762015-08-14 07:44:46 -0700431 src += offset;
scroggof24f2242015-03-03 08:59:20 -0800432 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
emmaleer8f4ba762015-08-14 07:44:46 -0700433 for (int x = 0; x < dstWidth; x++) {
msarett34e0ec42016-04-22 16:27:24 -0700434 dst[x] = premultiply_argb_as_rgba(src[3], src[0], src[1], src[2]);
emmaleer8f4ba762015-08-14 07:44:46 -0700435 src += deltaSrc;
scroggof24f2242015-03-03 08:59:20 -0800436 }
scroggof24f2242015-03-03 08:59:20 -0800437}
438
msarett34e0ec42016-04-22 16:27:24 -0700439static void swizzle_rgba_to_bgra_premul(
440 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
441 int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) {
442
443 src += offset;
444 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
445 for (int x = 0; x < dstWidth; x++) {
446 dst[x] = premultiply_argb_as_bgra(src[3], src[0], src[1], src[2]);
447 src += deltaSrc;
448 }
449}
450
451static void fast_swizzle_rgba_to_rgba_premul(
msaretta51e7782016-01-12 06:51:11 -0800452 void* dst, const uint8_t* src, int width, int bpp, int deltaSrc,
453 int offset, const SkPMColor ctable[]) {
454
455 // This function must not be called if we are sampling. If we are not
456 // sampling, deltaSrc should equal bpp.
457 SkASSERT(deltaSrc == bpp);
458
mtklein8bf7b792016-01-22 07:42:53 -0800459 SkOpts::RGBA_to_rgbA((uint32_t*) dst, src + offset, width);
msaretta51e7782016-01-12 06:51:11 -0800460}
461
msarett34e0ec42016-04-22 16:27:24 -0700462static void fast_swizzle_rgba_to_bgra_premul(
463 void* dst, const uint8_t* src, int width, int bpp, int deltaSrc,
464 int offset, const SkPMColor ctable[]) {
465
466 // This function must not be called if we are sampling. If we are not
467 // sampling, deltaSrc should equal bpp.
468 SkASSERT(deltaSrc == bpp);
469
470 SkOpts::RGBA_to_bgrA((uint32_t*) dst, src + offset, width);
471}
472
473static void swizzle_rgba_to_bgra_unpremul(
emmaleer8f4ba762015-08-14 07:44:46 -0700474 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
msarett5406d6f2015-08-31 06:55:13 -0700475 int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) {
msarett74114382015-03-16 11:55:18 -0700476
emmaleer8f4ba762015-08-14 07:44:46 -0700477 src += offset;
scroggof24f2242015-03-03 08:59:20 -0800478 uint32_t* SK_RESTRICT dst = reinterpret_cast<uint32_t*>(dstRow);
emmaleer8f4ba762015-08-14 07:44:46 -0700479 for (int x = 0; x < dstWidth; x++) {
scroggof24f2242015-03-03 08:59:20 -0800480 unsigned alpha = src[3];
msarett34e0ec42016-04-22 16:27:24 -0700481 dst[x] = SkPackARGB_as_BGRA(alpha, src[0], src[1], src[2]);
emmaleer8f4ba762015-08-14 07:44:46 -0700482 src += deltaSrc;
scroggof24f2242015-03-03 08:59:20 -0800483 }
scroggof24f2242015-03-03 08:59:20 -0800484}
485
msarett34e0ec42016-04-22 16:27:24 -0700486static void fast_swizzle_rgba_to_bgra_unpremul(
msarettbda86092016-01-19 10:40:12 -0800487 void* dst, const uint8_t* src, int width, int bpp, int deltaSrc, int offset,
488 const SkPMColor ctable[]) {
489
490 // This function must not be called if we are sampling. If we are not
491 // sampling, deltaSrc should equal bpp.
492 SkASSERT(deltaSrc == bpp);
493
mtklein8bf7b792016-01-22 07:42:53 -0800494 SkOpts::RGBA_to_BGRA((uint32_t*) dst, src + offset, width);
msarettbda86092016-01-19 10:40:12 -0800495}
496
scroggoef27d892015-10-23 09:29:22 -0700497// kCMYK
498//
499// CMYK is stored as four bytes per pixel.
500//
501// We will implement a crude conversion from CMYK -> RGB using formulas
502// from easyrgb.com.
503//
504// CMYK -> CMY
505// C = C * (1 - K) + K
506// M = M * (1 - K) + K
507// Y = Y * (1 - K) + K
508//
509// libjpeg actually gives us inverted CMYK, so we must subtract the
510// original terms from 1.
511// CMYK -> CMY
512// C = (1 - C) * (1 - (1 - K)) + (1 - K)
513// M = (1 - M) * (1 - (1 - K)) + (1 - K)
514// Y = (1 - Y) * (1 - (1 - K)) + (1 - K)
515//
516// Simplifying the above expression.
517// CMYK -> CMY
518// C = 1 - CK
519// M = 1 - MK
520// Y = 1 - YK
521//
522// CMY -> RGB
523// R = (1 - C) * 255
524// G = (1 - M) * 255
525// B = (1 - Y) * 255
526//
527// Therefore the full conversion is below. This can be verified at
528// www.rapidtables.com (assuming inverted CMYK).
529// CMYK -> RGB
530// R = C * K * 255
531// G = M * K * 255
532// B = Y * K * 255
533//
534// As a final note, we have treated the CMYK values as if they were on
535// a scale from 0-1, when in fact they are 8-bit ints scaling from 0-255.
536// We must divide each CMYK component by 255 to obtain the true conversion
537// we should perform.
538// CMYK -> RGB
539// R = C * K / 255
540// G = M * K / 255
541// B = Y * K / 255
msarett34e0ec42016-04-22 16:27:24 -0700542static void swizzle_cmyk_to_rgba(
scroggoef27d892015-10-23 09:29:22 -0700543 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
544 int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) {
545
546 src += offset;
547 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
548 for (int x = 0; x < dstWidth; x++) {
549 const uint8_t r = SkMulDiv255Round(src[0], src[3]);
550 const uint8_t g = SkMulDiv255Round(src[1], src[3]);
551 const uint8_t b = SkMulDiv255Round(src[2], src[3]);
552
msarett34e0ec42016-04-22 16:27:24 -0700553 dst[x] = SkPackARGB_as_RGBA(0xFF, r, g, b);
scroggoef27d892015-10-23 09:29:22 -0700554 src += deltaSrc;
555 }
scroggoef27d892015-10-23 09:29:22 -0700556}
557
msarett34e0ec42016-04-22 16:27:24 -0700558static void swizzle_cmyk_to_bgra(
559 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
560 int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) {
561
562 src += offset;
563 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
564 for (int x = 0; x < dstWidth; x++) {
565 const uint8_t r = SkMulDiv255Round(src[0], src[3]);
566 const uint8_t g = SkMulDiv255Round(src[1], src[3]);
567 const uint8_t b = SkMulDiv255Round(src[2], src[3]);
568
569 dst[x] = SkPackARGB_as_BGRA(0xFF, r, g, b);
570 src += deltaSrc;
571 }
572}
573
574static void fast_swizzle_cmyk_to_rgba(
msarettc5c322d2016-02-08 13:26:25 -0800575 void* dst, const uint8_t* src, int width, int bpp, int deltaSrc, int offset,
576 const SkPMColor ctable[]) {
577
578 // This function must not be called if we are sampling. If we are not
579 // sampling, deltaSrc should equal bpp.
580 SkASSERT(deltaSrc == bpp);
581
msarettc5c322d2016-02-08 13:26:25 -0800582 SkOpts::inverted_CMYK_to_RGB1((uint32_t*) dst, src + offset, width);
msarett34e0ec42016-04-22 16:27:24 -0700583}
584
585static void fast_swizzle_cmyk_to_bgra(
586 void* dst, const uint8_t* src, int width, int bpp, int deltaSrc, int offset,
587 const SkPMColor ctable[]) {
588
589 // This function must not be called if we are sampling. If we are not
590 // sampling, deltaSrc should equal bpp.
591 SkASSERT(deltaSrc == bpp);
592
msarettc5c322d2016-02-08 13:26:25 -0800593 SkOpts::inverted_CMYK_to_BGR1((uint32_t*) dst, src + offset, width);
msarettc5c322d2016-02-08 13:26:25 -0800594}
595
msaretta4970dc2016-01-11 07:23:23 -0800596static void swizzle_cmyk_to_565(
scroggoef27d892015-10-23 09:29:22 -0700597 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
598 int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) {
599
600 src += offset;
601 uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow;
602 for (int x = 0; x < dstWidth; x++) {
603 const uint8_t r = SkMulDiv255Round(src[0], src[3]);
604 const uint8_t g = SkMulDiv255Round(src[1], src[3]);
605 const uint8_t b = SkMulDiv255Round(src[2], src[3]);
606
607 dst[x] = SkPack888ToRGB16(r, g, b);
608 src += deltaSrc;
609 }
scroggoef27d892015-10-23 09:29:22 -0700610}
611
mtklein8604ca22016-01-11 13:13:55 -0800612template <SkSwizzler::RowProc proc>
msarett93e613d2016-02-03 10:44:46 -0800613void SkSwizzler::SkipLeadingGrayAlphaZerosThen(
614 void* dst, const uint8_t* src, int width,
615 int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) {
616 SkASSERT(!ctable);
617
618 const uint16_t* src16 = (const uint16_t*) (src + offset);
619 uint32_t* dst32 = (uint32_t*) dst;
620
621 // This may miss opportunities to skip when the output is premultiplied,
622 // e.g. for a src pixel 0x00FF which is not zero but becomes zero after premultiplication.
623 while (width > 0 && *src16 == 0x0000) {
624 width--;
625 dst32++;
626 src16 += deltaSrc / 2;
627 }
628 proc(dst32, (const uint8_t*)src16, width, bpp, deltaSrc, 0, ctable);
629}
630
631template <SkSwizzler::RowProc proc>
mtklein8604ca22016-01-11 13:13:55 -0800632void SkSwizzler::SkipLeading8888ZerosThen(
633 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
634 int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) {
635 SkASSERT(!ctable);
636
637 auto src32 = (const uint32_t*)(src+offset);
638 auto dst32 = (uint32_t*)dstRow;
639
640 // This may miss opportunities to skip when the output is premultiplied,
641 // e.g. for a src pixel 0x00FFFFFF which is not zero but becomes zero after premultiplication.
642 while (dstWidth > 0 && *src32 == 0x00000000) {
643 dstWidth--;
644 dst32++;
645 src32 += deltaSrc/4;
scroggof24f2242015-03-03 08:59:20 -0800646 }
mtklein8604ca22016-01-11 13:13:55 -0800647 proc(dst32, (const uint8_t*)src32, dstWidth, bpp, deltaSrc, 0, ctable);
scroggof24f2242015-03-03 08:59:20 -0800648}
scroggof24f2242015-03-03 08:59:20 -0800649
msaretta45a6682016-04-22 13:18:37 -0700650SkSwizzler* SkSwizzler::CreateSwizzler(const SkEncodedInfo& encodedInfo,
msarett74114382015-03-16 11:55:18 -0700651 const SkPMColor* ctable,
msarettfdb47572015-10-13 12:50:14 -0700652 const SkImageInfo& dstInfo,
msarett5af4e0b2015-11-17 11:18:03 -0800653 const SkCodec::Options& options,
msarett68758ae2016-04-25 11:41:15 -0700654 const SkIRect* frame,
655 bool preSwizzled) {
msaretta45a6682016-04-22 13:18:37 -0700656 if (SkEncodedInfo::kPalette_Color == encodedInfo.color() && nullptr == ctable) {
halcanary96fcdcc2015-08-27 07:41:13 -0700657 return nullptr;
scroggof24f2242015-03-03 08:59:20 -0800658 }
msaretta45a6682016-04-22 13:18:37 -0700659
msaretta51e7782016-01-12 06:51:11 -0800660 RowProc fastProc = nullptr;
halcanary96fcdcc2015-08-27 07:41:13 -0700661 RowProc proc = nullptr;
msarett68758ae2016-04-25 11:41:15 -0700662 if (preSwizzled) {
663 switch (dstInfo.colorType()) {
664 case kGray_8_SkColorType:
665 proc = &sample1;
666 fastProc = &copy;
667 break;
668 case kRGB_565_SkColorType:
669 proc = &sample2;
670 fastProc = &copy;
671 break;
672 case kRGBA_8888_SkColorType:
673 case kBGRA_8888_SkColorType:
674 proc = &sample4;
675 fastProc = &copy;
676 break;
677 default:
678 return nullptr;
679 }
680 } else {
681 SkCodec::ZeroInitialized zeroInit = options.fZeroInitialized;
682 const bool premultiply = (SkEncodedInfo::kOpaque_Alpha != encodedInfo.alpha()) &&
683 (kPremul_SkAlphaType == dstInfo.alphaType());
684
685 switch (encodedInfo.color()) {
686 case SkEncodedInfo::kGray_Color:
687 switch (encodedInfo.bitsPerComponent()) {
688 case 1:
689 switch (dstInfo.colorType()) {
690 case kRGBA_8888_SkColorType:
691 case kBGRA_8888_SkColorType:
692 proc = &swizzle_bit_to_n32;
693 break;
694 case kIndex_8_SkColorType:
695 proc = &swizzle_bit_to_index;
696 break;
697 case kRGB_565_SkColorType:
698 proc = &swizzle_bit_to_565;
699 break;
700 case kGray_8_SkColorType:
701 proc = &swizzle_bit_to_grayscale;
702 break;
703 default:
704 return nullptr;
msaretta45a6682016-04-22 13:18:37 -0700705 }
msarett68758ae2016-04-25 11:41:15 -0700706 break;
707 case 8:
708 switch (dstInfo.colorType()) {
709 case kRGBA_8888_SkColorType:
710 case kBGRA_8888_SkColorType:
711 proc = &swizzle_gray_to_n32;
712 fastProc = &fast_swizzle_gray_to_n32;
713 break;
714 case kGray_8_SkColorType:
715 proc = &sample1;
716 fastProc = &copy;
717 break;
718 case kRGB_565_SkColorType:
719 proc = &swizzle_gray_to_565;
720 break;
721 default:
722 return nullptr;
msarett93e613d2016-02-03 10:44:46 -0800723 }
msarett68758ae2016-04-25 11:41:15 -0700724 break;
725 default:
726 return nullptr;
727 }
728 break;
729 case SkEncodedInfo::kGrayAlpha_Color:
730 switch (dstInfo.colorType()) {
731 case kRGBA_8888_SkColorType:
732 case kBGRA_8888_SkColorType:
733 if (premultiply) {
msaretta45a6682016-04-22 13:18:37 -0700734 if (SkCodec::kYes_ZeroInitialized == zeroInit) {
msarett68758ae2016-04-25 11:41:15 -0700735 proc = &SkipLeadingGrayAlphaZerosThen
736 <swizzle_grayalpha_to_n32_premul>;
737 fastProc = &SkipLeadingGrayAlphaZerosThen
738 <fast_swizzle_grayalpha_to_n32_premul>;
msaretta45a6682016-04-22 13:18:37 -0700739 } else {
msarett68758ae2016-04-25 11:41:15 -0700740 proc = &swizzle_grayalpha_to_n32_premul;
741 fastProc = &fast_swizzle_grayalpha_to_n32_premul;
msaretta45a6682016-04-22 13:18:37 -0700742 }
scroggof24f2242015-03-03 08:59:20 -0800743 } else {
msarett68758ae2016-04-25 11:41:15 -0700744 if (SkCodec::kYes_ZeroInitialized == zeroInit) {
745 proc = &SkipLeadingGrayAlphaZerosThen
746 <swizzle_grayalpha_to_n32_unpremul>;
747 fastProc = &SkipLeadingGrayAlphaZerosThen
748 <fast_swizzle_grayalpha_to_n32_unpremul>;
749 } else {
750 proc = &swizzle_grayalpha_to_n32_unpremul;
751 fastProc = &fast_swizzle_grayalpha_to_n32_unpremul;
752 }
scroggof24f2242015-03-03 08:59:20 -0800753 }
msarett68758ae2016-04-25 11:41:15 -0700754 break;
755 default:
756 return nullptr;
757 }
758 break;
759 case SkEncodedInfo::kPalette_Color:
760 // We assume that the color table is premultiplied and swizzled
761 // as desired.
762 switch (encodedInfo.bitsPerComponent()) {
763 case 1:
764 case 2:
765 case 4:
766 switch (dstInfo.colorType()) {
767 case kRGBA_8888_SkColorType:
768 case kBGRA_8888_SkColorType:
769 proc = &swizzle_small_index_to_n32;
770 break;
771 case kRGB_565_SkColorType:
772 proc = &swizzle_small_index_to_565;
773 break;
774 case kIndex_8_SkColorType:
775 proc = &swizzle_small_index_to_index;
776 break;
777 default:
778 return nullptr;
779 }
780 break;
781 case 8:
782 switch (dstInfo.colorType()) {
783 case kRGBA_8888_SkColorType:
784 case kBGRA_8888_SkColorType:
785 if (SkCodec::kYes_ZeroInitialized == zeroInit) {
786 proc = &swizzle_index_to_n32_skipZ;
787 } else {
788 proc = &swizzle_index_to_n32;
789 }
790 break;
791 case kRGB_565_SkColorType:
792 proc = &swizzle_index_to_565;
793 break;
794 case kIndex_8_SkColorType:
795 proc = &sample1;
796 fastProc = &copy;
797 break;
798 default:
799 return nullptr;
800 }
801 break;
802 default:
803 return nullptr;
804 }
805 break;
806 case SkEncodedInfo::kRGB_Color:
807 switch (dstInfo.colorType()) {
808 case kRGBA_8888_SkColorType:
809 proc = &swizzle_rgb_to_rgba;
810 fastProc = &fast_swizzle_rgb_to_rgba;
811 break;
812 case kBGRA_8888_SkColorType:
813 proc = &swizzle_rgb_to_bgra;
814 fastProc = &fast_swizzle_rgb_to_bgra;
815 break;
816 case kRGB_565_SkColorType:
817 proc = &swizzle_rgb_to_565;
818 break;
819 default:
820 return nullptr;
821 }
822 break;
823 case SkEncodedInfo::kRGBA_Color:
824 switch (dstInfo.colorType()) {
825 case kRGBA_8888_SkColorType:
826 if (premultiply) {
827 if (SkCodec::kYes_ZeroInitialized == zeroInit) {
828 proc = &SkipLeading8888ZerosThen<swizzle_rgba_to_rgba_premul>;
829 fastProc = &SkipLeading8888ZerosThen
830 <fast_swizzle_rgba_to_rgba_premul>;
831 } else {
832 proc = &swizzle_rgba_to_rgba_premul;
833 fastProc = &fast_swizzle_rgba_to_rgba_premul;
834 }
msaretta45a6682016-04-22 13:18:37 -0700835 } else {
msarett68758ae2016-04-25 11:41:15 -0700836 if (SkCodec::kYes_ZeroInitialized == zeroInit) {
837 proc = &SkipLeading8888ZerosThen<sample4>;
838 fastProc = &SkipLeading8888ZerosThen<copy>;
839 } else {
840 proc = &sample4;
841 fastProc = &copy;
842 }
msarett34e0ec42016-04-22 16:27:24 -0700843 }
msarett68758ae2016-04-25 11:41:15 -0700844 break;
845 case kBGRA_8888_SkColorType:
846 if (premultiply) {
847 if (SkCodec::kYes_ZeroInitialized == zeroInit) {
848 proc = &SkipLeading8888ZerosThen<swizzle_rgba_to_bgra_premul>;
849 fastProc = &SkipLeading8888ZerosThen
850 <fast_swizzle_rgba_to_bgra_premul>;
851 } else {
852 proc = &swizzle_rgba_to_bgra_premul;
853 fastProc = &fast_swizzle_rgba_to_bgra_premul;
854 }
msarett34e0ec42016-04-22 16:27:24 -0700855 } else {
msarett68758ae2016-04-25 11:41:15 -0700856 if (SkCodec::kYes_ZeroInitialized == zeroInit) {
857 proc = &SkipLeading8888ZerosThen<swizzle_rgba_to_bgra_unpremul>;
858 fastProc = &SkipLeading8888ZerosThen
859 <fast_swizzle_rgba_to_bgra_unpremul>;
860 } else {
861 proc = &swizzle_rgba_to_bgra_unpremul;
862 fastProc = &fast_swizzle_rgba_to_bgra_unpremul;
863 }
msarett34e0ec42016-04-22 16:27:24 -0700864 }
msarett68758ae2016-04-25 11:41:15 -0700865 break;
866 default:
867 return nullptr;
868 }
869 break;
870 case SkEncodedInfo::kBGR_Color:
871 switch (dstInfo.colorType()) {
872 case kBGRA_8888_SkColorType:
873 proc = &swizzle_rgb_to_rgba;
874 fastProc = &fast_swizzle_rgb_to_rgba;
875 break;
876 case kRGBA_8888_SkColorType:
877 proc = &swizzle_rgb_to_bgra;
878 fastProc = &fast_swizzle_rgb_to_bgra;
879 break;
880 case kRGB_565_SkColorType:
881 proc = &swizzle_bgr_to_565;
882 break;
883 default:
884 return nullptr;
885 }
886 break;
887 case SkEncodedInfo::kBGRX_Color:
888 switch (dstInfo.colorType()) {
889 case kBGRA_8888_SkColorType:
890 proc = &swizzle_rgb_to_rgba;
891 break;
892 case kRGBA_8888_SkColorType:
893 proc = &swizzle_rgb_to_bgra;
894 break;
895 case kRGB_565_SkColorType:
896 proc = &swizzle_bgr_to_565;
897 break;
898 default:
899 return nullptr;
900 }
901 break;
902 case SkEncodedInfo::kBGRA_Color:
903 switch (dstInfo.colorType()) {
904 case kBGRA_8888_SkColorType:
905 if (premultiply) {
906 if (SkCodec::kYes_ZeroInitialized == zeroInit) {
907 proc = &SkipLeading8888ZerosThen<swizzle_rgba_to_rgba_premul>;
908 fastProc = &SkipLeading8888ZerosThen
909 <fast_swizzle_rgba_to_rgba_premul>;
910 } else {
911 proc = &swizzle_rgba_to_rgba_premul;
912 fastProc = &fast_swizzle_rgba_to_rgba_premul;
913 }
msarett34e0ec42016-04-22 16:27:24 -0700914 } else {
msarett68758ae2016-04-25 11:41:15 -0700915 if (SkCodec::kYes_ZeroInitialized == zeroInit) {
916 proc = &SkipLeading8888ZerosThen<sample4>;
917 fastProc = &SkipLeading8888ZerosThen<copy>;
918 } else {
919 proc = &sample4;
920 fastProc = &copy;
921 }
msaretta45a6682016-04-22 13:18:37 -0700922 }
msarett68758ae2016-04-25 11:41:15 -0700923 break;
924 case kRGBA_8888_SkColorType:
925 if (premultiply) {
926 if (SkCodec::kYes_ZeroInitialized == zeroInit) {
927 proc = &SkipLeading8888ZerosThen<swizzle_rgba_to_bgra_premul>;
928 fastProc = &SkipLeading8888ZerosThen
929 <fast_swizzle_rgba_to_bgra_premul>;
930 } else {
931 proc = &swizzle_rgba_to_bgra_premul;
932 fastProc = &fast_swizzle_rgba_to_bgra_premul;
933 }
msaretta45a6682016-04-22 13:18:37 -0700934 } else {
msarett68758ae2016-04-25 11:41:15 -0700935 if (SkCodec::kYes_ZeroInitialized == zeroInit) {
936 proc = &SkipLeading8888ZerosThen<swizzle_rgba_to_bgra_unpremul>;
937 fastProc = &SkipLeading8888ZerosThen
938 <fast_swizzle_rgba_to_bgra_unpremul>;
939 } else {
940 proc = &swizzle_rgba_to_bgra_unpremul;
941 fastProc = &fast_swizzle_rgba_to_bgra_unpremul;
942 }
msaretta45a6682016-04-22 13:18:37 -0700943 }
msarett68758ae2016-04-25 11:41:15 -0700944 break;
945 default:
946 return nullptr;
947 }
948 break;
949 case SkEncodedInfo::kInvertedCMYK_Color:
950 switch (dstInfo.colorType()) {
951 case kRGBA_8888_SkColorType:
952 proc = &swizzle_cmyk_to_rgba;
953 fastProc = &fast_swizzle_cmyk_to_rgba;
954 break;
955 case kBGRA_8888_SkColorType:
956 proc = &swizzle_cmyk_to_bgra;
957 fastProc = &fast_swizzle_cmyk_to_bgra;
958 break;
959 case kRGB_565_SkColorType:
960 proc = &swizzle_cmyk_to_565;
961 break;
962 default:
963 return nullptr;
964 }
965 break;
966 default:
967 return nullptr;
968 }
scroggof24f2242015-03-03 08:59:20 -0800969 }
msarett74114382015-03-16 11:55:18 -0700970
msaretta45a6682016-04-22 13:18:37 -0700971 int srcBPP;
msarett68758ae2016-04-25 11:41:15 -0700972 const int dstBPP = SkColorTypeBytesPerPixel(dstInfo.colorType());
973 if (preSwizzled) {
msaretta45a6682016-04-22 13:18:37 -0700974 srcBPP = dstBPP;
975 } else {
976 // Store bpp in bytes if it is an even multiple, otherwise use bits
977 uint8_t bitsPerPixel = encodedInfo.bitsPerPixel();
978 srcBPP = SkIsAlign8(bitsPerPixel) ? bitsPerPixel / 8 : bitsPerPixel;
979 }
mtklein3d00db32016-01-11 06:16:26 -0800980
msarettfdb47572015-10-13 12:50:14 -0700981 int srcOffset = 0;
982 int srcWidth = dstInfo.width();
msarett5af4e0b2015-11-17 11:18:03 -0800983 int dstOffset = 0;
984 int dstWidth = srcWidth;
msarettfdb47572015-10-13 12:50:14 -0700985 if (options.fSubset) {
msarett5af4e0b2015-11-17 11:18:03 -0800986 // We do not currently support subset decodes for image types that may have
987 // frames (gif).
988 SkASSERT(!frame);
msarettfdb47572015-10-13 12:50:14 -0700989 srcOffset = options.fSubset->left();
990 srcWidth = options.fSubset->width();
msarett5af4e0b2015-11-17 11:18:03 -0800991 dstWidth = srcWidth;
992 } else if (frame) {
993 dstOffset = frame->left();
994 srcWidth = frame->width();
msarettfdb47572015-10-13 12:50:14 -0700995 }
emmaleer8f4ba762015-08-14 07:44:46 -0700996
msaretta51e7782016-01-12 06:51:11 -0800997 return new SkSwizzler(fastProc, proc, ctable, srcOffset, srcWidth, dstOffset, dstWidth,
998 srcBPP, dstBPP);
scroggof24f2242015-03-03 08:59:20 -0800999}
1000
msaretta51e7782016-01-12 06:51:11 -08001001SkSwizzler::SkSwizzler(RowProc fastProc, RowProc proc, const SkPMColor* ctable, int srcOffset,
1002 int srcWidth, int dstOffset, int dstWidth, int srcBPP, int dstBPP)
1003 : fFastProc(fastProc)
msarett19032f72016-01-21 09:59:38 -08001004 , fSlowProc(proc)
1005 , fActualProc(fFastProc ? fFastProc : fSlowProc)
scroggof24f2242015-03-03 08:59:20 -08001006 , fColorTable(ctable)
msarettfdb47572015-10-13 12:50:14 -07001007 , fSrcOffset(srcOffset)
msarett5af4e0b2015-11-17 11:18:03 -08001008 , fDstOffset(dstOffset)
1009 , fSrcOffsetUnits(srcOffset * srcBPP)
1010 , fDstOffsetBytes(dstOffset * dstBPP)
1011 , fSrcWidth(srcWidth)
1012 , fDstWidth(dstWidth)
1013 , fSwizzleWidth(srcWidth)
1014 , fAllocatedWidth(dstWidth)
scroggoe7fc14b2015-10-02 13:14:46 -07001015 , fSampleX(1)
msarett5af4e0b2015-11-17 11:18:03 -08001016 , fSrcBPP(srcBPP)
1017 , fDstBPP(dstBPP)
scroggoe7fc14b2015-10-02 13:14:46 -07001018{}
1019
1020int SkSwizzler::onSetSampleX(int sampleX) {
msarett9972c422016-02-10 08:39:37 -08001021 SkASSERT(sampleX > 0);
1022
scroggoe7fc14b2015-10-02 13:14:46 -07001023 fSampleX = sampleX;
msarett5af4e0b2015-11-17 11:18:03 -08001024 fSrcOffsetUnits = (get_start_coord(sampleX) + fSrcOffset) * fSrcBPP;
1025 fDstOffsetBytes = (fDstOffset / sampleX) * fDstBPP;
1026 fSwizzleWidth = get_scaled_dimension(fSrcWidth, sampleX);
1027 fAllocatedWidth = get_scaled_dimension(fDstWidth, sampleX);
scroggoe7fc14b2015-10-02 13:14:46 -07001028
msarett9972c422016-02-10 08:39:37 -08001029 // The optimized swizzler functions do not support sampling. Sampled swizzles
1030 // are already fast because they skip pixels. We haven't seen a situation
1031 // where speeding up sampling has a significant impact on total decode time.
msarett19032f72016-01-21 09:59:38 -08001032 if (1 == fSampleX && fFastProc) {
1033 fActualProc = fFastProc;
1034 } else {
1035 fActualProc = fSlowProc;
1036 }
msaretta51e7782016-01-12 06:51:11 -08001037
msarett5af4e0b2015-11-17 11:18:03 -08001038 return fAllocatedWidth;
emmaleer8f4ba762015-08-14 07:44:46 -07001039}
scroggof24f2242015-03-03 08:59:20 -08001040
msaretta4970dc2016-01-11 07:23:23 -08001041void SkSwizzler::swizzle(void* dst, const uint8_t* SK_RESTRICT src) {
halcanary96fcdcc2015-08-27 07:41:13 -07001042 SkASSERT(nullptr != dst && nullptr != src);
msarett19032f72016-01-21 09:59:38 -08001043 fActualProc(SkTAddOffset<void>(dst, fDstOffsetBytes), src, fSwizzleWidth, fSrcBPP,
msarett5af4e0b2015-11-17 11:18:03 -08001044 fSampleX * fSrcBPP, fSrcOffsetUnits, fColorTable);
scroggof24f2242015-03-03 08:59:20 -08001045}