diff options
author | Matt Sarett <msarett@google.com> | 2016-12-14 11:48:31 -0500 |
---|---|---|
committer | Skia Commit-Bot <skia-commit-bot@chromium.org> | 2016-12-14 17:28:35 +0000 |
commit | 7a1cc6766d07f343923587deaf14e1a3965c2b8f (patch) | |
tree | 448f914a9cec02fa0c0ed5f2651975d0d7a6950c /src/codec/SkPngCodec.cpp | |
parent | ff11428526843d3e03feb6843bd21f2d80536415 (diff) |
SkPngCodec: Add support for 16-bit pngs (step 1)
Android plans to use 16-bit png to encode higher precision assets.
This CL should not change any behavior or cause diffs on Gold.
It simply moves the 16-bit -> 8-bit strip from libpng to SkSwizzler.
As a follow-up, I plan to add support for 16-bit input to
SkColorSpaceXform. This will require a new swizzler function that
just samples or subsets 16-bit values (but does not strip to 8-bit).
An alternative implementation could avoid the additional swizzler
functions by deciding whether or not to call png_set_strip() at
decode time (we would still need the swizzler fn to sample/subset
16-bit values). I find this strategy to be cleaner than that.
I would rather handle 16-bit rgb(a) all the time than *some* of
the time. And this is implementation is also more efficient
than libpng. Though it is also more skia code.
Gray and gray alpha are left alone until I know whether anyone
wants high precision gray support.
b/32984164
Change-Id: I44e307473526de3f4bba06879c5fffa25d480f56
Reviewed-on: https://skia-review.googlesource.com/6020
Reviewed-by: Leon Scroggins <scroggo@google.com>
Commit-Queue: Matt Sarett <msarett@google.com>
Diffstat (limited to 'src/codec/SkPngCodec.cpp')
-rw-r--r-- | src/codec/SkPngCodec.cpp | 28 |
1 files changed, 17 insertions, 11 deletions
diff --git a/src/codec/SkPngCodec.cpp b/src/codec/SkPngCodec.cpp index b8576fbc6c..56995801fc 100644 --- a/src/codec/SkPngCodec.cpp +++ b/src/codec/SkPngCodec.cpp @@ -874,17 +874,17 @@ static bool read_header(SkStream* stream, SkPngChunkReader* chunkReader, SkCodec // FIXME (scroggo): Once SK_GOOGLE3_PNG_HACK is no more, this method can be inline in // AutoCleanPng::infoCallback static void general_info_callback(png_structp png_ptr, png_infop info_ptr, - SkEncodedInfo::Color* outColor, SkEncodedInfo::Alpha* outAlpha) { + SkEncodedInfo::Color* outColor, SkEncodedInfo::Alpha* outAlpha, + int* outBitDepth) { png_uint_32 origWidth, origHeight; int bitDepth, encodedColorType; png_get_IHDR(png_ptr, info_ptr, &origWidth, &origHeight, &bitDepth, &encodedColorType, nullptr, nullptr, nullptr); - // Tell libpng to strip 16 bit/color files down to 8 bits/color. - // TODO: Should we handle this in SkSwizzler? Could this also benefit - // RAW decodes? - if (bitDepth == 16) { - SkASSERT(PNG_COLOR_TYPE_PALETTE != encodedColorType); + // TODO: Should we support 16-bits of precision for gray images? + if (bitDepth == 16 && (PNG_COLOR_TYPE_GRAY == encodedColorType || + PNG_COLOR_TYPE_GRAY_ALPHA == encodedColorType)) { + bitDepth = 8; png_set_strip_16(png_ptr); } @@ -899,6 +899,7 @@ static void general_info_callback(png_structp png_ptr, png_infop info_ptr, // byte into separate bytes (useful for paletted and grayscale images). if (bitDepth < 8) { // TODO: Should we use SkSwizzler here? + bitDepth = 8; png_set_packing(png_ptr); } @@ -922,6 +923,7 @@ static void general_info_callback(png_structp png_ptr, png_infop info_ptr, // Expand grayscale images to the full 8 bits from 1, 2, or 4 bits/pixel. if (bitDepth < 8) { // TODO: Should we use SkSwizzler here? + bitDepth = 8; png_set_expand_gray_1_2_4_to_8(png_ptr); } @@ -954,11 +956,14 @@ static void general_info_callback(png_structp png_ptr, png_infop info_ptr, if (outAlpha) { *outAlpha = alpha; } + if (outBitDepth) { + *outBitDepth = bitDepth; + } } #ifdef SK_GOOGLE3_PNG_HACK void SkPngCodec::rereadInfoCallback() { - general_info_callback(fPng_ptr, fInfo_ptr, nullptr, nullptr); + general_info_callback(fPng_ptr, fInfo_ptr, nullptr, nullptr, nullptr); png_set_interlace_handling(fPng_ptr); png_read_update_info(fPng_ptr, fInfo_ptr); } @@ -967,7 +972,8 @@ void SkPngCodec::rereadInfoCallback() { void AutoCleanPng::infoCallback() { SkEncodedInfo::Color color; SkEncodedInfo::Alpha alpha; - general_info_callback(fPng_ptr, fInfo_ptr, &color, &alpha); + int bitDepth; + general_info_callback(fPng_ptr, fInfo_ptr, &color, &alpha, &bitDepth); const int numberPasses = png_set_interlace_handling(fPng_ptr); @@ -990,7 +996,7 @@ void AutoCleanPng::infoCallback() { colorSpace = SkColorSpace::MakeNamed(SkColorSpace::kSRGB_Named); } - SkEncodedInfo encodedInfo = SkEncodedInfo::Make(color, alpha, 8); + SkEncodedInfo encodedInfo = SkEncodedInfo::Make(color, alpha, bitDepth); // FIXME (scroggo): Once we get rid of SK_GOOGLE3_PNG_HACK, general_info_callback can // be inlined, so these values will already be set. png_uint_32 origWidth = png_get_image_width(fPng_ptr, fInfo_ptr); @@ -1072,9 +1078,9 @@ bool SkPngCodec::initializeXforms(const SkImageInfo& dstInfo, const Options& opt return false; } - // If the image is RGBA and we have a color xform, we can skip the swizzler. + // If the image is 32-bit RGBA and we have a color xform, we can skip the swizzler. if (this->colorXform() && SkEncodedInfo::kRGBA_Color == this->getEncodedInfo().color() && - !options.fSubset) + 8 == this->getEncodedInfo().bitsPerComponent() && !options.fSubset) { fXformMode = kColorOnly_XformMode; return true; |