blob: 366a2e9ac4e2d3520a760d90ca666c04a7331b01 [file] [log] [blame]
Matt Sarett909d3792016-12-22 10:52:25 -05001/*
2 * Copyright 2016 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
Mike Kleinc0bd9f92019-04-23 12:05:21 -05008#include "gm/gm.h"
9#include "include/codec/SkCodec.h"
Ben Wagner7fde8e12019-05-01 17:28:53 -040010#include "include/core/SkBitmap.h"
11#include "include/core/SkCanvas.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050012#include "include/core/SkColorSpace.h"
Ben Wagner7fde8e12019-05-01 17:28:53 -040013#include "include/core/SkData.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050014#include "include/core/SkImage.h"
Ben Wagner7fde8e12019-05-01 17:28:53 -040015#include "include/core/SkImageInfo.h"
16#include "include/core/SkPaint.h"
17#include "include/core/SkPicture.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050018#include "include/core/SkPictureRecorder.h"
Ben Wagner7fde8e12019-05-01 17:28:53 -040019#include "include/core/SkRect.h"
20#include "include/core/SkRefCnt.h"
21#include "include/core/SkSize.h"
22#include "include/core/SkStream.h"
23#include "include/core/SkString.h"
24#include "include/core/SkTypes.h"
25#include "include/third_party/skcms/skcms.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050026#include "tools/Resources.h"
Matt Sarett909d3792016-12-22 10:52:25 -050027
Ben Wagner7fde8e12019-05-01 17:28:53 -040028#include <string.h>
29#include <memory>
30#include <utility>
31
32class GrContext;
33
Matt Sarett909d3792016-12-22 10:52:25 -050034static const int kWidth = 64;
35static const int kHeight = 64;
36
Brian Osmanb1168a72017-03-20 14:21:18 -040037static sk_sp<SkImage> make_raster_image(SkColorType colorType) {
Hal Canaryc465d132017-12-08 10:21:31 -050038 std::unique_ptr<SkStream> stream(GetResourceAsStream("images/google_chrome.ico"));
Mike Reedede7bac2017-07-23 15:30:02 -040039 std::unique_ptr<SkCodec> codec = SkCodec::MakeFromStream(std::move(stream));
Hal Canarybaa2a282018-11-26 15:34:12 -050040 if (!codec) {
41 return nullptr;
42 }
Matt Sarett909d3792016-12-22 10:52:25 -050043
44 SkBitmap bitmap;
45 SkImageInfo info = codec->getInfo().makeWH(kWidth, kHeight)
46 .makeColorType(colorType)
Brian Osman6b622962018-08-27 19:16:02 +000047 .makeAlphaType(kPremul_SkAlphaType);
Matt Sarett909d3792016-12-22 10:52:25 -050048 bitmap.allocPixels(info);
49 codec->getPixels(info, bitmap.getPixels(), bitmap.rowBytes());
50 bitmap.setImmutable();
51 return SkImage::MakeFromBitmap(bitmap);
52}
53
Matt Sarett34855f92017-01-10 17:41:53 -050054static sk_sp<SkImage> make_codec_image() {
Hal Canaryc465d132017-12-08 10:21:31 -050055 sk_sp<SkData> encoded = GetResourceAsData("images/randPixels.png");
Matt Sarett34855f92017-01-10 17:41:53 -050056 return SkImage::MakeFromEncoded(encoded);
57}
58
59static void draw_contents(SkCanvas* canvas) {
60 SkPaint paint;
61 paint.setStyle(SkPaint::kStroke_Style);
62 paint.setStrokeWidth(20);
63 paint.setColor(0xFF800000);
64 canvas->drawCircle(40, 40, 35, paint);
65 paint.setColor(0xFF008000);
66 canvas->drawCircle(50, 50, 35, paint);
67 paint.setColor(0xFF000080);
68 canvas->drawCircle(60, 60, 35, paint);
69}
70
Matt Sarett9df70bb2017-02-14 13:50:43 -050071static sk_sp<SkImage> make_picture_image() {
Matt Sarett34855f92017-01-10 17:41:53 -050072 SkPictureRecorder recorder;
73 draw_contents(recorder.beginRecording(SkRect::MakeIWH(kWidth, kHeight)));
74 return SkImage::MakeFromPicture(recorder.finishRecordingAsPicture(),
75 SkISize::Make(kWidth, kHeight), nullptr, nullptr,
76 SkImage::BitDepth::kU8,
Matt Sarett77a7a1b2017-02-07 13:56:11 -050077 SkColorSpace::MakeSRGB());
Matt Sarett34855f92017-01-10 17:41:53 -050078}
79
Matt Sarett733340a2017-05-02 16:19:51 -040080static sk_sp<SkColorSpace> make_parametric_transfer_fn(const SkColorSpacePrimaries& primaries) {
Brian Osman82ebe042019-01-04 17:03:00 -050081 skcms_Matrix3x3 toXYZD50;
Matt Sarett909d3792016-12-22 10:52:25 -050082 SkAssertResult(primaries.toXYZD50(&toXYZD50));
Brian Osman82ebe042019-01-04 17:03:00 -050083 skcms_TransferFunction fn = { 1.8f, 1.f, 0.f, 0.f, 0.f, 0.f, 0.f };
Matt Sarett733340a2017-05-02 16:19:51 -040084 return SkColorSpace::MakeRGB(fn, toXYZD50);
Matt Sarett909d3792016-12-22 10:52:25 -050085}
86
87static sk_sp<SkColorSpace> make_wide_gamut() {
88 // ProPhoto
89 SkColorSpacePrimaries primaries;
90 primaries.fRX = 0.7347f;
91 primaries.fRY = 0.2653f;
92 primaries.fGX = 0.1596f;
93 primaries.fGY = 0.8404f;
94 primaries.fBX = 0.0366f;
95 primaries.fBY = 0.0001f;
96 primaries.fWX = 0.34567f;
97 primaries.fWY = 0.35850f;
Matt Sarett733340a2017-05-02 16:19:51 -040098 return make_parametric_transfer_fn(primaries);
Matt Sarett909d3792016-12-22 10:52:25 -050099}
100
101static sk_sp<SkColorSpace> make_small_gamut() {
102 SkColorSpacePrimaries primaries;
103 primaries.fRX = 0.50f;
104 primaries.fRY = 0.33f;
105 primaries.fGX = 0.30f;
106 primaries.fGY = 0.50f;
107 primaries.fBX = 0.25f;
108 primaries.fBY = 0.16f;
109 primaries.fWX = 0.3127f;
110 primaries.fWY = 0.3290f;
Matt Sarett733340a2017-05-02 16:19:51 -0400111 return make_parametric_transfer_fn(primaries);
Matt Sarett909d3792016-12-22 10:52:25 -0500112}
113
114static void draw_image(SkCanvas* canvas, SkImage* image, SkColorType dstColorType,
Matt Sarett34855f92017-01-10 17:41:53 -0500115 SkAlphaType dstAlphaType, sk_sp<SkColorSpace> dstColorSpace,
116 SkImage::CachingHint hint) {
Matt Sarett909d3792016-12-22 10:52:25 -0500117 size_t rowBytes = image->width() * SkColorTypeBytesPerPixel(dstColorType);
118 sk_sp<SkData> data = SkData::MakeUninitialized(rowBytes * image->height());
Matt Sarett909d3792016-12-22 10:52:25 -0500119 SkImageInfo dstInfo = SkImageInfo::Make(image->width(), image->height(), dstColorType,
120 dstAlphaType, dstColorSpace);
Brian Osman89150582017-03-20 16:54:28 -0400121 if (!image->readPixels(dstInfo, data->writable_data(), rowBytes, 0, 0, hint)) {
122 memset(data->writable_data(), 0, rowBytes * image->height());
123 }
Matt Sarett909d3792016-12-22 10:52:25 -0500124
Matt Sarett909d3792016-12-22 10:52:25 -0500125 // Now that we have called readPixels(), dump the raw pixels into an srgb image.
Brian Osman6b622962018-08-27 19:16:02 +0000126 sk_sp<SkColorSpace> srgb = SkColorSpace::MakeSRGB();
Matt Sarett909d3792016-12-22 10:52:25 -0500127 sk_sp<SkImage> raw = SkImage::MakeRasterData(dstInfo.makeColorSpace(srgb), data, rowBytes);
128 canvas->drawImage(raw.get(), 0.0f, 0.0f, nullptr);
129}
130
131class ReadPixelsGM : public skiagm::GM {
132public:
133 ReadPixelsGM() {}
134
135protected:
136 SkString onShortName() override {
137 return SkString("readpixels");
138 }
139
140 SkISize onISize() override {
Brian Osmanb1168a72017-03-20 14:21:18 -0400141 return SkISize::Make(6 * kWidth, 9 * kHeight);
Matt Sarett909d3792016-12-22 10:52:25 -0500142 }
143
144 void onDraw(SkCanvas* canvas) override {
Matt Sarett909d3792016-12-22 10:52:25 -0500145 const SkAlphaType alphaTypes[] = {
146 kUnpremul_SkAlphaType,
147 kPremul_SkAlphaType,
148 };
149 const SkColorType colorTypes[] = {
150 kRGBA_8888_SkColorType,
151 kBGRA_8888_SkColorType,
152 kRGBA_F16_SkColorType,
153 };
154 const sk_sp<SkColorSpace> colorSpaces[] = {
155 make_wide_gamut(),
Matt Sarett77a7a1b2017-02-07 13:56:11 -0500156 SkColorSpace::MakeSRGB(),
Matt Sarett909d3792016-12-22 10:52:25 -0500157 make_small_gamut(),
158 };
159
160 for (sk_sp<SkColorSpace> dstColorSpace : colorSpaces) {
161 for (SkColorType srcColorType : colorTypes) {
Brian Osmanb1168a72017-03-20 14:21:18 -0400162 canvas->save();
163 sk_sp<SkImage> image = make_raster_image(srcColorType);
Hal Canarybaa2a282018-11-26 15:34:12 -0500164 if (!image) {
165 continue;
166 }
Brian Osman89150582017-03-20 16:54:28 -0400167 if (GrContext* context = canvas->getGrContext()) {
Brian Osmand566e2e2019-08-14 13:19:04 -0400168 image = image->makeTextureImage(context);
Brian Osman89150582017-03-20 16:54:28 -0400169 }
170 if (image) {
171 for (SkColorType dstColorType : colorTypes) {
172 for (SkAlphaType dstAlphaType : alphaTypes) {
173 draw_image(canvas, image.get(), dstColorType, dstAlphaType,
174 dstColorSpace, SkImage::kAllow_CachingHint);
175 canvas->translate((float)kWidth, 0.0f);
176 }
Matt Sarett909d3792016-12-22 10:52:25 -0500177 }
Matt Sarett909d3792016-12-22 10:52:25 -0500178 }
Brian Osmanb1168a72017-03-20 14:21:18 -0400179 canvas->restore();
180 canvas->translate(0.0f, (float) kHeight);
Matt Sarett909d3792016-12-22 10:52:25 -0500181 }
182 }
183 }
184
185private:
186 typedef skiagm::GM INHERITED;
187};
188DEF_GM( return new ReadPixelsGM; )
Matt Sarett34855f92017-01-10 17:41:53 -0500189
190class ReadPixelsCodecGM : public skiagm::GM {
191public:
192 ReadPixelsCodecGM() {}
193
194protected:
195 SkString onShortName() override {
196 return SkString("readpixelscodec");
197 }
198
199 SkISize onISize() override {
200 return SkISize::Make(3 * (kEncodedWidth + 1), 12 * (kEncodedHeight + 1));
201 }
202
Chris Dalton50e24d72019-02-07 16:20:09 -0700203 DrawResult onDraw(SkCanvas* canvas, SkString* errorMsg) override {
Matt Sarett34855f92017-01-10 17:41:53 -0500204 if (!canvas->imageInfo().colorSpace()) {
Chris Dalton50e24d72019-02-07 16:20:09 -0700205 *errorMsg = "This gm is only interesting in color correct modes.";
206 return DrawResult::kSkip;
Matt Sarett34855f92017-01-10 17:41:53 -0500207 }
208
209 const SkAlphaType alphaTypes[] = {
210 kUnpremul_SkAlphaType,
211 kPremul_SkAlphaType,
212 };
213 const SkColorType colorTypes[] = {
214 kRGBA_8888_SkColorType,
215 kBGRA_8888_SkColorType,
216 kRGBA_F16_SkColorType,
217 };
218 const sk_sp<SkColorSpace> colorSpaces[] = {
219 make_wide_gamut(),
Matt Sarett77a7a1b2017-02-07 13:56:11 -0500220 SkColorSpace::MakeSRGB(),
Matt Sarett34855f92017-01-10 17:41:53 -0500221 make_small_gamut(),
222 };
223 const SkImage::CachingHint hints[] = {
224 SkImage::kAllow_CachingHint,
225 SkImage::kDisallow_CachingHint,
226 };
227
228 sk_sp<SkImage> image = make_codec_image();
229 for (sk_sp<SkColorSpace> dstColorSpace : colorSpaces) {
230 canvas->save();
231 for (SkColorType dstColorType : colorTypes) {
232 for (SkAlphaType dstAlphaType : alphaTypes) {
233 for (SkImage::CachingHint hint : hints) {
234 draw_image(canvas, image.get(), dstColorType, dstAlphaType, dstColorSpace,
235 hint);
236 canvas->translate(0.0f, (float) kEncodedHeight + 1);
237 }
238 }
239 }
240 canvas->restore();
241 canvas->translate((float) kEncodedWidth + 1, 0.0f);
242 }
Chris Dalton50e24d72019-02-07 16:20:09 -0700243 return DrawResult::kOk;
Matt Sarett34855f92017-01-10 17:41:53 -0500244 }
245
246private:
247 static const int kEncodedWidth = 8;
248 static const int kEncodedHeight = 8;
249
250 typedef skiagm::GM INHERITED;
251};
252DEF_GM( return new ReadPixelsCodecGM; )
253
254class ReadPixelsPictureGM : public skiagm::GM {
255public:
256 ReadPixelsPictureGM() {}
257
258protected:
259 SkString onShortName() override {
260 return SkString("readpixelspicture");
261 }
262
263 SkISize onISize() override {
264 return SkISize::Make(3 * kWidth, 12 * kHeight);
265 }
266
Chris Dalton50e24d72019-02-07 16:20:09 -0700267 DrawResult onDraw(SkCanvas* canvas, SkString* errorMsg) override {
Matt Sarett34855f92017-01-10 17:41:53 -0500268 if (!canvas->imageInfo().colorSpace()) {
Chris Dalton50e24d72019-02-07 16:20:09 -0700269 *errorMsg = "This gm is only interesting in color correct modes.";
270 return DrawResult::kSkip;
Matt Sarett34855f92017-01-10 17:41:53 -0500271 }
272
273 const sk_sp<SkImage> images[] = {
Matt Sarett9df70bb2017-02-14 13:50:43 -0500274 make_picture_image(),
Matt Sarett34855f92017-01-10 17:41:53 -0500275 };
276 const SkAlphaType alphaTypes[] = {
277 kUnpremul_SkAlphaType,
278 kPremul_SkAlphaType,
279 };
280 const SkColorType colorTypes[] = {
281 kRGBA_8888_SkColorType,
282 kBGRA_8888_SkColorType,
283 kRGBA_F16_SkColorType,
284 };
285 const sk_sp<SkColorSpace> colorSpaces[] = {
286 make_wide_gamut(),
Matt Sarett77a7a1b2017-02-07 13:56:11 -0500287 SkColorSpace::MakeSRGB(),
Matt Sarett34855f92017-01-10 17:41:53 -0500288 make_small_gamut(),
289 };
290 const SkImage::CachingHint hints[] = {
291 SkImage::kAllow_CachingHint,
292 SkImage::kDisallow_CachingHint,
293 };
294
295 for (sk_sp<SkImage> image : images) {
296 for (sk_sp<SkColorSpace> dstColorSpace : colorSpaces) {
297 canvas->save();
298 for (SkColorType dstColorType : colorTypes) {
299 for (SkAlphaType dstAlphaType : alphaTypes) {
300 for (SkImage::CachingHint hint : hints) {
301 draw_image(canvas, image.get(), dstColorType, dstAlphaType,
302 dstColorSpace, hint);
303 canvas->translate(0.0f, (float) kHeight);
304 }
305 }
306 }
307 canvas->restore();
308 canvas->translate((float) kWidth, 0.0f);
309 }
310 }
Chris Dalton50e24d72019-02-07 16:20:09 -0700311 return DrawResult::kOk;
Matt Sarett34855f92017-01-10 17:41:53 -0500312 }
313
314private:
315
316 typedef skiagm::GM INHERITED;
317};
318DEF_GM( return new ReadPixelsPictureGM; )