Home | History | Annotate | Download | only in gm
      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 "SkColorPriv.h"
     10 #include "SkColorSpaceXform.h"
     11 #include "SkColorSpaceXformPriv.h"
     12 #include "SkOpts.h"
     13 #include "SkUtils.h"
     14 
     15 static 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 
     28 class GammaEncodedPremulGM : public skiagm::GM {
     29 public:
     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++) {
     40                     fColors[i++] = SkColorSetARGBInline(0xFF,
     41                                                         r * kColorScale,
     42                                                         g * kColorScale,
     43                                                         b * kColorScale);
     44                 }
     45             }
     46         }
     47 
     48     }
     49 
     50 protected:
     51     virtual SkISize onISize() override {
     52         return SkISize::Make(kAlphaMax, kNumColors * 2 * kStripeHeight);
     53     }
     54 
     55     SkString onShortName() override {
     56         return fName;
     57     }
     58 
     59     void onDraw(SkCanvas* canvas) override {
     60         if (canvas->imageInfo().isOpaque()) {
     61             return;
     62         }
     63 
     64         SkBitmap bitmap;
     65         SkImageInfo bitmapInfo = SkImageInfo::MakeN32Premul(kAlphaMax, 1,
     66                 canvas->imageInfo().refColorSpace());
     67         bitmap.allocPixels(bitmapInfo);
     68         uint32_t* pixels = bitmap.getAddr32(0, 0);
     69 
     70         for (int i = 0; i < kNumColors; i++) {
     71             // Create an entire row of the same color, with the alpha from 0 to kAlphaMax.
     72             uint32_t row[kAlphaMax];
     73             sk_memset32(row, fColors[i], kAlphaMax);
     74             for (int a = 0; a < kAlphaMax; a++) {
     75                 row[a] = (row[a] & 0x00FFFFFF) | (a << 24);
     76             }
     77 
     78             // Tranform row to dst, then premultiply.
     79             fXform->apply(select_xform_format(kN32_SkColorType), pixels,
     80                           SkColorSpaceXform::kBGRA_8888_ColorFormat, row, kAlphaMax,
     81                           kUnpremul_SkAlphaType);
     82             SkOpts::RGBA_to_rgbA(pixels, pixels, kAlphaMax);
     83             bitmap.notifyPixelsChanged();
     84 
     85             // Write the dst space premultiplied row to the canvas.
     86             for (int j = 0; j < kStripeHeight; j++) {
     87                 canvas->drawBitmap(bitmap, 0, 2 * i * kStripeHeight + j);
     88             }
     89 
     90             // Premultiply, then transform the row to dst.
     91             SkOpts::RGBA_to_rgbA(pixels, row, kAlphaMax);
     92             fXform->apply(select_xform_format(kN32_SkColorType), pixels,
     93                           SkColorSpaceXform::kBGRA_8888_ColorFormat, pixels, kAlphaMax,
     94                           kUnpremul_SkAlphaType);
     95             clamp_to_alpha(pixels, kAlphaMax);
     96             bitmap.notifyPixelsChanged();
     97 
     98             // Write the src space premultiplied row to the canvas.
     99             for (int j = 0; j < kStripeHeight; j++) {
    100                 canvas->drawBitmap(bitmap, 0, (2 * i + 1) * kStripeHeight + j);
    101             }
    102         }
    103     }
    104 
    105 private:
    106     static constexpr int kColorSteps = 4;
    107     static constexpr int kNumColors = kColorSteps * kColorSteps * kColorSteps;
    108     static constexpr int kColorScale = 255 / (kColorSteps - 1);
    109     static constexpr int kStripeHeight = 10;
    110     static constexpr int kAlphaMax = 255;
    111 
    112     sk_sp<SkColorSpace>                fDstSpace;
    113     sk_sp<SkColorSpace>                fSrcSpace;
    114     std::unique_ptr<SkColorSpaceXform> fXform;
    115     SkString                           fName;
    116     SkColor                            fColors[kNumColors];
    117 
    118     typedef GM INHERITED;
    119 };
    120 
    121 DEF_GM(return new GammaEncodedPremulGM(SkColorSpace::MakeSRGB(),
    122         SkColorSpace::MakeRGB(SkColorSpace::kSRGB_RenderTargetGamma, SkColorSpace::kRec2020_Gamut),
    123         "toWideGamut");)
    124 DEF_GM(return new GammaEncodedPremulGM(SkColorSpace::MakeRGB(SkColorSpace::kSRGB_RenderTargetGamma,
    125         SkColorSpace::kRec2020_Gamut), SkColorSpace::MakeSRGB(), "fromWideGamut");)
    126 DEF_GM(return new GammaEncodedPremulGM(SkColorSpace::MakeSRGB(),
    127         SkColorSpace::MakeRGB(SkColorSpace::kLinear_RenderTargetGamma, SkColorSpace::kSRGB_Gamut),
    128         "toLinear");)
    129 DEF_GM(return new GammaEncodedPremulGM(
    130         SkColorSpace::MakeRGB(SkColorSpace::kLinear_RenderTargetGamma, SkColorSpace::kSRGB_Gamut),
    131         SkColorSpace::MakeSRGB(), "fromLinear");)
    132 DEF_GM(return new GammaEncodedPremulGM(
    133         SkColorSpace::MakeRGB({ 1.8f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f },
    134         SkColorSpace::kSRGB_Gamut), SkColorSpace::MakeSRGB(), "from1.8");)
    135