1/*
2LodePNG Utils
3
4Copyright (c) 2005-2012 Lode Vandevenne
5
6This software is provided 'as-is', without any express or implied
7warranty. In no event will the authors be held liable for any damages
8arising from the use of this software.
9
10Permission is granted to anyone to use this software for any purpose,
11including commercial applications, and to alter it and redistribute it
12freely, 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#include "lodepng_util.h"
27#include <iostream>
28
29namespace lodepng
30{
31
32LodePNGInfo getPNGHeaderInfo(const std::vector<unsigned char>& png)
33{
34  unsigned w, h;
35  lodepng::State state;
36  lodepng_inspect(&w, &h, &state, &png[0], png.size());
37  return state.info_png;
38}
39
40unsigned getChunkInfo(std::vector<std::string>& names, std::vector<size_t>& sizes,
41                      const std::vector<unsigned char>& png)
42{
43  // Listing chunks is based on the original file, not the decoded png info.
44  const unsigned char *chunk, *begin, *end;
45  end = &png.back() + 1;
46  begin = chunk = &png.front() + 8;
47
48  while(chunk + 8 < end && chunk >= begin)
49  {
50    char type[5];
51    lodepng_chunk_type(type, chunk);
52    if(std::string(type).size() != 4) return 1;
53
54    names.push_back(type);
55    sizes.push_back(lodepng_chunk_length(chunk));
56
57    chunk = lodepng_chunk_next_const(chunk);
58  }
59  return 0;
60}
61
62unsigned 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  const unsigned char *chunk, *next, *begin, *end;
67  end = &png.back() + 1;
68  begin = chunk = &png.front() + 8;
69
70  int location = 0;
71
72  while(chunk + 8 < end && chunk >= begin)
73  {
74    char type[5];
75    lodepng_chunk_type(type, chunk);
76    std::string name(type);
77    if(name.size() != 4) return 1;
78
79    next = lodepng_chunk_next_const(chunk);
80
81    if(name == "IHDR")
82    {
83      location = 0;
84    }
85    else if(name == "PLTE")
86    {
87      location = 1;
88    }
89    else if(name == "IDAT")
90    {
91      location = 2;
92    }
93    else if(name != "IEND")
94    {
95      names[location].push_back(name);
96      chunks[location].push_back(std::vector<unsigned char>(chunk, next));
97    }
98
99    chunk = next;
100  }
101  return 0;
102}
103
104
105unsigned insertChunks(std::vector<unsigned char>& png,
106                      const std::vector<std::vector<unsigned char> > chunks[3])
107{
108  const unsigned char *chunk, *next, *begin, *end;
109  end = &png.back() + 1;
110  begin = chunk = &png.front() + 8;
111
112  size_t l0 = 0; //location 0: IHDR-l0-PLTE (or IHDR-l0-l1-IDAT)
113  size_t l1 = 0; //location 1: PLTE-l1-IDAT (or IHDR-l0-l1-IDAT)
114  size_t l2 = 0; //location 2: IDAT-l2-IEND
115
116  while(chunk + 8 < end && chunk >= begin)
117  {
118    char type[5];
119    lodepng_chunk_type(type, chunk);
120    std::string name(type);
121    if(name.size() != 4) return 1;
122
123    next = lodepng_chunk_next_const(chunk);
124
125    if(name == "PLTE")
126    {
127      if(l0 == 0) l0 = chunk - begin + 8;
128    }
129    else if(name == "IDAT")
130    {
131      if(l0 == 0) l0 = chunk - begin + 8;
132      if(l1 == 0) l1 = chunk - begin + 8;
133    }
134    else if(name == "IEND")
135    {
136      if(l2 == 0) l2 = chunk - begin + 8;
137    }
138
139    chunk = next;
140  }
141
142  std::vector<unsigned char> result;
143  result.insert(result.end(), png.begin(), png.begin() + l0);
144  for(size_t i = 0; i < chunks[0].size(); i++) result.insert(result.end(), chunks[0][i].begin(), chunks[0][i].end());
145  result.insert(result.end(), png.begin() + l0, png.begin() + l1);
146  for(size_t i = 0; i < chunks[1].size(); i++) result.insert(result.end(), chunks[1][i].begin(), chunks[1][i].end());
147  result.insert(result.end(), png.begin() + l1, png.begin() + l2);
148  for(size_t i = 0; i < chunks[2].size(); i++) result.insert(result.end(), chunks[2][i].begin(), chunks[2][i].end());
149  result.insert(result.end(), png.begin() + l2, png.end());
150
151  png = result;
152  return 0;
153}
154
155unsigned getFilterTypesInterlaced(std::vector<std::vector<unsigned char> >& filterTypes,
156                                  const std::vector<unsigned char>& png)
157{
158  //Get color type and interlace type
159  lodepng::State state;
160  unsigned w, h;
161  unsigned error;
162  error = lodepng_inspect(&w, &h, &state, &png[0], png.size());
163
164  if(error) return 1;
165
166  //Read literal data from all IDAT chunks
167  const unsigned char *chunk, *begin, *end;
168  end = &png.back() + 1;
169  begin = chunk = &png.front() + 8;
170
171  std::vector<unsigned char> zdata;
172
173  while(chunk + 8 < end && chunk >= begin)
174  {
175    char type[5];
176    lodepng_chunk_type(type, chunk);
177    if(std::string(type).size() != 4) return 1; //Probably not a PNG file
178
179    if(std::string(type) == "IDAT")
180    {
181      const unsigned char* cdata = lodepng_chunk_data_const(chunk);
182      unsigned clength = lodepng_chunk_length(chunk);
183
184      for(unsigned i = 0; i < clength; i++)
185      {
186        zdata.push_back(cdata[i]);
187      }
188    }
189
190    chunk = lodepng_chunk_next_const(chunk);
191  }
192
193  //Decompress all IDAT data
194  std::vector<unsigned char> data;
195  error = lodepng::decompress(data, &zdata[0], zdata.size());
196
197  if(error) return 1;
198
199  if(state.info_png.interlace_method == 0)
200  {
201    filterTypes.resize(1);
202
203    //A line is 1 filter byte + all pixels
204    size_t linebytes = 1 + lodepng_get_raw_size(w, 1, &state.info_png.color);
205
206    for(size_t i = 0; i < data.size(); i += linebytes)
207    {
208      filterTypes[0].push_back(data[i]);
209    }
210  }
211  else
212  {
213    //Interlaced
214    filterTypes.resize(7);
215    static const unsigned ADAM7_IX[7] = { 0, 4, 0, 2, 0, 1, 0 }; /*x start values*/
216    static const unsigned ADAM7_IY[7] = { 0, 0, 4, 0, 2, 0, 1 }; /*y start values*/
217    static const unsigned ADAM7_DX[7] = { 8, 8, 4, 4, 2, 2, 1 }; /*x delta values*/
218    static const unsigned ADAM7_DY[7] = { 8, 8, 8, 4, 4, 2, 2 }; /*y delta values*/
219    size_t pos = 0;
220    for(int j = 0; j < 7; j++)
221    {
222      unsigned w2 = (w - ADAM7_IX[j] + ADAM7_DX[j] - 1) / ADAM7_DX[j];
223      unsigned h2 = (h - ADAM7_IY[j] + ADAM7_DY[j] - 1) / ADAM7_DY[j];
224      if(ADAM7_IX[j] >= w || ADAM7_IY[j] >= h) w2 = h2 = 0;
225      size_t linebytes = 1 + lodepng_get_raw_size(w2, 1, &state.info_png.color);
226      for(size_t i = 0; i < h2; i++)
227      {
228        filterTypes[j].push_back(data[pos]);
229        pos += linebytes;
230      }
231    }
232  }
233  return 0; /* OK */
234}
235
236
237unsigned getFilterTypes(std::vector<unsigned char>& filterTypes, const std::vector<unsigned char>& png)
238{
239  std::vector<std::vector<unsigned char> > passes;
240  unsigned error = getFilterTypesInterlaced(passes, png);
241  if(error) return error;
242
243  if(passes.size() == 1)
244  {
245    filterTypes.swap(passes[0]);
246  }
247  else
248  {
249    lodepng::State state;
250    unsigned w, h;
251    lodepng_inspect(&w, &h, &state, &png[0], png.size());
252    /*
253    Interlaced. Simplify it: put pass 6 and 7 alternating in the one vector so
254    that one filter per scanline of the uninterlaced image is given, with that
255    filter corresponding the closest to what it would be for non-interlaced
256    image.
257    */
258    for(size_t i = 0; i < h; i++)
259    {
260      filterTypes.push_back(i % 2 == 0 ? passes[5][i / 2] : passes[6][i / 2]);
261    }
262  }
263  return 0; /* OK */
264}
265
266int getPaletteValue(const unsigned char* data, size_t i, int bits)
267{
268  if(bits == 8) return data[i];
269  else if(bits == 4) return (data[i / 2] >> ((i % 2) * 4)) & 15;
270  else if(bits == 2) return (data[i / 4] >> ((i % 4) * 2)) & 3;
271  else if(bits == 1) return (data[i / 8] >> (i % 8)) & 1;
272  else return 0;
273}
274
275//This uses a stripped down version of picoPNG to extract detailed zlib information while decompressing.
276static const unsigned long LENBASE[29] =
277    {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};
278static const unsigned long LENEXTRA[29] =
279    {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};
280static const unsigned long DISTBASE[30] =
281    {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};
282static const unsigned long DISTEXTRA[30] =
283    {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};
284static const unsigned long CLCL[19] =
285    {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; //code length code lengths
286
287struct ExtractZlib // Zlib decompression and information extraction
288{
289  std::vector<ZlibBlockInfo>* zlibinfo;
290  int error;
291
292  ExtractZlib(std::vector<ZlibBlockInfo>* output) : zlibinfo(output) {};
293
294  unsigned long readBitFromStream(size_t& bitp, const unsigned char* bits)
295  {
296    unsigned long result = (bits[bitp >> 3] >> (bitp & 0x7)) & 1;
297    bitp++;
298    return result;
299  }
300
301  unsigned long readBitsFromStream(size_t& bitp, const unsigned char* bits, size_t nbits)
302  {
303    unsigned long result = 0;
304    for(size_t i = 0; i < nbits; i++) result += (readBitFromStream(bitp, bits)) << i;
305    return result;
306  }
307
308  struct HuffmanTree
309  {
310    int makeFromLengths(const std::vector<unsigned long>& bitlen, unsigned long maxbitlen)
311    { //make tree given the lengths
312      unsigned long numcodes = (unsigned long)(bitlen.size()), treepos = 0, nodefilled = 0;
313      std::vector<unsigned long> tree1d(numcodes), blcount(maxbitlen + 1, 0), nextcode(maxbitlen + 1, 0);
314      //count number of instances of each code length
315      for(unsigned long bits = 0; bits < numcodes; bits++) blcount[bitlen[bits]]++;
316      for(unsigned long bits = 1; bits <= maxbitlen; bits++)
317      {
318        nextcode[bits] = (nextcode[bits - 1] + blcount[bits - 1]) << 1;
319      }
320      //generate all the codes
321      for(unsigned long n = 0; n < numcodes; n++) if(bitlen[n] != 0) tree1d[n] = nextcode[bitlen[n]]++;
322      tree2d.clear(); tree2d.resize(numcodes * 2, 32767); //32767 here means the tree2d isn't filled there yet
323      for(unsigned long n = 0; n < numcodes; n++) //the codes
324      for(unsigned long i = 0; i < bitlen[n]; i++) //the bits for this code
325      {
326        unsigned long bit = (tree1d[n] >> (bitlen[n] - i - 1)) & 1;
327        if(treepos > numcodes - 2) return 55;
328        if(tree2d[2 * treepos + bit] == 32767) //not yet filled in
329        {
330          if(i + 1 == bitlen[n])
331          {
332            //last bit
333            tree2d[2 * treepos + bit] = n;
334            treepos = 0;
335          }
336          else
337          {
338            //addresses are encoded as values > numcodes
339            tree2d[2 * treepos + bit] = ++nodefilled + numcodes;
340            treepos = nodefilled;
341          }
342        }
343        else treepos = tree2d[2 * treepos + bit] - numcodes; //subtract numcodes from address to get address value
344      }
345      return 0;
346    }
347    int decode(bool& decoded, unsigned long& result, size_t& treepos, unsigned long bit) const
348    { //Decodes a symbol from the tree
349      unsigned long numcodes = (unsigned long)tree2d.size() / 2;
350      if(treepos >= numcodes) return 11; //error: you appeared outside the codetree
351      result = tree2d[2 * treepos + bit];
352      decoded = (result < numcodes);
353      treepos = decoded ? 0 : result - numcodes;
354      return 0;
355    }
356    //2D representation of a huffman tree: one dimension is "0" or "1", the other contains all nodes and leaves.
357    std::vector<unsigned long> tree2d;
358  };
359
360  void inflate(std::vector<unsigned char>& out, const std::vector<unsigned char>& in, size_t inpos = 0)
361  {
362    size_t bp = 0, pos = 0; //bit pointer and byte pointer
363    error = 0;
364    unsigned long BFINAL = 0;
365    while(!BFINAL && !error)
366    {
367      size_t uncomprblockstart = pos;
368      size_t bpstart = bp;
369      if(bp >> 3 >= in.size()) { error = 52; return; } //error, bit pointer will jump past memory
370      BFINAL = readBitFromStream(bp, &in[inpos]);
371      unsigned long BTYPE = readBitFromStream(bp, &in[inpos]); BTYPE += 2 * readBitFromStream(bp, &in[inpos]);
372      zlibinfo->resize(zlibinfo->size() + 1);
373      zlibinfo->back().btype = BTYPE;
374      if(BTYPE == 3) { error = 20; return; } //error: invalid BTYPE
375      else if(BTYPE == 0) inflateNoCompression(out, &in[inpos], bp, pos, in.size());
376      else inflateHuffmanBlock(out, &in[inpos], bp, pos, in.size(), BTYPE);
377      size_t uncomprblocksize = pos - uncomprblockstart;
378      zlibinfo->back().compressedbits = bp - bpstart;
379      zlibinfo->back().uncompressedbytes = uncomprblocksize;
380    }
381  }
382
383  void generateFixedTrees(HuffmanTree& tree, HuffmanTree& treeD) //get the tree of a deflated block with fixed tree
384  {
385    std::vector<unsigned long> bitlen(288, 8), bitlenD(32, 5);;
386    for(size_t i = 144; i <= 255; i++) bitlen[i] = 9;
387    for(size_t i = 256; i <= 279; i++) bitlen[i] = 7;
388    tree.makeFromLengths(bitlen, 15);
389    treeD.makeFromLengths(bitlenD, 15);
390  }
391
392  //the code tree for Huffman codes, dist codes, and code length codes
393  HuffmanTree codetree, codetreeD, codelengthcodetree;
394  unsigned long huffmanDecodeSymbol(const unsigned char* in, size_t& bp, const HuffmanTree& codetree, size_t inlength)
395  {
396    //decode a single symbol from given list of bits with given code tree. return value is the symbol
397    bool decoded; unsigned long ct;
398    for(size_t treepos = 0;;)
399    {
400      if((bp & 0x07) == 0 && (bp >> 3) > inlength) { error = 10; return 0; } //error: end reached without endcode
401      error = codetree.decode(decoded, ct, treepos, readBitFromStream(bp, in));
402      if(error) return 0; //stop, an error happened
403      if(decoded) return ct;
404    }
405  }
406
407  void getTreeInflateDynamic(HuffmanTree& tree, HuffmanTree& treeD,
408                             const unsigned char* in, size_t& bp, size_t inlength)
409  {
410    size_t bpstart = bp;
411    //get the tree of a deflated block with dynamic tree, the tree itself is also Huffman compressed with a known tree
412    std::vector<unsigned long> bitlen(288, 0), bitlenD(32, 0);
413    if(bp >> 3 >= inlength - 2) { error = 49; return; } //the bit pointer is or will go past the memory
414    size_t HLIT =  readBitsFromStream(bp, in, 5) + 257; //number of literal/length codes + 257
415    size_t HDIST = readBitsFromStream(bp, in, 5) + 1; //number of dist codes + 1
416    size_t HCLEN = readBitsFromStream(bp, in, 4) + 4; //number of code length codes + 4
417    zlibinfo->back().hlit = HLIT - 257;
418    zlibinfo->back().hdist = HDIST - 1;
419    zlibinfo->back().hclen = HCLEN - 4;
420    std::vector<unsigned long> codelengthcode(19); //lengths of tree to decode the lengths of the dynamic tree
421    for(size_t i = 0; i < 19; i++) codelengthcode[CLCL[i]] = (i < HCLEN) ? readBitsFromStream(bp, in, 3) : 0;
422    //code length code lengths
423    for(size_t i = 0; i < codelengthcode.size(); i++) zlibinfo->back().clcl.push_back(codelengthcode[i]);
424    error = codelengthcodetree.makeFromLengths(codelengthcode, 7); if(error) return;
425    size_t i = 0, replength;
426    while(i < HLIT + HDIST)
427    {
428      unsigned long code = huffmanDecodeSymbol(in, bp, codelengthcodetree, inlength); if(error) return;
429      zlibinfo->back().treecodes.push_back(code); //tree symbol code
430      if(code <= 15)  { if(i < HLIT) bitlen[i++] = code; else bitlenD[i++ - HLIT] = code; } //a length code
431      else if(code == 16) //repeat previous
432      {
433        if(bp >> 3 >= inlength) { error = 50; return; } //error, bit pointer jumps past memory
434        replength = 3 + readBitsFromStream(bp, in, 2);
435        unsigned long value; //set value to the previous code
436        if((i - 1) < HLIT) value = bitlen[i - 1];
437        else value = bitlenD[i - HLIT - 1];
438        for(size_t n = 0; n < replength; n++) //repeat this value in the next lengths
439        {
440          if(i >= HLIT + HDIST) { error = 13; return; } //error: i is larger than the amount of codes
441          if(i < HLIT) bitlen[i++] = value; else bitlenD[i++ - HLIT] = value;
442        }
443      }
444      else if(code == 17) //repeat "0" 3-10 times
445      {
446        if(bp >> 3 >= inlength) { error = 50; return; } //error, bit pointer jumps past memory
447        replength = 3 + readBitsFromStream(bp, in, 3);
448        zlibinfo->back().treecodes.push_back(replength); //tree symbol code repetitions
449        for(size_t n = 0; n < replength; n++) //repeat this value in the next lengths
450        {
451          if(i >= HLIT + HDIST) { error = 14; return; } //error: i is larger than the amount of codes
452          if(i < HLIT) bitlen[i++] = 0; else bitlenD[i++ - HLIT] = 0;
453        }
454      }
455      else if(code == 18) //repeat "0" 11-138 times
456      {
457        if(bp >> 3 >= inlength) { error = 50; return; } //error, bit pointer jumps past memory
458        replength = 11 + readBitsFromStream(bp, in, 7);
459        zlibinfo->back().treecodes.push_back(replength); //tree symbol code repetitions
460        for(size_t n = 0; n < replength; n++) //repeat this value in the next lengths
461        {
462          if(i >= HLIT + HDIST) { error = 15; return; } //error: i is larger than the amount of codes
463          if(i < HLIT) bitlen[i++] = 0; else bitlenD[i++ - HLIT] = 0;
464        }
465      }
466      else { error = 16; return; } //error: somehow an unexisting code appeared. This can never happen.
467    }
468    if(bitlen[256] == 0) { error = 64; return; } //the length of the end code 256 must be larger than 0
469    error = tree.makeFromLengths(bitlen, 15);
470    if(error) return; //now we've finally got HLIT and HDIST, so generate the code trees, and the function is done
471    error = treeD.makeFromLengths(bitlenD, 15);
472    if(error) return;
473    zlibinfo->back().treebits = bp - bpstart;
474    //lit/len/end symbol lengths
475    for(size_t i = 0; i < bitlen.size(); i++) zlibinfo->back().litlenlengths.push_back(bitlen[i]);
476    //dist lengths
477    for(size_t i = 0; i < bitlenD.size(); i++) zlibinfo->back().distlengths.push_back(bitlenD[i]);
478  }
479
480  void inflateHuffmanBlock(std::vector<unsigned char>& out,
481                           const unsigned char* in, size_t& bp, size_t& pos, size_t inlength, unsigned long btype)
482  {
483    size_t numcodes = 0, numlit = 0, numlen = 0; //for logging
484    if(btype == 1) { generateFixedTrees(codetree, codetreeD); }
485    else if(btype == 2) { getTreeInflateDynamic(codetree, codetreeD, in, bp, inlength); if(error) return; }
486    for(;;)
487    {
488      unsigned long code = huffmanDecodeSymbol(in, bp, codetree, inlength); if(error) return;
489      numcodes++;
490      zlibinfo->back().lz77_lcode.push_back(code); //output code
491      zlibinfo->back().lz77_dcode.push_back(0);
492      zlibinfo->back().lz77_lbits.push_back(0);
493      zlibinfo->back().lz77_dbits.push_back(0);
494      zlibinfo->back().lz77_lvalue.push_back(0);
495      zlibinfo->back().lz77_dvalue.push_back(0);
496
497      if(code == 256) break; //end code
498      else if(code <= 255) //literal symbol
499      {
500        out.push_back((unsigned char)(code));
501        pos++;
502        numlit++;
503      }
504      else if(code >= 257 && code <= 285) //length code
505      {
506        size_t length = LENBASE[code - 257], numextrabits = LENEXTRA[code - 257];
507        if((bp >> 3) >= inlength) { error = 51; return; } //error, bit pointer will jump past memory
508        length += readBitsFromStream(bp, in, numextrabits);
509        unsigned long codeD = huffmanDecodeSymbol(in, bp, codetreeD, inlength); if(error) return;
510        if(codeD > 29) { error = 18; return; } //error: invalid dist code (30-31 are never used)
511        unsigned long dist = DISTBASE[codeD], numextrabitsD = DISTEXTRA[codeD];
512        if((bp >> 3) >= inlength) { error = 51; return; } //error, bit pointer will jump past memory
513        dist += readBitsFromStream(bp, in, numextrabitsD);
514        size_t start = pos, back = start - dist; //backwards
515        for(size_t i = 0; i < length; i++)
516        {
517          out.push_back(out[back++]);
518          pos++;
519          if(back >= start) back = start - dist;
520        }
521        numlen++;
522        zlibinfo->back().lz77_dcode.back() = codeD; //output distance code
523        zlibinfo->back().lz77_lbits.back() = numextrabits; //output length extra bits
524        zlibinfo->back().lz77_dbits.back() = numextrabitsD; //output dist extra bits
525        zlibinfo->back().lz77_lvalue.back() = length; //output length
526        zlibinfo->back().lz77_dvalue.back() = dist; //output dist
527      }
528    }
529    zlibinfo->back().numlit = numlit; //output number of literal symbols
530    zlibinfo->back().numlen = numlen; //output number of length symbols
531  }
532
533  void inflateNoCompression(std::vector<unsigned char>& out,
534                            const unsigned char* in, size_t& bp, size_t& pos, size_t inlength)
535  {
536    while((bp & 0x7) != 0) bp++; //go to first boundary of byte
537    size_t p = bp / 8;
538    if(p >= inlength - 4) { error = 52; return; } //error, bit pointer will jump past memory
539    unsigned long LEN = in[p] + 256 * in[p + 1], NLEN = in[p + 2] + 256 * in[p + 3]; p += 4;
540    if(LEN + NLEN != 65535) { error = 21; return; } //error: NLEN is not one's complement of LEN
541    if(p + LEN > inlength) { error = 23; return; } //error: reading outside of in buffer
542    for(unsigned long n = 0; n < LEN; n++)
543    {
544      out.push_back(in[p++]); //read LEN bytes of literal data
545      pos++;
546    }
547    bp = p * 8;
548  }
549
550  int decompress(std::vector<unsigned char>& out, const std::vector<unsigned char>& in) //returns error value
551  {
552    if(in.size() < 2) { return 53; } //error, size of zlib data too small
553    //error: 256 * in[0] + in[1] must be a multiple of 31, the FCHECK value is supposed to be made that way
554    if((in[0] * 256 + in[1]) % 31 != 0) { return 24; }
555    unsigned long CM = in[0] & 15, CINFO = (in[0] >> 4) & 15, FDICT = (in[1] >> 5) & 1;
556    //error: only compression method 8: inflate with sliding window of 32k is supported by the PNG spec
557    if(CM != 8 || CINFO > 7) { return 25; }
558    //error: the PNG spec says about the zlib stream: "The additional flags shall not specify a preset dictionary."
559    if(FDICT != 0) { return 26; }
560    inflate(out, in, 2);
561    return error; //note: adler32 checksum was skipped and ignored
562  }
563};
564
565struct ExtractPNG //PNG decoding and information extraction
566{
567  std::vector<ZlibBlockInfo>* zlibinfo;
568  int error;
569
570  ExtractPNG(std::vector<ZlibBlockInfo>* output) : zlibinfo(output) {};
571
572  void decode(const unsigned char* in, size_t size)
573  {
574    error = 0;
575    if(size == 0 || in == 0) { error = 48; return; } //the given data is empty
576    readPngHeader(&in[0], size); if(error) return;
577    size_t pos = 33; //first byte of the first chunk after the header
578    std::vector<unsigned char> idat; //the data from idat chunks
579    bool IEND = false;
580    //loop through the chunks, ignoring unknown chunks and stopping at IEND chunk.
581    //IDAT data is put at the start of the in buffer
582    while(!IEND)
583    {
584      //error: size of the in buffer too small to contain next chunk
585      if(pos + 8 >= size) { error = 30; return; }
586      size_t chunkLength = read32bitInt(&in[pos]); pos += 4;
587      if(chunkLength > 2147483647) { error = 63; return; }
588      //error: size of the in buffer too small to contain next chunk
589      if(pos + chunkLength >= size) { error = 35; return; }
590      //IDAT chunk, containing compressed image data
591      if(in[pos + 0] == 'I' && in[pos + 1] == 'D' && in[pos + 2] == 'A' && in[pos + 3] == 'T')
592      {
593        idat.insert(idat.end(), &in[pos + 4], &in[pos + 4 + chunkLength]);
594        pos += (4 + chunkLength);
595      }
596      else if(in[pos + 0] == 'I' && in[pos + 1] == 'E' && in[pos + 2] == 'N' && in[pos + 3] == 'D')
597      {
598          pos += 4;
599          IEND = true;
600      }
601      else //it's not an implemented chunk type, so ignore it: skip over the data
602      {
603        pos += (chunkLength + 4); //skip 4 letters and uninterpreted data of unimplemented chunk
604      }
605      pos += 4; //step over CRC (which is ignored)
606    }
607    std::vector<unsigned char> out; //now the out buffer will be filled
608    ExtractZlib zlib(zlibinfo); //decompress with the Zlib decompressor
609    error = zlib.decompress(out, idat);
610    if(error) return; //stop if the zlib decompressor returned an error
611  }
612
613  //read the information from the header and store it in the Info
614  void readPngHeader(const unsigned char* in, size_t inlength)
615  {
616    if(inlength < 29) { error = 27; return; } //error: the data length is smaller than the length of the header
617    if(in[0] != 137 || in[1] != 80 || in[2] != 78 || in[3] != 71
618    || in[4] != 13 || in[5] != 10 || in[6] != 26 || in[7] != 10) { error = 28; return; } //no PNG signature
619    //error: it doesn't start with a IHDR chunk!
620    if(in[12] != 'I' || in[13] != 'H' || in[14] != 'D' || in[15] != 'R') { error = 29; return; }
621  }
622
623  unsigned long readBitFromReversedStream(size_t& bitp, const unsigned char* bits)
624  {
625    unsigned long result = (bits[bitp >> 3] >> (7 - (bitp & 0x7))) & 1;
626    bitp++;
627    return result;
628  }
629
630  unsigned long readBitsFromReversedStream(size_t& bitp, const unsigned char* bits, unsigned long nbits)
631  {
632    unsigned long result = 0;
633    for(size_t i = nbits - 1; i < nbits; i--) result += ((readBitFromReversedStream(bitp, bits)) << i);
634    return result;
635  }
636
637  void setBitOfReversedStream(size_t& bitp, unsigned char* bits, unsigned long bit)
638  {
639    bits[bitp >> 3] |=  (bit << (7 - (bitp & 0x7))); bitp++;
640  }
641
642  unsigned long read32bitInt(const unsigned char* buffer)
643  {
644    return (buffer[0] << 24) | (buffer[1] << 16) | (buffer[2] << 8) | buffer[3];
645  }
646};
647
648void extractZlibInfo(std::vector<ZlibBlockInfo>& zlibinfo, const std::vector<unsigned char>& in)
649{
650  ExtractPNG decoder(&zlibinfo);
651  decoder.decode(&in[0], in.size());
652
653  if(decoder.error) std::cout << "extract error: " << decoder.error << std::endl;
654}
655
656} // namespace lodepng
657