I'd like to do this in a platform independant way, and I know libpng is a possibility, but I find it hard to figure out how. Does anyone know how to do this in a simple way?
                +1 
                A: 
                
                
              
            You can use Imagemagick but it does several other things as well.
                  Amit Kumar
                   2010-02-18 10:37:29
                
              
                +1 
                A: 
                
                
              I'd say libpng is still the easiest way. There's example read -> process -> write png program, it is fairly simple once you strip the error handling (setjmp/longjmp/png_jmpbuf) stuff. It doesn't get simpler than that.
                  sbk
                   2010-02-18 11:47:57
                
              Yes, I saw that. I must say, I was confused, but now that you TELL me that it's simple, it really is ;)
                  henle
                   2010-02-18 14:00:24
                
                +2 
                A: 
                
                
              There is a C++ wrapper for libpng called Png++. Check it here or just google it.
They have a real C++ interface with templates and such that uses libpng under the hood. I've found the code I have written quite expressive and high-level.
Example of "generator" which is the heart of the algorithm:
class PngGenerator : public png::generator< png::gray_pixel_1, PngGenerator>
{
  typedef png::generator< png::gray_pixel_1, PngGenerator> base_t;
public:
  typedef std::vector<char> line_t;
  typedef std::vector<line_t> picture_t;
  PngGenerator(const picture_t& iPicture) :
    base_t(iPicture.front().size(), iPicture.size()),
    _picture(iPicture), _row(iPicture.front().size())
  {
  } // PngGenerator
  png::byte* get_next_row(size_t pos)
  {
    const line_t& aLine = _picture[pos];
    for(size_t i(0), max(aLine.size()); i < max; ++i)
      _row[i] = pixel_t(aLine[i] == Png::White_256);
         // Pixel value can be either 0 or 1
         // 0: Black, 1: White
    return row_traits::get_data(_row);
  } // get_next_row
private:
  // To be transformed
  const picture_t& _picture;
  // Into
  typedef png::gray_pixel_1 pixel_t;
  typedef png::packed_pixel_row< pixel_t > row_t;
  typedef png::row_traits< row_t > row_traits;
  row_t _row; // Buffer
}; // class PngGenerator
And usage is like this:
std::ostream& Png::write(std::ostream& out)
{
  PngGenerator aPng(_picture);
  aPng.write(out);
  return out;
}
There were some bits still missing from libpng (interleaving options and such), but frankly I did not use them so it was okay for me.
                  Matthieu M.
                   2010-02-18 15:17:04