summaryrefslogtreecommitdiff
path: root/image.cpp
diff options
context:
space:
mode:
authorTom Smeding <tom@tomsmeding.com>2025-09-03 23:31:40 +0200
committerTom Smeding <tom@tomsmeding.com>2025-09-03 23:37:53 +0200
commit7e60437d3c064bca402d486be967c43bf4326067 (patch)
tree8b4307b90c942861176d9c705cd760b9fe7b6c6b /image.cpp
Initial (with old code)HEADmaster
This includes old code too, perhaps from 2021-05-05, judging from the birth timestamp on the directory. The old code included option parsing and equation solving for fancy mutually-dependent options, but no actual rendering (imagine that).
Diffstat (limited to 'image.cpp')
-rw-r--r--image.cpp56
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: