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