made an image object and added a way to parse through them

This commit is contained in:
luna 2025-08-03 18:43:02 +02:00
parent 9e0f25dd82
commit a8a44bd993
6 changed files with 60 additions and 84 deletions

View file

@ -6,50 +6,7 @@
#include "convert.h"
void lily_png::convert_to_ascii(file_reader::buffer<unsigned char> &src, file_reader::buffer<char> &dest, metadata &meta)
void lily_png::convert_to_ascii(image &src, image &dest)
{
auto pixel_size_ret = get_pixel_bit_size(meta);
if (!pixel_size_ret)
return ;
size_t pixel_size = pixel_size_ret.value();
size_t pixel_size_bytes = (pixel_size + 7)/8;
float aspect_ratio = get_aspect_ratio(meta);
metadata new_meta = meta;
new_meta.width = 40;
new_meta.height = 40;
file_reader::buffer<unsigned char> intermediate_resize{};
auto resize_ret = resize_image(src, intermediate_resize, meta, new_meta);
if (!resize_ret)
return ;
size_t intermediate_size = resize_ret.value();
size_t char_size = strlen("\033[38;2;255;255;255ma\033[0m ");
size_t width_char = char_size * new_meta.width;
size_t full_size = width_char * new_meta.height + new_meta.width;
dest.allocate(full_size);
size_t dest_index = 0;
size_t line_done = 0;
for (int i = 0; i < intermediate_size; i += pixel_size_bytes)
{
color_rgb tmp_color{};
tmp_color.r = intermediate_resize.data[i];
tmp_color.g = intermediate_resize.data[i + 1];
tmp_color.b = intermediate_resize.data[i + 2];
std::string format = std::format("\033[38;2;{};{};{}ma\033[0m ", tmp_color.r, tmp_color.g, tmp_color.b);
memcpy(&dest.data[dest_index], format.c_str(), format.size());
dest_index += format.size();
line_done++;
if (line_done == new_meta.width)
{
dest.data[dest_index] = '\n';
dest_index++;
line_done = 0;
}
if (dest_index >= full_size)
{
dest.data[dest_index] = '\0';
break;
}
}
}

View file

@ -7,5 +7,5 @@
namespace lily_png
{
void convert_to_ascii(file_reader::buffer<unsigned char> &src, file_reader::buffer<char> &dest, metadata &meta);
void convert_to_ascii(image &src, image &dest);
}

View file

