1
0
Fork 0
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

121 lines
4.1 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

/*
* Copyright 2021 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "gm/gm.h"
#include "include/core/SkCanvas.h"
#include "include/core/SkFont.h"
#include "include/core/SkSurface.h"
#include "tools/Resources.h"
static const skcms_TransferFunction gTFs[] = {
SkNamedTransferFn::kSRGB,
SkNamedTransferFn::k2Dot2,
SkNamedTransferFn::kLinear,
SkNamedTransferFn::kRec2020,
SkNamedTransferFn::kPQ,
SkNamedTransferFn::kHLG,
{-3.0f, 2.0f, 2.0f, 1/0.17883277f, 0.28466892f, 0.55991073f, 3.0f }, // HLG scaled 4x
};
static const skcms_Matrix3x3 gGamuts[] = {
SkNamedGamut::kSRGB,
SkNamedGamut::kAdobeRGB,
SkNamedGamut::kDisplayP3,
SkNamedGamut::kRec2020,
SkNamedGamut::kXYZ,
};
static const int W = 128,
H = 128;
// These GMs demonstrate that our color space management is self-consistent.
// (Important to note, self-consistent, not necessarily correct in an objective sense.)
//
// Let's let,
//
// SkColorSpace* imgCS = img->colorSpace();
// SkColorSpace* dstCS = canvas->imageInfo().colorSpace();
//
// Ordinarily we'd just
//
// canvas->drawImage(img, 0,0);
//
// which would convert that img's pixels from imgCS to dstCS while drawing.
//
// But before we draw in these GMs, we convert the image to an arbitrarily different color space,
// letting midCS range over the cross-product gTFs × gGamuts:
//
// canvas->drawImage(img->makeColorSpace(midCS), 0,0);
//
// This converts img first from imgCS to midCS, treating midCS as a destination color space,
// and then draws that midCS image to the dstCS canvas, treating midCS as a source color space.
// This should draw a grid of images that look identical except for small precision loss.
//
// If instead of calling SkImage::makeColorSpace() we use SkCanvas::makeSurface() to create a
// midCS offscreen, we construct the same logical imgCS -> midCS -> dstCS transform chain while
// exercising different drawing code paths. Both strategies should draw roughly the same.
namespace {
enum Strategy { SkImage_makeColorSpace, SkCanvas_makeSurface };
}
static void draw_colorspace_gm(Strategy strategy, SkCanvas* canvas) {
if (!canvas->imageInfo().colorSpace()) {
canvas->drawString("This GM only makes sense with color-managed drawing.",
W,H, SkFont{}, SkPaint{});
return;
}
sk_sp<SkImage> img = GetResourceAsImage("images/mandrill_128.png");
if (!img) {
canvas->drawString("Could not load our test image!",
W,H, SkFont{}, SkPaint{});
return;
}
SkASSERT(img->width() == W);
SkASSERT(img->height() == H);
SkASSERT(img->colorSpace());
for (skcms_Matrix3x3 gamut : gGamuts) {
canvas->save();
for (skcms_TransferFunction tf : gTFs) {
sk_sp<SkColorSpace> midCS = SkColorSpace::MakeRGB(tf, gamut);
switch (strategy) {
case SkImage_makeColorSpace: {
canvas->drawImage(img->makeColorSpace(midCS), 0,0);
} break;
case SkCanvas_makeSurface: {
sk_sp<SkSurface> offscreen =
canvas->makeSurface(canvas->imageInfo().makeColorSpace(midCS));
if (!offscreen) {
canvas->drawString("Could not allocate offscreen surface!",
W,H, SkFont{}, SkPaint{});
return;
}
offscreen->getCanvas()->drawImage(img, 0,0);
canvas->drawImage(offscreen->makeImageSnapshot(), 0,0);
} break;
}
canvas->translate(W, 0);
}
canvas->restore();
canvas->translate(0, H);
}
}
DEF_SIMPLE_GM(colorspace, canvas, W*SK_ARRAY_COUNT(gTFs), H*SK_ARRAY_COUNT(gGamuts)) {
draw_colorspace_gm(SkImage_makeColorSpace, canvas);
}
DEF_SIMPLE_GM(colorspace2, canvas, W*SK_ARRAY_COUNT(gTFs), H*SK_ARRAY_COUNT(gGamuts)) {
draw_colorspace_gm(SkCanvas_makeSurface, canvas);
}