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>
diff --git a/src/images/SkPNGImageEncoder.cpp b/src/images/SkPNGImageEncoder.cpp
index 55aead2..48aca8b 100644
--- a/src/images/SkPNGImageEncoder.cpp
+++ b/src/images/SkPNGImageEncoder.cpp
@@ -83,6 +83,17 @@
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 @@
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 @@
}
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 @@
default:
return false;
}
+
if (kIndex_8_SkColorType == colorType) {
SkColorTable* ctable = pixmap.ctable();
if (!ctable || ctable->count() == 0) {
@@ -250,9 +262,25 @@
// 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 @@
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()));