@ -1,5 +1,7 @@
#include "lily_png.h"
#include <limits.h>
std::vector<lily_png::color_rgb> palette;
bool palette_found = false;
@ -171,11 +173,10 @@ std::expected<bool, lily_png::png_error> lily_png::apply_to_pixel(file_reader::b
return true;
}
std::expected<lily_png::metadata, lily_png::png_error> lily_png::read_png(const std::string &file_path, file_reader::buffer<unsigned char> &data)
std::expected<bool, lily_png::png_error> lily_png::read_png(const std::string &file_path, image &data)
{
file_reader::buffer<unsigned char> tmp_data{};
metadata meta{0};
auto ret = read_raw_data(file_path, tmp_data, meta);
auto ret = read_raw_data(file_path, tmp_data, data.meta);
if (!ret)
{
return std::unexpected(ret.error());
@ -183,13 +184,13 @@ std::expected<lily_png::metadata, lily_png::png_error> lily_png::read_png(const
if (palette_found == true)
{
file_reader::buffer<unsigned char> dest_palette{};
auto apply_ret = apply_palette(tmp_data, dest_palette, meta);
auto apply_ret = apply_palette(tmp_data, dest_palette, data.meta);
if (!apply_ret)
return std::unexpected(apply_ret.error());
tmp_data = dest_palette;
}
auto res = filter(tmp_data, data, meta);
auto res = filter(tmp_data, data.buffer, data.meta);
if (!res)
return std::unexpected(res.error());
return meta;
return true;
}

View file

@ -14,7 +14,7 @@
namespace lily_png
{
std::expected<bool, png_error> apply_to_pixel(file_reader::buffer<unsigned char> &src, metadata &meta, std::function<void(unsigned char *, int, size_t)> func);
std::expected<metadata, png_error> read_png(const std::string &file_path, file_reader::buffer<unsigned char> &data);
std::expected<bool, png_error> read_png(const std::string &file_path, image &data);
}
template <>

View file

@ -63,37 +63,6 @@ std::expected<size_t, lily_png::png_error> lily_png::get_uncompressed_size(const
return ret;
}
std::expected<size_t, lily_png::png_error> lily_png::resize_image(file_reader::buffer<unsigned char> &src,
file_reader::buffer<unsigned char> &dest, metadata &meta, metadata &new_meta)
{
auto pixel_size_ret = get_pixel_bit_size(meta);
if (!pixel_size_ret)
return std::unexpected(pixel_size_ret.error());
size_t pixel_size = pixel_size_ret.value();
size_t pixel_size_bytes = (pixel_size + 7)/8;
int compressed_pixels_width = meta.width / new_meta.width;
int compressed_pixels_height = meta.height / new_meta.height;
auto uncompress_ret = get_uncompressed_size(new_meta);
if (!uncompress_ret)
return std::unexpected(uncompress_ret.error());
dest.allocate(uncompress_ret.value());
for (int y = 0; y < new_meta.height; y++)
{
for (int x = 0; x < new_meta.width; x++)
{
int src_x = static_cast<int>(x * compressed_pixels_width);
int src_y = static_cast<int>(y * compressed_pixels_height);
// Calculate the linear index for the source and destination buffers
size_t dest_index = (static_cast<size_t>(y) * new_meta.width + x) * pixel_size_bytes;
size_t src_index = (static_cast<size_t>(src_y) * meta.width + src_x) * pixel_size_bytes;
memcpy(&dest.data[dest_index], &src.data[src_index], pixel_size_bytes);
}
}
return uncompress_ret.value();
}
int lily_png::paeth_predict(const int a, const int b, const int c)
{
const int pred = a+b-c;
@ -118,3 +87,22 @@ float lily_png::get_aspect_ratio(const metadata &meta)
return aspect_ratio;
}
std::expected<size_t, lily_png::png_error> lily_png::image::resize_image(image &dest)
{
size_t new_size = (dest.meta.width * pixel_size_bytes) * dest.meta.height;
dest.buffer.allocate(new_size);
//this implementation is bad but its only a test
int compressed_pixels_width = meta.width / dest.meta.width;
int compressed_pixels_height = meta.height / dest.meta.height;
for (int y = 0; y < dest.meta.height; y++)
{
for (int x = 0; x < dest.meta.width; x++)
{
*(dest[y, x]) = *(operator[](y * compressed_pixels_height, x * compressed_pixels_width));
}
}
return new_size;
}

View file

@ -1,6 +1,7 @@
#pragma once
#include "metadata.h"
#include <expected>
#include <cassert>
namespace lily_png
{
@ -13,9 +14,38 @@ namespace lily_png
invalid_bit_depth,
invalid_color_type
};
std::expected<size_t, png_error> get_pixel_bit_size(const metadata &meta);
std::expected<size_t, png_error> get_uncompressed_size(const metadata &meta);
std::expected<size_t, png_error> resize_image(file_reader::buffer<unsigned char> &src, file_reader::buffer<unsigned char> &dest, metadata &meta, metadata &new_meta);
int paeth_predict(const int a, const int b, const int c);
float get_aspect_ratio(const metadata &meta);
struct image
{
image()
{
auto pixel_size_ret = get_pixel_bit_size(meta).or_else([] (png_error error)
{
return std::expected<size_t, png_error>(0);
});
pixel_size = pixel_size_ret.value();
pixel_size_bytes = (pixel_size + 7)/8;
}
file_reader::buffer<unsigned char> buffer{};
metadata meta{};
constexpr unsigned char *operator[](std::size_t y, std::size_t x) const
{
if (x > meta.width || y > meta.height)
return nullptr;
const size_t calculate = (y * meta.width + x) * pixel_size_bytes;
return &buffer.data[calculate];
}
std::expected<size_t, png_error> resize_image(image &dest);
private:
size_t pixel_size;
size_t pixel_size_bytes;
};
}