#include "image.h" #include #include #include #include #include #include #include static std::array 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 buffer(3 * width * height); for (size_t i = 0; i < width * height; i++) { const std::array 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: