Flutter Engine
The Flutter Engine
colorspace.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2021 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"
11#include "include/core/SkFont.h"
13#include "tools/DecodeUtils.h"
14#include "tools/Resources.h"
16
17static const skcms_TransferFunction gTFs[] = {
24 {-3.0f, 2.0f, 2.0f, 1/0.17883277f, 0.28466892f, 0.55991073f, 3.0f }, // HLG scaled 4x
25};
26
27static const skcms_Matrix3x3 gGamuts[] = {
33};
34
35static const int W = 128,
36 H = 128;
37
38// These GMs demonstrate that our color space management is self-consistent.
39// (Important to note, self-consistent, not necessarily correct in an objective sense.)
40//
41// Let's let,
42//
43// SkColorSpace* imgCS = img->colorSpace();
44// SkColorSpace* dstCS = canvas->imageInfo().colorSpace();
45//
46// Ordinarily we'd just
47//
48// canvas->drawImage(img, 0,0);
49//
50// which would convert that img's pixels from imgCS to dstCS while drawing.
51//
52// But before we draw in these GMs, we convert the image to an arbitrarily different color space,
53// letting midCS range over the cross-product gTFs × gGamuts:
54//
55// canvas->drawImage(img->makeColorSpace(midCS), 0,0);
56//
57// This converts img first from imgCS to midCS, treating midCS as a destination color space,
58// and then draws that midCS image to the dstCS canvas, treating midCS as a source color space.
59// This should draw a grid of images that look identical except for small precision loss.
60//
61// If instead of calling SkImage::makeColorSpace() we use SkCanvas::makeSurface() to create a
62// midCS offscreen, we construct the same logical imgCS -> midCS -> dstCS transform chain while
63// exercising different drawing code paths. Both strategies should draw roughly the same.
64
65namespace {
66 enum Strategy { SkImage_makeColorSpace, SkCanvas_makeSurface };
67}
68
69static void draw_colorspace_gm(Strategy strategy, SkCanvas* canvas) {
71 if (!canvas->imageInfo().colorSpace()) {
72 canvas->drawString("This GM only makes sense with color-managed drawing.",
73 W,H, font, SkPaint{});
74 return;
75 }
76
77 sk_sp<SkImage> img = ToolUtils::GetResourceAsImage("images/mandrill_128.png");
78 if (!img) {
79 canvas->drawString("Could not load our test image!",
80 W,H, font, SkPaint{});
81 return;
82 }
83
84 SkASSERT(img->width() == W);
85 SkASSERT(img->height() == H);
86 SkASSERT(img->colorSpace());
87
88 for (skcms_Matrix3x3 gamut : gGamuts) {
89 canvas->save();
90 for (skcms_TransferFunction tf : gTFs) {
92
93 switch (strategy) {
94 case SkImage_makeColorSpace: {
95 canvas->drawImage(img->makeColorSpace(nullptr, midCS), 0,0);
96 } break;
97
98 case SkCanvas_makeSurface: {
99 sk_sp<SkSurface> offscreen =
100 canvas->makeSurface(canvas->imageInfo().makeColorSpace(midCS));
101 if (!offscreen) {
102 canvas->drawString("Could not allocate offscreen surface!",
103 W,H, font, SkPaint{});
104 return;
105 }
106 offscreen->getCanvas()->drawImage(img, 0,0);
107 canvas->drawImage(offscreen->makeImageSnapshot(), 0,0);
108 } break;
109 }
110
111 canvas->translate(W, 0);
112 }
113 canvas->restore();
114 canvas->translate(0, H);
115 }
116}
117
118DEF_SIMPLE_GM(colorspace, canvas, W*std::size(gTFs), H*std::size(gGamuts)) {
119 draw_colorspace_gm(SkImage_makeColorSpace, canvas);
120}
121
122DEF_SIMPLE_GM(colorspace2, canvas, W*std::size(gTFs), H*std::size(gGamuts)) {
123 draw_colorspace_gm(SkCanvas_makeSurface, canvas);
124}
#define SkASSERT(cond)
Definition: SkAssert.h:116
void restore()
Definition: SkCanvas.cpp:461
void translate(SkScalar dx, SkScalar dy)
Definition: SkCanvas.cpp:1278
sk_sp< SkSurface > makeSurface(const SkImageInfo &info, const SkSurfaceProps *props=nullptr)
Definition: SkCanvas.cpp:1195
int save()
Definition: SkCanvas.cpp:447
void drawString(const char str[], SkScalar x, SkScalar y, const SkFont &font, const SkPaint &paint)
Definition: SkCanvas.h:1803
SkImageInfo imageInfo() const
Definition: SkCanvas.cpp:1206
void drawImage(const SkImage *image, SkScalar left, SkScalar top)
Definition: SkCanvas.h:1528
static sk_sp< SkColorSpace > MakeRGB(const skcms_TransferFunction &transferFn, const skcms_Matrix3x3 &toXYZ)
Definition: SkFont.h:35
virtual sk_sp< SkImage > makeColorSpace(GrDirectContext *direct, sk_sp< SkColorSpace > target) const =0
SkColorSpace * colorSpace() const
Definition: SkImage.cpp:156
int width() const
Definition: SkImage.h:285
int height() const
Definition: SkImage.h:291
SkCanvas * getCanvas()
Definition: SkSurface.cpp:82
sk_sp< SkImage > makeImageSnapshot()
Definition: SkSurface.cpp:90
DEF_SIMPLE_GM(colorspace, canvas, W *std::size(gTFs), H *std::size(gGamuts))
Definition: colorspace.cpp:118
static const skcms_Matrix3x3 gGamuts[]
Definition: colorspace.cpp:27
static const skcms_TransferFunction gTFs[]
Definition: colorspace.cpp:17
static const int W
Definition: colorspace.cpp:35
static void draw_colorspace_gm(Strategy strategy, SkCanvas *canvas)
Definition: colorspace.cpp:69
static constexpr skcms_Matrix3x3 kSRGB
Definition: SkColorSpace.h:67
static constexpr skcms_Matrix3x3 kAdobeRGB
Definition: SkColorSpace.h:77
static constexpr skcms_Matrix3x3 kXYZ
Definition: SkColorSpace.h:99
static constexpr skcms_Matrix3x3 kRec2020
Definition: SkColorSpace.h:93
static constexpr skcms_Matrix3x3 kDisplayP3
Definition: SkColorSpace.h:87
static constexpr skcms_TransferFunction kRec2020
Definition: SkColorSpace.h:54
static constexpr skcms_TransferFunction k2Dot2
Definition: SkColorSpace.h:48
static constexpr skcms_TransferFunction kSRGB
Definition: SkColorSpace.h:45
static constexpr skcms_TransferFunction kHLG
Definition: SkColorSpace.h:60
static constexpr skcms_TransferFunction kPQ
Definition: SkColorSpace.h:57
static constexpr skcms_TransferFunction kLinear
Definition: SkColorSpace.h:51
SkFont DefaultPortableFont()
sk_sp< SkImage > GetResourceAsImage(const char *resource)
Definition: DecodeUtils.h:25
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
Definition: switches.h:259
font
Font Metadata and Metrics.
Definition: SkMD5.cpp:130
SkColorSpace * colorSpace() const
SkImageInfo makeColorSpace(sk_sp< SkColorSpace > cs) const