OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2006 The Android Open Source Project | 2 * Copyright 2006 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 "SkImageDecoder.h" | 8 #include "SkImageDecoder.h" |
9 #include "SkImageEncoder.h" | 9 #include "SkImageEncoder.h" |
10 #include "SkColor.h" | 10 #include "SkColor.h" |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
93 #endif | 93 #endif |
94 virtual bool onDecode(SkStream* stream, SkBitmap* bm, Mode) SK_OVERRIDE; | 94 virtual bool onDecode(SkStream* stream, SkBitmap* bm, Mode) SK_OVERRIDE; |
95 | 95 |
96 private: | 96 private: |
97 SkPNGImageIndex* fImageIndex; | 97 SkPNGImageIndex* fImageIndex; |
98 | 98 |
99 bool onDecodeInit(SkStream* stream, png_structp *png_ptrp, png_infop *info_p
trp); | 99 bool onDecodeInit(SkStream* stream, png_structp *png_ptrp, png_infop *info_p
trp); |
100 bool decodePalette(png_structp png_ptr, png_infop info_ptr, | 100 bool decodePalette(png_structp png_ptr, png_infop info_ptr, |
101 bool * SK_RESTRICT hasAlphap, bool *reallyHasAlphap, | 101 bool * SK_RESTRICT hasAlphap, bool *reallyHasAlphap, |
102 SkColorTable **colorTablep); | 102 SkColorTable **colorTablep); |
103 bool getBitmapConfig(png_structp, png_infop, SkColorType*, bool* hasAlpha, | 103 bool getBitmapColorType(png_structp, png_infop, SkColorType*, bool* hasAlpha
, |
104 SkPMColor* theTranspColor); | 104 SkPMColor* theTranspColor); |
105 | 105 |
106 typedef SkImageDecoder INHERITED; | 106 typedef SkImageDecoder INHERITED; |
107 }; | 107 }; |
108 | 108 |
109 #ifndef png_jmpbuf | 109 #ifndef png_jmpbuf |
110 # define png_jmpbuf(png_ptr) ((png_ptr)->jmpbuf) | 110 # define png_jmpbuf(png_ptr) ((png_ptr)->jmpbuf) |
111 #endif | 111 #endif |
112 | 112 |
113 #define PNG_BYTES_TO_CHECK 4 | 113 #define PNG_BYTES_TO_CHECK 4 |
114 | 114 |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
159 uint8_t* tmp = storage; | 159 uint8_t* tmp = storage; |
160 png_read_rows(png_ptr, &tmp, png_bytepp_NULL, 1); | 160 png_read_rows(png_ptr, &tmp, png_bytepp_NULL, 1); |
161 } | 161 } |
162 } | 162 } |
163 | 163 |
164 static bool pos_le(int value, int max) { | 164 static bool pos_le(int value, int max) { |
165 return value > 0 && value <= max; | 165 return value > 0 && value <= max; |
166 } | 166 } |
167 | 167 |
168 static bool substituteTranspColor(SkBitmap* bm, SkPMColor match) { | 168 static bool substituteTranspColor(SkBitmap* bm, SkPMColor match) { |
169 SkASSERT(bm->config() == SkBitmap::kARGB_8888_Config); | 169 SkASSERT(bm->colorType() == kN32_SkColorType); |
170 | 170 |
171 bool reallyHasAlpha = false; | 171 bool reallyHasAlpha = false; |
172 | 172 |
173 for (int y = bm->height() - 1; y >= 0; --y) { | 173 for (int y = bm->height() - 1; y >= 0; --y) { |
174 SkPMColor* p = bm->getAddr32(0, y); | 174 SkPMColor* p = bm->getAddr32(0, y); |
175 for (int x = bm->width() - 1; x >= 0; --x) { | 175 for (int x = bm->width() - 1; x >= 0; --x) { |
176 if (match == *p) { | 176 if (match == *p) { |
177 *p = 0; | 177 *p = 0; |
178 reallyHasAlpha = true; | 178 reallyHasAlpha = true; |
179 } | 179 } |
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
314 | 314 |
315 png_uint_32 origWidth, origHeight; | 315 png_uint_32 origWidth, origHeight; |
316 int bitDepth, pngColorType, interlaceType; | 316 int bitDepth, pngColorType, interlaceType; |
317 png_get_IHDR(png_ptr, info_ptr, &origWidth, &origHeight, &bitDepth, | 317 png_get_IHDR(png_ptr, info_ptr, &origWidth, &origHeight, &bitDepth, |
318 &pngColorType, &interlaceType, int_p_NULL, int_p_NULL); | 318 &pngColorType, &interlaceType, int_p_NULL, int_p_NULL); |
319 | 319 |
320 SkColorType colorType; | 320 SkColorType colorType; |
321 bool hasAlpha = false; | 321 bool hasAlpha = false; |
322 SkPMColor theTranspColor = 0; // 0 tells us not to try to match | 322 SkPMColor theTranspColor = 0; // 0 tells us not to try to match |
323 | 323 |
324 if (!this->getBitmapConfig(png_ptr, info_ptr, &colorType, &hasAlpha, &theTra
nspColor)) { | 324 if (!this->getBitmapColorType(png_ptr, info_ptr, &colorType, &hasAlpha, &the
TranspColor)) { |
325 return false; | 325 return false; |
326 } | 326 } |
327 | 327 |
328 SkAlphaType alphaType = this->getRequireUnpremultipliedColors() ? | 328 SkAlphaType alphaType = this->getRequireUnpremultipliedColors() ? |
329 kUnpremul_SkAlphaType : kPremul_SkAlphaType; | 329 kUnpremul_SkAlphaType : kPremul_SkAlphaType; |
330 const int sampleSize = this->getSampleSize(); | 330 const int sampleSize = this->getSampleSize(); |
331 SkScaledBitmapSampler sampler(origWidth, origHeight, sampleSize); | 331 SkScaledBitmapSampler sampler(origWidth, origHeight, sampleSize); |
332 decodedBitmap->setInfo(SkImageInfo::Make(sampler.scaledWidth(), sampler.scal
edHeight(), | 332 decodedBitmap->setInfo(SkImageInfo::Make(sampler.scaledWidth(), sampler.scal
edHeight(), |
333 colorType, alphaType)); | 333 colorType, alphaType)); |
334 | 334 |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
455 } | 455 } |
456 } | 456 } |
457 | 457 |
458 /* read rest of file, and get additional chunks in info_ptr - REQUIRED */ | 458 /* read rest of file, and get additional chunks in info_ptr - REQUIRED */ |
459 png_read_end(png_ptr, info_ptr); | 459 png_read_end(png_ptr, info_ptr); |
460 | 460 |
461 if (0 != theTranspColor) { | 461 if (0 != theTranspColor) { |
462 reallyHasAlpha |= substituteTranspColor(decodedBitmap, theTranspColor); | 462 reallyHasAlpha |= substituteTranspColor(decodedBitmap, theTranspColor); |
463 } | 463 } |
464 if (reallyHasAlpha && this->getRequireUnpremultipliedColors()) { | 464 if (reallyHasAlpha && this->getRequireUnpremultipliedColors()) { |
465 switch (decodedBitmap->config()) { | 465 switch (decodedBitmap->colorType()) { |
466 case SkBitmap::kIndex8_Config: | 466 case kIndex_8_SkColorType: |
467 // Fall through. | 467 // Fall through. |
468 case SkBitmap::kARGB_4444_Config: | 468 case kARGB_4444_SkColorType: |
469 // We have chosen not to support unpremul for these configs. | 469 // We have chosen not to support unpremul for these colortypes. |
470 return false; | 470 return false; |
471 default: { | 471 default: { |
472 // Fall through to finish the decode. This config either | 472 // Fall through to finish the decode. This colortype either |
473 // supports unpremul or it is irrelevant because it has no | 473 // supports unpremul or it is irrelevant because it has no |
474 // alpha (or only alpha). | 474 // alpha (or only alpha). |
475 // These brackets prevent a warning. | 475 // These brackets prevent a warning. |
476 } | 476 } |
477 } | 477 } |
478 } | 478 } |
479 | 479 |
480 if (!reallyHasAlpha) { | 480 if (!reallyHasAlpha) { |
481 decodedBitmap->setAlphaType(kOpaque_SkAlphaType); | 481 decodedBitmap->setAlphaType(kOpaque_SkAlphaType); |
482 } | 482 } |
483 return true; | 483 return true; |
484 } | 484 } |
485 | 485 |
486 | 486 |
487 | 487 |
488 bool SkPNGImageDecoder::getBitmapConfig(png_structp png_ptr, png_infop info_ptr, | 488 bool SkPNGImageDecoder::getBitmapColorType(png_structp png_ptr, png_infop info_p
tr, |
489 SkColorType* colorTypep, | 489 SkColorType* colorTypep, |
490 bool* hasAlphap, | 490 bool* hasAlphap, |
491 SkPMColor* SK_RESTRICT theTranspColorp)
{ | 491 SkPMColor* SK_RESTRICT theTranspColor
p) { |
492 png_uint_32 origWidth, origHeight; | 492 png_uint_32 origWidth, origHeight; |
493 int bitDepth, colorType; | 493 int bitDepth, colorType; |
494 png_get_IHDR(png_ptr, info_ptr, &origWidth, &origHeight, &bitDepth, | 494 png_get_IHDR(png_ptr, info_ptr, &origWidth, &origHeight, &bitDepth, |
495 &colorType, int_p_NULL, int_p_NULL, int_p_NULL); | 495 &colorType, int_p_NULL, int_p_NULL, int_p_NULL); |
496 | 496 |
497 // check for sBIT chunk data, in case we should disable dithering because | 497 // check for sBIT chunk data, in case we should disable dithering because |
498 // our data is not truely 8bits per component | 498 // our data is not truely 8bits per component |
499 png_color_8p sig_bit; | 499 png_color_8p sig_bit; |
500 if (this->getDitherImage() && png_get_sBIT(png_ptr, info_ptr, &sig_bit)) { | 500 if (this->getDitherImage() && png_get_sBIT(png_ptr, info_ptr, &sig_bit)) { |
501 #if 0 | 501 #if 0 |
502 SkDebugf("----- sBIT %d %d %d %d\n", sig_bit->red, sig_bit->green, | 502 SkDebugf("----- sBIT %d %d %d %d\n", sig_bit->red, sig_bit->green, |
503 sig_bit->blue, sig_bit->alpha); | 503 sig_bit->blue, sig_bit->alpha); |
504 #endif | 504 #endif |
505 // 0 seems to indicate no information available | 505 // 0 seems to indicate no information available |
506 if (pos_le(sig_bit->red, SK_R16_BITS) && | 506 if (pos_le(sig_bit->red, SK_R16_BITS) && |
507 pos_le(sig_bit->green, SK_G16_BITS) && | 507 pos_le(sig_bit->green, SK_G16_BITS) && |
508 pos_le(sig_bit->blue, SK_B16_BITS)) { | 508 pos_le(sig_bit->blue, SK_B16_BITS)) { |
509 this->setDitherImage(false); | 509 this->setDitherImage(false); |
510 } | 510 } |
511 } | 511 } |
512 | 512 |
513 if (colorType == PNG_COLOR_TYPE_PALETTE) { | 513 if (colorType == PNG_COLOR_TYPE_PALETTE) { |
514 bool paletteHasAlpha = hasTransparencyInPalette(png_ptr, info_ptr); | 514 bool paletteHasAlpha = hasTransparencyInPalette(png_ptr, info_ptr); |
515 *colorTypep = this->getPrefColorType(kIndex_SrcDepth, paletteHasAlpha); | 515 *colorTypep = this->getPrefColorType(kIndex_SrcDepth, paletteHasAlpha); |
516 // now see if we can upscale to their requested config | 516 // now see if we can upscale to their requested colortype |
517 if (!canUpscalePaletteToConfig(*colorTypep, paletteHasAlpha)) { | 517 if (!canUpscalePaletteToConfig(*colorTypep, paletteHasAlpha)) { |
518 *colorTypep = kIndex_8_SkColorType; | 518 *colorTypep = kIndex_8_SkColorType; |
519 } | 519 } |
520 } else { | 520 } else { |
521 png_color_16p transpColor = NULL; | 521 png_color_16p transpColor = NULL; |
522 int numTransp = 0; | 522 int numTransp = 0; |
523 | 523 |
524 png_get_tRNS(png_ptr, info_ptr, NULL, &numTransp, &transpColor); | 524 png_get_tRNS(png_ptr, info_ptr, NULL, &numTransp, &transpColor); |
525 | 525 |
526 bool valid = png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS); | 526 bool valid = png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS); |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
607 } | 607 } |
608 } | 608 } |
609 | 609 |
610 #ifdef SK_SUPPORT_LEGACY_IMAGEDECODER_CHOOSER | 610 #ifdef SK_SUPPORT_LEGACY_IMAGEDECODER_CHOOSER |
611 if (!this->chooseFromOneChoice(*colorTypep, origWidth, origHeight)) { | 611 if (!this->chooseFromOneChoice(*colorTypep, origWidth, origHeight)) { |
612 return false; | 612 return false; |
613 } | 613 } |
614 #endif | 614 #endif |
615 | 615 |
616 // If the image has alpha and the decoder wants unpremultiplied | 616 // If the image has alpha and the decoder wants unpremultiplied |
617 // colors, the only supported config is 8888. | 617 // colors, the only supported colortype is 8888. |
618 if (this->getRequireUnpremultipliedColors() && *hasAlphap) { | 618 if (this->getRequireUnpremultipliedColors() && *hasAlphap) { |
619 *colorTypep = kN32_SkColorType; | 619 *colorTypep = kN32_SkColorType; |
620 } | 620 } |
621 | 621 |
622 if (fImageIndex != NULL) { | 622 if (fImageIndex != NULL) { |
623 if (kUnknown_SkColorType == fImageIndex->fColorType) { | 623 if (kUnknown_SkColorType == fImageIndex->fColorType) { |
624 // This is the first time for this subset decode. From now on, | 624 // This is the first time for this subset decode. From now on, |
625 // all decodes must be in the same config. | 625 // all decodes must be in the same colortype. |
626 fImageIndex->fColorType = *colorTypep; | 626 fImageIndex->fColorType = *colorTypep; |
627 } else if (fImageIndex->fColorType != *colorTypep) { | 627 } else if (fImageIndex->fColorType != *colorTypep) { |
628 // Requesting a different colortype for a subsequent decode is not | 628 // Requesting a different colortype for a subsequent decode is not |
629 // supported. Report failure before we make changes to png_ptr. | 629 // supported. Report failure before we make changes to png_ptr. |
630 return false; | 630 return false; |
631 } | 631 } |
632 } | 632 } |
633 | 633 |
634 bool convertGrayToRGB = PNG_COLOR_TYPE_GRAY == colorType && *colorTypep != k
Alpha_8_SkColorType; | 634 bool convertGrayToRGB = PNG_COLOR_TYPE_GRAY == colorType && *colorTypep != k
Alpha_8_SkColorType; |
635 | 635 |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
678 | 678 |
679 // check for bad images that might make us crash | 679 // check for bad images that might make us crash |
680 if (numTrans > numPalette) { | 680 if (numTrans > numPalette) { |
681 numTrans = numPalette; | 681 numTrans = numPalette; |
682 } | 682 } |
683 | 683 |
684 int index = 0; | 684 int index = 0; |
685 int transLessThanFF = 0; | 685 int transLessThanFF = 0; |
686 | 686 |
687 // Choose which function to use to create the color table. If the final dest
ination's | 687 // Choose which function to use to create the color table. If the final dest
ination's |
688 // config is unpremultiplied, the color table will store unpremultiplied col
ors. | 688 // colortype is unpremultiplied, the color table will store unpremultiplied
colors. |
689 PackColorProc proc; | 689 PackColorProc proc; |
690 if (this->getRequireUnpremultipliedColors()) { | 690 if (this->getRequireUnpremultipliedColors()) { |
691 proc = &SkPackARGB32NoCheck; | 691 proc = &SkPackARGB32NoCheck; |
692 } else { | 692 } else { |
693 proc = &SkPreMultiplyARGB; | 693 proc = &SkPreMultiplyARGB; |
694 } | 694 } |
695 for (; index < numTrans; index++) { | 695 for (; index < numTrans; index++) { |
696 transLessThanFF |= (int)*trans - 0xFF; | 696 transLessThanFF |= (int)*trans - 0xFF; |
697 *colorPtr++ = proc(*trans++, palette->red, palette->green, palette->blue
); | 697 *colorPtr++ = proc(*trans++, palette->red, palette->green, palette->blue
); |
698 palette++; | 698 palette++; |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
778 if (!rect.intersect(region)) { | 778 if (!rect.intersect(region)) { |
779 // If the requested region is entirely outside the image, just | 779 // If the requested region is entirely outside the image, just |
780 // returns false | 780 // returns false |
781 return false; | 781 return false; |
782 } | 782 } |
783 | 783 |
784 SkColorType colorType; | 784 SkColorType colorType; |
785 bool hasAlpha = false; | 785 bool hasAlpha = false; |
786 SkPMColor theTranspColor = 0; // 0 tells us not to try to match | 786 SkPMColor theTranspColor = 0; // 0 tells us not to try to match |
787 | 787 |
788 if (!this->getBitmapConfig(png_ptr, info_ptr, &colorType, &hasAlpha, &theTra
nspColor)) { | 788 if (!this->getBitmapColorType(png_ptr, info_ptr, &colorType, &hasAlpha, &the
TranspColor)) { |
789 return false; | 789 return false; |
790 } | 790 } |
791 | 791 |
792 const int sampleSize = this->getSampleSize(); | 792 const int sampleSize = this->getSampleSize(); |
793 SkScaledBitmapSampler sampler(origWidth, rect.height(), sampleSize); | 793 SkScaledBitmapSampler sampler(origWidth, rect.height(), sampleSize); |
794 | 794 |
795 SkBitmap decodedBitmap; | 795 SkBitmap decodedBitmap; |
796 decodedBitmap.setInfo(SkImageInfo::Make(sampler.scaledWidth(), sampler.scale
dHeight(), | 796 decodedBitmap.setInfo(SkImageInfo::Make(sampler.scaledWidth(), sampler.scale
dHeight(), |
797 colorType, kPremul_SkAlphaType)); | 797 colorType, kPremul_SkAlphaType)); |
798 | 798 |
(...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
991 #include "SkColorPriv.h" | 991 #include "SkColorPriv.h" |
992 #include "SkUnPreMultiply.h" | 992 #include "SkUnPreMultiply.h" |
993 | 993 |
994 static void sk_write_fn(png_structp png_ptr, png_bytep data, png_size_t len) { | 994 static void sk_write_fn(png_structp png_ptr, png_bytep data, png_size_t len) { |
995 SkWStream* sk_stream = (SkWStream*)png_get_io_ptr(png_ptr); | 995 SkWStream* sk_stream = (SkWStream*)png_get_io_ptr(png_ptr); |
996 if (!sk_stream->write(data, len)) { | 996 if (!sk_stream->write(data, len)) { |
997 png_error(png_ptr, "sk_write_fn Error!"); | 997 png_error(png_ptr, "sk_write_fn Error!"); |
998 } | 998 } |
999 } | 999 } |
1000 | 1000 |
1001 static transform_scanline_proc choose_proc(SkBitmap::Config config, | 1001 static transform_scanline_proc choose_proc(SkColorType ct, bool hasAlpha) { |
1002 bool hasAlpha) { | |
1003 // we don't care about search on alpha if we're kIndex8, since only the | 1002 // we don't care about search on alpha if we're kIndex8, since only the |
1004 // colortable packing cares about that distinction, not the pixels | 1003 // colortable packing cares about that distinction, not the pixels |
1005 if (SkBitmap::kIndex8_Config == config) { | 1004 if (kIndex_8_SkColorType == ct) { |
1006 hasAlpha = false; // we store false in the table entries for kIndex8 | 1005 hasAlpha = false; // we store false in the table entries for kIndex8 |
1007 } | 1006 } |
1008 | 1007 |
1009 static const struct { | 1008 static const struct { |
1010 SkBitmap::Config fConfig; | 1009 SkColorType fColorType; |
1011 bool fHasAlpha; | 1010 bool fHasAlpha; |
1012 transform_scanline_proc fProc; | 1011 transform_scanline_proc fProc; |
1013 } gMap[] = { | 1012 } gMap[] = { |
1014 { SkBitmap::kRGB_565_Config, false, transform_scanline_565 }, | 1013 { kRGB_565_SkColorType, false, transform_scanline_565 }, |
1015 { SkBitmap::kARGB_8888_Config, false, transform_scanline_888 }, | 1014 { kN32_SkColorType, false, transform_scanline_888 }, |
1016 { SkBitmap::kARGB_8888_Config, true, transform_scanline_8888 }, | 1015 { kN32_SkColorType, true, transform_scanline_8888 }, |
1017 { SkBitmap::kARGB_4444_Config, false, transform_scanline_444 }, | 1016 { kARGB_4444_SkColorType, false, transform_scanline_444 }, |
1018 { SkBitmap::kARGB_4444_Config, true, transform_scanline_4444 }, | 1017 { kARGB_4444_SkColorType, true, transform_scanline_4444 }, |
1019 { SkBitmap::kIndex8_Config, false, transform_scanline_memcpy }, | 1018 { kIndex_8_SkColorType, false, transform_scanline_memcpy }, |
1020 }; | 1019 }; |
1021 | 1020 |
1022 for (int i = SK_ARRAY_COUNT(gMap) - 1; i >= 0; --i) { | 1021 for (int i = SK_ARRAY_COUNT(gMap) - 1; i >= 0; --i) { |
1023 if (gMap[i].fConfig == config && gMap[i].fHasAlpha == hasAlpha) { | 1022 if (gMap[i].fColorType == ct && gMap[i].fHasAlpha == hasAlpha) { |
1024 return gMap[i].fProc; | 1023 return gMap[i].fProc; |
1025 } | 1024 } |
1026 } | 1025 } |
1027 sk_throw(); | 1026 sk_throw(); |
1028 return NULL; | 1027 return NULL; |
1029 } | 1028 } |
1030 | 1029 |
1031 // return the minimum legal bitdepth (by png standards) for this many colortable | 1030 // return the minimum legal bitdepth (by png standards) for this many colortable |
1032 // entries. SkBitmap always stores in 8bits per pixel, but for colorcount <= 16, | 1031 // entries. SkBitmap always stores in 8bits per pixel, but for colorcount <= 16, |
1033 // we can use fewer bits per in png | 1032 // we can use fewer bits per in png |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1100 } | 1099 } |
1101 return num_trans; | 1100 return num_trans; |
1102 } | 1101 } |
1103 | 1102 |
1104 class SkPNGImageEncoder : public SkImageEncoder { | 1103 class SkPNGImageEncoder : public SkImageEncoder { |
1105 protected: | 1104 protected: |
1106 virtual bool onEncode(SkWStream* stream, const SkBitmap& bm, int quality) SK
_OVERRIDE; | 1105 virtual bool onEncode(SkWStream* stream, const SkBitmap& bm, int quality) SK
_OVERRIDE; |
1107 private: | 1106 private: |
1108 bool doEncode(SkWStream* stream, const SkBitmap& bm, | 1107 bool doEncode(SkWStream* stream, const SkBitmap& bm, |
1109 const bool& hasAlpha, int colorType, | 1108 const bool& hasAlpha, int colorType, |
1110 int bitDepth, SkBitmap::Config config, | 1109 int bitDepth, SkColorType ct, |
1111 png_color_8& sig_bit); | 1110 png_color_8& sig_bit); |
1112 | 1111 |
1113 typedef SkImageEncoder INHERITED; | 1112 typedef SkImageEncoder INHERITED; |
1114 }; | 1113 }; |
1115 | 1114 |
1116 bool SkPNGImageEncoder::onEncode(SkWStream* stream, const SkBitmap& bitmap, | 1115 bool SkPNGImageEncoder::onEncode(SkWStream* stream, const SkBitmap& bitmap, int
/*quality*/) { |
1117 int /*quality*/) { | 1116 SkColorType ct = bitmap.colorType(); |
1118 SkBitmap::Config config = bitmap.config(); | |
1119 | 1117 |
1120 const bool hasAlpha = !bitmap.isOpaque(); | 1118 const bool hasAlpha = !bitmap.isOpaque(); |
1121 int colorType = PNG_COLOR_MASK_COLOR; | 1119 int colorType = PNG_COLOR_MASK_COLOR; |
1122 int bitDepth = 8; // default for color | 1120 int bitDepth = 8; // default for color |
1123 png_color_8 sig_bit; | 1121 png_color_8 sig_bit; |
1124 | 1122 |
1125 switch (config) { | 1123 switch (ct) { |
1126 case SkBitmap::kIndex8_Config: | 1124 case kIndex_8_SkColorType: |
1127 colorType |= PNG_COLOR_MASK_PALETTE; | 1125 colorType |= PNG_COLOR_MASK_PALETTE; |
1128 // fall through to the ARGB_8888 case | 1126 // fall through to the ARGB_8888 case |
1129 case SkBitmap::kARGB_8888_Config: | 1127 case kN32_SkColorType: |
1130 sig_bit.red = 8; | 1128 sig_bit.red = 8; |
1131 sig_bit.green = 8; | 1129 sig_bit.green = 8; |
1132 sig_bit.blue = 8; | 1130 sig_bit.blue = 8; |
1133 sig_bit.alpha = 8; | 1131 sig_bit.alpha = 8; |
1134 break; | 1132 break; |
1135 case SkBitmap::kARGB_4444_Config: | 1133 case kARGB_4444_SkColorType: |
1136 sig_bit.red = 4; | 1134 sig_bit.red = 4; |
1137 sig_bit.green = 4; | 1135 sig_bit.green = 4; |
1138 sig_bit.blue = 4; | 1136 sig_bit.blue = 4; |
1139 sig_bit.alpha = 4; | 1137 sig_bit.alpha = 4; |
1140 break; | 1138 break; |
1141 case SkBitmap::kRGB_565_Config: | 1139 case kRGB_565_SkColorType: |
1142 sig_bit.red = 5; | 1140 sig_bit.red = 5; |
1143 sig_bit.green = 6; | 1141 sig_bit.green = 6; |
1144 sig_bit.blue = 5; | 1142 sig_bit.blue = 5; |
1145 sig_bit.alpha = 0; | 1143 sig_bit.alpha = 0; |
1146 break; | 1144 break; |
1147 default: | 1145 default: |
1148 return false; | 1146 return false; |
1149 } | 1147 } |
1150 | 1148 |
1151 if (hasAlpha) { | 1149 if (hasAlpha) { |
(...skipping 14 matching lines...) Expand all Loading... |
1166 // we must do this after we have locked the pixels | 1164 // we must do this after we have locked the pixels |
1167 SkColorTable* ctable = bitmap.getColorTable(); | 1165 SkColorTable* ctable = bitmap.getColorTable(); |
1168 if (NULL != ctable) { | 1166 if (NULL != ctable) { |
1169 if (ctable->count() == 0) { | 1167 if (ctable->count() == 0) { |
1170 return false; | 1168 return false; |
1171 } | 1169 } |
1172 // check if we can store in fewer than 8 bits | 1170 // check if we can store in fewer than 8 bits |
1173 bitDepth = computeBitDepth(ctable->count()); | 1171 bitDepth = computeBitDepth(ctable->count()); |
1174 } | 1172 } |
1175 | 1173 |
1176 return doEncode(stream, bitmap, hasAlpha, colorType, | 1174 return doEncode(stream, bitmap, hasAlpha, colorType, bitDepth, ct, sig_bit); |
1177 bitDepth, config, sig_bit); | |
1178 } | 1175 } |
1179 | 1176 |
1180 bool SkPNGImageEncoder::doEncode(SkWStream* stream, const SkBitmap& bitmap, | 1177 bool SkPNGImageEncoder::doEncode(SkWStream* stream, const SkBitmap& bitmap, |
1181 const bool& hasAlpha, int colorType, | 1178 const bool& hasAlpha, int colorType, |
1182 int bitDepth, SkBitmap::Config config, | 1179 int bitDepth, SkColorType ct, |
1183 png_color_8& sig_bit) { | 1180 png_color_8& sig_bit) { |
1184 | 1181 |
1185 png_structp png_ptr; | 1182 png_structp png_ptr; |
1186 png_infop info_ptr; | 1183 png_infop info_ptr; |
1187 | 1184 |
1188 png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, sk_error_fn, | 1185 png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, sk_error_fn, |
1189 NULL); | 1186 NULL); |
1190 if (NULL == png_ptr) { | 1187 if (NULL == png_ptr) { |
1191 return false; | 1188 return false; |
1192 } | 1189 } |
(...skipping 24 matching lines...) Expand all Loading... |
1217 */ | 1214 */ |
1218 | 1215 |
1219 png_set_IHDR(png_ptr, info_ptr, bitmap.width(), bitmap.height(), | 1216 png_set_IHDR(png_ptr, info_ptr, bitmap.width(), bitmap.height(), |
1220 bitDepth, colorType, | 1217 bitDepth, colorType, |
1221 PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, | 1218 PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, |
1222 PNG_FILTER_TYPE_BASE); | 1219 PNG_FILTER_TYPE_BASE); |
1223 | 1220 |
1224 // set our colortable/trans arrays if needed | 1221 // set our colortable/trans arrays if needed |
1225 png_color paletteColors[256]; | 1222 png_color paletteColors[256]; |
1226 png_byte trans[256]; | 1223 png_byte trans[256]; |
1227 if (SkBitmap::kIndex8_Config == config) { | 1224 if (kIndex_8_SkColorType == ct) { |
1228 SkColorTable* ct = bitmap.getColorTable(); | 1225 SkColorTable* ct = bitmap.getColorTable(); |
1229 int numTrans = pack_palette(ct, paletteColors, trans, hasAlpha); | 1226 int numTrans = pack_palette(ct, paletteColors, trans, hasAlpha); |
1230 png_set_PLTE(png_ptr, info_ptr, paletteColors, ct->count()); | 1227 png_set_PLTE(png_ptr, info_ptr, paletteColors, ct->count()); |
1231 if (numTrans > 0) { | 1228 if (numTrans > 0) { |
1232 png_set_tRNS(png_ptr, info_ptr, trans, numTrans, NULL); | 1229 png_set_tRNS(png_ptr, info_ptr, trans, numTrans, NULL); |
1233 } | 1230 } |
1234 } | 1231 } |
1235 | 1232 |
1236 png_set_sBIT(png_ptr, info_ptr, &sig_bit); | 1233 png_set_sBIT(png_ptr, info_ptr, &sig_bit); |
1237 png_write_info(png_ptr, info_ptr); | 1234 png_write_info(png_ptr, info_ptr); |
1238 | 1235 |
1239 const char* srcImage = (const char*)bitmap.getPixels(); | 1236 const char* srcImage = (const char*)bitmap.getPixels(); |
1240 SkAutoSMalloc<1024> rowStorage(bitmap.width() << 2); | 1237 SkAutoSMalloc<1024> rowStorage(bitmap.width() << 2); |
1241 char* storage = (char*)rowStorage.get(); | 1238 char* storage = (char*)rowStorage.get(); |
1242 transform_scanline_proc proc = choose_proc(config, hasAlpha); | 1239 transform_scanline_proc proc = choose_proc(ct, hasAlpha); |
1243 | 1240 |
1244 for (int y = 0; y < bitmap.height(); y++) { | 1241 for (int y = 0; y < bitmap.height(); y++) { |
1245 png_bytep row_ptr = (png_bytep)storage; | 1242 png_bytep row_ptr = (png_bytep)storage; |
1246 proc(srcImage, bitmap.width(), storage); | 1243 proc(srcImage, bitmap.width(), storage); |
1247 png_write_rows(png_ptr, &row_ptr, 1); | 1244 png_write_rows(png_ptr, &row_ptr, 1); |
1248 srcImage += bitmap.rowBytes(); | 1245 srcImage += bitmap.rowBytes(); |
1249 } | 1246 } |
1250 | 1247 |
1251 png_write_end(png_ptr, info_ptr); | 1248 png_write_end(png_ptr, info_ptr); |
1252 | 1249 |
(...skipping 30 matching lines...) Expand all Loading... |
1283 return SkImageDecoder::kUnknown_Format; | 1280 return SkImageDecoder::kUnknown_Format; |
1284 } | 1281 } |
1285 | 1282 |
1286 SkImageEncoder* sk_libpng_efactory(SkImageEncoder::Type t) { | 1283 SkImageEncoder* sk_libpng_efactory(SkImageEncoder::Type t) { |
1287 return (SkImageEncoder::kPNG_Type == t) ? SkNEW(SkPNGImageEncoder) : NULL; | 1284 return (SkImageEncoder::kPNG_Type == t) ? SkNEW(SkPNGImageEncoder) : NULL; |
1288 } | 1285 } |
1289 | 1286 |
1290 static SkImageDecoder_DecodeReg gDReg(sk_libpng_dfactory); | 1287 static SkImageDecoder_DecodeReg gDReg(sk_libpng_dfactory); |
1291 static SkImageDecoder_FormatReg gFormatReg(get_format_png); | 1288 static SkImageDecoder_FormatReg gFormatReg(get_format_png); |
1292 static SkImageEncoder_EncodeReg gEReg(sk_libpng_efactory); | 1289 static SkImageEncoder_EncodeReg gEReg(sk_libpng_efactory); |
OLD | NEW |