diff --git a/file_reader b/file_reader index 54a063d..27ba379 160000 --- a/file_reader +++ b/file_reader @@ -1 +1 @@ -Subproject commit 54a063d5e6ab8ea06b1101154574d2eaeebbde5f +Subproject commit 27ba3791017f33bb60cc9775c2d8a5a44f400a41 diff --git a/src/convert.cpp b/src/convert.cpp index 40207d8..2aacc30 100644 --- a/src/convert.cpp +++ b/src/convert.cpp @@ -1,9 +1,71 @@ #include "convert.h" -void lily_png::convert_to_R32G32B32A32(file_reader::buffer &data, metadata &meta) +std::expected lily_png::convert_to_R32G32B32A32(file_reader::buffer &data, file_reader::buffer &dest, metadata &meta) { if (meta.color_type != static_cast(color::rgba)) - { + return std::unexpected(CONVERT_ERROR::color_type_mismatch); + if (!(meta.bit_depth == 8 || meta.bit_depth == 16)) + return std::unexpected(CONVERT_ERROR::non_standard_bit_depth); + size_t size = get_uncompressed_size(meta); + size_t dest_size = 0; + if (meta.bit_depth == 8) + { + dest_size = size * 4; + std::tuple pixel; + constexpr std::size_t size_tup = std::tuple_size_v; + dest.allocate(dest_size); + size_t dest_index = 0; + for (int i = 0; i < size; i += 4) + { + file_reader::parsing_buffer par_buf(data); + par_buf.point = &par_buf.buf.data[i]; + par_buf.consumed_size = 0; + read_comp(size_tup, par_buf, pixel); + color_rgba32 tmp{0}; + tmp.r = std::get<0>(pixel); + tmp.g = std::get<1>(pixel); + tmp.b = std::get<2>(pixel); + tmp.a = std::get<3>(pixel); + memcpy(&dest.data[dest_index], &tmp.r, sizeof(unsigned int)); + dest_index += sizeof(unsigned int); + memcpy(&dest.data[dest_index], &tmp.g, sizeof(unsigned int)); + dest_index += sizeof(unsigned int); + memcpy(&dest.data[dest_index], &tmp.b, sizeof(unsigned int)); + dest_index += sizeof(unsigned int); + memcpy(&dest.data[dest_index], &tmp.a, sizeof(unsigned int)); + dest_index += sizeof(unsigned int); + } } + + else if (meta.bit_depth == 16) + { + dest_size = size * 2; + std::tuple pixel; + constexpr std::size_t size_tup = std::tuple_size_v; + dest.allocate(dest_size); + size_t dest_index = 0; + for (int i = 0; i < size; i += 4 * sizeof(unsigned short)) + { + file_reader::parsing_buffer par_buf(data); + par_buf.point = &par_buf.buf.data[i]; + par_buf.consumed_size = 0; + read_comp(size_tup, par_buf, pixel); + color_rgba32 tmp{0}; + tmp.r = std::get<0>(pixel); + tmp.g = std::get<1>(pixel); + tmp.b = std::get<2>(pixel); + tmp.a = std::get<3>(pixel); + memcpy(&dest.data[dest_index], &tmp.r, sizeof(unsigned int)); + dest_index += sizeof(unsigned int); + memcpy(&dest.data[dest_index], &tmp.g, sizeof(unsigned int)); + dest_index += sizeof(unsigned int); + memcpy(&dest.data[dest_index], &tmp.b, sizeof(unsigned int)); + dest_index += sizeof(unsigned int); + memcpy(&dest.data[dest_index], &tmp.a, sizeof(unsigned int)); + dest_index += sizeof(unsigned int); + } + } + + return true; } diff --git a/src/convert.h b/src/convert.h index 95503a8..d41d02e 100644 --- a/src/convert.h +++ b/src/convert.h @@ -1,8 +1,40 @@ #pragma once #include "../file_reader/src/buffer.h" #include "metadata.h" +#include "utils.h" +#include +#include namespace lily_png { - void convert_to_R32G32B32A32(file_reader::buffer &data, metadata &meta); + struct color_rgb + { + unsigned char r = 0; + unsigned char g = 0; + unsigned char b = 0; + }; + + struct color_rgba + { + unsigned char r = 0; + unsigned char g = 0; + unsigned char b = 0; + unsigned char a = 0; + }; + + struct color_rgba32 + { + unsigned int r = 0; + unsigned int g = 0; + unsigned int b = 0; + unsigned int a = 0; + }; + + enum class CONVERT_ERROR + { + color_type_mismatch, + non_standard_bit_depth + }; + + std::expected convert_to_R32G32B32A32(file_reader::buffer &data, file_reader::buffer &dest, metadata &meta); } diff --git a/src/filter.cpp b/src/filter.cpp index 177ef19..6d7e862 100644 --- a/src/filter.cpp +++ b/src/filter.cpp @@ -1,6 +1,6 @@ #include "filter.h" -void lily_png::filter_scanline(unsigned char *scanline, unsigned char *previous_scanline, unsigned char *dest, metadata &meta, unsigned char filter_type) +std::expected lily_png::filter_scanline(unsigned char *scanline, unsigned char *previous_scanline, unsigned char *dest, metadata &meta, unsigned char filter_type) { size_t pixel_size = get_pixel_bit_size(meta); size_t pixel_size_bytes = (pixel_size + 7)/8; @@ -37,13 +37,13 @@ void lily_png::filter_scanline(unsigned char *scanline, unsigned char *previous_ dest[i] = scanline[i] + paeth_predict(a, b, c); break; default: - std::println("Non standard filter"); - break; + return std::unexpected(png_error::non_standard_filter); } } + return true; } -void lily_png::filter(file_reader::buffer &data, file_reader::buffer &dest , metadata &meta) +std::expected lily_png::filter(file_reader::buffer &data, file_reader::buffer &dest , metadata &meta) { unsigned long index = 0; unsigned long index_dest = 0; @@ -57,7 +57,9 @@ void lily_png::filter(file_reader::buffer &data, file_reader::buf { unsigned char filter = data.data[index]; std::println("Filter {}", filter); - filter_scanline(&data.data[index + 1], previous_scanline, &dest.data[index_dest], meta, filter); + auto res = filter_scanline(&data.data[index + 1], previous_scanline, &dest.data[index_dest], meta, filter); + if (!res) + return std::unexpected(res.error()); previous_scanline = &dest.data[index_dest]; index += scanline_size + 1; index_dest += scanline_size; diff --git a/src/filter.h b/src/filter.h index 3bbd496..8fec0fb 100644 --- a/src/filter.h +++ b/src/filter.h @@ -4,7 +4,7 @@ namespace lily_png { - void filter_scanline(unsigned char *scanline, unsigned char *previous_scanline, unsigned char *dest, metadata &meta, unsigned char filter_type); - void filter(file_reader::buffer &data, file_reader::buffer &dest ,metadata &meta); + std::expected lily_png::filter_scanline(unsigned char *scanline, unsigned char *previous_scanline, unsigned char *dest, metadata &meta, unsigned char filter_type); + std::expected filter(file_reader::buffer &data, file_reader::buffer &dest ,metadata &meta); } diff --git a/src/lily_png.cpp b/src/lily_png.cpp index 2b1d98e..d8a3ee2 100644 --- a/src/lily_png.cpp +++ b/src/lily_png.cpp @@ -153,6 +153,8 @@ std::expected lily_png::read_png(const apply_palette(tmp_data, dest_palette, meta); tmp_data = dest_palette; } - filter(tmp_data, data, meta); + auto res = filter(tmp_data, data, meta); + if (!res) + return std::unexpected(res.error()); return meta; } diff --git a/src/lily_png.h b/src/lily_png.h index e935f9a..b1adaa4 100644 --- a/src/lily_png.h +++ b/src/lily_png.h @@ -6,26 +6,11 @@ #include #include "utils.h" #include "filter.h" +#include "convert.h" #include namespace lily_png { - struct color_rgb - { - unsigned char r = 0; - unsigned char g = 0; - unsigned char b = 0; - }; - - enum class png_error - { - file_doesnt_exist, - read_failed, - file_is_not_a_png - }; - - - std::expected read_png(const std::string &file_path, file_reader::buffer &data); } diff --git a/src/utils.cpp b/src/utils.cpp index 6354d85..d2d39a0 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -4,7 +4,6 @@ size_t lily_png::get_pixel_bit_size(const metadata &meta) { size_t ret = 0; - std::println("Bit depth {} color {}", (int)meta.bit_depth, (int)meta.color_type); switch (meta.color_type) { case static_cast(color::grayscale): @@ -55,7 +54,6 @@ size_t lily_png::get_pixel_bit_size(const metadata &meta) size_t lily_png::get_uncompressed_size(const metadata &meta) { - std::println("metadata{{ width: {}, height: {}, bit_depth: {}, color_type: {}, compression: {}, filter: {}, interface: {} }}", meta.width, meta.height, (int)meta.bit_depth, (int)meta.color_type, (int)meta.compression, (int)meta.filter, (int)meta.interface); size_t ret = (meta.width * get_pixel_bit_size(meta) + 7)/8; //ceil() but for bytes ret = (ret + 1) * meta.height; std::println("Uncompressed size {}", ret); diff --git a/src/utils.h b/src/utils.h index ae29df7..3d68654 100644 --- a/src/utils.h +++ b/src/utils.h @@ -3,6 +3,13 @@ namespace lily_png { + enum class png_error + { + file_doesnt_exist, + read_failed, + file_is_not_a_png, + non_standard_filter + }; size_t get_pixel_bit_size(const metadata &meta); size_t get_uncompressed_size(const metadata &meta); int paeth_predict(const int a, const int b, const int c);