blob: 3369afe4dc2b2d8c9c50a1b66f4b9710bba4b7c4 [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"
Florin Malitaab244f02017-05-03 19:16:58 +000015#include "SkImage.h"
Matt Sarett84014f02017-01-10 11:28:54 -050016#include "SkImageEncoderPriv.h"
Matt Sarett26b44df2017-05-02 16:04:56 -040017#include "SkJpegEncoder.h"
Matt Sarettc367d032017-05-05 11:13:26 -040018#include "SkPngEncoder.h"
Matt Sarett84014f02017-01-10 11:28:54 -050019#include "SkPM4f.h"
20#include "SkSRGB.h"
Matt Sarett04c37312017-05-05 14:02:13 -040021#include "SkWebpEncoder.h"
Matt Sarett84014f02017-01-10 11:28:54 -050022
23namespace skiagm {
24
25static const int imageWidth = 128;
26static const int imageHeight = 128;
27
28static inline int div_round_up(int a, int b) {
29 return (a + b - 1) / b;
30}
31
Matt Sarett1da27ef2017-01-19 17:14:07 -050032sk_sp<SkColorSpace> fix_for_colortype(sk_sp<SkColorSpace> colorSpace, SkColorType colorType) {
33 if (kRGBA_F16_SkColorType == colorType) {
34 if (!colorSpace) {
Matt Sarett77a7a1b2017-02-07 13:56:11 -050035 return SkColorSpace::MakeSRGBLinear();
Matt Sarett1da27ef2017-01-19 17:14:07 -050036 }
37
38 return as_CSB(colorSpace)->makeLinearGamma();
39 }
40
41 return colorSpace;
42}
43
Matt Sarett84014f02017-01-10 11:28:54 -050044static void make_index8(SkBitmap* bitmap, SkAlphaType alphaType, sk_sp<SkColorSpace> colorSpace) {
45 const SkColor colors[] = {
46 0x800000FF, 0x8000FF00, 0x80FF0000, 0x80FFFF00,
47 };
48
49 auto toPMColor = [alphaType, colorSpace](SkColor color) {
Matt Sarett62bb2802017-01-23 12:28:02 -050050 // In the opaque/unpremul case, just convert to SkPMColor ordering.
51 if (kPremul_SkAlphaType != alphaType) {
Matt Sarett84014f02017-01-10 11:28:54 -050052 return SkSwizzle_BGRA_to_PMColor(color);
53 }
54
55 // Linear premultiply.
56 if (colorSpace) {
57 uint32_t result;
58 Sk4f pmFloat = SkColor4f::FromColor(color).premul().to4f_pmorder();
59 SkNx_cast<uint8_t>(sk_linear_to_srgb_needs_trunc(pmFloat)).store(&result);
60 result = (result & 0x00FFFFFF) | (color & 0xFF000000);
61 return result;
62 }
63
64 // Legacy premultiply.
65 return SkPreMultiplyColor(color);
66 };
67
68 // Note that these are not necessarily premultiplied, but they are platform byte ordering.
69 SkPMColor pmColors[SK_ARRAY_COUNT(colors)];
70 for (int i = 0; i < (int) SK_ARRAY_COUNT(colors); i++) {
71 pmColors[i] = toPMColor(colors[i]);
72 }
73
Matt Sarett84014f02017-01-10 11:28:54 -050074 SkImageInfo info = SkImageInfo::Make(imageWidth, imageHeight, kIndex_8_SkColorType,
75 alphaType, colorSpace);
Mike Reed6b3155c2017-04-03 14:41:44 -040076 bitmap->allocPixels(info, SkColorTable::Make(pmColors, SK_ARRAY_COUNT(pmColors)));
Matt Sarett84014f02017-01-10 11:28:54 -050077 for (int y = 0; y < imageHeight; y++) {
78 for (int x = 0; x < imageWidth; x++) {
79 *bitmap->getAddr8(x, y) = (x / div_round_up(imageWidth, 2)) +
80 (y / div_round_up(imageHeight, 3));
81 }
82 }
83}
84
85static void make(SkBitmap* bitmap, SkColorType colorType, SkAlphaType alphaType,
86 sk_sp<SkColorSpace> colorSpace) {
Matt Sarette95941f2017-01-27 18:16:40 -050087 const char* resource;
88 switch (colorType) {
89 case kIndex_8_SkColorType:
90 make_index8(bitmap, alphaType, colorSpace);
91 return;
92 case kGray_8_SkColorType:
93 resource = "grayscale.jpg";
94 alphaType = kOpaque_SkAlphaType;
95 break;
96 case kRGB_565_SkColorType:
97 resource = "color_wheel.jpg";
98 alphaType = kOpaque_SkAlphaType;
99 break;
100 default:
101 resource = (kOpaque_SkAlphaType == alphaType) ? "color_wheel.jpg"
102 : "color_wheel.png";
103 break;
Matt Sarett62bb2802017-01-23 12:28:02 -0500104 }
105
Matt Sarett1da27ef2017-01-19 17:14:07 -0500106 sk_sp<SkData> data = GetResourceAsData(resource);
Matt Sarett84014f02017-01-10 11:28:54 -0500107 std::unique_ptr<SkCodec> codec(SkCodec::NewFromData(data));
108 SkImageInfo dstInfo = codec->getInfo().makeColorType(colorType)
109 .makeAlphaType(alphaType)
Matt Sarett1da27ef2017-01-19 17:14:07 -0500110 .makeColorSpace(fix_for_colortype(colorSpace, colorType));
Matt Sarett84014f02017-01-10 11:28:54 -0500111 bitmap->allocPixels(dstInfo);
112 codec->getPixels(dstInfo, bitmap->getPixels(), bitmap->rowBytes());
113}
114
Matt Sarett62bb2802017-01-23 12:28:02 -0500115static sk_sp<SkData> encode_data(const SkBitmap& bitmap, SkEncodedImageFormat format) {
Matt Sarett84014f02017-01-10 11:28:54 -0500116 SkPixmap src;
117 if (!bitmap.peekPixels(&src)) {
118 return nullptr;
119 }
120 SkDynamicMemoryWStream buf;
Matt Sarett62bb2802017-01-23 12:28:02 -0500121
Matt Sarettc367d032017-05-05 11:13:26 -0400122 SkPngEncoder::Options pngOptions;
Matt Sarett04c37312017-05-05 14:02:13 -0400123 SkWebpEncoder::Options webpOptions;
Matt Sarett84014f02017-01-10 11:28:54 -0500124 if (bitmap.colorSpace()) {
Matt Sarettc367d032017-05-05 11:13:26 -0400125 pngOptions.fUnpremulBehavior = SkTransferFunctionBehavior::kRespect;
Matt Sarett04c37312017-05-05 14:02:13 -0400126 webpOptions.fUnpremulBehavior = SkTransferFunctionBehavior::kRespect;
Matt Sarett84014f02017-01-10 11:28:54 -0500127 }
Matt Sarett62bb2802017-01-23 12:28:02 -0500128
129 switch (format) {
130 case SkEncodedImageFormat::kPNG:
Matt Sarettc367d032017-05-05 11:13:26 -0400131 SkAssertResult(SkPngEncoder::Encode(&buf, src, pngOptions));
Matt Sarett62bb2802017-01-23 12:28:02 -0500132 break;
133 case SkEncodedImageFormat::kWEBP:
Matt Sarett04c37312017-05-05 14:02:13 -0400134 SkAssertResult(SkWebpEncoder::Encode(&buf, src, webpOptions));
Matt Sarette95941f2017-01-27 18:16:40 -0500135 break;
136 case SkEncodedImageFormat::kJPEG:
Matt Sarett26b44df2017-05-02 16:04:56 -0400137 SkAssertResult(SkJpegEncoder::Encode(&buf, src, SkJpegEncoder::Options()));
Matt Sarett62bb2802017-01-23 12:28:02 -0500138 break;
139 default:
140 break;
141 }
Matt Sarett84014f02017-01-10 11:28:54 -0500142 return buf.detachAsData();
143}
144
145class EncodeSRGBGM : public GM {
146public:
Matt Sarett62bb2802017-01-23 12:28:02 -0500147 EncodeSRGBGM(SkEncodedImageFormat format)
148 : fEncodedFormat(format)
149 {}
Matt Sarett84014f02017-01-10 11:28:54 -0500150
151protected:
152 SkString onShortName() override {
Matt Sarett62bb2802017-01-23 12:28:02 -0500153 const char* format = nullptr;
154 switch (fEncodedFormat) {
155 case SkEncodedImageFormat::kPNG:
Matt Sarette95941f2017-01-27 18:16:40 -0500156 format = "png";
Matt Sarett62bb2802017-01-23 12:28:02 -0500157 break;
158 case SkEncodedImageFormat::kWEBP:
Matt Sarette95941f2017-01-27 18:16:40 -0500159 format = "webp";
160 break;
161 case SkEncodedImageFormat::kJPEG:
162 format = "jpg";
Matt Sarett62bb2802017-01-23 12:28:02 -0500163 break;
164 default:
165 break;
166 }
Matt Sarette95941f2017-01-27 18:16:40 -0500167 return SkStringPrintf("encode-srgb-%s", format);
Matt Sarett84014f02017-01-10 11:28:54 -0500168 }
169
170 SkISize onISize() override {
Matt Sarette95941f2017-01-27 18:16:40 -0500171 return SkISize::Make(imageWidth * 2, imageHeight * 15);
Matt Sarett84014f02017-01-10 11:28:54 -0500172 }
173
174 void onDraw(SkCanvas* canvas) override {
Matt Sarett1da27ef2017-01-19 17:14:07 -0500175 const SkColorType colorTypes[] = {
Matt Sarett62bb2802017-01-23 12:28:02 -0500176 kN32_SkColorType, kRGBA_F16_SkColorType, kIndex_8_SkColorType, kGray_8_SkColorType,
Matt Sarette95941f2017-01-27 18:16:40 -0500177 kRGB_565_SkColorType,
Matt Sarett1da27ef2017-01-19 17:14:07 -0500178 };
179 const SkAlphaType alphaTypes[] = {
180 kUnpremul_SkAlphaType, kPremul_SkAlphaType, kOpaque_SkAlphaType,
181 };
Matt Sarett84014f02017-01-10 11:28:54 -0500182 const sk_sp<SkColorSpace> colorSpaces[] = {
Matt Sarett77a7a1b2017-02-07 13:56:11 -0500183 nullptr, SkColorSpace::MakeSRGB(),
Matt Sarett84014f02017-01-10 11:28:54 -0500184 };
185
186 SkBitmap bitmap;
187 for (SkColorType colorType : colorTypes) {
188 for (SkAlphaType alphaType : alphaTypes) {
189 canvas->save();
190 for (sk_sp<SkColorSpace> colorSpace : colorSpaces) {
191 make(&bitmap, colorType, alphaType, colorSpace);
Matt Sarett62bb2802017-01-23 12:28:02 -0500192 auto image = SkImage::MakeFromEncoded(encode_data(bitmap, fEncodedFormat));
Matt Sarett84014f02017-01-10 11:28:54 -0500193 canvas->drawImage(image.get(), 0.0f, 0.0f);
194 canvas->translate((float) imageWidth, 0.0f);
195 }
196 canvas->restore();
197 canvas->translate(0.0f, (float) imageHeight);
198 }
199 }
200 }
201
202private:
Matt Sarett62bb2802017-01-23 12:28:02 -0500203 SkEncodedImageFormat fEncodedFormat;
204
Matt Sarett84014f02017-01-10 11:28:54 -0500205 typedef GM INHERITED;
206};
207
Matt Sarett62bb2802017-01-23 12:28:02 -0500208DEF_GM( return new EncodeSRGBGM(SkEncodedImageFormat::kPNG); )
209DEF_GM( return new EncodeSRGBGM(SkEncodedImageFormat::kWEBP); )
Matt Sarette95941f2017-01-27 18:16:40 -0500210DEF_GM( return new EncodeSRGBGM(SkEncodedImageFormat::kJPEG); )
Matt Sarett84014f02017-01-10 11:28:54 -0500211}