blob: b9fe65bf6aa93ad4210d8bfcd5871de4dd79ecda [file] [log] [blame]
Matt Sarett84014f02017-01-10 11:28:54 -05001/*
2 * Copyright 2016 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
10#include "Resources.h"
11#include "SkCanvas.h"
12#include "SkCodec.h"
13#include "SkData.h"
14#include "SkImageEncoderPriv.h"
15#include "SkPM4f.h"
16#include "SkSRGB.h"
17
18namespace skiagm {
19
20static const int imageWidth = 128;
21static const int imageHeight = 128;
22
23static inline int div_round_up(int a, int b) {
24 return (a + b - 1) / b;
25}
26
27static void make_index8(SkBitmap* bitmap, SkAlphaType alphaType, sk_sp<SkColorSpace> colorSpace) {
28 const SkColor colors[] = {
29 0x800000FF, 0x8000FF00, 0x80FF0000, 0x80FFFF00,
30 };
31
32 auto toPMColor = [alphaType, colorSpace](SkColor color) {
33 // In the unpremul case, just convert to SkPMColor ordering.
34 if (kUnpremul_SkAlphaType == alphaType) {
35 return SkSwizzle_BGRA_to_PMColor(color);
36 }
37
38 // Linear premultiply.
39 if (colorSpace) {
40 uint32_t result;
41 Sk4f pmFloat = SkColor4f::FromColor(color).premul().to4f_pmorder();
42 SkNx_cast<uint8_t>(sk_linear_to_srgb_needs_trunc(pmFloat)).store(&result);
43 result = (result & 0x00FFFFFF) | (color & 0xFF000000);
44 return result;
45 }
46
47 // Legacy premultiply.
48 return SkPreMultiplyColor(color);
49 };
50
51 // Note that these are not necessarily premultiplied, but they are platform byte ordering.
52 SkPMColor pmColors[SK_ARRAY_COUNT(colors)];
53 for (int i = 0; i < (int) SK_ARRAY_COUNT(colors); i++) {
54 pmColors[i] = toPMColor(colors[i]);
55 }
56
57 sk_sp<SkColorTable> colorTable(new SkColorTable(pmColors, SK_ARRAY_COUNT(pmColors)));
58 SkImageInfo info = SkImageInfo::Make(imageWidth, imageHeight, kIndex_8_SkColorType,
59 alphaType, colorSpace);
60 bitmap->allocPixels(info, nullptr, colorTable.get());
61 for (int y = 0; y < imageHeight; y++) {
62 for (int x = 0; x < imageWidth; x++) {
63 *bitmap->getAddr8(x, y) = (x / div_round_up(imageWidth, 2)) +
64 (y / div_round_up(imageHeight, 3));
65 }
66 }
67}
68
69static void make(SkBitmap* bitmap, SkColorType colorType, SkAlphaType alphaType,
70 sk_sp<SkColorSpace> colorSpace) {
71 if (kIndex_8_SkColorType == colorType) {
72 make_index8(bitmap, alphaType, colorSpace);
73 return;
74 }
75
76 sk_sp<SkData> data = GetResourceAsData("color_wheel.png");
77 std::unique_ptr<SkCodec> codec(SkCodec::NewFromData(data));
78 SkImageInfo dstInfo = codec->getInfo().makeColorType(colorType)
79 .makeAlphaType(alphaType)
80 .makeColorSpace(colorSpace);
81 bitmap->allocPixels(dstInfo);
82 codec->getPixels(dstInfo, bitmap->getPixels(), bitmap->rowBytes());
83}
84
85static sk_sp<SkData> encode_data(const SkBitmap& bitmap) {
86 SkAutoLockPixels autoLockPixels(bitmap);
87 SkPixmap src;
88 if (!bitmap.peekPixels(&src)) {
89 return nullptr;
90 }
91 SkDynamicMemoryWStream buf;
92 SkEncodeOptions options;
93 if (bitmap.colorSpace()) {
94 options.fPremulBehavior = SkEncodeOptions::PremulBehavior::kGammaCorrect;
95 }
96 SkAssertResult(SkEncodeImageAsPNG(&buf, src, options));
97 return buf.detachAsData();
98}
99
100class EncodeSRGBGM : public GM {
101public:
102 EncodeSRGBGM() {}
103
104protected:
105 SkString onShortName() override {
106 return SkString("encode-srgb");
107 }
108
109 SkISize onISize() override {
110 return SkISize::Make(imageWidth * 2, imageHeight * 4);
111 }
112
113 void onDraw(SkCanvas* canvas) override {
114 const SkColorType colorTypes[] = { kN32_SkColorType, kIndex_8_SkColorType, };
115 const SkAlphaType alphaTypes[] = { kUnpremul_SkAlphaType, kPremul_SkAlphaType, };
116 const sk_sp<SkColorSpace> colorSpaces[] = {
117 nullptr, SkColorSpace::MakeNamed(SkColorSpace::kSRGB_Named),
118 };
119
120 SkBitmap bitmap;
121 for (SkColorType colorType : colorTypes) {
122 for (SkAlphaType alphaType : alphaTypes) {
123 canvas->save();
124 for (sk_sp<SkColorSpace> colorSpace : colorSpaces) {
125 make(&bitmap, colorType, alphaType, colorSpace);
126 auto image = SkImage::MakeFromEncoded(encode_data(bitmap));
127 canvas->drawImage(image.get(), 0.0f, 0.0f);
128 canvas->translate((float) imageWidth, 0.0f);
129 }
130 canvas->restore();
131 canvas->translate(0.0f, (float) imageHeight);
132 }
133 }
134 }
135
136private:
137 typedef GM INHERITED;
138};
139
140DEF_GM( return new EncodeSRGBGM; )
141}