Always encode images with sRGB encoded pixels

Bug: skia:
Change-Id: Icb25bc21a30e88f21df5b0e267d5a3a05535e44a
Reviewed-on: https://skia-review.googlesource.com/19544
Commit-Queue: Matt Sarett <msarett@google.com>
Commit-Queue: Mike Klein <mtklein@chromium.org>
Reviewed-by: Mike Klein <mtklein@chromium.org>
(cherry picked from commit 1950e0a868774330330555a9a368992218f42240)
Reviewed-on: https://skia-review.googlesource.com/19814
Reviewed-by: Matt Sarett <msarett@google.com>
diff --git a/src/images/SkImageEncoderFns.h b/src/images/SkImageEncoderFns.h
index b01f1cd..6b49b2d 100644
--- a/src/images/SkImageEncoderFns.h
+++ b/src/images/SkImageEncoderFns.h
@@ -15,6 +15,7 @@
 #include "SkBitmap.h"
 #include "SkColor.h"
 #include "SkColorPriv.h"
+#include "SkColorSpace_Base.h"
 #include "SkICC.h"
 #include "SkOpts.h"
 #include "SkPreConfig.h"
@@ -256,6 +257,7 @@
                                           int width, int, const SkPMColor*) {
     SkRasterPipeline_<256> p;
     p.append(SkRasterPipeline::load_f16, (const void**) &src);
+    p.append(SkRasterPipeline::to_srgb);
     p.append(SkRasterPipeline::store_u16_be, (void**) &dst);
     p.run(0, width);
 }
@@ -268,6 +270,7 @@
     SkRasterPipeline_<256> p;
     p.append(SkRasterPipeline::load_f16, (const void**) &src);
     p.append(SkRasterPipeline::unpremul);
+    p.append(SkRasterPipeline::to_srgb);
     p.append(SkRasterPipeline::store_u16_be, (void**) &dst);
     p.run(0, width);
 }
@@ -312,10 +315,21 @@
     p.run(0, width);
 }
 
