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>
This commit is contained in:
Matt Sarett 2017-03-14 14:10:48 -04:00 committed by Skia Commit-Bot
parent bdce9c2d73
commit 6de1310981
6 changed files with 93 additions and 6 deletions

View File

@ -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 {

View File

@ -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

View File

@ -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;

View File

@ -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(

View File

@ -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);
}

View File

@ -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) {