1/* 2 * Copyright 2007 The Android Open Source Project 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 9#include "SkScaledBitmapSampler.h" 10#include "SkBitmap.h" 11#include "SkColorPriv.h" 12#include "SkDither.h" 13#include "SkTypes.h" 14 15// 8888 16 17static bool Sample_Gray_D8888(void* SK_RESTRICT dstRow, 18 const uint8_t* SK_RESTRICT src, 19 int width, int deltaSrc, int, const SkPMColor[]) { 20 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow; 21 for (int x = 0; x < width; x++) { 22 dst[x] = SkPackARGB32(0xFF, src[0], src[0], src[0]); 23 src += deltaSrc; 24 } 25 return false; 26} 27 28static SkScaledBitmapSampler::RowProc get_gray_to_8888_proc(const SkImageDecoder& decoder) { 29 // Dither, unpremul, and skipZeroes have no effect 30 return Sample_Gray_D8888; 31} 32 33static bool Sample_RGBx_D8888(void* SK_RESTRICT dstRow, 34 const uint8_t* SK_RESTRICT src, 35 int width, int deltaSrc, int, const SkPMColor[]) { 36 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow; 37 for (int x = 0; x < width; x++) { 38 dst[x] = SkPackARGB32(0xFF, src[0], src[1], src[2]); 39 src += deltaSrc; 40 } 41 return false; 42} 43 44static SkScaledBitmapSampler::RowProc get_RGBx_to_8888_proc(const SkImageDecoder& decoder) { 45 // Dither, unpremul, and skipZeroes have no effect 46 return Sample_RGBx_D8888; 47} 48 49static bool Sample_RGBA_D8888(void* SK_RESTRICT dstRow, 50 const uint8_t* SK_RESTRICT src, 51 int width, int deltaSrc, int, const SkPMColor[]) { 52 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow; 53 unsigned alphaMask = 0xFF; 54 for (int x = 0; x < width; x++) { 55 unsigned alpha = src[3]; 56 dst[x] = SkPreMultiplyARGB(alpha, src[0], src[1], src[2]); 57 src += deltaSrc; 58 alphaMask &= alpha; 59 } 60 return alphaMask != 0xFF; 61} 62 63static bool Sample_RGBA_D8888_Unpremul(void* SK_RESTRICT dstRow, 64 const uint8_t* SK_RESTRICT src, 65 int width, int deltaSrc, int, 66 const SkPMColor[]) { 67 uint32_t* SK_RESTRICT dst = reinterpret_cast<uint32_t*>(dstRow); 68 unsigned alphaMask = 0xFF; 69 for (int x = 0; x < width; x++) { 70 unsigned alpha = src[3]; 71 dst[x] = SkPackARGB32NoCheck(alpha, src[0], src[1], src[2]); 72 src += deltaSrc; 73 alphaMask &= alpha; 74 } 75 return alphaMask != 0xFF; 76} 77 78static bool Sample_RGBA_D8888_SkipZ(void* SK_RESTRICT dstRow, 79 const uint8_t* SK_RESTRICT src, 80 int width, int deltaSrc, int, 81 const SkPMColor[]) { 82 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow; 83 unsigned alphaMask = 0xFF; 84 for (int x = 0; x < width; x++) { 85 unsigned alpha = src[3]; 86 if (0 != alpha) { 87 dst[x] = SkPreMultiplyARGB(alpha, src[0], src[1], src[2]); 88 } 89 src += deltaSrc; 90 alphaMask &= alpha; 91 } 92 return alphaMask != 0xFF; 93} 94 95static SkScaledBitmapSampler::RowProc get_RGBA_to_8888_proc(const SkImageDecoder& decoder) { 96 // Dither has no effect. 97 if (decoder.getRequireUnpremultipliedColors()) { 98 // We could check each component for a zero, at the expense of extra checks. 99 // For now, just return unpremul. 100 return Sample_RGBA_D8888_Unpremul; 101 } 102 // Supply the versions that premultiply the colors 103 if (decoder.getSkipWritingZeroes()) { 104 return Sample_RGBA_D8888_SkipZ; 105 } 106 return Sample_RGBA_D8888; 107} 108 109// 565 110 111static bool Sample_Gray_D565(void* SK_RESTRICT dstRow, 112 const uint8_t* SK_RESTRICT src, 113 int width, int deltaSrc, int, const SkPMColor[]) { 114 uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow; 115 for (int x = 0; x < width; x++) { 116 dst[x] = SkPack888ToRGB16(src[0], src[0], src[0]); 117 src += deltaSrc; 118 } 119 return false; 120} 121 122static bool Sample_Gray_D565_D(void* SK_RESTRICT dstRow, 123 const uint8_t* SK_RESTRICT src, 124 int width, int deltaSrc, int y, const SkPMColor[]) { 125 uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow; 126 DITHER_565_SCAN(y); 127 for (int x = 0; x < width; x++) { 128 dst[x] = SkDitherRGBTo565(src[0], src[0], src[0], DITHER_VALUE(x)); 129 src += deltaSrc; 130 } 131 return false; 132} 133 134static SkScaledBitmapSampler::RowProc get_gray_to_565_proc(const SkImageDecoder& decoder) { 135 // Unpremul and skip zeroes make no difference 136 if (decoder.getDitherImage()) { 137 return Sample_Gray_D565_D; 138 } 139 return Sample_Gray_D565; 140} 141 142static bool Sample_RGBx_D565(void* SK_RESTRICT dstRow, 143 const uint8_t* SK_RESTRICT src, 144 int width, int deltaSrc, int, const SkPMColor[]) { 145 uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow; 146 for (int x = 0; x < width; x++) { 147 dst[x] = SkPack888ToRGB16(src[0], src[1], src[2]); 148 src += deltaSrc; 149 } 150 return false; 151} 152 153static bool Sample_RGBx_D565_D(void* SK_RESTRICT dstRow, 154 const uint8_t* SK_RESTRICT src, 155 int width, int deltaSrc, int y, 156 const SkPMColor[]) { 157 uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow; 158 DITHER_565_SCAN(y); 159 for (int x = 0; x < width; x++) { 160 dst[x] = SkDitherRGBTo565(src[0], src[1], src[2], DITHER_VALUE(x)); 161 src += deltaSrc; 162 } 163 return false; 164} 165 166static SkScaledBitmapSampler::RowProc get_RGBx_to_565_proc(const SkImageDecoder& decoder) { 167 // Unpremul and skip zeroes make no difference 168 if (decoder.getDitherImage()) { 169 return Sample_RGBx_D565_D; 170 } 171 return Sample_RGBx_D565; 172} 173 174 175static bool Sample_D565_D565(void* SK_RESTRICT dstRow, 176 const uint8_t* SK_RESTRICT src, 177 int width, int deltaSrc, int, const SkPMColor[]) { 178 uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow; 179 uint16_t* SK_RESTRICT castedSrc = (uint16_t*) src; 180 for (int x = 0; x < width; x++) { 181 dst[x] = castedSrc[0]; 182 castedSrc += deltaSrc >> 1; 183 } 184 return false; 185} 186 187static SkScaledBitmapSampler::RowProc get_565_to_565_proc(const SkImageDecoder& decoder) { 188 // Unpremul, dither, and skip zeroes have no effect 189 return Sample_D565_D565; 190} 191 192// 4444 193 194static bool Sample_Gray_D4444(void* SK_RESTRICT dstRow, 195 const uint8_t* SK_RESTRICT src, 196 int width, int deltaSrc, int, const SkPMColor[]) { 197 SkPMColor16* SK_RESTRICT dst = (SkPMColor16*)dstRow; 198 for (int x = 0; x < width; x++) { 199 unsigned gray = src[0] >> 4; 200 dst[x] = SkPackARGB4444(0xF, gray, gray, gray); 201 src += deltaSrc; 202 } 203 return false; 204} 205 206static bool Sample_Gray_D4444_D(void* SK_RESTRICT dstRow, 207 const uint8_t* SK_RESTRICT src, 208 int width, int deltaSrc, int y, const SkPMColor[]) { 209 SkPMColor16* SK_RESTRICT dst = (SkPMColor16*)dstRow; 210 DITHER_4444_SCAN(y); 211 for (int x = 0; x < width; x++) { 212 dst[x] = SkDitherARGB32To4444(0xFF, src[0], src[0], src[0], 213 DITHER_VALUE(x)); 214 src += deltaSrc; 215 } 216 return false; 217} 218 219static SkScaledBitmapSampler::RowProc get_gray_to_4444_proc(const SkImageDecoder& decoder) { 220 // Skip zeroes and unpremul make no difference 221 if (decoder.getDitherImage()) { 222 return Sample_Gray_D4444_D; 223 } 224 return Sample_Gray_D4444; 225} 226 227static bool Sample_RGBx_D4444(void* SK_RESTRICT dstRow, 228 const uint8_t* SK_RESTRICT src, 229 int width, int deltaSrc, int, const SkPMColor[]) { 230 SkPMColor16* SK_RESTRICT dst = (SkPMColor16*)dstRow; 231 for (int x = 0; x < width; x++) { 232 dst[x] = SkPackARGB4444(0xF, src[0] >> 4, src[1] >> 4, src[2] >> 4); 233 src += deltaSrc; 234 } 235 return false; 236} 237 238static bool Sample_RGBx_D4444_D(void* SK_RESTRICT dstRow, 239 const uint8_t* SK_RESTRICT src, 240 int width, int deltaSrc, int y, const SkPMColor[]) { 241 SkPMColor16* dst = (SkPMColor16*)dstRow; 242 DITHER_4444_SCAN(y); 243 244 for (int x = 0; x < width; x++) { 245 dst[x] = SkDitherARGB32To4444(0xFF, src[0], src[1], src[2], 246 DITHER_VALUE(x)); 247 src += deltaSrc; 248 } 249 return false; 250} 251 252static SkScaledBitmapSampler::RowProc get_RGBx_to_4444_proc(const SkImageDecoder& decoder) { 253 // Skip zeroes and unpremul make no difference 254 if (decoder.getDitherImage()) { 255 return Sample_RGBx_D4444_D; 256 } 257 return Sample_RGBx_D4444; 258} 259 260static bool Sample_RGBA_D4444(void* SK_RESTRICT dstRow, 261 const uint8_t* SK_RESTRICT src, 262 int width, int deltaSrc, int, const SkPMColor[]) { 263 SkPMColor16* SK_RESTRICT dst = (SkPMColor16*)dstRow; 264 unsigned alphaMask = 0xFF; 265 266 for (int x = 0; x < width; x++) { 267 unsigned alpha = src[3]; 268 SkPMColor c = SkPreMultiplyARGB(alpha, src[0], src[1], src[2]); 269 dst[x] = SkPixel32ToPixel4444(c); 270 src += deltaSrc; 271 alphaMask &= alpha; 272 } 273 return alphaMask != 0xFF; 274} 275 276static bool Sample_RGBA_D4444_SkipZ(void* SK_RESTRICT dstRow, 277 const uint8_t* SK_RESTRICT src, 278 int width, int deltaSrc, int, 279 const SkPMColor[]) { 280 SkPMColor16* SK_RESTRICT dst = (SkPMColor16*)dstRow; 281 unsigned alphaMask = 0xFF; 282 283 for (int x = 0; x < width; x++) { 284 unsigned alpha = src[3]; 285 if (alpha != 0) { 286 SkPMColor c = SkPreMultiplyARGB(alpha, src[0], src[1], src[2]); 287 dst[x] = SkPixel32ToPixel4444(c); 288 } 289 src += deltaSrc; 290 alphaMask &= alpha; 291 } 292 return alphaMask != 0xFF; 293} 294 295 296static bool Sample_RGBA_D4444_D(void* SK_RESTRICT dstRow, 297 const uint8_t* SK_RESTRICT src, 298 int width, int deltaSrc, int y, 299 const SkPMColor[]) { 300 SkPMColor16* SK_RESTRICT dst = (SkPMColor16*)dstRow; 301 unsigned alphaMask = 0xFF; 302 DITHER_4444_SCAN(y); 303 304 for (int x = 0; x < width; x++) { 305 unsigned alpha = src[3]; 306 SkPMColor c = SkPreMultiplyARGB(alpha, src[0], src[1], src[2]); 307 dst[x] = SkDitherARGB32To4444(c, DITHER_VALUE(x)); 308 src += deltaSrc; 309 alphaMask &= alpha; 310 } 311 return alphaMask != 0xFF; 312} 313 314static bool Sample_RGBA_D4444_D_SkipZ(void* SK_RESTRICT dstRow, 315 const uint8_t* SK_RESTRICT src, 316 int width, int deltaSrc, int y, 317 const SkPMColor[]) { 318 SkPMColor16* SK_RESTRICT dst = (SkPMColor16*)dstRow; 319 unsigned alphaMask = 0xFF; 320 DITHER_4444_SCAN(y); 321 322 for (int x = 0; x < width; x++) { 323 unsigned alpha = src[3]; 324 if (alpha != 0) { 325 SkPMColor c = SkPreMultiplyARGB(alpha, src[0], src[1], src[2]); 326 dst[x] = SkDitherARGB32To4444(c, DITHER_VALUE(x)); 327 } 328 src += deltaSrc; 329 alphaMask &= alpha; 330 } 331 return alphaMask != 0xFF; 332} 333 334static SkScaledBitmapSampler::RowProc get_RGBA_to_4444_proc(const SkImageDecoder& decoder) { 335 if (decoder.getRequireUnpremultipliedColors()) { 336 // Unpremultiplied is not supported for 4444 337 return NULL; 338 } 339 const bool dither = decoder.getDitherImage(); 340 if (decoder.getSkipWritingZeroes()) { 341 if (dither) { 342 return Sample_RGBA_D4444_D_SkipZ; 343 } 344 return Sample_RGBA_D4444_SkipZ; 345 } 346 if (dither) { 347 return Sample_RGBA_D4444_D; 348 } 349 return Sample_RGBA_D4444; 350} 351 352// Index 353 354#define A32_MASK_IN_PLACE (SkPMColor)(SK_A32_MASK << SK_A32_SHIFT) 355 356static bool Sample_Index_D8888(void* SK_RESTRICT dstRow, 357 const uint8_t* SK_RESTRICT src, 358 int width, int deltaSrc, int, const SkPMColor ctable[]) { 359 360 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow; 361 SkPMColor cc = A32_MASK_IN_PLACE; 362 for (int x = 0; x < width; x++) { 363 SkPMColor c = ctable[*src]; 364 cc &= c; 365 dst[x] = c; 366 src += deltaSrc; 367 } 368 return cc != A32_MASK_IN_PLACE; 369} 370 371static bool Sample_Index_D8888_SkipZ(void* SK_RESTRICT dstRow, 372 const uint8_t* SK_RESTRICT src, 373 int width, int deltaSrc, int, 374 const SkPMColor ctable[]) { 375 376 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow; 377 SkPMColor cc = A32_MASK_IN_PLACE; 378 for (int x = 0; x < width; x++) { 379 SkPMColor c = ctable[*src]; 380 cc &= c; 381 if (c != 0) { 382 dst[x] = c; 383 } 384 src += deltaSrc; 385 } 386 return cc != A32_MASK_IN_PLACE; 387} 388 389static SkScaledBitmapSampler::RowProc get_index_to_8888_proc(const SkImageDecoder& decoder) { 390 if (decoder.getRequireUnpremultipliedColors()) { 391 // Unpremultiplied is not supported for an index source. 392 return NULL; 393 } 394 // Dither makes no difference 395 if (decoder.getSkipWritingZeroes()) { 396 return Sample_Index_D8888_SkipZ; 397 } 398 return Sample_Index_D8888; 399} 400 401static bool Sample_Index_D565(void* SK_RESTRICT dstRow, 402 const uint8_t* SK_RESTRICT src, 403 int width, int deltaSrc, int, const SkPMColor ctable[]) { 404 405 uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow; 406 for (int x = 0; x < width; x++) { 407 dst[x] = SkPixel32ToPixel16(ctable[*src]); 408 src += deltaSrc; 409 } 410 return false; 411} 412 413static bool Sample_Index_D565_D(void* SK_RESTRICT dstRow, 414 const uint8_t* SK_RESTRICT src, int width, 415 int deltaSrc, int y, const SkPMColor ctable[]) { 416 417 uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow; 418 DITHER_565_SCAN(y); 419 420 for (int x = 0; x < width; x++) { 421 SkPMColor c = ctable[*src]; 422 dst[x] = SkDitherRGBTo565(SkGetPackedR32(c), SkGetPackedG32(c), 423 SkGetPackedB32(c), DITHER_VALUE(x)); 424 src += deltaSrc; 425 } 426 return false; 427} 428 429static SkScaledBitmapSampler::RowProc get_index_to_565_proc(const SkImageDecoder& decoder) { 430 // Unpremultiplied and skip zeroes make no difference 431 if (decoder.getDitherImage()) { 432 return Sample_Index_D565_D; 433 } 434 return Sample_Index_D565; 435} 436 437static bool Sample_Index_D4444(void* SK_RESTRICT dstRow, 438 const uint8_t* SK_RESTRICT src, int width, 439 int deltaSrc, int y, const SkPMColor ctable[]) { 440 441 SkPMColor16* SK_RESTRICT dst = (SkPMColor16*)dstRow; 442 SkPMColor cc = A32_MASK_IN_PLACE; 443 for (int x = 0; x < width; x++) { 444 SkPMColor c = ctable[*src]; 445 cc &= c; 446 dst[x] = SkPixel32ToPixel4444(c); 447 src += deltaSrc; 448 } 449 return cc != A32_MASK_IN_PLACE; 450} 451 452static bool Sample_Index_D4444_D(void* SK_RESTRICT dstRow, 453 const uint8_t* SK_RESTRICT src, int width, 454 int deltaSrc, int y, const SkPMColor ctable[]) { 455 456 SkPMColor16* SK_RESTRICT dst = (SkPMColor16*)dstRow; 457 SkPMColor cc = A32_MASK_IN_PLACE; 458 DITHER_4444_SCAN(y); 459 460 for (int x = 0; x < width; x++) { 461 SkPMColor c = ctable[*src]; 462 cc &= c; 463 dst[x] = SkDitherARGB32To4444(c, DITHER_VALUE(x)); 464 src += deltaSrc; 465 } 466 return cc != A32_MASK_IN_PLACE; 467} 468 469static bool Sample_Index_D4444_SkipZ(void* SK_RESTRICT dstRow, 470 const uint8_t* SK_RESTRICT src, int width, 471 int deltaSrc, int y, const SkPMColor ctable[]) { 472 473 SkPMColor16* SK_RESTRICT dst = (SkPMColor16*)dstRow; 474 SkPMColor cc = A32_MASK_IN_PLACE; 475 for (int x = 0; x < width; x++) { 476 SkPMColor c = ctable[*src]; 477 cc &= c; 478 if (c != 0) { 479 dst[x] = SkPixel32ToPixel4444(c); 480 } 481 src += deltaSrc; 482 } 483 return cc != A32_MASK_IN_PLACE; 484} 485 486static bool Sample_Index_D4444_D_SkipZ(void* SK_RESTRICT dstRow, 487 const uint8_t* SK_RESTRICT src, int width, 488 int deltaSrc, int y, const SkPMColor ctable[]) { 489 490 SkPMColor16* SK_RESTRICT dst = (SkPMColor16*)dstRow; 491 SkPMColor cc = A32_MASK_IN_PLACE; 492 DITHER_4444_SCAN(y); 493 494 for (int x = 0; x < width; x++) { 495 SkPMColor c = ctable[*src]; 496 cc &= c; 497 if (c != 0) { 498 dst[x] = SkDitherARGB32To4444(c, DITHER_VALUE(x)); 499 } 500 src += deltaSrc; 501 } 502 return cc != A32_MASK_IN_PLACE; 503} 504 505static SkScaledBitmapSampler::RowProc get_index_to_4444_proc(const SkImageDecoder& decoder) { 506 // Unpremul not allowed 507 if (decoder.getRequireUnpremultipliedColors()) { 508 return NULL; 509 } 510 const bool dither = decoder.getDitherImage(); 511 if (decoder.getSkipWritingZeroes()) { 512 if (dither) { 513 return Sample_Index_D4444_D_SkipZ; 514 } 515 return Sample_Index_D4444_SkipZ; 516 } 517 if (dither) { 518 return Sample_Index_D4444_D; 519 } 520 return Sample_Index_D4444; 521} 522 523static bool Sample_Index_DI(void* SK_RESTRICT dstRow, 524 const uint8_t* SK_RESTRICT src, 525 int width, int deltaSrc, int, const SkPMColor[]) { 526 if (1 == deltaSrc) { 527 memcpy(dstRow, src, width); 528 } else { 529 uint8_t* SK_RESTRICT dst = (uint8_t*)dstRow; 530 for (int x = 0; x < width; x++) { 531 dst[x] = src[0]; 532 src += deltaSrc; 533 } 534 } 535 return false; 536} 537 538static SkScaledBitmapSampler::RowProc get_index_to_index_proc(const SkImageDecoder& decoder) { 539 // Unpremul not allowed 540 if (decoder.getRequireUnpremultipliedColors()) { 541 return NULL; 542 } 543 // Ignore dither and skip zeroes 544 return Sample_Index_DI; 545} 546 547// A8 548static bool Sample_Gray_DA8(void* SK_RESTRICT dstRow, 549 const uint8_t* SK_RESTRICT src, 550 int width, int deltaSrc, int, 551 const SkPMColor[]) { 552 memcpy(dstRow, src, width); 553 return true; 554} 555 556static SkScaledBitmapSampler::RowProc get_gray_to_A8_proc(const SkImageDecoder& decoder) { 557 if (decoder.getRequireUnpremultipliedColors()) { 558 return NULL; 559 } 560 // Ignore skip and dither. 561 return Sample_Gray_DA8; 562} 563 564typedef SkScaledBitmapSampler::RowProc (*RowProcChooser)(const SkImageDecoder& decoder); 565/////////////////////////////////////////////////////////////////////////////// 566 567#include "SkScaledBitmapSampler.h" 568 569SkScaledBitmapSampler::SkScaledBitmapSampler(int width, int height, 570 int sampleSize) { 571 fCTable = NULL; 572 fDstRow = NULL; 573 fRowProc = NULL; 574 575 if (width <= 0 || height <= 0) { 576 sk_throw(); 577 } 578 579 if (sampleSize <= 1) { 580 fScaledWidth = width; 581 fScaledHeight = height; 582 fX0 = fY0 = 0; 583 fDX = fDY = 1; 584 return; 585 } 586 587 int dx = SkMin32(sampleSize, width); 588 int dy = SkMin32(sampleSize, height); 589 590 fScaledWidth = width / dx; 591 fScaledHeight = height / dy; 592 593 SkASSERT(fScaledWidth > 0); 594 SkASSERT(fScaledHeight > 0); 595 596 fX0 = dx >> 1; 597 fY0 = dy >> 1; 598 599 SkASSERT(fX0 >= 0 && fX0 < width); 600 SkASSERT(fY0 >= 0 && fY0 < height); 601 602 fDX = dx; 603 fDY = dy; 604 605 SkASSERT(fDX > 0 && (fX0 + fDX * (fScaledWidth - 1)) < width); 606 SkASSERT(fDY > 0 && (fY0 + fDY * (fScaledHeight - 1)) < height); 607} 608 609bool SkScaledBitmapSampler::begin(SkBitmap* dst, SrcConfig sc, 610 const SkImageDecoder& decoder, 611 const SkPMColor ctable[]) { 612 static const RowProcChooser gProcChoosers[] = { 613 get_gray_to_8888_proc, 614 get_RGBx_to_8888_proc, 615 get_RGBA_to_8888_proc, 616 get_index_to_8888_proc, 617 NULL, // 565 to 8888 618 619 get_gray_to_565_proc, 620 get_RGBx_to_565_proc, 621 get_RGBx_to_565_proc, // The source alpha will be ignored. 622 get_index_to_565_proc, 623 get_565_to_565_proc, 624 625 get_gray_to_4444_proc, 626 get_RGBx_to_4444_proc, 627 get_RGBA_to_4444_proc, 628 get_index_to_4444_proc, 629 NULL, // 565 to 4444 630 631 NULL, // gray to index 632 NULL, // rgbx to index 633 NULL, // rgba to index 634 get_index_to_index_proc, 635 NULL, // 565 to index 636 637 get_gray_to_A8_proc, 638 NULL, // rgbx to a8 639 NULL, // rgba to a8 640 NULL, // index to a8 641 NULL, // 565 to a8 642 }; 643 644 // The jump between dst configs in the table 645 static const int gProcDstConfigSpan = 5; 646 SK_COMPILE_ASSERT(SK_ARRAY_COUNT(gProcChoosers) == 5 * gProcDstConfigSpan, 647 gProcs_has_the_wrong_number_of_entries); 648 649 fCTable = ctable; 650 651 int index = 0; 652 switch (sc) { 653 case SkScaledBitmapSampler::kGray: 654 fSrcPixelSize = 1; 655 index += 0; 656 break; 657 case SkScaledBitmapSampler::kRGB: 658 fSrcPixelSize = 3; 659 index += 1; 660 break; 661 case SkScaledBitmapSampler::kRGBX: 662 fSrcPixelSize = 4; 663 index += 1; 664 break; 665 case SkScaledBitmapSampler::kRGBA: 666 fSrcPixelSize = 4; 667 index += 2; 668 break; 669 case SkScaledBitmapSampler::kIndex: 670 fSrcPixelSize = 1; 671 index += 3; 672 break; 673 case SkScaledBitmapSampler::kRGB_565: 674 fSrcPixelSize = 2; 675 index += 4; 676 break; 677 default: 678 return false; 679 } 680 681 switch (dst->config()) { 682 case SkBitmap::kARGB_8888_Config: 683 index += 0 * gProcDstConfigSpan; 684 break; 685 case SkBitmap::kRGB_565_Config: 686 index += 1 * gProcDstConfigSpan; 687 break; 688 case SkBitmap::kARGB_4444_Config: 689 index += 2 * gProcDstConfigSpan; 690 break; 691 case SkBitmap::kIndex8_Config: 692 index += 3 * gProcDstConfigSpan; 693 break; 694 case SkBitmap::kA8_Config: 695 index += 4 * gProcDstConfigSpan; 696 break; 697 default: 698 return false; 699 } 700 701 RowProcChooser chooser = gProcChoosers[index]; 702 if (NULL == chooser) { 703 fRowProc = NULL; 704 } else { 705 fRowProc = chooser(decoder); 706 } 707 fDstRow = (char*)dst->getPixels(); 708 fDstRowBytes = dst->rowBytes(); 709 fCurrY = 0; 710 return fRowProc != NULL; 711} 712 713bool SkScaledBitmapSampler::next(const uint8_t* SK_RESTRICT src) { 714 SkASSERT((unsigned)fCurrY < (unsigned)fScaledHeight); 715 716 bool hadAlpha = fRowProc(fDstRow, src + fX0 * fSrcPixelSize, fScaledWidth, 717 fDX * fSrcPixelSize, fCurrY, fCTable); 718 fDstRow += fDstRowBytes; 719 fCurrY += 1; 720 return hadAlpha; 721} 722 723#ifdef SK_DEBUG 724// The following code is for a test to ensure that changing the method to get the right row proc 725// did not change the row proc unintentionally. Tested by ImageDecodingTest.cpp 726 727// friend of SkScaledBitmapSampler solely for the purpose of accessing fRowProc. 728class RowProcTester { 729public: 730 static SkScaledBitmapSampler::RowProc getRowProc(const SkScaledBitmapSampler& sampler) { 731 return sampler.fRowProc; 732 } 733}; 734 735 736// Table showing the expected RowProc for each combination of inputs. 737// Table formated as follows: 738// Each group of 5 consecutive rows represents sampling from a single 739// SkScaledBitmapSampler::SrcConfig. 740// Within each set, each row represents a different destination SkBitmap::Config 741// Each column represents a different combination of dither and unpremul. 742// D = dither ~D = no dither 743// U = unpremul ~U = no unpremul 744// ~D~U D~U ~DU DU 745SkScaledBitmapSampler::RowProc gTestProcs[] = { 746 // Gray 747 Sample_Gray_DA8, Sample_Gray_DA8, NULL, NULL, // to A8 748 NULL, NULL, NULL, NULL, // to Index8 749 Sample_Gray_D565, Sample_Gray_D565_D, Sample_Gray_D565, Sample_Gray_D565_D, // to 565 750 Sample_Gray_D4444, Sample_Gray_D4444_D, Sample_Gray_D4444, Sample_Gray_D4444_D, // to 4444 751 Sample_Gray_D8888, Sample_Gray_D8888, Sample_Gray_D8888, Sample_Gray_D8888, // to 8888 752 // Index 753 NULL, NULL, NULL, NULL, // to A8 754 Sample_Index_DI, Sample_Index_DI, NULL, NULL, // to Index8 755 Sample_Index_D565, Sample_Index_D565_D, Sample_Index_D565, Sample_Index_D565_D, // to 565 756 Sample_Index_D4444, Sample_Index_D4444_D, NULL, NULL, // to 4444 757 Sample_Index_D8888, Sample_Index_D8888, NULL, NULL, // to 8888 758 // RGB 759 NULL, NULL, NULL, NULL, // to A8 760 NULL, NULL, NULL, NULL, // to Index8 761 Sample_RGBx_D565, Sample_RGBx_D565_D, Sample_RGBx_D565, Sample_RGBx_D565_D, // to 565 762 Sample_RGBx_D4444, Sample_RGBx_D4444_D, Sample_RGBx_D4444, Sample_RGBx_D4444_D, // to 4444 763 Sample_RGBx_D8888, Sample_RGBx_D8888, Sample_RGBx_D8888, Sample_RGBx_D8888, // to 8888 764 // RGBx is the same as RGB 765 NULL, NULL, NULL, NULL, // to A8 766 NULL, NULL, NULL, NULL, // to Index8 767 Sample_RGBx_D565, Sample_RGBx_D565_D, Sample_RGBx_D565, Sample_RGBx_D565_D, // to 565 768 Sample_RGBx_D4444, Sample_RGBx_D4444_D, Sample_RGBx_D4444, Sample_RGBx_D4444_D, // to 4444 769 Sample_RGBx_D8888, Sample_RGBx_D8888, Sample_RGBx_D8888, Sample_RGBx_D8888, // to 8888 770 // RGBA 771 NULL, NULL, NULL, NULL, // to A8 772 NULL, NULL, NULL, NULL, // to Index8 773 Sample_RGBx_D565, Sample_RGBx_D565_D, Sample_RGBx_D565, Sample_RGBx_D565_D, // to 565 774 Sample_RGBA_D4444, Sample_RGBA_D4444_D, NULL, NULL, // to 4444 775 Sample_RGBA_D8888, Sample_RGBA_D8888, Sample_RGBA_D8888_Unpremul, Sample_RGBA_D8888_Unpremul, // to 8888 776 // RGB_565 777 NULL, NULL, NULL, NULL, // to A8 778 NULL, NULL, NULL, NULL, // to Index8 779 Sample_D565_D565, Sample_D565_D565, Sample_D565_D565, Sample_D565_D565, // to 565 780 NULL, NULL, NULL, NULL, // to 4444 781 NULL, NULL, NULL, NULL, // to 8888 782}; 783 784// Dummy class that allows instantiation of an ImageDecoder, so begin can query its fields. 785class DummyDecoder : public SkImageDecoder { 786public: 787 DummyDecoder() {} 788protected: 789 virtual bool onDecode(SkStream*, SkBitmap*, SkImageDecoder::Mode) SK_OVERRIDE { 790 return false; 791 } 792}; 793 794void test_row_proc_choice() { 795 SkBitmap dummyBitmap; 796 DummyDecoder dummyDecoder; 797 size_t procCounter = 0; 798 for (int sc = SkScaledBitmapSampler::kGray; sc <= SkScaledBitmapSampler::kRGB_565; ++sc) { 799 for (int c = SkBitmap::kA8_Config; c <= SkBitmap::kARGB_8888_Config; ++c) { 800 for (int unpremul = 0; unpremul <= 1; ++unpremul) { 801 for (int dither = 0; dither <= 1; ++dither) { 802 // Arbitrary width/height/sampleSize to allow SkScaledBitmapSampler to 803 // be considered valid. 804 SkScaledBitmapSampler sampler(10, 10, 1); 805 dummyBitmap.setConfig((SkBitmap::Config) c, 10, 10); 806 dummyDecoder.setDitherImage(SkToBool(dither)); 807 dummyDecoder.setRequireUnpremultipliedColors(SkToBool(unpremul)); 808 sampler.begin(&dummyBitmap, (SkScaledBitmapSampler::SrcConfig) sc, 809 dummyDecoder); 810 SkScaledBitmapSampler::RowProc expected = gTestProcs[procCounter]; 811 SkScaledBitmapSampler::RowProc actual = RowProcTester::getRowProc(sampler); 812 SkASSERT(expected == actual); 813 procCounter++; 814 } 815 } 816 } 817 } 818 SkASSERT(SK_ARRAY_COUNT(gTestProcs) == procCounter); 819} 820#endif // SK_DEBUG 821