From cf90f057fe6fc0f882a0e6e30ea9fe55106d81a9 Mon Sep 17 00:00:00 2001 From: Redacted Date: Thu, 10 Oct 2024 11:44:00 -0400 Subject: [PATCH] Refactor & Fixes. Rename to better fit the scope of this project. Allow loading an image from Color3* & Color4* --- CMakeLists.txt | 27 ++++++--- include/ReImage/Image.h | 31 ++++++++++ include/{ReTexture => ReImage}/flags.h | 3 +- include/ReTexture/Texture.h | 29 --------- main.cpp | 8 +-- src/{Texture.cpp => Image.cpp} | 84 ++++++++++++++++---------- 6 files changed, 108 insertions(+), 74 deletions(-) create mode 100644 include/ReImage/Image.h rename include/{ReTexture => ReImage}/flags.h (87%) delete mode 100644 include/ReTexture/Texture.h rename src/{Texture.cpp => Image.cpp} (56%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 30a02e8..10b98cb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ cmake_minimum_required(VERSION 3.18) -project(ReTexture +project(ReImage VERSION 1.0 LANGUAGES CXX ) @@ -11,6 +11,11 @@ include(cmake/CPM.cmake) set(CMAKE_CXX_STANDARD 20) +CPMAddPackage( + NAME mcolor + URL https://git.redacted.cc/maxine/mcolor/archive/Prerelease-4.zip +) + file(GLOB_RECURSE HEADERS "include/*.h") file(GLOB_RECURSE SOURCES "src/*.cpp") file(COPY "testImages" DESTINATION "${PROJECT_BINARY_DIR}") @@ -20,16 +25,22 @@ if (PROJECT_SOURCE_DIR STREQUAL PROJECT_BINARY_DIR) endif() if (UNIX AND NOT APPLE) - add_library(ReTexture SHARED ${SOURCES} ${HEADERS}) + add_library(ReImage SHARED ${SOURCES} ${HEADERS}) endif() if (WIN32) - add_library(ReTexture STATIC ${SOURCES} ${HEADERS}) + add_library(ReImage STATIC ${SOURCES} ${HEADERS}) endif() -target_include_directories(ReTexture PUBLIC ${PROJECT_SOURCE_DIR}/include) -add_executable(ReTextureTest main.cpp) +target_include_directories( + ReImage PUBLIC + ${PROJECT_SOURCE_DIR}/include + ${mcolor_SOURCE_DIR}/include -set_target_properties(ReTexture PROPERTIES LINKER_LANGUAGE CXX) -set_target_properties(ReTextureTest PROPERTIES LINKER_LANGUAGE CXX) -target_link_libraries(ReTextureTest PUBLIC ReTexture) +) +add_executable(ReImageTest main.cpp) + +set_target_properties(ReImage PROPERTIES LINKER_LANGUAGE CXX) +set_target_properties(ReImageTest PROPERTIES LINKER_LANGUAGE CXX) +target_link_libraries(ReImage PUBLIC mcolor) +target_link_libraries(ReImageTest PUBLIC ReImage) diff --git a/include/ReImage/Image.h b/include/ReImage/Image.h new file mode 100644 index 0000000..24809d1 --- /dev/null +++ b/include/ReImage/Image.h @@ -0,0 +1,31 @@ +#pragma once + +#include +#include +#include +#include + +namespace ReImage { + class Image { + private: + unsigned int width = 0; + unsigned int height = 0; + TextureFormat format; + TextureFlag flags; + Image(std::vector& pixel_data, TextureFormat format, unsigned int width, unsigned int height); + void load(const std::string& file); + void loadBMP(const std::string& file); + void loadPNG(const std::string& file); + void invertY(); + public: + std::vector pixel_data; + Image(const std::string& file, const TextureFlag& flags); + Image(const Color4* data, const size_t& length, unsigned int width, unsigned int height, TextureFlag flags = TextureFlag::NONE); + Image(const Color3* data, const size_t& length, unsigned int width, unsigned int height, TextureFlag flags = TextureFlag::NONE); + Image downscale(unsigned int rhs); + [[nodiscard]] unsigned int getWidth() const; + [[nodiscard]] unsigned int getHeight() const; + TextureFormat getTextureFormat(); + TextureFlag getFlags(); + }; +} \ No newline at end of file diff --git a/include/ReTexture/flags.h b/include/ReImage/flags.h similarity index 87% rename from include/ReTexture/flags.h rename to include/ReImage/flags.h index 1965cc1..92cddd9 100644 --- a/include/ReTexture/flags.h +++ b/include/ReImage/flags.h @@ -1,10 +1,9 @@ #pragma once -namespace ReTexture { +namespace ReImage { enum TextureFlag { NONE = 0, INVERT_Y = 1, - INVERT_X = 2, }; inline TextureFlag operator|(TextureFlag a, TextureFlag b) { diff --git a/include/ReTexture/Texture.h b/include/ReTexture/Texture.h deleted file mode 100644 index 821ae89..0000000 --- a/include/ReTexture/Texture.h +++ /dev/null @@ -1,29 +0,0 @@ -#pragma once - -#include -#include -#include - -namespace ReTexture { - class SoftwareTexture { - private: - unsigned int width = 0; - unsigned int height = 0; - TextureFormat format; - TextureFlag flags; - void load(const std::string& file); - void loadBMP(const std::string& file); - void loadPNG(const std::string& file); - void invertY(); - public: - std::vector pixelData; - explicit SoftwareTexture(const std::string& file); - SoftwareTexture(const std::string& file, const TextureFlag& flags); - SoftwareTexture(const std::vector& pixel_data, TextureFormat format, unsigned int width, unsigned int height); - SoftwareTexture downscale(unsigned int rhs); - [[nodiscard]] unsigned int getWidth() const; - [[nodiscard]] unsigned int getHeight() const; - TextureFormat getTextureFormat(); - TextureFlag getFlags(); - }; -} \ No newline at end of file diff --git a/main.cpp b/main.cpp index d07c93a..7b09a49 100644 --- a/main.cpp +++ b/main.cpp @@ -1,9 +1,9 @@ -#include +#include #include -using namespace ReTexture; +using namespace ReImage; int main() { - auto* bmp = new SoftwareTexture("testImages/1.bmp", {TextureFlag::INVERT_Y}); + auto* bmp = new Image("testImages/1.bmp", {TextureFlag::INVERT_Y}); std::cout << "Bitmap Width: " << bmp->getWidth() << std::endl; std::cout << "Bitmap Height: " << bmp->getHeight() << std::endl; @@ -14,7 +14,7 @@ int main() { std::cout << "Bitmap Format: RGBA" << std::endl; delete bmp; - auto* png = new SoftwareTexture("testImages/1.png", TextureFlag::INVERT_Y); + auto* png = new Image("testImages/1.png", TextureFlag::INVERT_Y); std::cout << "PNG width: " << png->getWidth() << std::endl; std::cout << "PNG height: " << png->getHeight() << std::endl; diff --git a/src/Texture.cpp b/src/Image.cpp similarity index 56% rename from src/Texture.cpp rename to src/Image.cpp index dc1d2bd..692d51b 100644 --- a/src/Texture.cpp +++ b/src/Image.cpp @@ -1,35 +1,36 @@ #include #include -#include +#include + #define STB_IMAGE_IMPLEMENTATION #include #define STB_IMAGE_RESIZE_IMPLEMENTATION #include -namespace ReTexture { +namespace ReImage { - SoftwareTexture::SoftwareTexture(const std::string &file, const TextureFlag& flags) { + Image::Image(const std::string &file, const TextureFlag& flags) { load(file); - if (flags & TextureFlag::INVERT_Y) + if (flags& TextureFlag::INVERT_Y) invertY(); this->flags = flags; } - SoftwareTexture::SoftwareTexture(const std::string &file) { - *this = SoftwareTexture(file, {}); - } - - SoftwareTexture::SoftwareTexture(const std::vector& pixel_data, TextureFormat format, unsigned int width, unsigned int height) { - pixelData = pixel_data; + Image::Image(const Color4* data, const size_t& length, unsigned int width, unsigned int height, TextureFlag flags) { + pixel_data.resize(length * 4); + memcpy(pixel_data.data(), data, length * sizeof(Color4)); this->width = width; this->height = height; - this->format = format; - this->flags = TextureFlag::NONE; + this->format = TextureFormat::RGBA; + if (flags & INVERT_Y) + invertY(); + + this->flags = flags; } - void SoftwareTexture::load(const std::string &file) { + void Image::load(const std::string& file) { std::ifstream ifStream(file, std::ios::in | std::ios::binary); unsigned char bmpFileHeader[14]; @@ -45,7 +46,7 @@ namespace ReTexture { loadPNG(file); } - void SoftwareTexture::loadBMP(const std::string &file) { + void Image::loadBMP(const std::string &file) { std::ifstream bmpFile(file, std::ios::in | std::ios::binary); if (!bmpFile.is_open()) return; @@ -60,22 +61,22 @@ namespace ReTexture { height = bmpInfoHeader[8] + (bmpInfoHeader[9] << 8) + (bmpInfoHeader[10] << 16) + (bmpInfoHeader[11] << 24); int rowPadded = (width * 3 + 3) & (~3); - pixelData.resize(width * height * 3); + pixel_data.resize(width * height * 3); std::vector rowData(rowPadded); for (int y = height - 1; y >= 0; --y) { bmpFile.read(reinterpret_cast(rowData.data()), rowPadded); for (int x = 0; x < width; ++x) { - pixelData[(y * width + x) * 3 + 2] = rowData[x * 3 + 0]; - pixelData[(y * width + x) * 3 + 1] = rowData[x * 3 + 1]; - pixelData[(y * width + x) * 3 + 0] = rowData[x * 3 + 2]; + pixel_data[(y * width + x) * 3 + 2] = rowData[x * 3 + 0]; + pixel_data[(y * width + x) * 3 + 1] = rowData[x * 3 + 1]; + pixel_data[(y * width + x) * 3 + 0] = rowData[x * 3 + 2]; } } bmpFile.close(); format = TextureFormat::RGB; } - void SoftwareTexture::loadPNG(const std::string &file) { + void Image::loadPNG(const std::string& file) { int channels, w, h; unsigned char* imageData = stbi_load(file.c_str(), &w, &h, &channels, 0); @@ -91,11 +92,11 @@ namespace ReTexture { if (channels == 4) format = TextureFormat::RGBA; - pixelData.assign(imageData, imageData + width * height * channels); + pixel_data.assign(imageData, imageData + width * height * channels); stbi_image_free(imageData); } - void SoftwareTexture::invertY() { + void Image::invertY() { unsigned int rowSize; if (format == TextureFormat::RGB) rowSize = width * 3; @@ -104,41 +105,62 @@ namespace ReTexture { std::vector temp(rowSize); for (unsigned int y = 0; y < height / 2; ++y) { - unsigned char *topRow = &pixelData[y * rowSize]; - unsigned char *bottomRow = &pixelData[(height - y - 1) * rowSize]; + unsigned char *topRow = &pixel_data[y * rowSize]; + unsigned char *bottomRow = &pixel_data[(height - y - 1) * rowSize]; std::copy(bottomRow, bottomRow + rowSize, temp.begin()); std::copy(topRow, topRow + rowSize, bottomRow); std::copy(temp.begin(), temp.end(), topRow); } } - unsigned int SoftwareTexture::getWidth() const { + unsigned int Image::getWidth() const { return width; } - unsigned int SoftwareTexture::getHeight() const { + unsigned int Image::getHeight() const { return height; } - TextureFormat SoftwareTexture::getTextureFormat() { + TextureFormat Image::getTextureFormat() { return format; } - TextureFlag SoftwareTexture::getFlags() { + TextureFlag Image::getFlags() { return flags; } - SoftwareTexture SoftwareTexture::downscale(unsigned int rhs) { + Image Image::downscale(unsigned int rhs) { std::vector result; if (format == TextureFormat::RGB) result.resize((width / rhs) * (height / rhs) * 3), - stbir_resize_uint8_linear(pixelData.data(), width, height, 0, result.data(), (width / rhs), (height / rhs), 0, stbir_pixel_layout::STBIR_RGB); + stbir_resize_uint8_linear(pixel_data.data(), width, height, 0, result.data(), (width / rhs), (height / rhs), 0, stbir_pixel_layout::STBIR_RGB); else if (format == TextureFormat::RGBA) result.resize((width / rhs) * (height / rhs) * 4), - stbir_resize_uint8_linear(pixelData.data(), width, height, 0, result.data(), (width / rhs), (height / rhs), 0, stbir_pixel_layout::STBIR_RGBA); + stbir_resize_uint8_linear(pixel_data.data(), width, height, 0, result.data(), (width / rhs), (height / rhs), 0, stbir_pixel_layout::STBIR_RGBA); - return SoftwareTexture(result, format, (width / rhs), (height / rhs)); + return Image(result, format, (width / rhs), (height / rhs)); + } + + Image::Image(std::vector& pixel_data, TextureFormat format, unsigned int width, unsigned int height) { + this->pixel_data = pixel_data; + this->width = width; + this->height = height; + this->format = format; + this->flags = TextureFlag::NONE; + + } + + Image::Image(const Color3* data, const size_t& length, unsigned int width, unsigned int height, TextureFlag flags) { + pixel_data.resize(length * 3); + memcpy(pixel_data.data(), data, length * sizeof(Color3)); + this->width = width; + this->height = height; + this->format = TextureFormat::RGB; + if (flags & INVERT_Y) + invertY(); + + this->flags = flags; } }