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