1 /* 2 LodePNG Utils 3 4 Copyright (c) 2005-2012 Lode Vandevenne 5 6 This software is provided 'as-is', without any express or implied 7 warranty. In no event will the authors be held liable for any damages 8 arising from the use of this software. 9 10 Permission is granted to anyone to use this software for any purpose, 11 including commercial applications, and to alter it and redistribute it 12 freely, subject to the following restrictions: 13 14 1. The origin of this software must not be misrepresented; you must not 15 claim that you wrote the original software. If you use this software 16 in a product, an acknowledgment in the product documentation would be 17 appreciated but is not required. 18 19 2. Altered source versions must be plainly marked as such, and must not be 20 misrepresented as being the original software. 21 22 3. This notice may not be removed or altered from any source 23 distribution. 24 */ 25 26 #include "lodepng_util.h" 27 #include <iostream> 28 29 namespace lodepng 30 { 31 32 LodePNGInfo 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 40 unsigned 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 62 unsigned getChunks(std::vector<std::string> names[3], 63 std::vector<std::vector<unsigned char> > chunks[3], 64 const std::vector<unsigned char>& png) 65 { 66 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 105 unsigned 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 155 unsigned 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 237 unsigned 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 266 int 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. 276 static 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}; 278 static 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}; 280 static 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}; 282 static 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}; 284 static 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 287 struct 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 565 struct 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 648 void 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