1/*
2 * Copyright 2017 Google Inc.
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#ifndef SkPngEncoder_DEFINED
9#define SkPngEncoder_DEFINED
10
11#include "SkEncoder.h"
12#include "SkDataTable.h"
13
14class SkPngEncoderMgr;
15class SkWStream;
16
17class SK_API SkPngEncoder : public SkEncoder {
18public:
19
20    enum class FilterFlag : int {
21        kZero  = 0x00,
22        kNone  = 0x08,
23        kSub   = 0x10,
24        kUp    = 0x20,
25        kAvg   = 0x40,
26        kPaeth = 0x80,
27        kAll   = kNone | kSub | kUp | kAvg | kPaeth,
28    };
29
30    struct Options {
31        /**
32         *  Selects which filtering strategies to use.
33         *
34         *  If a single filter is chosen, libpng will use that filter for every row.
35         *
36         *  If multiple filters are chosen, libpng will use a heuristic to guess which filter
37         *  will encode smallest, then apply that filter.  This happens on a per row basis,
38         *  different rows can use different filters.
39         *
40         *  Using a single filter (or less filters) is typically faster.  Trying all of the
41         *  filters may help minimize the output file size.
42         *
43         *  Our default value matches libpng's default.
44         */
45        FilterFlag fFilterFlags = FilterFlag::kAll;
46
47        /**
48         *  Must be in [0, 9] where 9 corresponds to maximal compression.  This value is passed
49         *  directly to zlib.  0 is a special case to skip zlib entirely, creating dramatically
50         *  larger pngs.
51         *
52         *  Our default value matches libpng's default.
53         */
54        int fZLibLevel = 6;
55
56        /**
57         *  If the input is premultiplied, this controls the unpremultiplication behavior.
58         *  The encoder can convert to linear before unpremultiplying or ignore the transfer
59         *  function and unpremultiply the input as is.
60         */
61        SkTransferFunctionBehavior fUnpremulBehavior = SkTransferFunctionBehavior::kRespect;
62
63        /**
64         *  Represents comments in the tEXt ancillary chunk of the png.
65         *  The 2i-th entry is the keyword for the i-th comment,
66         *  and the (2i + 1)-th entry is the text for the i-th comment.
67         */
68        sk_sp<SkDataTable> fComments;
69    };
70
71    /**
72     *  Encode the |src| pixels to the |dst| stream.
73     *  |options| may be used to control the encoding behavior.
74     *
75     *  Returns true on success.  Returns false on an invalid or unsupported |src|.
76     */
77    static bool Encode(SkWStream* dst, const SkPixmap& src, const Options& options);
78
79    /**
80     *  Create a png encoder that will encode the |src| pixels to the |dst| stream.
81     *  |options| may be used to control the encoding behavior.
82     *
83     *  |dst| is unowned but must remain valid for the lifetime of the object.
84     *
85     *  This returns nullptr on an invalid or unsupported |src|.
86     */
87    static std::unique_ptr<SkEncoder> Make(SkWStream* dst, const SkPixmap& src,
88                                           const Options& options);
89
90    ~SkPngEncoder() override;
91
92protected:
93    bool onEncodeRows(int numRows) override;
94
95    SkPngEncoder(std::unique_ptr<SkPngEncoderMgr>, const SkPixmap& src);
96
97    std::unique_ptr<SkPngEncoderMgr> fEncoderMgr;
98    typedef SkEncoder INHERITED;
99};
100
101static inline SkPngEncoder::FilterFlag operator|(SkPngEncoder::FilterFlag x,
102                                                 SkPngEncoder::FilterFlag y) {
103    return (SkPngEncoder::FilterFlag)((int)x | (int)y);
104}
105
106#endif
107