2 * Copyright 2016 Google Inc.
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
10 #include "Resources.h"
13 #include "SkColorSpace_Base.h"
16 #include "SkImageEncoderPriv.h"
17 #include "SkJpegEncoder.h"
23 static const int imageWidth = 128;
24 static const int imageHeight = 128;
26 static inline int div_round_up(int a, int b) {
27 return (a + b - 1) / b;
30 sk_sp<SkColorSpace> fix_for_colortype(sk_sp<SkColorSpace> colorSpace, SkColorType colorType) {
31 if (kRGBA_F16_SkColorType == colorType) {
33 return SkColorSpace::MakeSRGBLinear();
36 return as_CSB(colorSpace)->makeLinearGamma();
42 static void make_index8(SkBitmap* bitmap, SkAlphaType alphaType, sk_sp<SkColorSpace> colorSpace) {
43 const SkColor colors[] = {
44 0x800000FF, 0x8000FF00, 0x80FF0000, 0x80FFFF00,
47 auto toPMColor = [alphaType, colorSpace](SkColor color) {
48 // In the opaque/unpremul case, just convert to SkPMColor ordering.
49 if (kPremul_SkAlphaType != alphaType) {
50 return SkSwizzle_BGRA_to_PMColor(color);
53 // Linear premultiply.
56 Sk4f pmFloat = SkColor4f::FromColor(color).premul().to4f_pmorder();
57 SkNx_cast<uint8_t>(sk_linear_to_srgb_needs_trunc(pmFloat)).store(&result);
58 result = (result & 0x00FFFFFF) | (color & 0xFF000000);
62 // Legacy premultiply.
63 return SkPreMultiplyColor(color);
66 // Note that these are not necessarily premultiplied, but they are platform byte ordering.
67 SkPMColor pmColors[SK_ARRAY_COUNT(colors)];
68 for (int i = 0; i < (int) SK_ARRAY_COUNT(colors); i++) {
69 pmColors[i] = toPMColor(colors[i]);
72 SkImageInfo info = SkImageInfo::Make(imageWidth, imageHeight, kIndex_8_SkColorType,
73 alphaType, colorSpace);
74 bitmap->allocPixels(info, SkColorTable::Make(pmColors, SK_ARRAY_COUNT(pmColors)));
75 for (int y = 0; y < imageHeight; y++) {
76 for (int x = 0; x < imageWidth; x++) {
77 *bitmap->getAddr8(x, y) = (x / div_round_up(imageWidth, 2)) +
78 (y / div_round_up(imageHeight, 3));
83 static void make(SkBitmap* bitmap, SkColorType colorType, SkAlphaType alphaType,
84 sk_sp<SkColorSpace> colorSpace) {
87 case kIndex_8_SkColorType:
88 make_index8(bitmap, alphaType, colorSpace);
90 case kGray_8_SkColorType:
91 resource = "grayscale.jpg";
92 alphaType = kOpaque_SkAlphaType;
94 case kRGB_565_SkColorType:
95 resource = "color_wheel.jpg";
96 alphaType = kOpaque_SkAlphaType;
99 resource = (kOpaque_SkAlphaType == alphaType) ? "color_wheel.jpg"
104 sk_sp<SkData> data = GetResourceAsData(resource);
105 std::unique_ptr<SkCodec> codec(SkCodec::NewFromData(data));
106 SkImageInfo dstInfo = codec->getInfo().makeColorType(colorType)
107 .makeAlphaType(alphaType)
108 .makeColorSpace(fix_for_colortype(colorSpace, colorType));
109 bitmap->allocPixels(dstInfo);
110 codec->getPixels(dstInfo, bitmap->getPixels(), bitmap->rowBytes());
113 static sk_sp<SkData> encode_data(const SkBitmap& bitmap, SkEncodedImageFormat format) {
115 if (!bitmap.peekPixels(&src)) {
118 SkDynamicMemoryWStream buf;
120 SkEncodeOptions options;
121 if (bitmap.colorSpace()) {
122 options.fUnpremulBehavior = SkTransferFunctionBehavior::kRespect;
126 case SkEncodedImageFormat::kPNG:
127 SkAssertResult(SkEncodeImageAsPNG(&buf, src, options));
129 case SkEncodedImageFormat::kWEBP:
130 SkAssertResult(SkEncodeImageAsWEBP(&buf, src, options));
132 case SkEncodedImageFormat::kJPEG:
133 SkAssertResult(SkJpegEncoder::Encode(&buf, src, SkJpegEncoder::Options()));
138 return buf.detachAsData();
141 class EncodeSRGBGM : public GM {
143 EncodeSRGBGM(SkEncodedImageFormat format)
144 : fEncodedFormat(format)
148 SkString onShortName() override {
149 const char* format = nullptr;
150 switch (fEncodedFormat) {
151 case SkEncodedImageFormat::kPNG:
154 case SkEncodedImageFormat::kWEBP:
157 case SkEncodedImageFormat::kJPEG:
163 return SkStringPrintf("encode-srgb-%s", format);
166 SkISize onISize() override {
167 return SkISize::Make(imageWidth * 2, imageHeight * 15);
170 void onDraw(SkCanvas* canvas) override {
171 const SkColorType colorTypes[] = {
172 kN32_SkColorType, kRGBA_F16_SkColorType, kIndex_8_SkColorType, kGray_8_SkColorType,
173 kRGB_565_SkColorType,
175 const SkAlphaType alphaTypes[] = {
176 kUnpremul_SkAlphaType, kPremul_SkAlphaType, kOpaque_SkAlphaType,
178 const sk_sp<SkColorSpace> colorSpaces[] = {
179 nullptr, SkColorSpace::MakeSRGB(),
183 for (SkColorType colorType : colorTypes) {
184 for (SkAlphaType alphaType : alphaTypes) {
186 for (sk_sp<SkColorSpace> colorSpace : colorSpaces) {
187 make(&bitmap, colorType, alphaType, colorSpace);
188 auto image = SkImage::MakeFromEncoded(encode_data(bitmap, fEncodedFormat));
189 canvas->drawImage(image.get(), 0.0f, 0.0f);
190 canvas->translate((float) imageWidth, 0.0f);
193 canvas->translate(0.0f, (float) imageHeight);
199 SkEncodedImageFormat fEncodedFormat;
201 typedef GM INHERITED;
204 DEF_GM( return new EncodeSRGBGM(SkEncodedImageFormat::kPNG); )
205 DEF_GM( return new EncodeSRGBGM(SkEncodedImageFormat::kWEBP); )
206 DEF_GM( return new EncodeSRGBGM(SkEncodedImageFormat::kJPEG); )