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 "SkColorData.h" 10 #include "SkMaskSwizzler.h" 11 12 static 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 29 static 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 46 static 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 64 static 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 82 static 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 100 static 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. 120 static 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 137 static 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 154 static 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 171 static 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 189 static 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 207 static 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 225 static 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 243 static 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 260 static 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 277 static 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 294 static 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 312 static 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 330 static 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 348 static 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 366 static 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 */ 387 SkMaskSwizzler* 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 */ 537 SkMaskSwizzler::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 547 int 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 */ 565 void 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