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