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