From 847b8660b5dd6c22b2b784a7a2317cd690c9e7f3 Mon Sep 17 00:00:00 2001 From: ohyzha Date: Wed, 31 Jul 2024 12:53:27 +0300 Subject: [PATCH] implement png image loader and refactor existing loader classes --- openVulkanoCpp/Image/ImageLoader.cpp | 53 ++++++++++++++++++++++++ openVulkanoCpp/Image/ImageLoader.hpp | 1 + openVulkanoCpp/Image/ImageLoaderJpeg.cpp | 24 ++++------- openVulkanoCpp/Image/ImageLoaderPng.cpp | 26 ++++++++++++ openVulkanoCpp/Image/ImageLoaderPng.hpp | 19 +++++++++ 5 files changed, 108 insertions(+), 15 deletions(-) create mode 100644 openVulkanoCpp/Image/ImageLoader.cpp create mode 100644 openVulkanoCpp/Image/ImageLoaderPng.cpp create mode 100644 openVulkanoCpp/Image/ImageLoaderPng.hpp diff --git a/openVulkanoCpp/Image/ImageLoader.cpp b/openVulkanoCpp/Image/ImageLoader.cpp new file mode 100644 index 0000000..e6d847a --- /dev/null +++ b/openVulkanoCpp/Image/ImageLoader.cpp @@ -0,0 +1,53 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include "ImageLoader.hpp" +#include "Base/Logger.hpp" +#include + +#define STB_IMAGE_IMPLEMENTATION +#include + +namespace OpenVulkano::Image +{ + std::unique_ptr IImageLoader::loadData(const uint8_t* data, int size, int desiredChannels) + { + Image result; + int rows, cols, channels; + stbi_set_flip_vertically_on_load(true); + uint8_t* pixelData = stbi_load_from_memory(data, static_cast(size), &rows, &cols, &channels, desiredChannels); + if (desiredChannels != 0 && channels < desiredChannels) + { + Logger::INPUT->warn( + "Stbi load image channels mismatch. Desired channels = {}, actual amount of channels in image = {}", + desiredChannels, channels); + } + result.data = OpenVulkano::Array(cols * rows * channels); + switch (channels) + { + case 1: + result.dataFormat = OpenVulkano::DataFormat::R8_UNORM; + break; + case 2: + result.dataFormat = OpenVulkano::DataFormat::R8G8_UNORM; + break; + case 3: + result.dataFormat = OpenVulkano::DataFormat::R8G8B8_UNORM; + break; + case 4: + result.dataFormat = OpenVulkano::DataFormat::R8G8B8A8_UNORM; + break; + } + result.resolution.x = cols; + result.resolution.y = rows; + result.resolution.z = 1; + std::memcpy(result.data.Data(), pixelData, result.data.Size()); + stbi_image_free(pixelData); + return std::make_unique(std::move(result)); + } +} \ No newline at end of file diff --git a/openVulkanoCpp/Image/ImageLoader.hpp b/openVulkanoCpp/Image/ImageLoader.hpp index d3a288f..1bc6b0f 100644 --- a/openVulkanoCpp/Image/ImageLoader.hpp +++ b/openVulkanoCpp/Image/ImageLoader.hpp @@ -18,6 +18,7 @@ namespace OpenVulkano::Image public: virtual ~IImageLoader() = default; + static std::unique_ptr loadData(const uint8_t* data, int size, int desiredChannels = 0); virtual std::unique_ptr loadFromFile(const std::string& filePath) = 0; virtual std::unique_ptr loadFromMemory(const std::vector& buffer) = 0; }; diff --git a/openVulkanoCpp/Image/ImageLoaderJpeg.cpp b/openVulkanoCpp/Image/ImageLoaderJpeg.cpp index f9daec4..41915d6 100644 --- a/openVulkanoCpp/Image/ImageLoaderJpeg.cpp +++ b/openVulkanoCpp/Image/ImageLoaderJpeg.cpp @@ -33,11 +33,11 @@ namespace OpenVulkano::Image std::unique_ptr ImageLoaderJpeg::loadJpeg(const uint8_t* data, size_t size) { - Image result; - - int rows, cols; #if __has_include("turbojpeg.h") { + Image result; + + int rows, cols; unsigned char* compressedImage = const_cast(data); int jpegSubsamp; @@ -51,22 +51,16 @@ namespace OpenVulkano::Image tjDecompress2(jpegDecompressor, compressedImage, size, result.data.Data(), cols, 0 /*pitch*/, rows, TJPF_RGBA, TJFLAG_FASTDCT); tjDestroy(jpegDecompressor); + result.resolution.x = cols; + result.resolution.y = rows; + result.resolution.z = 1; + + return std::make_unique(std::move(result)); } #else { - int channels; - uint8_t* pixelData = stbi_load_from_memory(data, size, &cols, &rows, &channels, 3); - result.data = OpenVulkano::Array(cols * rows * channels); - result.dataFormat = channels == 3 ? OpenVulkano::DataFormat::R8G8B8_UINT : - OpenVulkano::DataFormat::R8G8B8A8_UINT; - std::memcpy(result.data.Data(), pixelData, result.data.Size()); - stbi_image_free(pixelData); + return loadData(data, static_cast(size), 3); } #endif - result.resolution.x = cols; - result.resolution.y = rows; - result.resolution.z = 1; - - return std::make_unique(std::move(result)); } } \ No newline at end of file diff --git a/openVulkanoCpp/Image/ImageLoaderPng.cpp b/openVulkanoCpp/Image/ImageLoaderPng.cpp new file mode 100644 index 0000000..ee37dd1 --- /dev/null +++ b/openVulkanoCpp/Image/ImageLoaderPng.cpp @@ -0,0 +1,26 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +#include "ImageLoaderPng.hpp" +#include +#include +#include + +namespace OpenVulkano::Image +{ + std::unique_ptr ImageLoaderPng::loadFromFile(const std::string& filePath) + { + std::ifstream file(filePath, std::ios::binary); + if (!file) { throw std::runtime_error("Could not open file: " + filePath); } + std::vector buffer((std::istreambuf_iterator(file)), std::istreambuf_iterator()); + return loadData(buffer.data(), static_cast(buffer.size())); + } + + std::unique_ptr ImageLoaderPng::loadFromMemory(const std::vector& buffer) + { + return loadData(buffer.data(), static_cast(buffer.size())); + } +} \ No newline at end of file diff --git a/openVulkanoCpp/Image/ImageLoaderPng.hpp b/openVulkanoCpp/Image/ImageLoaderPng.hpp new file mode 100644 index 0000000..7b449cf --- /dev/null +++ b/openVulkanoCpp/Image/ImageLoaderPng.hpp @@ -0,0 +1,19 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include "ImageLoader.hpp" + +namespace OpenVulkano::Image +{ + class ImageLoaderPng : public IImageLoader + { + public: + std::unique_ptr loadFromFile(const std::string& filePath) override; + std::unique_ptr loadFromMemory(const std::vector& buffer) override; + }; +} \ No newline at end of file