aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Matt Sarett <msarett@google.com>2017-03-14 14:10:48 -0400
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2017-03-14 18:44:36 +0000
commit6de131098113669e6c1fcf5d63c77b37bfaae4ad (patch)
treed314f91015ec1518454ba0cdbd001ce7c906429b
parentbdce9c2d73e3661f8061f73e35b74ba35d98e5ff (diff)
Begin implementation of SkImage_Base::makeColorSpace
Originally: https://skia-review.googlesource.com/9622 CQ_INCLUDE_TRYBOTS=skia.primary:Test-Mac-Clang-MacMini6.2-CPU-AVX-x86_64-Release,Test-Android-Clang-PixelC-CPU-TegraX1-arm64-Debug-Android BUG=skia: Change-Id: I7ef1daaab32892399e3333e4b2fc75d70a1900e4 Reviewed-on: https://skia-review.googlesource.com/9651 Commit-Queue: Matt Sarett <msarett@google.com> Reviewed-by: Matt Sarett <msarett@google.com>
-rw-r--r--src/core/SkColorSpaceXformCanvas.cpp4
-rw-r--r--src/image/SkImage.cpp13
-rw-r--r--src/image/SkImage_Base.h12
-rw-r--r--src/image/SkImage_Generator.cpp18
-rw-r--r--src/image/SkImage_Raster.cpp20
-rw-r--r--tests/ImageTest.cpp32
6 files changed, 93 insertions, 6 deletions
diff --git a/src/core/SkColorSpaceXformCanvas.cpp b/src/core/SkColorSpaceXformCanvas.cpp
index 89c81e5462..ac93e3a1ee 100644
--- a/src/core/SkColorSpaceXformCanvas.cpp
+++ b/src/core/SkColorSpaceXformCanvas.cpp
@@ -8,6 +8,7 @@
#include "SkColorFilter.h"
#include "SkColorSpaceXform.h"
#include "SkColorSpaceXformCanvas.h"
+#include "SkImage_Base.h"
#include "SkMakeUnique.h"
#include "SkNoDrawCanvas.h"
#include "SkSurface.h"
@@ -72,8 +73,7 @@ public:
}
sk_sp<const SkImage> xform(const SkImage* img) const {
- // TODO: for real
- return sk_ref_sp(img);
+ return as_IB(img)->makeColorSpace(fTargetCS);
}
void onDrawPaint(const SkPaint& paint) override {
diff --git a/src/image/SkImage.cpp b/src/image/SkImage.cpp
index d76276be1f..2513e844d1 100644
--- a/src/image/SkImage.cpp
+++ b/src/image/SkImage.cpp
@@ -312,6 +312,19 @@ bool SkImage::isAlphaOnly() const {
return as_IB(this)->onImageInfo().colorType() == kAlpha_8_SkColorType;
}
+sk_sp<SkImage> SkImage_Base::makeColorSpace(sk_sp<SkColorSpace> target) const {
+ SkColorSpaceTransferFn fn;
+ if (!target || !target->isNumericalTransferFn(&fn)) {
+ return nullptr;
+ }
+
+ if (SkColorSpace::Equals(this->colorSpace(), target.get())) {
+ return sk_ref_sp(const_cast<SkImage_Base*>(this));
+ }
+
+ return this->onMakeColorSpace(std::move(target));
+}
+
//////////////////////////////////////////////////////////////////////////////////////
#if !SK_SUPPORT_GPU
diff --git a/src/image/SkImage_Base.h b/src/image/SkImage_Base.h
index e08d7610f7..284af0d1a6 100644
--- a/src/image/SkImage_Base.h
+++ b/src/image/SkImage_Base.h
@@ -81,14 +81,18 @@ public:
fAddedToCache.store(true);
}
- virtual sk_sp<SkImage> onMakeColorSpace(sk_sp<SkColorSpace>) {
- // TODO: Implement this.
- return sk_ref_sp(this);
- }
+ // 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));
+ }
+
private:
// Set true by caches when they cache content that's derived from the current pixels.
mutable SkAtomic<bool> fAddedToCache;
diff --git a/src/image/SkImage_Generator.cpp b/src/image/SkImage_Generator.cpp
index ae3f9f83f4..fb80767999 100644
--- a/src/image/SkImage_Generator.cpp
+++ b/src/image/SkImage_Generator.cpp
@@ -40,6 +40,7 @@ public:
GrTexture* asTextureRef(GrContext*, const GrSamplerParams&, SkColorSpace*,
sk_sp<SkColorSpace>*, SkScalar scaleAdjust[2]) const override;
bool onIsLazyGenerated() const override { return true; }
+ sk_sp<SkImage> onMakeColorSpace(sk_sp<SkColorSpace>) const override;
private:
mutable SkImageCacherator fCache;
@@ -115,6 +116,23 @@ sk_sp<SkImage> SkImage_Generator::onMakeSubset(const SkIRect& subset) const {
return validator ? sk_sp<SkImage>(new SkImage_Generator(&validator)) : nullptr;
}
+sk_sp<SkImage> SkImage_Generator::onMakeColorSpace(sk_sp<SkColorSpace> target) const {
+ SkBitmap dst;
+ SkImageInfo dstInfo = fCache.info().makeColorSpace(target);
+ if (kIndex_8_SkColorType == dstInfo.colorType() ||
+ kGray_8_SkColorType == dstInfo.colorType()) {
+ dstInfo = dstInfo.makeColorType(kN32_SkColorType);
+ }
+ dst.allocPixels(dstInfo);
+
+ if (!fCache.directGeneratePixels(dstInfo, dst.getPixels(), dst.rowBytes(), 0, 0)) {
+ return nullptr;
+ }
+
+ dst.setImmutable();
+ return SkImage::MakeFromBitmap(dst);
+}
+
sk_sp<SkImage> SkImage::MakeFromGenerator(std::unique_ptr<SkImageGenerator> generator,
const SkIRect* subset) {
SkImageCacherator::Validator validator(
diff --git a/src/image/SkImage_Raster.cpp b/src/image/SkImage_Raster.cpp
index 220cc01b11..782093e27b 100644
--- a/src/image/SkImage_Raster.cpp
+++ b/src/image/SkImage_Raster.cpp
@@ -120,6 +120,8 @@ public:
return fBitmap.pixelRef() && fBitmap.pixelRef()->isLazyGenerated();
}
+ sk_sp<SkImage> onMakeColorSpace(sk_sp<SkColorSpace>) const override;
+
#if SK_SUPPORT_GPU
sk_sp<GrTexture> refPinnedTexture(uint32_t* uniqueID) const override;
bool onPinAsTexture(GrContext*) const override;
@@ -365,3 +367,21 @@ bool SkImage_Raster::onAsLegacyBitmap(SkBitmap* bitmap, LegacyBitmapMode mode) c
}
return this->INHERITED::onAsLegacyBitmap(bitmap, mode);
}
+
+sk_sp<SkImage> SkImage_Raster::onMakeColorSpace(sk_sp<SkColorSpace> target) const {
+ SkBitmap dst;
+ SkImageInfo dstInfo = fBitmap.info().makeColorSpace(target);
+ if (kIndex_8_SkColorType == dstInfo.colorType() ||
+ kGray_8_SkColorType == dstInfo.colorType())
+ {
+ dstInfo = dstInfo.makeColorType(kN32_SkColorType);
+ }
+ dst.allocPixels(dstInfo);
+
+ SkPixmap src;
+ SkAssertResult(this->onPeekPixels(&src));
+
+ SkAssertResult(dst.writePixels(src));
+ dst.setImmutable();
+ return SkImage::MakeFromBitmap(dst);
+}
diff --git a/tests/ImageTest.cpp b/tests/ImageTest.cpp
index 720f016c05..e0e64ead10 100644
--- a/tests/ImageTest.cpp
+++ b/tests/ImageTest.cpp
@@ -1050,6 +1050,10 @@ static sk_sp<SkImage> create_picture_image(sk_sp<SkColorSpace> space) {
nullptr, nullptr, SkImage::BitDepth::kU8, std::move(space));
};
+static inline bool almost_equal(int a, int b) {
+ return SkTAbs(a - b) <= 1;
+}
+
DEF_TEST(Image_ColorSpace, r) {
sk_sp<SkColorSpace> srgb = SkColorSpace::MakeSRGB();
sk_sp<SkImage> image = GetResourceAsImage("mandrill_512_q075.jpg");
@@ -1082,6 +1086,34 @@ DEF_TEST(Image_ColorSpace, r) {
REPORTER_ASSERT(r, SkColorSpace::Equals(rec2020.get(), image->colorSpace()));
}
+DEF_TEST(Image_makeColorSpace, r) {
+ sk_sp<SkColorSpace> p3 = SkColorSpace::MakeRGB(SkColorSpace::kSRGB_RenderTargetGamma,
+ SkColorSpace::kDCIP3_D65_Gamut);
+
+ SkBitmap srgbBitmap;
+ srgbBitmap.allocPixels(SkImageInfo::MakeS32(1, 1, kOpaque_SkAlphaType));
+ *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);
+ SkBitmap p3Bitmap;
+ bool success = p3Image->asLegacyBitmap(&p3Bitmap, SkImage::kRO_LegacyBitmapMode);
+ REPORTER_ASSERT(r, success);
+ p3Bitmap.lockPixels();
+ REPORTER_ASSERT(r, almost_equal(0x28, SkGetPackedR32(*p3Bitmap.getAddr32(0, 0))));
+ REPORTER_ASSERT(r, almost_equal(0x40, SkGetPackedG32(*p3Bitmap.getAddr32(0, 0))));
+ REPORTER_ASSERT(r, almost_equal(0x5E, SkGetPackedB32(*p3Bitmap.getAddr32(0, 0))));
+
+ srgbImage = GetResourceAsImage("1x1.png");
+ p3Image = as_IB(srgbImage)->makeColorSpace(p3);
+ success = p3Image->asLegacyBitmap(&p3Bitmap, SkImage::kRO_LegacyBitmapMode);
+ REPORTER_ASSERT(r, success);
+ p3Bitmap.lockPixels();
+ REPORTER_ASSERT(r, almost_equal(0x8B, SkGetPackedR32(*p3Bitmap.getAddr32(0, 0))));
+ REPORTER_ASSERT(r, almost_equal(0x82, SkGetPackedG32(*p3Bitmap.getAddr32(0, 0))));
+ REPORTER_ASSERT(r, almost_equal(0x77, SkGetPackedB32(*p3Bitmap.getAddr32(0, 0))));
+}
+
///////////////////////////////////////////////////////////////////////////////////////////////////
static void make_all_premul(SkBitmap* bm) {