From 8e1d7c4e484ef43dddc5074055727694ceb0e37b Mon Sep 17 00:00:00 2001 From: Adrian Kummerlaender Date: Sat, 14 May 2016 16:28:50 +0200 Subject: Extract stream management into `ppm_pixel_stream`, provide Cartesian coordinates --- example.cc | 45 +++++++++++++++++++++++++-------------------- src/imgen.cc | 48 ++++++++++++++++++++++++++++++++---------------- src/imgen.h | 22 ++++++++++++++++++---- 3 files changed, 75 insertions(+), 40 deletions(-) diff --git a/example.cc b/example.cc index 18d0e78..22f5c19 100644 --- a/example.cc +++ b/example.cc @@ -3,44 +3,49 @@ #include #include -template -double minkowski_metric(int refX, int refY, int x, int y) { - return std::pow( - std::pow(std::abs(refX - x), p) + std::pow(std::abs(refY - y), p), - 1.0/p - ); +int minkowski_metric(double p, int refX, int refY, int x, int y) { + return static_cast(std::nearbyint( + std::pow( + std::pow(std::abs(refX - x), p) + std::pow(std::abs(refY - y), p), + 1.0 / p + ) + )); } -double euclidean_metric(int refX, int refY, int x, int y) { - return minkowski_metric<2>(refX, refY, x, y); +int euclidean_metric(int refX, int refY, int x, int y) { + return minkowski_metric(2, refX, refY, x, y); } int manhattan_metric(int refX, int refY, int x, int y) { - return minkowski_metric<1>(refX, refY, x, y); + return minkowski_metric(1, refX, refY, x, y); } int main(int, char*[]) { using refpos = std::tuple; - std::array ref{ - refpos(100, 50, imgen::color(255, 0, 0 )), - refpos(490, 300, imgen::color(0, 255, 0 )), - refpos(250, 250, imgen::color(0, 0, 255)), - refpos(400, 20, imgen::color(100, 10, 100)), - refpos(60, 400, imgen::color(20, 60, 300)) + std::array ref{ + refpos( 0, 0, imgen::color(255, 0, 0 )), + refpos( 100, 100, imgen::color(0, 255, 0 )), + refpos(-100, 100, imgen::color(0, 0, 255 )), + refpos( 100, -100, imgen::color(255, 255, 0 )), + refpos(-100, -100, imgen::color(0, 255, 255 )), + refpos( 200, 200, imgen::color(255, 0, 0 )), + refpos(-200, 200, imgen::color(0, 255, 0 )), + refpos( 200, -200, imgen::color(0, 255, 255 )), + refpos(-200, -200, imgen::color(255, 255, 0 )) }; imgen::write_ppm( "test.ppm", - 500, - 500, - [&ref](std::size_t x, std::size_t y) -> imgen::color { + 512, + 512, + [&ref](std::ptrdiff_t x, std::ptrdiff_t y) -> imgen::color { const refpos& nearest = *std::min_element( ref.begin(), ref.end(), [x, y](const refpos& a, const refpos& b) -> bool { - return minkowski_metric<5>(std::get<0>(a), std::get<1>(a), x, y) - < minkowski_metric<5>(std::get<0>(b), std::get<1>(b), x, y); + return euclidean_metric(std::get<0>(a), std::get<1>(a), x, y) + < euclidean_metric(std::get<0>(b), std::get<1>(b), x, y); } ); diff --git a/src/imgen.cc b/src/imgen.cc index d574672..25731e1 100644 --- a/src/imgen.cc +++ b/src/imgen.cc @@ -1,34 +1,50 @@ #include "imgen.h" -#include - namespace { inline void write_color(std::ofstream& out, const imgen::color& color) { - out << std::get<0>(color); - out << std::get<1>(color); - out << std::get<2>(color); + out << std::get<0>(color) + << std::get<1>(color) + << std::get<2>(color); } } namespace imgen { +ppm_pixel_stream::ppm_pixel_stream( + const std::string& path, + const std::size_t width, + const std::size_t height +): stream_() { + this->stream_.open(path, std::ios::binary | std::ios::out); + this->stream_.sync_with_stdio(false); + + this->stream_ << "P6\n" << width << " " << height << "\n255\n"; +} + +ppm_pixel_stream& ppm_pixel_stream::operator<<(const color& value) { + write_color(this->stream_, value); + + return *this; +} + void write_ppm( - const std::string& path, - const std::size_t sizeX, - const std::size_t sizeY, - std::function generator + const std::string& path, + const std::size_t width, + const std::size_t height, + std::function generator ) { - std::ofstream out; - out.open(path, std::ios::binary | std::ios::out); - out.sync_with_stdio(false); + ppm_pixel_stream file(path, width, height); - out << "P6\n" << sizeX << " " << sizeY << "\n255\n"; + const std::ptrdiff_t min_y = height / 2 * -1; + const std::ptrdiff_t max_y = height / 2; + const std::ptrdiff_t min_x = width / 2 * -1; + const std::ptrdiff_t max_x = width / 2; - for ( std::size_t posY = 0; posY < sizeY; ++posY ) { - for ( std::size_t posX = 0; posX < sizeX; ++posX ) { - write_color(out, generator(posX, posY)); + for ( std::ptrdiff_t posY = min_y; posY < max_y; ++posY ) { + for ( std::ptrdiff_t posX = min_x; posX < max_x; ++posX ) { + file << generator(posX, posY); } } } diff --git a/src/imgen.h b/src/imgen.h index 5ddbaf6..35b798d 100644 --- a/src/imgen.h +++ b/src/imgen.h @@ -1,16 +1,30 @@ #include #include +#include #include namespace imgen { using color = std::tuple; +class ppm_pixel_stream { + public: + ppm_pixel_stream(const std::string& path, + const std::size_t width, + const std::size_t height); + + ppm_pixel_stream& operator<<(const color& value); + + private: + std::ofstream stream_; + +}; + void write_ppm( - const std::string& path, - const std::size_t sizeX, - const std::size_t sizeY, - std::function generator + const std::string& path, + const std::size_t sizeX, + const std::size_t sizeY, + std::function generator ); } -- cgit v1.2.3