SkSwizzler.cpp revision 93e613d6bdea05d96e232ed261d7bf886c91bb8e
1/* 2 * Copyright 2015 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8#include "SkCodecPriv.h" 9#include "SkColorPriv.h" 10#include "SkOpts.h" 11#include "SkSwizzler.h" 12#include "SkTemplates.h" 13 14static void copy(void* dst, const uint8_t* src, int width, int bpp, int deltaSrc, int offset, 15 const SkPMColor ctable[]) { 16 // This function must not be called if we are sampling. If we are not 17 // sampling, deltaSrc should equal bpp. 18 SkASSERT(deltaSrc == bpp); 19 20 memcpy(dst, src + offset, width * bpp); 21} 22 23static void sample1(void* dst, const uint8_t* src, int width, int bpp, int deltaSrc, int offset, 24 const SkPMColor ctable[]) { 25 src += offset; 26 uint8_t* dst8 = (uint8_t*) dst; 27 for (int x = 0; x < width; x++) { 28 dst8[x] = *src; 29 src += deltaSrc; 30 } 31} 32 33static void sample2(void* dst, const uint8_t* src, int width, int bpp, int deltaSrc, int offset, 34 const SkPMColor ctable[]) { 35 src += offset; 36 uint16_t* dst16 = (uint16_t*) dst; 37 for (int x = 0; x < width; x++) { 38 dst16[x] = *((const uint16_t*) src); 39 src += deltaSrc; 40 } 41} 42 43static void sample4(void* dst, const uint8_t* src, int width, int bpp, int deltaSrc, int offset, 44 const SkPMColor ctable[]) { 45 src += offset; 46 uint32_t* dst32 = (uint32_t*) dst; 47 for (int x = 0; x < width; x++) { 48 dst32[x] = *((const uint32_t*) src); 49 src += deltaSrc; 50 } 51} 52 53// kBit 54// These routines exclusively choose between white and black 55 56#define GRAYSCALE_BLACK 0 57#define GRAYSCALE_WHITE 0xFF 58 59 60// same as swizzle_bit_to_index and swizzle_bit_to_n32 except for value assigned to dst[x] 61static void swizzle_bit_to_grayscale( 62 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth, 63 int bpp, int deltaSrc, int offset, const SkPMColor* /*ctable*/) { 64 65 uint8_t* SK_RESTRICT dst = (uint8_t*) dstRow; 66 67 // increment src by byte offset and bitIndex by bit offset 68 src += offset / 8; 69 int bitIndex = offset % 8; 70 uint8_t currByte = *src; 71 72 dst[0] = ((currByte >> (7-bitIndex)) & 1) ? GRAYSCALE_WHITE : GRAYSCALE_BLACK; 73 74 for (int x = 1; x < dstWidth; x++) { 75 int bitOffset = bitIndex + deltaSrc; 76 bitIndex = bitOffset % 8; 77 currByte = *(src += bitOffset / 8); 78 dst[x] = ((currByte >> (7-bitIndex)) & 1) ? GRAYSCALE_WHITE : GRAYSCALE_BLACK; 79 } 80} 81 82#undef GRAYSCALE_BLACK 83#undef GRAYSCALE_WHITE 84 85// same as swizzle_bit_to_grayscale and swizzle_bit_to_n32 except for value assigned to dst[x] 86static void swizzle_bit_to_index( 87 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth, 88 int bpp, int deltaSrc, int offset, const SkPMColor* /*ctable*/) { 89 uint8_t* SK_RESTRICT dst = (uint8_t*) dstRow; 90 91 // increment src by byte offset and bitIndex by bit offset 92 src += offset / 8; 93 int bitIndex = offset % 8; 94 uint8_t currByte = *src; 95 96 dst[0] = ((currByte >> (7-bitIndex)) & 1); 97 98 for (int x = 1; x < dstWidth; x++) { 99 int bitOffset = bitIndex + deltaSrc; 100 bitIndex = bitOffset % 8; 101 currByte = *(src += bitOffset / 8); 102 dst[x] = ((currByte >> (7-bitIndex)) & 1); 103 } 104} 105 106// same as swizzle_bit_to_grayscale and swizzle_bit_to_index except for value assigned to dst[x] 107static void swizzle_bit_to_n32( 108 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth, 109 int bpp, int deltaSrc, int offset, const SkPMColor* /*ctable*/) { 110 SkPMColor* SK_RESTRICT dst = (SkPMColor*) dstRow; 111 112 // increment src by byte offset and bitIndex by bit offset 113 src += offset / 8; 114 int bitIndex = offset % 8; 115 uint8_t currByte = *src; 116 117 dst[0] = ((currByte >> (7 - bitIndex)) & 1) ? SK_ColorWHITE : SK_ColorBLACK; 118 119 for (int x = 1; x < dstWidth; x++) { 120 int bitOffset = bitIndex + deltaSrc; 121 bitIndex = bitOffset % 8; 122 currByte = *(src += bitOffset / 8); 123 dst[x] = ((currByte >> (7 - bitIndex)) & 1) ? SK_ColorWHITE : SK_ColorBLACK; 124 } 125} 126 127#define RGB565_BLACK 0 128#define RGB565_WHITE 0xFFFF 129 130static void swizzle_bit_to_565( 131 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth, 132 int bpp, int deltaSrc, int offset, const SkPMColor* /*ctable*/) { 133 uint16_t* SK_RESTRICT dst = (uint16_t*) dstRow; 134 135 // increment src by byte offset and bitIndex by bit offset 136 src += offset / 8; 137 int bitIndex = offset % 8; 138 uint8_t currByte = *src; 139 140 dst[0] = ((currByte >> (7 - bitIndex)) & 1) ? RGB565_WHITE : RGB565_BLACK; 141 142 for (int x = 1; x < dstWidth; x++) { 143 int bitOffset = bitIndex + deltaSrc; 144 bitIndex = bitOffset % 8; 145 currByte = *(src += bitOffset / 8); 146 dst[x] = ((currByte >> (7 - bitIndex)) & 1) ? RGB565_WHITE : RGB565_BLACK; 147 } 148} 149 150#undef RGB565_BLACK 151#undef RGB565_WHITE 152 153// kIndex1, kIndex2, kIndex4 154 155static void swizzle_small_index_to_index( 156 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth, 157 int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) { 158 159 uint8_t* dst = (uint8_t*) dstRow; 160 src += offset / 8; 161 int bitIndex = offset % 8; 162 uint8_t currByte = *src; 163 const uint8_t mask = (1 << bpp) - 1; 164 uint8_t index = (currByte >> (8 - bpp - bitIndex)) & mask; 165 dst[0] = index; 166 167 for (int x = 1; x < dstWidth; x++) { 168 int bitOffset = bitIndex + deltaSrc; 169 bitIndex = bitOffset % 8; 170 currByte = *(src += bitOffset / 8); 171 index = (currByte >> (8 - bpp - bitIndex)) & mask; 172 dst[x] = index; 173 } 174} 175 176static void swizzle_small_index_to_565( 177 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth, 178 int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) { 179 180 uint16_t* dst = (uint16_t*) dstRow; 181 src += offset / 8; 182 int bitIndex = offset % 8; 183 uint8_t currByte = *src; 184 const uint8_t mask = (1 << bpp) - 1; 185 uint8_t index = (currByte >> (8 - bpp - bitIndex)) & mask; 186 dst[0] = SkPixel32ToPixel16(ctable[index]); 187 188 for (int x = 1; x < dstWidth; x++) { 189 int bitOffset = bitIndex + deltaSrc; 190 bitIndex = bitOffset % 8; 191 currByte = *(src += bitOffset / 8); 192 index = (currByte >> (8 - bpp - bitIndex)) & mask; 193 dst[x] = SkPixel32ToPixel16(ctable[index]); 194 } 195} 196 197static void swizzle_small_index_to_n32( 198 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth, 199 int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) { 200 201 SkPMColor* dst = (SkPMColor*) dstRow; 202 src += offset / 8; 203 int bitIndex = offset % 8; 204 uint8_t currByte = *src; 205 const uint8_t mask = (1 << bpp) - 1; 206 uint8_t index = (currByte >> (8 - bpp - bitIndex)) & mask; 207 dst[0] = ctable[index]; 208 209 for (int x = 1; x < dstWidth; x++) { 210 int bitOffset = bitIndex + deltaSrc; 211 bitIndex = bitOffset % 8; 212 currByte = *(src += bitOffset / 8); 213 index = (currByte >> (8 - bpp - bitIndex)) & mask; 214 dst[x] = ctable[index]; 215 } 216} 217 218// kIndex 219 220static void swizzle_index_to_n32( 221 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth, 222 int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) { 223 224 src += offset; 225 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow; 226 for (int x = 0; x < dstWidth; x++) { 227 SkPMColor c = ctable[*src]; 228 dst[x] = c; 229 src += deltaSrc; 230 } 231} 232 233static void swizzle_index_to_n32_skipZ( 234 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth, 235 int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) { 236 237 src += offset; 238 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow; 239 for (int x = 0; x < dstWidth; x++) { 240 SkPMColor c = ctable[*src]; 241 if (c != 0) { 242 dst[x] = c; 243 } 244 src += deltaSrc; 245 } 246} 247 248static void swizzle_index_to_565( 249 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth, 250 int bytesPerPixel, int deltaSrc, int offset, const SkPMColor ctable[]) { 251 src += offset; 252 uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow; 253 for (int x = 0; x < dstWidth; x++) { 254 dst[x] = SkPixel32ToPixel16(ctable[*src]); 255 src += deltaSrc; 256 } 257} 258 259// kGray 260 261static void swizzle_gray_to_n32( 262 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth, 263 int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) { 264 265 src += offset; 266 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow; 267 for (int x = 0; x < dstWidth; x++) { 268 dst[x] = SkPackARGB32NoCheck(0xFF, *src, *src, *src); 269 src += deltaSrc; 270 } 271} 272 273static void fast_swizzle_gray_to_n32( 274 void* dst, const uint8_t* src, int width, int bpp, int deltaSrc, int offset, 275 const SkPMColor ctable[]) { 276 277 // This function must not be called if we are sampling. If we are not 278 // sampling, deltaSrc should equal bpp. 279 SkASSERT(deltaSrc == bpp); 280 281 // Note that there is no need to distinguish between RGB and BGR. 282 // Each color channel will get the same value. 283 SkOpts::gray_to_RGB1((uint32_t*) dst, src + offset, width); 284} 285 286static void swizzle_gray_to_565( 287 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth, 288 int bytesPerPixel, int deltaSrc, int offset, const SkPMColor ctable[]) { 289 290 src += offset; 291 uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow; 292 for (int x = 0; x < dstWidth; x++) { 293 dst[x] = SkPack888ToRGB16(src[0], src[0], src[0]); 294 src += deltaSrc; 295 } 296} 297 298// kGrayAlpha 299 300static void swizzle_grayalpha_to_n32_unpremul( 301 void* dst, const uint8_t* src, int width, int bpp, int deltaSrc, int offset, 302 const SkPMColor ctable[]) { 303 304 src += offset; 305 SkPMColor* dst32 = (SkPMColor*) dst; 306 for (int x = 0; x < width; x++) { 307 dst32[x] = SkPackARGB32NoCheck(src[1], src[0], src[0], src[0]); 308 src += deltaSrc; 309 } 310} 311 312static void swizzle_grayalpha_to_n32_premul( 313 void* dst, const uint8_t* src, int width, int bpp, int deltaSrc, int offset, 314 const SkPMColor ctable[]) { 315 316 src += offset; 317 SkPMColor* dst32 = (SkPMColor*) dst; 318 for (int x = 0; x < width; x++) { 319 uint8_t pmgray = SkMulDiv255Round(src[1], src[0]); 320 dst32[x] = SkPackARGB32NoCheck(src[1], pmgray, pmgray, pmgray); 321 src += deltaSrc; 322 } 323} 324 325// kBGRX 326 327static void swizzle_bgrx_to_n32( 328 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth, 329 int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) { 330 331 src += offset; 332 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow; 333 for (int x = 0; x < dstWidth; x++) { 334 dst[x] = SkPackARGB32NoCheck(0xFF, src[2], src[1], src[0]); 335 src += deltaSrc; 336 } 337} 338 339static void swizzle_bgrx_to_565( 340 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth, 341 int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) { 342 343 src += offset; 344 uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow; 345 for (int x = 0; x < dstWidth; x++) { 346 dst[x] = SkPack888ToRGB16(src[2], src[1], src[0]); 347 src += deltaSrc; 348 } 349} 350 351// kBGRA 352 353static void swizzle_bgra_to_n32_unpremul( 354 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth, 355 int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) { 356 357 src += offset; 358 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow; 359 for (int x = 0; x < dstWidth; x++) { 360 uint8_t alpha = src[3]; 361 dst[x] = SkPackARGB32NoCheck(alpha, src[2], src[1], src[0]); 362 src += deltaSrc; 363 } 364} 365 366static void fast_swizzle_bgra_to_n32_unpremul( 367 void* dst, const uint8_t* src, int width, int bpp, int deltaSrc, int offset, 368 const SkPMColor ctable[]) { 369 370 // This function must not be called if we are sampling. If we are not 371 // sampling, deltaSrc should equal bpp. 372 SkASSERT(deltaSrc == bpp); 373 374#ifdef SK_PMCOLOR_IS_RGBA 375 SkOpts::RGBA_to_BGRA((uint32_t*) dst, src + offset, width); 376#else 377 memcpy(dst, src + offset, width * bpp); 378#endif 379} 380 381static void swizzle_bgra_to_n32_premul( 382 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth, 383 int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) { 384 385 src += offset; 386 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow; 387 for (int x = 0; x < dstWidth; x++) { 388 uint8_t alpha = src[3]; 389 dst[x] = SkPremultiplyARGBInline(alpha, src[2], src[1], src[0]); 390 src += deltaSrc; 391 } 392} 393 394static void fast_swizzle_bgra_to_n32_premul( 395 void* dst, const uint8_t* src, int width, int bpp, int deltaSrc, int offset, 396 const SkPMColor ctable[]) { 397 398 // This function must not be called if we are sampling. If we are not 399 // sampling, deltaSrc should equal bpp. 400 SkASSERT(deltaSrc == bpp); 401 402#ifdef SK_PMCOLOR_IS_RGBA 403 SkOpts::RGBA_to_bgrA((uint32_t*) dst, src + offset, width); 404#else 405 SkOpts::RGBA_to_rgbA((uint32_t*) dst, src + offset, width); 406#endif 407} 408 409// kRGB 410 411static void swizzle_rgb_to_n32( 412 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth, 413 int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) { 414 415 src += offset; 416 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow; 417 for (int x = 0; x < dstWidth; x++) { 418 dst[x] = SkPackARGB32NoCheck(0xFF, src[0], src[1], src[2]); 419 src += deltaSrc; 420 } 421} 422 423static void fast_swizzle_rgb_to_n32( 424 void* dst, const uint8_t* src, int width, int bpp, int deltaSrc, 425 int offset, const SkPMColor ctable[]) { 426 427 // This function must not be called if we are sampling. If we are not 428 // sampling, deltaSrc should equal bpp. 429 SkASSERT(deltaSrc == bpp); 430 431#ifdef SK_PMCOLOR_IS_RGBA 432 SkOpts::RGB_to_RGB1((uint32_t*) dst, src + offset, width); 433#else 434 SkOpts::RGB_to_BGR1((uint32_t*) dst, src + offset, width); 435#endif 436} 437 438static void swizzle_rgb_to_565( 439 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth, 440 int bytesPerPixel, int deltaSrc, int offset, const SkPMColor ctable[]) { 441 442 src += offset; 443 uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow; 444 for (int x = 0; x < dstWidth; x++) { 445 dst[x] = SkPack888ToRGB16(src[0], src[1], src[2]); 446 src += deltaSrc; 447 } 448} 449 450// kRGBA 451 452static void swizzle_rgba_to_n32_premul( 453 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth, 454 int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) { 455 456 src += offset; 457 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow; 458 for (int x = 0; x < dstWidth; x++) { 459 unsigned alpha = src[3]; 460 dst[x] = SkPremultiplyARGBInline(alpha, src[0], src[1], src[2]); 461 src += deltaSrc; 462 } 463} 464 465static void fast_swizzle_rgba_to_n32_premul( 466 void* dst, const uint8_t* src, int width, int bpp, int deltaSrc, 467 int offset, const SkPMColor ctable[]) { 468 469 // This function must not be called if we are sampling. If we are not 470 // sampling, deltaSrc should equal bpp. 471 SkASSERT(deltaSrc == bpp); 472 473#ifdef SK_PMCOLOR_IS_RGBA 474 SkOpts::RGBA_to_rgbA((uint32_t*) dst, src + offset, width); 475#else 476 SkOpts::RGBA_to_bgrA((uint32_t*) dst, src + offset, width); 477#endif 478} 479 480static void swizzle_rgba_to_n32_unpremul( 481 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth, 482 int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) { 483 484 src += offset; 485 uint32_t* SK_RESTRICT dst = reinterpret_cast<uint32_t*>(dstRow); 486 for (int x = 0; x < dstWidth; x++) { 487 unsigned alpha = src[3]; 488 dst[x] = SkPackARGB32NoCheck(alpha, src[0], src[1], src[2]); 489 src += deltaSrc; 490 } 491} 492 493static void fast_swizzle_rgba_to_n32_unpremul( 494 void* dst, const uint8_t* src, int width, int bpp, int deltaSrc, int offset, 495 const SkPMColor ctable[]) { 496 497 // This function must not be called if we are sampling. If we are not 498 // sampling, deltaSrc should equal bpp. 499 SkASSERT(deltaSrc == bpp); 500 501#ifdef SK_PMCOLOR_IS_RGBA 502 memcpy(dst, src + offset, width * bpp); 503#else 504 SkOpts::RGBA_to_BGRA((uint32_t*) dst, src + offset, width); 505#endif 506} 507 508// kCMYK 509// 510// CMYK is stored as four bytes per pixel. 511// 512// We will implement a crude conversion from CMYK -> RGB using formulas 513// from easyrgb.com. 514// 515// CMYK -> CMY 516// C = C * (1 - K) + K 517// M = M * (1 - K) + K 518// Y = Y * (1 - K) + K 519// 520// libjpeg actually gives us inverted CMYK, so we must subtract the 521// original terms from 1. 522// CMYK -> CMY 523// C = (1 - C) * (1 - (1 - K)) + (1 - K) 524// M = (1 - M) * (1 - (1 - K)) + (1 - K) 525// Y = (1 - Y) * (1 - (1 - K)) + (1 - K) 526// 527// Simplifying the above expression. 528// CMYK -> CMY 529// C = 1 - CK 530// M = 1 - MK 531// Y = 1 - YK 532// 533// CMY -> RGB 534// R = (1 - C) * 255 535// G = (1 - M) * 255 536// B = (1 - Y) * 255 537// 538// Therefore the full conversion is below. This can be verified at 539// www.rapidtables.com (assuming inverted CMYK). 540// CMYK -> RGB 541// R = C * K * 255 542// G = M * K * 255 543// B = Y * K * 255 544// 545// As a final note, we have treated the CMYK values as if they were on 546// a scale from 0-1, when in fact they are 8-bit ints scaling from 0-255. 547// We must divide each CMYK component by 255 to obtain the true conversion 548// we should perform. 549// CMYK -> RGB 550// R = C * K / 255 551// G = M * K / 255 552// B = Y * K / 255 553static void swizzle_cmyk_to_n32( 554 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth, 555 int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) { 556 557 src += offset; 558 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow; 559 for (int x = 0; x < dstWidth; x++) { 560 const uint8_t r = SkMulDiv255Round(src[0], src[3]); 561 const uint8_t g = SkMulDiv255Round(src[1], src[3]); 562 const uint8_t b = SkMulDiv255Round(src[2], src[3]); 563 564 dst[x] = SkPackARGB32NoCheck(0xFF, r, g, b); 565 src += deltaSrc; 566 } 567} 568 569static void swizzle_cmyk_to_565( 570 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth, 571 int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) { 572 573 src += offset; 574 uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow; 575 for (int x = 0; x < dstWidth; x++) { 576 const uint8_t r = SkMulDiv255Round(src[0], src[3]); 577 const uint8_t g = SkMulDiv255Round(src[1], src[3]); 578 const uint8_t b = SkMulDiv255Round(src[2], src[3]); 579 580 dst[x] = SkPack888ToRGB16(r, g, b); 581 src += deltaSrc; 582 } 583} 584 585template <SkSwizzler::RowProc proc> 586void SkSwizzler::SkipLeadingGrayAlphaZerosThen( 587 void* dst, const uint8_t* src, int width, 588 int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) { 589 SkASSERT(!ctable); 590 591 const uint16_t* src16 = (const uint16_t*) (src + offset); 592 uint32_t* dst32 = (uint32_t*) dst; 593 594 // This may miss opportunities to skip when the output is premultiplied, 595 // e.g. for a src pixel 0x00FF which is not zero but becomes zero after premultiplication. 596 while (width > 0 && *src16 == 0x0000) { 597 width--; 598 dst32++; 599 src16 += deltaSrc / 2; 600 } 601 proc(dst32, (const uint8_t*)src16, width, bpp, deltaSrc, 0, ctable); 602} 603 604template <SkSwizzler::RowProc proc> 605void SkSwizzler::SkipLeading8888ZerosThen( 606 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth, 607 int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) { 608 SkASSERT(!ctable); 609 610 auto src32 = (const uint32_t*)(src+offset); 611 auto dst32 = (uint32_t*)dstRow; 612 613 // This may miss opportunities to skip when the output is premultiplied, 614 // e.g. for a src pixel 0x00FFFFFF which is not zero but becomes zero after premultiplication. 615 while (dstWidth > 0 && *src32 == 0x00000000) { 616 dstWidth--; 617 dst32++; 618 src32 += deltaSrc/4; 619 } 620 proc(dst32, (const uint8_t*)src32, dstWidth, bpp, deltaSrc, 0, ctable); 621} 622 623SkSwizzler* SkSwizzler::CreateSwizzler(SkSwizzler::SrcConfig sc, 624 const SkPMColor* ctable, 625 const SkImageInfo& dstInfo, 626 const SkCodec::Options& options, 627 const SkIRect* frame) { 628 if (dstInfo.colorType() == kUnknown_SkColorType || kUnknown == sc) { 629 return nullptr; 630 } 631 if ((kIndex == sc || kIndex4 == sc || kIndex2 == sc || kIndex1 == sc) 632 && nullptr == ctable) { 633 return nullptr; 634 } 635 RowProc fastProc = nullptr; 636 RowProc proc = nullptr; 637 SkCodec::ZeroInitialized zeroInit = options.fZeroInitialized; 638 switch (sc) { 639 case kBit: 640 switch (dstInfo.colorType()) { 641 case kN32_SkColorType: 642 proc = &swizzle_bit_to_n32; 643 break; 644 case kIndex_8_SkColorType: 645 proc = &swizzle_bit_to_index; 646 break; 647 case kRGB_565_SkColorType: 648 proc = &swizzle_bit_to_565; 649 break; 650 case kGray_8_SkColorType: 651 proc = &swizzle_bit_to_grayscale; 652 break; 653 default: 654 break; 655 } 656 break; 657 case kIndex1: 658 case kIndex2: 659 case kIndex4: 660 switch (dstInfo.colorType()) { 661 case kN32_SkColorType: 662 proc = &swizzle_small_index_to_n32; 663 break; 664 case kRGB_565_SkColorType: 665 proc = &swizzle_small_index_to_565; 666 break; 667 case kIndex_8_SkColorType: 668 proc = &swizzle_small_index_to_index; 669 break; 670 default: 671 break; 672 } 673 break; 674 case kIndex: 675 switch (dstInfo.colorType()) { 676 case kN32_SkColorType: 677 // We assume the color premultiplied ctable (or not) as desired. 678 if (SkCodec::kYes_ZeroInitialized == zeroInit) { 679 proc = &swizzle_index_to_n32_skipZ; 680 break; 681 } else { 682 proc = &swizzle_index_to_n32; 683 break; 684 } 685 break; 686 case kRGB_565_SkColorType: 687 proc = &swizzle_index_to_565; 688 break; 689 case kIndex_8_SkColorType: 690 proc = &sample1; 691 fastProc = © 692 break; 693 default: 694 break; 695 } 696 break; 697 case kGray: 698 switch (dstInfo.colorType()) { 699 case kN32_SkColorType: 700 proc = &swizzle_gray_to_n32; 701 fastProc = &fast_swizzle_gray_to_n32; 702 break; 703 case kGray_8_SkColorType: 704 proc = &sample1; 705 fastProc = © 706 break; 707 case kRGB_565_SkColorType: 708 proc = &swizzle_gray_to_565; 709 break; 710 default: 711 break; 712 } 713 break; 714 case kGrayAlpha: 715 switch (dstInfo.colorType()) { 716 case kN32_SkColorType: 717 if (dstInfo.alphaType() == kUnpremul_SkAlphaType) { 718 if (SkCodec::kYes_ZeroInitialized == zeroInit) { 719 proc = &SkipLeadingGrayAlphaZerosThen 720 <swizzle_grayalpha_to_n32_unpremul>; 721 } else { 722 proc = &swizzle_grayalpha_to_n32_unpremul; 723 } 724 } else { 725 if (SkCodec::kYes_ZeroInitialized == zeroInit) { 726 proc = &SkipLeadingGrayAlphaZerosThen<swizzle_grayalpha_to_n32_premul>; 727 } else { 728 proc = &swizzle_grayalpha_to_n32_premul; 729 } 730 } 731 break; 732 default: 733 break; 734 } 735 break; 736 case kBGR: 737 case kBGRX: 738 switch (dstInfo.colorType()) { 739 case kN32_SkColorType: 740 proc = &swizzle_bgrx_to_n32; 741 break; 742 case kRGB_565_SkColorType: 743 proc = &swizzle_bgrx_to_565; 744 break; 745 default: 746 break; 747 } 748 break; 749 case kBGRA: 750 switch (dstInfo.colorType()) { 751 case kN32_SkColorType: 752 if (dstInfo.alphaType() == kUnpremul_SkAlphaType) { 753 if (SkCodec::kYes_ZeroInitialized == zeroInit) { 754 proc = &SkipLeading8888ZerosThen<swizzle_bgra_to_n32_unpremul>; 755 fastProc = &SkipLeading8888ZerosThen<fast_swizzle_bgra_to_n32_unpremul>; 756 } else { 757 proc = &swizzle_bgra_to_n32_unpremul; 758 fastProc = &fast_swizzle_bgra_to_n32_unpremul; 759 } 760 } else { 761 if (SkCodec::kYes_ZeroInitialized == zeroInit) { 762 proc = &SkipLeading8888ZerosThen<swizzle_bgra_to_n32_premul>; 763 fastProc = &SkipLeading8888ZerosThen<fast_swizzle_bgra_to_n32_premul>; 764 } else { 765 proc = &swizzle_bgra_to_n32_premul; 766 fastProc = &fast_swizzle_bgra_to_n32_premul; 767 } 768 } 769 break; 770 default: 771 break; 772 } 773 break; 774 case kRGB: 775 switch (dstInfo.colorType()) { 776 case kN32_SkColorType: 777 proc = &swizzle_rgb_to_n32; 778 fastProc = &fast_swizzle_rgb_to_n32; 779 break; 780 case kRGB_565_SkColorType: 781 proc = &swizzle_rgb_to_565; 782 default: 783 break; 784 } 785 break; 786 case kRGBA: 787 switch (dstInfo.colorType()) { 788 case kN32_SkColorType: 789 if (dstInfo.alphaType() == kUnpremul_SkAlphaType) { 790 if (SkCodec::kYes_ZeroInitialized == zeroInit) { 791 proc = &SkipLeading8888ZerosThen<swizzle_rgba_to_n32_unpremul>; 792 fastProc = &SkipLeading8888ZerosThen<fast_swizzle_rgba_to_n32_unpremul>; 793 } else { 794 proc = &swizzle_rgba_to_n32_unpremul; 795 fastProc = &fast_swizzle_rgba_to_n32_unpremul; 796 } 797 } else { 798 if (SkCodec::kYes_ZeroInitialized == zeroInit) { 799 proc = &SkipLeading8888ZerosThen<swizzle_rgba_to_n32_premul>; 800 fastProc = &SkipLeading8888ZerosThen<fast_swizzle_rgba_to_n32_premul>; 801 } else { 802 proc = &swizzle_rgba_to_n32_premul; 803 fastProc = &fast_swizzle_rgba_to_n32_premul; 804 } 805 } 806 break; 807 default: 808 break; 809 } 810 break; 811 case kCMYK: 812 switch (dstInfo.colorType()) { 813 case kN32_SkColorType: 814 proc = &swizzle_cmyk_to_n32; 815 break; 816 case kRGB_565_SkColorType: 817 proc = &swizzle_cmyk_to_565; 818 break; 819 default: 820 break; 821 } 822 break; 823 case kNoOp8: 824 proc = &sample1; 825 fastProc = © 826 break; 827 case kNoOp16: 828 proc = sample2; 829 fastProc = © 830 break; 831 case kNoOp32: 832 proc = &sample4; 833 fastProc = © 834 break; 835 default: 836 break; 837 } 838 839 // Store bpp in bytes if it is an even multiple, otherwise use bits 840 int srcBPP = SkIsAlign8(BitsPerPixel(sc)) ? BytesPerPixel(sc) : BitsPerPixel(sc); 841 int dstBPP = SkColorTypeBytesPerPixel(dstInfo.colorType()); 842 843 int srcOffset = 0; 844 int srcWidth = dstInfo.width(); 845 int dstOffset = 0; 846 int dstWidth = srcWidth; 847 if (options.fSubset) { 848 // We do not currently support subset decodes for image types that may have 849 // frames (gif). 850 SkASSERT(!frame); 851 srcOffset = options.fSubset->left(); 852 srcWidth = options.fSubset->width(); 853 dstWidth = srcWidth; 854 } else if (frame) { 855 dstOffset = frame->left(); 856 srcWidth = frame->width(); 857 } 858 859 return new SkSwizzler(fastProc, proc, ctable, srcOffset, srcWidth, dstOffset, dstWidth, 860 srcBPP, dstBPP); 861} 862 863SkSwizzler::SkSwizzler(RowProc fastProc, RowProc proc, const SkPMColor* ctable, int srcOffset, 864 int srcWidth, int dstOffset, int dstWidth, int srcBPP, int dstBPP) 865 : fFastProc(fastProc) 866 , fSlowProc(proc) 867 , fActualProc(fFastProc ? fFastProc : fSlowProc) 868 , fColorTable(ctable) 869 , fSrcOffset(srcOffset) 870 , fDstOffset(dstOffset) 871 , fSrcOffsetUnits(srcOffset * srcBPP) 872 , fDstOffsetBytes(dstOffset * dstBPP) 873 , fSrcWidth(srcWidth) 874 , fDstWidth(dstWidth) 875 , fSwizzleWidth(srcWidth) 876 , fAllocatedWidth(dstWidth) 877 , fSampleX(1) 878 , fSrcBPP(srcBPP) 879 , fDstBPP(dstBPP) 880{} 881 882int SkSwizzler::onSetSampleX(int sampleX) { 883 SkASSERT(sampleX > 0); // Surely there is an upper limit? Should there be 884 // way to report failure? 885 fSampleX = sampleX; 886 fSrcOffsetUnits = (get_start_coord(sampleX) + fSrcOffset) * fSrcBPP; 887 fDstOffsetBytes = (fDstOffset / sampleX) * fDstBPP; 888 fSwizzleWidth = get_scaled_dimension(fSrcWidth, sampleX); 889 fAllocatedWidth = get_scaled_dimension(fDstWidth, sampleX); 890 891 // The optimized swizzler routines do not (yet) support sampling. 892 if (1 == fSampleX && fFastProc) { 893 fActualProc = fFastProc; 894 } else { 895 fActualProc = fSlowProc; 896 } 897 898 return fAllocatedWidth; 899} 900 901void SkSwizzler::swizzle(void* dst, const uint8_t* SK_RESTRICT src) { 902 SkASSERT(nullptr != dst && nullptr != src); 903 fActualProc(SkTAddOffset<void>(dst, fDstOffsetBytes), src, fSwizzleWidth, fSrcBPP, 904 fSampleX * fSrcBPP, fSrcOffsetUnits, fColorTable); 905} 906