| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2010 The Android Open Source Project | 2 * Copyright 2010 The Android Open Source Project |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
| 5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
| 6 */ | 6 */ |
| 7 | 7 |
| 8 #include "SkPDFImage.h" | 8 #include "SkPDFImage.h" |
| 9 | 9 |
| 10 #include "SkBitmap.h" | 10 #include "SkBitmap.h" |
| (...skipping 318 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 329 SkColor color = SkUnPreMultiply::PMColorToColor((*table)[i]); | 329 SkColor color = SkUnPreMultiply::PMColorToColor((*table)[i]); |
| 330 buf[0] = SkGetPackedR32(color); | 330 buf[0] = SkGetPackedR32(color); |
| 331 buf[1] = SkGetPackedG32(color); | 331 buf[1] = SkGetPackedG32(color); |
| 332 buf[2] = SkGetPackedB32(color); | 332 buf[2] = SkGetPackedB32(color); |
| 333 index.append(buf, 3); | 333 index.append(buf, 3); |
| 334 } | 334 } |
| 335 result->append(new SkPDFString(index))->unref(); | 335 result->append(new SkPDFString(index))->unref(); |
| 336 return result; | 336 return result; |
| 337 } | 337 } |
| 338 | 338 |
| 339 /** | |
| 340 * Removes the alpha component of an ARGB color (including unpremultiply) while | |
| 341 * keeping the output in the same format as the input. | |
| 342 */ | |
| 343 static uint32_t remove_alpha_argb8888(uint32_t pmColor) { | |
| 344 SkColor color = SkUnPreMultiply::PMColorToColor(pmColor); | |
| 345 return SkPackARGB32NoCheck(SK_AlphaOPAQUE, | |
| 346 SkColorGetR(color), | |
| 347 SkColorGetG(color), | |
| 348 SkColorGetB(color)); | |
| 349 } | |
| 350 | |
| 351 static uint16_t remove_alpha_argb4444(uint16_t pmColor) { | |
| 352 return SkPixel32ToPixel4444( | |
| 353 remove_alpha_argb8888(SkPixel4444ToPixel32(pmColor))); | |
| 354 } | |
| 355 | |
| 356 static uint32_t get_argb8888_neighbor_avg_color(const SkBitmap& bitmap, | |
| 357 int xOrig, int yOrig) { | |
| 358 uint8_t count = 0; | |
| 359 uint16_t r = 0; | |
| 360 uint16_t g = 0; | |
| 361 uint16_t b = 0; | |
| 362 | |
| 363 for (int y = yOrig - 1; y <= yOrig + 1; y++) { | |
| 364 if (y < 0 || y >= bitmap.height()) { | |
| 365 continue; | |
| 366 } | |
| 367 uint32_t* src = bitmap.getAddr32(0, y); | |
| 368 for (int x = xOrig - 1; x <= xOrig + 1; x++) { | |
| 369 if (x < 0 || x >= bitmap.width()) { | |
| 370 continue; | |
| 371 } | |
| 372 if (SkGetPackedA32(src[x]) != SK_AlphaTRANSPARENT) { | |
| 373 uint32_t color = remove_alpha_argb8888(src[x]); | |
| 374 r += SkGetPackedR32(color); | |
| 375 g += SkGetPackedG32(color); | |
| 376 b += SkGetPackedB32(color); | |
| 377 count++; | |
| 378 } | |
| 379 } | |
| 380 } | |
| 381 | |
| 382 if (count == 0) { | |
| 383 return SkPackARGB32NoCheck(SK_AlphaOPAQUE, 0, 0, 0); | |
| 384 } else { | |
| 385 return SkPackARGB32NoCheck(SK_AlphaOPAQUE, | |
| 386 r / count, g / count, b / count); | |
| 387 } | |
| 388 } | |
| 389 | |
| 390 static uint16_t get_argb4444_neighbor_avg_color(const SkBitmap& bitmap, | |
| 391 int xOrig, int yOrig) { | |
| 392 uint8_t count = 0; | |
| 393 uint8_t r = 0; | |
| 394 uint8_t g = 0; | |
| 395 uint8_t b = 0; | |
| 396 | |
| 397 for (int y = yOrig - 1; y <= yOrig + 1; y++) { | |
| 398 if (y < 0 || y >= bitmap.height()) { | |
| 399 continue; | |
| 400 } | |
| 401 uint16_t* src = bitmap.getAddr16(0, y); | |
| 402 for (int x = xOrig - 1; x <= xOrig + 1; x++) { | |
| 403 if (x < 0 || x >= bitmap.width()) { | |
| 404 continue; | |
| 405 } | |
| 406 if ((SkGetPackedA4444(src[x]) & 0x0F) != SK_AlphaTRANSPARENT) { | |
| 407 uint16_t color = remove_alpha_argb4444(src[x]); | |
| 408 r += SkGetPackedR4444(color); | |
| 409 g += SkGetPackedG4444(color); | |
| 410 b += SkGetPackedB4444(color); | |
| 411 count++; | |
| 412 } | |
| 413 } | |
| 414 } | |
| 415 | |
| 416 if (count == 0) { | |
| 417 return SkPackARGB4444(SK_AlphaOPAQUE & 0x0F, 0, 0, 0); | |
| 418 } else { | |
| 419 return SkPackARGB4444(SK_AlphaOPAQUE & 0x0F, | |
| 420 r / count, g / count, b / count); | |
| 421 } | |
| 422 } | |
| 423 | |
| 424 static SkBitmap unpremultiply_bitmap(const SkBitmap& bitmap, | |
| 425 const SkIRect& srcRect) { | |
| 426 SkBitmap outBitmap; | |
| 427 outBitmap.setConfig(bitmap.config(), srcRect.width(), srcRect.height()); | |
| 428 SkASSERT(outBitmap.allocPixels()); | |
| 429 size_t dstRow = 0; | |
| 430 | |
| 431 outBitmap.lockPixels(); | |
| 432 bitmap.lockPixels(); | |
| 433 switch (bitmap.config()) { | |
| 434 case SkBitmap::kARGB_4444_Config: { | |
| 435 for (int y = srcRect.fTop; y < srcRect.fBottom; y++) { | |
| 436 uint16_t* dst = outBitmap.getAddr16(0, dstRow); | |
| 437 uint16_t* src = bitmap.getAddr16(0, y); | |
| 438 for (int x = srcRect.fLeft; x < srcRect.fRight; x++) { | |
| 439 uint8_t a = SkGetPackedA4444(src[x]); | |
| 440 // It is necessary to average the color component of | |
| 441 // transparent pixels with their surrounding neighbors | |
| 442 // since the PDF renderer may separately re-sample the | |
| 443 // alpha and color channels when the image is not | |
| 444 // displayed at its native resolution. Since an alpha of | |
| 445 // zero gives no information about the color component, | |
| 446 // the pathological case is a white image with sharp | |
| 447 // transparency bounds - the color channel goes to black, | |
| 448 // and the should-be-transparent pixels are rendered | |
| 449 // as grey because of the separate soft mask and color | |
| 450 // resizing. | |
| 451 if (a == (SK_AlphaTRANSPARENT & 0x0F)) { | |
| 452 *dst = get_argb4444_neighbor_avg_color(bitmap, x, y); | |
| 453 } else { | |
| 454 *dst = remove_alpha_argb4444(src[x]); | |
| 455 } | |
| 456 dst++; | |
| 457 } | |
| 458 dstRow++; | |
| 459 } | |
| 460 break; | |
| 461 } | |
| 462 case SkBitmap::kARGB_8888_Config: { | |
| 463 for (int y = srcRect.fTop; y < srcRect.fBottom; y++) { | |
| 464 uint32_t* dst = outBitmap.getAddr32(0, dstRow); | |
| 465 uint32_t* src = bitmap.getAddr32(0, y); | |
| 466 for (int x = srcRect.fLeft; x < srcRect.fRight; x++) { | |
| 467 uint8_t a = SkGetPackedA32(src[x]); | |
| 468 if (a == SK_AlphaTRANSPARENT) { | |
| 469 *dst = get_argb8888_neighbor_avg_color(bitmap, x, y); | |
| 470 } else { | |
| 471 *dst = remove_alpha_argb8888(src[x]); | |
| 472 } | |
| 473 dst++; | |
| 474 } | |
| 475 dstRow++; | |
| 476 } | |
| 477 break; | |
| 478 } | |
| 479 default: | |
| 480 SkASSERT(false); | |
| 481 } | |
| 482 bitmap.unlockPixels(); | |
| 483 outBitmap.unlockPixels(); | |
| 484 | |
| 485 outBitmap.setImmutable(); | |
| 486 | |
| 487 return outBitmap; | |
| 488 } | |
| 489 | |
| 490 // static | 339 // static |
| 491 SkPDFImage* SkPDFImage::CreateImage(const SkBitmap& bitmap, | 340 SkPDFImage* SkPDFImage::CreateImage(const SkBitmap& bitmap, |
| 492 const SkIRect& srcRect, | 341 const SkIRect& srcRect, |
| 493 SkPicture::EncodeBitmap encoder) { | 342 SkPicture::EncodeBitmap encoder) { |
| 494 if (bitmap.getConfig() == SkBitmap::kNo_Config) { | 343 if (bitmap.getConfig() == SkBitmap::kNo_Config) { |
| 495 return NULL; | 344 return NULL; |
| 496 } | 345 } |
| 497 | 346 |
| 498 bool isTransparent = false; | 347 bool isTransparent = false; |
| 499 SkAutoTUnref<SkStream> alphaData; | 348 SkAutoTUnref<SkStream> alphaData; |
| 500 if (!bitmap.isOpaque()) { | 349 if (!bitmap.isOpaque()) { |
| 501 // Note that isOpaque is not guaranteed to return false for bitmaps | 350 // Note that isOpaque is not guaranteed to return false for bitmaps |
| 502 // with alpha support but a completely opaque alpha channel, | 351 // with alpha support but a completely opaque alpha channel, |
| 503 // so alphaData may still be NULL if we have a completely opaque | 352 // so alphaData may still be NULL if we have a completely opaque |
| 504 // (or transparent) bitmap. | 353 // (or transparent) bitmap. |
| 505 alphaData.reset( | 354 alphaData.reset( |
| 506 extract_image_data(bitmap, srcRect, true, &isTransparent)); | 355 extract_image_data(bitmap, srcRect, true, &isTransparent)); |
| 507 } | 356 } |
| 508 if (isTransparent) { | 357 if (isTransparent) { |
| 509 return NULL; | 358 return NULL; |
| 510 } | 359 } |
| 511 | 360 |
| 512 SkPDFImage* image; | 361 SkPDFImage* image = SkNEW_ARGS(SkPDFImage, (NULL, bitmap, |
| 513 SkBitmap::Config config = bitmap.config(); | 362 false, srcRect, encoder)); |
| 514 if (alphaData.get() != NULL && (config == SkBitmap::kARGB_8888_Config || | |
| 515 config == SkBitmap::kARGB_4444_Config)) { | |
| 516 SkBitmap unpremulBitmap = unpremultiply_bitmap(bitmap, srcRect); | |
| 517 image = SkNEW_ARGS(SkPDFImage, (NULL, unpremulBitmap, false, | |
| 518 SkIRect::MakeWH(srcRect.width(), srcRect.height()), | |
| 519 encoder)); | |
| 520 } else { | |
| 521 image = SkNEW_ARGS(SkPDFImage, (NULL, bitmap, false, srcRect, encoder)); | |
| 522 } | |
| 523 if (alphaData.get() != NULL) { | 363 if (alphaData.get() != NULL) { |
| 524 SkAutoTUnref<SkPDFImage> mask( | 364 SkAutoTUnref<SkPDFImage> mask( |
| 525 SkNEW_ARGS(SkPDFImage, (alphaData.get(), bitmap, | 365 SkNEW_ARGS(SkPDFImage, (alphaData.get(), bitmap, |
| 526 true, srcRect, NULL))); | 366 true, srcRect, NULL))); |
| 527 image->addSMask(mask); | 367 image->addSMask(mask); |
| 528 } | 368 } |
| 529 | 369 |
| 530 return image; | 370 return image; |
| 531 } | 371 } |
| 532 | 372 |
| (...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 680 // but the new catalog wants it compressed. | 520 // but the new catalog wants it compressed. |
| 681 if (!getSubstitute()) { | 521 if (!getSubstitute()) { |
| 682 SkPDFStream* substitute = SkNEW_ARGS(SkPDFImage, (*this)); | 522 SkPDFStream* substitute = SkNEW_ARGS(SkPDFImage, (*this)); |
| 683 setSubstitute(substitute); | 523 setSubstitute(substitute); |
| 684 catalog->setSubstitute(this, substitute); | 524 catalog->setSubstitute(this, substitute); |
| 685 } | 525 } |
| 686 return false; | 526 return false; |
| 687 } | 527 } |
| 688 return true; | 528 return true; |
| 689 } | 529 } |
| OLD | NEW |