blob: d5cf2ec62309311df3ce14844cfea9613639078c [file] [log] [blame]
reed@android.comb08eb2b2009-01-06 20:16:26 +00001/*
epoger@google.comec3ed6a2011-07-28 14:26:00 +00002 * Copyright 2009 The Android Open Source Project
reed@android.comb08eb2b2009-01-06 20:16:26 +00003 *
epoger@google.comec3ed6a2011-07-28 14:26:00 +00004 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
reed@android.comb08eb2b2009-01-06 20:16:26 +00006 */
7
Hal Canarydb683012016-11-23 08:55:18 -07008#include "SkImageEncoderPriv.h"
Matt Sarett26b44df2017-05-02 16:04:56 -04009#include "SkJpegEncoder.h"
Matt Sarettc367d032017-05-05 11:13:26 -040010#include "SkPngEncoder.h"
Matt Sarett04c37312017-05-05 14:02:13 -040011#include "SkWebpEncoder.h"
reed@android.comb08eb2b2009-01-06 20:16:26 +000012
Matt Sarett22469d92017-05-05 15:40:05 -040013#ifndef SK_HAS_JPEG_LIBRARY
14bool SkJpegEncoder::Encode(SkWStream*, const SkPixmap&, const Options&) { return false; }
Matt Sarette6c210a2017-05-11 17:39:04 -040015std::unique_ptr<SkEncoder> SkJpegEncoder::Make(SkWStream*, const SkPixmap&, const Options&) {
Matt Sarett22469d92017-05-05 15:40:05 -040016 return nullptr;
17}
18#endif
19
20#ifndef SK_HAS_PNG_LIBRARY
21bool SkPngEncoder::Encode(SkWStream*, const SkPixmap&, const Options&) { return false; }
Matt Sarette6c210a2017-05-11 17:39:04 -040022std::unique_ptr<SkEncoder> SkPngEncoder::Make(SkWStream*, const SkPixmap&, const Options&) {
Matt Sarett22469d92017-05-05 15:40:05 -040023 return nullptr;
24}
25#endif
26
27#ifndef SK_HAS_WEBP_LIBRARY
28bool SkWebpEncoder::Encode(SkWStream*, const SkPixmap&, const Options&) { return false; }
29#endif
30
Hal Canarydb683012016-11-23 08:55:18 -070031bool SkEncodeImage(SkWStream* dst, const SkPixmap& src,
32 SkEncodedImageFormat format, int quality) {
Hal Canary1fcc4042016-11-30 17:07:59 -050033 #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) {
Matt Sarett26b44df2017-05-02 16:04:56 -040040 case SkEncodedImageFormat::kJPEG: {
41 SkJpegEncoder::Options opts;
42 opts.fQuality = quality;
43 return SkJpegEncoder::Encode(dst, src, opts);
44 }
Matt Sarettc367d032017-05-05 11:13:26 -040045 case SkEncodedImageFormat::kPNG: {
46 SkPngEncoder::Options opts;
Matt Sarettc367d032017-05-05 11:13:26 -040047 return SkPngEncoder::Encode(dst, src, opts);
48 }
Matt Sarett04c37312017-05-05 14:02:13 -040049 case SkEncodedImageFormat::kWEBP: {
50 SkWebpEncoder::Options opts;
Leon Scroggins IIIe7f165b2018-12-10 10:29:18 -050051 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 }
Matt Sarett04c37312017-05-05 14:02:13 -040070 return SkWebpEncoder::Encode(dst, src, opts);
71 }
Matt Sarett84014f02017-01-10 11:28:54 -050072 default:
73 return false;
Hal Canary1fcc4042016-11-30 17:07:59 -050074 }
75 #endif
reed53b9e2e2014-12-19 12:26:07 -080076}
Matt Sarettc367d032017-05-05 11:13:26 -040077
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}
Mike Reed25eef6b2017-12-08 16:20:58 -050096
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}