blob: 1d7bb5702f493d67073589333b5f56ed12e98394 [file] [log] [blame]
Matt Sarett35b8b262017-03-08 11:31:06 -05001/*
2 * Copyright 2017 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"
Florin Malitaab244f02017-05-03 19:16:58 +00009#include "SkColorPriv.h"
Matt Sarett35b8b262017-03-08 11:31:06 -050010#include "SkColorSpaceXform.h"
11#include "SkColorSpaceXformPriv.h"
12#include "SkOpts.h"
13#include "SkUtils.h"
14
15static void clamp_to_alpha(uint32_t* pixels, int count) {
16 for (int i = 0; i < count; i++) {
17 uint8_t a = SkGetPackedA32(pixels[i]);
18 uint8_t r = SkGetPackedR32(pixels[i]);
19 uint8_t g = SkGetPackedG32(pixels[i]);
20 uint8_t b = SkGetPackedB32(pixels[i]);
21 pixels[i] = SkPackARGB32(a,
22 SkTMin(a, r),
23 SkTMin(a, g),
24 SkTMin(a, b));
25 }
26}
27
28class GammaEncodedPremulGM : public skiagm::GM {
29public:
30 GammaEncodedPremulGM(sk_sp<SkColorSpace> dst, sk_sp<SkColorSpace> src, const char* desc)
31 : fDstSpace(dst)
32 , fSrcSpace(src)
33 , fXform(SkColorSpaceXform::New(src.get(), dst.get()))
34 , fName(SkStringPrintf("gamma_encoded_premul_dst-v-src_%s", desc))
35 {
36 int i = 0;
37 for (int r = 0; r < kColorSteps; r++) {
38 for (int g = 0; g < kColorSteps; g++) {
39 for (int b = 0; b < kColorSteps; b++) {
Cary Clark6cdb7d32018-04-24 14:47:16 -040040 fColors[i++] = SkColorSetRGB(r * kColorScale,
41 g * kColorScale,
42 b * kColorScale);
Matt Sarett35b8b262017-03-08 11:31:06 -050043 }
44 }
45 }
46
47 }
48
49protected:
50 virtual SkISize onISize() override {
51 return SkISize::Make(kAlphaMax, kNumColors * 2 * kStripeHeight);
52 }
53
54 SkString onShortName() override {
55 return fName;
56 }
57
58 void onDraw(SkCanvas* canvas) override {
59 if (canvas->imageInfo().isOpaque()) {
60 return;
61 }
62
63 SkBitmap bitmap;
64 SkImageInfo bitmapInfo = SkImageInfo::MakeN32Premul(kAlphaMax, 1,
65 canvas->imageInfo().refColorSpace());
66 bitmap.allocPixels(bitmapInfo);
67 uint32_t* pixels = bitmap.getAddr32(0, 0);
68
69 for (int i = 0; i < kNumColors; i++) {
70 // Create an entire row of the same color, with the alpha from 0 to kAlphaMax.
71 uint32_t row[kAlphaMax];
72 sk_memset32(row, fColors[i], kAlphaMax);
73 for (int a = 0; a < kAlphaMax; a++) {
74 row[a] = (row[a] & 0x00FFFFFF) | (a << 24);
75 }
76
77 // Tranform row to dst, then premultiply.
78 fXform->apply(select_xform_format(kN32_SkColorType), pixels,
79 SkColorSpaceXform::kBGRA_8888_ColorFormat, row, kAlphaMax,
80 kUnpremul_SkAlphaType);
81 SkOpts::RGBA_to_rgbA(pixels, pixels, kAlphaMax);
Hal Canary85932482017-07-11 09:53:40 -040082 bitmap.notifyPixelsChanged();
Matt Sarett35b8b262017-03-08 11:31:06 -050083
84 // Write the dst space premultiplied row to the canvas.
85 for (int j = 0; j < kStripeHeight; j++) {
86 canvas->drawBitmap(bitmap, 0, 2 * i * kStripeHeight + j);
87 }
88
89 // Premultiply, then transform the row to dst.
90 SkOpts::RGBA_to_rgbA(pixels, row, kAlphaMax);
91 fXform->apply(select_xform_format(kN32_SkColorType), pixels,
92 SkColorSpaceXform::kBGRA_8888_ColorFormat, pixels, kAlphaMax,
93 kUnpremul_SkAlphaType);
94 clamp_to_alpha(pixels, kAlphaMax);
Hal Canary85932482017-07-11 09:53:40 -040095 bitmap.notifyPixelsChanged();
Matt Sarett35b8b262017-03-08 11:31:06 -050096
97 // Write the src space premultiplied row to the canvas.
98 for (int j = 0; j < kStripeHeight; j++) {
99 canvas->drawBitmap(bitmap, 0, (2 * i + 1) * kStripeHeight + j);
100 }
101 }
102 }
103
104private:
105 static constexpr int kColorSteps = 4;
106 static constexpr int kNumColors = kColorSteps * kColorSteps * kColorSteps;
107 static constexpr int kColorScale = 255 / (kColorSteps - 1);
108 static constexpr int kStripeHeight = 10;
109 static constexpr int kAlphaMax = 255;
110
111 sk_sp<SkColorSpace> fDstSpace;
112 sk_sp<SkColorSpace> fSrcSpace;
113 std::unique_ptr<SkColorSpaceXform> fXform;
114 SkString fName;
115 SkColor fColors[kNumColors];
116
117 typedef GM INHERITED;
118};
119
120DEF_GM(return new GammaEncodedPremulGM(SkColorSpace::MakeSRGB(),
121 SkColorSpace::MakeRGB(SkColorSpace::kSRGB_RenderTargetGamma, SkColorSpace::kRec2020_Gamut),
122 "toWideGamut");)
123DEF_GM(return new GammaEncodedPremulGM(SkColorSpace::MakeRGB(SkColorSpace::kSRGB_RenderTargetGamma,
124 SkColorSpace::kRec2020_Gamut), SkColorSpace::MakeSRGB(), "fromWideGamut");)
125DEF_GM(return new GammaEncodedPremulGM(SkColorSpace::MakeSRGB(),
126 SkColorSpace::MakeRGB(SkColorSpace::kLinear_RenderTargetGamma, SkColorSpace::kSRGB_Gamut),
127 "toLinear");)
128DEF_GM(return new GammaEncodedPremulGM(
129 SkColorSpace::MakeRGB(SkColorSpace::kLinear_RenderTargetGamma, SkColorSpace::kSRGB_Gamut),
130 SkColorSpace::MakeSRGB(), "fromLinear");)
131DEF_GM(return new GammaEncodedPremulGM(
132 SkColorSpace::MakeRGB({ 1.8f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f },
133 SkColorSpace::kSRGB_Gamut), SkColorSpace::MakeSRGB(), "from1.8");)