OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2010, The Android Open Source Project | 2 * Copyright 2010, The Android Open Source Project |
3 * | 3 * |
4 * Licensed under the Apache License, Version 2.0 (the "License"); | 4 * Licensed under the Apache License, Version 2.0 (the "License"); |
5 * you may not use this file except in compliance with the License. | 5 * you may not use this file except in compliance with the License. |
6 * You may obtain a copy of the License at | 6 * You may obtain a copy of the License at |
7 * | 7 * |
8 * http://www.apache.org/licenses/LICENSE-2.0 | 8 * http://www.apache.org/licenses/LICENSE-2.0 |
9 * | 9 * |
10 * Unless required by applicable law or agreed to in writing, software | 10 * Unless required by applicable law or agreed to in writing, software |
(...skipping 426 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
437 this->shouldPremultiply())) { | 437 this->shouldPremultiply())) { |
438 return false; | 438 return false; |
439 } | 439 } |
440 | 440 |
441 // Decode the WebP image data stream using WebP incremental decoding. | 441 // Decode the WebP image data stream using WebP incremental decoding. |
442 return webp_idecode(stream, &config); | 442 return webp_idecode(stream, &config); |
443 } | 443 } |
444 | 444 |
445 /////////////////////////////////////////////////////////////////////////////// | 445 /////////////////////////////////////////////////////////////////////////////// |
446 | 446 |
| 447 #include "SkUnPreMultiply.h" |
| 448 |
447 typedef void (*ScanlineImporter)(const uint8_t* in, uint8_t* out, int width, | 449 typedef void (*ScanlineImporter)(const uint8_t* in, uint8_t* out, int width, |
448 const SkPMColor* SK_RESTRICT ctable); | 450 const SkPMColor* SK_RESTRICT ctable); |
449 | 451 |
450 static void ARGB_8888_To_RGB(const uint8_t* in, uint8_t* rgb, int width, | 452 static void ARGB_8888_To_RGB(const uint8_t* in, uint8_t* rgb, int width, |
451 const SkPMColor*) { | 453 const SkPMColor*) { |
452 const uint32_t* SK_RESTRICT src = (const uint32_t*)in; | 454 const uint32_t* SK_RESTRICT src = (const uint32_t*)in; |
453 for (int i = 0; i < width; ++i) { | 455 for (int i = 0; i < width; ++i) { |
454 const uint32_t c = *src++; | 456 const uint32_t c = *src++; |
455 rgb[0] = SkGetPackedR32(c); | 457 rgb[0] = SkGetPackedR32(c); |
456 rgb[1] = SkGetPackedG32(c); | 458 rgb[1] = SkGetPackedG32(c); |
457 rgb[2] = SkGetPackedB32(c); | 459 rgb[2] = SkGetPackedB32(c); |
458 rgb += 3; | 460 rgb += 3; |
459 } | 461 } |
460 } | 462 } |
461 | 463 |
| 464 static void ARGB_8888_To_RGBA(const uint8_t* in, uint8_t* rgb, int width, |
| 465 const SkPMColor*) { |
| 466 const uint32_t* SK_RESTRICT src = (const uint32_t*)in; |
| 467 const SkUnPreMultiply::Scale* SK_RESTRICT table = |
| 468 SkUnPreMultiply::GetScaleTable(); |
| 469 for (int i = 0; i < width; ++i) { |
| 470 const uint32_t c = *src++; |
| 471 uint8_t a = SkGetPackedA32(c); |
| 472 uint8_t r = SkGetPackedR32(c); |
| 473 uint8_t g = SkGetPackedG32(c); |
| 474 uint8_t b = SkGetPackedB32(c); |
| 475 if (0 != a && 255 != a) { |
| 476 SkUnPreMultiply::Scale scale = table[a]; |
| 477 r = SkUnPreMultiply::ApplyScale(scale, r); |
| 478 g = SkUnPreMultiply::ApplyScale(scale, g); |
| 479 b = SkUnPreMultiply::ApplyScale(scale, b); |
| 480 } |
| 481 rgb[0] = r; |
| 482 rgb[1] = g; |
| 483 rgb[2] = b; |
| 484 rgb[3] = a; |
| 485 rgb += 4; |
| 486 } |
| 487 } |
| 488 |
462 static void RGB_565_To_RGB(const uint8_t* in, uint8_t* rgb, int width, | 489 static void RGB_565_To_RGB(const uint8_t* in, uint8_t* rgb, int width, |
463 const SkPMColor*) { | 490 const SkPMColor*) { |
464 const uint16_t* SK_RESTRICT src = (const uint16_t*)in; | 491 const uint16_t* SK_RESTRICT src = (const uint16_t*)in; |
465 for (int i = 0; i < width; ++i) { | 492 for (int i = 0; i < width; ++i) { |
466 const uint16_t c = *src++; | 493 const uint16_t c = *src++; |
467 rgb[0] = SkPacked16ToR32(c); | 494 rgb[0] = SkPacked16ToR32(c); |
468 rgb[1] = SkPacked16ToG32(c); | 495 rgb[1] = SkPacked16ToG32(c); |
469 rgb[2] = SkPacked16ToB32(c); | 496 rgb[2] = SkPacked16ToB32(c); |
470 rgb += 3; | 497 rgb += 3; |
471 } | 498 } |
472 } | 499 } |
473 | 500 |
474 static void ARGB_4444_To_RGB(const uint8_t* in, uint8_t* rgb, int width, | 501 static void ARGB_4444_To_RGB(const uint8_t* in, uint8_t* rgb, int width, |
475 const SkPMColor*) { | 502 const SkPMColor*) { |
476 const SkPMColor16* SK_RESTRICT src = (const SkPMColor16*)in; | 503 const SkPMColor16* SK_RESTRICT src = (const SkPMColor16*)in; |
477 for (int i = 0; i < width; ++i) { | 504 for (int i = 0; i < width; ++i) { |
478 const SkPMColor16 c = *src++; | 505 const SkPMColor16 c = *src++; |
479 rgb[0] = SkPacked4444ToR32(c); | 506 rgb[0] = SkPacked4444ToR32(c); |
480 rgb[1] = SkPacked4444ToG32(c); | 507 rgb[1] = SkPacked4444ToG32(c); |
481 rgb[2] = SkPacked4444ToB32(c); | 508 rgb[2] = SkPacked4444ToB32(c); |
482 rgb += 3; | 509 rgb += 3; |
483 } | 510 } |
484 } | 511 } |
485 | 512 |
| 513 static void ARGB_4444_To_RGBA(const uint8_t* in, uint8_t* rgb, int width, |
| 514 const SkPMColor*) { |
| 515 const SkPMColor16* SK_RESTRICT src = (const SkPMColor16*)in; |
| 516 const SkUnPreMultiply::Scale* SK_RESTRICT table = |
| 517 SkUnPreMultiply::GetScaleTable(); |
| 518 for (int i = 0; i < width; ++i) { |
| 519 const SkPMColor16 c = *src++; |
| 520 uint8_t a = SkPacked4444ToA32(c); |
| 521 uint8_t r = SkPacked4444ToR32(c); |
| 522 uint8_t g = SkPacked4444ToG32(c); |
| 523 uint8_t b = SkPacked4444ToB32(c); |
| 524 if (0 != a && 255 != a) { |
| 525 SkUnPreMultiply::Scale scale = table[a]; |
| 526 r = SkUnPreMultiply::ApplyScale(scale, r); |
| 527 g = SkUnPreMultiply::ApplyScale(scale, g); |
| 528 b = SkUnPreMultiply::ApplyScale(scale, b); |
| 529 } |
| 530 rgb[0] = r; |
| 531 rgb[1] = g; |
| 532 rgb[2] = b; |
| 533 rgb[3] = a; |
| 534 rgb += 4; |
| 535 } |
| 536 } |
| 537 |
486 static void Index8_To_RGB(const uint8_t* in, uint8_t* rgb, int width, | 538 static void Index8_To_RGB(const uint8_t* in, uint8_t* rgb, int width, |
487 const SkPMColor* SK_RESTRICT ctable) { | 539 const SkPMColor* SK_RESTRICT ctable) { |
488 const uint8_t* SK_RESTRICT src = (const uint8_t*)in; | 540 const uint8_t* SK_RESTRICT src = (const uint8_t*)in; |
489 for (int i = 0; i < width; ++i) { | 541 for (int i = 0; i < width; ++i) { |
490 const uint32_t c = ctable[*src++]; | 542 const uint32_t c = ctable[*src++]; |
491 rgb[0] = SkGetPackedR32(c); | 543 rgb[0] = SkGetPackedR32(c); |
492 rgb[1] = SkGetPackedG32(c); | 544 rgb[1] = SkGetPackedG32(c); |
493 rgb[2] = SkGetPackedB32(c); | 545 rgb[2] = SkGetPackedB32(c); |
494 rgb += 3; | 546 rgb += 3; |
495 } | 547 } |
496 } | 548 } |
497 | 549 |
498 static ScanlineImporter ChooseImporter(const SkBitmap::Config& config) { | 550 static ScanlineImporter ChooseImporter(const SkBitmap::Config& config, |
| 551 bool hasAlpha, |
| 552 int* bpp) { |
499 switch (config) { | 553 switch (config) { |
500 case SkBitmap::kARGB_8888_Config: | 554 case SkBitmap::kARGB_8888_Config: |
501 return ARGB_8888_To_RGB; | 555 if (hasAlpha) { |
| 556 *bpp = 4; |
| 557 return ARGB_8888_To_RGBA; |
| 558 } else { |
| 559 *bpp = 3; |
| 560 return ARGB_8888_To_RGB; |
| 561 } |
| 562 case SkBitmap::kARGB_4444_Config: |
| 563 if (hasAlpha) { |
| 564 *bpp = 4; |
| 565 return ARGB_4444_To_RGBA; |
| 566 } else { |
| 567 *bpp = 3; |
| 568 return ARGB_4444_To_RGB; |
| 569 } |
502 case SkBitmap::kRGB_565_Config: | 570 case SkBitmap::kRGB_565_Config: |
| 571 *bpp = 3; |
503 return RGB_565_To_RGB; | 572 return RGB_565_To_RGB; |
504 case SkBitmap::kARGB_4444_Config: | |
505 return ARGB_4444_To_RGB; | |
506 case SkBitmap::kIndex8_Config: | 573 case SkBitmap::kIndex8_Config: |
| 574 *bpp = 3; |
507 return Index8_To_RGB; | 575 return Index8_To_RGB; |
508 default: | 576 default: |
509 return NULL; | 577 return NULL; |
510 } | 578 } |
511 } | 579 } |
512 | 580 |
513 static int stream_writer(const uint8_t* data, size_t data_size, | 581 static int stream_writer(const uint8_t* data, size_t data_size, |
514 const WebPPicture* const picture) { | 582 const WebPPicture* const picture) { |
515 SkWStream* const stream = (SkWStream*)picture->custom_ptr; | 583 SkWStream* const stream = (SkWStream*)picture->custom_ptr; |
516 return stream->write(data, data_size) ? 1 : 0; | 584 return stream->write(data, data_size) ? 1 : 0; |
517 } | 585 } |
518 | 586 |
519 class SkWEBPImageEncoder : public SkImageEncoder { | 587 class SkWEBPImageEncoder : public SkImageEncoder { |
520 protected: | 588 protected: |
521 virtual bool onEncode(SkWStream* stream, const SkBitmap& bm, int quality) SK
_OVERRIDE; | 589 virtual bool onEncode(SkWStream* stream, const SkBitmap& bm, int quality) SK
_OVERRIDE; |
522 | 590 |
523 private: | 591 private: |
524 typedef SkImageEncoder INHERITED; | 592 typedef SkImageEncoder INHERITED; |
525 }; | 593 }; |
526 | 594 |
527 bool SkWEBPImageEncoder::onEncode(SkWStream* stream, const SkBitmap& bm, | 595 bool SkWEBPImageEncoder::onEncode(SkWStream* stream, const SkBitmap& bm, |
528 int quality) { | 596 int quality) { |
529 const SkBitmap::Config config = bm.config(); | 597 const SkBitmap::Config config = bm.config(); |
530 const ScanlineImporter scanline_import = ChooseImporter(config); | 598 const bool hasAlpha = !bm.isOpaque(); |
| 599 int bpp = -1; |
| 600 const ScanlineImporter scanline_import = ChooseImporter(config, hasAlpha, |
| 601 &bpp); |
531 if (NULL == scanline_import) { | 602 if (NULL == scanline_import) { |
532 return false; | 603 return false; |
533 } | 604 } |
| 605 if (-1 == bpp) { |
| 606 return false; |
| 607 } |
534 | 608 |
535 SkAutoLockPixels alp(bm); | 609 SkAutoLockPixels alp(bm); |
536 SkAutoLockColors ctLocker; | 610 SkAutoLockColors ctLocker; |
537 if (NULL == bm.getPixels()) { | 611 if (NULL == bm.getPixels()) { |
538 return false; | 612 return false; |
539 } | 613 } |
540 | 614 |
541 WebPConfig webp_config; | 615 WebPConfig webp_config; |
542 if (!WebPConfigPreset(&webp_config, WEBP_PRESET_DEFAULT, (float) quality)) { | 616 if (!WebPConfigPreset(&webp_config, WEBP_PRESET_DEFAULT, (float) quality)) { |
543 return false; | 617 return false; |
544 } | 618 } |
545 | 619 |
546 WebPPicture pic; | 620 WebPPicture pic; |
547 WebPPictureInit(&pic); | 621 WebPPictureInit(&pic); |
548 pic.width = bm.width(); | 622 pic.width = bm.width(); |
549 pic.height = bm.height(); | 623 pic.height = bm.height(); |
550 pic.writer = stream_writer; | 624 pic.writer = stream_writer; |
551 pic.custom_ptr = (void*)stream; | 625 pic.custom_ptr = (void*)stream; |
552 | 626 |
553 const SkPMColor* colors = ctLocker.lockColors(bm); | 627 const SkPMColor* colors = ctLocker.lockColors(bm); |
554 const uint8_t* src = (uint8_t*)bm.getPixels(); | 628 const uint8_t* src = (uint8_t*)bm.getPixels(); |
555 const int rgbStride = pic.width * 3; | 629 const int rgbStride = pic.width * bpp; |
556 | 630 |
557 // Import (for each scanline) the bit-map image (in appropriate color-space) | 631 // Import (for each scanline) the bit-map image (in appropriate color-space) |
558 // to RGB color space. | 632 // to RGB color space. |
559 uint8_t* rgb = new uint8_t[rgbStride * pic.height]; | 633 uint8_t* rgb = new uint8_t[rgbStride * pic.height]; |
560 for (int y = 0; y < pic.height; ++y) { | 634 for (int y = 0; y < pic.height; ++y) { |
561 scanline_import(src + y * bm.rowBytes(), rgb + y * rgbStride, | 635 scanline_import(src + y * bm.rowBytes(), rgb + y * rgbStride, |
562 pic.width, colors); | 636 pic.width, colors); |
563 } | 637 } |
564 | 638 |
565 bool ok = SkToBool(WebPPictureImportRGB(&pic, rgb, rgbStride)); | 639 bool ok; |
| 640 if (bpp == 3) { |
| 641 ok = SkToBool(WebPPictureImportRGB(&pic, rgb, rgbStride)); |
| 642 } else { |
| 643 ok = SkToBool(WebPPictureImportRGBA(&pic, rgb, rgbStride)); |
| 644 } |
566 delete[] rgb; | 645 delete[] rgb; |
567 | 646 |
568 ok = ok && WebPEncode(&webp_config, &pic); | 647 ok = ok && WebPEncode(&webp_config, &pic); |
569 WebPPictureFree(&pic); | 648 WebPPictureFree(&pic); |
570 | 649 |
571 return ok; | 650 return ok; |
572 } | 651 } |
573 | 652 |
574 | 653 |
575 /////////////////////////////////////////////////////////////////////////////// | 654 /////////////////////////////////////////////////////////////////////////////// |
(...skipping 19 matching lines...) Expand all Loading... |
595 return SkImageDecoder::kUnknown_Format; | 674 return SkImageDecoder::kUnknown_Format; |
596 } | 675 } |
597 | 676 |
598 static SkImageEncoder* sk_libwebp_efactory(SkImageEncoder::Type t) { | 677 static SkImageEncoder* sk_libwebp_efactory(SkImageEncoder::Type t) { |
599 return (SkImageEncoder::kWEBP_Type == t) ? SkNEW(SkWEBPImageEncoder) : NUL
L; | 678 return (SkImageEncoder::kWEBP_Type == t) ? SkNEW(SkWEBPImageEncoder) : NUL
L; |
600 } | 679 } |
601 | 680 |
602 static SkImageDecoder_DecodeReg gDReg(sk_libwebp_dfactory); | 681 static SkImageDecoder_DecodeReg gDReg(sk_libwebp_dfactory); |
603 static SkImageDecoder_FormatReg gFormatReg(get_format_webp); | 682 static SkImageDecoder_FormatReg gFormatReg(get_format_webp); |
604 static SkImageEncoder_EncodeReg gEReg(sk_libwebp_efactory); | 683 static SkImageEncoder_EncodeReg gEReg(sk_libwebp_efactory); |
OLD | NEW |