xref: /aosp_15_r20/external/skia/tests/EncodeTest.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker  * Copyright 2017 Google Inc.
3*c8dee2aaSAndroid Build Coastguard Worker  *
4*c8dee2aaSAndroid Build Coastguard Worker  * Use of this source code is governed by a BSD-style license that can be
5*c8dee2aaSAndroid Build Coastguard Worker  * found in the LICENSE file.
6*c8dee2aaSAndroid Build Coastguard Worker  */
7*c8dee2aaSAndroid Build Coastguard Worker 
8*c8dee2aaSAndroid Build Coastguard Worker #include "include/codec/SkCodec.h"
9*c8dee2aaSAndroid Build Coastguard Worker #include "include/codec/SkEncodedImageFormat.h"
10*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkAlphaType.h"
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkBitmap.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkCanvas.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkColor.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkColorPriv.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkColorType.h"
16*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkData.h"
17*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkDataTable.h"
18*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkImage.h"
19*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkImageInfo.h"
20*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPixmap.h"
21*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkRefCnt.h"
22*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkStream.h"
23*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkSurface.h"
24*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkTypes.h"
25*c8dee2aaSAndroid Build Coastguard Worker #include "include/encode/SkEncoder.h"
26*c8dee2aaSAndroid Build Coastguard Worker #include "include/encode/SkJpegEncoder.h"
27*c8dee2aaSAndroid Build Coastguard Worker #include "include/encode/SkPngEncoder.h"
28*c8dee2aaSAndroid Build Coastguard Worker #include "include/encode/SkWebpEncoder.h"
29*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkAssert.h"
30*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkMalloc.h"
31*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkTemplates.h"
32*c8dee2aaSAndroid Build Coastguard Worker #include "modules/skcms/src/skcms_public.h"
33*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkImageInfoPriv.h"
34*c8dee2aaSAndroid Build Coastguard Worker #include "tests/Test.h"
35*c8dee2aaSAndroid Build Coastguard Worker #include "tools/DecodeUtils.h"
36*c8dee2aaSAndroid Build Coastguard Worker 
37*c8dee2aaSAndroid Build Coastguard Worker #include <png.h>
38*c8dee2aaSAndroid Build Coastguard Worker #include <webp/decode.h>
39*c8dee2aaSAndroid Build Coastguard Worker 
40*c8dee2aaSAndroid Build Coastguard Worker #include <algorithm>
41*c8dee2aaSAndroid Build Coastguard Worker #include <cstddef>
42*c8dee2aaSAndroid Build Coastguard Worker #include <initializer_list>
43*c8dee2aaSAndroid Build Coastguard Worker #include <memory>
44*c8dee2aaSAndroid Build Coastguard Worker #include <string>
45*c8dee2aaSAndroid Build Coastguard Worker #include <vector>
46*c8dee2aaSAndroid Build Coastguard Worker 
encode(SkEncodedImageFormat format,SkWStream * dst,const SkPixmap & src)47*c8dee2aaSAndroid Build Coastguard Worker static bool encode(SkEncodedImageFormat format, SkWStream* dst, const SkPixmap& src) {
48*c8dee2aaSAndroid Build Coastguard Worker     switch (format) {
49*c8dee2aaSAndroid Build Coastguard Worker         case SkEncodedImageFormat::kJPEG:
50*c8dee2aaSAndroid Build Coastguard Worker             return SkJpegEncoder::Encode(dst, src, SkJpegEncoder::Options());
51*c8dee2aaSAndroid Build Coastguard Worker         case SkEncodedImageFormat::kPNG:
52*c8dee2aaSAndroid Build Coastguard Worker             return SkPngEncoder::Encode(dst, src, SkPngEncoder::Options());
53*c8dee2aaSAndroid Build Coastguard Worker         default:
54*c8dee2aaSAndroid Build Coastguard Worker             return false;
55*c8dee2aaSAndroid Build Coastguard Worker     }
56*c8dee2aaSAndroid Build Coastguard Worker }
57*c8dee2aaSAndroid Build Coastguard Worker 
make(SkEncodedImageFormat format,SkWStream * dst,const SkPixmap & src)58*c8dee2aaSAndroid Build Coastguard Worker static std::unique_ptr<SkEncoder> make(SkEncodedImageFormat format, SkWStream* dst,
59*c8dee2aaSAndroid Build Coastguard Worker                                        const SkPixmap& src) {
60*c8dee2aaSAndroid Build Coastguard Worker     switch (format) {
61*c8dee2aaSAndroid Build Coastguard Worker         case SkEncodedImageFormat::kJPEG:
62*c8dee2aaSAndroid Build Coastguard Worker             return SkJpegEncoder::Make(dst, src, SkJpegEncoder::Options());
63*c8dee2aaSAndroid Build Coastguard Worker         case SkEncodedImageFormat::kPNG:
64*c8dee2aaSAndroid Build Coastguard Worker             return SkPngEncoder::Make(dst, src, SkPngEncoder::Options());
65*c8dee2aaSAndroid Build Coastguard Worker         default:
66*c8dee2aaSAndroid Build Coastguard Worker             return nullptr;
67*c8dee2aaSAndroid Build Coastguard Worker     }
68*c8dee2aaSAndroid Build Coastguard Worker }
69*c8dee2aaSAndroid Build Coastguard Worker 
test_encode(skiatest::Reporter * r,SkEncodedImageFormat format)70*c8dee2aaSAndroid Build Coastguard Worker static void test_encode(skiatest::Reporter* r, SkEncodedImageFormat format) {
71*c8dee2aaSAndroid Build Coastguard Worker     SkBitmap bitmap;
72*c8dee2aaSAndroid Build Coastguard Worker     bool success = ToolUtils::GetResourceAsBitmap("images/mandrill_128.png", &bitmap);
73*c8dee2aaSAndroid Build Coastguard Worker     if (!success) {
74*c8dee2aaSAndroid Build Coastguard Worker         return;
75*c8dee2aaSAndroid Build Coastguard Worker     }
76*c8dee2aaSAndroid Build Coastguard Worker 
77*c8dee2aaSAndroid Build Coastguard Worker     SkPixmap src;
78*c8dee2aaSAndroid Build Coastguard Worker     success = bitmap.peekPixels(&src);
79*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(r, success);
80*c8dee2aaSAndroid Build Coastguard Worker     if (!success) {
81*c8dee2aaSAndroid Build Coastguard Worker         return;
82*c8dee2aaSAndroid Build Coastguard Worker     }
83*c8dee2aaSAndroid Build Coastguard Worker 
84*c8dee2aaSAndroid Build Coastguard Worker     SkDynamicMemoryWStream dst0, dst1, dst2, dst3;
85*c8dee2aaSAndroid Build Coastguard Worker     success = encode(format, &dst0, src);
86*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(r, success);
87*c8dee2aaSAndroid Build Coastguard Worker 
88*c8dee2aaSAndroid Build Coastguard Worker     auto encoder1 = make(format, &dst1, src);
89*c8dee2aaSAndroid Build Coastguard Worker     for (int i = 0; i < src.height(); i++) {
90*c8dee2aaSAndroid Build Coastguard Worker         success = encoder1->encodeRows(1);
91*c8dee2aaSAndroid Build Coastguard Worker         REPORTER_ASSERT(r, success);
92*c8dee2aaSAndroid Build Coastguard Worker     }
93*c8dee2aaSAndroid Build Coastguard Worker 
94*c8dee2aaSAndroid Build Coastguard Worker     auto encoder2 = make(format, &dst2, src);
95*c8dee2aaSAndroid Build Coastguard Worker     for (int i = 0; i < src.height(); i+=3) {
96*c8dee2aaSAndroid Build Coastguard Worker         success = encoder2->encodeRows(3);
97*c8dee2aaSAndroid Build Coastguard Worker         REPORTER_ASSERT(r, success);
98*c8dee2aaSAndroid Build Coastguard Worker     }
99*c8dee2aaSAndroid Build Coastguard Worker 
100*c8dee2aaSAndroid Build Coastguard Worker     auto encoder3 = make(format, &dst3, src);
101*c8dee2aaSAndroid Build Coastguard Worker     success = encoder3->encodeRows(200);
102*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(r, success);
103*c8dee2aaSAndroid Build Coastguard Worker 
104*c8dee2aaSAndroid Build Coastguard Worker     sk_sp<SkData> data0 = dst0.detachAsData();
105*c8dee2aaSAndroid Build Coastguard Worker     sk_sp<SkData> data1 = dst1.detachAsData();
106*c8dee2aaSAndroid Build Coastguard Worker     sk_sp<SkData> data2 = dst2.detachAsData();
107*c8dee2aaSAndroid Build Coastguard Worker     sk_sp<SkData> data3 = dst3.detachAsData();
108*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(r, data0->equals(data1.get()));
109*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(r, data0->equals(data2.get()));
110*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(r, data0->equals(data3.get()));
111*c8dee2aaSAndroid Build Coastguard Worker }
112*c8dee2aaSAndroid Build Coastguard Worker 
DEF_TEST(Encode,r)113*c8dee2aaSAndroid Build Coastguard Worker DEF_TEST(Encode, r) {
114*c8dee2aaSAndroid Build Coastguard Worker     test_encode(r, SkEncodedImageFormat::kJPEG);
115*c8dee2aaSAndroid Build Coastguard Worker     test_encode(r, SkEncodedImageFormat::kPNG);
116*c8dee2aaSAndroid Build Coastguard Worker }
117*c8dee2aaSAndroid Build Coastguard Worker 
almost_equals(SkPMColor a,SkPMColor b,int tolerance)118*c8dee2aaSAndroid Build Coastguard Worker static inline bool almost_equals(SkPMColor a, SkPMColor b, int tolerance) {
119*c8dee2aaSAndroid Build Coastguard Worker     if (SkTAbs((int)SkGetPackedR32(a) - (int)SkGetPackedR32(b)) > tolerance) {
120*c8dee2aaSAndroid Build Coastguard Worker         return false;
121*c8dee2aaSAndroid Build Coastguard Worker     }
122*c8dee2aaSAndroid Build Coastguard Worker 
123*c8dee2aaSAndroid Build Coastguard Worker     if (SkTAbs((int)SkGetPackedG32(a) - (int)SkGetPackedG32(b)) > tolerance) {
124*c8dee2aaSAndroid Build Coastguard Worker         return false;
125*c8dee2aaSAndroid Build Coastguard Worker     }
126*c8dee2aaSAndroid Build Coastguard Worker 
127*c8dee2aaSAndroid Build Coastguard Worker     if (SkTAbs((int)SkGetPackedB32(a) - (int)SkGetPackedB32(b)) > tolerance) {
128*c8dee2aaSAndroid Build Coastguard Worker         return false;
129*c8dee2aaSAndroid Build Coastguard Worker     }
130*c8dee2aaSAndroid Build Coastguard Worker 
131*c8dee2aaSAndroid Build Coastguard Worker     if (SkTAbs((int)SkGetPackedA32(a) - (int)SkGetPackedA32(b)) > tolerance) {
132*c8dee2aaSAndroid Build Coastguard Worker         return false;
133*c8dee2aaSAndroid Build Coastguard Worker     }
134*c8dee2aaSAndroid Build Coastguard Worker 
135*c8dee2aaSAndroid Build Coastguard Worker     return true;
136*c8dee2aaSAndroid Build Coastguard Worker }
137*c8dee2aaSAndroid Build Coastguard Worker 
almost_equals(const SkBitmap & a,const SkBitmap & b,int tolerance)138*c8dee2aaSAndroid Build Coastguard Worker static inline bool almost_equals(const SkBitmap& a, const SkBitmap& b, int tolerance) {
139*c8dee2aaSAndroid Build Coastguard Worker     if (a.info() != b.info()) {
140*c8dee2aaSAndroid Build Coastguard Worker         return false;
141*c8dee2aaSAndroid Build Coastguard Worker     }
142*c8dee2aaSAndroid Build Coastguard Worker 
143*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(kN32_SkColorType == a.colorType());
144*c8dee2aaSAndroid Build Coastguard Worker     for (int y = 0; y < a.height(); y++) {
145*c8dee2aaSAndroid Build Coastguard Worker         for (int x = 0; x < a.width(); x++) {
146*c8dee2aaSAndroid Build Coastguard Worker             if (!almost_equals(*a.getAddr32(x, y), *b.getAddr32(x, y), tolerance)) {
147*c8dee2aaSAndroid Build Coastguard Worker                 return false;
148*c8dee2aaSAndroid Build Coastguard Worker             }
149*c8dee2aaSAndroid Build Coastguard Worker         }
150*c8dee2aaSAndroid Build Coastguard Worker     }
151*c8dee2aaSAndroid Build Coastguard Worker 
152*c8dee2aaSAndroid Build Coastguard Worker     return true;
153*c8dee2aaSAndroid Build Coastguard Worker }
154*c8dee2aaSAndroid Build Coastguard Worker 
test_png_encoding_roundtrip_from_specific_source_format(skiatest::Reporter * r,SkColorType colorType,SkAlphaType alphaType,int tolerance)155*c8dee2aaSAndroid Build Coastguard Worker void test_png_encoding_roundtrip_from_specific_source_format(skiatest::Reporter* r,
156*c8dee2aaSAndroid Build Coastguard Worker                                                              SkColorType colorType,
157*c8dee2aaSAndroid Build Coastguard Worker                                                              SkAlphaType alphaType,
158*c8dee2aaSAndroid Build Coastguard Worker                                                              int tolerance) {
159*c8dee2aaSAndroid Build Coastguard Worker     ///////////////////////////////////////////////////
160*c8dee2aaSAndroid Build Coastguard Worker     // Decode the test image into `originalBitmapRgba8`
161*c8dee2aaSAndroid Build Coastguard Worker     // (RGBA8, as the name implies).
162*c8dee2aaSAndroid Build Coastguard Worker     SkBitmap originalBitmapRgba8;
163*c8dee2aaSAndroid Build Coastguard Worker     {
164*c8dee2aaSAndroid Build Coastguard Worker         const char* resource = (kOpaque_SkAlphaType == alphaType) ? "images/color_wheel.jpg"
165*c8dee2aaSAndroid Build Coastguard Worker                                                                   : "images/color_wheel.png";
166*c8dee2aaSAndroid Build Coastguard Worker         sk_sp<SkData> data = GetResourceAsData(resource);
167*c8dee2aaSAndroid Build Coastguard Worker         if (!data) {
168*c8dee2aaSAndroid Build Coastguard Worker             return;
169*c8dee2aaSAndroid Build Coastguard Worker         }
170*c8dee2aaSAndroid Build Coastguard Worker         std::unique_ptr<SkCodec> codec = SkCodec::MakeFromData(data);
171*c8dee2aaSAndroid Build Coastguard Worker         REPORTER_ASSERT(r, !!codec);
172*c8dee2aaSAndroid Build Coastguard Worker         if (!codec) {
173*c8dee2aaSAndroid Build Coastguard Worker             return;
174*c8dee2aaSAndroid Build Coastguard Worker         }
175*c8dee2aaSAndroid Build Coastguard Worker         SkImageInfo dstInfo = codec->getInfo().makeColorType(kRGBA_8888_SkColorType);
176*c8dee2aaSAndroid Build Coastguard Worker         originalBitmapRgba8.allocPixels(dstInfo);
177*c8dee2aaSAndroid Build Coastguard Worker         SkCodec::Result result = codec->getPixels(
178*c8dee2aaSAndroid Build Coastguard Worker                 dstInfo, originalBitmapRgba8.getPixels(), originalBitmapRgba8.rowBytes());
179*c8dee2aaSAndroid Build Coastguard Worker         REPORTER_ASSERT(r,
180*c8dee2aaSAndroid Build Coastguard Worker                         result == SkCodec::kSuccess,
181*c8dee2aaSAndroid Build Coastguard Worker                         "result=%s, color=%d, alpha=%d",
182*c8dee2aaSAndroid Build Coastguard Worker                         SkCodec::ResultToString(result),
183*c8dee2aaSAndroid Build Coastguard Worker                         static_cast<int>(colorType),
184*c8dee2aaSAndroid Build Coastguard Worker                         static_cast<int>(alphaType));
185*c8dee2aaSAndroid Build Coastguard Worker         if (result != SkCodec::kSuccess) {
186*c8dee2aaSAndroid Build Coastguard Worker             return;
187*c8dee2aaSAndroid Build Coastguard Worker         }
188*c8dee2aaSAndroid Build Coastguard Worker     }
189*c8dee2aaSAndroid Build Coastguard Worker 
190*c8dee2aaSAndroid Build Coastguard Worker     //////////////////////////////////////////////////////////////////
191*c8dee2aaSAndroid Build Coastguard Worker     // Transform `originalBitmapRgba8` into `originalBitmap` (into the
192*c8dee2aaSAndroid Build Coastguard Worker     // `colorType` / `alphaType` that this test cares about).
193*c8dee2aaSAndroid Build Coastguard Worker     SkBitmap originalBitmap;
194*c8dee2aaSAndroid Build Coastguard Worker     {
195*c8dee2aaSAndroid Build Coastguard Worker         SkImageInfo dstInfo =
196*c8dee2aaSAndroid Build Coastguard Worker                 originalBitmapRgba8.info().makeColorType(colorType).makeAlphaType(alphaType);
197*c8dee2aaSAndroid Build Coastguard Worker         originalBitmap.allocPixels(dstInfo);
198*c8dee2aaSAndroid Build Coastguard Worker 
199*c8dee2aaSAndroid Build Coastguard Worker         skcms_PixelFormat dstFormat;
200*c8dee2aaSAndroid Build Coastguard Worker         switch (colorType) {
201*c8dee2aaSAndroid Build Coastguard Worker             case kRGBA_8888_SkColorType:
202*c8dee2aaSAndroid Build Coastguard Worker                 dstFormat = skcms_PixelFormat_RGBA_8888;
203*c8dee2aaSAndroid Build Coastguard Worker                 break;
204*c8dee2aaSAndroid Build Coastguard Worker             case kBGRA_8888_SkColorType:
205*c8dee2aaSAndroid Build Coastguard Worker                 dstFormat = skcms_PixelFormat_BGRA_8888;
206*c8dee2aaSAndroid Build Coastguard Worker                 break;
207*c8dee2aaSAndroid Build Coastguard Worker             case kRGBA_F16_SkColorType:
208*c8dee2aaSAndroid Build Coastguard Worker                 dstFormat = skcms_PixelFormat_RGBA_hhhh;
209*c8dee2aaSAndroid Build Coastguard Worker                 break;
210*c8dee2aaSAndroid Build Coastguard Worker             case kRGBA_F32_SkColorType:
211*c8dee2aaSAndroid Build Coastguard Worker                 dstFormat = skcms_PixelFormat_RGBA_ffff;
212*c8dee2aaSAndroid Build Coastguard Worker                 break;
213*c8dee2aaSAndroid Build Coastguard Worker             default:
214*c8dee2aaSAndroid Build Coastguard Worker                 SkUNREACHABLE;
215*c8dee2aaSAndroid Build Coastguard Worker         }
216*c8dee2aaSAndroid Build Coastguard Worker 
217*c8dee2aaSAndroid Build Coastguard Worker         auto to_skcms_alpha = [](SkAlphaType alpha) -> skcms_AlphaFormat {
218*c8dee2aaSAndroid Build Coastguard Worker             switch (alpha) {
219*c8dee2aaSAndroid Build Coastguard Worker                 case kOpaque_SkAlphaType:
220*c8dee2aaSAndroid Build Coastguard Worker                     return skcms_AlphaFormat_Opaque;
221*c8dee2aaSAndroid Build Coastguard Worker                 case kPremul_SkAlphaType:
222*c8dee2aaSAndroid Build Coastguard Worker                     return skcms_AlphaFormat_PremulAsEncoded;
223*c8dee2aaSAndroid Build Coastguard Worker                 case kUnpremul_SkAlphaType:
224*c8dee2aaSAndroid Build Coastguard Worker                     return skcms_AlphaFormat_Unpremul;
225*c8dee2aaSAndroid Build Coastguard Worker                     break;
226*c8dee2aaSAndroid Build Coastguard Worker                 case kUnknown_SkAlphaType:
227*c8dee2aaSAndroid Build Coastguard Worker                     SkUNREACHABLE;
228*c8dee2aaSAndroid Build Coastguard Worker             }
229*c8dee2aaSAndroid Build Coastguard Worker             SkUNREACHABLE;
230*c8dee2aaSAndroid Build Coastguard Worker         };
231*c8dee2aaSAndroid Build Coastguard Worker         skcms_AlphaFormat srcAlpha = to_skcms_alpha(originalBitmapRgba8.alphaType());
232*c8dee2aaSAndroid Build Coastguard Worker         skcms_AlphaFormat dstAlpha = to_skcms_alpha(alphaType);
233*c8dee2aaSAndroid Build Coastguard Worker 
234*c8dee2aaSAndroid Build Coastguard Worker         size_t npixels = originalBitmapRgba8.width() * originalBitmapRgba8.height();
235*c8dee2aaSAndroid Build Coastguard Worker         bool success = skcms_Transform(originalBitmapRgba8.getAddr(0, 0),
236*c8dee2aaSAndroid Build Coastguard Worker                                        skcms_PixelFormat_RGBA_8888,
237*c8dee2aaSAndroid Build Coastguard Worker                                        srcAlpha,
238*c8dee2aaSAndroid Build Coastguard Worker                                        nullptr,
239*c8dee2aaSAndroid Build Coastguard Worker                                        originalBitmap.getAddr(0, 0),
240*c8dee2aaSAndroid Build Coastguard Worker                                        dstFormat,
241*c8dee2aaSAndroid Build Coastguard Worker                                        dstAlpha,
242*c8dee2aaSAndroid Build Coastguard Worker                                        nullptr,
243*c8dee2aaSAndroid Build Coastguard Worker                                        npixels);
244*c8dee2aaSAndroid Build Coastguard Worker         REPORTER_ASSERT(r, success);
245*c8dee2aaSAndroid Build Coastguard Worker         if (!success) {
246*c8dee2aaSAndroid Build Coastguard Worker             return;
247*c8dee2aaSAndroid Build Coastguard Worker         }
248*c8dee2aaSAndroid Build Coastguard Worker     }
249*c8dee2aaSAndroid Build Coastguard Worker 
250*c8dee2aaSAndroid Build Coastguard Worker     /////////////////////////////////////////////
251*c8dee2aaSAndroid Build Coastguard Worker     // Encode `originalBitmap` into `encodedPng`.
252*c8dee2aaSAndroid Build Coastguard Worker     sk_sp<SkData> encodedPng;
253*c8dee2aaSAndroid Build Coastguard Worker     {
254*c8dee2aaSAndroid Build Coastguard Worker         SkPixmap src;
255*c8dee2aaSAndroid Build Coastguard Worker         bool success = originalBitmap.peekPixels(&src);
256*c8dee2aaSAndroid Build Coastguard Worker         REPORTER_ASSERT(r, success);
257*c8dee2aaSAndroid Build Coastguard Worker         if (!success) {
258*c8dee2aaSAndroid Build Coastguard Worker             return;
259*c8dee2aaSAndroid Build Coastguard Worker         }
260*c8dee2aaSAndroid Build Coastguard Worker         SkDynamicMemoryWStream buf;
261*c8dee2aaSAndroid Build Coastguard Worker         success = SkPngEncoder::Encode(&buf, src, SkPngEncoder::Options());
262*c8dee2aaSAndroid Build Coastguard Worker         REPORTER_ASSERT(r, success);
263*c8dee2aaSAndroid Build Coastguard Worker         if (!success) {
264*c8dee2aaSAndroid Build Coastguard Worker             return;
265*c8dee2aaSAndroid Build Coastguard Worker         }
266*c8dee2aaSAndroid Build Coastguard Worker         encodedPng = buf.detachAsData();
267*c8dee2aaSAndroid Build Coastguard Worker     }
268*c8dee2aaSAndroid Build Coastguard Worker 
269*c8dee2aaSAndroid Build Coastguard Worker     /////////////////////////////////////////////////////
270*c8dee2aaSAndroid Build Coastguard Worker     // Decode `encodedPng` into `roundtripBitmap` (RGBA8).
271*c8dee2aaSAndroid Build Coastguard Worker     SkBitmap roundtripBitmap;
272*c8dee2aaSAndroid Build Coastguard Worker     {
273*c8dee2aaSAndroid Build Coastguard Worker         std::unique_ptr<SkCodec> codec = SkCodec::MakeFromData(encodedPng);
274*c8dee2aaSAndroid Build Coastguard Worker         REPORTER_ASSERT(r, !!codec);
275*c8dee2aaSAndroid Build Coastguard Worker         if (!codec) {
276*c8dee2aaSAndroid Build Coastguard Worker             return;
277*c8dee2aaSAndroid Build Coastguard Worker         }
278*c8dee2aaSAndroid Build Coastguard Worker         SkImageInfo dstInfo = codec->getInfo().makeColorType(kRGBA_8888_SkColorType);
279*c8dee2aaSAndroid Build Coastguard Worker         roundtripBitmap.allocPixels(dstInfo);
280*c8dee2aaSAndroid Build Coastguard Worker         SkCodec::Result result =
281*c8dee2aaSAndroid Build Coastguard Worker                 codec->getPixels(dstInfo, roundtripBitmap.getPixels(), roundtripBitmap.rowBytes());
282*c8dee2aaSAndroid Build Coastguard Worker         REPORTER_ASSERT(r,
283*c8dee2aaSAndroid Build Coastguard Worker                         result == SkCodec::kSuccess,
284*c8dee2aaSAndroid Build Coastguard Worker                         "result=%s, color=%d, alpha=%d",
285*c8dee2aaSAndroid Build Coastguard Worker                         SkCodec::ResultToString(result),
286*c8dee2aaSAndroid Build Coastguard Worker                         static_cast<int>(colorType),
287*c8dee2aaSAndroid Build Coastguard Worker                         static_cast<int>(alphaType));
288*c8dee2aaSAndroid Build Coastguard Worker         if (result != SkCodec::kSuccess) {
289*c8dee2aaSAndroid Build Coastguard Worker             return;
290*c8dee2aaSAndroid Build Coastguard Worker         }
291*c8dee2aaSAndroid Build Coastguard Worker     }
292*c8dee2aaSAndroid Build Coastguard Worker 
293*c8dee2aaSAndroid Build Coastguard Worker     //////////////////////////////////////////////////////////////////////////
294*c8dee2aaSAndroid Build Coastguard Worker     // Ensure that `originalBitmap` into `roundtripBitmap` are (almost) equal.
295*c8dee2aaSAndroid Build Coastguard Worker     // (We can't use the `almost_equals` overload which operates on `SkBitmap`s,
296*c8dee2aaSAndroid Build Coastguard Worker     // because our bitmaps may expectedly have differente alpha types.)
297*c8dee2aaSAndroid Build Coastguard Worker     if (originalBitmapRgba8.dimensions() != roundtripBitmap.dimensions()) {
298*c8dee2aaSAndroid Build Coastguard Worker         REPORTER_ASSERT(r, false);
299*c8dee2aaSAndroid Build Coastguard Worker         return;
300*c8dee2aaSAndroid Build Coastguard Worker     }
301*c8dee2aaSAndroid Build Coastguard Worker     for (int y = 0; y < originalBitmap.height(); y++) {
302*c8dee2aaSAndroid Build Coastguard Worker         for (int x = 0; x < originalBitmap.width(); x++) {
303*c8dee2aaSAndroid Build Coastguard Worker             SkColor originalColor = originalBitmap.getColor(x, y);
304*c8dee2aaSAndroid Build Coastguard Worker             SkColor roundtripColor = roundtripBitmap.getColor(x, y);
305*c8dee2aaSAndroid Build Coastguard Worker             SkPMColor originalPremulColor = SkPreMultiplyColor(originalColor);
306*c8dee2aaSAndroid Build Coastguard Worker             SkPMColor roundtripPremulColor = SkPreMultiplyColor(roundtripColor);
307*c8dee2aaSAndroid Build Coastguard Worker             bool almost_same = almost_equals(originalPremulColor, roundtripPremulColor, tolerance);
308*c8dee2aaSAndroid Build Coastguard Worker             REPORTER_ASSERT(r,
309*c8dee2aaSAndroid Build Coastguard Worker                             almost_same,
310*c8dee2aaSAndroid Build Coastguard Worker                             "x=%d, y=%d, original=0x%08x, roundtrip=0x%08x, color=%d, alpha=%d",
311*c8dee2aaSAndroid Build Coastguard Worker                             x,
312*c8dee2aaSAndroid Build Coastguard Worker                             y,
313*c8dee2aaSAndroid Build Coastguard Worker                             originalPremulColor,
314*c8dee2aaSAndroid Build Coastguard Worker                             roundtripPremulColor,
315*c8dee2aaSAndroid Build Coastguard Worker                             static_cast<int>(colorType),
316*c8dee2aaSAndroid Build Coastguard Worker                             static_cast<int>(alphaType));
317*c8dee2aaSAndroid Build Coastguard Worker             if (!almost_same) {
318*c8dee2aaSAndroid Build Coastguard Worker                 return;
319*c8dee2aaSAndroid Build Coastguard Worker             }
320*c8dee2aaSAndroid Build Coastguard Worker         }
321*c8dee2aaSAndroid Build Coastguard Worker     }
322*c8dee2aaSAndroid Build Coastguard Worker }
323*c8dee2aaSAndroid Build Coastguard Worker 
DEF_TEST(Encode_png_roundtrip_for_different_source_formats,r)324*c8dee2aaSAndroid Build Coastguard Worker DEF_TEST(Encode_png_roundtrip_for_different_source_formats, r) {
325*c8dee2aaSAndroid Build Coastguard Worker     test_png_encoding_roundtrip_from_specific_source_format(
326*c8dee2aaSAndroid Build Coastguard Worker             r, kN32_SkColorType, kOpaque_SkAlphaType, 0);
327*c8dee2aaSAndroid Build Coastguard Worker     test_png_encoding_roundtrip_from_specific_source_format(
328*c8dee2aaSAndroid Build Coastguard Worker             r, kN32_SkColorType, kUnpremul_SkAlphaType, 0);
329*c8dee2aaSAndroid Build Coastguard Worker     test_png_encoding_roundtrip_from_specific_source_format(
330*c8dee2aaSAndroid Build Coastguard Worker             r, kN32_SkColorType, kPremul_SkAlphaType, 0);
331*c8dee2aaSAndroid Build Coastguard Worker 
332*c8dee2aaSAndroid Build Coastguard Worker     // PNG encoder used to narrow down `kRGBA_F16_SkColorType` from RGBA to RGB
333*c8dee2aaSAndroid Build Coastguard Worker     // (BE16) by skipping the alpha channel via `png_set_filler`.  But this
334*c8dee2aaSAndroid Build Coastguard Worker     // wasn't done quite right for `kRGBA_F32_SkColorType`, which motivated this
335*c8dee2aaSAndroid Build Coastguard Worker     // test.  See the code review comments of http://review.skia.org/922676 for
336*c8dee2aaSAndroid Build Coastguard Worker     // more details.
337*c8dee2aaSAndroid Build Coastguard Worker     test_png_encoding_roundtrip_from_specific_source_format(
338*c8dee2aaSAndroid Build Coastguard Worker             r, kRGBA_F16_SkColorType, kOpaque_SkAlphaType, 0);
339*c8dee2aaSAndroid Build Coastguard Worker     test_png_encoding_roundtrip_from_specific_source_format(
340*c8dee2aaSAndroid Build Coastguard Worker             r, kRGBA_F32_SkColorType, kOpaque_SkAlphaType, 0);
341*c8dee2aaSAndroid Build Coastguard Worker }
342*c8dee2aaSAndroid Build Coastguard Worker 
DEF_TEST(Encode_JPG,r)343*c8dee2aaSAndroid Build Coastguard Worker DEF_TEST(Encode_JPG, r) {
344*c8dee2aaSAndroid Build Coastguard Worker     auto image = ToolUtils::GetResourceAsImage("images/mandrill_128.png");
345*c8dee2aaSAndroid Build Coastguard Worker     if (!image) {
346*c8dee2aaSAndroid Build Coastguard Worker         return;
347*c8dee2aaSAndroid Build Coastguard Worker     }
348*c8dee2aaSAndroid Build Coastguard Worker 
349*c8dee2aaSAndroid Build Coastguard Worker     for (auto ct : { kRGBA_8888_SkColorType,
350*c8dee2aaSAndroid Build Coastguard Worker                      kBGRA_8888_SkColorType,
351*c8dee2aaSAndroid Build Coastguard Worker                      kRGB_565_SkColorType,
352*c8dee2aaSAndroid Build Coastguard Worker                      kARGB_4444_SkColorType,
353*c8dee2aaSAndroid Build Coastguard Worker                      kGray_8_SkColorType,
354*c8dee2aaSAndroid Build Coastguard Worker                      kRGBA_F16_SkColorType }) {
355*c8dee2aaSAndroid Build Coastguard Worker         for (auto at : { kPremul_SkAlphaType, kUnpremul_SkAlphaType, kOpaque_SkAlphaType }) {
356*c8dee2aaSAndroid Build Coastguard Worker             auto info = SkImageInfo::Make(image->width(), image->height(), ct, at);
357*c8dee2aaSAndroid Build Coastguard Worker             auto surface = SkSurfaces::Raster(info);
358*c8dee2aaSAndroid Build Coastguard Worker             auto canvas = surface->getCanvas();
359*c8dee2aaSAndroid Build Coastguard Worker             canvas->drawImage(image, 0, 0);
360*c8dee2aaSAndroid Build Coastguard Worker 
361*c8dee2aaSAndroid Build Coastguard Worker             SkBitmap bm;
362*c8dee2aaSAndroid Build Coastguard Worker             bm.allocPixels(info);
363*c8dee2aaSAndroid Build Coastguard Worker             if (!surface->makeImageSnapshot()->readPixels(nullptr, bm.pixmap(), 0, 0)) {
364*c8dee2aaSAndroid Build Coastguard Worker                 ERRORF(r, "failed to readPixels! ct: %i\tat: %i\n", ct, at);
365*c8dee2aaSAndroid Build Coastguard Worker                 continue;
366*c8dee2aaSAndroid Build Coastguard Worker             }
367*c8dee2aaSAndroid Build Coastguard Worker             for (auto alphaOption : { SkJpegEncoder::AlphaOption::kIgnore,
368*c8dee2aaSAndroid Build Coastguard Worker                                       SkJpegEncoder::AlphaOption::kBlendOnBlack }) {
369*c8dee2aaSAndroid Build Coastguard Worker                 SkJpegEncoder::Options opts;
370*c8dee2aaSAndroid Build Coastguard Worker                 opts.fAlphaOption = alphaOption;
371*c8dee2aaSAndroid Build Coastguard Worker                 SkNullWStream ignored;
372*c8dee2aaSAndroid Build Coastguard Worker                 if (!SkJpegEncoder::Encode(&ignored, bm.pixmap(), opts)) {
373*c8dee2aaSAndroid Build Coastguard Worker                     REPORTER_ASSERT(r, ct == kARGB_4444_SkColorType
374*c8dee2aaSAndroid Build Coastguard Worker                                     && alphaOption == SkJpegEncoder::AlphaOption::kBlendOnBlack);
375*c8dee2aaSAndroid Build Coastguard Worker                 }
376*c8dee2aaSAndroid Build Coastguard Worker             }
377*c8dee2aaSAndroid Build Coastguard Worker         }
378*c8dee2aaSAndroid Build Coastguard Worker     }
379*c8dee2aaSAndroid Build Coastguard Worker }
380*c8dee2aaSAndroid Build Coastguard Worker 
DEF_TEST(Encode_JpegDownsample,r)381*c8dee2aaSAndroid Build Coastguard Worker DEF_TEST(Encode_JpegDownsample, r) {
382*c8dee2aaSAndroid Build Coastguard Worker     SkBitmap bitmap;
383*c8dee2aaSAndroid Build Coastguard Worker     bool success = ToolUtils::GetResourceAsBitmap("images/mandrill_128.png", &bitmap);
384*c8dee2aaSAndroid Build Coastguard Worker     if (!success) {
385*c8dee2aaSAndroid Build Coastguard Worker         return;
386*c8dee2aaSAndroid Build Coastguard Worker     }
387*c8dee2aaSAndroid Build Coastguard Worker 
388*c8dee2aaSAndroid Build Coastguard Worker     SkPixmap src;
389*c8dee2aaSAndroid Build Coastguard Worker     success = bitmap.peekPixels(&src);
390*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(r, success);
391*c8dee2aaSAndroid Build Coastguard Worker     if (!success) {
392*c8dee2aaSAndroid Build Coastguard Worker         return;
393*c8dee2aaSAndroid Build Coastguard Worker     }
394*c8dee2aaSAndroid Build Coastguard Worker 
395*c8dee2aaSAndroid Build Coastguard Worker     SkDynamicMemoryWStream dst0, dst1, dst2;
396*c8dee2aaSAndroid Build Coastguard Worker     SkJpegEncoder::Options options;
397*c8dee2aaSAndroid Build Coastguard Worker     success = SkJpegEncoder::Encode(&dst0, src, options);
398*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(r, success);
399*c8dee2aaSAndroid Build Coastguard Worker 
400*c8dee2aaSAndroid Build Coastguard Worker     options.fDownsample = SkJpegEncoder::Downsample::k422;
401*c8dee2aaSAndroid Build Coastguard Worker     success = SkJpegEncoder::Encode(&dst1, src, options);
402*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(r, success);
403*c8dee2aaSAndroid Build Coastguard Worker 
404*c8dee2aaSAndroid Build Coastguard Worker     options.fDownsample = SkJpegEncoder::Downsample::k444;
405*c8dee2aaSAndroid Build Coastguard Worker     success = SkJpegEncoder::Encode(&dst2, src, options);
406*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(r, success);
407*c8dee2aaSAndroid Build Coastguard Worker 
408*c8dee2aaSAndroid Build Coastguard Worker     sk_sp<SkData> data0 = dst0.detachAsData();
409*c8dee2aaSAndroid Build Coastguard Worker     sk_sp<SkData> data1 = dst1.detachAsData();
410*c8dee2aaSAndroid Build Coastguard Worker     sk_sp<SkData> data2 = dst2.detachAsData();
411*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(r, data0->size() < data1->size());
412*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(r, data1->size() < data2->size());
413*c8dee2aaSAndroid Build Coastguard Worker 
414*c8dee2aaSAndroid Build Coastguard Worker     SkBitmap bm0, bm1, bm2;
415*c8dee2aaSAndroid Build Coastguard Worker     SkImages::DeferredFromEncodedData(data0)->asLegacyBitmap(&bm0);
416*c8dee2aaSAndroid Build Coastguard Worker     SkImages::DeferredFromEncodedData(data1)->asLegacyBitmap(&bm1);
417*c8dee2aaSAndroid Build Coastguard Worker     SkImages::DeferredFromEncodedData(data2)->asLegacyBitmap(&bm2);
418*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(r, almost_equals(bm0, bm1, 60));
419*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(r, almost_equals(bm1, bm2, 60));
420*c8dee2aaSAndroid Build Coastguard Worker }
421*c8dee2aaSAndroid Build Coastguard Worker 
pushComment(std::vector<std::string> & comments,const char * keyword,const char * text)422*c8dee2aaSAndroid Build Coastguard Worker static inline void pushComment(
423*c8dee2aaSAndroid Build Coastguard Worker         std::vector<std::string>& comments, const char* keyword, const char* text) {
424*c8dee2aaSAndroid Build Coastguard Worker     comments.push_back(keyword);
425*c8dee2aaSAndroid Build Coastguard Worker     comments.push_back(text);
426*c8dee2aaSAndroid Build Coastguard Worker }
427*c8dee2aaSAndroid Build Coastguard Worker 
testPngComments(const SkPixmap & src,SkPngEncoder::Options & options,skiatest::Reporter * r)428*c8dee2aaSAndroid Build Coastguard Worker static void testPngComments(const SkPixmap& src, SkPngEncoder::Options& options,
429*c8dee2aaSAndroid Build Coastguard Worker         skiatest::Reporter* r) {
430*c8dee2aaSAndroid Build Coastguard Worker     std::vector<std::string> commentStrings;
431*c8dee2aaSAndroid Build Coastguard Worker     pushComment(commentStrings, "key", "text");
432*c8dee2aaSAndroid Build Coastguard Worker     pushComment(commentStrings, "test", "something");
433*c8dee2aaSAndroid Build Coastguard Worker     pushComment(commentStrings, "have some", "spaces in both");
434*c8dee2aaSAndroid Build Coastguard Worker 
435*c8dee2aaSAndroid Build Coastguard Worker     std::string longKey(PNG_KEYWORD_MAX_LENGTH, 'x');
436*c8dee2aaSAndroid Build Coastguard Worker #ifdef SK_DEBUG
437*c8dee2aaSAndroid Build Coastguard Worker     commentStrings.push_back(longKey);
438*c8dee2aaSAndroid Build Coastguard Worker #else
439*c8dee2aaSAndroid Build Coastguard Worker     // We call SkDEBUGFAILF it the key is too long so we'll only test this in release mode.
440*c8dee2aaSAndroid Build Coastguard Worker     commentStrings.push_back(longKey + "x");
441*c8dee2aaSAndroid Build Coastguard Worker #endif
442*c8dee2aaSAndroid Build Coastguard Worker     commentStrings.push_back("");
443*c8dee2aaSAndroid Build Coastguard Worker 
444*c8dee2aaSAndroid Build Coastguard Worker     std::vector<const char*> commentPointers;
445*c8dee2aaSAndroid Build Coastguard Worker     std::vector<size_t> commentSizes;
446*c8dee2aaSAndroid Build Coastguard Worker     for(auto& str : commentStrings) {
447*c8dee2aaSAndroid Build Coastguard Worker         commentPointers.push_back(str.c_str());
448*c8dee2aaSAndroid Build Coastguard Worker         commentSizes.push_back(str.length() + 1);
449*c8dee2aaSAndroid Build Coastguard Worker     }
450*c8dee2aaSAndroid Build Coastguard Worker 
451*c8dee2aaSAndroid Build Coastguard Worker     options.fComments = SkDataTable::MakeCopyArrays((void const *const *)commentPointers.data(),
452*c8dee2aaSAndroid Build Coastguard Worker             commentSizes.data(), commentStrings.size());
453*c8dee2aaSAndroid Build Coastguard Worker 
454*c8dee2aaSAndroid Build Coastguard Worker 
455*c8dee2aaSAndroid Build Coastguard Worker     SkDynamicMemoryWStream dst;
456*c8dee2aaSAndroid Build Coastguard Worker     bool success = SkPngEncoder::Encode(&dst, src, options);
457*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(r, success);
458*c8dee2aaSAndroid Build Coastguard Worker 
459*c8dee2aaSAndroid Build Coastguard Worker     std::vector<char> output(dst.bytesWritten());
460*c8dee2aaSAndroid Build Coastguard Worker     dst.copyTo(output.data());
461*c8dee2aaSAndroid Build Coastguard Worker 
462*c8dee2aaSAndroid Build Coastguard Worker     // Each chunk is of the form length (4 bytes), chunk type (tEXt), data,
463*c8dee2aaSAndroid Build Coastguard Worker     // checksum (4 bytes).  Make sure we find all of them in the encoded
464*c8dee2aaSAndroid Build Coastguard Worker     // results.
465*c8dee2aaSAndroid Build Coastguard Worker     const char kExpected1[] =
466*c8dee2aaSAndroid Build Coastguard Worker         "\x00\x00\x00\x08tEXtkey\x00text\x9e\xe7\x66\x51";
467*c8dee2aaSAndroid Build Coastguard Worker     const char kExpected2[] =
468*c8dee2aaSAndroid Build Coastguard Worker         "\x00\x00\x00\x0etEXttest\x00something\x29\xba\xef\xac";
469*c8dee2aaSAndroid Build Coastguard Worker     const char kExpected3[] =
470*c8dee2aaSAndroid Build Coastguard Worker         "\x00\x00\x00\x18tEXthave some\x00spaces in both\x8d\x69\x34\x2d";
471*c8dee2aaSAndroid Build Coastguard Worker     std::string longKeyRecord = "tEXt" + longKey; // A snippet of our long key comment
472*c8dee2aaSAndroid Build Coastguard Worker     std::string tooLongRecord = "tExt" + longKey + "x"; // A snippet whose key is too long
473*c8dee2aaSAndroid Build Coastguard Worker 
474*c8dee2aaSAndroid Build Coastguard Worker     auto search1 = std::search(output.begin(), output.end(),
475*c8dee2aaSAndroid Build Coastguard Worker             kExpected1, kExpected1 + sizeof(kExpected1));
476*c8dee2aaSAndroid Build Coastguard Worker     auto search2 = std::search(output.begin(), output.end(),
477*c8dee2aaSAndroid Build Coastguard Worker             kExpected2, kExpected2 + sizeof(kExpected2));
478*c8dee2aaSAndroid Build Coastguard Worker     auto search3 = std::search(output.begin(), output.end(),
479*c8dee2aaSAndroid Build Coastguard Worker             kExpected3, kExpected3 + sizeof(kExpected3));
480*c8dee2aaSAndroid Build Coastguard Worker     auto search4 = std::search(output.begin(), output.end(),
481*c8dee2aaSAndroid Build Coastguard Worker             longKeyRecord.begin(), longKeyRecord.end());
482*c8dee2aaSAndroid Build Coastguard Worker     auto search5 = std::search(output.begin(), output.end(),
483*c8dee2aaSAndroid Build Coastguard Worker             tooLongRecord.begin(), tooLongRecord.end());
484*c8dee2aaSAndroid Build Coastguard Worker 
485*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(r, search1 != output.end());
486*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(r, search2 != output.end());
487*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(r, search3 != output.end());
488*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(r, search4 != output.end());
489*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(r, search5 == output.end());
490*c8dee2aaSAndroid Build Coastguard Worker     // Comments test ends
491*c8dee2aaSAndroid Build Coastguard Worker }
492*c8dee2aaSAndroid Build Coastguard Worker 
DEF_TEST(Encode_PngOptions,r)493*c8dee2aaSAndroid Build Coastguard Worker DEF_TEST(Encode_PngOptions, r) {
494*c8dee2aaSAndroid Build Coastguard Worker     SkBitmap bitmap;
495*c8dee2aaSAndroid Build Coastguard Worker     bool success = ToolUtils::GetResourceAsBitmap("images/mandrill_128.png", &bitmap);
496*c8dee2aaSAndroid Build Coastguard Worker     if (!success) {
497*c8dee2aaSAndroid Build Coastguard Worker         return;
498*c8dee2aaSAndroid Build Coastguard Worker     }
499*c8dee2aaSAndroid Build Coastguard Worker 
500*c8dee2aaSAndroid Build Coastguard Worker     SkPixmap src;
501*c8dee2aaSAndroid Build Coastguard Worker     success = bitmap.peekPixels(&src);
502*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(r, success);
503*c8dee2aaSAndroid Build Coastguard Worker     if (!success) {
504*c8dee2aaSAndroid Build Coastguard Worker         return;
505*c8dee2aaSAndroid Build Coastguard Worker     }
506*c8dee2aaSAndroid Build Coastguard Worker 
507*c8dee2aaSAndroid Build Coastguard Worker     SkDynamicMemoryWStream dst0, dst1, dst2;
508*c8dee2aaSAndroid Build Coastguard Worker     SkPngEncoder::Options options;
509*c8dee2aaSAndroid Build Coastguard Worker     success = SkPngEncoder::Encode(&dst0, src, options);
510*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(r, success);
511*c8dee2aaSAndroid Build Coastguard Worker 
512*c8dee2aaSAndroid Build Coastguard Worker     options.fFilterFlags = SkPngEncoder::FilterFlag::kUp;
513*c8dee2aaSAndroid Build Coastguard Worker     success = SkPngEncoder::Encode(&dst1, src, options);
514*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(r, success);
515*c8dee2aaSAndroid Build Coastguard Worker 
516*c8dee2aaSAndroid Build Coastguard Worker     options.fZLibLevel = 3;
517*c8dee2aaSAndroid Build Coastguard Worker     success = SkPngEncoder::Encode(&dst2, src, options);
518*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(r, success);
519*c8dee2aaSAndroid Build Coastguard Worker 
520*c8dee2aaSAndroid Build Coastguard Worker     testPngComments(src, options, r);
521*c8dee2aaSAndroid Build Coastguard Worker 
522*c8dee2aaSAndroid Build Coastguard Worker     sk_sp<SkData> data0 = dst0.detachAsData();
523*c8dee2aaSAndroid Build Coastguard Worker     sk_sp<SkData> data1 = dst1.detachAsData();
524*c8dee2aaSAndroid Build Coastguard Worker     sk_sp<SkData> data2 = dst2.detachAsData();
525*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(r, data0->size() < data1->size());
526*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(r, data1->size() < data2->size());
527*c8dee2aaSAndroid Build Coastguard Worker 
528*c8dee2aaSAndroid Build Coastguard Worker     SkBitmap bm0, bm1, bm2;
529*c8dee2aaSAndroid Build Coastguard Worker     SkImages::DeferredFromEncodedData(data0)->asLegacyBitmap(&bm0);
530*c8dee2aaSAndroid Build Coastguard Worker     SkImages::DeferredFromEncodedData(data1)->asLegacyBitmap(&bm1);
531*c8dee2aaSAndroid Build Coastguard Worker     SkImages::DeferredFromEncodedData(data2)->asLegacyBitmap(&bm2);
532*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(r, almost_equals(bm0, bm1, 0));
533*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(r, almost_equals(bm0, bm2, 0));
534*c8dee2aaSAndroid Build Coastguard Worker }
535*c8dee2aaSAndroid Build Coastguard Worker 
536*c8dee2aaSAndroid Build Coastguard Worker #ifndef SK_BUILD_FOR_GOOGLE3
DEF_TEST(Encode_WebpQuality,r)537*c8dee2aaSAndroid Build Coastguard Worker DEF_TEST(Encode_WebpQuality, r) {
538*c8dee2aaSAndroid Build Coastguard Worker     SkBitmap bm;
539*c8dee2aaSAndroid Build Coastguard Worker     bm.allocN32Pixels(100, 100);
540*c8dee2aaSAndroid Build Coastguard Worker     bm.eraseColor(SK_ColorBLUE);
541*c8dee2aaSAndroid Build Coastguard Worker 
542*c8dee2aaSAndroid Build Coastguard Worker     SkWebpEncoder::Options opts;
543*c8dee2aaSAndroid Build Coastguard Worker     opts.fCompression = SkWebpEncoder::Compression::kLossless;
544*c8dee2aaSAndroid Build Coastguard Worker     SkDynamicMemoryWStream stream;
545*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT_RELEASE(SkWebpEncoder::Encode(&stream, bm.pixmap(), opts));
546*c8dee2aaSAndroid Build Coastguard Worker     auto dataLossLess = stream.detachAsData();
547*c8dee2aaSAndroid Build Coastguard Worker 
548*c8dee2aaSAndroid Build Coastguard Worker     opts.fCompression = SkWebpEncoder::Compression::kLossy;
549*c8dee2aaSAndroid Build Coastguard Worker     opts.fQuality = 99;
550*c8dee2aaSAndroid Build Coastguard Worker     stream.reset();
551*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT_RELEASE(SkWebpEncoder::Encode(&stream, bm.pixmap(), opts));
552*c8dee2aaSAndroid Build Coastguard Worker     auto dataLossy = stream.detachAsData();
553*c8dee2aaSAndroid Build Coastguard Worker 
554*c8dee2aaSAndroid Build Coastguard Worker     enum Format {
555*c8dee2aaSAndroid Build Coastguard Worker         kMixed    = 0,
556*c8dee2aaSAndroid Build Coastguard Worker         kLossy    = 1,
557*c8dee2aaSAndroid Build Coastguard Worker         kLossless = 2,
558*c8dee2aaSAndroid Build Coastguard Worker     };
559*c8dee2aaSAndroid Build Coastguard Worker 
560*c8dee2aaSAndroid Build Coastguard Worker     auto test = [&r](const sk_sp<SkData>& data, Format expected) {
561*c8dee2aaSAndroid Build Coastguard Worker         auto printFormat = [](int f) {
562*c8dee2aaSAndroid Build Coastguard Worker             switch (f) {
563*c8dee2aaSAndroid Build Coastguard Worker                 case kMixed:    return "mixed";
564*c8dee2aaSAndroid Build Coastguard Worker                 case kLossy:    return "lossy";
565*c8dee2aaSAndroid Build Coastguard Worker                 case kLossless: return "lossless";
566*c8dee2aaSAndroid Build Coastguard Worker                 default:        return "unknown";
567*c8dee2aaSAndroid Build Coastguard Worker             }
568*c8dee2aaSAndroid Build Coastguard Worker         };
569*c8dee2aaSAndroid Build Coastguard Worker 
570*c8dee2aaSAndroid Build Coastguard Worker         if (!data) {
571*c8dee2aaSAndroid Build Coastguard Worker             ERRORF(r, "Failed to encode. Expected %s", printFormat(expected));
572*c8dee2aaSAndroid Build Coastguard Worker             return;
573*c8dee2aaSAndroid Build Coastguard Worker         }
574*c8dee2aaSAndroid Build Coastguard Worker 
575*c8dee2aaSAndroid Build Coastguard Worker         WebPBitstreamFeatures features;
576*c8dee2aaSAndroid Build Coastguard Worker         auto status = WebPGetFeatures(data->bytes(), data->size(), &features);
577*c8dee2aaSAndroid Build Coastguard Worker         if (status != VP8_STATUS_OK) {
578*c8dee2aaSAndroid Build Coastguard Worker             ERRORF(r, "Encode had an error %i. Expected %s", status, printFormat(expected));
579*c8dee2aaSAndroid Build Coastguard Worker             return;
580*c8dee2aaSAndroid Build Coastguard Worker         }
581*c8dee2aaSAndroid Build Coastguard Worker 
582*c8dee2aaSAndroid Build Coastguard Worker         if (expected != features.format) {
583*c8dee2aaSAndroid Build Coastguard Worker             ERRORF(r, "Expected %s encode, but got format %s", printFormat(expected),
584*c8dee2aaSAndroid Build Coastguard Worker                                                                printFormat(features.format));
585*c8dee2aaSAndroid Build Coastguard Worker         }
586*c8dee2aaSAndroid Build Coastguard Worker     };
587*c8dee2aaSAndroid Build Coastguard Worker 
588*c8dee2aaSAndroid Build Coastguard Worker     test(dataLossy,    kLossy);
589*c8dee2aaSAndroid Build Coastguard Worker     test(dataLossLess, kLossless);
590*c8dee2aaSAndroid Build Coastguard Worker }
591*c8dee2aaSAndroid Build Coastguard Worker #endif
592*c8dee2aaSAndroid Build Coastguard Worker 
DEF_TEST(Encode_WebpOptions,r)593*c8dee2aaSAndroid Build Coastguard Worker DEF_TEST(Encode_WebpOptions, r) {
594*c8dee2aaSAndroid Build Coastguard Worker     SkBitmap bitmap;
595*c8dee2aaSAndroid Build Coastguard Worker     bool success = ToolUtils::GetResourceAsBitmap("images/google_chrome.ico", &bitmap);
596*c8dee2aaSAndroid Build Coastguard Worker     if (!success) {
597*c8dee2aaSAndroid Build Coastguard Worker         return;
598*c8dee2aaSAndroid Build Coastguard Worker     }
599*c8dee2aaSAndroid Build Coastguard Worker 
600*c8dee2aaSAndroid Build Coastguard Worker     SkPixmap src;
601*c8dee2aaSAndroid Build Coastguard Worker     success = bitmap.peekPixels(&src);
602*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(r, success);
603*c8dee2aaSAndroid Build Coastguard Worker     if (!success) {
604*c8dee2aaSAndroid Build Coastguard Worker         return;
605*c8dee2aaSAndroid Build Coastguard Worker     }
606*c8dee2aaSAndroid Build Coastguard Worker 
607*c8dee2aaSAndroid Build Coastguard Worker     SkDynamicMemoryWStream dst0, dst1, dst2, dst3;
608*c8dee2aaSAndroid Build Coastguard Worker     SkWebpEncoder::Options options;
609*c8dee2aaSAndroid Build Coastguard Worker     options.fCompression = SkWebpEncoder::Compression::kLossless;
610*c8dee2aaSAndroid Build Coastguard Worker     options.fQuality = 0.0f;
611*c8dee2aaSAndroid Build Coastguard Worker     success = SkWebpEncoder::Encode(&dst0, src, options);
612*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(r, success);
613*c8dee2aaSAndroid Build Coastguard Worker 
614*c8dee2aaSAndroid Build Coastguard Worker     options.fQuality = 100.0f;
615*c8dee2aaSAndroid Build Coastguard Worker     success = SkWebpEncoder::Encode(&dst1, src, options);
616*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(r, success);
617*c8dee2aaSAndroid Build Coastguard Worker 
618*c8dee2aaSAndroid Build Coastguard Worker     options.fCompression = SkWebpEncoder::Compression::kLossy;
619*c8dee2aaSAndroid Build Coastguard Worker     options.fQuality = 100.0f;
620*c8dee2aaSAndroid Build Coastguard Worker     success = SkWebpEncoder::Encode(&dst2, src, options);
621*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(r, success);
622*c8dee2aaSAndroid Build Coastguard Worker 
623*c8dee2aaSAndroid Build Coastguard Worker     options.fCompression = SkWebpEncoder::Compression::kLossy;
624*c8dee2aaSAndroid Build Coastguard Worker     options.fQuality = 50.0f;
625*c8dee2aaSAndroid Build Coastguard Worker     success = SkWebpEncoder::Encode(&dst3, src, options);
626*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(r, success);
627*c8dee2aaSAndroid Build Coastguard Worker 
628*c8dee2aaSAndroid Build Coastguard Worker     sk_sp<SkData> data0 = dst0.detachAsData();
629*c8dee2aaSAndroid Build Coastguard Worker     sk_sp<SkData> data1 = dst1.detachAsData();
630*c8dee2aaSAndroid Build Coastguard Worker     sk_sp<SkData> data2 = dst2.detachAsData();
631*c8dee2aaSAndroid Build Coastguard Worker     sk_sp<SkData> data3 = dst3.detachAsData();
632*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(r, data0->size() > data1->size());
633*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(r, data1->size() > data2->size());
634*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(r, data2->size() > data3->size());
635*c8dee2aaSAndroid Build Coastguard Worker 
636*c8dee2aaSAndroid Build Coastguard Worker     SkBitmap bm0, bm1, bm2, bm3;
637*c8dee2aaSAndroid Build Coastguard Worker     SkImages::DeferredFromEncodedData(data0)->asLegacyBitmap(&bm0);
638*c8dee2aaSAndroid Build Coastguard Worker     SkImages::DeferredFromEncodedData(data1)->asLegacyBitmap(&bm1);
639*c8dee2aaSAndroid Build Coastguard Worker     SkImages::DeferredFromEncodedData(data2)->asLegacyBitmap(&bm2);
640*c8dee2aaSAndroid Build Coastguard Worker     SkImages::DeferredFromEncodedData(data3)->asLegacyBitmap(&bm3);
641*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(r, almost_equals(bm0, bm1, 0));
642*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(r, almost_equals(bm0, bm2, 90));
643*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(r, almost_equals(bm2, bm3, 50));
644*c8dee2aaSAndroid Build Coastguard Worker }
645*c8dee2aaSAndroid Build Coastguard Worker 
DEF_TEST(Encode_WebpAnimated,r)646*c8dee2aaSAndroid Build Coastguard Worker DEF_TEST(Encode_WebpAnimated, r) {
647*c8dee2aaSAndroid Build Coastguard Worker     const int frameCount = 3;
648*c8dee2aaSAndroid Build Coastguard Worker     const int width = 16;
649*c8dee2aaSAndroid Build Coastguard Worker     const int height = 16;
650*c8dee2aaSAndroid Build Coastguard Worker     auto info = SkImageInfo::MakeN32Premul(width, height);
651*c8dee2aaSAndroid Build Coastguard Worker     std::vector<SkBitmap> bitmaps(frameCount);
652*c8dee2aaSAndroid Build Coastguard Worker     std::vector<SkEncoder::Frame> frames(frameCount);
653*c8dee2aaSAndroid Build Coastguard Worker     std::vector<int> durations = {50, 100, 150};
654*c8dee2aaSAndroid Build Coastguard Worker     std::vector<SkColor> colors = {SK_ColorRED, SK_ColorBLUE, SK_ColorGREEN};
655*c8dee2aaSAndroid Build Coastguard Worker 
656*c8dee2aaSAndroid Build Coastguard Worker     for (int i = 0; i < frameCount; i++) {
657*c8dee2aaSAndroid Build Coastguard Worker         bitmaps[i].allocPixels(info);
658*c8dee2aaSAndroid Build Coastguard Worker         bitmaps[i].eraseColor(colors[i]);
659*c8dee2aaSAndroid Build Coastguard Worker         REPORTER_ASSERT(r, bitmaps[i].peekPixels(&frames[i].pixmap));
660*c8dee2aaSAndroid Build Coastguard Worker         frames[i].duration = durations[i];
661*c8dee2aaSAndroid Build Coastguard Worker     }
662*c8dee2aaSAndroid Build Coastguard Worker 
663*c8dee2aaSAndroid Build Coastguard Worker     SkDynamicMemoryWStream stream;
664*c8dee2aaSAndroid Build Coastguard Worker     SkWebpEncoder::Options options;
665*c8dee2aaSAndroid Build Coastguard Worker     options.fCompression = SkWebpEncoder::Compression::kLossless;
666*c8dee2aaSAndroid Build Coastguard Worker     options.fQuality = 100;
667*c8dee2aaSAndroid Build Coastguard Worker 
668*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(r, SkWebpEncoder::EncodeAnimated(&stream, frames, options));
669*c8dee2aaSAndroid Build Coastguard Worker 
670*c8dee2aaSAndroid Build Coastguard Worker     auto codec = SkCodec::MakeFromData(stream.detachAsData());
671*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(r, !!codec);
672*c8dee2aaSAndroid Build Coastguard Worker 
673*c8dee2aaSAndroid Build Coastguard Worker     std::vector<SkCodec::FrameInfo> frameInfos = codec->getFrameInfo();
674*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(r, frameInfos.size() == frameCount);
675*c8dee2aaSAndroid Build Coastguard Worker 
676*c8dee2aaSAndroid Build Coastguard Worker     for (size_t i = 0; i < frameInfos.size(); ++i) {
677*c8dee2aaSAndroid Build Coastguard Worker         SkBitmap bitmap;
678*c8dee2aaSAndroid Build Coastguard Worker         bitmap.allocPixels(info);
679*c8dee2aaSAndroid Build Coastguard Worker         bitmap.eraseColor(0);
680*c8dee2aaSAndroid Build Coastguard Worker 
681*c8dee2aaSAndroid Build Coastguard Worker         SkCodec::Options codecOptions;
682*c8dee2aaSAndroid Build Coastguard Worker         codecOptions.fFrameIndex = (int)i;
683*c8dee2aaSAndroid Build Coastguard Worker 
684*c8dee2aaSAndroid Build Coastguard Worker         auto result = codec->getPixels(info, bitmap.getPixels(), bitmap.rowBytes(), &codecOptions);
685*c8dee2aaSAndroid Build Coastguard Worker         if (result != SkCodec::kSuccess) {
686*c8dee2aaSAndroid Build Coastguard Worker             ERRORF(r, "error in frame %zu: %s", i, SkCodec::ResultToString(result));
687*c8dee2aaSAndroid Build Coastguard Worker         }
688*c8dee2aaSAndroid Build Coastguard Worker 
689*c8dee2aaSAndroid Build Coastguard Worker         REPORTER_ASSERT(r, almost_equals(bitmap, bitmaps[i], 0));
690*c8dee2aaSAndroid Build Coastguard Worker         REPORTER_ASSERT(r, frameInfos[i].fDuration == durations[i]);
691*c8dee2aaSAndroid Build Coastguard Worker     }
692*c8dee2aaSAndroid Build Coastguard Worker }
693*c8dee2aaSAndroid Build Coastguard Worker 
DEF_TEST(Encode_WebpAnimated_FrameUnmatched,r)694*c8dee2aaSAndroid Build Coastguard Worker DEF_TEST(Encode_WebpAnimated_FrameUnmatched, r) {
695*c8dee2aaSAndroid Build Coastguard Worker     // Create two frames with unmatched sizes and verify the encode should fail.
696*c8dee2aaSAndroid Build Coastguard Worker     SkEncoder::Frame frame1;
697*c8dee2aaSAndroid Build Coastguard Worker     SkBitmap bm1;
698*c8dee2aaSAndroid Build Coastguard Worker     bm1.allocPixels(SkImageInfo::MakeN32Premul(8, 8));
699*c8dee2aaSAndroid Build Coastguard Worker     bm1.eraseColor(SK_ColorYELLOW);
700*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(r, bm1.peekPixels(&frame1.pixmap));
701*c8dee2aaSAndroid Build Coastguard Worker     frame1.duration = 200;
702*c8dee2aaSAndroid Build Coastguard Worker 
703*c8dee2aaSAndroid Build Coastguard Worker     SkEncoder::Frame frame2;
704*c8dee2aaSAndroid Build Coastguard Worker     SkBitmap bm2;
705*c8dee2aaSAndroid Build Coastguard Worker     bm2.allocPixels(SkImageInfo::MakeN32Premul(16, 16));
706*c8dee2aaSAndroid Build Coastguard Worker     bm2.eraseColor(SK_ColorYELLOW);
707*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(r, bm2.peekPixels(&frame2.pixmap));
708*c8dee2aaSAndroid Build Coastguard Worker     frame2.duration = 200;
709*c8dee2aaSAndroid Build Coastguard Worker 
710*c8dee2aaSAndroid Build Coastguard Worker     SkDynamicMemoryWStream stream;
711*c8dee2aaSAndroid Build Coastguard Worker     SkWebpEncoder::Options options;
712*c8dee2aaSAndroid Build Coastguard Worker     options.fCompression = SkWebpEncoder::Compression::kLossy;
713*c8dee2aaSAndroid Build Coastguard Worker     options.fQuality = 100;
714*c8dee2aaSAndroid Build Coastguard Worker     std::vector<SkEncoder::Frame> frames = {frame1, frame2};
715*c8dee2aaSAndroid Build Coastguard Worker     bool output = SkWebpEncoder::EncodeAnimated(&stream, frames, options);
716*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(r, !output);
717*c8dee2aaSAndroid Build Coastguard Worker }
718*c8dee2aaSAndroid Build Coastguard Worker 
DEF_TEST(Encode_Alpha,r)719*c8dee2aaSAndroid Build Coastguard Worker DEF_TEST(Encode_Alpha, r) {
720*c8dee2aaSAndroid Build Coastguard Worker     // These formats have no sensible way to encode alpha images.
721*c8dee2aaSAndroid Build Coastguard Worker     for (auto format : { SkEncodedImageFormat::kJPEG,
722*c8dee2aaSAndroid Build Coastguard Worker                          SkEncodedImageFormat::kPNG,
723*c8dee2aaSAndroid Build Coastguard Worker                          SkEncodedImageFormat::kWEBP }) {
724*c8dee2aaSAndroid Build Coastguard Worker         for (int ctAsInt = kUnknown_SkColorType + 1; ctAsInt <= kLastEnum_SkColorType; ctAsInt++) {
725*c8dee2aaSAndroid Build Coastguard Worker             auto ct = static_cast<SkColorType>(ctAsInt);
726*c8dee2aaSAndroid Build Coastguard Worker             // Non-alpha-only colortypes are tested elsewhere.
727*c8dee2aaSAndroid Build Coastguard Worker             if (!SkColorTypeIsAlphaOnly(ct)) continue;
728*c8dee2aaSAndroid Build Coastguard Worker             SkBitmap bm;
729*c8dee2aaSAndroid Build Coastguard Worker             bm.allocPixels(SkImageInfo::Make(10, 10, ct, kPremul_SkAlphaType));
730*c8dee2aaSAndroid Build Coastguard Worker             sk_bzero(bm.getPixels(), bm.computeByteSize());
731*c8dee2aaSAndroid Build Coastguard Worker             SkDynamicMemoryWStream stream;
732*c8dee2aaSAndroid Build Coastguard Worker             bool success = false;
733*c8dee2aaSAndroid Build Coastguard Worker             if (format == SkEncodedImageFormat::kJPEG) {
734*c8dee2aaSAndroid Build Coastguard Worker                 success = SkJpegEncoder::Encode(&stream, bm.pixmap(), {});
735*c8dee2aaSAndroid Build Coastguard Worker             } else if (format == SkEncodedImageFormat::kPNG) {
736*c8dee2aaSAndroid Build Coastguard Worker                 success = SkPngEncoder::Encode(&stream, bm.pixmap(), {});
737*c8dee2aaSAndroid Build Coastguard Worker             } else {
738*c8dee2aaSAndroid Build Coastguard Worker                 success = SkWebpEncoder::Encode(&stream, bm.pixmap(), {});
739*c8dee2aaSAndroid Build Coastguard Worker             }
740*c8dee2aaSAndroid Build Coastguard Worker 
741*c8dee2aaSAndroid Build Coastguard Worker             if ((format == SkEncodedImageFormat::kJPEG || format == SkEncodedImageFormat::kPNG) &&
742*c8dee2aaSAndroid Build Coastguard Worker                 ct == kAlpha_8_SkColorType) {
743*c8dee2aaSAndroid Build Coastguard Worker                 // We support encoding alpha8 to png and jpeg with our own private meaning.
744*c8dee2aaSAndroid Build Coastguard Worker                 REPORTER_ASSERT(r, success);
745*c8dee2aaSAndroid Build Coastguard Worker                 REPORTER_ASSERT(r, stream.bytesWritten() > 0);
746*c8dee2aaSAndroid Build Coastguard Worker             } else {
747*c8dee2aaSAndroid Build Coastguard Worker                 REPORTER_ASSERT(r, !success);
748*c8dee2aaSAndroid Build Coastguard Worker                 REPORTER_ASSERT(r, stream.bytesWritten() == 0);
749*c8dee2aaSAndroid Build Coastguard Worker             }
750*c8dee2aaSAndroid Build Coastguard Worker         }
751*c8dee2aaSAndroid Build Coastguard Worker     }
752*c8dee2aaSAndroid Build Coastguard Worker }
753