Ejemplo n.º 1
0
/*
Display the names and sizes of all chunks in the PNG file.
*/
void displayChunkNames(const std::vector<unsigned char>& buffer)
{
  // Listing chunks is based on the original file, not the decoded png info.
  const unsigned char *chunk, *begin, *end, *next;
  end = &buffer.back() + 1;
  begin = chunk = &buffer.front() + 8;

  std::cout << std::endl << "Chunks:" << std::endl;
  std::cout << " type: length(s)";
  std::string last_type;
  while(chunk + 8 < end && chunk >= begin)
  {
    char type[5];
    lodepng_chunk_type(type, chunk);
    if(std::string(type).size() != 4)
    {
      std::cout << "this is probably not a PNG" << std::endl;
      return;
    }

    if(last_type != type)
    {
      std::cout << std::endl;
      std::cout << " " << type << ": ";
    }
    last_type = type;

    std::cout << lodepng_chunk_length(chunk) << ", ";

    next = lodepng_chunk_next_const(chunk);
    if (next <= chunk) break; // integer overflow
    chunk = next;
  }
  std::cout << std::endl;
}
Ejemplo n.º 2
0
unsigned getChunkInfo(std::vector<std::string>& names, std::vector<size_t>& sizes,
                      const std::vector<unsigned char>& png)
{
  // Listing chunks is based on the original file, not the decoded png info.
  const unsigned char *chunk, *begin, *end, *next;
  end = &png.back() + 1;
  begin = chunk = &png.front() + 8;

  while(chunk + 8 < end && chunk >= begin)
  {
    char type[5];
    lodepng_chunk_type(type, chunk);
    if(std::string(type).size() != 4) return 1;

    unsigned length = lodepng_chunk_length(chunk);
    if(chunk + length + 12 > end) return 1;
    names.push_back(type);
    sizes.push_back(length);

    next = lodepng_chunk_next_const(chunk);
    if (next <= chunk) return 1; // integer overflow
    chunk = next;
  }
  return 0;
}
Ejemplo n.º 3
0
	unsigned getChunks(std::vector<std::string> names[3],
					   std::vector<std::vector<unsigned char> > chunks[3],
					   const std::vector<unsigned char>& png) {
		const unsigned char *chunk, *next, *begin, *end;
		end = &png.back() + 1;
		begin = chunk = &png.front() + 8;

		int location = 0;

		while (chunk + 8 < end && chunk >= begin) {
			char type[5];
			lodepng_chunk_type(type, chunk);
			std::string name(type);
			if (name.size() != 4) return 1;

			next = lodepng_chunk_next_const(chunk);

			if (name == "IHDR") {
				location = 0;
			} else if (name == "PLTE") {
				location = 1;
			} else if (name == "IDAT") {
				location = 2;
			} else if (name != "IEND") {
				names[location].push_back(name);
				chunks[location].push_back(std::vector<unsigned char>(chunk, next));
			}

			chunk = next;
		}
		return 0;
	}
Ejemplo n.º 4
0
unsigned insertChunks(std::vector<unsigned char>& png,
                      const std::vector<std::vector<unsigned char> > chunks[3])
{
  const unsigned char *chunk, *next, *begin, *end;
  end = &png.back() + 1;
  begin = chunk = &png.front() + 8;

  ptrdiff_t l0 = 0; //location 0: IHDR-l0-PLTE (or IHDR-l0-l1-IDAT)
  ptrdiff_t l1 = 0; //location 1: PLTE-l1-IDAT (or IHDR-l0-l1-IDAT)
  ptrdiff_t l2 = 0; //location 2: IDAT-l2-IEND

  while(chunk + 8 < end && chunk >= begin)
  {
    char type[5];
    lodepng_chunk_type(type, chunk);
    std::string name(type);
    if(name.size() != 4) return 1;

    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;
}
Ejemplo n.º 5
0
/*
Show the filtertypes of each scanline in this PNG image.
*/
void displayFilterTypes(const std::vector<unsigned char>& buffer, bool ignore_checksums)
{
  //Get color type and interlace type
  lodepng::State state;
  if(ignore_checksums)
  {
    state.decoder.ignore_crc = 1;
    state.decoder.zlibsettings.ignore_adler32 = 1;
  }
  unsigned w, h;
  unsigned error;
  error = lodepng_inspect(&w, &h, &state, &buffer[0], buffer.size());

  if(error)
  {
    std::cout << "inspect error " << error << ": " << lodepng_error_text(error) << std::endl;
    return;
  }

  if(state.info_png.interlace_method == 1)
  {
    std::cout << "showing filtertypes for interlaced PNG not supported by this example" << std::endl;
    return;
  }

  //Read literal data from all IDAT chunks
  const unsigned char *chunk, *begin, *end, *next;
  end = &buffer.back() + 1;
  begin = chunk = &buffer.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)
    {
      std::cout << "this is probably not a PNG" << std::endl;
      return;
    }

    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 > buffer.size() || chunk + clength + 12 < begin) {
        std::cout << "invalid chunk length" << std::endl;
        return;
      }

      for(unsigned i = 0; i < clength; i++)
      {
        zdata.push_back(cdata[i]);
      }
    }

    next = lodepng_chunk_next_const(chunk);
    if (next <= chunk) break; // integer overflow
    chunk = next;
  }

  //Decompress all IDAT data
  std::vector<unsigned char> data;
  error = lodepng::decompress(data, &zdata[0], zdata.size());

  if(error)
  {
    std::cout << "decompress error " << error << ": " << lodepng_error_text(error) << std::endl;
    return;
  }

  //A line is 1 filter byte + all pixels
  size_t linebytes = 1 + lodepng_get_raw_size(w, 1, &state.info_png.color);

  if(linebytes == 0)
  {
    std::cout << "error: linebytes is 0" << std::endl;
    return;
  }

  std::cout << "Filter types: ";
  for(size_t i = 0; i < data.size(); i += linebytes)
  {
    std::cout << (int)(data[i]) << " ";
  }
  std::cout << std::endl;

}
Ejemplo n.º 6
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 || ADAM7_IY[j] >= h) w2 = 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 */
}