File: png_codec.h

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (175 lines) | stat: -rw-r--r-- 7,157 bytes parent folder | download | duplicates (6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
// Copyright 2011 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef UI_GFX_CODEC_PNG_CODEC_H_
#define UI_GFX_CODEC_PNG_CODEC_H_

#include <stddef.h>

#include <string>
#include <vector>

#include "base/containers/span.h"
#include "ui/gfx/codec/codec_export.h"

class SkBitmap;

namespace gfx {

class Size;

// Interface for encoding and decoding PNG data. This is a wrapper around
// libpng, which has an inconvenient interface for callers. This is currently
// designed for use in tests only (where we control the files), so the handling
// isn't as robust as would be required for a browser (see Decode() for more).
// WebKit has its own more complicated PNG decoder which handles, among other
// things, partially downloaded data.
class CODEC_EXPORT PNGCodec {
 public:
  static constexpr int DEFAULT_ZLIB_COMPRESSION = 6;

  enum ColorFormat {
    // 4 bytes per pixel, in RGBA order in memory regardless of endianness.
    // Alpha is unpremultiplied, the same as what PNG uses.
    FORMAT_RGBA,

    // 4 bytes per pixel, in BGRA order in memory regardless of endianness.
    // Alpha is unpremultiplied, the same as what PNG uses.
    //
    // This is the default Windows DIB order.
    FORMAT_BGRA,

    // SkBitmap format. For Encode() kN32_SkColorType (4 bytes per pixel) and
    // kAlpha_8_SkColorType (1 byte per pixel) formats are supported.
    // kAlpha_8_SkColorType gets encoded into a grayscale PNG treating alpha as
    // the color intensity. For Decode() kN32_SkColorType is always used.
    //
    // When encoding from a SkBitmap (which implicitly chooses the
    // FORMAT_SkBitmap ColorFormat), this respects the input's alpha type:
    // kOpaque_SkAlphaType, kPremul_SkAlphaType or kUnpremul_SkAlphaType. For
    // premul input, the Encode callee will convert to PNG's unpremul.
    //
    // When encoding from a std::vector, passing FORMAT_SkBitmap treats the
    // pixel data as kN32_SkColorType and kPremul_SkAlphaType. Again, the
    // Encode callee will convert to PNG's unpremul.
    //
    // When decoding with FORMAT_SkBitmap (implicitly if passing a SkBitmap* to
    // Decode), the output SkBitmap or pixel data is kN32_SkColorType and
    // either kOpaque_SkAlphaType or kPremul_SkAlphaType, depending on whether
    // the source PNG image is opaque.
    //
    // FORMAT_SkBitmap prefers premultiplied alpha even though the PNG file
    // format (and other ColorFormat enum values) work with unpremultiplied
    // alpha. Per SkAlphaType documentation, premultiplied color components
    // improve performance.
    //
    // This implies that, for a kUnpremul_SkAlphaType input SkBitmap, a round
    // trip (encoding to PNG and decoding back via this file's functions) can
    // be lossy, even though PNG is a lossless format (in unpremultiplied alpha
    // space). The input can distinguish completely transparent red from
    // completely transparent black but the output will not.
    FORMAT_SkBitmap
  };

  // Represents a comment in the tEXt ancillary chunk of the png.
  struct CODEC_EXPORT Comment {
    Comment(const std::string& k, const std::string& t);
    ~Comment();

    std::string key;
    std::string text;
  };

  PNGCodec(const PNGCodec&) = delete;
  PNGCodec& operator=(const PNGCodec&) = delete;

  // Encodes the given raw `input` data, with each pixel being represented as
  // given in `format`.
  //
  // Returns the encoded data on success, or std::nullopt on failure.
  //
  // size: dimensions of the image
  //
  // row_byte_width: the width in bytes of each row. This may be greater than `w
  // * bytes_per_pixel` if there is extra padding at the end of each row (often,
  // each row is padded to the next machine word).
  //
  // discard_transparency: when true, and when the input data format includes
  // alpha values, these alpha values will be discarded and only RGB will be
  // written to the resulting file. Otherwise, alpha values in the input will be
  // preserved.
  //
  // comments: comments to be written in the png's metadata.
  //
  // TODO(https://crbug.com/371929522): This is a dangerous call, as it takes an
  // unsafe raw pointer and cannot be spanified. Most callers are actually
  // calling this with an SkBitmap that doesn't qualify for the other two
  // SkBitmap calls below. This method (and the two SkBitmap methods below)
  // should be removed, and a more general SkBitmap encoding method should be
  // added.
  static std::optional<std::vector<uint8_t>> Encode(
      const unsigned char* input,
      ColorFormat format,
      const Size& size,
      int row_byte_width,
      bool discard_transparency,
      const std::vector<Comment>& comments);

  // Call `PNGCodec::Encode` on the supplied SkBitmap `input`, which is assumed
  // to be `kN32_SkColorType`, 32 bits per pixel. The params
  // `discard_transparency` and `output` are passed directly to Encode(); refer
  // to Encode() for more information.
  static std::optional<std::vector<uint8_t>> EncodeBGRASkBitmap(
      const SkBitmap& input,
      bool discard_transparency);

  // Call `PNGCodec::Encode` on the supplied SkBitmap `input`. The difference
  // between this and the previous method is that this restricts compression to
  // zlib q1, which is just rle encoding.
  static std::optional<std::vector<uint8_t>> FastEncodeBGRASkBitmap(
      const SkBitmap& input,
      bool discard_transparency);

  // Decodes the PNG data contained in `input`.
  //
  // Returns the decoded data on success, or std::nullopt on failure. The output
  // data will be written in the format specified by the `format` parameter.
  //
  // This function may not support all PNG types, and it hasn't been tested
  // with a large number of images, so assume a new format may not work. It's
  // really designed to be able to read in something written by Encode() above.
  //
  // TODO(https://crbug.com/371926662): There are few callers; remove.
  struct CODEC_EXPORT DecodeOutput {
    DecodeOutput();

    // Move-only type to intentionally prevent large copies.
    DecodeOutput(const DecodeOutput& other) = delete;
    DecodeOutput& operator=(const DecodeOutput& other) = delete;
    DecodeOutput(DecodeOutput&& other);
    DecodeOutput& operator=(DecodeOutput&& other);

    ~DecodeOutput();

    std::vector<uint8_t> output;
    int width = 0;
    int height = 0;
  };
  static std::optional<DecodeOutput> Decode(base::span<const uint8_t> input,
                                            ColorFormat format);

  // Decodes the PNG data directly into an SkBitmap. This is significantly
  // faster than the vector<uint8_t> version of Decode() above when dealing with
  // PNG files that are >500K, which a lot of theme images are. (There are a lot
  // of themes that have a NTP image of about ~1 megabyte, and those require a
  // 7-10 megabyte side buffer.)
  //
  // Returns a valid SkBitmap if the data can be decoded as a PNG, and a null
  // SkBitmap otherwise.
  static SkBitmap Decode(base::span<const uint8_t> input);
};

}  // namespace gfx

#endif  // UI_GFX_CODEC_PNG_CODEC_H_