Compress-Zopfli
view release on metacpan or search on metacpan
zopflib/src/zopflipng/lodepng/lodepng_util.cpp view on Meta::CPAN
next = lodepng_chunk_next_const(chunk);
if (next <= chunk) return 1; // integer overflow
if(name == "PLTE")
{
if(l0 == 0) l0 = chunk - begin + 8;
}
else if(name == "IDAT")
{
if(l0 == 0) l0 = chunk - begin + 8;
if(l1 == 0) l1 = chunk - begin + 8;
}
else if(name == "IEND")
{
if(l2 == 0) l2 = chunk - begin + 8;
}
chunk = next;
}
std::vector<unsigned char> result;
result.insert(result.end(), png.begin(), png.begin() + l0);
for(size_t i = 0; i < chunks[0].size(); i++) result.insert(result.end(), chunks[0][i].begin(), chunks[0][i].end());
result.insert(result.end(), png.begin() + l0, png.begin() + l1);
for(size_t i = 0; i < chunks[1].size(); i++) result.insert(result.end(), chunks[1][i].begin(), chunks[1][i].end());
result.insert(result.end(), png.begin() + l1, png.begin() + l2);
for(size_t i = 0; i < chunks[2].size(); i++) result.insert(result.end(), chunks[2][i].begin(), chunks[2][i].end());
result.insert(result.end(), png.begin() + l2, png.end());
png = result;
return 0;
}
unsigned getFilterTypesInterlaced(std::vector<std::vector<unsigned char> >& filterTypes,
const std::vector<unsigned char>& png)
{
//Get color type and interlace type
lodepng::State state;
unsigned w, h;
unsigned error;
error = lodepng_inspect(&w, &h, &state, &png[0], png.size());
if(error) return 1;
//Read literal data from all IDAT chunks
const unsigned char *chunk, *begin, *end, *next;
end = &png.back() + 1;
begin = chunk = &png.front() + 8;
std::vector<unsigned char> zdata;
while(chunk + 8 < end && chunk >= begin)
{
char type[5];
lodepng_chunk_type(type, chunk);
if(std::string(type).size() != 4) return 1; //Probably not a PNG file
if(std::string(type) == "IDAT")
{
const unsigned char* cdata = lodepng_chunk_data_const(chunk);
unsigned clength = lodepng_chunk_length(chunk);
if(chunk + clength + 12 > end || clength > png.size() || chunk + clength + 12 < begin) {
// corrupt chunk length
return 1;
}
for(unsigned i = 0; i < clength; i++)
{
zdata.push_back(cdata[i]);
}
}
next = lodepng_chunk_next_const(chunk);
if (next <= chunk) return 1; // integer overflow
chunk = next;
}
//Decompress all IDAT data
std::vector<unsigned char> data;
error = lodepng::decompress(data, &zdata[0], zdata.size());
if(error) return 1;
if(state.info_png.interlace_method == 0)
{
filterTypes.resize(1);
//A line is 1 filter byte + all pixels
size_t linebytes = 1 + lodepng_get_raw_size(w, 1, &state.info_png.color);
for(size_t i = 0; i < data.size(); i += linebytes)
{
filterTypes[0].push_back(data[i]);
}
}
else
{
//Interlaced
filterTypes.resize(7);
static const unsigned ADAM7_IX[7] = { 0, 4, 0, 2, 0, 1, 0 }; /*x start values*/
static const unsigned ADAM7_IY[7] = { 0, 0, 4, 0, 2, 0, 1 }; /*y start values*/
static const unsigned ADAM7_DX[7] = { 8, 8, 4, 4, 2, 2, 1 }; /*x delta values*/
static const unsigned ADAM7_DY[7] = { 8, 8, 8, 4, 4, 2, 2 }; /*y delta values*/
size_t pos = 0;
for(size_t j = 0; j < 7; j++)
{
unsigned w2 = (w - ADAM7_IX[j] + ADAM7_DX[j] - 1) / ADAM7_DX[j];
unsigned h2 = (h - ADAM7_IY[j] + ADAM7_DY[j] - 1) / ADAM7_DY[j];
if(ADAM7_IX[j] >= w) w2 = 0;
if(ADAM7_IY[j] >= h) h2 = 0;
size_t linebytes = 1 + lodepng_get_raw_size(w2, 1, &state.info_png.color);
for(size_t i = 0; i < h2; i++)
{
filterTypes[j].push_back(data[pos]);
pos += linebytes;
}
}
}
return 0; /* OK */
}
unsigned getFilterTypes(std::vector<unsigned char>& filterTypes, const std::vector<unsigned char>& png)
{
std::vector<std::vector<unsigned char> > passes;
unsigned error = getFilterTypesInterlaced(passes, png);
if(error) return error;
if(passes.size() == 1)
( run in 0.307 second using v1.01-cache-2.11-cpan-ceb78f64989 )