aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/images
diff options
context:
space:
mode:
authorGravatar Matt Sarett <msarett@google.com>2017-04-05 17:36:04 -0400
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2017-04-05 22:56:37 +0000
commit7abfb5e1547bcbf626b2078991a9fe31c24b5d10 (patch)
treea49a9092113724118589802260e854cf812e5791 /src/images
parent3dbef9f184cfecadf14d4c424cf02ee2e8f68d44 (diff)
SkImageEncoder: Be more lenient on inputs
(1) Some clients want us to write ICC profiles, even though they have not opted into linear unpremultiplication. This CL allows that behavior. (2) We should not assert that the transfer function must be linear or srgb. Particularly in non-linear blending modes, skia is willing to support a larger set of transfer functions. (3) We still need to require linear or srgb when in kRespect transfer function mode. We have not yet implemented linear unpremultiplies for arbitrary transfer functions. Bug: skia: Change-Id: Idce9f07c3d36eca4d78ede5e2650b2cab412904c Reviewed-on: https://skia-review.googlesource.com/11349 Commit-Queue: Matt Sarett <msarett@google.com> Reviewed-by: Leon Scroggins <scroggo@google.com>
Diffstat (limited to 'src/images')
-rw-r--r--src/images/SkJPEGImageEncoder.cpp17
-rw-r--r--src/images/SkPNGImageEncoder.cpp46
-rw-r--r--src/images/SkWEBPImageEncoder.cpp31
3 files changed, 43 insertions, 51 deletions
diff --git a/src/images/SkJPEGImageEncoder.cpp b/src/images/SkJPEGImageEncoder.cpp
index 845673421c..764e9c43b0 100644
--- a/src/images/SkJPEGImageEncoder.cpp
+++ b/src/images/SkJPEGImageEncoder.cpp
@@ -82,22 +82,17 @@ static bool set_encode_config(J_COLOR_SPACE* jpegColorType, int* numComponents,
}
bool SkEncodeImageAsJPEG(SkWStream* stream, const SkPixmap& pixmap, const SkEncodeOptions& opts) {
- SkASSERT(!pixmap.colorSpace() || pixmap.colorSpace()->gammaCloseToSRGB() ||
- pixmap.colorSpace()->gammaIsLinear());
-
- SkPixmap src = pixmap;
- if (SkTransferFunctionBehavior::kIgnore == opts.fUnpremulBehavior) {
- src.setColorSpace(nullptr);
- } else {
- // kCorrect behavior requires a color space. It's not actually critical in the
- // jpeg case (since jpegs are opaque), but Skia color correct behavior generally
+ if (SkTransferFunctionBehavior::kRespect == opts.fUnpremulBehavior) {
+ // Respecting the transfer function requries a color space. It's not actually critical
+ // in the jpeg case (since jpegs are opaque), but Skia color correct behavior generally
// requires pixels to be tagged with color spaces.
- if (!src.colorSpace()) {
+ if (!pixmap.colorSpace() || (!pixmap.colorSpace()->gammaCloseToSRGB() &&
+ !pixmap.colorSpace()->gammaIsLinear())) {
return false;
}
}
- return SkEncodeImageAsJPEG(stream, src, 100);
+ return SkEncodeImageAsJPEG(stream, pixmap, 100);
}
bool SkEncodeImageAsJPEG(SkWStream* stream, const SkPixmap& pixmap, int quality) {
diff --git a/src/images/SkPNGImageEncoder.cpp b/src/images/SkPNGImageEncoder.cpp
index 9f5ebd27ab..b57c32a0fc 100644
--- a/src/images/SkPNGImageEncoder.cpp
+++ b/src/images/SkPNGImageEncoder.cpp
@@ -51,8 +51,10 @@ static void set_icc(png_structp png_ptr, png_infop info_ptr, sk_sp<SkData> icc)
png_set_iCCP(png_ptr, info_ptr, name, 0, iccPtr, icc->size());
}
-static transform_scanline_proc choose_proc(const SkImageInfo& info) {
- const bool isGammaEncoded = info.gammaCloseToSRGB();
+static transform_scanline_proc choose_proc(const SkImageInfo& info,
+ SkTransferFunctionBehavior unpremulBehavior) {
+ const bool isSRGBTransferFn =
+ (SkTransferFunctionBehavior::kRespect == unpremulBehavior) && info.gammaCloseToSRGB();
switch (info.colorType()) {
case kRGBA_8888_SkColorType:
switch (info.alphaType()) {
@@ -61,8 +63,8 @@ static transform_scanline_proc choose_proc(const SkImageInfo& info) {
case kUnpremul_SkAlphaType:
return transform_scanline_memcpy;
case kPremul_SkAlphaType:
- return isGammaEncoded ? transform_scanline_srgbA :
- transform_scanline_rgbA;
+ return isSRGBTransferFn ? transform_scanline_srgbA :
+ transform_scanline_rgbA;
default:
SkASSERT(false);
return nullptr;
@@ -74,8 +76,8 @@ static transform_scanline_proc choose_proc(const SkImageInfo& info) {
case kUnpremul_SkAlphaType:
return transform_scanline_BGRA;
case kPremul_SkAlphaType:
- return isGammaEncoded ? transform_scanline_sbgrA :
- transform_scanline_bgrA;
+ return isSRGBTransferFn ? transform_scanline_sbgrA :
+ transform_scanline_bgrA;
default:
SkASSERT(false);
return nullptr;
@@ -118,14 +120,15 @@ static transform_scanline_proc choose_proc(const SkImageInfo& info) {
opaque, the return value will always be 0.
*/
static inline int pack_palette(SkColorTable* ctable, png_color* SK_RESTRICT palette,
- png_byte* SK_RESTRICT alphas, const SkImageInfo& info) {
+ png_byte* SK_RESTRICT alphas, const SkImageInfo& info,
+ SkTransferFunctionBehavior unpremulBehavior) {
const SkPMColor* colors = ctable->readColors();
const int count = ctable->count();
SkPMColor storage[256];
if (kPremul_SkAlphaType == info.alphaType()) {
// Unpremultiply the colors.
const SkImageInfo rgbaInfo = info.makeColorType(kRGBA_8888_SkColorType);
- transform_scanline_proc proc = choose_proc(rgbaInfo);
+ transform_scanline_proc proc = choose_proc(rgbaInfo, unpremulBehavior);
proc((char*) storage, (const char*) colors, ctable->count(), 4, nullptr);
colors = storage;
}
@@ -174,17 +177,13 @@ static inline int pack_palette(SkColorTable* ctable, png_color* SK_RESTRICT pale
return numWithAlpha;
}
-static bool do_encode(SkWStream*, const SkPixmap&, int, int, png_color_8&);
+static bool do_encode(SkWStream*, const SkPixmap&, int, int, png_color_8&,
+ SkTransferFunctionBehavior unpremulBehavior);
-bool SkEncodeImageAsPNG(SkWStream* stream, const SkPixmap& src, const SkEncodeOptions& opts) {
- SkASSERT(!src.colorSpace() || src.colorSpace()->gammaCloseToSRGB() ||
- src.colorSpace()->gammaIsLinear());
-
- SkPixmap pixmap = src;
- if (SkTransferFunctionBehavior::kIgnore == opts.fUnpremulBehavior) {
- pixmap.setColorSpace(nullptr);
- } else {
- if (!pixmap.colorSpace()) {
+bool SkEncodeImageAsPNG(SkWStream* stream, const SkPixmap& pixmap, const SkEncodeOptions& opts) {
+ if (SkTransferFunctionBehavior::kRespect == opts.fUnpremulBehavior) {
+ if (!pixmap.colorSpace() || (!pixmap.colorSpace()->gammaCloseToSRGB() &&
+ !pixmap.colorSpace()->gammaIsLinear())) {
return false;
}
}
@@ -276,7 +275,7 @@ bool SkEncodeImageAsPNG(SkWStream* stream, const SkPixmap& src, const SkEncodeOp
// or 4 bit indices.
}
- return do_encode(stream, pixmap, pngColorType, bitDepth, sig_bit);
+ return do_encode(stream, pixmap, pngColorType, bitDepth, sig_bit, opts.fUnpremulBehavior);
}
static int num_components(int pngColorType) {
@@ -294,8 +293,8 @@ static int num_components(int pngColorType) {
}
}
-static bool do_encode(SkWStream* stream, const SkPixmap& pixmap,
- int pngColorType, int bitDepth, png_color_8& sig_bit) {
+static bool do_encode(SkWStream* stream, const SkPixmap& pixmap, int pngColorType, int bitDepth,
+ png_color_8& sig_bit, SkTransferFunctionBehavior unpremulBehavior) {
png_structp png_ptr;
png_infop info_ptr;
@@ -340,7 +339,8 @@ static bool do_encode(SkWStream* stream, const SkPixmap& pixmap,
if (kIndex_8_SkColorType == pixmap.colorType()) {
SkColorTable* colorTable = pixmap.ctable();
SkASSERT(colorTable);
- int numTrans = pack_palette(colorTable, paletteColors, trans, pixmap.info());
+ int numTrans = pack_palette(colorTable, paletteColors, trans, pixmap.info(),
+ unpremulBehavior);
png_set_PLTE(png_ptr, info_ptr, paletteColors, colorTable->count());
if (numTrans > 0) {
png_set_tRNS(png_ptr, info_ptr, trans, numTrans, nullptr);
@@ -371,7 +371,7 @@ static bool do_encode(SkWStream* stream, const SkPixmap& pixmap,
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());
+ transform_scanline_proc proc = choose_proc(pixmap.info(), unpremulBehavior);
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/SkWEBPImageEncoder.cpp b/src/images/SkWEBPImageEncoder.cpp
index 728dbc712a..c0cd4a6cae 100644
--- a/src/images/SkWEBPImageEncoder.cpp
+++ b/src/images/SkWEBPImageEncoder.cpp
@@ -40,8 +40,10 @@ extern "C" {
#include "webp/mux.h"
}
-static transform_scanline_proc choose_proc(const SkImageInfo& info) {
- const bool isGammaEncoded = info.gammaCloseToSRGB();
+static transform_scanline_proc choose_proc(const SkImageInfo& info,
+ SkTransferFunctionBehavior unpremulBehavior) {
+ const bool isSRGBTransferFn =
+ (SkTransferFunctionBehavior::kRespect == unpremulBehavior) && info.gammaCloseToSRGB();
switch (info.colorType()) {
case kRGBA_8888_SkColorType:
switch (info.alphaType()) {
@@ -50,8 +52,8 @@ static transform_scanline_proc choose_proc(const SkImageInfo& info) {
case kUnpremul_SkAlphaType:
return transform_scanline_memcpy;
case kPremul_SkAlphaType:
- return isGammaEncoded ? transform_scanline_srgbA :
- transform_scanline_rgbA;
+ return isSRGBTransferFn ? transform_scanline_srgbA :
+ transform_scanline_rgbA;
default:
return nullptr;
}
@@ -62,8 +64,8 @@ static transform_scanline_proc choose_proc(const SkImageInfo& info) {
case kUnpremul_SkAlphaType:
return transform_scanline_BGRA;
case kPremul_SkAlphaType:
- return isGammaEncoded ? transform_scanline_sbgrA :
- transform_scanline_bgrA;
+ return isSRGBTransferFn ? transform_scanline_sbgrA :
+ transform_scanline_bgrA;
default:
return nullptr;
}
@@ -121,21 +123,16 @@ static int stream_writer(const uint8_t* data, size_t data_size,
return stream->write(data, data_size) ? 1 : 0;
}
-static bool do_encode(SkWStream* stream, const SkPixmap& srcPixmap, const SkEncodeOptions& opts,
+static bool do_encode(SkWStream* stream, const SkPixmap& pixmap, const SkEncodeOptions& opts,
int quality) {
- SkASSERT(!srcPixmap.colorSpace() || srcPixmap.colorSpace()->gammaCloseToSRGB() ||
- srcPixmap.colorSpace()->gammaIsLinear());
-
- SkPixmap pixmap = srcPixmap;
- if (SkTransferFunctionBehavior::kIgnore == opts.fUnpremulBehavior) {
- pixmap.setColorSpace(nullptr);
- } else {
- if (!pixmap.colorSpace()) {
+ if (SkTransferFunctionBehavior::kRespect == opts.fUnpremulBehavior) {
+ if (!pixmap.colorSpace() || (!pixmap.colorSpace()->gammaCloseToSRGB() &&
+ !pixmap.colorSpace()->gammaIsLinear())) {
return false;
}
}
- const transform_scanline_proc proc = choose_proc(pixmap.info());
+ const transform_scanline_proc proc = choose_proc(pixmap.info(), opts.fUnpremulBehavior);
if (!proc) {
return false;
}
@@ -162,7 +159,7 @@ static bool do_encode(SkWStream* stream, const SkPixmap& srcPixmap, const SkEnco
if (kPremul_SkAlphaType == pixmap.alphaType()) {
// Unpremultiply the colors.
const SkImageInfo rgbaInfo = pixmap.info().makeColorType(kRGBA_8888_SkColorType);
- transform_scanline_proc proc = choose_proc(rgbaInfo);
+ transform_scanline_proc proc = choose_proc(rgbaInfo, opts.fUnpremulBehavior);
proc((char*) storage, (const char*) colors, pixmap.ctable()->count(), 4, nullptr);
colors = storage;
}