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