diff options
author | 2017-01-19 17:14:07 -0500 | |
---|---|---|
committer | 2017-01-19 23:07:13 +0000 | |
commit | 1da27ef853ae3e701b7f4aae670c21684396dcce (patch) | |
tree | 56fb2fed264ab2f3d1d130eac8bce03f4fa430a9 /src/images | |
parent | 0d7d8de00a3ce2e70cf1221392db3d960610ad62 (diff) |
Add F16 support to SkPNGImageEncoder
BUG=skia:
CQ_INCLUDE_TRYBOTS=skia.primary:Test-Ubuntu-GCC-GCE-CPU-AVX2-x86_64-Release-SKNX_NO_SIMD
Change-Id: Ifd221365a7b9f9a4a4fc5382621e0da7189e1148
Reviewed-on: https://skia-review.googlesource.com/6526
Reviewed-by: Mike Klein <mtklein@chromium.org>
Reviewed-by: Leon Scroggins <scroggo@google.com>
Commit-Queue: Matt Sarett <msarett@google.com>
Diffstat (limited to 'src/images')
-rw-r--r-- | src/images/SkPNGImageEncoder.cpp | 68 | ||||
-rw-r--r-- | src/images/transform_scanline.h | 46 |
2 files changed, 86 insertions, 28 deletions
diff --git a/src/images/SkPNGImageEncoder.cpp b/src/images/SkPNGImageEncoder.cpp index 55aead2c04..48aca8bb1e 100644 --- a/src/images/SkPNGImageEncoder.cpp +++ b/src/images/SkPNGImageEncoder.cpp @@ -83,6 +83,17 @@ static transform_scanline_proc choose_proc(const SkImageInfo& info) { case kIndex_8_SkColorType: case kGray_8_SkColorType: return transform_scanline_memcpy; + case kRGBA_F16_SkColorType: + switch (info.alphaType()) { + case kOpaque_SkAlphaType: + case kUnpremul_SkAlphaType: + return transform_scanline_F16; + case kPremul_SkAlphaType: + return transform_scanline_F16_premul; + default: + SkASSERT(false); + return nullptr; + } default: SkASSERT(false); return nullptr; @@ -168,19 +179,8 @@ bool SkEncodeImageAsPNG(SkWStream* stream, const SkPixmap& src, const SkEncodeOp if (!pixmap.addr() || pixmap.info().isEmpty()) { return false; } - const SkColorType colorType = pixmap.colorType(); - switch (colorType) { - case kIndex_8_SkColorType: - case kGray_8_SkColorType: - case kRGBA_8888_SkColorType: - case kBGRA_8888_SkColorType: - case kARGB_4444_SkColorType: - case kRGB_565_SkColorType: - break; - default: - return false; - } + const SkColorType colorType = pixmap.colorType(); const SkAlphaType alphaType = pixmap.alphaType(); switch (alphaType) { case kUnpremul_SkAlphaType: @@ -197,12 +197,23 @@ bool SkEncodeImageAsPNG(SkWStream* stream, const SkPixmap& src, const SkEncodeOp } const bool isOpaque = (kOpaque_SkAlphaType == alphaType); - const int bitDepth = 8; + int bitDepth = 8; png_color_8 sig_bit; sk_bzero(&sig_bit, sizeof(png_color_8)); - int pngColorType; switch (colorType) { + case kRGBA_F16_SkColorType: + if (!pixmap.colorSpace() || !pixmap.colorSpace()->gammaIsLinear()) { + return false; + } + + sig_bit.red = 16; + sig_bit.green = 16; + sig_bit.blue = 16; + sig_bit.alpha = 16; + bitDepth = 16; + pngColorType = isOpaque ? PNG_COLOR_TYPE_RGB : PNG_COLOR_TYPE_RGB_ALPHA; + break; case kIndex_8_SkColorType: sig_bit.red = 8; sig_bit.green = 8; @@ -240,6 +251,7 @@ bool SkEncodeImageAsPNG(SkWStream* stream, const SkPixmap& src, const SkEncodeOp default: return false; } + if (kIndex_8_SkColorType == colorType) { SkColorTable* ctable = pixmap.ctable(); if (!ctable || ctable->count() == 0) { @@ -250,9 +262,25 @@ bool SkEncodeImageAsPNG(SkWStream* stream, const SkPixmap& src, const SkEncodeOp // When ctable->count() <= 16, we could potentially use 1, 2, // or 4 bit indices. } + return do_encode(stream, pixmap, pngColorType, bitDepth, sig_bit); } +static int num_components(int pngColorType) { + switch (pngColorType) { + case PNG_COLOR_TYPE_PALETTE: + case PNG_COLOR_TYPE_GRAY: + return 1; + case PNG_COLOR_TYPE_RGB: + return 3; + case PNG_COLOR_TYPE_RGBA: + return 4; + default: + SkASSERT(false); + return 0; + } +} + static bool do_encode(SkWStream* stream, const SkPixmap& pixmap, int pngColorType, int bitDepth, png_color_8& sig_bit) { png_structp png_ptr; @@ -308,12 +336,18 @@ static bool do_encode(SkWStream* stream, const SkPixmap& pixmap, png_set_sBIT(png_ptr, info_ptr, &sig_bit); png_write_info(png_ptr, info_ptr); + int pngBytesPerPixel = num_components(pngColorType) * (bitDepth / 8); + if (kRGBA_F16_SkColorType == pixmap.colorType() && kOpaque_SkAlphaType == pixmap.alphaType()) { + // For kOpaque, kRGBA_F16, we will keep the row as RGBA and tell libpng + // to skip the alpha channel. + png_set_filler(png_ptr, 0, PNG_FILLER_AFTER); + pngBytesPerPixel = 8; + } - const char* srcImage = (const char*)pixmap.addr(); - SkAutoSTMalloc<1024, char> rowStorage(pixmap.width() << 2); + SkAutoSTMalloc<1024, char> rowStorage(pixmap.width() * pngBytesPerPixel); char* storage = rowStorage.get(); + const char* srcImage = (const char*)pixmap.addr(); transform_scanline_proc proc = choose_proc(pixmap.info()); - for (int y = 0; y < pixmap.height(); y++) { png_bytep row_ptr = (png_bytep)storage; proc(storage, srcImage, pixmap.width(), SkColorTypeBytesPerPixel(pixmap.colorType())); diff --git a/src/images/transform_scanline.h b/src/images/transform_scanline.h index 1ce67cd3a2..1c263487bd 100644 --- a/src/images/transform_scanline.h +++ b/src/images/transform_scanline.h @@ -96,7 +96,7 @@ static void transform_scanline_444(char* SK_RESTRICT dst, const char* SK_RESTRIC template <bool kIsRGBA> static inline void transform_scanline_unpremultiply(char* SK_RESTRICT dst, - const char* SK_RESTRICT src, int width, int) { + const char* SK_RESTRICT src, int width) { const uint32_t* srcP = (const SkPMColor*)src; const SkUnPreMultiply::Scale* table = SkUnPreMultiply::GetScaleTable(); @@ -132,21 +132,20 @@ static inline void transform_scanline_unpremultiply(char* SK_RESTRICT dst, * Transform from legacy kPremul, kRGBA_8888_SkColorType to 4-bytes-per-pixel unpremultiplied RGBA. */ static void transform_scanline_rgbA(char* SK_RESTRICT dst, const char* SK_RESTRICT src, int width, - int bpp) { - transform_scanline_unpremultiply<true>(dst, src, width, bpp); + int) { + transform_scanline_unpremultiply<true>(dst, src, width); } /** * Transform from legacy kPremul, kBGRA_8888_SkColorType to 4-bytes-per-pixel unpremultiplied RGBA. */ static void transform_scanline_bgrA(char* SK_RESTRICT dst, const char* SK_RESTRICT src, int width, - int bpp) { - transform_scanline_unpremultiply<false>(dst, src, width, bpp); + int) { + transform_scanline_unpremultiply<false>(dst, src, width); } template <bool kIsRGBA> -static inline void transform_scanline_unpremultiply_sRGB(void* dst, const void* src, int width, int) -{ +static inline void transform_scanline_unpremultiply_sRGB(void* dst, const void* src, int width) { SkRasterPipeline p; p.append(SkRasterPipeline::load_8888, &src); if (!kIsRGBA) { @@ -164,16 +163,16 @@ static inline void transform_scanline_unpremultiply_sRGB(void* dst, const void* * Transform from kPremul, kRGBA_8888_SkColorType to 4-bytes-per-pixel unpremultiplied RGBA. */ static void transform_scanline_srgbA(char* SK_RESTRICT dst, const char* SK_RESTRICT src, - int width, int bpp) { - transform_scanline_unpremultiply_sRGB<true>(dst, src, width, bpp); + int width, int) { + transform_scanline_unpremultiply_sRGB<true>(dst, src, width); } /** * Transform from kPremul, kBGRA_8888_SkColorType to 4-bytes-per-pixel unpremultiplied RGBA. */ static void transform_scanline_sbgrA(char* SK_RESTRICT dst, const char* SK_RESTRICT src, - int width, int bpp) { - transform_scanline_unpremultiply_sRGB<false>(dst, src, width, bpp); + int width, int) { + transform_scanline_unpremultiply_sRGB<false>(dst, src, width); } /** @@ -219,3 +218,28 @@ static void transform_scanline_4444(char* SK_RESTRICT dst, const char* SK_RESTRI *dst++ = a; } } + +/** + * Transform from kRGBA_F16 to 4-bytes-per-pixel RGBA. + */ +static void transform_scanline_F16(char* SK_RESTRICT dst, const char* SK_RESTRICT src, int width, + int) { + SkRasterPipeline p; + p.append(SkRasterPipeline::load_f16, (const void**) &src); + p.append(SkRasterPipeline::to_srgb); + p.append(SkRasterPipeline::store_u16_be, (void**) &dst); + p.run(0, 0, width); +} + +/** + * Transform from kPremul, kRGBA_F16 to 4-bytes-per-pixel RGBA. + */ +static void transform_scanline_F16_premul(char* SK_RESTRICT dst, const char* SK_RESTRICT src, + int width, int) { + SkRasterPipeline p; + p.append(SkRasterPipeline::load_f16, (const void**) &src); + p.append(SkRasterPipeline::unpremul); + p.append(SkRasterPipeline::to_srgb); + p.append(SkRasterPipeline::store_u16_be, (void**) &dst); + p.run(0, 0, width); +} |