read a PNG, the result will be in the same color type as the PNG (hence "generic")*/
| 4560 | |
| 4561 | /*read a PNG, the result will be in the same color type as the PNG (hence "generic")*/ |
| 4562 | static void decodeGeneric(unsigned char** out, unsigned* w, unsigned* h, |
| 4563 | LodePNGState* state, |
| 4564 | const unsigned char* in, size_t insize) |
| 4565 | { |
| 4566 | unsigned char IEND = 0; |
| 4567 | const unsigned char* chunk; |
| 4568 | size_t i; |
| 4569 | ucvector idat; /*the data from idat chunks*/ |
| 4570 | ucvector scanlines; |
| 4571 | |
| 4572 | /*for unknown chunk order*/ |
| 4573 | unsigned unknown = 0; |
| 4574 | #ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS |
| 4575 | unsigned critical_pos = 1; /*1 = after IHDR, 2 = after PLTE, 3 = after IDAT*/ |
| 4576 | #endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ |
| 4577 | |
| 4578 | /*provide some proper output values if error will happen*/ |
| 4579 | *out = 0; |
| 4580 | |
| 4581 | state->error = lodepng_inspect(w, h, state, in, insize); /*reads header and resets other parameters in state->info_png*/ |
| 4582 | if(state->error) return; |
| 4583 | |
| 4584 | ucvector_init(&idat); |
| 4585 | chunk = &in[33]; /*first byte of the first chunk after the header*/ |
| 4586 | |
| 4587 | /*loop through the chunks, ignoring unknown chunks and stopping at IEND chunk. |
| 4588 | IDAT data is put at the start of the in buffer*/ |
| 4589 | while(!IEND && !state->error) |
| 4590 | { |
| 4591 | unsigned chunkLength; |
| 4592 | const unsigned char* data; /*the data in the chunk*/ |
| 4593 | |
| 4594 | /*error: size of the in buffer too small to contain next chunk*/ |
| 4595 | if((size_t)((chunk - in) + 12) > insize || chunk < in) CERROR_BREAK(state->error, 30); |
| 4596 | |
| 4597 | /*length of the data of the chunk, excluding the length bytes, chunk type and CRC bytes*/ |
| 4598 | chunkLength = lodepng_chunk_length(chunk); |
| 4599 | /*error: chunk length larger than the max PNG chunk size*/ |
| 4600 | if(chunkLength > 2147483647) CERROR_BREAK(state->error, 63); |
| 4601 | |
| 4602 | if((size_t)((chunk - in) + chunkLength + 12) > insize || (chunk + chunkLength + 12) < in) |
| 4603 | { |
| 4604 | CERROR_BREAK(state->error, 64); /*error: size of the in buffer too small to contain next chunk*/ |
| 4605 | } |
| 4606 | |
| 4607 | data = lodepng_chunk_data_const(chunk); |
| 4608 | |
| 4609 | /*IDAT chunk, containing compressed image data*/ |
| 4610 | if(lodepng_chunk_type_equals(chunk, "IDAT")) |
| 4611 | { |
| 4612 | size_t oldsize = idat.size; |
| 4613 | if(!ucvector_resize(&idat, oldsize + chunkLength)) CERROR_BREAK(state->error, 83 /*alloc fail*/); |
| 4614 | for(i = 0; i < chunkLength; i++) idat.data[oldsize + i] = data[i]; |
| 4615 | #ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS |
| 4616 | critical_pos = 3; |
| 4617 | #endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ |
| 4618 | } |
| 4619 | /*IEND chunk*/ |
no test coverage detected