• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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"
9 #include "SkColorSpaceXform.h"
10 #include "SkColorSpaceXformPriv.h"
11 #include "SkOpts.h"
12 #include "SkUtils.h"
13 
clamp_to_alpha(uint32_t * pixels,int count)14 static void clamp_to_alpha(uint32_t* pixels, int count) {
15     for (int i = 0; i < count; i++) {
16         uint8_t a = SkGetPackedA32(pixels[i]);
17         uint8_t r = SkGetPackedR32(pixels[i]);
18         uint8_t g = SkGetPackedG32(pixels[i]);
19         uint8_t b = SkGetPackedB32(pixels[i]);
20         pixels[i] = SkPackARGB32(a,
21                                  SkTMin(a, r),
22                                  SkTMin(a, g),
23                                  SkTMin(a, b));
24     }
25 }
26 
27 class GammaEncodedPremulGM : public skiagm::GM {
28 public:
GammaEncodedPremulGM(sk_sp<SkColorSpace> dst,sk_sp<SkColorSpace> src,const char * desc)29     GammaEncodedPremulGM(sk_sp<SkColorSpace> dst, sk_sp<SkColorSpace> src, const char* desc)
30         : fDstSpace(dst)
31         , fSrcSpace(src)
32         , fXform(SkColorSpaceXform::New(src.get(), dst.get()))
33         , fName(SkStringPrintf("gamma_encoded_premul_dst-v-src_%s", desc))
34     {
35         int i = 0;
36         for (int r = 0; r < kColorSteps; r++) {
37             for (int g = 0; g < kColorSteps; g++) {
38                 for (int b = 0; b < kColorSteps; b++) {
39                     fColors[i++] = SkColorSetARGBInline(0xFF,
40                                                         r * kColorScale,
41                                                         g * kColorScale,
42                                                         b * kColorScale);
43                 }
44             }
45         }
46 
47     }
48 
49 protected:
onISize()50     virtual SkISize onISize() override {
51         return SkISize::Make(kAlphaMax, kNumColors * 2 * kStripeHeight);
52     }
53 
onShortName()54     SkString onShortName() override {
55         return fName;
56     }
57 
onDraw(SkCanvas * canvas)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);
82 
83             // Write the dst space premultiplied row to the canvas.
84             for (int j = 0; j < kStripeHeight; j++) {
85                 canvas->drawBitmap(bitmap, 0, 2 * i * kStripeHeight + j);
86             }
87 
88             // Premultiply, then transform the row to dst.
89             SkOpts::RGBA_to_rgbA(pixels, row, kAlphaMax);
90             fXform->apply(select_xform_format(kN32_SkColorType), pixels,
91                           SkColorSpaceXform::kBGRA_8888_ColorFormat, pixels, kAlphaMax,
92                           kUnpremul_SkAlphaType);
93             clamp_to_alpha(pixels, kAlphaMax);
94 
95             // Write the src space premultiplied row to the canvas.
96             for (int j = 0; j < kStripeHeight; j++) {
97                 canvas->drawBitmap(bitmap, 0, (2 * i + 1) * kStripeHeight + j);
98             }
99         }
100     }
101 
102 private:
103     static constexpr int kColorSteps = 4;
104     static constexpr int kNumColors = kColorSteps * kColorSteps * kColorSteps;
105     static constexpr int kColorScale = 255 / (kColorSteps - 1);
106     static constexpr int kStripeHeight = 10;
107     static constexpr int kAlphaMax = 255;
108 
109     sk_sp<SkColorSpace>                fDstSpace;
110     sk_sp<SkColorSpace>                fSrcSpace;
111     std::unique_ptr<SkColorSpaceXform> fXform;
112     SkString                           fName;
113     SkColor                            fColors[kNumColors];
114 
115     typedef GM INHERITED;
116 };
117 
118 DEF_GM(return new GammaEncodedPremulGM(SkColorSpace::MakeSRGB(),
119         SkColorSpace::MakeRGB(SkColorSpace::kSRGB_RenderTargetGamma, SkColorSpace::kRec2020_Gamut),
120         "toWideGamut");)
121 DEF_GM(return new GammaEncodedPremulGM(SkColorSpace::MakeRGB(SkColorSpace::kSRGB_RenderTargetGamma,
122         SkColorSpace::kRec2020_Gamut), SkColorSpace::MakeSRGB(), "fromWideGamut");)
123 DEF_GM(return new GammaEncodedPremulGM(SkColorSpace::MakeSRGB(),
124         SkColorSpace::MakeRGB(SkColorSpace::kLinear_RenderTargetGamma, SkColorSpace::kSRGB_Gamut),
125         "toLinear");)
126 DEF_GM(return new GammaEncodedPremulGM(
127         SkColorSpace::MakeRGB(SkColorSpace::kLinear_RenderTargetGamma, SkColorSpace::kSRGB_Gamut),
128         SkColorSpace::MakeSRGB(), "fromLinear");)
129 DEF_GM(return new GammaEncodedPremulGM(
130         SkColorSpace::MakeRGB({ 1.8f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f },
131         SkColorSpace::kSRGB_Gamut), SkColorSpace::MakeSRGB(), "from1.8");)
132