Make ImageWriter an abstract base class; add PngImageWriter
This commit is contained in:
1 parent
a233b746c2
commit
d764740b54
4 files changed
+60
-41
No files matched your search
@@ -1,51 +1,15 @@
|
|||||||
#include <fart/ImageWriter.h>
|
#include <fart/ImageWriter.h>
|
||||||
#include <png.h>
|
#include <fart/PngImageWriter.h>
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <algorithm>
|
|
||||||
#include <cmath>
|
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
static uint8_t to_byte(double v)
|
ImageWriter * ImageWriter::build(const std::string & fname)
|
||||||
{
|
|
||||||
return (uint8_t)std::lround(std::clamp(v, 0.0, 1.0) * 255.0);
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool write_png(const Image & image, const std::string & fname)
|
|
||||||
{
|
|
||||||
std::vector<uint8_t> buffer(image.width * image.height * 4u);
|
|
||||||
for (size_t i = 0u; i < image.pixels.size(); i++)
|
|
||||||
{
|
|
||||||
const Color & c = image.pixels[i];
|
|
||||||
buffer[i * 4u + 0u] = to_byte(c.r);
|
|
||||||
buffer[i * 4u + 1u] = to_byte(c.g);
|
|
||||||
buffer[i * 4u + 2u] = to_byte(c.b);
|
|
||||||
buffer[i * 4u + 3u] = to_byte(c.a);
|
|
||||||
}
|
|
||||||
|
|
||||||
png_image png = {};
|
|
||||||
png.version = PNG_IMAGE_VERSION;
|
|
||||||
png.width = image.width;
|
|
||||||
png.height = image.height;
|
|
||||||
png.format = PNG_FORMAT_RGBA;
|
|
||||||
|
|
||||||
if (!png_image_write_to_file(&png, fname.c_str(), 0, buffer.data(), 0, nullptr))
|
|
||||||
{
|
|
||||||
fprintf(stderr, "Error writing PNG file '%s': %s\n", fname.c_str(), png.message);
|
|
||||||
png_image_free(&png);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ImageWriter::write(const Image & image, const std::string & fname)
|
|
||||||
{
|
{
|
||||||
std::string ext = std::filesystem::path(fname).extension().string();
|
std::string ext = std::filesystem::path(fname).extension().string();
|
||||||
if (ext == ".png")
|
if (ext == ".png")
|
||||||
{
|
{
|
||||||
return write_png(image, fname);
|
return new PngImageWriter(fname);
|
||||||
}
|
}
|
||||||
fprintf(stderr, "Unsupported output image format: '%s'\n", fname.c_str());
|
fprintf(stderr, "Unsupported output image format: '%s'\n", fname.c_str());
|
||||||
return false;
|
return nullptr;
|
||||||
}
|
}
|
||||||
@@ -6,5 +6,11 @@
|
|||||||
class ImageWriter
|
class ImageWriter
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static bool write(const Image & image, const std::string & fname);
|
static ImageWriter * build(const std::string & fname);
|
||||||
|
virtual ~ImageWriter() = default;
|
||||||
|
virtual bool write(const Image & image) = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
ImageWriter(const std::string & fname) : fname(fname) {}
|
||||||
|
std::string fname;
|
||||||
};
|
};
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
#include <fart/PngImageWriter.h>
|
||||||
|
#include <png.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <cmath>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
static uint8_t to_byte(double v)
|
||||||
|
{
|
||||||
|
return (uint8_t)std::lround(std::clamp(v, 0.0, 1.0) * 255.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PngImageWriter::write(const Image & image)
|
||||||
|
{
|
||||||
|
std::vector<uint8_t> buffer(image.width * image.height * 4u);
|
||||||
|
for (size_t i = 0u; i < image.pixels.size(); i++)
|
||||||
|
{
|
||||||
|
const Color & c = image.pixels[i];
|
||||||
|
buffer[i * 4u + 0u] = to_byte(c.r);
|
||||||
|
buffer[i * 4u + 1u] = to_byte(c.g);
|
||||||
|
buffer[i * 4u + 2u] = to_byte(c.b);
|
||||||
|
buffer[i * 4u + 3u] = to_byte(c.a);
|
||||||
|
}
|
||||||
|
|
||||||
|
png_image png = {};
|
||||||
|
png.version = PNG_IMAGE_VERSION;
|
||||||
|
png.width = image.width;
|
||||||
|
png.height = image.height;
|
||||||
|
png.format = PNG_FORMAT_RGBA;
|
||||||
|
|
||||||
|
if (!png_image_write_to_file(&png, fname.c_str(), 0, buffer.data(), 0, nullptr))
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Error writing PNG file '%s': %s\n", fname.c_str(), png.message);
|
||||||
|
png_image_free(&png);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <fart/ImageWriter.h>
|
||||||
|
|
||||||
|
class PngImageWriter : public ImageWriter
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PngImageWriter(const std::string & fname) : ImageWriter(fname) {}
|
||||||
|
bool write(const Image & image) override;
|
||||||
|
};
|
||||||
Reference in new issue
Block a user