Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(33)

Side by Side Diff: src/images/SkImageDecoder_libpng.cpp

Issue 1014553003: Revert "Indexed PNG decoding: Ensure color table is large enough that the bit depth of the image wi… (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Created 5 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « gyp/tests.gypi ('k') | tests/IndexedPngOverflowTest.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
90 #ifdef SK_BUILD_FOR_ANDROID 90 #ifdef SK_BUILD_FOR_ANDROID
91 bool onBuildTileIndex(SkStreamRewindable *stream, int *width, int *height) S K_OVERRIDE; 91 bool onBuildTileIndex(SkStreamRewindable *stream, int *width, int *height) S K_OVERRIDE;
92 bool onDecodeSubset(SkBitmap* bitmap, const SkIRect& region) SK_OVERRIDE; 92 bool onDecodeSubset(SkBitmap* bitmap, const SkIRect& region) SK_OVERRIDE;
93 #endif 93 #endif
94 Result onDecode(SkStream* stream, SkBitmap* bm, Mode) SK_OVERRIDE; 94 Result 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, int bitDepth, 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 getBitmapColorType(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)
(...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after
343 343
344 // from here down we are concerned with colortables and pixels 344 // from here down we are concerned with colortables and pixels
345 345
346 // we track if we actually see a non-opaque pixels, since sometimes a PNG se ts its colortype 346 // we track if we actually see a non-opaque pixels, since sometimes a PNG se ts its colortype
347 // to |= PNG_COLOR_MASK_ALPHA, but all of its pixels are in fact opaque. We care, since we 347 // to |= PNG_COLOR_MASK_ALPHA, but all of its pixels are in fact opaque. We care, since we
348 // draw lots faster if we can flag the bitmap has being opaque 348 // draw lots faster if we can flag the bitmap has being opaque
349 bool reallyHasAlpha = false; 349 bool reallyHasAlpha = false;
350 SkColorTable* colorTable = NULL; 350 SkColorTable* colorTable = NULL;
351 351
352 if (pngColorType == PNG_COLOR_TYPE_PALETTE) { 352 if (pngColorType == PNG_COLOR_TYPE_PALETTE) {
353 decodePalette(png_ptr, info_ptr, bitDepth, &hasAlpha, &reallyHasAlpha, & colorTable); 353 decodePalette(png_ptr, info_ptr, &hasAlpha, &reallyHasAlpha, &colorTable );
354 } 354 }
355 355
356 SkAutoUnref aur(colorTable); 356 SkAutoUnref aur(colorTable);
357 357
358 if (!this->allocPixelRef(decodedBitmap, 358 if (!this->allocPixelRef(decodedBitmap,
359 kIndex_8_SkColorType == colorType ? colorTable : NU LL)) { 359 kIndex_8_SkColorType == colorType ? colorTable : NU LL)) {
360 return kFailure; 360 return kFailure;
361 } 361 }
362 362
363 SkAutoLockPixels alp(*decodedBitmap); 363 SkAutoLockPixels alp(*decodedBitmap);
(...skipping 286 matching lines...) Expand 10 before | Expand all | Expand 10 after
650 if (colorType == PNG_COLOR_TYPE_RGB || convertGrayToRGB) { 650 if (colorType == PNG_COLOR_TYPE_RGB || convertGrayToRGB) {
651 png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER); 651 png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER);
652 } 652 }
653 653
654 return true; 654 return true;
655 } 655 }
656 656
657 typedef uint32_t (*PackColorProc)(U8CPU a, U8CPU r, U8CPU g, U8CPU b); 657 typedef uint32_t (*PackColorProc)(U8CPU a, U8CPU r, U8CPU g, U8CPU b);
658 658
659 bool SkPNGImageDecoder::decodePalette(png_structp png_ptr, png_infop info_ptr, 659 bool SkPNGImageDecoder::decodePalette(png_structp png_ptr, png_infop info_ptr,
660 int bitDepth, bool *hasAlphap, 660 bool *hasAlphap, bool *reallyHasAlphap,
661 bool *reallyHasAlphap,
662 SkColorTable **colorTablep) { 661 SkColorTable **colorTablep) {
663 int numPalette; 662 int numPalette;
664 png_colorp palette; 663 png_colorp palette;
665 png_bytep trans; 664 png_bytep trans;
666 int numTrans; 665 int numTrans;
667 666
668 png_get_PLTE(png_ptr, info_ptr, &palette, &numPalette); 667 png_get_PLTE(png_ptr, info_ptr, &palette, &numPalette);
669 668
669 /* BUGGY IMAGE WORKAROUND
670
671 We hit some images (e.g. fruit_.png) who contain bytes that are == color table_count
672 which is a problem since we use the byte as an index. To work around thi s we grow
673 the colortable by 1 (if its < 256) and duplicate the last color into tha t slot.
674 */
675 int colorCount = numPalette + (numPalette < 256);
670 SkPMColor colorStorage[256]; // worst-case storage 676 SkPMColor colorStorage[256]; // worst-case storage
671 SkPMColor* colorPtr = colorStorage; 677 SkPMColor* colorPtr = colorStorage;
672 678
673 if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { 679 if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
674 png_get_tRNS(png_ptr, info_ptr, &trans, &numTrans, NULL); 680 png_get_tRNS(png_ptr, info_ptr, &trans, &numTrans, NULL);
675 *hasAlphap = (numTrans > 0); 681 *hasAlphap = (numTrans > 0);
676 } else { 682 } else {
677 numTrans = 0; 683 numTrans = 0;
678 } 684 }
679 685
(...skipping 18 matching lines...) Expand all
698 *colorPtr++ = proc(*trans++, palette->red, palette->green, palette->blue ); 704 *colorPtr++ = proc(*trans++, palette->red, palette->green, palette->blue );
699 palette++; 705 palette++;
700 } 706 }
701 bool reallyHasAlpha = (transLessThanFF < 0); 707 bool reallyHasAlpha = (transLessThanFF < 0);
702 708
703 for (; index < numPalette; index++) { 709 for (; index < numPalette; index++) {
704 *colorPtr++ = SkPackARGB32(0xFF, palette->red, palette->green, palette-> blue); 710 *colorPtr++ = SkPackARGB32(0xFF, palette->red, palette->green, palette-> blue);
705 palette++; 711 palette++;
706 } 712 }
707 713
708 /* BUGGY IMAGE WORKAROUND 714 // see BUGGY IMAGE WORKAROUND comment above
709 715 if (numPalette < 256) {
710 Invalid images could contain pixel values that are greater than the numb er of palette 716 *colorPtr = colorPtr[-1];
711 entries. Since we use pixel values as indices into the palette this coul d result in reading
712 beyond the end of the palette which could leak the contents of uninitial ized memory. To
713 ensure this doesn't happen, we grow the colortable to the maximum size t hat can be
714 addressed by the bitdepth of the image and fill it with the last palette color or black if
715 the palette is empty (really broken image).
716 */
717 int colorCount = SkTMax(numPalette, 1 << SkTMin(bitDepth, 8));
718 SkPMColor lastColor = index > 0 ? colorPtr[-1] : SkPackARGB32(0xFF, 0, 0, 0) ;
719 for (; index < colorCount; index++) {
720 *colorPtr++ = lastColor;
721 } 717 }
722 718
723 *colorTablep = SkNEW_ARGS(SkColorTable, (colorStorage, colorCount)); 719 *colorTablep = SkNEW_ARGS(SkColorTable, (colorStorage, colorCount));
724 *reallyHasAlphap = reallyHasAlpha; 720 *reallyHasAlphap = reallyHasAlpha;
725 return true; 721 return true;
726 } 722 }
727 723
728 #ifdef SK_BUILD_FOR_ANDROID 724 #ifdef SK_BUILD_FOR_ANDROID
729 725
730 bool SkPNGImageDecoder::onBuildTileIndex(SkStreamRewindable* sk_stream, int *wid th, int *height) { 726 bool SkPNGImageDecoder::onBuildTileIndex(SkStreamRewindable* sk_stream, int *wid th, int *height) {
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
800 796
801 // from here down we are concerned with colortables and pixels 797 // from here down we are concerned with colortables and pixels
802 798
803 // we track if we actually see a non-opaque pixels, since sometimes a PNG se ts its colortype 799 // we track if we actually see a non-opaque pixels, since sometimes a PNG se ts its colortype
804 // to |= PNG_COLOR_MASK_ALPHA, but all of its pixels are in fact opaque. We care, since we 800 // to |= PNG_COLOR_MASK_ALPHA, but all of its pixels are in fact opaque. We care, since we
805 // draw lots faster if we can flag the bitmap has being opaque 801 // draw lots faster if we can flag the bitmap has being opaque
806 bool reallyHasAlpha = false; 802 bool reallyHasAlpha = false;
807 SkColorTable* colorTable = NULL; 803 SkColorTable* colorTable = NULL;
808 804
809 if (pngColorType == PNG_COLOR_TYPE_PALETTE) { 805 if (pngColorType == PNG_COLOR_TYPE_PALETTE) {
810 decodePalette(png_ptr, info_ptr, &hasAlpha, &reallyHasAlpha, &colorTable , bitDepth); 806 decodePalette(png_ptr, info_ptr, &hasAlpha, &reallyHasAlpha, &colorTable );
811 } 807 }
812 808
813 SkAutoUnref aur(colorTable); 809 SkAutoUnref aur(colorTable);
814 810
815 // Check ahead of time if the swap(dest, src) is possible. 811 // Check ahead of time if the swap(dest, src) is possible.
816 // If yes, then we will stick to AllocPixelRef since it's cheaper with the s wap happening. 812 // If yes, then we will stick to AllocPixelRef since it's cheaper with the s wap happening.
817 // If no, then we will use alloc to allocate pixels to prevent garbage colle ction. 813 // If no, then we will use alloc to allocate pixels to prevent garbage colle ction.
818 int w = rect.width() / sampleSize; 814 int w = rect.width() / sampleSize;
819 int h = rect.height() / sampleSize; 815 int h = rect.height() / sampleSize;
820 const bool swapOnly = (rect == region) && (w == decodedBitmap.width()) && 816 const bool swapOnly = (rect == region) && (w == decodedBitmap.width()) &&
(...skipping 459 matching lines...) Expand 10 before | Expand all | Expand 10 after
1280 return SkImageDecoder::kUnknown_Format; 1276 return SkImageDecoder::kUnknown_Format;
1281 } 1277 }
1282 1278
1283 SkImageEncoder* sk_libpng_efactory(SkImageEncoder::Type t) { 1279 SkImageEncoder* sk_libpng_efactory(SkImageEncoder::Type t) {
1284 return (SkImageEncoder::kPNG_Type == t) ? SkNEW(SkPNGImageEncoder) : NULL; 1280 return (SkImageEncoder::kPNG_Type == t) ? SkNEW(SkPNGImageEncoder) : NULL;
1285 } 1281 }
1286 1282
1287 static SkImageDecoder_DecodeReg gDReg(sk_libpng_dfactory); 1283 static SkImageDecoder_DecodeReg gDReg(sk_libpng_dfactory);
1288 static SkImageDecoder_FormatReg gFormatReg(get_format_png); 1284 static SkImageDecoder_FormatReg gFormatReg(get_format_png);
1289 static SkImageEncoder_EncodeReg gEReg(sk_libpng_efactory); 1285 static SkImageEncoder_EncodeReg gEReg(sk_libpng_efactory);
OLDNEW
« no previous file with comments | « gyp/tests.gypi ('k') | tests/IndexedPngOverflowTest.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698