From 8cb751ff015271e1844feece5db2113eaec64af3 Mon Sep 17 00:00:00 2001 From: Frederico Linhares Date: Fri, 23 Jun 2023 20:45:23 -0300 Subject: feat Create an interface to read binary files * test/meshes/cube.cgmesh: Store data using Big-Endian order. --- src/vk/qoi.cpp | 85 +++++++++++++++------------------------------------------- 1 file changed, 22 insertions(+), 63 deletions(-) (limited to 'src/vk/qoi.cpp') diff --git a/src/vk/qoi.cpp b/src/vk/qoi.cpp index 8b7ef9e..4e2b2a4 100644 --- a/src/vk/qoi.cpp +++ b/src/vk/qoi.cpp @@ -19,6 +19,8 @@ #include #include +#include "../binary_reader.hpp" + namespace { @@ -88,26 +90,6 @@ color_hash(const RGBA &colors) return colors.red*3 + colors.green*5 + colors.blue*7 + colors.alpha*11; } -void -read_chars(uint8_t *data, int &p, char *str, int size) -{ - for(int i{0}; i < size; i++) str[i] = (char)data[p++]; -} - -void -read_ui8(uint8_t *data, int &p, uint8_t &num) -{ - num = data[p++]; -} - -void -read_ui32(uint8_t *data, int &p, uint32_t &num) -{ - uint8_t b1{data[p++]}, b2{data[p++]}, b3{data[p++]}, b4{data[p++]}; - - num = b1 << 24 | b2 << 16 | b3 << 8 | b4; -} - } namespace VK::QOI @@ -116,38 +98,22 @@ namespace VK::QOI Image::Image(const char *file_path, uint8_t channels): channels{channels} { - int data_p{0}; - int data_size; - uint8_t *data; - if(this->channels != 0 && this->channels != 3 && this->channels != 4) { throw std::invalid_argument{"invalid number of channels"}; } - { // Read data from file. - std::ifstream file(file_path, std::ios::binary | std::ios::ate); - if(!file) - { - throw std::runtime_error{"failed to open QOI file"}; - } - - data_size = file.tellg(); - if(data_size < HEADER_SIZE + (int)sizeof(PADDING)) - { - throw std::runtime_error{"invalid QOI file"}; - } - - file.seekg(0); - data = new uint8_t[data_size]; - file.read((char*)data, data_size); + BinaryReader input{file_path}; + if(input.size() < HEADER_SIZE + (int)sizeof(PADDING)) + { + throw std::runtime_error{"invalid QOI file"}; } - read_chars(data, data_p, this->header.magic, 4); - read_ui32(data, data_p, this->header.width); - read_ui32(data, data_p, this->header.height); - read_ui8(data, data_p, this->header.channels); - read_ui8(data, data_p, this->header.colorspace); + input.read_chars(this->header.magic, 4); + this->header.width = input.read_ui32(); + this->header.height = input.read_ui32(); + this->header.channels = input.read_ui8(); + this->header.colorspace = input.read_ui8(); if(this->header.width == 0 || this->header.height == 0 || this->header.channels < 3 || this->header.channels > 4 || @@ -165,7 +131,7 @@ Image::Image(const char *file_path, uint8_t channels): std::array index; Pixel pixel{}; - int chunks_len = data_size - (int)sizeof(PADDING); + int chunks_len = input.size() - (int)sizeof(PADDING); /* This algorithm is based on the original implementation that is in GitHub: @@ -181,25 +147,22 @@ Image::Image(const char *file_path, uint8_t channels): { run--; } - else if(data_p < chunks_len) + else if(input.pointer() < chunks_len) { - uint8_t output; - int b1; - read_ui8(data, data_p, output); - b1 = output; + int b1 = input.read_ui8(); if (b1 == OP_RGB) { - read_ui8(data, data_p, pixel.colors.red); - read_ui8(data, data_p, pixel.colors.green); - read_ui8(data, data_p, pixel.colors.blue); + pixel.colors.red = input.read_ui8(); + pixel.colors.green = input.read_ui8(); + pixel.colors.blue = input.read_ui8(); } else if (b1 == OP_RGBA) { - read_ui8(data, data_p, pixel.colors.red); - read_ui8(data, data_p, pixel.colors.green); - read_ui8(data, data_p, pixel.colors.blue); - read_ui8(data, data_p, pixel.colors.alpha); + pixel.colors.red = input.read_ui8(); + pixel.colors.green = input.read_ui8(); + pixel.colors.blue = input.read_ui8(); + pixel.colors.alpha = input.read_ui8(); } else if ((b1 & MASK_2_BITS) == OP_INDEX) { @@ -213,9 +176,7 @@ Image::Image(const char *file_path, uint8_t channels): } else if ((b1 & MASK_2_BITS) == OP_LUMA) { - int b2; - read_ui8(data, data_p, output); - b2 = output; + int b2 = input.read_ui8(); int vg = (b1 & 0x3f) - 32; pixel.colors.red += vg - 8 + ((b2 >> 4) & 0x0f); pixel.colors.green += vg; @@ -234,8 +195,6 @@ Image::Image(const char *file_path, uint8_t channels): this->pixels[pixel_p++] = pixel.colors.blue; if(this->channels == 4) this->pixels[pixel_p++] = pixel.colors.alpha; } - - delete[] data; } Image::~Image() -- cgit v1.2.3