1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
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:
|