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

Unified Diff: src/codec/SkCodec_libpng.cpp

Issue 1055743003: Swizzler changes Index8 and 565 (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Fix windows errors Created 5 years, 8 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/codec/SkCodec_libpng.h ('k') | src/codec/SkMaskSwizzler.cpp » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/codec/SkCodec_libpng.cpp
diff --git a/src/codec/SkCodec_libpng.cpp b/src/codec/SkCodec_libpng.cpp
index 121b74ff0b3a97defc00a75ed5c2c1cabda5b2e4..250d815f6bf2aecd3204d9eb3dbc070db19166aa 100644
--- a/src/codec/SkCodec_libpng.cpp
+++ b/src/codec/SkCodec_libpng.cpp
@@ -15,6 +15,7 @@
#include "SkSize.h"
#include "SkStream.h"
#include "SkSwizzler.h"
+#include "SkUtils.h"
///////////////////////////////////////////////////////////////////////////////
// Helper macros
@@ -119,7 +120,7 @@ typedef uint32_t (*PackColorProc)(U8CPU a, U8CPU r, U8CPU g, U8CPU b);
// Note: SkColorTable claims to store SkPMColors, which is not necessarily
// the case here.
-bool SkPngCodec::decodePalette(bool premultiply) {
+bool SkPngCodec::decodePalette(bool premultiply, int bitDepth, int* ctableCount) {
int numPalette;
png_colorp palette;
png_bytep trans;
@@ -128,14 +129,7 @@ bool SkPngCodec::decodePalette(bool premultiply) {
return false;
}
- /* BUGGY IMAGE WORKAROUND
-
- We hit some images (e.g. fruit_.png) who contain bytes that are == colortable_count
- which is a problem since we use the byte as an index. To work around this we grow
- the colortable by 1 (if its < 256) and duplicate the last color into that slot.
- */
- const int colorCount = numPalette + (numPalette < 256);
- // Note: These are not necessarily SkPMColors.
+ // Note: These are not necessarily SkPMColors
SkPMColor colorStorage[256]; // worst-case storage
SkPMColor* colorPtr = colorStorage;
@@ -175,9 +169,24 @@ bool SkPngCodec::decodePalette(bool premultiply) {
palette++;
}
- // see BUGGY IMAGE WORKAROUND comment above
- if (numPalette < 256) {
- *colorPtr = colorPtr[-1];
+ /* BUGGY IMAGE WORKAROUND
+ Invalid images could contain pixel values that are greater than the number of palette
+ entries. Since we use pixel values as indices into the palette this could result in reading
+ beyond the end of the palette which could leak the contents of uninitialized memory. To
+ ensure this doesn't happen, we grow the colortable to the maximum size that can be
+ addressed by the bitdepth of the image and fill it with the last palette color or black if
+ the palette is empty (really broken image).
+ */
+ int colorCount = SkTMax(numPalette, 1 << SkTMin(bitDepth, 8));
+ SkPMColor lastColor = index > 0 ? colorPtr[-1] : SkPackARGB32(0xFF, 0, 0, 0);
+ for (; index < colorCount; index++) {
+ *colorPtr++ = lastColor;
+ }
+
+ // Set the new color count
+ if (ctableCount != NULL) {
+ SkASSERT(256 == *ctableCount);
+ *ctableCount = colorCount;
}
fColorTable.reset(SkNEW_ARGS(SkColorTable, (colorStorage, colorCount)));
@@ -276,10 +285,7 @@ static bool read_header(SkStream* stream, png_structp* png_ptrp,
SkAlphaType skAlphaType;
switch (colorType) {
case PNG_COLOR_TYPE_PALETTE:
- // Technically, this is true of the data, but I don't think we want
- // to support it.
- // skColorType = kIndex8_SkColorType;
- skColorType = kN32_SkColorType;
+ skColorType = kIndex_8_SkColorType;
skAlphaType = has_transparency_in_palette(png_ptr, info_ptr) ?
kUnpremul_SkAlphaType : kOpaque_SkAlphaType;
break;
@@ -387,22 +393,43 @@ void SkPngCodec::destroyReadStruct() {
static bool conversion_possible(const SkImageInfo& dst, const SkImageInfo& src) {
// TODO: Support other conversions
- if (dst.colorType() != src.colorType()) {
- return false;
- }
if (dst.profileType() != src.profileType()) {
return false;
}
- if (dst.alphaType() == src.alphaType()) {
- return true;
+
+ // Check for supported alpha types
+ if (src.alphaType() != dst.alphaType()) {
+ if (kOpaque_SkAlphaType == src.alphaType()) {
+ // If the source is opaque, we must decode to opaque
+ return false;
+ }
+
+ // The source is not opaque
+ switch (dst.alphaType()) {
+ case kPremul_SkAlphaType:
+ case kUnpremul_SkAlphaType:
+ // The source is not opaque, so either of these is okay
+ break;
+ default:
+ // We cannot decode a non-opaque image to opaque (or unknown)
+ return false;
+ }
+ }
+
+ // Check for supported color types
+ switch (dst.colorType()) {
+ // Allow output to kN32 from any type of input
+ case kN32_SkColorType:
+ return true;
+ default:
+ return dst.colorType() == src.colorType();
}
- return kPremul_SkAlphaType == dst.alphaType() &&
- kUnpremul_SkAlphaType == src.alphaType();
}
SkCodec::Result SkPngCodec::initializeSwizzler(const SkImageInfo& requestedInfo,
void* dst, size_t rowBytes,
- const Options& options) {
+ const Options& options,
+ int* ctableCount) {
// FIXME: Could we use the return value of setjmp to specify the type of
// error?
if (setjmp(png_jmpbuf(fPng_ptr))) {
@@ -423,7 +450,8 @@ SkCodec::Result SkPngCodec::initializeSwizzler(const SkImageInfo& requestedInfo,
fReallyHasAlpha = false;
if (PNG_COLOR_TYPE_PALETTE == pngColorType) {
fSrcConfig = SkSwizzler::kIndex;
- if (!this->decodePalette(kPremul_SkAlphaType == requestedInfo.alphaType())) {
+ if (!this->decodePalette(kPremul_SkAlphaType == requestedInfo.alphaType(), bitDepth,
+ ctableCount)) {
return kInvalidInput;
}
} else if (kAlpha_8_SkColorType == requestedInfo.colorType()) {
@@ -492,8 +520,18 @@ SkCodec::Result SkPngCodec::onGetPixels(const SkImageInfo& requestedInfo, void*
return kInvalidConversion;
}
+ // Note that ctableCount will be modified if there is a color table
const Result result = this->initializeSwizzler(requestedInfo, dst, rowBytes,
- options);
+ options, ctableCount);
+
+ // Copy the color table to the client if necessary
+ if (kIndex_8_SkColorType == requestedInfo.colorType()) {
+ SkASSERT(NULL != ctable);
+ SkASSERT(NULL != ctableCount);
+ SkASSERT(NULL != fColorTable.get());
+ sk_memcpy32(ctable, fColorTable->readColors(), *ctableCount);
+ }
+
if (result != kSuccess) {
return result;
}
@@ -631,7 +669,9 @@ SkScanlineDecoder* SkPngCodec::onGetScanlineDecoder(const SkImageInfo& dstInfo)
Options opts;
// FIXME: Pass this in to getScanlineDecoder?
opts.fZeroInitialized = kNo_ZeroInitialized;
- if (this->initializeSwizzler(dstInfo, NULL, dstInfo.minRowBytes(), opts) != kSuccess) {
+ // FIXME: onGetScanlineDecoder does not currently have a way to get color table information
+ // for a kIndex8 decoder.
+ if (this->initializeSwizzler(dstInfo, NULL, dstInfo.minRowBytes(), opts, NULL) != kSuccess) {
SkCodecPrintf("failed to initialize the swizzler.\n");
return NULL;
}
« no previous file with comments | « src/codec/SkCodec_libpng.h ('k') | src/codec/SkMaskSwizzler.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698