blob: 894b0ef8d58bb23013e0bb825edef45fd1927989 [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"
Matt Sarett1da27ef2017-01-19 17:14:07 -050013#include "SkColorSpace_Base.h"
Matt Sarett84014f02017-01-10 11:28:54 -050014#include "SkData.h"
15#include "SkImageEncoderPriv.h"
16#include "SkPM4f.h"
17#include "SkSRGB.h"
18
19namespace skiagm {
20
21static const int imageWidth = 128;
22static const int imageHeight = 128;
23
24static inline int div_round_up(int a, int b) {
25 return (a + b - 1) / b;
26}
27
Matt Sarett1da27ef2017-01-19 17:14:07 -050028sk_sp<SkColorSpace> fix_for_colortype(sk_sp<SkColorSpace> colorSpace, SkColorType colorType) {
29 if (kRGBA_F16_SkColorType == colorType) {
30 if (!colorSpace) {
Matt Sarett77a7a1b2017-02-07 13:56:11 -050031 return SkColorSpace::MakeSRGBLinear();
Matt Sarett1da27ef2017-01-19 17:14:07 -050032 }
33
34 return as_CSB(colorSpace)->makeLinearGamma();
35 }
36
37 return colorSpace;
38}
39
Matt Sarett84014f02017-01-10 11:28:54 -050040static void make_index8(SkBitmap* bitmap, SkAlphaType alphaType, sk_sp<SkColorSpace> colorSpace) {
41 const SkColor colors[] = {
42 0x800000FF, 0x8000FF00, 0x80FF0000, 0x80FFFF00,
43 };
44
45 auto toPMColor = [alphaType, colorSpace](SkColor color) {
Matt Sarett62bb2802017-01-23 12:28:02 -050046 // In the opaque/unpremul case, just convert to SkPMColor ordering.
47 if (kPremul_SkAlphaType != alphaType) {
Matt Sarett84014f02017-01-10 11:28:54 -050048 return SkSwizzle_BGRA_to_PMColor(color);
49 }
50
51 // Linear premultiply.
52 if (colorSpace) {
53 uint32_t result;
54 Sk4f pmFloat = SkColor4f::FromColor(color).premul().to4f_pmorder();
55 SkNx_cast<uint8_t>(sk_linear_to_srgb_needs_trunc(pmFloat)).store(&result);
56 result = (result & 0x00FFFFFF) | (color & 0xFF000000);
57 return result;
58 }
59
60 // Legacy premultiply.
61 return SkPreMultiplyColor(color);
62 };
63
64 // Note that these are not necessarily premultiplied, but they are platform byte ordering.
65 SkPMColor pmColors[SK_ARRAY_COUNT(colors)];
66 for (int i = 0; i < (int) SK_ARRAY_COUNT(colors); i++) {
67 pmColors[i] = toPMColor(colors[i]);
68 }
69
Matt Sarett84014f02017-01-10 11:28:54 -050070 SkImageInfo info = SkImageInfo::Make(imageWidth, imageHeight, kIndex_8_SkColorType,
71 alphaType, colorSpace);
Mike Reed6b3155c2017-04-03 14:41:44 -040072 bitmap->allocPixels(info, SkColorTable::Make(pmColors, SK_ARRAY_COUNT(pmColors)));
Matt Sarett84014f02017-01-10 11:28:54 -050073 for (int y = 0; y < imageHeight; y++) {
74 for (int x = 0; x < imageWidth; x++) {
75 *bitmap->getAddr8(x, y) = (x / div_round_up(imageWidth, 2)) +
76 (y / div_round_up(imageHeight, 3));
77 }
78 }
79}
80
81static void make(SkBitmap* bitmap, SkColorType colorType, SkAlphaType alphaType,
82 sk_sp<SkColorSpace> colorSpace) {
Matt Sarette95941f2017-01-27 18:16:40 -050083 const char* resource;
84 switch (colorType) {
85 case kIndex_8_SkColorType:
86 make_index8(bitmap, alphaType, colorSpace);
87 return;
88 case kGray_8_SkColorType:
89 resource = "grayscale.jpg";
90 alphaType = kOpaque_SkAlphaType;
91 break;
92 case kRGB_565_SkColorType:
93 resource = "color_wheel.jpg";
94 alphaType = kOpaque_SkAlphaType;
95 break;
96 default:
97 resource = (kOpaque_SkAlphaType == alphaType) ? "color_wheel.jpg"
98 : "color_wheel.png";
99 break;
Matt Sarett62bb2802017-01-23 12:28:02 -0500100 }
101
Matt Sarett1da27ef2017-01-19 17:14:07 -0500102 sk_sp<SkData> data = GetResourceAsData(resource);
Matt Sarett84014f02017-01-10 11:28:54 -0500103 std::unique_ptr<SkCodec> codec(SkCodec::NewFromData(data));
104 SkImageInfo dstInfo = codec->getInfo().makeColorType(colorType)
105 .makeAlphaType(alphaType)
Matt Sarett1da27ef2017-01-19 17:14:07 -0500106 .makeColorSpace(fix_for_colortype(colorSpace, colorType));
Matt Sarett84014f02017-01-10 11:28:54 -0500107 bitmap->allocPixels(dstInfo);
108 codec->getPixels(dstInfo, bitmap->getPixels(), bitmap->rowBytes());
109}
110
Matt Sarett62bb2802017-01-23 12:28:02 -0500111static sk_sp<SkData> encode_data(const SkBitmap& bitmap, SkEncodedImageFormat format) {
Matt Sarett84014f02017-01-10 11:28:54 -0500112 SkAutoLockPixels autoLockPixels(bitmap);
113 SkPixmap src;
114 if (!bitmap.peekPixels(&src)) {
115 return nullptr;
116 }
117 SkDynamicMemoryWStream buf;
Matt Sarett62bb2802017-01-23 12:28:02 -0500118
Matt Sarett84014f02017-01-10 11:28:54 -0500119 SkEncodeOptions options;
120 if (bitmap.colorSpace()) {
Matt Sarettcf3f2342017-03-23 15:32:25 -0400121 options.fUnpremulBehavior = SkTransferFunctionBehavior::kRespect;
Matt Sarett84014f02017-01-10 11:28:54 -0500122 }
Matt Sarett62bb2802017-01-23 12:28:02 -0500123
124 switch (format) {
125 case SkEncodedImageFormat::kPNG:
Matt Sarette95941f2017-01-27 18:16:40 -0500126 SkAssertResult(SkEncodeImageAsPNG(&buf, src, options));
Matt Sarett62bb2802017-01-23 12:28:02 -0500127 break;
128 case SkEncodedImageFormat::kWEBP:
Matt Sarette95941f2017-01-27 18:16:40 -0500129 SkAssertResult(SkEncodeImageAsWEBP(&buf, src, options));
130 break;
131 case SkEncodedImageFormat::kJPEG:
132 SkAssertResult(SkEncodeImageAsJPEG(&buf, src, options));
Matt Sarett62bb2802017-01-23 12:28:02 -0500133 break;
134 default:
135 break;
136 }
Matt Sarett84014f02017-01-10 11:28:54 -0500137 return buf.detachAsData();
138}
139
140class EncodeSRGBGM : public GM {
141public:
Matt Sarett62bb2802017-01-23 12:28:02 -0500142 EncodeSRGBGM(SkEncodedImageFormat format)
143 : fEncodedFormat(format)
144 {}
Matt Sarett84014f02017-01-10 11:28:54 -0500145
146protected:
147 SkString onShortName() override {
Matt Sarett62bb2802017-01-23 12:28:02 -0500148 const char* format = nullptr;
149 switch (fEncodedFormat) {
150 case SkEncodedImageFormat::kPNG:
Matt Sarette95941f2017-01-27 18:16:40 -0500151 format = "png";
Matt Sarett62bb2802017-01-23 12:28:02 -0500152 break;
153 case SkEncodedImageFormat::kWEBP:
Matt Sarette95941f2017-01-27 18:16:40 -0500154 format = "webp";
155 break;
156 case SkEncodedImageFormat::kJPEG:
157 format = "jpg";
Matt Sarett62bb2802017-01-23 12:28:02 -0500158 break;
159 default:
160 break;
161 }
Matt Sarette95941f2017-01-27 18:16:40 -0500162 return SkStringPrintf("encode-srgb-%s", format);
Matt Sarett84014f02017-01-10 11:28:54 -0500163 }
164
165 SkISize onISize() override {
Matt Sarette95941f2017-01-27 18:16:40 -0500166 return SkISize::Make(imageWidth * 2, imageHeight * 15);
Matt Sarett84014f02017-01-10 11:28:54 -0500167 }
168
169 void onDraw(SkCanvas* canvas) override {
Matt Sarett1da27ef2017-01-19 17:14:07 -0500170 const SkColorType colorTypes[] = {
Matt Sarett62bb2802017-01-23 12:28:02 -0500171 kN32_SkColorType, kRGBA_F16_SkColorType, kIndex_8_SkColorType, kGray_8_SkColorType,
Matt Sarette95941f2017-01-27 18:16:40 -0500172 kRGB_565_SkColorType,
Matt Sarett1da27ef2017-01-19 17:14:07 -0500173 };
174 const SkAlphaType alphaTypes[] = {
175 kUnpremul_SkAlphaType, kPremul_SkAlphaType, kOpaque_SkAlphaType,
176 };
Matt Sarett84014f02017-01-10 11:28:54 -0500177 const sk_sp<SkColorSpace> colorSpaces[] = {
Matt Sarett77a7a1b2017-02-07 13:56:11 -0500178 nullptr, SkColorSpace::MakeSRGB(),
Matt Sarett84014f02017-01-10 11:28:54 -0500179 };
180
181 SkBitmap bitmap;
182 for (SkColorType colorType : colorTypes) {
183 for (SkAlphaType alphaType : alphaTypes) {
184 canvas->save();
185 for (sk_sp<SkColorSpace> colorSpace : colorSpaces) {
186 make(&bitmap, colorType, alphaType, colorSpace);
Matt Sarett62bb2802017-01-23 12:28:02 -0500187 auto image = SkImage::MakeFromEncoded(encode_data(bitmap, fEncodedFormat));
Matt Sarett84014f02017-01-10 11:28:54 -0500188 canvas->drawImage(image.get(), 0.0f, 0.0f);
189 canvas->translate((float) imageWidth, 0.0f);
190 }
191 canvas->restore();
192 canvas->translate(0.0f, (float) imageHeight);
193 }
194 }
195 }
196
197private:
Matt Sarett62bb2802017-01-23 12:28:02 -0500198 SkEncodedImageFormat fEncodedFormat;
199
Matt Sarett84014f02017-01-10 11:28:54 -0500200 typedef GM INHERITED;
201};
202
Matt Sarett62bb2802017-01-23 12:28:02 -0500203DEF_GM( return new EncodeSRGBGM(SkEncodedImageFormat::kPNG); )
204DEF_GM( return new EncodeSRGBGM(SkEncodedImageFormat::kWEBP); )
Matt Sarette95941f2017-01-27 18:16:40 -0500205DEF_GM( return new EncodeSRGBGM(SkEncodedImageFormat::kJPEG); )
Matt Sarett84014f02017-01-10 11:28:54 -0500206}