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 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 325static 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 338static 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 353static 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 365static 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 379static 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 392static 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 407static 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 420static 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 437static 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 449static 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 464static 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 478static 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 491static 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 506static 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 519static 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 579static 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 595static 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 610static 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 626template <SkSwizzler::RowProc proc> 627void 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 645template <SkSwizzler::RowProc proc> 646void 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 664SkSwizzler* 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 = © 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 = © 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 = © 875 break; 876 case kNoOp16: 877 proc = sample2; 878 fastProc = © 879 break; 880 case kNoOp32: 881 proc = &sample4; 882 fastProc = © 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 912SkSwizzler::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 931int 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 952void 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