xref: /third_party/skia/tests/EncodeTest.cpp (revision cb93a386)
1cb93a386Sopenharmony_ci/*
2cb93a386Sopenharmony_ci * Copyright 2017 Google Inc.
3cb93a386Sopenharmony_ci *
4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be
5cb93a386Sopenharmony_ci * found in the LICENSE file.
6cb93a386Sopenharmony_ci */
7cb93a386Sopenharmony_ci
8cb93a386Sopenharmony_ci#include "tests/Test.h"
9cb93a386Sopenharmony_ci#include "tools/Resources.h"
10cb93a386Sopenharmony_ci
11cb93a386Sopenharmony_ci#include "include/core/SkBitmap.h"
12cb93a386Sopenharmony_ci#include "include/core/SkCanvas.h"
13cb93a386Sopenharmony_ci#include "include/core/SkColorPriv.h"
14cb93a386Sopenharmony_ci#include "include/core/SkEncodedImageFormat.h"
15cb93a386Sopenharmony_ci#include "include/core/SkImage.h"
16cb93a386Sopenharmony_ci#include "include/core/SkStream.h"
17cb93a386Sopenharmony_ci#include "include/core/SkSurface.h"
18cb93a386Sopenharmony_ci#include "include/encode/SkJpegEncoder.h"
19cb93a386Sopenharmony_ci#include "include/encode/SkPngEncoder.h"
20cb93a386Sopenharmony_ci#include "include/encode/SkWebpEncoder.h"
21cb93a386Sopenharmony_ci#include "include/private/SkImageInfoPriv.h"
22cb93a386Sopenharmony_ci
23cb93a386Sopenharmony_ci#include "png.h"
24cb93a386Sopenharmony_ci
25cb93a386Sopenharmony_ci#include <algorithm>
26cb93a386Sopenharmony_ci#include <string>
27cb93a386Sopenharmony_ci#include <vector>
28cb93a386Sopenharmony_ci
29cb93a386Sopenharmony_ci// FIXME: Update the Google3 build's dependencies so it can run this test.
30cb93a386Sopenharmony_ci#ifndef SK_BUILD_FOR_GOOGLE3
31cb93a386Sopenharmony_ci#include "webp/decode.h"
32cb93a386Sopenharmony_ci#endif
33cb93a386Sopenharmony_ci
34cb93a386Sopenharmony_cistatic bool encode(SkEncodedImageFormat format, SkWStream* dst, const SkPixmap& src) {
35cb93a386Sopenharmony_ci    switch (format) {
36cb93a386Sopenharmony_ci        case SkEncodedImageFormat::kJPEG:
37cb93a386Sopenharmony_ci            return SkJpegEncoder::Encode(dst, src, SkJpegEncoder::Options());
38cb93a386Sopenharmony_ci        case SkEncodedImageFormat::kPNG:
39cb93a386Sopenharmony_ci            return SkPngEncoder::Encode(dst, src, SkPngEncoder::Options());
40cb93a386Sopenharmony_ci        default:
41cb93a386Sopenharmony_ci            return false;
42cb93a386Sopenharmony_ci    }
43cb93a386Sopenharmony_ci}
44cb93a386Sopenharmony_ci
45cb93a386Sopenharmony_cistatic std::unique_ptr<SkEncoder> make(SkEncodedImageFormat format, SkWStream* dst,
46cb93a386Sopenharmony_ci                                       const SkPixmap& src) {
47cb93a386Sopenharmony_ci    switch (format) {
48cb93a386Sopenharmony_ci        case SkEncodedImageFormat::kJPEG:
49cb93a386Sopenharmony_ci            return SkJpegEncoder::Make(dst, src, SkJpegEncoder::Options());
50cb93a386Sopenharmony_ci        case SkEncodedImageFormat::kPNG:
51cb93a386Sopenharmony_ci            return SkPngEncoder::Make(dst, src, SkPngEncoder::Options());
52cb93a386Sopenharmony_ci        default:
53cb93a386Sopenharmony_ci            return nullptr;
54cb93a386Sopenharmony_ci    }
55cb93a386Sopenharmony_ci}
56cb93a386Sopenharmony_ci
57cb93a386Sopenharmony_cistatic void test_encode(skiatest::Reporter* r, SkEncodedImageFormat format) {
58cb93a386Sopenharmony_ci    SkBitmap bitmap;
59cb93a386Sopenharmony_ci    bool success = GetResourceAsBitmap("images/mandrill_128.png", &bitmap);
60cb93a386Sopenharmony_ci    if (!success) {
61cb93a386Sopenharmony_ci        return;
62cb93a386Sopenharmony_ci    }
63cb93a386Sopenharmony_ci
64cb93a386Sopenharmony_ci    SkPixmap src;
65cb93a386Sopenharmony_ci    success = bitmap.peekPixels(&src);
66cb93a386Sopenharmony_ci    REPORTER_ASSERT(r, success);
67cb93a386Sopenharmony_ci    if (!success) {
68cb93a386Sopenharmony_ci        return;
69cb93a386Sopenharmony_ci    }
70cb93a386Sopenharmony_ci
71cb93a386Sopenharmony_ci    SkDynamicMemoryWStream dst0, dst1, dst2, dst3;
72cb93a386Sopenharmony_ci    success = encode(format, &dst0, src);
73cb93a386Sopenharmony_ci    REPORTER_ASSERT(r, success);
74cb93a386Sopenharmony_ci
75cb93a386Sopenharmony_ci    auto encoder1 = make(format, &dst1, src);
76cb93a386Sopenharmony_ci    for (int i = 0; i < src.height(); i++) {
77cb93a386Sopenharmony_ci        success = encoder1->encodeRows(1);
78cb93a386Sopenharmony_ci        REPORTER_ASSERT(r, success);
79cb93a386Sopenharmony_ci    }
80cb93a386Sopenharmony_ci
81cb93a386Sopenharmony_ci    auto encoder2 = make(format, &dst2, src);
82cb93a386Sopenharmony_ci    for (int i = 0; i < src.height(); i+=3) {
83cb93a386Sopenharmony_ci        success = encoder2->encodeRows(3);
84cb93a386Sopenharmony_ci        REPORTER_ASSERT(r, success);
85cb93a386Sopenharmony_ci    }
86cb93a386Sopenharmony_ci
87cb93a386Sopenharmony_ci    auto encoder3 = make(format, &dst3, src);
88cb93a386Sopenharmony_ci    success = encoder3->encodeRows(200);
89cb93a386Sopenharmony_ci    REPORTER_ASSERT(r, success);
90cb93a386Sopenharmony_ci
91cb93a386Sopenharmony_ci    sk_sp<SkData> data0 = dst0.detachAsData();
92cb93a386Sopenharmony_ci    sk_sp<SkData> data1 = dst1.detachAsData();
93cb93a386Sopenharmony_ci    sk_sp<SkData> data2 = dst2.detachAsData();
94cb93a386Sopenharmony_ci    sk_sp<SkData> data3 = dst3.detachAsData();
95cb93a386Sopenharmony_ci    REPORTER_ASSERT(r, data0->equals(data1.get()));
96cb93a386Sopenharmony_ci    REPORTER_ASSERT(r, data0->equals(data2.get()));
97cb93a386Sopenharmony_ci    REPORTER_ASSERT(r, data0->equals(data3.get()));
98cb93a386Sopenharmony_ci}
99cb93a386Sopenharmony_ci
100cb93a386Sopenharmony_ciDEF_TEST(Encode, r) {
101cb93a386Sopenharmony_ci    test_encode(r, SkEncodedImageFormat::kJPEG);
102cb93a386Sopenharmony_ci    test_encode(r, SkEncodedImageFormat::kPNG);
103cb93a386Sopenharmony_ci}
104cb93a386Sopenharmony_ci
105cb93a386Sopenharmony_cistatic inline bool almost_equals(SkPMColor a, SkPMColor b, int tolerance) {
106cb93a386Sopenharmony_ci    if (SkTAbs((int)SkGetPackedR32(a) - (int)SkGetPackedR32(b)) > tolerance) {
107cb93a386Sopenharmony_ci        return false;
108cb93a386Sopenharmony_ci    }
109cb93a386Sopenharmony_ci
110cb93a386Sopenharmony_ci    if (SkTAbs((int)SkGetPackedG32(a) - (int)SkGetPackedG32(b)) > tolerance) {
111cb93a386Sopenharmony_ci        return false;
112cb93a386Sopenharmony_ci    }
113cb93a386Sopenharmony_ci
114cb93a386Sopenharmony_ci    if (SkTAbs((int)SkGetPackedB32(a) - (int)SkGetPackedB32(b)) > tolerance) {
115cb93a386Sopenharmony_ci        return false;
116cb93a386Sopenharmony_ci    }
117cb93a386Sopenharmony_ci
118cb93a386Sopenharmony_ci    if (SkTAbs((int)SkGetPackedA32(a) - (int)SkGetPackedA32(b)) > tolerance) {
119cb93a386Sopenharmony_ci        return false;
120cb93a386Sopenharmony_ci    }
121cb93a386Sopenharmony_ci
122cb93a386Sopenharmony_ci    return true;
123cb93a386Sopenharmony_ci}
124cb93a386Sopenharmony_ci
125cb93a386Sopenharmony_cistatic inline bool almost_equals(const SkBitmap& a, const SkBitmap& b, int tolerance) {
126cb93a386Sopenharmony_ci    if (a.info() != b.info()) {
127cb93a386Sopenharmony_ci        return false;
128cb93a386Sopenharmony_ci    }
129cb93a386Sopenharmony_ci
130cb93a386Sopenharmony_ci    SkASSERT(kN32_SkColorType == a.colorType());
131cb93a386Sopenharmony_ci    for (int y = 0; y < a.height(); y++) {
132cb93a386Sopenharmony_ci        for (int x = 0; x < a.width(); x++) {
133cb93a386Sopenharmony_ci            if (!almost_equals(*a.getAddr32(x, y), *b.getAddr32(x, y), tolerance)) {
134cb93a386Sopenharmony_ci                return false;
135cb93a386Sopenharmony_ci            }
136cb93a386Sopenharmony_ci        }
137cb93a386Sopenharmony_ci    }
138cb93a386Sopenharmony_ci
139cb93a386Sopenharmony_ci    return true;
140cb93a386Sopenharmony_ci}
141cb93a386Sopenharmony_ci
142cb93a386Sopenharmony_ciDEF_TEST(Encode_JPG, r) {
143cb93a386Sopenharmony_ci    auto image = GetResourceAsImage("images/mandrill_128.png");
144cb93a386Sopenharmony_ci    if (!image) {
145cb93a386Sopenharmony_ci        return;
146cb93a386Sopenharmony_ci    }
147cb93a386Sopenharmony_ci
148cb93a386Sopenharmony_ci    for (auto ct : { kRGBA_8888_SkColorType,
149cb93a386Sopenharmony_ci                     kBGRA_8888_SkColorType,
150cb93a386Sopenharmony_ci                     kRGB_565_SkColorType,
151cb93a386Sopenharmony_ci                     kARGB_4444_SkColorType,
152cb93a386Sopenharmony_ci                     kGray_8_SkColorType,
153cb93a386Sopenharmony_ci                     kRGBA_F16_SkColorType }) {
154cb93a386Sopenharmony_ci        for (auto at : { kPremul_SkAlphaType, kUnpremul_SkAlphaType, kOpaque_SkAlphaType }) {
155cb93a386Sopenharmony_ci            auto info = SkImageInfo::Make(image->width(), image->height(), ct, at);
156cb93a386Sopenharmony_ci            auto surface = SkSurface::MakeRaster(info);
157cb93a386Sopenharmony_ci            auto canvas = surface->getCanvas();
158cb93a386Sopenharmony_ci            canvas->drawImage(image, 0, 0);
159cb93a386Sopenharmony_ci
160cb93a386Sopenharmony_ci            SkBitmap bm;
161cb93a386Sopenharmony_ci            bm.allocPixels(info);
162cb93a386Sopenharmony_ci            if (!surface->makeImageSnapshot()->readPixels(nullptr, bm.pixmap(), 0, 0)) {
163cb93a386Sopenharmony_ci                ERRORF(r, "failed to readPixels! ct: %i\tat: %i\n", ct, at);
164cb93a386Sopenharmony_ci                continue;
165cb93a386Sopenharmony_ci            }
166cb93a386Sopenharmony_ci            for (auto alphaOption : { SkJpegEncoder::AlphaOption::kIgnore,
167cb93a386Sopenharmony_ci                                      SkJpegEncoder::AlphaOption::kBlendOnBlack }) {
168cb93a386Sopenharmony_ci                SkJpegEncoder::Options opts;
169cb93a386Sopenharmony_ci                opts.fAlphaOption = alphaOption;
170cb93a386Sopenharmony_ci                SkNullWStream ignored;
171cb93a386Sopenharmony_ci                if (!SkJpegEncoder::Encode(&ignored, bm.pixmap(), opts)) {
172cb93a386Sopenharmony_ci                    REPORTER_ASSERT(r, ct == kARGB_4444_SkColorType
173cb93a386Sopenharmony_ci                                    && alphaOption == SkJpegEncoder::AlphaOption::kBlendOnBlack);
174cb93a386Sopenharmony_ci                }
175cb93a386Sopenharmony_ci            }
176cb93a386Sopenharmony_ci        }
177cb93a386Sopenharmony_ci    }
178cb93a386Sopenharmony_ci}
179cb93a386Sopenharmony_ci
180cb93a386Sopenharmony_ciDEF_TEST(Encode_JpegDownsample, r) {
181cb93a386Sopenharmony_ci    SkBitmap bitmap;
182cb93a386Sopenharmony_ci    bool success = GetResourceAsBitmap("images/mandrill_128.png", &bitmap);
183cb93a386Sopenharmony_ci    if (!success) {
184cb93a386Sopenharmony_ci        return;
185cb93a386Sopenharmony_ci    }
186cb93a386Sopenharmony_ci
187cb93a386Sopenharmony_ci    SkPixmap src;
188cb93a386Sopenharmony_ci    success = bitmap.peekPixels(&src);
189cb93a386Sopenharmony_ci    REPORTER_ASSERT(r, success);
190cb93a386Sopenharmony_ci    if (!success) {
191cb93a386Sopenharmony_ci        return;
192cb93a386Sopenharmony_ci    }
193cb93a386Sopenharmony_ci
194cb93a386Sopenharmony_ci    SkDynamicMemoryWStream dst0, dst1, dst2;
195cb93a386Sopenharmony_ci    SkJpegEncoder::Options options;
196cb93a386Sopenharmony_ci    success = SkJpegEncoder::Encode(&dst0, src, options);
197cb93a386Sopenharmony_ci    REPORTER_ASSERT(r, success);
198cb93a386Sopenharmony_ci
199cb93a386Sopenharmony_ci    options.fDownsample = SkJpegEncoder::Downsample::k422;
200cb93a386Sopenharmony_ci    success = SkJpegEncoder::Encode(&dst1, src, options);
201cb93a386Sopenharmony_ci    REPORTER_ASSERT(r, success);
202cb93a386Sopenharmony_ci
203cb93a386Sopenharmony_ci    options.fDownsample = SkJpegEncoder::Downsample::k444;
204cb93a386Sopenharmony_ci    success = SkJpegEncoder::Encode(&dst2, src, options);
205cb93a386Sopenharmony_ci    REPORTER_ASSERT(r, success);
206cb93a386Sopenharmony_ci
207cb93a386Sopenharmony_ci    sk_sp<SkData> data0 = dst0.detachAsData();
208cb93a386Sopenharmony_ci    sk_sp<SkData> data1 = dst1.detachAsData();
209cb93a386Sopenharmony_ci    sk_sp<SkData> data2 = dst2.detachAsData();
210cb93a386Sopenharmony_ci    REPORTER_ASSERT(r, data0->size() < data1->size());
211cb93a386Sopenharmony_ci    REPORTER_ASSERT(r, data1->size() < data2->size());
212cb93a386Sopenharmony_ci
213cb93a386Sopenharmony_ci    SkBitmap bm0, bm1, bm2;
214cb93a386Sopenharmony_ci    SkImage::MakeFromEncoded(data0)->asLegacyBitmap(&bm0);
215cb93a386Sopenharmony_ci    SkImage::MakeFromEncoded(data1)->asLegacyBitmap(&bm1);
216cb93a386Sopenharmony_ci    SkImage::MakeFromEncoded(data2)->asLegacyBitmap(&bm2);
217cb93a386Sopenharmony_ci    REPORTER_ASSERT(r, almost_equals(bm0, bm1, 60));
218cb93a386Sopenharmony_ci    REPORTER_ASSERT(r, almost_equals(bm1, bm2, 60));
219cb93a386Sopenharmony_ci}
220cb93a386Sopenharmony_ci
221cb93a386Sopenharmony_cistatic inline void pushComment(
222cb93a386Sopenharmony_ci        std::vector<std::string>& comments, const char* keyword, const char* text) {
223cb93a386Sopenharmony_ci    comments.push_back(keyword);
224cb93a386Sopenharmony_ci    comments.push_back(text);
225cb93a386Sopenharmony_ci}
226cb93a386Sopenharmony_ci
227cb93a386Sopenharmony_cistatic void testPngComments(const SkPixmap& src, SkPngEncoder::Options& options,
228cb93a386Sopenharmony_ci        skiatest::Reporter* r) {
229cb93a386Sopenharmony_ci    std::vector<std::string> commentStrings;
230cb93a386Sopenharmony_ci    pushComment(commentStrings, "key", "text");
231cb93a386Sopenharmony_ci    pushComment(commentStrings, "test", "something");
232cb93a386Sopenharmony_ci    pushComment(commentStrings, "have some", "spaces in both");
233cb93a386Sopenharmony_ci
234cb93a386Sopenharmony_ci    std::string longKey(PNG_KEYWORD_MAX_LENGTH, 'x');
235cb93a386Sopenharmony_ci#ifdef SK_DEBUG
236cb93a386Sopenharmony_ci    commentStrings.push_back(longKey);
237cb93a386Sopenharmony_ci#else
238cb93a386Sopenharmony_ci    // We call SkDEBUGFAILF it the key is too long so we'll only test this in release mode.
239cb93a386Sopenharmony_ci    commentStrings.push_back(longKey + "x");
240cb93a386Sopenharmony_ci#endif
241cb93a386Sopenharmony_ci    commentStrings.push_back("");
242cb93a386Sopenharmony_ci
243cb93a386Sopenharmony_ci    std::vector<const char*> commentPointers;
244cb93a386Sopenharmony_ci    std::vector<size_t> commentSizes;
245cb93a386Sopenharmony_ci    for(auto& str : commentStrings) {
246cb93a386Sopenharmony_ci        commentPointers.push_back(str.c_str());
247cb93a386Sopenharmony_ci        commentSizes.push_back(str.length() + 1);
248cb93a386Sopenharmony_ci    }
249cb93a386Sopenharmony_ci
250cb93a386Sopenharmony_ci    options.fComments = SkDataTable::MakeCopyArrays((void const *const *)commentPointers.data(),
251cb93a386Sopenharmony_ci            commentSizes.data(), commentStrings.size());
252cb93a386Sopenharmony_ci
253cb93a386Sopenharmony_ci
254cb93a386Sopenharmony_ci    SkDynamicMemoryWStream dst;
255cb93a386Sopenharmony_ci    bool success = SkPngEncoder::Encode(&dst, src, options);
256cb93a386Sopenharmony_ci    REPORTER_ASSERT(r, success);
257cb93a386Sopenharmony_ci
258cb93a386Sopenharmony_ci    std::vector<char> output(dst.bytesWritten());
259cb93a386Sopenharmony_ci    dst.copyTo(output.data());
260cb93a386Sopenharmony_ci
261cb93a386Sopenharmony_ci    // Each chunk is of the form length (4 bytes), chunk type (tEXt), data,
262cb93a386Sopenharmony_ci    // checksum (4 bytes).  Make sure we find all of them in the encoded
263cb93a386Sopenharmony_ci    // results.
264cb93a386Sopenharmony_ci    const char kExpected1[] =
265cb93a386Sopenharmony_ci        "\x00\x00\x00\x08tEXtkey\x00text\x9e\xe7\x66\x51";
266cb93a386Sopenharmony_ci    const char kExpected2[] =
267cb93a386Sopenharmony_ci        "\x00\x00\x00\x0etEXttest\x00something\x29\xba\xef\xac";
268cb93a386Sopenharmony_ci    const char kExpected3[] =
269cb93a386Sopenharmony_ci        "\x00\x00\x00\x18tEXthave some\x00spaces in both\x8d\x69\x34\x2d";
270cb93a386Sopenharmony_ci    std::string longKeyRecord = "tEXt" + longKey; // A snippet of our long key comment
271cb93a386Sopenharmony_ci    std::string tooLongRecord = "tExt" + longKey + "x"; // A snippet whose key is too long
272cb93a386Sopenharmony_ci
273cb93a386Sopenharmony_ci    auto search1 = std::search(output.begin(), output.end(),
274cb93a386Sopenharmony_ci            kExpected1, kExpected1 + sizeof(kExpected1));
275cb93a386Sopenharmony_ci    auto search2 = std::search(output.begin(), output.end(),
276cb93a386Sopenharmony_ci            kExpected2, kExpected2 + sizeof(kExpected2));
277cb93a386Sopenharmony_ci    auto search3 = std::search(output.begin(), output.end(),
278cb93a386Sopenharmony_ci            kExpected3, kExpected3 + sizeof(kExpected3));
279cb93a386Sopenharmony_ci    auto search4 = std::search(output.begin(), output.end(),
280cb93a386Sopenharmony_ci            longKeyRecord.begin(), longKeyRecord.end());
281cb93a386Sopenharmony_ci    auto search5 = std::search(output.begin(), output.end(),
282cb93a386Sopenharmony_ci            tooLongRecord.begin(), tooLongRecord.end());
283cb93a386Sopenharmony_ci
284cb93a386Sopenharmony_ci    REPORTER_ASSERT(r, search1 != output.end());
285cb93a386Sopenharmony_ci    REPORTER_ASSERT(r, search2 != output.end());
286cb93a386Sopenharmony_ci    REPORTER_ASSERT(r, search3 != output.end());
287cb93a386Sopenharmony_ci    REPORTER_ASSERT(r, search4 != output.end());
288cb93a386Sopenharmony_ci    REPORTER_ASSERT(r, search5 == output.end());
289cb93a386Sopenharmony_ci    // Comments test ends
290cb93a386Sopenharmony_ci}
291cb93a386Sopenharmony_ci
292cb93a386Sopenharmony_ciDEF_TEST(Encode_PngOptions, r) {
293cb93a386Sopenharmony_ci    SkBitmap bitmap;
294cb93a386Sopenharmony_ci    bool success = GetResourceAsBitmap("images/mandrill_128.png", &bitmap);
295cb93a386Sopenharmony_ci    if (!success) {
296cb93a386Sopenharmony_ci        return;
297cb93a386Sopenharmony_ci    }
298cb93a386Sopenharmony_ci
299cb93a386Sopenharmony_ci    SkPixmap src;
300cb93a386Sopenharmony_ci    success = bitmap.peekPixels(&src);
301cb93a386Sopenharmony_ci    REPORTER_ASSERT(r, success);
302cb93a386Sopenharmony_ci    if (!success) {
303cb93a386Sopenharmony_ci        return;
304cb93a386Sopenharmony_ci    }
305cb93a386Sopenharmony_ci
306cb93a386Sopenharmony_ci    SkDynamicMemoryWStream dst0, dst1, dst2;
307cb93a386Sopenharmony_ci    SkPngEncoder::Options options;
308cb93a386Sopenharmony_ci    success = SkPngEncoder::Encode(&dst0, src, options);
309cb93a386Sopenharmony_ci    REPORTER_ASSERT(r, success);
310cb93a386Sopenharmony_ci
311cb93a386Sopenharmony_ci    options.fFilterFlags = SkPngEncoder::FilterFlag::kUp;
312cb93a386Sopenharmony_ci    success = SkPngEncoder::Encode(&dst1, src, options);
313cb93a386Sopenharmony_ci    REPORTER_ASSERT(r, success);
314cb93a386Sopenharmony_ci
315cb93a386Sopenharmony_ci    options.fZLibLevel = 3;
316cb93a386Sopenharmony_ci    success = SkPngEncoder::Encode(&dst2, src, options);
317cb93a386Sopenharmony_ci    REPORTER_ASSERT(r, success);
318cb93a386Sopenharmony_ci
319cb93a386Sopenharmony_ci    testPngComments(src, options, r);
320cb93a386Sopenharmony_ci
321cb93a386Sopenharmony_ci    sk_sp<SkData> data0 = dst0.detachAsData();
322cb93a386Sopenharmony_ci    sk_sp<SkData> data1 = dst1.detachAsData();
323cb93a386Sopenharmony_ci    sk_sp<SkData> data2 = dst2.detachAsData();
324cb93a386Sopenharmony_ci    REPORTER_ASSERT(r, data0->size() < data1->size());
325cb93a386Sopenharmony_ci    REPORTER_ASSERT(r, data1->size() < data2->size());
326cb93a386Sopenharmony_ci
327cb93a386Sopenharmony_ci    SkBitmap bm0, bm1, bm2;
328cb93a386Sopenharmony_ci    SkImage::MakeFromEncoded(data0)->asLegacyBitmap(&bm0);
329cb93a386Sopenharmony_ci    SkImage::MakeFromEncoded(data1)->asLegacyBitmap(&bm1);
330cb93a386Sopenharmony_ci    SkImage::MakeFromEncoded(data2)->asLegacyBitmap(&bm2);
331cb93a386Sopenharmony_ci    REPORTER_ASSERT(r, almost_equals(bm0, bm1, 0));
332cb93a386Sopenharmony_ci    REPORTER_ASSERT(r, almost_equals(bm0, bm2, 0));
333cb93a386Sopenharmony_ci}
334cb93a386Sopenharmony_ci
335cb93a386Sopenharmony_ci#ifndef SK_BUILD_FOR_GOOGLE3
336cb93a386Sopenharmony_ciDEF_TEST(Encode_WebpQuality, r) {
337cb93a386Sopenharmony_ci    SkBitmap bm;
338cb93a386Sopenharmony_ci    bm.allocN32Pixels(100, 100);
339cb93a386Sopenharmony_ci    bm.eraseColor(SK_ColorBLUE);
340cb93a386Sopenharmony_ci
341cb93a386Sopenharmony_ci    auto dataLossy    = SkEncodeBitmap(bm, SkEncodedImageFormat::kWEBP, 99);
342cb93a386Sopenharmony_ci    auto dataLossLess = SkEncodeBitmap(bm, SkEncodedImageFormat::kWEBP, 100);
343cb93a386Sopenharmony_ci
344cb93a386Sopenharmony_ci    enum Format {
345cb93a386Sopenharmony_ci        kMixed    = 0,
346cb93a386Sopenharmony_ci        kLossy    = 1,
347cb93a386Sopenharmony_ci        kLossless = 2,
348cb93a386Sopenharmony_ci    };
349cb93a386Sopenharmony_ci
350cb93a386Sopenharmony_ci    auto test = [&r](const sk_sp<SkData>& data, Format expected) {
351cb93a386Sopenharmony_ci        auto printFormat = [](int f) {
352cb93a386Sopenharmony_ci            switch (f) {
353cb93a386Sopenharmony_ci                case kMixed:    return "mixed";
354cb93a386Sopenharmony_ci                case kLossy:    return "lossy";
355cb93a386Sopenharmony_ci                case kLossless: return "lossless";
356cb93a386Sopenharmony_ci                default:        return "unknown";
357cb93a386Sopenharmony_ci            }
358cb93a386Sopenharmony_ci        };
359cb93a386Sopenharmony_ci
360cb93a386Sopenharmony_ci        if (!data) {
361cb93a386Sopenharmony_ci            ERRORF(r, "Failed to encode. Expected %s", printFormat(expected));
362cb93a386Sopenharmony_ci            return;
363cb93a386Sopenharmony_ci        }
364cb93a386Sopenharmony_ci
365cb93a386Sopenharmony_ci        WebPBitstreamFeatures features;
366cb93a386Sopenharmony_ci        auto status = WebPGetFeatures(data->bytes(), data->size(), &features);
367cb93a386Sopenharmony_ci        if (status != VP8_STATUS_OK) {
368cb93a386Sopenharmony_ci            ERRORF(r, "Encode had an error %i. Expected %s", status, printFormat(expected));
369cb93a386Sopenharmony_ci            return;
370cb93a386Sopenharmony_ci        }
371cb93a386Sopenharmony_ci
372cb93a386Sopenharmony_ci        if (expected != features.format) {
373cb93a386Sopenharmony_ci            ERRORF(r, "Expected %s encode, but got format %s", printFormat(expected),
374cb93a386Sopenharmony_ci                                                               printFormat(features.format));
375cb93a386Sopenharmony_ci        }
376cb93a386Sopenharmony_ci    };
377cb93a386Sopenharmony_ci
378cb93a386Sopenharmony_ci    test(dataLossy,    kLossy);
379cb93a386Sopenharmony_ci    test(dataLossLess, kLossless);
380cb93a386Sopenharmony_ci}
381cb93a386Sopenharmony_ci#endif
382cb93a386Sopenharmony_ci
383cb93a386Sopenharmony_ciDEF_TEST(Encode_WebpOptions, r) {
384cb93a386Sopenharmony_ci    SkBitmap bitmap;
385cb93a386Sopenharmony_ci    bool success = GetResourceAsBitmap("images/google_chrome.ico", &bitmap);
386cb93a386Sopenharmony_ci    if (!success) {
387cb93a386Sopenharmony_ci        return;
388cb93a386Sopenharmony_ci    }
389cb93a386Sopenharmony_ci
390cb93a386Sopenharmony_ci    SkPixmap src;
391cb93a386Sopenharmony_ci    success = bitmap.peekPixels(&src);
392cb93a386Sopenharmony_ci    REPORTER_ASSERT(r, success);
393cb93a386Sopenharmony_ci    if (!success) {
394cb93a386Sopenharmony_ci        return;
395cb93a386Sopenharmony_ci    }
396cb93a386Sopenharmony_ci
397cb93a386Sopenharmony_ci    SkDynamicMemoryWStream dst0, dst1, dst2, dst3;
398cb93a386Sopenharmony_ci    SkWebpEncoder::Options options;
399cb93a386Sopenharmony_ci    options.fCompression = SkWebpEncoder::Compression::kLossless;
400cb93a386Sopenharmony_ci    options.fQuality = 0.0f;
401cb93a386Sopenharmony_ci    success = SkWebpEncoder::Encode(&dst0, src, options);
402cb93a386Sopenharmony_ci    REPORTER_ASSERT(r, success);
403cb93a386Sopenharmony_ci
404cb93a386Sopenharmony_ci    options.fQuality = 100.0f;
405cb93a386Sopenharmony_ci    success = SkWebpEncoder::Encode(&dst1, src, options);
406cb93a386Sopenharmony_ci    REPORTER_ASSERT(r, success);
407cb93a386Sopenharmony_ci
408cb93a386Sopenharmony_ci    options.fCompression = SkWebpEncoder::Compression::kLossy;
409cb93a386Sopenharmony_ci    options.fQuality = 100.0f;
410cb93a386Sopenharmony_ci    success = SkWebpEncoder::Encode(&dst2, src, options);
411cb93a386Sopenharmony_ci    REPORTER_ASSERT(r, success);
412cb93a386Sopenharmony_ci
413cb93a386Sopenharmony_ci    options.fCompression = SkWebpEncoder::Compression::kLossy;
414cb93a386Sopenharmony_ci    options.fQuality = 50.0f;
415cb93a386Sopenharmony_ci    success = SkWebpEncoder::Encode(&dst3, src, options);
416cb93a386Sopenharmony_ci    REPORTER_ASSERT(r, success);
417cb93a386Sopenharmony_ci
418cb93a386Sopenharmony_ci    sk_sp<SkData> data0 = dst0.detachAsData();
419cb93a386Sopenharmony_ci    sk_sp<SkData> data1 = dst1.detachAsData();
420cb93a386Sopenharmony_ci    sk_sp<SkData> data2 = dst2.detachAsData();
421cb93a386Sopenharmony_ci    sk_sp<SkData> data3 = dst3.detachAsData();
422cb93a386Sopenharmony_ci    REPORTER_ASSERT(r, data0->size() > data1->size());
423cb93a386Sopenharmony_ci    REPORTER_ASSERT(r, data1->size() > data2->size());
424cb93a386Sopenharmony_ci    REPORTER_ASSERT(r, data2->size() > data3->size());
425cb93a386Sopenharmony_ci
426cb93a386Sopenharmony_ci    SkBitmap bm0, bm1, bm2, bm3;
427cb93a386Sopenharmony_ci    SkImage::MakeFromEncoded(data0)->asLegacyBitmap(&bm0);
428cb93a386Sopenharmony_ci    SkImage::MakeFromEncoded(data1)->asLegacyBitmap(&bm1);
429cb93a386Sopenharmony_ci    SkImage::MakeFromEncoded(data2)->asLegacyBitmap(&bm2);
430cb93a386Sopenharmony_ci    SkImage::MakeFromEncoded(data3)->asLegacyBitmap(&bm3);
431cb93a386Sopenharmony_ci    REPORTER_ASSERT(r, almost_equals(bm0, bm1, 0));
432cb93a386Sopenharmony_ci    REPORTER_ASSERT(r, almost_equals(bm0, bm2, 90));
433cb93a386Sopenharmony_ci    REPORTER_ASSERT(r, almost_equals(bm2, bm3, 50));
434cb93a386Sopenharmony_ci}
435cb93a386Sopenharmony_ci
436cb93a386Sopenharmony_ciDEF_TEST(Encode_Alpha, r) {
437cb93a386Sopenharmony_ci    // These formats have no sensible way to encode alpha images.
438cb93a386Sopenharmony_ci    for (auto format : { SkEncodedImageFormat::kJPEG,
439cb93a386Sopenharmony_ci                         SkEncodedImageFormat::kPNG,
440cb93a386Sopenharmony_ci                         SkEncodedImageFormat::kWEBP }) {
441cb93a386Sopenharmony_ci        for (int ctAsInt = kUnknown_SkColorType + 1; ctAsInt <= kLastEnum_SkColorType; ctAsInt++) {
442cb93a386Sopenharmony_ci            auto ct = static_cast<SkColorType>(ctAsInt);
443cb93a386Sopenharmony_ci            // Non-alpha-only colortypes are tested elsewhere.
444cb93a386Sopenharmony_ci            if (!SkColorTypeIsAlphaOnly(ct)) continue;
445cb93a386Sopenharmony_ci            SkBitmap bm;
446cb93a386Sopenharmony_ci            bm.allocPixels(SkImageInfo::Make(10, 10, ct, kPremul_SkAlphaType));
447cb93a386Sopenharmony_ci            sk_bzero(bm.getPixels(), bm.computeByteSize());
448cb93a386Sopenharmony_ci            auto data = SkEncodeBitmap(bm, format, 100);
449cb93a386Sopenharmony_ci            if (format == SkEncodedImageFormat::kPNG && ct == kAlpha_8_SkColorType) {
450cb93a386Sopenharmony_ci                // We support encoding alpha8 to png with our own private meaning.
451cb93a386Sopenharmony_ci                REPORTER_ASSERT(r, data != nullptr);
452cb93a386Sopenharmony_ci            } else {
453cb93a386Sopenharmony_ci                REPORTER_ASSERT(r, data == nullptr);
454cb93a386Sopenharmony_ci            }
455cb93a386Sopenharmony_ci        }
456cb93a386Sopenharmony_ci    }
457cb93a386Sopenharmony_ci}
458