aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/images
diff options
context:
space:
mode:
authorGravatar Matt Sarett <msarett@google.com>2017-01-23 19:37:37 -0500
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2017-01-24 15:11:48 +0000
commit55213562f9a63cbc324833fdd1c16cc79646515a (patch)
tree2122c0e986882a3a92ba3f4ad7dc54bef6f2ec6b /src/images
parent6f4a9b294868a94e5b1e06a8e855833614355bcc (diff)
Add F16 and gamma correct support to webp encoder
BUG=skia: Change-Id: Ib788466fa1e2bed26e7ffd8f03bee42930eae1d6 Reviewed-on: https://skia-review.googlesource.com/7425 Commit-Queue: Matt Sarett <msarett@google.com> Reviewed-by: Leon Scroggins <scroggo@google.com>
Diffstat (limited to 'src/images')
-rw-r--r--src/images/SkImageEncoderPriv.h1
-rw-r--r--src/images/SkWEBPImageEncoder.cpp86
-rw-r--r--src/images/transform_scanline.h31
3 files changed, 94 insertions, 24 deletions
diff --git a/src/images/SkImageEncoderPriv.h b/src/images/SkImageEncoderPriv.h
index 7748204fed..e2f72caa8d 100644
--- a/src/images/SkImageEncoderPriv.h
+++ b/src/images/SkImageEncoderPriv.h
@@ -35,6 +35,7 @@ struct SkEncodeOptions {
#endif
#ifdef SK_HAS_WEBP_LIBRARY
+ bool SkEncodeImageAsWEBP(SkWStream*, const SkPixmap&, const SkEncodeOptions&);
bool SkEncodeImageAsWEBP(SkWStream*, const SkPixmap&, int quality);
#else
#define SkEncodeImageAsWEBP(...) false
diff --git a/src/images/SkWEBPImageEncoder.cpp b/src/images/SkWEBPImageEncoder.cpp
index 7d95906e0e..5928f97861 100644
--- a/src/images/SkWEBPImageEncoder.cpp
+++ b/src/images/SkWEBPImageEncoder.cpp
@@ -39,46 +39,44 @@ extern "C" {
#include "webp/encode.h"
}
-static transform_scanline_proc choose_proc(const SkImageInfo& info, int* bpp) {
+static transform_scanline_proc choose_proc(const SkImageInfo& info) {
+ const bool isGammaEncoded = info.gammaCloseToSRGB();
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;
+ return isGammaEncoded ? transform_scanline_srgbA :
+ transform_scanline_rgbA;
default:
return nullptr;
}
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;
+ return isGammaEncoded ? transform_scanline_sbgrA :
+ transform_scanline_bgrA;
default:
return nullptr;
}
case kRGB_565_SkColorType:
- *bpp = 3;
+ if (!info.isOpaque()) {
+ return nullptr;
+ }
+
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;
@@ -86,20 +84,31 @@ static transform_scanline_proc choose_proc(const SkImageInfo& info, int* bpp) {
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 transform_scanline_gray;
+ case kRGBA_F16_SkColorType:
+ if (!info.colorSpace() || !info.colorSpace()->gammaIsLinear()) {
+ return nullptr;
+ }
+
+ switch (info.alphaType()) {
+ case kOpaque_SkAlphaType:
+ case kUnpremul_SkAlphaType:
+ return transform_scanline_F16_to_8888;
+ case kPremul_SkAlphaType:
+ return transform_scanline_F16_premul_to_8888;
+ default:
+ return nullptr;
+ }
default:
return nullptr;
}
@@ -111,13 +120,31 @@ static int stream_writer(const uint8_t* data, size_t data_size,
return stream->write(data, data_size) ? 1 : 0;
}
-bool SkEncodeImageAsWEBP(SkWStream* stream, const SkPixmap& pixmap, int quality) {
- int bpp = -1;
- const transform_scanline_proc proc = choose_proc(pixmap.info(), &bpp);
+static bool do_encode(SkWStream* stream, const SkPixmap& srcPixmap, const SkEncodeOptions& opts,
+ int quality) {
+ SkASSERT(!srcPixmap.colorSpace() || srcPixmap.colorSpace()->gammaCloseToSRGB() ||
+ srcPixmap.colorSpace()->gammaIsLinear());
+
+ SkPixmap pixmap = srcPixmap;
+ if (SkEncodeOptions::PremulBehavior::kLegacy == opts.fPremulBehavior) {
+ pixmap.setColorSpace(nullptr);
+ } else {
+ if (!pixmap.colorSpace()) {
+ return false;
+ }
+ }
+
+ const transform_scanline_proc proc = choose_proc(pixmap.info());
if (!proc) {
return false;
}
- SkASSERT(-1 != bpp);
+
+ int bpp;
+ if (kRGBA_F16_SkColorType == pixmap.colorType()) {
+ bpp = 4;
+ } else {
+ bpp = pixmap.isOpaque() ? 3 : 4;
+ }
if (nullptr == pixmap.addr()) {
return false;
@@ -132,8 +159,10 @@ bool SkEncodeImageAsWEBP(SkWStream* stream, const SkPixmap& pixmap, int quality)
colors = pixmap.ctable()->readColors();
if (kPremul_SkAlphaType == pixmap.alphaType()) {
- transform_scanline_rgbA((char*) storage, (const char*) colors, pixmap.ctable()->count(),
- 4, nullptr);
+ // Unpremultiply the colors.
+ const SkImageInfo rgbaInfo = pixmap.info().makeColorType(kRGBA_8888_SkColorType);
+ transform_scanline_proc proc = choose_proc(rgbaInfo);
+ proc((char*) storage, (const char*) colors, pixmap.ctable()->count(), 4, nullptr);
colors = storage;
}
}
@@ -165,7 +194,11 @@ bool SkEncodeImageAsWEBP(SkWStream* stream, const SkPixmap& pixmap, int quality)
if (bpp == 3) {
ok = SkToBool(WebPPictureImportRGB(&pic, &rgb[0], rgbStride));
} else {
- ok = SkToBool(WebPPictureImportRGBA(&pic, &rgb[0], rgbStride));
+ if (pixmap.isOpaque()) {
+ ok = SkToBool(WebPPictureImportRGBX(&pic, &rgb[0], rgbStride));
+ } else {
+ ok = SkToBool(WebPPictureImportRGBA(&pic, &rgb[0], rgbStride));
+ }
}
ok = ok && WebPEncode(&webp_config, &pic);
@@ -173,4 +206,13 @@ bool SkEncodeImageAsWEBP(SkWStream* stream, const SkPixmap& pixmap, int quality)
return ok;
}
+
+bool SkEncodeImageAsWEBP(SkWStream* stream, const SkPixmap& src, int quality) {
+ return do_encode(stream, src, SkEncodeOptions(), quality);
+}
+
+bool SkEncodeImageAsWEBP(SkWStream* stream, const SkPixmap& src, const SkEncodeOptions& opts) {
+ return do_encode(stream, src, opts, 100);
+}
+
#endif
diff --git a/src/images/transform_scanline.h b/src/images/transform_scanline.h
index d49203642e..6bf347419f 100644
--- a/src/images/transform_scanline.h
+++ b/src/images/transform_scanline.h
@@ -254,7 +254,7 @@ static inline void transform_scanline_4444(char* SK_RESTRICT dst, const char* SK
}
/**
- * Transform from kRGBA_F16 to 4-bytes-per-pixel RGBA.
+ * Transform from kRGBA_F16 to 8-bytes-per-pixel RGBA.
*/
static inline void transform_scanline_F16(char* SK_RESTRICT dst, const char* SK_RESTRICT src,
int width, int, const SkPMColor*) {
@@ -266,7 +266,7 @@ static inline void transform_scanline_F16(char* SK_RESTRICT dst, const char* SK_
}
/**
- * Transform from kPremul, kRGBA_F16 to 4-bytes-per-pixel RGBA.
+ * Transform from kPremul, kRGBA_F16 to 8-bytes-per-pixel RGBA.
*/
static inline void transform_scanline_F16_premul(char* SK_RESTRICT dst, const char* SK_RESTRICT src,
int width, int, const SkPMColor*) {
@@ -277,3 +277,30 @@ static inline void transform_scanline_F16_premul(char* SK_RESTRICT dst, const ch
p.append(SkRasterPipeline::store_u16_be, (void**) &dst);
p.run(0, width);
}
+
+/**
+ * Transform from kRGBA_F16 to 4-bytes-per-pixel RGBA.
+ */
+static inline void transform_scanline_F16_to_8888(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);
+ p.append(SkRasterPipeline::store_8888, (void**) &dst);
+ p.run(0, width);
+}
+
+/**
+ * Transform from kPremul, kRGBA_F16 to 4-bytes-per-pixel RGBA.
+ */
+static inline void transform_scanline_F16_premul_to_8888(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);
+ p.append(SkRasterPipeline::to_srgb);
+ p.append(SkRasterPipeline::store_8888, (void**) &dst);
+ p.run(0, width);
+}