diff --git a/ppmimage.cpp b/ppmimage.cpp index 8695938..dafa791 100755 --- a/ppmimage.cpp +++ b/ppmimage.cpp @@ -1,34 +1,20 @@ -#include #include "ppmimage.hpp" -int PPMImage::getHeigth() const -{ - return heigth; -} - -int PPMImage::getWidth() const -{ - return width; -} - -std::vector PPMImage::getData() const -{ - return data; -} +//TODO:: write tests -- this code compiles :-) -PPMImage::PPMImage(int width, int heigth):width(width), heigth(heigth) -{ - for (int i = 0; i < width * heigth; ++i) { - data.push_back(Color(0.0f, 0.0f, 0.0f)); - } -} +constexpr auto P3MARKER = "P3"; +constexpr auto PPMNL = '\n'; +constexpr auto PPMSPACE = ' '; +constexpr auto PPMMAGIC = 255; std::ostream &operator <<(std::ostream &stream, const PPMImage &image) { - stream << "P3\n" << image.getWidth() << " " << image.getHeigth() << "\n255\n"; + stream << P3MARKER << PPMNL << image.width << PPMSPACE << image.height << PPMNL << PPMMAGIC << PPMNL; + if( !stream ) return stream; - for (auto color: image.getData()) { - stream << color.r() << " " << color.g() << " " << color.b() << std::endl; + for ( const auto& color: image.data ) { + stream << color.r() << PPMSPACE << color.g() << PPMSPACE << color.b() << PPMNL; + if( !stream ) return stream; } return stream; @@ -36,5 +22,32 @@ std::ostream &operator <<(std::ostream &stream, const PPMImage &image) std::istream &operator >>(std::istream &stream, PPMImage &image) { + if( !stream ) return stream; + std::string p3; + stream >> p3; + if( !stream ) return stream; + if( p3 != P3MARKER ) { + stream.setstate(std::ios_base::failbit); + return stream; + } + size_t width, height, magic; + stream >> width >> height >> magic; + if( !stream ) return stream; + if( magic != PPMMAGIC ) { + stream.setstate(std::ios_base::failbit); + return stream; + } + std::vector data; + data.reserve(width*height); // avoid reallocations and copies + + for( auto count = width*height; count --> 0; ) { + float r, g, b; + stream >> r >> g >> b; + if( !stream ) return stream; + data.emplace_back(r, g, b); + } + image = PPMImage { width, height, data }; + + return stream; } diff --git a/ppmimage.hpp b/ppmimage.hpp index 45a458f..5fe0343 100755 --- a/ppmimage.hpp +++ b/ppmimage.hpp @@ -5,17 +5,18 @@ #include #include "color.hpp" -class PPMImage -{ -private: +// PPMImage is semi-immutable: one can manipulate in-place the individual pixels but you can't +// resize the image. The array of pixels will be moved whenever possible. + +struct PPMImage { + const size_t width; + const size_t height; std::vector data; - int width; - int heigth; -public: - PPMImage(int width, int heigth); - int getHeigth() const; - int getWidth() const; - std::vector getData() const; + PPMImage(size_t width_, size_t height_) : width {width_}, height {height_}, data {width*height, Color{.0f, .0f, .0f}} {} + PPMImage(size_t width_, size_t height_, std::vector const& data_) : width {width_}, height {height_}, data {data_} {} + PPMImage(size_t width_, size_t height_, std::vector && data_) : width {width_}, height {height_}, data {std::move(data_)} {} + PPMImage& operator=(PPMImage const& image) { new(this) PPMImage { image.width, image.height, image.data }; return *this; } + PPMImage& operator=(PPMImage && image) { new(this) PPMImage { image.width, image.height, std::move(image.data) }; return *this; } }; std::ostream& operator <<(std::ostream &stream, PPMImage const &image);