• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 
8 #include "gm.h"
9 #include "Resources.h"
10 #include "SkCodec.h"
11 #include "SkColorSpace.h"
12 #include "SkColorSpacePriv.h"
13 #include "SkHalf.h"
14 #include "SkImage.h"
15 #include "SkImageInfoPriv.h"
16 #include "SkPictureRecorder.h"
17 
18 static const int kWidth = 64;
19 static const int kHeight = 64;
20 
make_raster_image(SkColorType colorType)21 static sk_sp<SkImage> make_raster_image(SkColorType colorType) {
22     std::unique_ptr<SkStream> stream(GetResourceAsStream("images/google_chrome.ico"));
23     std::unique_ptr<SkCodec> codec = SkCodec::MakeFromStream(std::move(stream));
24     if (!codec) {
25         return nullptr;
26     }
27 
28     SkBitmap bitmap;
29     SkImageInfo info = codec->getInfo().makeWH(kWidth, kHeight)
30                                        .makeColorType(colorType)
31                                        .makeAlphaType(kPremul_SkAlphaType);
32     bitmap.allocPixels(info);
33     codec->getPixels(info, bitmap.getPixels(), bitmap.rowBytes());
34     bitmap.setImmutable();
35     return SkImage::MakeFromBitmap(bitmap);
36 }
37 
make_codec_image()38 static sk_sp<SkImage> make_codec_image() {
39     sk_sp<SkData> encoded = GetResourceAsData("images/randPixels.png");
40     return SkImage::MakeFromEncoded(encoded);
41 }
42 
draw_contents(SkCanvas * canvas)43 static void draw_contents(SkCanvas* canvas) {
44     SkPaint paint;
45     paint.setStyle(SkPaint::kStroke_Style);
46     paint.setStrokeWidth(20);
47     paint.setColor(0xFF800000);
48     canvas->drawCircle(40, 40, 35, paint);
49     paint.setColor(0xFF008000);
50     canvas->drawCircle(50, 50, 35, paint);
51     paint.setColor(0xFF000080);
52     canvas->drawCircle(60, 60, 35, paint);
53 }
54 
make_picture_image()55 static sk_sp<SkImage> make_picture_image() {
56     SkPictureRecorder recorder;
57     draw_contents(recorder.beginRecording(SkRect::MakeIWH(kWidth, kHeight)));
58     return SkImage::MakeFromPicture(recorder.finishRecordingAsPicture(),
59                                     SkISize::Make(kWidth, kHeight), nullptr, nullptr,
60                                     SkImage::BitDepth::kU8,
61                                     SkColorSpace::MakeSRGB());
62 }
63 
make_parametric_transfer_fn(const SkColorSpacePrimaries & primaries)64 static sk_sp<SkColorSpace> make_parametric_transfer_fn(const SkColorSpacePrimaries& primaries) {
65     skcms_Matrix3x3 toXYZD50;
66     SkAssertResult(primaries.toXYZD50(&toXYZD50));
67     skcms_TransferFunction fn = { 1.8f, 1.f, 0.f, 0.f, 0.f, 0.f, 0.f };
68     return SkColorSpace::MakeRGB(fn, toXYZD50);
69 }
70 
make_wide_gamut()71 static sk_sp<SkColorSpace> make_wide_gamut() {
72     // ProPhoto
73     SkColorSpacePrimaries primaries;
74     primaries.fRX = 0.7347f;
75     primaries.fRY = 0.2653f;
76     primaries.fGX = 0.1596f;
77     primaries.fGY = 0.8404f;
78     primaries.fBX = 0.0366f;
79     primaries.fBY = 0.0001f;
80     primaries.fWX = 0.34567f;
81     primaries.fWY = 0.35850f;
82     return make_parametric_transfer_fn(primaries);
83 }
84 
make_small_gamut()85 static sk_sp<SkColorSpace> make_small_gamut() {
86     SkColorSpacePrimaries primaries;
87     primaries.fRX = 0.50f;
88     primaries.fRY = 0.33f;
89     primaries.fGX = 0.30f;
90     primaries.fGY = 0.50f;
91     primaries.fBX = 0.25f;
92     primaries.fBY = 0.16f;
93     primaries.fWX = 0.3127f;
94     primaries.fWY = 0.3290f;
95     return make_parametric_transfer_fn(primaries);
96 }
97 
draw_image(SkCanvas * canvas,SkImage * image,SkColorType dstColorType,SkAlphaType dstAlphaType,sk_sp<SkColorSpace> dstColorSpace,SkImage::CachingHint hint)98 static void draw_image(SkCanvas* canvas, SkImage* image, SkColorType dstColorType,
99                        SkAlphaType dstAlphaType, sk_sp<SkColorSpace> dstColorSpace,
100                        SkImage::CachingHint hint) {
101     size_t rowBytes = image->width() * SkColorTypeBytesPerPixel(dstColorType);
102     sk_sp<SkData> data = SkData::MakeUninitialized(rowBytes * image->height());
103     SkImageInfo dstInfo = SkImageInfo::Make(image->width(), image->height(), dstColorType,
104                                             dstAlphaType, dstColorSpace);
105     if (!image->readPixels(dstInfo, data->writable_data(), rowBytes, 0, 0, hint)) {
106         memset(data->writable_data(), 0, rowBytes * image->height());
107     }
108 
109     // Now that we have called readPixels(), dump the raw pixels into an srgb image.
110     sk_sp<SkColorSpace> srgb = SkColorSpace::MakeSRGB();
111     sk_sp<SkImage> raw = SkImage::MakeRasterData(dstInfo.makeColorSpace(srgb), data, rowBytes);
112     canvas->drawImage(raw.get(), 0.0f, 0.0f, nullptr);
113 }
114 
115 class ReadPixelsGM : public skiagm::GM {
116 public:
ReadPixelsGM()117     ReadPixelsGM() {}
118 
119 protected:
onShortName()120     SkString onShortName() override {
121         return SkString("readpixels");
122     }
123 
onISize()124     SkISize onISize() override {
125         return SkISize::Make(6 * kWidth, 9 * kHeight);
126     }
127 
onDraw(SkCanvas * canvas)128     void onDraw(SkCanvas* canvas) override {
129         const SkAlphaType alphaTypes[] = {
130                 kUnpremul_SkAlphaType,
131                 kPremul_SkAlphaType,
132         };
133         const SkColorType colorTypes[] = {
134                 kRGBA_8888_SkColorType,
135                 kBGRA_8888_SkColorType,
136                 kRGBA_F16_SkColorType,
137         };
138         const sk_sp<SkColorSpace> colorSpaces[] = {
139                 make_wide_gamut(),
140                 SkColorSpace::MakeSRGB(),
141                 make_small_gamut(),
142         };
143 
144         for (sk_sp<SkColorSpace> dstColorSpace : colorSpaces) {
145             for (SkColorType srcColorType : colorTypes) {
146                 canvas->save();
147                 sk_sp<SkImage> image = make_raster_image(srcColorType);
148                 if (!image) {
149                     continue;
150                 }
151                 if (GrContext* context = canvas->getGrContext()) {
152                     image = image->makeTextureImage(context, canvas->imageInfo().colorSpace());
153                 }
154                 if (image) {
155                     for (SkColorType dstColorType : colorTypes) {
156                         for (SkAlphaType dstAlphaType : alphaTypes) {
157                             draw_image(canvas, image.get(), dstColorType, dstAlphaType,
158                                        dstColorSpace, SkImage::kAllow_CachingHint);
159                             canvas->translate((float)kWidth, 0.0f);
160                         }
161                     }
162                 }
163                 canvas->restore();
164                 canvas->translate(0.0f, (float) kHeight);
165             }
166         }
167     }
168 
169 private:
170     typedef skiagm::GM INHERITED;
171 };
172 DEF_GM( return new ReadPixelsGM; )
173 
174 class ReadPixelsCodecGM : public skiagm::GM {
175 public:
ReadPixelsCodecGM()176     ReadPixelsCodecGM() {}
177 
178 protected:
onShortName()179     SkString onShortName() override {
180         return SkString("readpixelscodec");
181     }
182 
onISize()183     SkISize onISize() override {
184         return SkISize::Make(3 * (kEncodedWidth + 1), 12 * (kEncodedHeight + 1));
185     }
186 
onDraw(SkCanvas * canvas,SkString * errorMsg)187     DrawResult onDraw(SkCanvas* canvas, SkString* errorMsg) override {
188         if (!canvas->imageInfo().colorSpace()) {
189             *errorMsg = "This gm is only interesting in color correct modes.";
190             return DrawResult::kSkip;
191         }
192 
193         const SkAlphaType alphaTypes[] = {
194                 kUnpremul_SkAlphaType,
195                 kPremul_SkAlphaType,
196         };
197         const SkColorType colorTypes[] = {
198                 kRGBA_8888_SkColorType,
199                 kBGRA_8888_SkColorType,
200                 kRGBA_F16_SkColorType,
201         };
202         const sk_sp<SkColorSpace> colorSpaces[] = {
203                 make_wide_gamut(),
204                 SkColorSpace::MakeSRGB(),
205                 make_small_gamut(),
206         };
207         const SkImage::CachingHint hints[] = {
208                 SkImage::kAllow_CachingHint,
209                 SkImage::kDisallow_CachingHint,
210         };
211 
212         sk_sp<SkImage> image = make_codec_image();
213         for (sk_sp<SkColorSpace> dstColorSpace : colorSpaces) {
214             canvas->save();
215             for (SkColorType dstColorType : colorTypes) {
216                 for (SkAlphaType dstAlphaType : alphaTypes) {
217                     for (SkImage::CachingHint hint : hints) {
218                         draw_image(canvas, image.get(), dstColorType, dstAlphaType, dstColorSpace,
219                                    hint);
220                         canvas->translate(0.0f, (float) kEncodedHeight + 1);
221                     }
222                 }
223             }
224             canvas->restore();
225             canvas->translate((float) kEncodedWidth + 1, 0.0f);
226         }
227         return DrawResult::kOk;
228     }
229 
230 private:
231     static const int kEncodedWidth = 8;
232     static const int kEncodedHeight = 8;
233 
234     typedef skiagm::GM INHERITED;
235 };
236 DEF_GM( return new ReadPixelsCodecGM; )
237 
238 class ReadPixelsPictureGM : public skiagm::GM {
239 public:
ReadPixelsPictureGM()240     ReadPixelsPictureGM() {}
241 
242 protected:
onShortName()243     SkString onShortName() override {
244         return SkString("readpixelspicture");
245     }
246 
onISize()247     SkISize onISize() override {
248         return SkISize::Make(3 * kWidth, 12 * kHeight);
249     }
250 
onDraw(SkCanvas * canvas,SkString * errorMsg)251     DrawResult onDraw(SkCanvas* canvas, SkString* errorMsg) override {
252         if (!canvas->imageInfo().colorSpace()) {
253             *errorMsg = "This gm is only interesting in color correct modes.";
254             return DrawResult::kSkip;
255         }
256 
257         const sk_sp<SkImage> images[] = {
258                 make_picture_image(),
259         };
260         const SkAlphaType alphaTypes[] = {
261                 kUnpremul_SkAlphaType,
262                 kPremul_SkAlphaType,
263         };
264         const SkColorType colorTypes[] = {
265                 kRGBA_8888_SkColorType,
266                 kBGRA_8888_SkColorType,
267                 kRGBA_F16_SkColorType,
268         };
269         const sk_sp<SkColorSpace> colorSpaces[] = {
270                 make_wide_gamut(),
271                 SkColorSpace::MakeSRGB(),
272                 make_small_gamut(),
273         };
274         const SkImage::CachingHint hints[] = {
275                 SkImage::kAllow_CachingHint,
276                 SkImage::kDisallow_CachingHint,
277         };
278 
279         for (sk_sp<SkImage> image : images) {
280             for (sk_sp<SkColorSpace> dstColorSpace : colorSpaces) {
281                 canvas->save();
282                 for (SkColorType dstColorType : colorTypes) {
283                     for (SkAlphaType dstAlphaType : alphaTypes) {
284                         for (SkImage::CachingHint hint : hints) {
285                             draw_image(canvas, image.get(), dstColorType, dstAlphaType,
286                                        dstColorSpace, hint);
287                             canvas->translate(0.0f, (float) kHeight);
288                         }
289                     }
290                 }
291                 canvas->restore();
292                 canvas->translate((float) kWidth, 0.0f);
293             }
294         }
295         return DrawResult::kOk;
296     }
297 
298 private:
299 
300     typedef skiagm::GM INHERITED;
301 };
302 DEF_GM( return new ReadPixelsPictureGM; )
303