diff options
Diffstat (limited to 'image.cpp')
-rw-r--r-- | image.cpp | 56 |
1 files changed, 56 insertions, 0 deletions
diff --git a/image.cpp b/image.cpp new file mode 100644 index 0000000..675e22f --- /dev/null +++ b/image.cpp @@ -0,0 +1,56 @@ +#include "image.h" +#include <iostream> +#include <array> +#include <string> +#include <cstring> +#include <cassert> +#include <cmath> +#include <png.h> + + +static std::array<uint8_t, 3> render_pixel(double x) { + const double red = 1 - std::pow(1 - x, 3); + const double green = 1 - std::pow(1 - x, 3); + const double blue = 1 - std::pow(1 - x, 6); + return {(uint8_t)(red * 255), (uint8_t)(green * 255), (uint8_t)(blue * 255)}; +} + +HistImage::HistImage(size_t width, size_t height) + : width{width}, height{height}, data(width * height, 0) {} + +void HistImage::add(const HistImage &other) { + assert(width == other.width && height == other.height); + for (size_t i = 0; i < width * height; i++) data[i] += other.data[i]; +} + +void HistImage::render(const char *fname) const { + uint64_t maxval = 0; + for (size_t i = 0; i < width * height; i++) maxval = std::max(maxval, data[i]); + const double maxvald = maxval; + + std::vector<uint8_t> buffer(3 * width * height); + for (size_t i = 0; i < width * height; i++) { + const std::array<uint8_t, 3> pix = render_pixel((double)data[i] / maxvald); + memcpy(&buffer[3 * i], &pix[0], 3); + } + + png_image png; + memset(&png, 0, sizeof png); + png.version = PNG_IMAGE_VERSION; + png.width = width; + png.height = height; + png.format = PNG_FORMAT_RGB; + + int ret = png_image_write_to_file(&png, fname, 0, buffer.data(), 3 * width, NULL); + if (ret != 0 && (png.warning_or_error & 2)) { + std::string errmsg; + char *p = (char*)memchr(png.message, ' ', sizeof png.message); + if (p != NULL) { errmsg = std::string(png.message, p - png.message); } + else errmsg = std::string(png.message, sizeof png.message); + std::cerr << "PNG write failed: " << errmsg << std::endl; + } + + png_image_free(&png); +} + +// vim: set sw=4 ts=4 noet: |