From bbfa8faf5337ebdff60ef2106074417aa628eca1 Mon Sep 17 00:00:00 2001 From: Hop311 Date: Sun, 24 Sep 2023 22:42:48 +0100 Subject: Adding terrain image/type loading --- src/openvic-simulation/utility/BMP.cpp | 93 +++++++++++++++++++++++++++------- src/openvic-simulation/utility/BMP.hpp | 17 +++++-- 2 files changed, 89 insertions(+), 21 deletions(-) (limited to 'src/openvic-simulation/utility') diff --git a/src/openvic-simulation/utility/BMP.cpp b/src/openvic-simulation/utility/BMP.cpp index 531870b..2fa9417 100644 --- a/src/openvic-simulation/utility/BMP.cpp +++ b/src/openvic-simulation/utility/BMP.cpp @@ -11,13 +11,12 @@ BMP::~BMP() { close(); } -bool BMP::open(char const* filepath) { +bool BMP::open(fs::path const& filepath) { reset(); - errno = 0; - file = fopen(filepath, "rb"); - if (file == nullptr || errno != 0) { - Logger::error("Failed to open BMP file \"", filepath, "\" (errno = ", errno, ")"); - file = nullptr; + file.open(filepath, std::ios::binary); + if (file.fail()) { + Logger::error("Failed to open BMP file \"", filepath, "\""); + close(); return false; } return true; @@ -28,15 +27,17 @@ bool BMP::read_header() { Logger::error("BMP header already validated!"); return false; } - if (file == nullptr) { + if (!file.is_open()) { Logger::error("Cannot read BMP header before opening a file"); return false; } - if (fseek(file, 0, SEEK_SET) != 0) { + file.seekg(0, std::ios::beg); + if (file.fail()) { Logger::error("Failed to move to the beginning of the BMP file!"); return false; } - if (fread(&header, sizeof(header), 1, file) != 1) { + file.read(reinterpret_cast(&header), sizeof(header)); + if (file.fail()) { Logger::error("Failed to read BMP header!"); return false; } @@ -117,7 +118,11 @@ bool BMP::read_header() { } bool BMP::read_palette() { - if (file == nullptr) { + if (palette_read) { + Logger::error("BMP palette already read!"); + return false; + } + if (!file.is_open()) { Logger::error("Cannot read BMP palette before opening a file"); return false; } @@ -129,24 +134,25 @@ bool BMP::read_palette() { Logger::error("Cannot read BMP palette - header indicates this file doesn't have one"); return false; } - if (fseek(file, sizeof(header), SEEK_SET) != 0) { + file.seekg(sizeof(header), std::ios::beg); + if (file.fail()) { Logger::error("Failed to move to the palette in the BMP file!"); return false; } palette.resize(palette_size); - if (fread(palette.data(), palette_size * PALETTE_COLOUR_SIZE, 1, file) != 1) { + file.read(reinterpret_cast(palette.data()), palette_size * PALETTE_COLOUR_SIZE); + if (file.fail()) { Logger::error("Failed to read BMP header!"); palette.clear(); return false; } - return true; + palette_read = true; + return palette_read; } void BMP::close() { - if (file != nullptr) { - if (fclose(file) != 0) - Logger::error("Failed to close BMP!"); - file = nullptr; + if (file.is_open()) { + file.close(); } } @@ -156,8 +162,61 @@ void BMP::reset() { header_validated = false; palette_size = 0; palette.clear(); + pixel_data.clear(); +} + +int32_t BMP::get_width() const { + return header.width_px; +} + +int32_t BMP::get_height() const { + return header.height_px; +} + +uint16_t BMP::get_bits_per_pixel() const { + return header.bits_per_pixel; } std::vector const& BMP::get_palette() const { + if (!palette_read) { + Logger::warning("Trying to get BMP palette before loading"); + } return palette; } + +bool BMP::read_pixel_data() { + if (pixel_data_read) { + Logger::error("BMP pixel data already read!"); + return false; + } + if (!file.is_open()) { + Logger::error("Cannot read BMP pixel data before opening a file"); + return false; + } + if (!header_validated) { + Logger::error("Cannot read pixel data before BMP header is validated!"); + return false; + } + file.seekg(header.offset, std::ios::beg); + if (file.fail()) { + Logger::error("Failed to move to the pixel data in the BMP file!"); + return false; + } + const size_t pixel_data_size = get_width() * get_height() * header.bits_per_pixel / 8; + pixel_data.resize(pixel_data_size); + file.read(reinterpret_cast(pixel_data.data()), pixel_data_size); + if (file.fail()) { + Logger::error("Failed to read BMP pixel data!"); + pixel_data.clear(); + return false; + } + pixel_data_read = true; + return pixel_data_read; +} + +std::vector const& BMP::get_pixel_data() const { + if (!pixel_data_read) { + Logger::warning("Trying to get BMP pixel data before loading"); + } + return pixel_data; +} diff --git a/src/openvic-simulation/utility/BMP.hpp b/src/openvic-simulation/utility/BMP.hpp index f04b41a..c08ac99 100644 --- a/src/openvic-simulation/utility/BMP.hpp +++ b/src/openvic-simulation/utility/BMP.hpp @@ -1,11 +1,14 @@ #pragma once -#include +#include +#include #include #include "openvic-simulation/types/Colour.hpp" namespace OpenVic { + namespace fs = std::filesystem; + class BMP { #pragma pack(push) #pragma pack(1) @@ -29,10 +32,11 @@ namespace OpenVic { } header; #pragma pack(pop) - FILE* file = nullptr; - bool header_validated = false; + std::ifstream file; + bool header_validated = false, palette_read = false, pixel_data_read = false; uint32_t palette_size = 0; std::vector palette; + std::vector pixel_data; public: static constexpr uint32_t PALETTE_COLOUR_SIZE = sizeof(colour_t); @@ -40,12 +44,17 @@ namespace OpenVic { BMP() = default; ~BMP(); - bool open(char const* filepath); + bool open(fs::path const& filepath); bool read_header(); bool read_palette(); + bool read_pixel_data(); void close(); void reset(); + int32_t get_width() const; + int32_t get_height() const; + uint16_t get_bits_per_pixel() const; std::vector const& get_palette() const; + std::vector const& get_pixel_data() const; }; } -- cgit v1.2.3-56-ga3b1