diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/images/SkPNGImageEncoder.cpp | 5 | ||||
-rw-r--r-- | src/images/SkWEBPImageEncoder.cpp | 202 | ||||
-rw-r--r-- | src/images/transform_scanline.h | 88 |
3 files changed, 139 insertions, 156 deletions
diff --git a/src/images/SkPNGImageEncoder.cpp b/src/images/SkPNGImageEncoder.cpp index 48aca8bb1e..e4a60f917a 100644 --- a/src/images/SkPNGImageEncoder.cpp +++ b/src/images/SkPNGImageEncoder.cpp @@ -113,7 +113,7 @@ static inline int pack_palette(SkColorTable* ctable, png_color* SK_RESTRICT pale // Unpremultiply the colors. const SkImageInfo rgbaInfo = info.makeColorType(kRGBA_8888_SkColorType); transform_scanline_proc proc = choose_proc(rgbaInfo); - proc((char*) storage, (const char*) colors, ctable->count(), 4); + proc((char*) storage, (const char*) colors, ctable->count(), 4, nullptr); colors = storage; } @@ -350,7 +350,8 @@ static bool do_encode(SkWStream* stream, const SkPixmap& pixmap, 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())); + proc(storage, srcImage, pixmap.width(), SkColorTypeBytesPerPixel(pixmap.colorType()), + nullptr); png_write_rows(png_ptr, &row_ptr, 1); srcImage += pixmap.rowBytes(); } diff --git a/src/images/SkWEBPImageEncoder.cpp b/src/images/SkWEBPImageEncoder.cpp index aad06ac1d3..7d95906e0e 100644 --- a/src/images/SkWEBPImageEncoder.cpp +++ b/src/images/SkWEBPImageEncoder.cpp @@ -24,6 +24,7 @@ #include "SkTemplates.h" #include "SkUnPreMultiply.h" #include "SkUtils.h" +#include "transform_scanline.h" // A WebP decoder only, on top of (subset of) libwebp // For more information on WebP image format, and libwebp library, see: @@ -38,131 +39,67 @@ extern "C" { #include "webp/encode.h" } -typedef void (*ScanlineImporter)(const uint8_t* in, uint8_t* out, int width, - const SkPMColor* SK_RESTRICT ctable); - -static void ARGB_8888_To_RGB(const uint8_t* in, uint8_t* rgb, int width, - const SkPMColor*) { - const uint32_t* SK_RESTRICT src = (const uint32_t*)in; - for (int i = 0; i < width; ++i) { - const uint32_t c = *src++; - rgb[0] = SkGetPackedR32(c); - rgb[1] = SkGetPackedG32(c); - rgb[2] = SkGetPackedB32(c); - rgb += 3; - } -} - -static void ARGB_8888_To_RGBA(const uint8_t* in, uint8_t* rgb, int width, - const SkPMColor*) { - const uint32_t* SK_RESTRICT src = (const uint32_t*)in; - const SkUnPreMultiply::Scale* SK_RESTRICT table = - SkUnPreMultiply::GetScaleTable(); - for (int i = 0; i < width; ++i) { - const uint32_t c = *src++; - uint8_t a = SkGetPackedA32(c); - uint8_t r = SkGetPackedR32(c); - uint8_t g = SkGetPackedG32(c); - uint8_t b = SkGetPackedB32(c); - if (0 != a && 255 != a) { - SkUnPreMultiply::Scale scale = table[a]; - r = SkUnPreMultiply::ApplyScale(scale, r); - g = SkUnPreMultiply::ApplyScale(scale, g); - b = SkUnPreMultiply::ApplyScale(scale, b); - } - rgb[0] = r; - rgb[1] = g; - rgb[2] = b; - rgb[3] = a; - rgb += 4; - } -} - -static void RGB_565_To_RGB(const uint8_t* in, uint8_t* rgb, int width, - const SkPMColor*) { - const uint16_t* SK_RESTRICT src = (const uint16_t*)in; - for (int i = 0; i < width; ++i) { - const uint16_t c = *src++; - rgb[0] = SkPacked16ToR32(c); - rgb[1] = SkPacked16ToG32(c); - rgb[2] = SkPacked16ToB32(c); - rgb += 3; - } -} - -static void ARGB_4444_To_RGB(const uint8_t* in, uint8_t* rgb, int width, - const SkPMColor*) { - const SkPMColor16* SK_RESTRICT src = (const SkPMColor16*)in; - for (int i = 0; i < width; ++i) { - const SkPMColor16 c = *src++; - rgb[0] = SkPacked4444ToR32(c); - rgb[1] = SkPacked4444ToG32(c); - rgb[2] = SkPacked4444ToB32(c); - rgb += 3; - } -} - -static void ARGB_4444_To_RGBA(const uint8_t* in, uint8_t* rgb, int width, - const SkPMColor*) { - const SkPMColor16* SK_RESTRICT src = (const SkPMColor16*)in; - const SkUnPreMultiply::Scale* SK_RESTRICT table = - SkUnPreMultiply::GetScaleTable(); - for (int i = 0; i < width; ++i) { - const SkPMColor16 c = *src++; - uint8_t a = SkPacked4444ToA32(c); - uint8_t r = SkPacked4444ToR32(c); - uint8_t g = SkPacked4444ToG32(c); - uint8_t b = SkPacked4444ToB32(c); - if (0 != a && 255 != a) { - SkUnPreMultiply::Scale scale = table[a]; - r = SkUnPreMultiply::ApplyScale(scale, r); - g = SkUnPreMultiply::ApplyScale(scale, g); - b = SkUnPreMultiply::ApplyScale(scale, b); - } - rgb[0] = r; - rgb[1] = g; - rgb[2] = b; - rgb[3] = a; - rgb += 4; - } -} - -static void Index8_To_RGB(const uint8_t* in, uint8_t* rgb, int width, - const SkPMColor* SK_RESTRICT ctable) { - const uint8_t* SK_RESTRICT src = (const uint8_t*)in; - for (int i = 0; i < width; ++i) { - const uint32_t c = ctable[*src++]; - rgb[0] = SkGetPackedR32(c); - rgb[1] = SkGetPackedG32(c); - rgb[2] = SkGetPackedB32(c); - rgb += 3; - } -} - -static ScanlineImporter ChooseImporter(SkColorType ct, bool hasAlpha, int* bpp) { - switch (ct) { - case kN32_SkColorType: - if (hasAlpha) { - *bpp = 4; - return ARGB_8888_To_RGBA; - } else { - *bpp = 3; - return ARGB_8888_To_RGB; +static transform_scanline_proc choose_proc(const SkImageInfo& info, int* bpp) { + switch (info.colorType()) { + case kRGBA_8888_SkColorType: + switch (info.alphaType()) { + case kOpaque_SkAlphaType: + *bpp = 3; + return transform_scanline_RGBX; + case kUnpremul_SkAlphaType: + *bpp = 4; + return transform_scanline_memcpy; + case kPremul_SkAlphaType: + *bpp = 4; + return transform_scanline_rgbA; + default: + return nullptr; } - case kARGB_4444_SkColorType: - if (hasAlpha) { - *bpp = 4; - return ARGB_4444_To_RGBA; - } else { - *bpp = 3; - return ARGB_4444_To_RGB; + case kBGRA_8888_SkColorType: + switch (info.alphaType()) { + case kOpaque_SkAlphaType: + *bpp = 3; + return transform_scanline_BGRX; + case kUnpremul_SkAlphaType: + *bpp = 4; + return transform_scanline_BGRA; + case kPremul_SkAlphaType: + *bpp = 4; + return transform_scanline_bgrA; + default: + return nullptr; } case kRGB_565_SkColorType: *bpp = 3; - return RGB_565_To_RGB; + return transform_scanline_565; + case kARGB_4444_SkColorType: + switch (info.alphaType()) { + case kOpaque_SkAlphaType: + *bpp = 3; + return transform_scanline_444; + case kPremul_SkAlphaType: + *bpp = 4; + return transform_scanline_4444; + default: + return nullptr; + } case kIndex_8_SkColorType: + switch (info.alphaType()) { + case kOpaque_SkAlphaType: + *bpp = 3; + return transform_scanline_index8_opaque; + case kUnpremul_SkAlphaType: + case kPremul_SkAlphaType: + // If the color table is premultiplied, we'll fix it before calling the + // scanline proc. + *bpp = 4; + return transform_scanline_index8_unpremul; + default: + return nullptr; + } + case kGray_8_SkColorType: *bpp = 3; - return Index8_To_RGB; + return transform_scanline_gray; default: return nullptr; } @@ -175,20 +112,32 @@ static int stream_writer(const uint8_t* data, size_t data_size, } bool SkEncodeImageAsWEBP(SkWStream* stream, const SkPixmap& pixmap, int quality) { - const bool hasAlpha = !pixmap.isOpaque(); int bpp = -1; - const ScanlineImporter scanline_import = ChooseImporter(pixmap.colorType(), hasAlpha, &bpp); - if (nullptr == scanline_import) { - return false; - } - if (-1 == bpp) { + const transform_scanline_proc proc = choose_proc(pixmap.info(), &bpp); + if (!proc) { return false; } + SkASSERT(-1 != bpp); if (nullptr == pixmap.addr()) { return false; } + const SkPMColor* colors = nullptr; + SkPMColor storage[256]; + if (kIndex_8_SkColorType == pixmap.colorType()) { + if (!pixmap.ctable()) { + return false; + } + + colors = pixmap.ctable()->readColors(); + if (kPremul_SkAlphaType == pixmap.alphaType()) { + transform_scanline_rgbA((char*) storage, (const char*) colors, pixmap.ctable()->count(), + 4, nullptr); + colors = storage; + } + } + WebPConfig webp_config; if (!WebPConfigPreset(&webp_config, WEBP_PRESET_DEFAULT, (float) quality)) { return false; @@ -201,7 +150,6 @@ bool SkEncodeImageAsWEBP(SkWStream* stream, const SkPixmap& pixmap, int quality) pic.writer = stream_writer; pic.custom_ptr = (void*)stream; - const SkPMColor* colors = pixmap.ctable() ? pixmap.ctable()->readColors() : nullptr; const uint8_t* src = (uint8_t*)pixmap.addr(); const int rgbStride = pic.width * bpp; const size_t rowBytes = pixmap.rowBytes(); @@ -210,7 +158,7 @@ bool SkEncodeImageAsWEBP(SkWStream* stream, const SkPixmap& pixmap, int quality) // to RGB color space. std::unique_ptr<uint8_t[]> rgb(new uint8_t[rgbStride * pic.height]); for (int y = 0; y < pic.height; ++y) { - scanline_import(src + y * rowBytes, &rgb[y * rgbStride], pic.width, colors); + proc((char*) &rgb[y * rgbStride], (const char*) &src[y * rowBytes], pic.width, bpp, colors); } bool ok; diff --git a/src/images/transform_scanline.h b/src/images/transform_scanline.h index 1c263487bd..e26dde3e07 100644 --- a/src/images/transform_scanline.h +++ b/src/images/transform_scanline.h @@ -23,23 +23,57 @@ * 'bpp' is bytes per pixel in the 'src' buffer. */ typedef void (*transform_scanline_proc)(char* SK_RESTRICT dst, const char* SK_RESTRICT src, - int width, int bpp); + int width, int bpp, const SkPMColor* colors); /** * Identity transformation: just copy bytes from src to dst. */ -static void transform_scanline_memcpy(char* SK_RESTRICT dst, const char* SK_RESTRICT src, - int width, int bpp) { +static inline void transform_scanline_memcpy(char* SK_RESTRICT dst, const char* SK_RESTRICT src, + int width, int bpp, const SkPMColor*) { memcpy(dst, src, width * bpp); } +static inline void transform_scanline_index8_opaque(char* SK_RESTRICT dst, + const char* SK_RESTRICT src, int width, int, + const SkPMColor* colors) { + for (int i = 0; i < width; i++) { + const uint32_t c = colors[(uint8_t)*src++]; + dst[0] = SkGetPackedR32(c); + dst[1] = SkGetPackedG32(c); + dst[2] = SkGetPackedB32(c); + dst += 3; + } +} + +static inline void transform_scanline_index8_unpremul(char* SK_RESTRICT dst, + const char* SK_RESTRICT src, int width, int, + const SkPMColor* colors) { + uint32_t* SK_RESTRICT dst32 = (uint32_t*) dst; + for (int i = 0; i < width; i++) { + // This function swizzles R and B on platforms where SkPMColor is BGRA. This is + // exactly what we want. + dst32[i] = SkSwizzle_RGBA_to_PMColor(colors[(uint8_t)*src++]); + } +} + +static inline void transform_scanline_gray(char* SK_RESTRICT dst, const char* SK_RESTRICT src, + int width, int, const SkPMColor* colors) { + for (int i = 0; i < width; i++) { + const uint8_t g = (uint8_t) *src++; + dst[0] = g; + dst[1] = g; + dst[2] = g; + dst += 3; + } +} + /** * Transform from kRGB_565_Config to 3-bytes-per-pixel RGB. * Alpha channel data is not present in kRGB_565_Config format, so there is no * alpha channel data to preserve. */ -static void transform_scanline_565(char* SK_RESTRICT dst, const char* SK_RESTRICT src, - int width, int) { +static inline void transform_scanline_565(char* SK_RESTRICT dst, const char* SK_RESTRICT src, + int width, int, const SkPMColor*) { const uint16_t* srcP = (const uint16_t*)src; for (int i = 0; i < width; i++) { unsigned c = *srcP++; @@ -53,8 +87,8 @@ static void transform_scanline_565(char* SK_RESTRICT dst, const char* SK_RESTRIC * Transform from kRGBA_8888_SkColorType to 3-bytes-per-pixel RGB. * Alpha channel data is abandoned. */ -static void transform_scanline_RGBX(char* SK_RESTRICT dst, const char* SK_RESTRICT src, - int width, int) { +static inline void transform_scanline_RGBX(char* SK_RESTRICT dst, const char* SK_RESTRICT src, + int width, int, const SkPMColor*) { const uint32_t* srcP = (const SkPMColor*)src; for (int i = 0; i < width; i++) { uint32_t c = *srcP++; @@ -68,8 +102,8 @@ static void transform_scanline_RGBX(char* SK_RESTRICT dst, const char* SK_RESTRI * Transform from kBGRA_8888_SkColorType to 3-bytes-per-pixel RGB. * Alpha channel data is abandoned. */ -static void transform_scanline_BGRX(char* SK_RESTRICT dst, const char* SK_RESTRICT src, - int width, int) { +static inline void transform_scanline_BGRX(char* SK_RESTRICT dst, const char* SK_RESTRICT src, + int width, int, const SkPMColor*) { const uint32_t* srcP = (const SkPMColor*)src; for (int i = 0; i < width; i++) { uint32_t c = *srcP++; @@ -83,8 +117,8 @@ static void transform_scanline_BGRX(char* SK_RESTRICT dst, const char* SK_RESTRI * Transform from kARGB_4444_Config to 3-bytes-per-pixel RGB. * Alpha channel data, if any, is abandoned. */ -static void transform_scanline_444(char* SK_RESTRICT dst, const char* SK_RESTRICT src, - int width, int) { +static inline void transform_scanline_444(char* SK_RESTRICT dst, const char* SK_RESTRICT src, + int width, int, const SkPMColor*) { const SkPMColor16* srcP = (const SkPMColor16*)src; for (int i = 0; i < width; i++) { SkPMColor16 c = *srcP++; @@ -131,16 +165,16 @@ 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) { +static inline void transform_scanline_rgbA(char* SK_RESTRICT dst, const char* SK_RESTRICT src, + int width, int, const SkPMColor*) { 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) { +static inline void transform_scanline_bgrA(char* SK_RESTRICT dst, const char* SK_RESTRICT src, + int width, int, const SkPMColor*) { transform_scanline_unpremultiply<false>(dst, src, width); } @@ -162,24 +196,24 @@ 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) { +static inline void transform_scanline_srgbA(char* SK_RESTRICT dst, const char* SK_RESTRICT src, + int width, int, const SkPMColor*) { 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) { +static inline void transform_scanline_sbgrA(char* SK_RESTRICT dst, const char* SK_RESTRICT src, + int width, int, const SkPMColor*) { transform_scanline_unpremultiply_sRGB<false>(dst, src, width); } /** * Transform from kUnpremul, 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) { +static inline void transform_scanline_BGRA(char* SK_RESTRICT dst, const char* SK_RESTRICT src, + int width, int, const SkPMColor*) { const uint32_t* srcP = (const SkPMColor*)src; for (int i = 0; i < width; i++) { uint32_t c = *srcP++; @@ -194,8 +228,8 @@ static void transform_scanline_BGRA(char* SK_RESTRICT dst, const char* SK_RESTRI * Transform from kARGB_8888_Config to 4-bytes-per-pixel RGBA, * with scaling of RGB based on alpha channel. */ -static void transform_scanline_4444(char* SK_RESTRICT dst, const char* SK_RESTRICT src, - int width, int) { +static inline void transform_scanline_4444(char* SK_RESTRICT dst, const char* SK_RESTRICT src, + int width, int, const SkPMColor*) { const SkPMColor16* srcP = (const SkPMColor16*)src; const SkUnPreMultiply::Scale* table = SkUnPreMultiply::GetScaleTable(); @@ -222,8 +256,8 @@ static void transform_scanline_4444(char* SK_RESTRICT dst, const char* SK_RESTRI /** * 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) { +static inline void transform_scanline_F16(char* SK_RESTRICT dst, const char* SK_RESTRICT src, + int width, int, const SkPMColor*) { SkRasterPipeline p; p.append(SkRasterPipeline::load_f16, (const void**) &src); p.append(SkRasterPipeline::to_srgb); @@ -234,8 +268,8 @@ static void transform_scanline_F16(char* SK_RESTRICT dst, const char* SK_RESTRIC /** * 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) { +static inline void transform_scanline_F16_premul(char* SK_RESTRICT dst, const char* SK_RESTRICT src, + int width, int, const SkPMColor*) { SkRasterPipeline p; p.append(SkRasterPipeline::load_f16, (const void**) &src); p.append(SkRasterPipeline::unpremul); |