1 /*
2 * Copyright 2020 Google LLC
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/gm.h"
9 #include "include/core/SkCanvas.h"
10 #include "include/core/SkData.h"
11 #include "include/core/SkEncodedImageFormat.h"
12 #include "include/core/SkImage.h"
13 #include "include/core/SkImageInfo.h"
14 #include "include/core/SkSize.h"
15 #include "include/core/SkString.h"
16 #include "include/core/SkSurface.h"
17 #include "tools/Resources.h"
18
19 namespace skiagm {
20
21 static const int imageWidth = 128;
22 static const int imageHeight = 128;
23
make_image(SkColorType colorType,SkAlphaType alphaType)24 static sk_sp<SkImage> make_image(SkColorType colorType, SkAlphaType alphaType) {
25 const char* resource;
26 switch (colorType) {
27 case kGray_8_SkColorType:
28 if (alphaType != kOpaque_SkAlphaType) {
29 return nullptr;
30 }
31 resource = "images/grayscale.jpg";
32 break;
33 case kRGB_565_SkColorType:
34 case kRGB_888x_SkColorType:
35 case kRGB_101010x_SkColorType:
36 case kBGR_101010x_SkColorType:
37 if (alphaType != kOpaque_SkAlphaType) {
38 return nullptr;
39 }
40 resource = "images/color_wheel.jpg";
41 break;
42 default:
43 resource = (kOpaque_SkAlphaType == alphaType) ? "images/color_wheel.jpg"
44 : "images/rainbow-gradient.png";
45 break;
46 }
47
48 auto image = GetResourceAsImage(resource);
49 if (!image) {
50 return nullptr;
51 }
52
53 auto surface = SkSurface::MakeRaster(SkImageInfo::Make(image->width(), image->height(),
54 colorType, alphaType, image->refColorSpace()));
55 surface->getCanvas()->drawImage(image, 0, 0);
56 return surface->makeImageSnapshot();
57 }
58
59 // This GM looks different depending on the colortype used, so we use different
60 // names to treat them as different GMs.
61 // All Variants draw images in pairs:
62 // - First as an image of the SkColorType of the destination
63 // - Next as the result of encoding and decoding the first image
64 enum class Variant {
65 // One pair, using an opaque image.
66 kOpaque,
67 // One pair, using a grayscale image.
68 kGray,
69 // An opaque pair followed by two more for premul and unpremul.
70 kNormal,
71 };
72
73 class EncodeColorTypesGM : public GM {
74 public:
EncodeColorTypesGM(SkEncodedImageFormat format,int quality,Variant variant,const char * name)75 EncodeColorTypesGM(SkEncodedImageFormat format, int quality, Variant variant, const char* name)
76 : fFormat(format)
77 , fQuality(quality)
78 , fVariant(variant)
79 , fName(name)
80 {}
81
82 protected:
onShortName()83 SkString onShortName() override {
84 const char* variant = fVariant == Variant::kOpaque ? "opaque-":
85 fVariant == Variant::kGray ? "gray-" :
86 "" ;
87 return SkStringPrintf("encode-%scolor-types-%s", variant, fName);
88 }
89
onISize()90 SkISize onISize() override {
91 const int width = fVariant == Variant::kNormal ? imageWidth * 7 : imageWidth * 2;
92 return SkISize::Make(width, imageHeight);
93 }
94
onDraw(SkCanvas * canvas,SkString * errorMsg)95 DrawResult onDraw(SkCanvas* canvas, SkString* errorMsg) override {
96 const auto colorType = canvas->imageInfo().colorType();
97 switch (fVariant) {
98 case Variant::kGray:
99 if (colorType != kGray_8_SkColorType) {
100 return DrawResult::kSkip;
101 }
102 break;
103 case Variant::kOpaque:
104 if (colorType != kRGB_565_SkColorType &&
105 colorType != kRGB_888x_SkColorType &&
106 colorType != kRGB_101010x_SkColorType &&
107 colorType != kBGR_101010x_SkColorType)
108 {
109 return DrawResult::kSkip;
110 }
111 break;
112 case Variant::kNormal:
113 if (colorType != kARGB_4444_SkColorType &&
114 colorType != kRGBA_8888_SkColorType &&
115 colorType != kBGRA_8888_SkColorType &&
116 colorType != kRGBA_1010102_SkColorType &&
117 colorType != kBGRA_1010102_SkColorType &&
118 colorType != kRGBA_F16Norm_SkColorType &&
119 colorType != kRGBA_F16_SkColorType &&
120 colorType != kRGBA_F32_SkColorType)
121 {
122 return DrawResult::kSkip;
123 }
124 break;
125 }
126 const SkAlphaType alphaTypes[] = {
127 kOpaque_SkAlphaType, kPremul_SkAlphaType, kUnpremul_SkAlphaType,
128 };
129
130 for (SkAlphaType alphaType : alphaTypes) {
131 auto src = make_image(colorType, alphaType);
132 auto decoded = src ? SkImage::MakeFromEncoded(src->encodeToData(fFormat, fQuality))
133 : nullptr;
134 if (!src || !decoded) {
135 break;
136 }
137
138 canvas->drawImage(src, 0.0f, 0.0f);
139 canvas->translate((float) imageWidth, 0.0f);
140
141 canvas->drawImage(decoded, 0.0f, 0.0f);
142 canvas->translate((float) imageWidth * 1.5, 0.0f);
143 }
144 return DrawResult::kOk;
145 }
146
147 private:
148 const SkEncodedImageFormat fFormat;
149 const int fQuality;
150 const Variant fVariant;
151 const char* fName;
152
153 using INHERITED = GM;
154 };
155
156
157 #define DEF_ENCODE_GM(format, quality, variant, name) \
158 static skiagm::GMRegistry SK_MACRO_CONCAT(SK_MACRO_APPEND_LINE(REG_), variant)(\
159 [](){return std::unique_ptr<skiagm::GM>([](){\
160 return new EncodeColorTypesGM(format, quality, Variant::variant, name);\
161 }());});
162
163 #define DEF_VARIANTS(format, quality, name) \
164 DEF_ENCODE_GM(format, quality, kNormal, name); \
165 DEF_ENCODE_GM(format, quality, kOpaque, name); \
166 DEF_ENCODE_GM(format, quality, kGray, name);
167
168 DEF_VARIANTS(SkEncodedImageFormat::kWEBP, 100, "webp-lossless")
169 DEF_VARIANTS(SkEncodedImageFormat::kWEBP, 80, "webp-lossy")
170 } // namespace skiagm
171