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 "include/private/SkColorData.h"
9#include "src/codec/SkCodecPriv.h"
10#include "src/codec/SkMaskSwizzler.h"
11
12static void swizzle_mask16_to_rgba_opaque(
13 void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks,
14 uint32_t startX, uint32_t sampleX) {
15
16 // Use the masks to decode to the destination
17 uint16_t* srcPtr = ((uint16_t*) srcRow) + startX;
18 SkPMColor* dstPtr = (SkPMColor*) dstRow;
19 for (int i = 0; i < width; i++) {
20 uint16_t p = srcPtr[0];
21 uint8_t red = masks->getRed(p);
22 uint8_t green = masks->getGreen(p);
23 uint8_t blue = masks->getBlue(p);
24 dstPtr[i] = SkPackARGB_as_RGBA(0xFF, red, green, blue);
25 srcPtr += sampleX;
26 }
27}
28
29static void swizzle_mask16_to_bgra_opaque(
30 void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks,
31 uint32_t startX, uint32_t sampleX) {
32
33 // Use the masks to decode to the destination
34 uint16_t* srcPtr = ((uint16_t*) srcRow) + startX;
35 SkPMColor* dstPtr = (SkPMColor*) dstRow;
36 for (int i = 0; i < width; i++) {
37 uint16_t p = srcPtr[0];
38 uint8_t red = masks->getRed(p);
39 uint8_t green = masks->getGreen(p);
40 uint8_t blue = masks->getBlue(p);
41 dstPtr[i] = SkPackARGB_as_BGRA(0xFF, red, green, blue);
42 srcPtr += sampleX;
43 }
44}
45
46static void swizzle_mask16_to_rgba_unpremul(
47 void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks,
48 uint32_t startX, uint32_t sampleX) {
49
50 // Use the masks to decode to the destination
51 uint16_t* srcPtr = ((uint16_t*) srcRow) + startX;
52 SkPMColor* dstPtr = (SkPMColor*) dstRow;
53 for (int i = 0; i < width; i++) {
54 uint16_t p = srcPtr[0];
55 uint8_t red = masks->getRed(p);
56 uint8_t green = masks->getGreen(p);
57 uint8_t blue = masks->getBlue(p);
58 uint8_t alpha = masks->getAlpha(p);
59 dstPtr[i] = SkPackARGB_as_RGBA(alpha, red, green, blue);
60 srcPtr += sampleX;
61 }
62}
63
64static void swizzle_mask16_to_bgra_unpremul(
65 void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks,
66 uint32_t startX, uint32_t sampleX) {
67
68 // Use the masks to decode to the destination
69 uint16_t* srcPtr = ((uint16_t*) srcRow) + startX;
70 SkPMColor* dstPtr = (SkPMColor*) dstRow;
71 for (int i = 0; i < width; i++) {
72 uint16_t p = srcPtr[0];
73 uint8_t red = masks->getRed(p);
74 uint8_t green = masks->getGreen(p);
75 uint8_t blue = masks->getBlue(p);
76 uint8_t alpha = masks->getAlpha(p);
77 dstPtr[i] = SkPackARGB_as_BGRA(alpha, red, green, blue);
78 srcPtr += sampleX;
79 }
80}
81
82static void swizzle_mask16_to_rgba_premul(
83 void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks,
84 uint32_t startX, uint32_t sampleX) {
85
86 // Use the masks to decode to the destination
87 uint16_t* srcPtr = ((uint16_t*) srcRow) + startX;
88 SkPMColor* dstPtr = (SkPMColor*) dstRow;
89 for (int i = 0; i < width; i++) {
90 uint16_t p = srcPtr[0];
91 uint8_t red = masks->getRed(p);
92 uint8_t green = masks->getGreen(p);
93 uint8_t blue = masks->getBlue(p);
94 uint8_t alpha = masks->getAlpha(p);
95 dstPtr[i] = premultiply_argb_as_rgba(alpha, red, green, blue);
96 srcPtr += sampleX;
97 }
98}
99
100static void swizzle_mask16_to_bgra_premul(
101 void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks,
102 uint32_t startX, uint32_t sampleX) {
103
104 // Use the masks to decode to the destination
105 uint16_t* srcPtr = ((uint16_t*) srcRow) + startX;
106 SkPMColor* dstPtr = (SkPMColor*) dstRow;
107 for (int i = 0; i < width; i++) {
108 uint16_t p = srcPtr[0];
109 uint8_t red = masks->getRed(p);
110 uint8_t green = masks->getGreen(p);
111 uint8_t blue = masks->getBlue(p);
112 uint8_t alpha = masks->getAlpha(p);
113 dstPtr[i] = premultiply_argb_as_bgra(alpha, red, green, blue);
114 srcPtr += sampleX;
115 }
116}
117
118// TODO (msarett): We have promoted a two byte per pixel image to 8888, only to
119// convert it back to 565. Instead, we should swizzle to 565 directly.
120static void swizzle_mask16_to_565(
121 void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks,
122 uint32_t startX, uint32_t sampleX) {
123
124 // Use the masks to decode to the destination
125 uint16_t* srcPtr = ((uint16_t*) srcRow) + startX;
126 uint16_t* dstPtr = (uint16_t*) dstRow;
127 for (int i = 0; i < width; i++) {
128 uint16_t p = srcPtr[0];
129 uint8_t red = masks->getRed(p);
130 uint8_t green = masks->getGreen(p);
131 uint8_t blue = masks->getBlue(p);
132 dstPtr[i] = SkPack888ToRGB16(red, green, blue);
133 srcPtr += sampleX;
134 }
135}
136
137static void swizzle_mask24_to_rgba_opaque(
138 void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks,
139 uint32_t startX, uint32_t sampleX) {
140
141 // Use the masks to decode to the destination
142 srcRow += 3 * startX;
143 SkPMColor* dstPtr = (SkPMColor*) dstRow;
144 for (int i = 0; i < width; i++) {
145 uint32_t p = srcRow[0] | (srcRow[1] << 8) | srcRow[2] << 16;
146 uint8_t red = masks->getRed(p);
147 uint8_t green = masks->getGreen(p);
148 uint8_t blue = masks->getBlue(p);
149 dstPtr[i] = SkPackARGB_as_RGBA(0xFF, red, green, blue);
150 srcRow += 3 * sampleX;
151 }
152}
153
154static void swizzle_mask24_to_bgra_opaque(
155 void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks,
156 uint32_t startX, uint32_t sampleX) {
157
158 // Use the masks to decode to the destination
159 srcRow += 3 * startX;
160 SkPMColor* dstPtr = (SkPMColor*) dstRow;
161 for (int i = 0; i < width; i++) {
162 uint32_t p = srcRow[0] | (srcRow[1] << 8) | srcRow[2] << 16;
163 uint8_t red = masks->getRed(p);
164 uint8_t green = masks->getGreen(p);
165 uint8_t blue = masks->getBlue(p);
166 dstPtr[i] = SkPackARGB_as_BGRA(0xFF, red, green, blue);
167 srcRow += 3 * sampleX;
168 }
169}
170
171static void swizzle_mask24_to_rgba_unpremul(
172 void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks,
173 uint32_t startX, uint32_t sampleX) {
174
175 // Use the masks to decode to the destination
176 srcRow += 3 * startX;
177 SkPMColor* dstPtr = (SkPMColor*) dstRow;
178 for (int i = 0; i < width; i++) {
179 uint32_t p = srcRow[0] | (srcRow[1] << 8) | srcRow[2] << 16;
180 uint8_t red = masks->getRed(p);
181 uint8_t green = masks->getGreen(p);
182 uint8_t blue = masks->getBlue(p);
183 uint8_t alpha = masks->getAlpha(p);
184 dstPtr[i] = SkPackARGB_as_RGBA(alpha, red, green, blue);
185 srcRow += 3 * sampleX;
186 }
187}
188
189static void swizzle_mask24_to_bgra_unpremul(
190 void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks,
191 uint32_t startX, uint32_t sampleX) {
192
193 // Use the masks to decode to the destination
194 srcRow += 3 * startX;
195 SkPMColor* dstPtr = (SkPMColor*) dstRow;
196 for (int i = 0; i < width; i++) {
197 uint32_t p = srcRow[0] | (srcRow[1] << 8) | srcRow[2] << 16;
198 uint8_t red = masks->getRed(p);
199 uint8_t green = masks->getGreen(p);
200 uint8_t blue = masks->getBlue(p);
201 uint8_t alpha = masks->getAlpha(p);
202 dstPtr[i] = SkPackARGB_as_BGRA(alpha, red, green, blue);
203 srcRow += 3 * sampleX;
204 }
205}
206
207static void swizzle_mask24_to_rgba_premul(
208 void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks,
209 uint32_t startX, uint32_t sampleX) {
210
211 // Use the masks to decode to the destination
212 srcRow += 3 * startX;
213 SkPMColor* dstPtr = (SkPMColor*) dstRow;
214 for (int i = 0; i < width; i++) {
215 uint32_t p = srcRow[0] | (srcRow[1] << 8) | srcRow[2] << 16;
216 uint8_t red = masks->getRed(p);
217 uint8_t green = masks->getGreen(p);
218 uint8_t blue = masks->getBlue(p);
219 uint8_t alpha = masks->getAlpha(p);
220 dstPtr[i] = premultiply_argb_as_rgba(alpha, red, green, blue);
221 srcRow += 3 * sampleX;
222 }
223}
224
225static void swizzle_mask24_to_bgra_premul(
226 void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks,
227 uint32_t startX, uint32_t sampleX) {
228
229 // Use the masks to decode to the destination
230 srcRow += 3 * startX;
231 SkPMColor* dstPtr = (SkPMColor*) dstRow;
232 for (int i = 0; i < width; i++) {
233 uint32_t p = srcRow[0] | (srcRow[1] << 8) | srcRow[2] << 16;
234 uint8_t red = masks->getRed(p);
235 uint8_t green = masks->getGreen(p);
236 uint8_t blue = masks->getBlue(p);
237 uint8_t alpha = masks->getAlpha(p);
238 dstPtr[i] = premultiply_argb_as_bgra(alpha, red, green, blue);
239 srcRow += 3 * sampleX;
240 }
241}
242
243static void swizzle_mask24_to_565(
244 void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks,
245 uint32_t startX, uint32_t sampleX) {
246
247 // Use the masks to decode to the destination
248 srcRow += 3 * startX;
249 uint16_t* dstPtr = (uint16_t*) dstRow;
250 for (int i = 0; i < width; i++) {
251 uint32_t p = srcRow[0] | (srcRow[1] << 8) | srcRow[2] << 16;
252 uint8_t red = masks->getRed(p);
253 uint8_t green = masks->getGreen(p);
254 uint8_t blue = masks->getBlue(p);
255 dstPtr[i] = SkPack888ToRGB16(red, green, blue);
256 srcRow += 3 * sampleX;
257 }
258}
259
260static void swizzle_mask32_to_rgba_opaque(
261 void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks,
262 uint32_t startX, uint32_t sampleX) {
263
264 // Use the masks to decode to the destination
265 uint32_t* srcPtr = ((uint32_t*) srcRow) + startX;
266 SkPMColor* dstPtr = (SkPMColor*) dstRow;
267 for (int i = 0; i < width; i++) {
268 uint32_t p = srcPtr[0];
269 uint8_t red = masks->getRed(p);
270 uint8_t green = masks->getGreen(p);
271 uint8_t blue = masks->getBlue(p);
272 dstPtr[i] = SkPackARGB_as_RGBA(0xFF, red, green, blue);
273 srcPtr += sampleX;
274 }
275}
276
277static void swizzle_mask32_to_bgra_opaque(
278 void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks,
279 uint32_t startX, uint32_t sampleX) {
280
281 // Use the masks to decode to the destination
282 uint32_t* srcPtr = ((uint32_t*) srcRow) + startX;
283 SkPMColor* dstPtr = (SkPMColor*) dstRow;
284 for (int i = 0; i < width; i++) {
285 uint32_t p = srcPtr[0];
286 uint8_t red = masks->getRed(p);
287 uint8_t green = masks->getGreen(p);
288 uint8_t blue = masks->getBlue(p);
289 dstPtr[i] = SkPackARGB_as_BGRA(0xFF, red, green, blue);
290 srcPtr += sampleX;
291 }
292}
293
294static void swizzle_mask32_to_rgba_unpremul(
295 void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks,
296 uint32_t startX, uint32_t sampleX) {
297
298 // Use the masks to decode to the destination
299 uint32_t* srcPtr = ((uint32_t*) srcRow) + startX;
300 SkPMColor* dstPtr = (SkPMColor*) dstRow;
301 for (int i = 0; i < width; i++) {
302 uint32_t p = srcPtr[0];
303 uint8_t red = masks->getRed(p);
304 uint8_t green = masks->getGreen(p);
305 uint8_t blue = masks->getBlue(p);
306 uint8_t alpha = masks->getAlpha(p);
307 dstPtr[i] = SkPackARGB_as_RGBA(alpha, red, green, blue);
308 srcPtr += sampleX;
309 }
310}
311
312static void swizzle_mask32_to_bgra_unpremul(
313 void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks,
314 uint32_t startX, uint32_t sampleX) {
315
316 // Use the masks to decode to the destination
317 uint32_t* srcPtr = ((uint32_t*) srcRow) + startX;
318 SkPMColor* dstPtr = (SkPMColor*) dstRow;
319 for (int i = 0; i < width; i++) {
320 uint32_t p = srcPtr[0];
321 uint8_t red = masks->getRed(p);
322 uint8_t green = masks->getGreen(p);
323 uint8_t blue = masks->getBlue(p);
324 uint8_t alpha = masks->getAlpha(p);
325 dstPtr[i] = SkPackARGB_as_BGRA(alpha, red, green, blue);
326 srcPtr += sampleX;
327 }
328}
329
330static void swizzle_mask32_to_rgba_premul(
331 void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks,
332 uint32_t startX, uint32_t sampleX) {
333
334 // Use the masks to decode to the destination
335 uint32_t* srcPtr = ((uint32_t*) srcRow) + startX;
336 SkPMColor* dstPtr = (SkPMColor*) dstRow;
337 for (int i = 0; i < width; i++) {
338 uint32_t p = srcPtr[0];
339 uint8_t red = masks->getRed(p);
340 uint8_t green = masks->getGreen(p);
341 uint8_t blue = masks->getBlue(p);
342 uint8_t alpha = masks->getAlpha(p);
343 dstPtr[i] = premultiply_argb_as_rgba(alpha, red, green, blue);
344 srcPtr += sampleX;
345 }
346}
347
348static void swizzle_mask32_to_bgra_premul(
349 void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks,
350 uint32_t startX, uint32_t sampleX) {
351
352 // Use the masks to decode to the destination
353 uint32_t* srcPtr = ((uint32_t*) srcRow) + startX;
354 SkPMColor* dstPtr = (SkPMColor*) dstRow;
355 for (int i = 0; i < width; i++) {
356 uint32_t p = srcPtr[0];
357 uint8_t red = masks->getRed(p);
358 uint8_t green = masks->getGreen(p);
359 uint8_t blue = masks->getBlue(p);
360 uint8_t alpha = masks->getAlpha(p);
361 dstPtr[i] = premultiply_argb_as_bgra(alpha, red, green, blue);
362 srcPtr += sampleX;
363 }
364}
365
366static void swizzle_mask32_to_565(
367 void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks,
368 uint32_t startX, uint32_t sampleX) {
369 // Use the masks to decode to the destination
370 uint32_t* srcPtr = ((uint32_t*) srcRow) + startX;
371 uint16_t* dstPtr = (uint16_t*) dstRow;
372 for (int i = 0; i < width; i++) {
373 uint32_t p = srcPtr[0];
374 uint8_t red = masks->getRed(p);
375 uint8_t green = masks->getGreen(p);
376 uint8_t blue = masks->getBlue(p);
377 dstPtr[i] = SkPack888ToRGB16(red, green, blue);
378 srcPtr += sampleX;
379 }
380}
381
382/*
383 *
384 * Create a new mask swizzler
385 *
386 */
387SkMaskSwizzler* SkMaskSwizzler::CreateMaskSwizzler(const SkImageInfo& dstInfo,
388 bool srcIsOpaque, SkMasks* masks, uint32_t bitsPerPixel,
389 const SkCodec::Options& options) {
390
391 // Choose the appropriate row procedure
392 RowProc proc = nullptr;
393 switch (bitsPerPixel) {
394 case 16:
395 switch (dstInfo.colorType()) {
396 case kRGBA_8888_SkColorType:
397 if (srcIsOpaque) {
398 proc = &swizzle_mask16_to_rgba_opaque;
399 } else {
400 switch (dstInfo.alphaType()) {
401 case kUnpremul_SkAlphaType:
402 proc = &swizzle_mask16_to_rgba_unpremul;
403 break;
404 case kPremul_SkAlphaType:
405 proc = &swizzle_mask16_to_rgba_premul;
406 break;
407 default:
408 break;
409 }
410 }
411 break;
412 case kBGRA_8888_SkColorType:
413 if (srcIsOpaque) {
414 proc = &swizzle_mask16_to_bgra_opaque;
415 } else {
416 switch (dstInfo.alphaType()) {
417 case kUnpremul_SkAlphaType:
418 proc = &swizzle_mask16_to_bgra_unpremul;
419 break;
420 case kPremul_SkAlphaType:
421 proc = &swizzle_mask16_to_bgra_premul;
422 break;
423 default:
424 break;
425 }
426 }
427 break;
428 case kRGB_565_SkColorType:
429 proc = &swizzle_mask16_to_565;
430 break;
431 default:
432 break;
433 }
434 break;
435 case 24:
436 switch (dstInfo.colorType()) {
437 case kRGBA_8888_SkColorType:
438 if (srcIsOpaque) {
439 proc = &swizzle_mask24_to_rgba_opaque;
440 } else {
441 switch (dstInfo.alphaType()) {
442 case kUnpremul_SkAlphaType:
443 proc = &swizzle_mask24_to_rgba_unpremul;
444 break;
445 case kPremul_SkAlphaType:
446 proc = &swizzle_mask24_to_rgba_premul;
447 break;
448 default:
449 break;
450 }
451 }
452 break;
453 case kBGRA_8888_SkColorType:
454 if (srcIsOpaque) {
455 proc = &swizzle_mask24_to_bgra_opaque;
456 } else {
457 switch (dstInfo.alphaType()) {
458 case kUnpremul_SkAlphaType:
459 proc = &swizzle_mask24_to_bgra_unpremul;
460 break;
461 case kPremul_SkAlphaType:
462 proc = &swizzle_mask24_to_bgra_premul;
463 break;
464 default:
465 break;
466 }
467 }
468 break;
469 case kRGB_565_SkColorType:
470 proc = &swizzle_mask24_to_565;
471 break;
472 default:
473 break;
474 }
475 break;
476 case 32:
477 switch (dstInfo.colorType()) {
478 case kRGBA_8888_SkColorType:
479 if (srcIsOpaque) {
480 proc = &swizzle_mask32_to_rgba_opaque;
481 } else {
482 switch (dstInfo.alphaType()) {
483 case kUnpremul_SkAlphaType:
484 proc = &swizzle_mask32_to_rgba_unpremul;
485 break;
486 case kPremul_SkAlphaType:
487 proc = &swizzle_mask32_to_rgba_premul;
488 break;
489 default:
490 break;
491 }
492 }
493 break;
494 case kBGRA_8888_SkColorType:
495 if (srcIsOpaque) {
496 proc = &swizzle_mask32_to_bgra_opaque;
497 } else {
498 switch (dstInfo.alphaType()) {
499 case kUnpremul_SkAlphaType:
500 proc = &swizzle_mask32_to_bgra_unpremul;
501 break;
502 case kPremul_SkAlphaType:
503 proc = &swizzle_mask32_to_bgra_premul;
504 break;
505 default:
506 break;
507 }
508 }
509 break;
510 case kRGB_565_SkColorType:
511 proc = &swizzle_mask32_to_565;
512 break;
513 default:
514 break;
515 }
516 break;
517 default:
518 SkASSERT(false);
519 return nullptr;
520 }
521
522 int srcOffset = 0;
523 int srcWidth = dstInfo.width();
524 if (options.fSubset) {
525 srcOffset = options.fSubset->left();
526 srcWidth = options.fSubset->width();
527 }
528
529 return new SkMaskSwizzler(masks, proc, srcOffset, srcWidth);
530}
531
532/*
533 *
534 * Constructor for mask swizzler
535 *
536 */
537SkMaskSwizzler::SkMaskSwizzler(SkMasks* masks, RowProc proc, int srcOffset, int subsetWidth)
538 : fMasks(masks)
539 , fRowProc(proc)
540 , fSubsetWidth(subsetWidth)
541 , fDstWidth(subsetWidth)
542 , fSampleX(1)
543 , fSrcOffset(srcOffset)
544 , fX0(srcOffset)
545{}
546
547int SkMaskSwizzler::onSetSampleX(int sampleX) {
548 // FIXME: Share this function with SkSwizzler?
549 SkASSERT(sampleX > 0); // Surely there is an upper limit? Should there be
550 // way to report failure?
551 fSampleX = sampleX;
552 fX0 = get_start_coord(sampleX) + fSrcOffset;
553 fDstWidth = get_scaled_dimension(fSubsetWidth, sampleX);
554
555 // check that fX0 is valid
556 SkASSERT(fX0 >= 0);
557 return fDstWidth;
558}
559
560/*
561 *
562 * Swizzle the specified row
563 *
564 */
565void SkMaskSwizzler::swizzle(void* dst, const uint8_t* SK_RESTRICT src) {
566 SkASSERT(nullptr != dst && nullptr != src);
567 fRowProc(dst, src, fDstWidth, fMasks, fX0, fSampleX);
568}
569