Add SkTransferFunctionBehavior flag: Use in codec and encoder
authorMatt Sarett <msarett@google.com>
Thu, 23 Mar 2017 19:32:25 +0000 (15:32 -0400)
committerSkia Commit-Bot <skia-commit-bot@chromium.org>
Fri, 24 Mar 2017 13:19:53 +0000 (13:19 +0000)
This is a step towards removing the non-linear blending flag from
SkColorSpace.  The flag on SkColorSpace used to control the premul
behavior - now it is controlled by this option.

BUG=skia:

Change-Id: Ia29bd8c2b0596a93c6aa14332dcd9bd39e388a90
Reviewed-on: https://skia-review.googlesource.com/10008
Reviewed-by: Mike Reed <reed@google.com>
Reviewed-by: Leon Scroggins <scroggo@google.com>
Commit-Queue: Matt Sarett <msarett@google.com>

22 files changed:
gm/encode-srgb.cpp
include/codec/SkCodec.h
include/core/SkColorSpace.h
src/codec/SkAndroidCodec.cpp
src/codec/SkBmpCodec.cpp
src/codec/SkCodec.cpp
src/codec/SkCodecPriv.h
src/codec/SkGifCodec.cpp
src/codec/SkJpegCodec.cpp
src/codec/SkPngCodec.cpp
src/codec/SkRawCodec.cpp
src/codec/SkSampledCodec.cpp
src/codec/SkWebpAdapterCodec.cpp
src/codec/SkWebpCodec.cpp
src/core/SkColorSpaceXform.cpp
src/core/SkColorSpaceXform_A2B.h
src/core/SkColorSpaceXform_Base.h
src/images/SkImageEncoderPriv.h
src/images/SkJPEGImageEncoder.cpp
src/images/SkPNGImageEncoder.cpp
src/images/SkWEBPImageEncoder.cpp
tests/CodecTest.cpp

index 2a89ea3..f62d48a 100644 (file)
@@ -119,7 +119,7 @@ static sk_sp<SkData> encode_data(const SkBitmap& bitmap, SkEncodedImageFormat fo
 
     SkEncodeOptions options;
     if (bitmap.colorSpace()) {
-        options.fColorBehavior = SkEncodeOptions::ColorBehavior::kCorrect;
+        options.fUnpremulBehavior = SkTransferFunctionBehavior::kRespect;
     }
 
     switch (format) {
index 13730e2..11d28ea 100644 (file)
@@ -249,9 +249,10 @@ public:
             , fSubset(nullptr)
             , fFrameIndex(0)
             , fHasPriorFrame(false)
+            , fPremulBehavior(SkTransferFunctionBehavior::kRespect)
         {}
 
-        ZeroInitialized             fZeroInitialized;
+        ZeroInitialized            fZeroInitialized;
         /**
          *  If not NULL, represents a subset of the original image to decode.
          *  Must be within the bounds returned by getInfo().
@@ -269,14 +270,14 @@ public:
          *  subset left and subset width to decode partial scanlines on calls
          *  to getScanlines().
          */
-        const SkIRect*              fSubset;
+        const SkIRect*             fSubset;
 
         /**
          *  The frame to decode.
          *
          *  Only meaningful for multi-frame images.
          */
-        size_t fFrameIndex;
+        size_t                     fFrameIndex;
 
         /**
          *  If true, the dst already contains the prior frame.
@@ -295,7 +296,15 @@ public:
          *  codec needs to first decode the prior frame (which in turn may need
          *  to decode its prior frame).
          */
-        bool   fHasPriorFrame;
+        bool                       fHasPriorFrame;
+
+        /**
+         *  Indicates whether we should do a linear premultiply or a legacy premultiply.
+         *
+         *  In the case where the dst SkColorSpace is nullptr, this flag is ignored and
+         *  we will always do a legacy premultiply.
+         */
+        SkTransferFunctionBehavior fPremulBehavior;
     };
 
     /**
@@ -781,7 +790,8 @@ protected:
 
     virtual int onOutputScanline(int inputScanline) const;
 
-    bool initializeColorXform(const SkImageInfo& dstInfo);
+    bool initializeColorXform(const SkImageInfo& dstInfo,
+                              SkTransferFunctionBehavior premulBehavior);
     SkColorSpaceXform* colorXform() const { return fColorXform.get(); }
 
     virtual std::vector<FrameInfo> onGetFrameInfo() {
index ebc0ca1..27288f7 100644 (file)
@@ -174,4 +174,17 @@ protected:
     SkColorSpace() {}
 };
 
+enum class SkTransferFunctionBehavior {
+    /**
+     *  Converts to a linear space before premultiplying, unpremultiplying, or blending.
+     */
+    kRespect,
+
+    /**
+     *  Premultiplies, unpremultiplies, and blends ignoring the transfer function.  Pixels are
+     *  treated as if they are linear, regardless of their transfer function encoding.
+     */
+    kIgnore,
+};
+
 #endif
