• 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/gm.h"
9 #include "include/codec/SkCodec.h"
10 #include "include/core/SkBitmap.h"
11 #include "include/core/SkCanvas.h"
12 #include "include/core/SkColorSpace.h"
13 #include "include/core/SkData.h"
14 #include "include/core/SkImage.h"
15 #include "include/core/SkImageInfo.h"
16 #include "include/core/SkPaint.h"
17 #include "include/core/SkPicture.h"
18 #include "include/core/SkPictureRecorder.h"
19 #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"
26 #include "tools/Resources.h"
27 
28 #include <string.h>
29 #include <memory>
30 #include <utility>
31 
32 class GrContext;
33 
34 static const int kWidth = 64;
35 static const int kHeight = 64;
36 
make_raster_image(SkColorType colorType)37 static sk_sp<SkImage> make_raster_image(SkColorType colorType) {
38     std::unique_ptr<SkStream> stream(GetResourceAsStream("images/google_chrome.ico"));
39     std::unique_ptr<SkCodec> codec = SkCodec::MakeFromStream(std::move(stream));
40     if (!codec) {
41         return nullptr;
42     }
43 
44     SkBitmap bitmap;
45     SkImageInfo info = codec->getInfo().makeWH(kWidth, kHeight)
46                                        .makeColorType(colorType)
47                                        .makeAlphaType(kPremul_SkAlphaType);
48     bitmap.allocPixels(info);
49     codec->getPixels(info, bitmap.getPixels(), bitmap.rowBytes());
50     bitmap.setImmutable();
51     return SkImage::MakeFromBitmap(bitmap);
52 }
53 
make_codec_image()54 static sk_sp<SkImage> make_codec_image() {
55     sk_sp<SkData> encoded = GetResourceAsData("images/randPixels.png");
56     return SkImage::MakeFromEncoded(encoded);
57 }
58 
draw_contents(SkCanvas * canvas)59 static 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 
make_picture_image()71 static sk_sp<SkImage> make_picture_image() {
72     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,
77                                     SkColorSpace::MakeSRGB());
78 }
79 
make_parametric_transfer_fn(const SkColorSpacePrimaries & primaries)80 static sk_sp<SkColorSpace> make_parametric_transfer_fn(const SkColorSpacePrimaries& primaries) {
81     skcms_Matrix3x3 toXYZD50;
82     SkAssertResult(primaries.toXYZD50(&toXYZD50));
83     skcms_TransferFunction fn = { 1.8f, 1.f, 0.f, 0.f, 0.f, 0.f, 0.f };
84     return SkColorSpace::MakeRGB(fn, toXYZD50);
85 }
86 
make_wide_gamut()87 static 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;
98     return make_parametric_transfer_fn(primaries);
99 }
100 
make_small_gamut()101 static 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;
111     return make_parametric_transfer_fn(primaries);
112 }
113 
draw_image(SkCanvas * canvas,SkImage * image,SkColorType dstColorType,SkAlphaType dstAlphaType,sk_sp<SkColorSpace> dstColorSpace,SkImage::CachingHint hint)114 static void draw_image(SkCanvas* canvas, SkImage* image, SkColorType dstColorType,
115                        SkAlphaType dstAlphaType, sk_sp<SkColorSpace> dstColorSpace,
116                        SkImage::CachingHint hint) {
117     size_t rowBytes = image->width() * SkColorTypeBytesPerPixel(dstColorType);
118     sk_sp<SkData> data = SkData::MakeUninitialized(rowBytes * image->height());
119     SkImageInfo dstInfo = SkImageInfo::Make(image->width(), image->height(), dstColorType,
120                                             dstAlphaType, dstColorSpace);
121     if (!image->readPixels(dstInfo, data->writable_data(), rowBytes, 0, 0, hint)) {
122         memset(data->writable_data(), 0, rowBytes * image->height());
123     }
124 
125     // Now that we have called readPixels(), dump the raw pixels into an srgb image.
126     sk_sp<SkColorSpace> srgb = SkColorSpace::MakeSRGB();
127     sk_sp<SkImage> raw = SkImage::MakeRasterData(dstInfo.makeColorSpace(srgb), data, rowBytes);
128     canvas->drawImage(raw.get(), 0.0f, 0.0f, nullptr);
129 }
130 
131 class ReadPixelsGM : public skiagm::GM {
132 public:
ReadPixelsGM()133     ReadPixelsGM() {}
134 
135 protected:
onShortName()136     SkString onShortName() override {
137         return SkString("readpixels");
138     }
139 
onISize()140     SkISize onISize() override {
141         return SkISize::Make(6 * kWidth, 9 * kHeight);
142     }
143 
onDraw(SkCanvas * canvas)144     void onDraw(SkCanvas* canvas) override {
145         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(),
156                 SkColorSpace::MakeSRGB(),
157                 make_small_gamut(),
158         };
159 
160         for (sk_sp<SkColorSpace> dstColorSpace : colorSpaces) {
161             for (SkColorType srcColorType : colorTypes) {
162                 canvas->save();
163                 sk_sp<SkImage> image = make_raster_image(srcColorType);
164                 if (!image) {
165                     continue;
166                 }
167                 if (GrContext* context = canvas->getGrContext()) {
168                     image = image->makeTextureImage(context);
169                 }
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                         }
177                     }
178                 }
179                 canvas->restore();
180                 canvas->translate(0.0f, (float) kHeight);
181             }
182         }
183     }
184 
185 private:
186     typedef skiagm::GM INHERITED;
187 };
188 DEF_GM( return new ReadPixelsGM; )
189 
190 class ReadPixelsCodecGM : public skiagm::GM {
191 public:
ReadPixelsCodecGM()192     ReadPixelsCodecGM() {}
193 
194 protected:
onShortName()195     SkString onShortName() override {
196         return SkString("readpixelscodec");
197     }
198 
onISize()199     SkISize onISize() override {
200         return SkISize::Make(3 * (kEncodedWidth + 1), 12 * (kEncodedHeight + 1));
201     }
202 
onDraw(SkCanvas * canvas,SkString * errorMsg)203     DrawResult onDraw(SkCanvas* canvas, SkString* errorMsg) override {
204         if (!canvas->imageInfo().colorSpace()) {
205             *errorMsg = "This gm is only interesting in color correct modes.";
206             return DrawResult::kSkip;
207         }
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(),
220                 SkColorSpace::MakeSRGB(),
221                 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         }
243         return DrawResult::kOk;
244     }
245 
246 private:
247     static const int kEncodedWidth = 8;
248     static const int kEncodedHeight = 8;
249 
250     typedef skiagm::GM INHERITED;
251 };
252 DEF_GM( return new ReadPixelsCodecGM; )
253 
254 class ReadPixelsPictureGM : public skiagm::GM {
255 public:
ReadPixelsPictureGM()256     ReadPixelsPictureGM() {}
257 
258 protected:
onShortName()259     SkString onShortName() override {
260         return SkString("readpixelspicture");
261     }
262 
onISize()263     SkISize onISize() override {
264         return SkISize::Make(3 * kWidth, 12 * kHeight);
265     }
266 
onDraw(SkCanvas * canvas,SkString * errorMsg)267     DrawResult onDraw(SkCanvas* canvas, SkString* errorMsg) override {
268         if (!canvas->imageInfo().colorSpace()) {
269             *errorMsg = "This gm is only interesting in color correct modes.";
270             return DrawResult::kSkip;
271         }
272 
273         const sk_sp<SkImage> images[] = {
274                 make_picture_image(),
275         };
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(),
287                 SkColorSpace::MakeSRGB(),
288                 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         }
311         return DrawResult::kOk;
312     }
313 
314 private:
315 
316     typedef skiagm::GM INHERITED;
317 };
318 DEF_GM( return new ReadPixelsPictureGM; )
319