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

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

Issue 948163002: Indexed PNG decoding: Ensure color table is large enough that the bit depth of the image will not a… (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Fixed argument order in some conditional Android code. 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, 100 bool decodePalette(png_structp png_ptr, png_infop info_ptr, int bitDepth,
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, &hasAlpha, &reallyHasAlpha, &colorTable ); 353 decodePalette(png_ptr, info_ptr, bitDepth, &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 280 matching lines...) Expand 10 before | Expand all | Expand 10 after
644 if (colorType == PNG_COLOR_TYPE_RGB || convertGrayToRGB) { 644 if (colorType == PNG_COLOR_TYPE_RGB || convertGrayToRGB) {
645 png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER); 645 png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER);
646 } 646 }
647 647
648 return true; 648 return true;
649 } 649 }
650 650
651 typedef uint32_t (*PackColorProc)(U8CPU a, U8CPU r, U8CPU g, U8CPU b); 651 typedef uint32_t (*PackColorProc)(U8CPU a, U8CPU r, U8CPU g, U8CPU b);
652 652
653 bool SkPNGImageDecoder::decodePalette(png_structp png_ptr, png_infop info_ptr, 653 bool SkPNGImageDecoder::decodePalette(png_structp png_ptr, png_infop info_ptr,
654 bool *hasAlphap, bool *reallyHasAlphap, 654 int bitDepth, bool *hasAlphap,
655 bool *reallyHasAlphap,
655 SkColorTable **colorTablep) { 656 SkColorTable **colorTablep) {
656 int numPalette; 657 int numPalette;
657 png_colorp palette; 658 png_colorp palette;
658 png_bytep trans; 659 png_bytep trans;
659 int numTrans; 660 int numTrans;
660 661
661 png_get_PLTE(png_ptr, info_ptr, &palette, &numPalette); 662 png_get_PLTE(png_ptr, info_ptr, &palette, &numPalette);
662 663
663 /* BUGGY IMAGE WORKAROUND
664
665 We hit some images (e.g. fruit_.png) who contain bytes that are == color table_count
666 which is a problem since we use the byte as an index. To work around thi s we grow
667 the colortable by 1 (if its < 256) and duplicate the last color into tha t slot.
668 */
669 int colorCount = numPalette + (numPalette < 256);
670 SkPMColor colorStorage[256]; // worst-case storage 664 SkPMColor colorStorage[256]; // worst-case storage
671 SkPMColor* colorPtr = colorStorage; 665 SkPMColor* colorPtr = colorStorage;
672 666
673 if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { 667 if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
674 png_get_tRNS(png_ptr, info_ptr, &trans, &numTrans, NULL); 668 png_get_tRNS(png_ptr, info_ptr, &trans, &numTrans, NULL);
675 *hasAlphap = (numTrans > 0); 669 *hasAlphap = (numTrans > 0);
676 } else { 670 } else {
677 numTrans = 0; 671 numTrans = 0;
678 } 672 }
679 673
(...skipping 18 matching lines...) Expand all
698 *colorPtr++ = proc(*trans++, palette->red, palette->green, palette->blue ); 692 *colorPtr++ = proc(*trans++, palette->red, palette->green, palette->blue );
699 palette++; 693 palette++;
700 } 694 }
701 bool reallyHasAlpha = (transLessThanFF < 0); 695 bool reallyHasAlpha = (transLessThanFF < 0);
702 696
703 for (; index < numPalette; index++) { 697 for (; index < numPalette; index++) {
704 *colorPtr++ = SkPackARGB32(0xFF, palette->red, palette->green, palette-> blue); 698 *colorPtr++ = SkPackARGB32(0xFF, palette->red, palette->green, palette-> blue);
705 palette++; 699 palette++;
706 } 700 }
707 701
708 // see BUGGY IMAGE WORKAROUND comment above 702 /* BUGGY IMAGE WORKAROUND
709 if (numPalette < 256) { 703
710 *colorPtr = colorPtr[-1]; 704 Invalid images could contain pixel values that are greater than the numb er of palette
705 entries. Since we use pixel values as indices into the palette this coul d result in reading
706 beyond the end of the palette which could leak the contents of uninitial ized memory. To
707 ensure this doesn't happen, we grow the colortable to the maximum size t hat can be
708 addressed by the bitdepth of the image and fill it with the last palette color or black if
709 the palette is empty (really broken image).
710 */
711 int colorCount = SkTMax(numPalette, 1 << SkTMin(bitDepth, 8));
712 SkPMColor lastColor = index > 0 ? colorPtr[-1] : SkPackARGB32(0xFF, 0, 0, 0) ;
713 for (; index < colorCount; index++) {
714 *colorPtr++ = lastColor;
711 } 715 }
712 716
713 *colorTablep = SkNEW_ARGS(SkColorTable, (colorStorage, colorCount)); 717 *colorTablep = SkNEW_ARGS(SkColorTable, (colorStorage, colorCount));
714 *reallyHasAlphap = reallyHasAlpha; 718 *reallyHasAlphap = reallyHasAlpha;
715 return true; 719 return true;
716 } 720 }
717 721
718 #ifdef SK_BUILD_FOR_ANDROID 722 #ifdef SK_BUILD_FOR_ANDROID
719 723
720 bool SkPNGImageDecoder::onBuildTileIndex(SkStreamRewindable* sk_stream, int *wid th, int *height) { 724 bool SkPNGImageDecoder::onBuildTileIndex(SkStreamRewindable* sk_stream, int *wid th, int *height) {
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
790 794
791 // from here down we are concerned with colortables and pixels 795 // from here down we are concerned with colortables and pixels
792 796
793 // we track if we actually see a non-opaque pixels, since sometimes a PNG se ts its colortype 797 // we track if we actually see a non-opaque pixels, since sometimes a PNG se ts its colortype
794 // to |= PNG_COLOR_MASK_ALPHA, but all of its pixels are in fact opaque. We care, since we 798 // to |= PNG_COLOR_MASK_ALPHA, but all of its pixels are in fact opaque. We care, since we
795 // draw lots faster if we can flag the bitmap has being opaque 799 // draw lots faster if we can flag the bitmap has being opaque
796 bool reallyHasAlpha = false; 800 bool reallyHasAlpha = false;
797 SkColorTable* colorTable = NULL; 801 SkColorTable* colorTable = NULL;
798 802
799 if (pngColorType == PNG_COLOR_TYPE_PALETTE) { 803 if (pngColorType == PNG_COLOR_TYPE_PALETTE) {
800 decodePalette(png_ptr, info_ptr, &hasAlpha, &reallyHasAlpha, &colorTable ); 804 decodePalette(png_ptr, info_ptr, bitDepth, &hasAlpha, &reallyHasAlpha, & colorTable);
801 } 805 }
802 806
803 SkAutoUnref aur(colorTable); 807 SkAutoUnref aur(colorTable);
804 808
805 // Check ahead of time if the swap(dest, src) is possible. 809 // Check ahead of time if the swap(dest, src) is possible.
806 // If yes, then we will stick to AllocPixelRef since it's cheaper with the s wap happening. 810 // If yes, then we will stick to AllocPixelRef since it's cheaper with the s wap happening.
807 // If no, then we will use alloc to allocate pixels to prevent garbage colle ction. 811 // If no, then we will use alloc to allocate pixels to prevent garbage colle ction.
808 int w = rect.width() / sampleSize; 812 int w = rect.width() / sampleSize;
809 int h = rect.height() / sampleSize; 813 int h = rect.height() / sampleSize;
810 const bool swapOnly = (rect == region) && (w == decodedBitmap.width()) && 814 const bool swapOnly = (rect == region) && (w == decodedBitmap.width()) &&
(...skipping 459 matching lines...) Expand 10 before | Expand all | Expand 10 after
1270 return SkImageDecoder::kUnknown_Format; 1274 return SkImageDecoder::kUnknown_Format;
1271 } 1275 }
1272 1276
1273 SkImageEncoder* sk_libpng_efactory(SkImageEncoder::Type t) { 1277 SkImageEncoder* sk_libpng_efactory(SkImageEncoder::Type t) {
1274 return (SkImageEncoder::kPNG_Type == t) ? SkNEW(SkPNGImageEncoder) : NULL; 1278 return (SkImageEncoder::kPNG_Type == t) ? SkNEW(SkPNGImageEncoder) : NULL;
1275 } 1279 }
1276 1280
1277 static SkImageDecoder_DecodeReg gDReg(sk_libpng_dfactory); 1281 static SkImageDecoder_DecodeReg gDReg(sk_libpng_dfactory);
1278 static SkImageDecoder_FormatReg gFormatReg(get_format_png); 1282 static SkImageDecoder_FormatReg gFormatReg(get_format_png);
1279 static SkImageEncoder_EncodeReg gEReg(sk_libpng_efactory); 1283 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