Add color space to picture image as a creation parameter
This gives a picture image a preferred "native" color space, which
facilitates caching and other things.
BUG=skia:
Change-Id: I95988c14d17f96d7d870b3d1c3b723c36e2c170d
Reviewed-on: https://skia-review.googlesource.com/6158
Reviewed-by: Mike Reed <reed@google.com>
Reviewed-by: Florin Malita <fmalita@chromium.org>
Commit-Queue: Brian Osman <brianosman@google.com>
diff --git a/gm/image.cpp b/gm/image.cpp
index c1d3372..0bdd994 100644
--- a/gm/image.cpp
+++ b/gm/image.cpp
@@ -246,7 +246,8 @@
SkPictureRecorder recorder;
draw(recorder.beginRecording(SkRect::MakeIWH(info.width(), info.height())));
return SkImage::MakeFromPicture(recorder.finishRecordingAsPicture(),
- info.dimensions(), nullptr, nullptr);
+ info.dimensions(), nullptr, nullptr,
+ SkColorSpace::MakeNamed(SkColorSpace::kSRGB_Named));
}
static sk_sp<SkImage> make_codec(const SkImageInfo& info, GrContext*, void (*draw)(SkCanvas*)) {
@@ -343,7 +344,8 @@
SkPictureRecorder recorder;
draw_opaque_contents(recorder.beginRecording(SkRect::MakeIWH(info.width(), info.height())));
sk_sp<SkPicture> pict(recorder.finishRecordingAsPicture());
- return SkImageGenerator::NewFromPicture(info.dimensions(), pict.get(), nullptr, nullptr);
+ return SkImageGenerator::NewFromPicture(info.dimensions(), pict.get(), nullptr, nullptr,
+ SkColorSpace::MakeNamed(SkColorSpace::kSRGB_Named));
}
static SkImageGenerator* gen_png(const SkImageInfo& info) {
diff --git a/gm/image_pict.cpp b/gm/image_pict.cpp
index d2e1eba..229f3c5 100644
--- a/gm/image_pict.cpp
+++ b/gm/image_pict.cpp
@@ -62,14 +62,15 @@
// extract enough just for the oval.
const SkISize size = SkISize::Make(100, 100);
+ auto srgbColorSpace = SkColorSpace::MakeNamed(SkColorSpace::kSRGB_Named);
SkMatrix matrix;
matrix.setTranslate(-100, -100);
- fImage0 = SkImage::MakeFromPicture(fPicture, size, &matrix, nullptr);
+ fImage0 = SkImage::MakeFromPicture(fPicture, size, &matrix, nullptr, srgbColorSpace);
matrix.postTranslate(-50, -50);
matrix.postRotate(45);
matrix.postTranslate(50, 50);
- fImage1 = SkImage::MakeFromPicture(fPicture, size, &matrix, nullptr);
+ fImage1 = SkImage::MakeFromPicture(fPicture, size, &matrix, nullptr, srgbColorSpace);
}
void drawSet(SkCanvas* canvas) const {
@@ -107,7 +108,8 @@
static SkImageGenerator* make_pic_generator(GrContext*, SkPicture* pic) {
SkMatrix matrix;
matrix.setTranslate(-100, -100);
- return SkImageGenerator::NewFromPicture(SkISize::Make(100, 100), pic, &matrix, nullptr);
+ return SkImageGenerator::NewFromPicture(SkISize::Make(100, 100), pic, &matrix, nullptr,
+ SkColorSpace::MakeNamed(SkColorSpace::kSRGB_Named));
}
class RasterGenerator : public SkImageGenerator {
diff --git a/gm/image_shader.cpp b/gm/image_shader.cpp
index 49b1ed5..7803739 100644
--- a/gm/image_shader.cpp
+++ b/gm/image_shader.cpp
@@ -47,7 +47,8 @@
}
static sk_sp<SkImage> make_pict_gen(GrContext*, SkPicture* pic, const SkImageInfo& info) {
- return SkImage::MakeFromPicture(sk_ref_sp(pic), info.dimensions(), nullptr, nullptr);
+ return SkImage::MakeFromPicture(sk_ref_sp(pic), info.dimensions(), nullptr, nullptr,
+ SkColorSpace::MakeNamed(SkColorSpace::kSRGB_Named));
}
static sk_sp<SkImage> make_encode_gen(GrContext* ctx, SkPicture* pic, const SkImageInfo& info) {
diff --git a/gm/pictureimagegenerator.cpp b/gm/pictureimagegenerator.cpp
index ab4c808..b247af2 100644
--- a/gm/pictureimagegenerator.cpp
+++ b/gm/pictureimagegenerator.cpp
@@ -138,6 +138,7 @@
{ SkISize::Make(200, 100), -1, -1, 0.5f },
};
+ auto srgbColorSpace = SkColorSpace::MakeNamed(SkColorSpace::kSRGB_Named);
const unsigned kDrawsPerRow = 4;
const SkScalar kDrawSize = 250;
@@ -154,10 +155,14 @@
}
std::unique_ptr<SkImageGenerator> gen(
SkImageGenerator::NewFromPicture(configs[i].size, fPicture.get(), &m,
- p.getAlpha() != 255 ? &p : nullptr));
+ p.getAlpha() != 255 ? &p : nullptr,
+ srgbColorSpace));
+
+ SkImageInfo bmInfo = gen->getInfo().makeColorSpace(
+ sk_ref_sp(canvas->imageInfo().colorSpace()));
+
SkBitmap bm;
- SkAssertResult(gen->tryGenerateBitmap(&bm, SkImageInfo::MakeN32Premul(configs[i].size),
- nullptr));
+ SkAssertResult(gen->tryGenerateBitmap(&bm, bmInfo, nullptr));
const SkScalar x = kDrawSize * (i % kDrawsPerRow);
const SkScalar y = kDrawSize * (i / kDrawsPerRow);
diff --git a/gm/verylargebitmap.cpp b/gm/verylargebitmap.cpp
index 08ca481..280d117 100644
--- a/gm/verylargebitmap.cpp
+++ b/gm/verylargebitmap.cpp
@@ -32,7 +32,8 @@
SkPictureRecorder recorder;
draw(recorder.beginRecording(SkRect::MakeIWH(width, height)), width, height, colors);
return SkImage::MakeFromPicture(recorder.finishRecordingAsPicture(),
- SkISize::Make(width, height), nullptr, nullptr);
+ SkISize::Make(width, height), nullptr, nullptr,
+ SkColorSpace::MakeNamed(SkColorSpace::kSRGB_Named));
}
typedef sk_sp<SkImage> (*ImageMakerProc)(int width, int height, SkColor colors[2]);
diff --git a/include/core/SkImage.h b/include/core/SkImage.h
index 2cbcb0a..100298a 100644
--- a/include/core/SkImage.h
+++ b/include/core/SkImage.h
@@ -154,8 +154,15 @@
const SkISize nv12Sizes[2], GrSurfaceOrigin,
sk_sp<SkColorSpace> = nullptr);
+ /**
+ * Create a new image from the specified picture. The color space becomes a preferred
+ * color space for playback of the picture when retrieving the rasterized image contents.
+ */
static sk_sp<SkImage> MakeFromPicture(sk_sp<SkPicture>, const SkISize& dimensions,
- const SkMatrix*, const SkPaint*);
+ const SkMatrix*, const SkPaint*, sk_sp<SkColorSpace>);
+
+ static sk_sp<SkImage> MakeFromPicture(sk_sp<SkPicture> picture, const SkISize& dimensions,
+ const SkMatrix* matrix, const SkPaint* paint);
static sk_sp<SkImage> MakeTextureFromPixmap(GrContext*, const SkPixmap&, SkBudgeted budgeted);
diff --git a/include/core/SkImageGenerator.h b/include/core/SkImageGenerator.h
index eace286..0d24d3a 100644
--- a/include/core/SkImageGenerator.h
+++ b/include/core/SkImageGenerator.h
@@ -241,7 +241,7 @@
* time.
*/
static SkImageGenerator* NewFromPicture(const SkISize&, const SkPicture*, const SkMatrix*,
- const SkPaint*);
+ const SkPaint*, sk_sp<SkColorSpace>);
bool tryGenerateBitmap(SkBitmap* bm, const SkImageInfo& info, SkBitmap::Allocator* allocator);
diff --git a/src/core/SkPictureImageGenerator.cpp b/src/core/SkPictureImageGenerator.cpp
index d4cf92e..8e42d27 100644
--- a/src/core/SkPictureImageGenerator.cpp
+++ b/src/core/SkPictureImageGenerator.cpp
@@ -17,7 +17,7 @@
class SkPictureImageGenerator : SkImageGenerator {
public:
static SkImageGenerator* Create(const SkISize&, const SkPicture*, const SkMatrix*,
- const SkPaint*);
+ const SkPaint*, sk_sp<SkColorSpace>);
protected:
bool onGetPixels(const SkImageInfo& info, void* pixels, size_t rowBytes, SkPMColor ctable[],
@@ -30,7 +30,8 @@
#endif
private:
- SkPictureImageGenerator(const SkISize&, const SkPicture*, const SkMatrix*, const SkPaint*);
+ SkPictureImageGenerator(const SkImageInfo& info, const SkPicture*, const SkMatrix*,
+ const SkPaint*);
sk_sp<const SkPicture> fPicture;
SkMatrix fMatrix;
@@ -40,17 +41,29 @@
};
SkImageGenerator* SkPictureImageGenerator::Create(const SkISize& size, const SkPicture* picture,
- const SkMatrix* matrix, const SkPaint* paint) {
+ const SkMatrix* matrix, const SkPaint* paint,
+ sk_sp<SkColorSpace> colorSpace) {
if (!picture || size.isEmpty()) {
return nullptr;
}
- return new SkPictureImageGenerator(size, picture, matrix, paint);
+ SkColorType colorType;
+ if (!colorSpace || colorSpace->gammaCloseToSRGB()) {
+ colorType = kN32_SkColorType;
+ } else if (colorSpace->gammaIsLinear()) {
+ colorType = kRGBA_F16_SkColorType;
+ } else {
+ return nullptr;
+ }
+
+ SkImageInfo info = SkImageInfo::Make(size.width(), size.height(), colorType,
+ kPremul_SkAlphaType, std::move(colorSpace));
+ return new SkPictureImageGenerator(info, picture, matrix, paint);
}
-SkPictureImageGenerator::SkPictureImageGenerator(const SkISize& size, const SkPicture* picture,
+SkPictureImageGenerator::SkPictureImageGenerator(const SkImageInfo& info, const SkPicture* picture,
const SkMatrix* matrix, const SkPaint* paint)
- : INHERITED(SkImageInfo::MakeS32(size.width(), size.height(), kPremul_SkAlphaType))
+ : INHERITED(info)
, fPicture(SkRef(picture)) {
if (matrix) {
@@ -123,8 +136,9 @@
///////////////////////////////////////////////////////////////////////////////////////////////////
SkImageGenerator* SkImageGenerator::NewFromPicture(const SkISize& size, const SkPicture* picture,
- const SkMatrix* matrix, const SkPaint* paint) {
- return SkPictureImageGenerator::Create(size, picture, matrix, paint);
+ const SkMatrix* matrix, const SkPaint* paint,
+ sk_sp<SkColorSpace> colorSpace) {
+ return SkPictureImageGenerator::Create(size, picture, matrix, paint, std::move(colorSpace));
}
///////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/core/SkPictureShader.cpp b/src/core/SkPictureShader.cpp
index 23f2e31..e34ca99 100644
--- a/src/core/SkPictureShader.cpp
+++ b/src/core/SkPictureShader.cpp
@@ -157,6 +157,7 @@
}
sk_sp<SkShader> SkPictureShader::refBitmapShader(const SkMatrix& viewMatrix, const SkMatrix* localM,
+ SkColorSpace* dstColorSpace,
const int maxTextureSize) const {
SkASSERT(fPicture && !fPicture->cullRect().isEmpty());
@@ -225,7 +226,8 @@
SkMatrix::kFill_ScaleToFit);
sk_sp<SkImage> tileImage(
- SkImage::MakeFromPicture(fPicture, tileSize, &tileMatrix, nullptr));
+ SkImage::MakeFromPicture(fPicture, tileSize, &tileMatrix, nullptr,
+ sk_ref_sp(dstColorSpace)));
if (!tileImage) {
return nullptr;
}
@@ -245,7 +247,8 @@
}
SkShader::Context* SkPictureShader::onCreateContext(const ContextRec& rec, void* storage) const {
- sk_sp<SkShader> bitmapShader(this->refBitmapShader(*rec.fMatrix, rec.fLocalMatrix));
+ sk_sp<SkShader> bitmapShader(this->refBitmapShader(*rec.fMatrix, rec.fLocalMatrix,
+ rec.fDstColorSpace));
if (!bitmapShader) {
return nullptr;
}
@@ -323,7 +326,7 @@
maxTextureSize = args.fContext->caps()->maxTextureSize();
}
sk_sp<SkShader> bitmapShader(this->refBitmapShader(*args.fViewMatrix, args.fLocalMatrix,
- maxTextureSize));
+ args.fDstColorSpace, maxTextureSize));
if (!bitmapShader) {
return nullptr;
}
diff --git a/src/core/SkPictureShader.h b/src/core/SkPictureShader.h
index f2927a0..6de7e4a 100644
--- a/src/core/SkPictureShader.h
+++ b/src/core/SkPictureShader.h
@@ -41,6 +41,7 @@
SkPictureShader(sk_sp<SkPicture>, TileMode, TileMode, const SkMatrix*, const SkRect*);
sk_sp<SkShader> refBitmapShader(const SkMatrix&, const SkMatrix* localMatrix,
+ SkColorSpace* dstColorSpace,
const int maxTextureSize = 0) const;
sk_sp<SkPicture> fPicture;
diff --git a/src/image/SkImage.cpp b/src/image/SkImage.cpp
index 9aff820..7a71546 100644
--- a/src/image/SkImage.cpp
+++ b/src/image/SkImage.cpp
@@ -314,12 +314,18 @@
}
sk_sp<SkImage> SkImage::MakeFromPicture(sk_sp<SkPicture> picture, const SkISize& dimensions,
- const SkMatrix* matrix, const SkPaint* paint) {
+ const SkMatrix* matrix, const SkPaint* paint,
+ sk_sp<SkColorSpace> colorSpace) {
if (!picture) {
return nullptr;
}
- return MakeFromGenerator(SkImageGenerator::NewFromPicture(dimensions, picture.get(),
- matrix, paint));
+ return MakeFromGenerator(SkImageGenerator::NewFromPicture(dimensions, picture.get(), matrix,
+ paint, std::move(colorSpace)));
+}
+
+sk_sp<SkImage> SkImage::MakeFromPicture(sk_sp<SkPicture> picture, const SkISize& dimensions,
+ const SkMatrix* matrix, const SkPaint* paint) {
+ return MakeFromPicture(std::move(picture), dimensions, matrix, paint, nullptr);
}
sk_sp<SkImage> SkImage::makeWithFilter(const SkImageFilter* filter, const SkIRect& subset,
diff --git a/tests/ImageIsOpaqueTest.cpp b/tests/ImageIsOpaqueTest.cpp
index cc7255d..21ddb5d 100644
--- a/tests/ImageIsOpaqueTest.cpp
+++ b/tests/ImageIsOpaqueTest.cpp
@@ -124,7 +124,8 @@
SkImage::MakeRasterCopy(pmap),
GetResourceAsImage("mandrill_128.png"),
GetResourceAsImage("color_wheel.jpg"),
- SkImage::MakeFromPicture(make_picture(), { 10, 10 }, nullptr, nullptr),
+ SkImage::MakeFromPicture(make_picture(), { 10, 10 }, nullptr, nullptr,
+ SkColorSpace::MakeNamed(SkColorSpace::kSRGB_Named)),
})
{
REPORTER_ASSERT(reporter, image->isAlphaOnly() == false);
diff --git a/tests/ImageTest.cpp b/tests/ImageTest.cpp
index 3b99394..c801d67 100644
--- a/tests/ImageTest.cpp
+++ b/tests/ImageTest.cpp
@@ -129,7 +129,8 @@
SkCanvas* canvas = recorder.beginRecording(10, 10);
canvas->clear(SK_ColorCYAN);
return SkImage::MakeFromPicture(recorder.finishRecordingAsPicture(), SkISize::Make(10, 10),
- nullptr, nullptr);
+ nullptr, nullptr,
+ SkColorSpace::MakeNamed(SkColorSpace::kSRGB_Named));
};
#endif
// Want to ensure that our Release is called when the owning image is destroyed
diff --git a/tests/SkResourceCacheTest.cpp b/tests/SkResourceCacheTest.cpp
index c8da135..ed2ff74 100644
--- a/tests/SkResourceCacheTest.cpp
+++ b/tests/SkResourceCacheTest.cpp
@@ -329,7 +329,8 @@
SkCanvas* canvas = recorder.beginRecording(10, 10);
canvas->clear(SK_ColorCYAN);
return SkImage::MakeFromPicture(recorder.finishRecordingAsPicture(),
- SkISize::Make(10, 10), nullptr, nullptr);
+ SkISize::Make(10, 10), nullptr, nullptr,
+ SkColorSpace::MakeNamed(SkColorSpace::kSRGB_Named));
});
}
}