-static inline sk_sp<SkData> icc_from_color_space(const SkColorSpace& cs) {
+static inline sk_sp<SkData> icc_from_color_space(const SkImageInfo& info) {
+    SkColorSpace* cs = info.colorSpace();
+    if (!cs) {
+        return nullptr;
+    }
+
+    sk_sp<SkColorSpace> owned;
+    if (kRGBA_F16_SkColorType == info.colorType()) {
+        owned = as_CSB(cs)->makeSRGBGamma();
+        cs = owned.get();
+    }
+
     SkColorSpaceTransferFn fn;
     SkMatrix44 toXYZD50(SkMatrix44::kUninitialized_Constructor);
-    if (cs.isNumericalTransferFn(&fn) && cs.toXYZD50(&toXYZD50)) {
+    if (cs->isNumericalTransferFn(&fn) && cs->toXYZD50(&toXYZD50)) {
         return SkICC::WriteToICC(fn, toXYZD50);
     }
 
diff --git a/src/images/SkJpegEncoder.cpp b/src/images/SkJpegEncoder.cpp
index eaea77e..a0ee398 100644
--- a/src/images/SkJpegEncoder.cpp
+++ b/src/images/SkJpegEncoder.cpp
@@ -207,29 +207,19 @@
     jpeg_set_quality(encoderMgr->cinfo(), options.fQuality, TRUE);
     jpeg_start_compress(encoderMgr->cinfo(), TRUE);
 
-    if (SkColorSpace* cs = src.colorSpace()) {
-        sk_sp<SkColorSpace> owned;
-        if (src.colorType() == kRGBA_F16_SkColorType) {
-            // We'll be converting to 8-bit sRGB, so we'd better tag it that way.
-            owned = as_CSB(src.colorSpace())->makeSRGBGamma();
-            cs = owned.get();
-        }
+    sk_sp<SkData> icc = icc_from_color_space(src.info());
+    if (icc) {
+        // Create a contiguous block of memory with the icc signature followed by the profile.
+        sk_sp<SkData> markerData =
+                SkData::MakeUninitialized(kICCMarkerHeaderSize + icc->size());
+        uint8_t* ptr = (uint8_t*) markerData->writable_data();
+        memcpy(ptr, kICCSig, sizeof(kICCSig));
+        ptr += sizeof(kICCSig);
+        *ptr++ = 1; // This is the first marker.
+        *ptr++ = 1; // Out of one total markers.
+        memcpy(ptr, icc->data(), icc->size());
 
-        sk_sp<SkData> icc = icc_from_color_space(*cs);
-        if (icc) {
-            // Create a contiguous block of memory with the icc signature followed by the profile.
-            sk_sp<SkData> markerData =
-                    SkData::MakeUninitialized(kICCMarkerHeaderSize + icc->size());
-            uint8_t* ptr = (uint8_t*) markerData->writable_data();
-            memcpy(ptr, kICCSig, sizeof(kICCSig));
-            ptr += sizeof(kICCSig);
-            *ptr++ = 1; // This is the first marker.
-            *ptr++ = 1; // Out of one total markers.
-            memcpy(ptr, icc->data(), icc->size());
-
-            jpeg_write_marker(encoderMgr->cinfo(), kICCMarker, markerData->bytes(),
-                              markerData->size());
-        }
+        jpeg_write_marker(encoderMgr->cinfo(), kICCMarker, markerData->bytes(), markerData->size());
     }
 
     return std::unique_ptr<SkJpegEncoder>(new SkJpegEncoder(std::move(encoderMgr), src));
diff --git a/src/images/SkPngEncoder.cpp b/src/images/SkPngEncoder.cpp
index d28657f..7a1bfcf 100644
--- a/src/images/SkPngEncoder.cpp
+++ b/src/images/SkPngEncoder.cpp
@@ -53,7 +53,7 @@
     bool setHeader(const SkImageInfo& srcInfo, const SkPngEncoder::Options& options);
     bool setPalette(const SkImageInfo& srcInfo, SkColorTable* colorTable,
                     SkTransferFunctionBehavior);
-    bool setColorSpace(SkColorSpace* colorSpace);
+    bool setColorSpace(const SkImageInfo& info);
     bool writeInfo(const SkImageInfo& srcInfo);
     void chooseProc(const SkImageInfo& srcInfo, SkTransferFunctionBehavior unpremulBehavior);
 
@@ -327,8 +327,8 @@
     return true;
 }
 
-static void set_icc(png_structp png_ptr, png_infop info_ptr, const SkColorSpace& colorSpace) {
-    sk_sp<SkData> icc = icc_from_color_space(colorSpace);
+static void set_icc(png_structp png_ptr, png_infop info_ptr, const SkImageInfo& info) {
+    sk_sp<SkData> icc = icc_from_color_space(info);
     if (!icc) {
         return;
     }
@@ -344,17 +344,15 @@
     png_set_iCCP(png_ptr, info_ptr, name, 0, iccPtr, icc->size());
 }
 
-bool SkPngEncoderMgr::setColorSpace(SkColorSpace* colorSpace) {
+bool SkPngEncoderMgr::setColorSpace(const SkImageInfo& info) {
     if (setjmp(png_jmpbuf(fPngPtr))) {
         return false;
     }
 
-    if (colorSpace) {
-        if (colorSpace->isSRGB()) {
-            png_set_sRGB(fPngPtr, fInfoPtr, PNG_sRGB_INTENT_PERCEPTUAL);
-        } else {
-            set_icc(fPngPtr, fInfoPtr, *colorSpace);
-        }
+    if (info.colorSpace() && info.colorSpace()->isSRGB()) {
+        png_set_sRGB(fPngPtr, fInfoPtr, PNG_sRGB_INTENT_PERCEPTUAL);
+    } else {
+        set_icc(fPngPtr, fInfoPtr, info);
     }
 
     return true;
@@ -401,7 +399,7 @@
         return nullptr;
     }
 
-    if (!encoderMgr->setColorSpace(src.colorSpace())) {
+    if (!encoderMgr->setColorSpace(src.info())) {
         return nullptr;
     }
 
diff --git a/src/images/SkWebpEncoder.cpp b/src/images/SkWebpEncoder.cpp
index 81ed7e1..296d4f4 100644
--- a/src/images/SkWebpEncoder.cpp
+++ b/src/images/SkWebpEncoder.cpp
@@ -194,16 +194,7 @@
     // If there is no need to embed an ICC profile, we write directly to the input stream.
     // Otherwise, we will first encode to |tmp| and use a mux to add the ICC chunk.  libwebp
     // forces us to have an encoded image before we can add a profile.
-    sk_sp<SkData> icc;
-    if (SkColorSpace* cs = pixmap.colorSpace()) {
-        sk_sp<SkColorSpace> owned;
-        if (pixmap.colorType() == kRGBA_F16_SkColorType) {
-            // We'll be converting to 8-bit sRGB, so we'd better tag it that way.
-            owned = as_CSB(pixmap.colorSpace())->makeSRGBGamma();
-            cs = owned.get();
-        }
-        icc = icc_from_color_space(*cs);
-    }
+    sk_sp<SkData> icc = icc_from_color_space(pixmap.info());
     SkDynamicMemoryWStream tmp;
     pic.custom_ptr = icc ? (void*)&tmp : (void*)stream;