1 /*
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 "SkImage.h"
15 #include "SkImageEncoderPriv.h"
16 #include "SkJpegEncoder.h"
17 #include "SkPngEncoder.h"
18 #include "SkPM4f.h"
19 #include "SkSRGB.h"
20 #include "SkWebpEncoder.h"
21
22 namespace skiagm {
23
24 static const int imageWidth = 128;
25 static const int imageHeight = 128;
26
fix_for_colortype(sk_sp<SkColorSpace> colorSpace,SkColorType colorType)27 sk_sp<SkColorSpace> fix_for_colortype(sk_sp<SkColorSpace> colorSpace, SkColorType colorType) {
28 if (kRGBA_F16_SkColorType == colorType) {
29 if (!colorSpace) {
30 return SkColorSpace::MakeSRGBLinear();
31 }
32
33 return colorSpace->makeLinearGamma();
34 }
35
36 return colorSpace;
37 }
38
make(SkBitmap * bitmap,SkColorType colorType,SkAlphaType alphaType,sk_sp<SkColorSpace> colorSpace)39 static void make(SkBitmap* bitmap, SkColorType colorType, SkAlphaType alphaType,
40 sk_sp<SkColorSpace> colorSpace) {
41 const char* resource;
42 switch (colorType) {
43 case kGray_8_SkColorType:
44 resource = "images/grayscale.jpg";
45 alphaType = kOpaque_SkAlphaType;
46 break;
47 case kRGB_565_SkColorType:
48 resource = "images/color_wheel.jpg";
49 alphaType = kOpaque_SkAlphaType;
50 break;
51 default:
52 resource = (kOpaque_SkAlphaType == alphaType) ? "images/color_wheel.jpg"
53 : "images/color_wheel.png";
54 break;
55 }
56
57 sk_sp<SkData> data = GetResourceAsData(resource);
58 std::unique_ptr<SkCodec> codec = SkCodec::MakeFromData(data);
59 SkImageInfo dstInfo = codec->getInfo().makeColorType(colorType)
60 .makeAlphaType(alphaType)
61 .makeColorSpace(fix_for_colortype(colorSpace, colorType));
62 bitmap->allocPixels(dstInfo);
63 codec->getPixels(dstInfo, bitmap->getPixels(), bitmap->rowBytes());
64 }
65
encode_data(const SkBitmap & bitmap,SkEncodedImageFormat format)66 static sk_sp<SkData> encode_data(const SkBitmap& bitmap, SkEncodedImageFormat format) {
67 SkPixmap src;
68 if (!bitmap.peekPixels(&src)) {
69 return nullptr;
70 }
71 SkDynamicMemoryWStream buf;
72
73 SkPngEncoder::Options pngOptions;
74 SkWebpEncoder::Options webpOptions;
75 SkTransferFunctionBehavior behavior = bitmap.colorSpace()
76 ? SkTransferFunctionBehavior::kRespect : SkTransferFunctionBehavior::kIgnore;
77 pngOptions.fUnpremulBehavior = behavior;
78 webpOptions.fUnpremulBehavior = behavior;
79
80 switch (format) {
81 case SkEncodedImageFormat::kPNG:
82 SkAssertResult(SkPngEncoder::Encode(&buf, src, pngOptions));
83 break;
84 case SkEncodedImageFormat::kWEBP:
85 SkAssertResult(SkWebpEncoder::Encode(&buf, src, webpOptions));
86 break;
87 case SkEncodedImageFormat::kJPEG:
88 SkAssertResult(SkJpegEncoder::Encode(&buf, src, SkJpegEncoder::Options()));
89 break;
90 default:
91 break;
92 }
93 return buf.detachAsData();
94 }
95
96 class EncodeSRGBGM : public GM {
97 public:
EncodeSRGBGM(SkEncodedImageFormat format)98 EncodeSRGBGM(SkEncodedImageFormat format)
99 : fEncodedFormat(format)
100 {}
101
102 protected:
onShortName()103 SkString onShortName() override {
104 const char* format = nullptr;
105 switch (fEncodedFormat) {
106 case SkEncodedImageFormat::kPNG:
107 format = "png";
108 break;
109 case SkEncodedImageFormat::kWEBP:
110 format = "webp";
111 break;
112 case SkEncodedImageFormat::kJPEG:
113 format = "jpg";
114 break;
115 default:
116 break;
117 }
118 return SkStringPrintf("encode-srgb-%s", format);
119 }
120
onISize()121 SkISize onISize() override {
122 return SkISize::Make(imageWidth * 2, imageHeight * 15);
123 }
124
onDraw(SkCanvas * canvas)125 void onDraw(SkCanvas* canvas) override {
126 const SkColorType colorTypes[] = {
127 kN32_SkColorType, kRGBA_F16_SkColorType, kGray_8_SkColorType, kRGB_565_SkColorType,
128 };
129 const SkAlphaType alphaTypes[] = {
130 kUnpremul_SkAlphaType, kPremul_SkAlphaType, kOpaque_SkAlphaType,
131 };
132 const sk_sp<SkColorSpace> colorSpaces[] = {
133 nullptr, SkColorSpace::MakeSRGB(),
134 };
135
136 SkBitmap bitmap;
137 for (SkColorType colorType : colorTypes) {
138 for (SkAlphaType alphaType : alphaTypes) {
139 canvas->save();
140 for (sk_sp<SkColorSpace> colorSpace : colorSpaces) {
141 make(&bitmap, colorType, alphaType, colorSpace);
142 auto image = SkImage::MakeFromEncoded(encode_data(bitmap, fEncodedFormat));
143 canvas->drawImage(image.get(), 0.0f, 0.0f);
144 canvas->translate((float) imageWidth, 0.0f);
145 }
146 canvas->restore();
147 canvas->translate(0.0f, (float) imageHeight);
148 }
149 }
150 }
151
152 private:
153 SkEncodedImageFormat fEncodedFormat;
154
155 typedef GM INHERITED;
156 };
157
158 DEF_GM( return new EncodeSRGBGM(SkEncodedImageFormat::kPNG); )
159 DEF_GM( return new EncodeSRGBGM(SkEncodedImageFormat::kWEBP); )
160 DEF_GM( return new EncodeSRGBGM(SkEncodedImageFormat::kJPEG); )
161 }
162