xref: /aosp_15_r20/external/zopfli/src/zopflipng/lodepng/lodepng_util.h (revision e47783fd9ac7e78d0523d35be12ee382df490d63)
1 /*
2 LodePNG Utils
3 
4 Copyright (c) 2005-2020 Lode Vandevenne
5 
6 This software is provided 'as-is', without any express or implied
7 warranty. In no event will the authors be held liable for any damages
8 arising from the use of this software.
9 
10 Permission is granted to anyone to use this software for any purpose,
11 including commercial applications, and to alter it and redistribute it
12 freely, subject to the following restrictions:
13 
14     1. The origin of this software must not be misrepresented; you must not
15     claim that you wrote the original software. If you use this software
16     in a product, an acknowledgment in the product documentation would be
17     appreciated but is not required.
18 
19     2. Altered source versions must be plainly marked as such, and must not be
20     misrepresented as being the original software.
21 
22     3. This notice may not be removed or altered from any source
23     distribution.
24 */
25 
26 /*
27 Extra C++ utilities for LodePNG, for convenience.
28 Not part of the stable API of lodepng, more loose separate utils.
29 */
30 
31 #ifndef LODEPNG_UTIL_H
32 #define LODEPNG_UTIL_H
33 
34 #include <string>
35 #include <vector>
36 #include "lodepng.h"
37 
38 namespace lodepng {
39 
40 /*
41 Returns info from the header of the PNG by value, purely for convenience.
42 Does NOT check for errors. Returns bogus info if the PNG has an error.
43 Does not require cleanup of allocated memory because no palette or text chunk
44 info is in the LodePNGInfo object after checking only the header of the PNG.
45 */
46 LodePNGInfo getPNGHeaderInfo(const std::vector<unsigned char>& png);
47 
48 /*
49 Get the names and sizes of all chunks in the PNG file.
50 Returns 0 if ok, non-0 if error happened.
51 */
52 unsigned getChunkInfo(std::vector<std::string>& names, std::vector<size_t>& sizes,
53                       const std::vector<unsigned char>& png);
54 
55 /*
56 Returns the names and full chunks (including the name and everything else that
57 makes up the chunk) for all chunks except IHDR, PLTE, IDAT and IEND.
58 It separates the chunks into 3 separate lists, representing the chunks between
59 certain critical chunks: 0: IHDR-PLTE, 1: PLTE-IDAT, 2: IDAT-IEND
60 Returns 0 if ok, non-0 if error happened.
61 */
62 unsigned getChunks(std::vector<std::string> names[3],
63                    std::vector<std::vector<unsigned char> > chunks[3],
64                    const std::vector<unsigned char>& png);
65 
66 /*
67 Inserts chunks into the given png file. The chunks must be fully encoded,
68 including length, type, content and CRC.
69 The array index determines where it goes:
70 0: between IHDR and PLTE, 1: between PLTE and IDAT, 2: between IDAT and IEND.
71 They're appended at the end of those locations within the PNG.
72 Returns 0 if ok, non-0 if error happened.
73 */
74 unsigned insertChunks(std::vector<unsigned char>& png,
75                       const std::vector<std::vector<unsigned char> > chunks[3]);
76 
77 /*
78 Get the filtertypes of each scanline in this PNG file.
79 Returns 0 if ok, 1 if PNG decoding error happened.
80 
81 For a non-interlaced PNG, it returns one filtertype per scanline, in order.
82 
83 For interlaced PNGs, it returns a result as if it's not interlaced. It returns
84 one filtertype per scanline, in order. The values match pass 6 and 7 of the
85 Adam7 interlacing, alternating between the two, so that the values correspond
86 the most to their scanlines.
87 */
88 unsigned getFilterTypes(std::vector<unsigned char>& filterTypes, const std::vector<unsigned char>& png);
89 
90 /*
91 Get the filtertypes of each scanline in every interlace pass this PNG file.
92 Returns 0 if ok, 1 if PNG decoding error happened.
93 
94 For a non-interlaced PNG, it returns one filtertype per scanline, in order, in
95 a single std::vector in filterTypes.
96 
97 For an interlaced PNG, it returns 7 std::vectors in filterTypes, one for each
98 Adam7 pass. The amount of values per pass can be calculated as follows, where
99 w and h are the size of the image and all divisions are integer divisions:
100 pass 1: (h + 7) / 8
101 pass 2: w <= 4 ? 0 : (h + 7) / 8
102 pass 3: h <= 4 ? 0 : (h + 7) / 8
103 pass 4: w <= 2 ? 0 : (h + 3) / 4
104 pass 5: h <= 2 ? 0 : (h + 3) / 4
105 pass 6: w <= 1 ? 0 : (h + 1) / 2
106 pass 7: h <= 1 ? 0 : (h + 1) / 2
107 */
108 unsigned getFilterTypesInterlaced(std::vector<std::vector<unsigned char> >& filterTypes,
109                                   const std::vector<unsigned char>& png);
110 
111 /*
112 Returns the value of the i-th pixel in an image with 1, 2, 4 or 8-bit color.
113 E.g. if bits is 4 and i is 5, it returns the 5th nibble (4-bit group), which
114 is the second half of the 3th byte, in big endian (PNG's endian order).
115 */
116 int getPaletteValue(const unsigned char* data, size_t i, int bits);
117 
118 #ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
119 
120 /* Similar to convertRGBModel, but the 'to' model is sRGB. The pixel format
121 of in and out must be the same and is given by state_in->info_raw. An
122 error may occur if the pixel format cannot contain the new colors (e.g. palette) */
123 unsigned convertToSrgb(unsigned char* out, const unsigned char* in,
124                        unsigned w, unsigned h,
125                        const LodePNGState* state_in);
126 
127 /* Similar to convertRGBModel, but the 'from' model is sRGB. The pixel format
128 of in and out must be the same and is given by state_out->info_raw. An
129 error may occur if the pixel format cannot contain the new colors (e.g. palette) */
130 unsigned convertFromSrgb(unsigned char* out, const unsigned char* in,
131                          unsigned w, unsigned h,
132                          const LodePNGState* state_out);
133 
134 /*
135 Converts from one RGB model to another RGB model.
136 Similar to calling convertToXYZ followed by convertFromXYZ, but may be
137 more efficient and more precise (e.g. no computation needed when both models
138 are the same). See their documentation for more info.
139 
140 Parameters:
141 
142 *) out: output pixel data
143 *) in: input pixel data
144 *) w, h: image size
145 *) state_out: output RGB color model in state_out->info_png and byte format in state_out->info_raw.
146 *) state_in: output RGB color model in state_in->info_png and byte format in state_in->info_raw
147 *) return value: 0 if ok, positive value if error
148 *) rendering_intent: 1 for relative, 3 for absolute, should be relative for standard behavior.
149    See description at convertFromXYZ.
150 */
151 unsigned convertRGBModel(unsigned char* out, const unsigned char* in,
152                          unsigned w, unsigned h,
153                          const LodePNGState* state_out,
154                          const LodePNGState* state_in,
155                          unsigned rendering_intent);
156 
157 /*
158 Converts the RGB color to the absolute XYZ color space given the RGB color profile
159 chunks in the PNG info.
160 
161 Color space here refers to the different possible RGB spaces with different
162 possible chromaticities or whitepoint and XYZ color from colorimetry, not the
163 LodePNGColorType that describes the byte based encoding.
164 
165 You need this function only if the PNG could contain data in an arbitrary RGB
166 color space and you wish to output to a display or format that does not provide
167 color management for you (so you need to convert rather than pass on the profile
168 to it) but expects a certain RGB format (e.g. sRGB). See the background info below.
169 
170 Supports the gAMA, cHRM, sRGB and iCCP colorimetry chunks. If no colometry chunks are present
171 (that is, in state->info_png, the fields gama_defined, chrm_defined, srgb_defined and
172 iccp_defined are all 0), it assumes the format is sRGB.
173 For more information, see the chunk specifications in the PNG specification.
174 
175 Some background:
176 
177 A PNG image contains RGB data inside, but this data may use a specific RGB model (by default sRGB but
178 different if colorimetry chunks are given).
179 The computer display and/or operating system can have another RGB model (typically sRGB, or wider gamut
180 or HDR formats).
181 
182 The PNG chunks describe what format the data inside has, not the format of the display. To correctly
183 display a PNG image on a display, a conversion is needed from the PNG model to the display model if their
184 models differ. Some options to achieve that are:
185 *) If your use case already supports color management on its own, you can give it the RGB values straight from
186    the PNG image and give it the information from the cHRM, gAMA, sRGB and iCCP chunks (which you can find
187    in the LodePNGInfo), and the color management should then handle it correctly for you. You don't need
188    this function here in that case.
189 *) If your use case does not support color management, you may instead want to give it the RGB values in a
190    consistent color model, such as sRGB, but the PNG does not necessarily have it in this desired model.
191    In that case, use the function below (or a similar one from a CMS library if you prefer) to convert it to
192    the absolute color space XYZ, and then you can convert it to the target RGB with the counterpart convertFromXYZ
193    further below.
194 
195 Parameters:
196 
197 *) out: 4 floats per pixel, X,Y,Z,alpha color format, in range 0-1 (normally, not clipped if beyond), must
198    be allocated to have 4 * w * h floats available.
199 *) whitepoint: output argument, the whitepoint the original RGB data used, given in absolute XYZ. Needed for
200    relative rendering intents: give these values to counterpart function convertFromXYZ.
201 *) in: input RGB color, in byte format given by state->info_raw and RGB color profile given by info->info_png
202 *) w, h: image size
203 *) state (when using a LodePNG decode function that takes a LodePNGState parameter, can directly use that one):
204    state->info_png: PNG info with possibly an RGB color model in cHRM,gAMA and/or sRGB chunks
205    state->info_raw: byte format of in (amount of channels, bit depth)
206 *) return value: 0 if ok, positive value if error
207 */
208 unsigned convertToXYZ(float* out, float whitepoint[3],
209                       const unsigned char* in, unsigned w, unsigned h,
210                       const LodePNGState* state);
211 
212 /*
213 Same as convertToXYZ but takes floating point input. Slower.
214 The main black..white range in 0..1. Does not clip values that are outside that range.
215 */
216 unsigned convertToXYZFloat(float* out, float whitepoint[3], const float* in,
217                            unsigned w, unsigned h, const LodePNGState* state);
218 
219 /*
220 Converts XYZ to RGB in the RGB color model given by info and byte format by mode_out.
221 If info has no coloremtry chunks, converts to sRGB.
222 Parameters:
223 *) out: output color in byte format given by state->info_raw and RGB color profile given
224    by info->info_png. Must have enough bytes allocated to contain pixels in the given byte format.
225 *) in: 4 floats per pixel, X,Y,Z,alpha color format, in range 0-1 (normally).
226 *) whitepoint: input argument, the original whitepoint in absolute XYZ that the pixel data
227    in "in" had back when it was in a previous RGB space. Needed to preserve the whitepoint
228    in the new target RGB space for relative rendering intent.
229 *) rendering_intent: the desired rendering intent, with numeric meaning matching the
230    values used by ICC: 0=perceptual, 1=relative, 2=saturation, 3=absolute.
231    Should be 1 for normal use cases, it adapts white to match that of different RGB
232    models which is the best practice. Using 3 may change the color of white and may
233    turn grayscale into colors of a certain tone. Using 0 and 2 will have the same
234    effect as 1 because using those requires more data than the matrix-based RGB profiles
235    supporetd here have.
236 *) w, h: image size
237 *) state:
238    state->info_png: PNG info with possibly an RGB color profile in cHRM,gAMA and/or sRGB chunks
239    state->info_raw: byte format of out (amount of channels, bit depth)
240 *) return value: 0 if ok, positive value if error
241 */
242 unsigned convertFromXYZ(unsigned char* out, const float* in, unsigned w, unsigned h,
243                         const LodePNGState* state,
244                         const float whitepoint[3], unsigned rendering_intent);
245 
246 /*
247 Same as convertFromXYZ but outputs the RGB colors in floating point.
248 The main black..white range in 0..1. Does not clip values that are outside that range.
249 */
250 unsigned convertFromXYZFloat(float* out, const float* in, unsigned w, unsigned h,
251                              const LodePNGState* state,
252                              const float whitepoint[3], unsigned rendering_intent);
253 #endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
254 
255 /*
256 The information for extractZlibInfo.
257 */
258 struct ZlibBlockInfo {
259   int btype; //block type (0-2)
260   size_t compressedbits; //size of compressed block in bits
261   size_t uncompressedbytes; //size of uncompressed block in bytes
262 
263   // only filled in for block type 2
264   size_t treebits; //encoded tree size in bits
265   int hlit; //the HLIT value that was filled in for this tree
266   int hdist; //the HDIST value that was filled in for this tree
267   int hclen; //the HCLEN value that was filled in for this tree
268   std::vector<int> clcl; //19 code length code lengths (compressed tree's tree)
269   std::vector<int> treecodes; //N tree codes, with values 0-18. Values 17 or 18 are followed by the repetition value.
270   std::vector<int> litlenlengths; //288 code lengths for lit/len symbols
271   std::vector<int> distlengths; //32 code lengths for dist symbols
272 
273   // only filled in for block types 1 or 2
274   std::vector<int> lz77_lcode; //LZ77 codes. 0-255: literals. 256: end symbol. 257-285: length code of length/dist pairs
275   // the next vectors have the same size as lz77_lcode, but an element only has meaningful value if lz77_lcode contains a length code.
276   std::vector<int> lz77_dcode;
277   std::vector<int> lz77_lbits;
278   std::vector<int> lz77_dbits;
279   std::vector<int> lz77_lvalue;
280   std::vector<int> lz77_dvalue;
281   size_t numlit; //number of lit codes in this block
282   size_t numlen; //number of len codes in this block
283 };
284 
285 //Extracts all info needed from a PNG file to reconstruct the zlib compression exactly.
286 void extractZlibInfo(std::vector<ZlibBlockInfo>& zlibinfo, const std::vector<unsigned char>& in);
287 
288 } // namespace lodepng
289 
290 #endif /*LODEPNG_UTIL_H inclusion guard*/
291