Add SkImage::makeColorSpace() to public API
authorMatt Sarett <msarett@google.com>
Wed, 5 Apr 2017 15:41:27 +0000 (11:41 -0400)
committerSkia Commit-Bot <skia-commit-bot@chromium.org>
Wed, 5 Apr 2017 16:17:15 +0000 (16:17 +0000)
Gives Chrome the flexibility to xform and cache
SkImages before they reach the
SkColorSpaceXformCanvas.

Bug: skia:
Change-Id: I1f188f385b953b5a958c15578ea66deffb4dc6c5
Reviewed-on: https://skia-review.googlesource.com/11290
Commit-Queue: Matt Sarett <msarett@google.com>
Reviewed-by: Mike Klein <mtklein@chromium.org>
Reviewed-by: Mike Reed <reed@google.com>
include/core/SkImage.h
src/core/SkColorSpaceXformer.cpp
src/image/SkImage.cpp
src/image/SkImage_Base.h
tests/ImageTest.cpp

index f504897..ace4fe7 100644 (file)
@@ -437,6 +437,22 @@ public:
      */
     bool isLazyGenerated() const;
 
+    /**
+     *  If |target| is supported, returns an SkImage in the |target| color space.
+     *  Otherwise, returns nullptr.
+     *
+     *  This will leave the image as is if it already in the |target| color space.
+     *  Otherwise, it will convert the pixels from the src color space to the |target|
+     *  color space.  If this->colorSpace() is nullptr, the src color space will be
+     *  treated as sRGB.
+     *
+     *  If |premulBehavior| is kIgnore, any premultiplication or unpremultiplication will
+     *  be performed in the gamma encoded space.  If it is kRespect, premultiplication is
+     *  assumed to be linear.
+     */
+    sk_sp<SkImage> makeColorSpace(sk_sp<SkColorSpace> target,
+                                  SkTransferFunctionBehavior premulBehavior) const;
+
 protected:
     SkImage(int width, int height, uint32_t uniqueID);
 
