1cb93a386Sopenharmony_ci/*
2cb93a386Sopenharmony_ci * Copyright 2009 The Android Open Source Project
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/core/SkBitmap.h"
9cb93a386Sopenharmony_ci#include "include/encode/SkJpegEncoder.h"
10cb93a386Sopenharmony_ci#include "include/encode/SkPngEncoder.h"
11cb93a386Sopenharmony_ci#include "include/encode/SkWebpEncoder.h"
12cb93a386Sopenharmony_ci#include "src/images/SkImageEncoderPriv.h"
13cb93a386Sopenharmony_ci
14cb93a386Sopenharmony_ci#ifndef SK_ENCODE_JPEG
15cb93a386Sopenharmony_cibool SkJpegEncoder::Encode(SkWStream*, const SkPixmap&, const Options&) { return false; }
16cb93a386Sopenharmony_cistd::unique_ptr<SkEncoder> SkJpegEncoder::Make(SkWStream*, const SkPixmap&, const Options&) {
17cb93a386Sopenharmony_ci    return nullptr;
18cb93a386Sopenharmony_ci}
19cb93a386Sopenharmony_ci#endif
20cb93a386Sopenharmony_ci
21cb93a386Sopenharmony_ci#ifndef SK_ENCODE_PNG
22cb93a386Sopenharmony_cibool SkPngEncoder::Encode(SkWStream*, const SkPixmap&, const Options&) { return false; }
23cb93a386Sopenharmony_cistd::unique_ptr<SkEncoder> SkPngEncoder::Make(SkWStream*, const SkPixmap&, const Options&) {
24cb93a386Sopenharmony_ci    return nullptr;
25cb93a386Sopenharmony_ci}
26cb93a386Sopenharmony_ci#endif
27cb93a386Sopenharmony_ci
28cb93a386Sopenharmony_ci#ifndef SK_ENCODE_WEBP
29cb93a386Sopenharmony_cibool SkWebpEncoder::Encode(SkWStream*, const SkPixmap&, const Options&) { return false; }
30cb93a386Sopenharmony_ci#endif
31cb93a386Sopenharmony_ci
32cb93a386Sopenharmony_cibool SkEncodeImage(SkWStream* dst, const SkBitmap& src, SkEncodedImageFormat f, int q) {
33cb93a386Sopenharmony_ci    SkPixmap pixmap;
34cb93a386Sopenharmony_ci    return src.peekPixels(&pixmap) && SkEncodeImage(dst, pixmap, f, q);
35cb93a386Sopenharmony_ci}
36cb93a386Sopenharmony_ci
37cb93a386Sopenharmony_cibool SkEncodeImage(SkWStream* dst, const SkPixmap& src,
38cb93a386Sopenharmony_ci                   SkEncodedImageFormat format, int quality) {
39cb93a386Sopenharmony_ci    #ifdef SK_USE_CG_ENCODER
40cb93a386Sopenharmony_ci        (void)quality;
41cb93a386Sopenharmony_ci        return SkEncodeImageWithCG(dst, src, format);
42cb93a386Sopenharmony_ci    #elif SK_USE_WIC_ENCODER
43cb93a386Sopenharmony_ci        return SkEncodeImageWithWIC(dst, src, format, quality);
44cb93a386Sopenharmony_ci    #elif SK_ENABLE_NDK_IMAGES
45cb93a386Sopenharmony_ci        return SkEncodeImageWithNDK(dst, src, format, quality);
46cb93a386Sopenharmony_ci    #else
47cb93a386Sopenharmony_ci        switch(format) {
48cb93a386Sopenharmony_ci            case SkEncodedImageFormat::kJPEG: {
49cb93a386Sopenharmony_ci                SkJpegEncoder::Options opts;
50cb93a386Sopenharmony_ci                opts.fQuality = quality;
51cb93a386Sopenharmony_ci                return SkJpegEncoder::Encode(dst, src, opts);
52cb93a386Sopenharmony_ci            }
53cb93a386Sopenharmony_ci            case SkEncodedImageFormat::kPNG: {
54cb93a386Sopenharmony_ci                SkPngEncoder::Options opts;
55cb93a386Sopenharmony_ci                return SkPngEncoder::Encode(dst, src, opts);
56cb93a386Sopenharmony_ci            }
57cb93a386Sopenharmony_ci            case SkEncodedImageFormat::kWEBP: {
58cb93a386Sopenharmony_ci                SkWebpEncoder::Options opts;
59cb93a386Sopenharmony_ci                if (quality == 100) {
60cb93a386Sopenharmony_ci                    opts.fCompression = SkWebpEncoder::Compression::kLossless;
61cb93a386Sopenharmony_ci                    // Note: SkEncodeImage treats 0 quality as the lowest quality
62cb93a386Sopenharmony_ci                    // (greatest compression) and 100 as the highest quality (least
63cb93a386Sopenharmony_ci                    // compression). For kLossy, this matches libwebp's
64cb93a386Sopenharmony_ci                    // interpretation, so it is passed directly to libwebp. But
65cb93a386Sopenharmony_ci                    // with kLossless, libwebp always creates the highest quality
66cb93a386Sopenharmony_ci                    // image. In this case, fQuality is reinterpreted as how much
67cb93a386Sopenharmony_ci                    // effort (time) to put into making a smaller file. This API
68cb93a386Sopenharmony_ci                    // does not provide a way to specify this value (though it can
69cb93a386Sopenharmony_ci                    // be specified by using SkWebpEncoder::Encode) so we have to
70cb93a386Sopenharmony_ci                    // pick one arbitrarily. This value matches that chosen by
71cb93a386Sopenharmony_ci                    // blink::ImageEncoder::ComputeWebpOptions as well
72cb93a386Sopenharmony_ci                    // WebPConfigInit.
73cb93a386Sopenharmony_ci                    opts.fQuality = 75;
74cb93a386Sopenharmony_ci                } else {
75cb93a386Sopenharmony_ci                    opts.fCompression = SkWebpEncoder::Compression::kLossy;
76cb93a386Sopenharmony_ci                    opts.fQuality = quality;
77cb93a386Sopenharmony_ci                }
78cb93a386Sopenharmony_ci                return SkWebpEncoder::Encode(dst, src, opts);
79cb93a386Sopenharmony_ci            }
80cb93a386Sopenharmony_ci            default:
81cb93a386Sopenharmony_ci                return false;
82cb93a386Sopenharmony_ci        }
83cb93a386Sopenharmony_ci    #endif
84cb93a386Sopenharmony_ci}
85cb93a386Sopenharmony_ci
86cb93a386Sopenharmony_cibool SkEncoder::encodeRows(int numRows) {
87cb93a386Sopenharmony_ci    SkASSERT(numRows > 0 && fCurrRow < fSrc.height());
88cb93a386Sopenharmony_ci    if (numRows <= 0 || fCurrRow >= fSrc.height()) {
89cb93a386Sopenharmony_ci        return false;
90cb93a386Sopenharmony_ci    }
91cb93a386Sopenharmony_ci
92cb93a386Sopenharmony_ci    if (fCurrRow + numRows > fSrc.height()) {
93cb93a386Sopenharmony_ci        numRows = fSrc.height() - fCurrRow;
94cb93a386Sopenharmony_ci    }
95cb93a386Sopenharmony_ci
96cb93a386Sopenharmony_ci    if (!this->onEncodeRows(numRows)) {
97cb93a386Sopenharmony_ci        // If we fail, short circuit any future calls.
98cb93a386Sopenharmony_ci        fCurrRow = fSrc.height();
99cb93a386Sopenharmony_ci        return false;
100cb93a386Sopenharmony_ci    }
101cb93a386Sopenharmony_ci
102cb93a386Sopenharmony_ci    return true;
103cb93a386Sopenharmony_ci}
104cb93a386Sopenharmony_ci
105cb93a386Sopenharmony_cisk_sp<SkData> SkEncodePixmap(const SkPixmap& src, SkEncodedImageFormat format, int quality) {
106cb93a386Sopenharmony_ci    SkDynamicMemoryWStream stream;
107cb93a386Sopenharmony_ci    return SkEncodeImage(&stream, src, format, quality) ? stream.detachAsData() : nullptr;
108cb93a386Sopenharmony_ci}
109cb93a386Sopenharmony_ci
110cb93a386Sopenharmony_cisk_sp<SkData> SkEncodeBitmap(const SkBitmap& src, SkEncodedImageFormat format, int quality) {
111cb93a386Sopenharmony_ci    SkPixmap pixmap;
112cb93a386Sopenharmony_ci    return src.peekPixels(&pixmap) ? SkEncodePixmap(pixmap, format, quality) : nullptr;
113cb93a386Sopenharmony_ci}
114