index 76ad0f9..3a4d2b3 100644 (file)
@@ -179,18 +179,15 @@ sk_sp<SkColorSpace> SkAndroidCodec::computeOutputColorSpace(SkColorType outputCo
             if (encodedSpace->isNumericalTransferFn(&fn)) {
                 // Leave the pixels in the encoded color space.  Color space conversion
                 // will be handled after decode time.
-                return as_CSB(encodedSpace)->makeWithNonLinearBlending();
+                return sk_ref_sp(encodedSpace);
             }
 
             if (is_wide_gamut(encodedSpace)) {
                 return SkColorSpace::MakeRGB(SkColorSpace::kSRGB_RenderTargetGamma,
-                                             SkColorSpace::kDCIP3_D65_Gamut,
-                                             SkColorSpace::kNonLinearBlending_ColorSpaceFlag);
+                                             SkColorSpace::kDCIP3_D65_Gamut);
             }
 
-            return SkColorSpace::MakeRGB(SkColorSpace::kSRGB_RenderTargetGamma,
-                                         SkColorSpace::kSRGB_Gamut,
-                                         SkColorSpace::kNonLinearBlending_ColorSpaceFlag);
+            return SkColorSpace::MakeSRGB();
         }
         case kRGBA_F16_SkColorType:
             return SkColorSpace::MakeSRGBLinear();
