1cb93a386Sopenharmony_ci/*
2cb93a386Sopenharmony_ci * Copyright 2020 Google LLC
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 "include/private/SkTFitsIn.h"
9cb93a386Sopenharmony_ci#include "include/private/SkTo.h"
10cb93a386Sopenharmony_ci#include "src/images/SkImageEncoderPriv.h"
11cb93a386Sopenharmony_ci#include "src/ports/SkNDKConversions.h"
12cb93a386Sopenharmony_ci
13cb93a386Sopenharmony_cibool SkEncodeImageWithNDK(SkWStream* stream, const SkPixmap& pmap, SkEncodedImageFormat format,
14cb93a386Sopenharmony_ci                          int quality) {
15cb93a386Sopenharmony_ci    // If any of these values is invalid (e.g. set to zero), the info will be rejected by
16cb93a386Sopenharmony_ci    // AndroidBitmap_compress.
17cb93a386Sopenharmony_ci    AndroidBitmapInfo info {
18cb93a386Sopenharmony_ci        .width  = SkTFitsIn<uint32_t>(pmap.width())    ? SkToU32(pmap.width())    : 0,
19cb93a386Sopenharmony_ci        .height = SkTFitsIn<uint32_t>(pmap.height())   ? SkToU32(pmap.height())   : 0,
20cb93a386Sopenharmony_ci        .stride = SkTFitsIn<uint32_t>(pmap.rowBytes()) ? SkToU32(pmap.rowBytes()) : 0,
21cb93a386Sopenharmony_ci        .format = SkNDKConversions::toAndroidBitmapFormat(pmap.colorType())
22cb93a386Sopenharmony_ci    };
23cb93a386Sopenharmony_ci
24cb93a386Sopenharmony_ci    switch (pmap.alphaType()) {
25cb93a386Sopenharmony_ci        case kPremul_SkAlphaType:
26cb93a386Sopenharmony_ci            info.flags = ANDROID_BITMAP_FLAGS_ALPHA_PREMUL;
27cb93a386Sopenharmony_ci            break;
28cb93a386Sopenharmony_ci        case kOpaque_SkAlphaType:
29cb93a386Sopenharmony_ci            info.flags = ANDROID_BITMAP_FLAGS_ALPHA_OPAQUE;
30cb93a386Sopenharmony_ci            break;
31cb93a386Sopenharmony_ci        case kUnpremul_SkAlphaType:
32cb93a386Sopenharmony_ci            info.flags = ANDROID_BITMAP_FLAGS_ALPHA_UNPREMUL;
33cb93a386Sopenharmony_ci            break;
34cb93a386Sopenharmony_ci        default:
35cb93a386Sopenharmony_ci            return false;
36cb93a386Sopenharmony_ci    }
37cb93a386Sopenharmony_ci
38cb93a386Sopenharmony_ci    AndroidBitmapCompressFormat androidFormat;
39cb93a386Sopenharmony_ci    switch (format) {
40cb93a386Sopenharmony_ci        case SkEncodedImageFormat::kJPEG:
41cb93a386Sopenharmony_ci            androidFormat = ANDROID_BITMAP_COMPRESS_FORMAT_JPEG;
42cb93a386Sopenharmony_ci            break;
43cb93a386Sopenharmony_ci        case SkEncodedImageFormat::kPNG:
44cb93a386Sopenharmony_ci            androidFormat = ANDROID_BITMAP_COMPRESS_FORMAT_PNG;
45cb93a386Sopenharmony_ci            break;
46cb93a386Sopenharmony_ci        case SkEncodedImageFormat::kWEBP:
47cb93a386Sopenharmony_ci            if (quality == 100) {
48cb93a386Sopenharmony_ci                // Mimic the behavior of SkImageEncoder.cpp. In LOSSLESS mode, libwebp
49cb93a386Sopenharmony_ci                // interprets quality as the amount of effort (time) to spend making
50cb93a386Sopenharmony_ci                // the encoded image smaller, while the visual quality remains constant.
51cb93a386Sopenharmony_ci                // This value of 75 (on a scale of 0 - 100, where 100 spends the most
52cb93a386Sopenharmony_ci                // time for the smallest encoding) matches WebPConfigInit.
53cb93a386Sopenharmony_ci                androidFormat = ANDROID_BITMAP_COMPRESS_FORMAT_WEBP_LOSSLESS;
54cb93a386Sopenharmony_ci                quality = 75;
55cb93a386Sopenharmony_ci            } else {
56cb93a386Sopenharmony_ci                androidFormat = ANDROID_BITMAP_COMPRESS_FORMAT_WEBP_LOSSY;
57cb93a386Sopenharmony_ci            }
58cb93a386Sopenharmony_ci            break;
59cb93a386Sopenharmony_ci        default:
60cb93a386Sopenharmony_ci            return false;
61cb93a386Sopenharmony_ci    }
62cb93a386Sopenharmony_ci
63cb93a386Sopenharmony_ci    auto write_to_stream = [](void* userContext, const void* data, size_t size) {
64cb93a386Sopenharmony_ci        return reinterpret_cast<SkWStream*>(userContext)->write(data, size);
65cb93a386Sopenharmony_ci    };
66cb93a386Sopenharmony_ci
67cb93a386Sopenharmony_ci    return ANDROID_BITMAP_RESULT_SUCCESS == AndroidBitmap_compress(&info,
68cb93a386Sopenharmony_ci            SkNDKConversions::toDataSpace(pmap.colorSpace()), pmap.addr(), androidFormat, quality,
69cb93a386Sopenharmony_ci            reinterpret_cast<void*>(stream), write_to_stream);
70cb93a386Sopenharmony_ci}
71