Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
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
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:465
void translate(SkScalar dx, SkScalar dy)
sk_sp< SkSurface > makeSurface(const SkImageInfo &info, const SkSurfaceProps *props=nullptr)
int save()
Definition SkCanvas.cpp:451
void drawString(const char str[], SkScalar x, SkScalar y, const SkFont &font, const SkPaint &paint)
Definition SkCanvas.h:1803
SkImageInfo imageInfo() const
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)
static const skcms_Matrix3x3 gGamuts[]
static const skcms_TransferFunction gTFs[]
static const int W
static void draw_colorspace_gm(Strategy strategy, SkCanvas *canvas)
#define DEF_SIMPLE_GM(NAME, CANVAS, W, H)
Definition gm.h:50
static constexpr skcms_Matrix3x3 kSRGB
static constexpr skcms_Matrix3x3 kAdobeRGB
static constexpr skcms_Matrix3x3 kXYZ
static constexpr skcms_Matrix3x3 kRec2020
static constexpr skcms_Matrix3x3 kDisplayP3
static constexpr skcms_TransferFunction kRec2020
static constexpr skcms_TransferFunction k2Dot2
static constexpr skcms_TransferFunction kSRGB
static constexpr skcms_TransferFunction kHLG
static constexpr skcms_TransferFunction kPQ
static constexpr skcms_TransferFunction kLinear
SkFont DefaultPortableFont()
sk_sp< SkImage > GetResourceAsImage(const char *resource)
Definition DecodeUtils.h:25
Definition SkMD5.cpp:130
SkColorSpace * colorSpace() const
SkImageInfo makeColorSpace(sk_sp< SkColorSpace > cs) const