TazGraph Project v0.1.0
Loading...
Searching...
No Matches
picoPNG.h
1#pragma once
2
3#include <vector>
4
5/*
6decodePNG: The picoPNG function, decodes a PNG file buffer in memory, into a raw pixel buffer.
7out_image: output parameter, this will contain the raw pixels after decoding.
8 By default the output is 32-bit RGBA color.
9 The std::vector is automatically resized to the correct size.
10image_width: output_parameter, this will contain the width of the image in pixels.
11image_height: output_parameter, this will contain the height of the image in pixels.
12in_png: pointer to the buffer of the PNG file in memory. To get it from a file on
13 disk, load it and store it in a memory buffer yourself first.
14in_size: size of the input PNG file in bytes.
15convert_to_rgba32: optional parameter, true by default.
16 Set to true to get the output in RGBA 32-bit (8 bit per channel) color format
17 no matter what color type the original PNG image had. This gives predictable,
18 useable data from any random input PNG.
19 Set to false to do no color conversion at all. The result then has the same data
20 type as the PNG image, which can range from 1 bit to 64 bits per pixel.
21 Information about the color type or palette colors are not provided. You need
22 to know this information yourself to be able to use the data so this only
23 works for trusted PNG files. Use LodePNG instead of picoPNG if you need this information.
24return: 0 if success, not 0 if some error occured.
25*/
26int decodePNG(std::vector<unsigned char>& out_image, unsigned long& image_width, unsigned long& image_height, const unsigned char* in_png, size_t in_size, bool convert_to_rgba32)
27{
28 // picoPNG version 20101224
29 // Copyright (c) 2005-2010 Lode Vandevenne
30 //
31 // This software is provided 'as-is', without any express or implied
32 // warranty. In no event will the authors be held liable for any damages
33 // arising from the use of this software.
34 //
35 // Permission is granted to anyone to use this software for any purpose,
36 // including commercial applications, and to alter it and redistribute it
37 // freely, subject to the following restrictions:
38 //
39 // 1. The origin of this software must not be misrepresented; you must not
40 // claim that you wrote the original software. If you use this software
41 // in a product, an acknowledgment in the product documentation would be
42 // appreciated but is not required.
43 // 2. Altered source versions must be plainly marked as such, and must not be
44 // misrepresented as being the original software.
45 // 3. This notice may not be removed or altered from any source distribution.
46
47 // picoPNG is a PNG decoder in one C++ function of around 500 lines. Use picoPNG for
48 // programs that need only 1 .cpp file. Since it's a single function, it's very limited,
49 // it can convert a PNG to raw pixel data either converted to 32-bit RGBA color or
50 // with no color conversion at all. For anything more complex, another tiny library
51 // is available: LodePNG (lodepng.c(pp)), which is a single source and header file.
52 // Apologies for the compact code style, it's to make this tiny.
53
54 static const unsigned long LENBASE[29] = { 3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258 };
55 static const unsigned long LENEXTRA[29] = { 0,0,0,0,0,0,0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0 };
56 static const unsigned long DISTBASE[30] = { 1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577 };
57 static const unsigned long DISTEXTRA[30] = { 0,0,0,0,1,1,2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13 };
58 static const unsigned long CLCL[19] = { 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 }; //code length code lengths
59 struct Zlib //nested functions for zlib decompression
60 {
61 static unsigned long readBitFromStream(size_t& bitp, const unsigned char* bits) { unsigned long result = (bits[bitp >> 3] >> (bitp & 0x7)) & 1; bitp++; return result; }
62 static unsigned long readBitsFromStream(size_t& bitp, const unsigned char* bits, size_t nbits)
63 {
64 unsigned long result = 0;
65 for (size_t i = 0; i < nbits; i++) result += (readBitFromStream(bitp, bits)) << i;
66 return result;
67 }
68 struct HuffmanTree
69 {
70 int makeFromLengths(const std::vector<unsigned long>& bitlen, unsigned long maxbitlen)
71 { //make tree given the lengths
72 unsigned long numcodes = (unsigned long)(bitlen.size()), treepos = 0, nodefilled = 0;
73 std::vector<unsigned long> tree1d(numcodes), blcount(maxbitlen + 1, 0), nextcode(maxbitlen + 1, 0);
74 for (unsigned long bits = 0; bits < numcodes; bits++) blcount[bitlen[bits]]++; //count number of instances of each code length
75 for (unsigned long bits = 1; bits <= maxbitlen; bits++) nextcode[bits] = (nextcode[bits - 1] + blcount[bits - 1]) << 1;
76 for (unsigned long n = 0; n < numcodes; n++) if (bitlen[n] != 0) tree1d[n] = nextcode[bitlen[n]]++; //generate all the codes
77 tree2d.clear(); tree2d.resize(numcodes * 2, 32767); //32767 here means the tree2d isn't filled there yet
78 for (unsigned long n = 0; n < numcodes; n++) //the codes
79 for (unsigned long i = 0; i < bitlen[n]; i++) //the bits for this code
80 {
81 unsigned long bit = (tree1d[n] >> (bitlen[n] - i - 1)) & 1;
82 if (treepos > numcodes - 2) return 55;
83 if (tree2d[2 * treepos + bit] == 32767) //not yet filled in
84 {
85 if (i + 1 == bitlen[n]) { tree2d[2 * treepos + bit] = n; treepos = 0; } //last bit
86 else { tree2d[2 * treepos + bit] = ++nodefilled + numcodes; treepos = nodefilled; } //addresses are encoded as values > numcodes
87 }
88 else treepos = tree2d[2 * treepos + bit] - numcodes; //subtract numcodes from address to get address value
89 }
90 return 0;
91 }
92 int decode(bool& decoded, unsigned long& result, size_t& treepos, unsigned long bit) const
93 { //Decodes a symbol from the tree
94 unsigned long numcodes = (unsigned long)tree2d.size() / 2;
95 if (treepos >= numcodes) return 11; //error: you appeared outside the codetree
96 result = tree2d[2 * treepos + bit];
97 decoded = (result < numcodes);
98 treepos = decoded ? 0 : result - numcodes;
99 return 0;
100 }
101 std::vector<unsigned long> tree2d; //2D representation of a huffman tree: The one dimension is "0" or "1", the other contains all nodes and leaves of the tree.
102 };
103 struct Inflator
104 {
105 int error;
106 void inflate(std::vector<unsigned char>& out, const std::vector<unsigned char>& in, size_t inpos = 0)
107 {
108 size_t bp = 0, pos = 0; //bit pointer and byte pointer
109 error = 0;
110 unsigned long BFINAL = 0;
111 while (!BFINAL && !error)
112 {
113 if (bp >> 3 >= in.size()) { error = 52; return; } //error, bit pointer will jump past memory
114 BFINAL = readBitFromStream(bp, &in[inpos]);
115 unsigned long BTYPE = readBitFromStream(bp, &in[inpos]); BTYPE += 2 * readBitFromStream(bp, &in[inpos]);
116 if (BTYPE == 3) { error = 20; return; } //error: invalid BTYPE
117 else if (BTYPE == 0) inflateNoCompression(out, &in[inpos], bp, pos, in.size());
118 else inflateHuffmanBlock(out, &in[inpos], bp, pos, in.size(), BTYPE);
119 }
120 if (!error) out.resize(pos); //Only now we know the true size of out, resize it to that
121 }
122 void generateFixedTrees(HuffmanTree& tree, HuffmanTree& treeD) //get the tree of a deflated block with fixed tree
123 {
124 std::vector<unsigned long> bitlen(288, 8), bitlenD(32, 5);;
125 for (size_t i = 144; i <= 255; i++) bitlen[i] = 9;
126 for (size_t i = 256; i <= 279; i++) bitlen[i] = 7;
127 tree.makeFromLengths(bitlen, 15);
128 treeD.makeFromLengths(bitlenD, 15);
129 }
130 HuffmanTree codetree, codetreeD, codelengthcodetree; //the code tree for Huffman codes, dist codes, and code length codes
131 unsigned long huffmanDecodeSymbol(const unsigned char* in, size_t& bp, const HuffmanTree& codetree, size_t inlength)
132 { //decode a single symbol from given list of bits with given code tree. return value is the symbol
133 bool decoded; unsigned long ct;
134 for (size_t treepos = 0;;)
135 {
136 if ((bp & 0x07) == 0 && (bp >> 3) > inlength) { error = 10; return 0; } //error: end reached without endcode
137 error = codetree.decode(decoded, ct, treepos, readBitFromStream(bp, in)); if (error) return 0; //stop, an error happened
138 if (decoded) return ct;
139 }
140 }
141 void getTreeInflateDynamic(HuffmanTree& tree, HuffmanTree& treeD, const unsigned char* in, size_t& bp, size_t inlength)
142 { //get the tree of a deflated block with dynamic tree, the tree itself is also Huffman compressed with a known tree
143 std::vector<unsigned long> bitlen(288, 0), bitlenD(32, 0);
144 if (bp >> 3 >= inlength - 2) { error = 49; return; } //the bit pointer is or will go past the memory
145 size_t HLIT = readBitsFromStream(bp, in, 5) + 257; //number of literal/length codes + 257
146 size_t HDIST = readBitsFromStream(bp, in, 5) + 1; //number of dist codes + 1
147 size_t HCLEN = readBitsFromStream(bp, in, 4) + 4; //number of code length codes + 4
148 std::vector<unsigned long> codelengthcode(19); //lengths of tree to decode the lengths of the dynamic tree
149 for (size_t i = 0; i < 19; i++) codelengthcode[CLCL[i]] = (i < HCLEN) ? readBitsFromStream(bp, in, 3) : 0;
150 error = codelengthcodetree.makeFromLengths(codelengthcode, 7); if (error) return;
151 size_t i = 0, replength;
152 while (i < HLIT + HDIST)
153 {
154 unsigned long code = huffmanDecodeSymbol(in, bp, codelengthcodetree, inlength); if (error) return;
155 if (code <= 15) { if (i < HLIT) bitlen[i++] = code; else bitlenD[i++ - HLIT] = code; } //a length code
156 else if (code == 16) //repeat previous
157 {
158 if (bp >> 3 >= inlength) { error = 50; return; } //error, bit pointer jumps past memory
159 replength = 3 + readBitsFromStream(bp, in, 2);
160 unsigned long value; //set value to the previous code
161 if ((i - 1) < HLIT) value = bitlen[i - 1];
162 else value = bitlenD[i - HLIT - 1];
163 for (size_t n = 0; n < replength; n++) //repeat this value in the next lengths
164 {
165 if (i >= HLIT + HDIST) { error = 13; return; } //error: i is larger than the amount of codes
166 if (i < HLIT) bitlen[i++] = value; else bitlenD[i++ - HLIT] = value;
167 }
168 }
169 else if (code == 17) //repeat "0" 3-10 times
170 {
171 if (bp >> 3 >= inlength) { error = 50; return; } //error, bit pointer jumps past memory
172 replength = 3 + readBitsFromStream(bp, in, 3);
173 for (size_t n = 0; n < replength; n++) //repeat this value in the next lengths
174 {
175 if (i >= HLIT + HDIST) { error = 14; return; } //error: i is larger than the amount of codes
176 if (i < HLIT) bitlen[i++] = 0; else bitlenD[i++ - HLIT] = 0;
177 }
178 }
179 else if (code == 18) //repeat "0" 11-138 times
180 {
181 if (bp >> 3 >= inlength) { error = 50; return; } //error, bit pointer jumps past memory
182 replength = 11 + readBitsFromStream(bp, in, 7);
183 for (size_t n = 0; n < replength; n++) //repeat this value in the next lengths
184 {
185 if (i >= HLIT + HDIST) { error = 15; return; } //error: i is larger than the amount of codes
186 if (i < HLIT) bitlen[i++] = 0; else bitlenD[i++ - HLIT] = 0;
187 }
188 }
189 else { error = 16; return; } //error: somehow an unexisting code appeared. This can never happen.
190 }
191 if (bitlen[256] == 0) { error = 64; return; } //the length of the end code 256 must be larger than 0
192 error = tree.makeFromLengths(bitlen, 15); if (error) return; //now we've finally got HLIT and HDIST, so generate the code trees, and the function is done
193 error = treeD.makeFromLengths(bitlenD, 15); if (error) return;
194 }
195 void inflateHuffmanBlock(std::vector<unsigned char>& out, const unsigned char* in, size_t& bp, size_t& pos, size_t inlength, unsigned long btype)
196 {
197 if (btype == 1) { generateFixedTrees(codetree, codetreeD); }
198 else if (btype == 2) { getTreeInflateDynamic(codetree, codetreeD, in, bp, inlength); if (error) return; }
199 for (;;)
200 {
201 unsigned long code = huffmanDecodeSymbol(in, bp, codetree, inlength); if (error) return;
202 if (code == 256) return; //end code
203 else if (code <= 255) //literal symbol
204 {
205 if (pos >= out.size()) out.resize((pos + 1) * 2); //reserve more room
206 out[pos++] = (unsigned char)(code);
207 }
208 else if (code >= 257 && code <= 285) //length code
209 {
210 size_t length = LENBASE[code - 257], numextrabits = LENEXTRA[code - 257];
211 if ((bp >> 3) >= inlength) { error = 51; return; } //error, bit pointer will jump past memory
212 length += readBitsFromStream(bp, in, numextrabits);
213 unsigned long codeD = huffmanDecodeSymbol(in, bp, codetreeD, inlength); if (error) return;
214 if (codeD > 29) { error = 18; return; } //error: invalid dist code (30-31 are never used)
215 unsigned long dist = DISTBASE[codeD], numextrabitsD = DISTEXTRA[codeD];
216 if ((bp >> 3) >= inlength) { error = 51; return; } //error, bit pointer will jump past memory
217 dist += readBitsFromStream(bp, in, numextrabitsD);
218 size_t start = pos, back = start - dist; //backwards
219 if (pos + length >= out.size()) out.resize((pos + length) * 2); //reserve more room
220 for (size_t i = 0; i < length; i++) { out[pos++] = out[back++]; if (back >= start) back = start - dist; }
221 }
222 }
223 }
224 void inflateNoCompression(std::vector<unsigned char>& out, const unsigned char* in, size_t& bp, size_t& pos, size_t inlength)
225 {
226 while ((bp & 0x7) != 0) bp++; //go to first boundary of byte
227 size_t p = bp / 8;
228 if (p >= inlength - 4) { error = 52; return; } //error, bit pointer will jump past memory
229 unsigned long LEN = in[p] + 256 * in[p + 1], NLEN = in[p + 2] + 256 * in[p + 3]; p += 4;
230 if (LEN + NLEN != 65535) { error = 21; return; } //error: NLEN is not one's complement of LEN
231 if (pos + LEN >= out.size()) out.resize(pos + LEN);
232 if (p + LEN > inlength) { error = 23; return; } //error: reading outside of in buffer
233 for (unsigned long n = 0; n < LEN; n++) out[pos++] = in[p++]; //read LEN bytes of literal data
234 bp = p * 8;
235 }
236 };
237 int decompress(std::vector<unsigned char>& out, const std::vector<unsigned char>& in) //returns error value
238 {
239 Inflator inflator;
240 if (in.size() < 2) { return 53; } //error, size of zlib data too small
241 if ((in[0] * 256 + in[1]) % 31 != 0) { return 24; } //error: 256 * in[0] + in[1] must be a multiple of 31, the FCHECK value is supposed to be made that way
242 unsigned long CM = in[0] & 15, CINFO = (in[0] >> 4) & 15, FDICT = (in[1] >> 5) & 1;
243 if (CM != 8 || CINFO > 7) { return 25; } //error: only compression method 8: inflate with sliding window of 32k is supported by the PNG spec
244 if (FDICT != 0) { return 26; } //error: the specification of PNG says about the zlib stream: "The additional flags shall not specify a preset dictionary."
245 inflator.inflate(out, in, 2);
246 return inflator.error; //note: adler32 checksum was skipped and ignored
247 }
248 };
249 struct PNG //nested functions for PNG decoding
250 {
251 struct Info
252 {
253 unsigned long width, height, colorType, bitDepth, compressionMethod, filterMethod, interlaceMethod, key_r, key_g, key_b;
254 bool key_defined; //is a transparent color key given?
255 std::vector<unsigned char> palette;
256 } info;
257 int error;
258 void decode(std::vector<unsigned char>& out, const unsigned char* in, size_t size, bool convert_to_rgba32)
259 {
260 error = 0;
261 if (size == 0 || in == 0) { error = 48; return; } //the given data is empty
262 readPngHeader(&in[0], size); if (error) return;
263 size_t pos = 33; //first byte of the first chunk after the header
264 std::vector<unsigned char> idat; //the data from idat chunks
265 bool IEND = false, known_type = true;
266 info.key_defined = false;
267 while (!IEND) //loop through the chunks, ignoring unknown chunks and stopping at IEND chunk. IDAT data is put at the start of the in buffer
268 {
269 if (pos + 8 >= size) { error = 30; return; } //error: size of the in buffer too small to contain next chunk
270 size_t chunkLength = read32bitInt(&in[pos]); pos += 4;
271 if (chunkLength > 2147483647) { error = 63; return; }
272 if (pos + chunkLength >= size) { error = 35; return; } //error: size of the in buffer too small to contain next chunk
273 if (in[pos + 0] == 'I' && in[pos + 1] == 'D' && in[pos + 2] == 'A' && in[pos + 3] == 'T') //IDAT chunk, containing compressed image data
274 {
275 idat.insert(idat.end(), &in[pos + 4], &in[pos + 4 + chunkLength]);
276 pos += (4 + chunkLength);
277 }
278 else if (in[pos + 0] == 'I' && in[pos + 1] == 'E' && in[pos + 2] == 'N' && in[pos + 3] == 'D') { pos += 4; IEND = true; }
279 else if (in[pos + 0] == 'P' && in[pos + 1] == 'L' && in[pos + 2] == 'T' && in[pos + 3] == 'E') //palette chunk (PLTE)
280 {
281 pos += 4; //go after the 4 letters
282 info.palette.resize(4 * (chunkLength / 3));
283 if (info.palette.size() > (4 * 256)) { error = 38; return; } //error: palette too big
284 for (size_t i = 0; i < info.palette.size(); i += 4)
285 {
286 for (size_t j = 0; j < 3; j++) info.palette[i + j] = in[pos++]; //RGB
287 info.palette[i + 3] = 255; //alpha
288 }
289 }
290 else if (in[pos + 0] == 't' && in[pos + 1] == 'R' && in[pos + 2] == 'N' && in[pos + 3] == 'S') //palette transparency chunk (tRNS)
291 {
292 pos += 4; //go after the 4 letters
293 if (info.colorType == 3)
294 {
295 if (4 * chunkLength > info.palette.size()) { error = 39; return; } //error: more alpha values given than there are palette entries
296 for (size_t i = 0; i < chunkLength; i++) info.palette[4 * i + 3] = in[pos++];
297 }
298 else if (info.colorType == 0)
299 {
300 if (chunkLength != 2) { error = 40; return; } //error: this chunk must be 2 bytes for greyscale image
301 info.key_defined = 1; info.key_r = info.key_g = info.key_b = 256 * in[pos] + in[pos + 1]; pos += 2;
302 }
303 else if (info.colorType == 2)
304 {
305 if (chunkLength != 6) { error = 41; return; } //error: this chunk must be 6 bytes for RGB image
306 info.key_defined = 1;
307 info.key_r = 256 * in[pos] + in[pos + 1]; pos += 2;
308 info.key_g = 256 * in[pos] + in[pos + 1]; pos += 2;
309 info.key_b = 256 * in[pos] + in[pos + 1]; pos += 2;
310 }
311 else { error = 42; return; } //error: tRNS chunk not allowed for other color models
312 }
313 else //it's not an implemented chunk type, so ignore it: skip over the data
314 {
315 if (!(in[pos + 0] & 32)) { error = 69; return; } //error: unknown critical chunk (5th bit of first byte of chunk type is 0)
316 pos += (chunkLength + 4); //skip 4 letters and uninterpreted data of unimplemented chunk
317 known_type = false;
318 }
319 pos += 4; //step over CRC (which is ignored)
320 }
321 unsigned long bpp = getBpp(info);
322 std::vector<unsigned char> scanlines(((info.width * (info.height * bpp + 7)) / 8) + info.height); //now the out buffer will be filled
323 Zlib zlib; //decompress with the Zlib decompressor
324 error = zlib.decompress(scanlines, idat); if (error) return; //stop if the zlib decompressor returned an error
325 size_t bytewidth = (bpp + 7) / 8, outlength = (info.height * info.width * bpp + 7) / 8;
326 out.resize(outlength); //time to fill the out buffer
327 unsigned char* out_ = outlength ? &out[0] : 0; //use a regular pointer to the std::vector for faster code if compiled without optimization
328 if (info.interlaceMethod == 0) //no interlace, just filter
329 {
330 size_t linestart = 0, linelength = (info.width * bpp + 7) / 8; //length in bytes of a scanline, excluding the filtertype byte
331 if (bpp >= 8) //byte per byte
332 for (unsigned long y = 0; y < info.height; y++)
333 {
334 unsigned long filterType = scanlines[linestart];
335 const unsigned char* prevline = (y == 0) ? 0 : &out_[(y - 1) * info.width * bytewidth];
336 unFilterScanline(&out_[linestart - y], &scanlines[linestart + 1], prevline, bytewidth, filterType, linelength); if (error) return;
337 linestart += (1 + linelength); //go to start of next scanline
338 }
339 else //less than 8 bits per pixel, so fill it up bit per bit
340 {
341 std::vector<unsigned char> templine((info.width * bpp + 7) >> 3); //only used if bpp < 8
342 for (size_t y = 0, obp = 0; y < info.height; y++)
343 {
344 unsigned long filterType = scanlines[linestart];
345 const unsigned char* prevline = (y == 0) ? 0 : &out_[(y - 1) * info.width * bytewidth];
346 unFilterScanline(&templine[0], &scanlines[linestart + 1], prevline, bytewidth, filterType, linelength); if (error) return;
347 for (size_t bp = 0; bp < info.width * bpp;) setBitOfReversedStream(obp, out_, readBitFromReversedStream(bp, &templine[0]));
348 linestart += (1 + linelength); //go to start of next scanline
349 }
350 }
351 }
352 else //interlaceMethod is 1 (Adam7)
353 {
354 size_t passw[7] = { (info.width + 7) / 8, (info.width + 3) / 8, (info.width + 3) / 4, (info.width + 1) / 4, (info.width + 1) / 2, (info.width + 0) / 2, (info.width + 0) / 1 };
355 size_t passh[7] = { (info.height + 7) / 8, (info.height + 7) / 8, (info.height + 3) / 8, (info.height + 3) / 4, (info.height + 1) / 4, (info.height + 1) / 2, (info.height + 0) / 2 };
356 size_t passstart[7] = { 0 };
357 size_t pattern[28] = { 0,4,0,2,0,1,0,0,0,4,0,2,0,1,8,8,4,4,2,2,1,8,8,8,4,4,2,2 }; //values for the adam7 passes
358 for (int i = 0; i < 6; i++) passstart[i + 1] = passstart[i] + passh[i] * ((passw[i] ? 1 : 0) + (passw[i] * bpp + 7) / 8);
359 std::vector<unsigned char> scanlineo((info.width * bpp + 7) / 8), scanlinen((info.width * bpp + 7) / 8); //"old" and "new" scanline
360 for (int i = 0; i < 7; i++)
361 adam7Pass(&out_[0], &scanlinen[0], &scanlineo[0], &scanlines[passstart[i]], info.width, pattern[i], pattern[i + 7], pattern[i + 14], pattern[i + 21], passw[i], passh[i], bpp);
362 }
363 if (convert_to_rgba32 && (info.colorType != 6 || info.bitDepth != 8)) //conversion needed
364 {
365 std::vector<unsigned char> data = out;
366 error = convert(out, &data[0], info, info.width, info.height);
367 }
368 }
369 void readPngHeader(const unsigned char* in, size_t inlength) //read the information from the header and store it in the Info
370 {
371 if (inlength < 29) { error = 27; return; } //error: the data length is smaller than the length of the header
372 if (in[0] != 137 || in[1] != 80 || in[2] != 78 || in[3] != 71 || in[4] != 13 || in[5] != 10 || in[6] != 26 || in[7] != 10) { error = 28; return; } //no PNG signature
373 if (in[12] != 'I' || in[13] != 'H' || in[14] != 'D' || in[15] != 'R') { error = 29; return; } //error: it doesn't start with a IHDR chunk!
374 info.width = read32bitInt(&in[16]); info.height = read32bitInt(&in[20]);
375 info.bitDepth = in[24]; info.colorType = in[25];
376 info.compressionMethod = in[26]; if (in[26] != 0) { error = 32; return; } //error: only compression method 0 is allowed in the specification
377 info.filterMethod = in[27]; if (in[27] != 0) { error = 33; return; } //error: only filter method 0 is allowed in the specification
378 info.interlaceMethod = in[28]; if (in[28] > 1) { error = 34; return; } //error: only interlace methods 0 and 1 exist in the specification
379 error = checkColorValidity(info.colorType, info.bitDepth);
380 }
381 void unFilterScanline(unsigned char* recon, const unsigned char* scanline, const unsigned char* precon, size_t bytewidth, unsigned long filterType, size_t length)
382 {
383 switch (filterType)
384 {
385 case 0: for (size_t i = 0; i < length; i++) recon[i] = scanline[i]; break;
386 case 1:
387 for (size_t i = 0; i < bytewidth; i++) recon[i] = scanline[i];
388 for (size_t i = bytewidth; i < length; i++) recon[i] = scanline[i] + recon[i - bytewidth];
389 break;
390 case 2:
391 if (precon) for (size_t i = 0; i < length; i++) recon[i] = scanline[i] + precon[i];
392 else for (size_t i = 0; i < length; i++) recon[i] = scanline[i];
393 break;
394 case 3:
395 if (precon)
396 {
397 for (size_t i = 0; i < bytewidth; i++) recon[i] = scanline[i] + precon[i] / 2;
398 for (size_t i = bytewidth; i < length; i++) recon[i] = scanline[i] + ((recon[i - bytewidth] + precon[i]) / 2);
399 }
400 else
401 {
402 for (size_t i = 0; i < bytewidth; i++) recon[i] = scanline[i];
403 for (size_t i = bytewidth; i < length; i++) recon[i] = scanline[i] + recon[i - bytewidth] / 2;
404 }
405 break;
406 case 4:
407 if (precon)
408 {
409 for (size_t i = 0; i < bytewidth; i++) recon[i] = scanline[i] + paethPredictor(0, precon[i], 0);
410 for (size_t i = bytewidth; i < length; i++) recon[i] = scanline[i] + paethPredictor(recon[i - bytewidth], precon[i], precon[i - bytewidth]);
411 }
412 else
413 {
414 for (size_t i = 0; i < bytewidth; i++) recon[i] = scanline[i];
415 for (size_t i = bytewidth; i < length; i++) recon[i] = scanline[i] + paethPredictor(recon[i - bytewidth], 0, 0);
416 }
417 break;
418 default: error = 36; return; //error: unexisting filter type given
419 }
420 }
421 void adam7Pass(unsigned char* out, unsigned char* linen, unsigned char* lineo, const unsigned char* in, unsigned long w, size_t passleft, size_t passtop, size_t spacex, size_t spacey, size_t passw, size_t passh, unsigned long bpp)
422 { //filter and reposition the pixels into the output when the image is Adam7 interlaced. This function can only do it after the full image is already decoded. The out buffer must have the correct allocated memory size already.
423 if (passw == 0) return;
424 size_t bytewidth = (bpp + 7) / 8, linelength = 1 + ((bpp * passw + 7) / 8);
425 for (unsigned long y = 0; y < passh; y++)
426 {
427 unsigned char filterType = in[y * linelength], * prevline = (y == 0) ? 0 : lineo;
428 unFilterScanline(linen, &in[y * linelength + 1], prevline, bytewidth, filterType, (w * bpp + 7) / 8); if (error) return;
429 if (bpp >= 8) for (size_t i = 0; i < passw; i++) for (size_t b = 0; b < bytewidth; b++) //b = current byte of this pixel
430 out[bytewidth * w * (passtop + spacey * y) + bytewidth * (passleft + spacex * i) + b] = linen[bytewidth * i + b];
431 else for (size_t i = 0; i < passw; i++)
432 {
433 size_t obp = bpp * w * (passtop + spacey * y) + bpp * (passleft + spacex * i), bp = i * bpp;
434 for (size_t b = 0; b < bpp; b++) setBitOfReversedStream(obp, out, readBitFromReversedStream(bp, &linen[0]));
435 }
436 unsigned char* temp = linen; linen = lineo; lineo = temp; //swap the two buffer pointers "line old" and "line new"
437 }
438 }
439 static unsigned long readBitFromReversedStream(size_t& bitp, const unsigned char* bits) { unsigned long result = (bits[bitp >> 3] >> (7 - (bitp & 0x7))) & 1; bitp++; return result; }
440 static unsigned long readBitsFromReversedStream(size_t& bitp, const unsigned char* bits, unsigned long nbits)
441 {
442 unsigned long result = 0;
443 for (size_t i = nbits - 1; i < nbits; i--) result += ((readBitFromReversedStream(bitp, bits)) << i);
444 return result;
445 }
446 void setBitOfReversedStream(size_t& bitp, unsigned char* bits, unsigned long bit) { bits[bitp >> 3] |= (bit << (7 - (bitp & 0x7))); bitp++; }
447 unsigned long read32bitInt(const unsigned char* buffer) { return (buffer[0] << 24) | (buffer[1] << 16) | (buffer[2] << 8) | buffer[3]; }
448 int checkColorValidity(unsigned long colorType, unsigned long bd) //return type is a LodePNG error code
449 {
450 if ((colorType == 2 || colorType == 4 || colorType == 6)) { if (!(bd == 8 || bd == 16)) return 37; else return 0; }
451 else if (colorType == 0) { if (!(bd == 1 || bd == 2 || bd == 4 || bd == 8 || bd == 16)) return 37; else return 0; }
452 else if (colorType == 3) { if (!(bd == 1 || bd == 2 || bd == 4 || bd == 8)) return 37; else return 0; }
453 else return 31; //unexisting color type
454 }
455 unsigned long getBpp(const Info& info)
456 {
457 if (info.colorType == 2) return (3 * info.bitDepth);
458 else if (info.colorType >= 4) return (info.colorType - 2) * info.bitDepth;
459 else return info.bitDepth;
460 }
461 int convert(std::vector<unsigned char>& out, const unsigned char* in, Info& infoIn, unsigned long w, unsigned long h)
462 { //converts from any color type to 32-bit. return value = LodePNG error code
463 size_t numpixels = w * h, bp = 0;
464 out.resize(numpixels * 4);
465 unsigned char* out_ = out.empty() ? 0 : &out[0]; //faster if compiled without optimization
466 if (infoIn.bitDepth == 8 && infoIn.colorType == 0) //greyscale
467 for (size_t i = 0; i < numpixels; i++)
468 {
469 out_[4 * i + 0] = out_[4 * i + 1] = out_[4 * i + 2] = in[i];
470 out_[4 * i + 3] = (infoIn.key_defined && in[i] == infoIn.key_r) ? 0 : 255;
471 }
472 else if (infoIn.bitDepth == 8 && infoIn.colorType == 2) //RGB color
473 for (size_t i = 0; i < numpixels; i++)
474 {
475 for (size_t c = 0; c < 3; c++) out_[4 * i + c] = in[3 * i + c];
476 out_[4 * i + 3] = (infoIn.key_defined == 1 && in[3 * i + 0] == infoIn.key_r && in[3 * i + 1] == infoIn.key_g && in[3 * i + 2] == infoIn.key_b) ? 0 : 255;
477 }
478 else if (infoIn.bitDepth == 8 && infoIn.colorType == 3) //indexed color (palette)
479 for (size_t i = 0; i < numpixels; i++)
480 {
481 if (4U * in[i] >= infoIn.palette.size()) return 46;
482 for (size_t c = 0; c < 4; c++) out_[4 * i + c] = infoIn.palette[4 * in[i] + c]; //get rgb colors from the palette
483 }
484 else if (infoIn.bitDepth == 8 && infoIn.colorType == 4) //greyscale with alpha
485 for (size_t i = 0; i < numpixels; i++)
486 {
487 out_[4 * i + 0] = out_[4 * i + 1] = out_[4 * i + 2] = in[2 * i + 0];
488 out_[4 * i + 3] = in[2 * i + 1];
489 }
490 else if (infoIn.bitDepth == 8 && infoIn.colorType == 6) for (size_t i = 0; i < numpixels; i++) for (size_t c = 0; c < 4; c++) out_[4 * i + c] = in[4 * i + c]; //RGB with alpha
491 else if (infoIn.bitDepth == 16 && infoIn.colorType == 0) //greyscale
492 for (size_t i = 0; i < numpixels; i++)
493 {
494 out_[4 * i + 0] = out_[4 * i + 1] = out_[4 * i + 2] = in[2 * i];
495 out_[4 * i + 3] = (infoIn.key_defined && 256U * in[i] + in[i + 1] == infoIn.key_r) ? 0 : 255;
496 }
497 else if (infoIn.bitDepth == 16 && infoIn.colorType == 2) //RGB color
498 for (size_t i = 0; i < numpixels; i++)
499 {
500 for (size_t c = 0; c < 3; c++) out_[4 * i + c] = in[6 * i + 2 * c];
501 out_[4 * i + 3] = (infoIn.key_defined && 256U * in[6 * i + 0] + in[6 * i + 1] == infoIn.key_r && 256U * in[6 * i + 2] + in[6 * i + 3] == infoIn.key_g && 256U * in[6 * i + 4] + in[6 * i + 5] == infoIn.key_b) ? 0 : 255;
502 }
503 else if (infoIn.bitDepth == 16 && infoIn.colorType == 4) //greyscale with alpha
504 for (size_t i = 0; i < numpixels; i++)
505 {
506 out_[4 * i + 0] = out_[4 * i + 1] = out_[4 * i + 2] = in[4 * i]; //most significant byte
507 out_[4 * i + 3] = in[4 * i + 2];
508 }
509 else if (infoIn.bitDepth == 16 && infoIn.colorType == 6) for (size_t i = 0; i < numpixels; i++) for (size_t c = 0; c < 4; c++) out_[4 * i + c] = in[8 * i + 2 * c]; //RGB with alpha
510 else if (infoIn.bitDepth < 8 && infoIn.colorType == 0) //greyscale
511 for (size_t i = 0; i < numpixels; i++)
512 {
513 unsigned long value = (readBitsFromReversedStream(bp, in, infoIn.bitDepth) * 255) / ((1 << infoIn.bitDepth) - 1); //scale value from 0 to 255
514 out_[4 * i + 0] = out_[4 * i + 1] = out_[4 * i + 2] = (unsigned char)(value);
515 out_[4 * i + 3] = (infoIn.key_defined && value && ((1U << infoIn.bitDepth) - 1U) == infoIn.key_r && ((1U << infoIn.bitDepth) - 1U)) ? 0 : 255;
516 }
517 else if (infoIn.bitDepth < 8 && infoIn.colorType == 3) //palette
518 for (size_t i = 0; i < numpixels; i++)
519 {
520 unsigned long value = readBitsFromReversedStream(bp, in, infoIn.bitDepth);
521 if (4 * value >= infoIn.palette.size()) return 47;
522 for (size_t c = 0; c < 4; c++) out_[4 * i + c] = infoIn.palette[4 * value + c]; //get rgb colors from the palette
523 }
524 return 0;
525 }
526 unsigned char paethPredictor(short a, short b, short c) //Paeth predicter, used by PNG filter type 4
527 {
528 short p = a + b - c, pa = p > a ? (p - a) : (a - p), pb = p > b ? (p - b) : (b - p), pc = p > c ? (p - c) : (c - p);
529 return (unsigned char)((pa <= pb && pa <= pc) ? a : pb <= pc ? b : c);
530 }
531 };
532 PNG decoder; decoder.decode(out_image, in_png, in_size, convert_to_rgba32);
533 image_width = decoder.info.width; image_height = decoder.info.height;
534 return decoder.error;
535}