index 4d93fae..8a83dbc 100644 (file)
@@ -28,7 +28,7 @@ std::unique_ptr<SkColorSpaceXformer> SkColorSpaceXformer::Make(sk_sp<SkColorSpac
 }
 
 sk_sp<SkImage> SkColorSpaceXformer::apply(const SkImage* src) {
-    return as_IB(src)->makeColorSpace(fDst);
+    return src->makeColorSpace(fDst, SkTransferFunctionBehavior::kIgnore);
 }
 
 sk_sp<SkImage> SkColorSpaceXformer::apply(const SkBitmap& src) {
@@ -37,7 +37,7 @@ sk_sp<SkImage> SkColorSpaceXformer::apply(const SkBitmap& src) {
         return nullptr;
     }
 
-    sk_sp<SkImage> xformed = as_IB(image)->makeColorSpace(fDst);
+    sk_sp<SkImage> xformed = image->makeColorSpace(fDst, SkTransferFunctionBehavior::kIgnore);
     // We want to be sure we don't let the kNever_SkCopyPixelsMode image escape this stack frame.
     SkASSERT(xformed != image);
     return xformed;
index e45bbd7..0847eb1 100644 (file)
@@ -302,7 +302,13 @@ bool SkImage::isAlphaOnly() const {
     return as_IB(this)->onImageInfo().colorType() == kAlpha_8_SkColorType;
 }
 
-sk_sp<SkImage> SkImage_Base::makeColorSpace(sk_sp<SkColorSpace> target) const {
+sk_sp<SkImage> SkImage::makeColorSpace(sk_sp<SkColorSpace> target,
+                                       SkTransferFunctionBehavior premulBehavior) const {
+    if (SkTransferFunctionBehavior::kRespect == premulBehavior) {
+        // TODO (msarett, brianosman): Implement this.
+        return nullptr;
+    }
+
     SkColorSpaceTransferFn fn;
     if (!target || !target->isNumericalTransferFn(&fn)) {
         return nullptr;
@@ -313,11 +319,12 @@ sk_sp<SkImage> SkImage_Base::makeColorSpace(sk_sp<SkColorSpace> target) const {
     // (2) The color type is kAlpha8.
     if ((!this->colorSpace() && target->isSRGB()) ||
             SkColorSpace::Equals(this->colorSpace(), target.get()) ||
-            kAlpha_8_SkColorType == this->onImageInfo().colorType()) {
-        return sk_ref_sp(const_cast<SkImage_Base*>(this));
+            kAlpha_8_SkColorType == as_IB(this)->onImageInfo().colorType()) {
+        return sk_ref_sp(const_cast<SkImage*>(this));
     }
 
-    return this->onMakeColorSpace(std::move(target));
+    // TODO: We might consider making this a deferred conversion?
+    return as_IB(this)->onMakeColorSpace(std::move(target));
 }
 
 //////////////////////////////////////////////////////////////////////////////////////
index 5bdf940..062d785 100644 (file)
@@ -86,17 +86,10 @@ public:
         fAddedToCache.store(true);
     }
 
-    // Transforms image into the input color space.
-    sk_sp<SkImage> makeColorSpace(sk_sp<SkColorSpace> target) const;
-
     virtual bool onPinAsTexture(GrContext*) const { return false; }
     virtual void onUnpinAsTexture(GrContext*) const {}
 
-protected:
-    virtual sk_sp<SkImage> onMakeColorSpace(sk_sp<SkColorSpace>) const {
-        // TODO: Make this pure virtual.
-        return sk_ref_sp(const_cast<SkImage_Base*>(this));
-    }
+    virtual sk_sp<SkImage> onMakeColorSpace(sk_sp<SkColorSpace>) const = 0;
 
 private:
     // Set true by caches when they cache content that's derived from the current pixels.
index 9916ed3..22004a0 100644 (file)
@@ -1061,7 +1061,7 @@ DEF_TEST(Image_makeColorSpace, r) {
     *srgbBitmap.getAddr32(0, 0) = SkSwizzle_RGBA_to_PMColor(0xFF604020);
     srgbBitmap.setImmutable();
     sk_sp<SkImage> srgbImage = SkImage::MakeFromBitmap(srgbBitmap);
-    sk_sp<SkImage> p3Image = as_IB(srgbImage)->makeColorSpace(p3);
+    sk_sp<SkImage> p3Image = srgbImage->makeColorSpace(p3, SkTransferFunctionBehavior::kIgnore);
     SkBitmap p3Bitmap;
     bool success = p3Image->asLegacyBitmap(&p3Bitmap, SkImage::kRO_LegacyBitmapMode);
     REPORTER_ASSERT(r, success);
@@ -1070,7 +1070,8 @@ DEF_TEST(Image_makeColorSpace, r) {
     REPORTER_ASSERT(r, almost_equal(0x40, SkGetPackedG32(*p3Bitmap.getAddr32(0, 0))));
     REPORTER_ASSERT(r, almost_equal(0x5E, SkGetPackedB32(*p3Bitmap.getAddr32(0, 0))));
 
-    sk_sp<SkImage> adobeImage = as_IB(srgbImage)->makeColorSpace(adobeGamut);
+    sk_sp<SkImage> adobeImage = srgbImage->makeColorSpace(adobeGamut,
+                                                          SkTransferFunctionBehavior::kIgnore);
     SkBitmap adobeBitmap;
     success = adobeImage->asLegacyBitmap(&adobeBitmap, SkImage::kRO_LegacyBitmapMode);
     REPORTER_ASSERT(r, success);
@@ -1080,7 +1081,7 @@ DEF_TEST(Image_makeColorSpace, r) {
     REPORTER_ASSERT(r, almost_equal(0x4C, SkGetPackedB32(*adobeBitmap.getAddr32(0, 0))));
 
     srgbImage = GetResourceAsImage("1x1.png");
-    p3Image = as_IB(srgbImage)->makeColorSpace(p3);
+    p3Image = srgbImage->makeColorSpace(p3, SkTransferFunctionBehavior::kIgnore);
     success = p3Image->asLegacyBitmap(&p3Bitmap, SkImage::kRO_LegacyBitmapMode);
     REPORTER_ASSERT(r, success);
     p3Bitmap.lockPixels();