index 354bee6..3d3782b 100644 (file)
@@ -615,7 +615,9 @@ int32_t SkBmpCodec::getDstRow(int32_t y, int32_t height) const {
 
 SkCodec::Result SkBmpCodec::prepareToDecode(const SkImageInfo& dstInfo,
         const SkCodec::Options& options, SkPMColor inputColorPtr[], int* inputColorCount) {
-    if (!conversion_possible(dstInfo, this->getInfo()) || !this->initializeColorXform(dstInfo)) {
+    if (!conversion_possible(dstInfo, this->getInfo()) ||
+        !this->initializeColorXform(dstInfo, options.fPremulBehavior))
+    {
         return kInvalidConversion;
     }
 
index e9eeb45..5bdb3e2 100644 (file)
@@ -9,7 +9,7 @@
 #include "SkCodec.h"
 #include "SkCodecPriv.h"
 #include "SkColorSpace.h"
-#include "SkColorSpaceXform.h"
+#include "SkColorSpaceXform_Base.h"
 #include "SkData.h"
 #include "SkGifCodec.h"
 #include "SkHalf.h"
@@ -474,11 +474,14 @@ void SkCodec::fillIncompleteImage(const SkImageInfo& info, void* dst, size_t row
     }
 }
 
-bool SkCodec::initializeColorXform(const SkImageInfo& dstInfo) {
+bool SkCodec::initializeColorXform(const SkImageInfo& dstInfo,
+                                   SkTransferFunctionBehavior premulBehavior) {
     fColorXform = nullptr;
-    bool needsPremul = needs_premul(dstInfo, fEncodedInfo);
-    if (needs_color_xform(dstInfo, fSrcInfo, needsPremul)) {
-        fColorXform = SkColorSpaceXform::New(fSrcInfo.colorSpace(), dstInfo.colorSpace());
+    bool needsColorCorrectPremul = needs_premul(dstInfo, fEncodedInfo) &&
+                                   SkTransferFunctionBehavior::kRespect == premulBehavior;
+    if (needs_color_xform(dstInfo, fSrcInfo, needsColorCorrectPremul)) {
+        fColorXform = SkColorSpaceXform_Base::New(fSrcInfo.colorSpace(), dstInfo.colorSpace(),
+                                                  premulBehavior);
         if (!fColorXform) {
             return false;
         }
index 026120f..5bf0272 100644 (file)
@@ -301,7 +301,7 @@ static inline bool needs_premul(const SkImageInfo& dstInfo, const SkEncodedInfo&
 }
 
 static inline bool needs_color_xform(const SkImageInfo& dstInfo, const SkImageInfo& srcInfo,
-                                     bool needsPremul) {
+                                     bool needsColorCorrectPremul) {
     // We never perform a color xform in legacy mode.
     if (!dstInfo.colorSpace()) {
         return false;
@@ -314,10 +314,6 @@ static inline bool needs_color_xform(const SkImageInfo& dstInfo, const SkImageIn
     bool srcDstNotEqual =
             !SkColorSpace_Base::EqualsIgnoreFlags(srcInfo.colorSpace(), dstInfo.colorSpace());
 
-    // We provide the option for both legacy premuls and color correct premuls.
-    bool needsColorCorrectPremul =
-            needsPremul && !as_CSB(dstInfo.colorSpace())->nonLinearBlending();
-
     return needsColorCorrectPremul || isF16 || srcDstNotEqual;
 }
 
index 2903717..a70f7be 100644 (file)
@@ -183,7 +183,9 @@ void SkGifCodec::initializeColorTable(const SkImageInfo& dstInfo, size_t frameIn
 SkCodec::Result SkGifCodec::prepareToDecode(const SkImageInfo& dstInfo, SkPMColor* inputColorPtr,
         int* inputColorCount, const Options& opts) {
     // Check for valid input parameters
-    if (!conversion_possible(dstInfo, this->getInfo()) || !this->initializeColorXform(dstInfo)) {
+    if (!conversion_possible(dstInfo, this->getInfo()) ||
+        !this->initializeColorXform(dstInfo, opts.fPremulBehavior))
+    {
         return gif_error("Cannot convert input type to output type.\n", kInvalidConversion);
     }
 
index 624bc25..213c587 100644 (file)
@@ -583,7 +583,7 @@ SkCodec::Result SkJpegCodec::onGetPixels(const SkImageInfo& dstInfo,
         return fDecoderMgr->returnFailure("setjmp", kInvalidInput);
     }
 
-    if (!this->initializeColorXform(dstInfo)) {
+    if (!this->initializeColorXform(dstInfo, options.fPremulBehavior)) {
         return kInvalidConversion;
     }
 
@@ -692,7 +692,7 @@ SkCodec::Result SkJpegCodec::onStartScanlineDecode(const SkImageInfo& dstInfo,
         return kInvalidInput;
     }
 
-    if (!this->initializeColorXform(dstInfo)) {
+    if (!this->initializeColorXform(dstInfo, options.fPremulBehavior)) {
         return kInvalidConversion;
     }
 
index b6258ab..901f55f 100644 (file)
@@ -1093,7 +1093,7 @@ bool SkPngCodec::initializeXforms(const SkImageInfo& dstInfo, const Options& opt
     // interlaced scanline decoder may need to rewind.
     fSwizzler.reset(nullptr);
 
-    if (!this->initializeColorXform(dstInfo)) {
+    if (!this->initializeColorXform(dstInfo, options.fPremulBehavior)) {
         return false;
     }
 
index 97baa9c..272f737 100644 (file)
@@ -690,7 +690,9 @@ SkCodec::Result SkRawCodec::onGetPixels(const SkImageInfo& dstInfo, void* dst,
                                         size_t dstRowBytes, const Options& options,
                                         SkPMColor ctable[], int* ctableCount,
                                         int* rowsDecoded) {
-    if (!conversion_possible(dstInfo, this->getInfo()) || !this->initializeColorXform(dstInfo)) {
+    if (!conversion_possible(dstInfo, this->getInfo()) ||
+        !this->initializeColorXform(dstInfo, options.fPremulBehavior))
+    {
         SkCodecPrintf("Error: cannot convert input type to output type.\n");
         return kInvalidConversion;
     }
index 1d9953b..2b6483b 100644 (file)
@@ -75,6 +75,7 @@ SkCodec::Result SkSampledCodec::onGetAndroidPixels(const SkImageInfo& info, void
     // Create an Options struct for the codec.
     SkCodec::Options codecOptions;
     codecOptions.fZeroInitialized = options.fZeroInitialized;
+    codecOptions.fPremulBehavior = SkTransferFunctionBehavior::kIgnore;
 
     SkIRect* subset = options.fSubset;
     if (!subset || subset->size() == this->codec()->getInfo().dimensions()) {
@@ -171,6 +172,7 @@ SkCodec::Result SkSampledCodec::sampledDecode(const SkImageInfo& info, void* pix
     // Create options struct for the codec.
     SkCodec::Options sampledOptions;
     sampledOptions.fZeroInitialized = options.fZeroInitialized;
+    sampledOptions.fPremulBehavior = SkTransferFunctionBehavior::kIgnore;
 
     // FIXME: This was already called by onGetAndroidPixels. Can we reduce that?
     int sampleSize = options.fSampleSize;
index 5aefe5d..cf1f0e0 100644 (file)
@@ -40,6 +40,7 @@ SkCodec::Result SkWebpAdapterCodec::onGetAndroidPixels(const SkImageInfo& info,
     SkCodec::Options codecOptions;
     codecOptions.fZeroInitialized = options.fZeroInitialized;
     codecOptions.fSubset = options.fSubset;
+    codecOptions.fPremulBehavior = SkTransferFunctionBehavior::kIgnore;
     return this->codec()->getPixels(info, pixels, rowBytes, &codecOptions, options.fColorPtr,
             options.fColorCount);
 }
index c602fcd..ae8668b 100644 (file)
@@ -194,11 +194,9 @@ bool SkWebpCodec::onGetValidSubset(SkIRect* desiredSubset) const {
 SkCodec::Result SkWebpCodec::onGetPixels(const SkImageInfo& dstInfo, void* dst, size_t rowBytes,
                                          const Options& options, SkPMColor*, int*,
                                          int* rowsDecodedPtr) {
-    if (!conversion_possible(dstInfo, this->getInfo())) {
-        return kInvalidConversion;
-    }
-
-    if (!this->initializeColorXform(dstInfo)) {
+    if (!conversion_possible(dstInfo, this->getInfo()) ||
+        !this->initializeColorXform(dstInfo, options.fPremulBehavior))
+    {
         return kInvalidConversion;
     }
 
index b81c23c..3179920 100644 (file)
@@ -292,6 +292,12 @@ void SkColorSpaceXform_Base::BuildDstGammaTables(const uint8_t* dstGammaTables[3
 
 std::unique_ptr<SkColorSpaceXform> SkColorSpaceXform::New(SkColorSpace* srcSpace,
                                                           SkColorSpace* dstSpace) {
+    return SkColorSpaceXform_Base::New(srcSpace, dstSpace, SkTransferFunctionBehavior::kRespect);
+}
+
+std::unique_ptr<SkColorSpaceXform> SkColorSpaceXform_Base::New(SkColorSpace* srcSpace,
+        SkColorSpace* dstSpace, SkTransferFunctionBehavior premulBehavior) {
+
     if (!srcSpace || !dstSpace) {
         // Invalid input
         return nullptr;
@@ -328,13 +334,13 @@ std::unique_ptr<SkColorSpaceXform> SkColorSpaceXform::New(SkColorSpace* srcSpace
     switch (csm) {
         case kNone_ColorSpaceMatch:
             return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_XYZ
-                    <kNone_ColorSpaceMatch>(srcSpaceXYZ, srcToDst, dstSpaceXYZ));
+                    <kNone_ColorSpaceMatch>(srcSpaceXYZ, srcToDst, dstSpaceXYZ, premulBehavior));
         case kGamut_ColorSpaceMatch:
             return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_XYZ
-                    <kGamut_ColorSpaceMatch>(srcSpaceXYZ, srcToDst, dstSpaceXYZ));
+                    <kGamut_ColorSpaceMatch>(srcSpaceXYZ, srcToDst, dstSpaceXYZ, premulBehavior));
         case kFull_ColorSpaceMatch:
             return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_XYZ
-                    <kFull_ColorSpaceMatch>(srcSpaceXYZ, srcToDst, dstSpaceXYZ));
+                    <kFull_ColorSpaceMatch>(srcSpaceXYZ, srcToDst, dstSpaceXYZ, premulBehavior));
         default:
             SkASSERT(false);
             return nullptr;
@@ -931,8 +937,8 @@ static AI int num_tables(SkColorSpace_XYZ* space) {
 template <ColorSpaceMatch kCSM>
 SkColorSpaceXform_XYZ<kCSM>
 ::SkColorSpaceXform_XYZ(SkColorSpace_XYZ* srcSpace, const SkMatrix44& srcToDst,
-                        SkColorSpace_XYZ* dstSpace)
-    : fLinearBlending(!dstSpace->nonLinearBlending())
+                        SkColorSpace_XYZ* dstSpace, SkTransferFunctionBehavior premulBehavior)
+    : fPremulBehavior(premulBehavior)
 {
     fSrcToDst[ 0] = srcToDst.get(0, 0);
     fSrcToDst[ 1] = srcToDst.get(1, 0);
@@ -1227,7 +1233,8 @@ bool SkColorSpaceXform_XYZ<kCSM>
         }
     }
 
-    if (kPremul_SkAlphaType == alphaType && fLinearBlending) {
+    if (kPremul_SkAlphaType == alphaType && SkTransferFunctionBehavior::kRespect == fPremulBehavior)
+    {
         pipeline.append(SkRasterPipeline::premul);
     }
 
@@ -1249,7 +1256,8 @@ bool SkColorSpaceXform_XYZ<kCSM>
             break;
     }
 
-    if (kPremul_SkAlphaType == alphaType && !fLinearBlending) {
+    if (kPremul_SkAlphaType == alphaType && SkTransferFunctionBehavior::kIgnore == fPremulBehavior)
+    {
         pipeline.append(SkRasterPipeline::premul);
     }
 
@@ -1262,13 +1270,13 @@ bool SkColorSpaceXform_XYZ<kCSM>
             pipeline.append(SkRasterPipeline::store_8888, &dst);
             break;
         case kRGBA_F16_ColorFormat:
-            if (kLinear_DstGamma != fDstGamma || !fLinearBlending) {
+            if (kLinear_DstGamma != fDstGamma) {
                 return false;
             }
             pipeline.append(SkRasterPipeline::store_f16, &dst);
             break;
         case kRGBA_F32_ColorFormat:
-            if (kLinear_DstGamma != fDstGamma || !fLinearBlending) {
+            if (kLinear_DstGamma != fDstGamma) {
                 return false;
             }
             pipeline.append(SkRasterPipeline::store_f32, &dst);
@@ -1284,6 +1292,6 @@ bool SkColorSpaceXform_XYZ<kCSM>
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
 std::unique_ptr<SkColorSpaceXform> SlowIdentityXform(SkColorSpace_XYZ* space) {
-    return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_XYZ
-            <kNone_ColorSpaceMatch>(space, SkMatrix::I(), space));
+    return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_XYZ<kNone_ColorSpaceMatch>
+            (space, SkMatrix::I(), space, SkTransferFunctionBehavior::kRespect));
 }
index 9376491..9374020 100644 (file)
@@ -53,7 +53,7 @@ private:
     std::forward_list<std::vector<float>>        fTableStorage;
     std::vector<sk_sp<const SkGammas>>           fGammaRefs;
 
-    friend class SkColorSpaceXform;
+    friend class SkColorSpaceXform_Base;
 };
 
 #endif
index cb98c68..f72ace0 100644 (file)
@@ -19,6 +19,9 @@ class SkColorSpaceXform_Base : public SkColorSpaceXform {
 public:
     static constexpr int kDstGammaTableSize = 1024;
 
+    static std::unique_ptr<SkColorSpaceXform> New(SkColorSpace* srcSpace, SkColorSpace* dstSpace,
+                                                  SkTransferFunctionBehavior premulBehavior);
+
 protected:
     virtual bool onApply(ColorFormat dstFormat, void* dst, ColorFormat srcFormat, const void* src,
                          int count, SkAlphaType alphaType) const = 0;
@@ -61,22 +64,22 @@ private:
                        int count, SkAlphaType alphaType) const;
 
     SkColorSpaceXform_XYZ(SkColorSpace_XYZ* srcSpace, const SkMatrix44& srcToDst,
-                          SkColorSpace_XYZ* dstSpace);
+                          SkColorSpace_XYZ* dstSpace, SkTransferFunctionBehavior premulBehavior);
 
     // Contain pointers into storage or pointers into precomputed tables.
-    const float*         fSrcGammaTables[3];
-    SkAutoTMalloc<float> fSrcStorage;
-    const uint8_t*       fDstGammaTables[3];
-    sk_sp<SkData>        fDstStorage;
+    const float*               fSrcGammaTables[3];
+    SkAutoTMalloc<float>       fSrcStorage;
+    const uint8_t*             fDstGammaTables[3];
+    sk_sp<SkData>              fDstStorage;
 
     // Holds a 3x4 matrix.  Padding is useful for vector loading.
-    float                fSrcToDst[13];
+    float                      fSrcToDst[13];
 
-    SrcGamma             fSrcGamma;
-    DstGamma             fDstGamma;
-    bool                 fLinearBlending;
+    SrcGamma                   fSrcGamma;
+    DstGamma                   fDstGamma;
+    SkTransferFunctionBehavior fPremulBehavior;
 
-    friend class SkColorSpaceXform;
+    friend class SkColorSpaceXform_Base;
     friend std::unique_ptr<SkColorSpaceXform> SlowIdentityXform(SkColorSpace_XYZ* space);
 };
 
index 69d45fb..540d930 100644 (file)
 #include "SkImageEncoder.h"
 
 struct SkEncodeOptions {
-    enum class ColorBehavior {
-         // Convert to a linear space before premultiplying or unpremultiplying.
-        kCorrect,
-
-        // Ignore the transfer function when premultiplying or unpremultiplying.
-        kLegacy,
-    };
-
-    ColorBehavior fColorBehavior = ColorBehavior::kLegacy;
+    SkTransferFunctionBehavior fUnpremulBehavior = SkTransferFunctionBehavior::kIgnore;
 };
 
 #ifdef SK_HAS_JPEG_LIBRARY
index 014a0ae..8456734 100644 (file)
@@ -86,7 +86,7 @@ bool SkEncodeImageAsJPEG(SkWStream* stream, const SkPixmap& pixmap, const SkEnco
             pixmap.colorSpace()->gammaIsLinear());
 
     SkPixmap src = pixmap;
-    if (SkEncodeOptions::ColorBehavior::kLegacy == opts.fColorBehavior) {
+    if (SkTransferFunctionBehavior::kIgnore == opts.fUnpremulBehavior) {
         src.setColorSpace(nullptr);
     } else {
         // kCorrect behavior requires a color space.  It's not actually critical in the
index e28ae12..9f5ebd2 100644 (file)
@@ -181,7 +181,7 @@ bool SkEncodeImageAsPNG(SkWStream* stream, const SkPixmap& src, const SkEncodeOp
              src.colorSpace()->gammaIsLinear());
 
     SkPixmap pixmap = src;
-    if (SkEncodeOptions::ColorBehavior::kLegacy == opts.fColorBehavior) {
+    if (SkTransferFunctionBehavior::kIgnore == opts.fUnpremulBehavior) {
         pixmap.setColorSpace(nullptr);
     } else {
         if (!pixmap.colorSpace()) {
index a9fcc31..28dff05 100644 (file)
@@ -126,7 +126,7 @@ static bool do_encode(SkWStream* stream, const SkPixmap& srcPixmap, const SkEnco
             srcPixmap.colorSpace()->gammaIsLinear());
 
     SkPixmap pixmap = srcPixmap;
-    if (SkEncodeOptions::ColorBehavior::kLegacy == opts.fColorBehavior) {
+    if (SkTransferFunctionBehavior::kIgnore == opts.fUnpremulBehavior) {
         pixmap.setColorSpace(nullptr);
     } else {
         if (!pixmap.colorSpace()) {
index da75ffb..dd11ff8 100644 (file)
@@ -1555,7 +1555,7 @@ static void test_encode_icc(skiatest::Reporter* r, SkEncodedImageFormat format)
     srgbBitmap.peekPixels(&pixmap);
     SkDynamicMemoryWStream srgbBuf;
     SkEncodeOptions opts;
-    opts.fColorBehavior = SkEncodeOptions::ColorBehavior::kCorrect;
+    opts.fUnpremulBehavior = SkTransferFunctionBehavior::kRespect;
     encode_format(&srgbBuf, pixmap, opts, format);
     sk_sp<SkData> srgbData = srgbBuf.detachAsData();
     std::unique_ptr<SkCodec> srgbCodec(SkCodec::NewFromData(srgbData));