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