10#define STB_IMAGE_IMPLEMENTATION
12#include "stb/stb_image.h"
31 auto ext = std::filesystem::path(filepath).extension().string();
32 if (!ext.empty() && ext[0] ==
'.') {
36 static const std::vector<std::string> supported = {
37 "png",
"jpg",
"jpeg",
"bmp",
"tga",
"psd",
"gif",
"hdr",
"pic",
"pnm"
40 return std::ranges::find(supported, ext) != supported.end();
66 "Opened image: {} ({}x{}, {} channels)",
140 uint32_t region_width = x_end - x_start;
141 uint32_t region_height = y_end - y_start;
142 size_t region_size =
static_cast<size_t>(region_width * region_height) *
m_image_data->channels;
143 std::vector<uint8_t> region_data(region_size);
145 for (uint32_t y = 0; y < region_height; ++y) {
147 size_t dst_offset =
static_cast<size_t>(y * region_width) *
m_image_data->channels;
148 size_t row_size =
static_cast<size_t>(region_width) *
m_image_data->channels;
150 region_data.data() + dst_offset,
155 return { region_data };
161 m_last_error =
"Images use direct GPU texture creation, not containers";
168 m_last_error =
"Images cannot be loaded into SignalSourceContainer";
184 return {
"png",
"jpg",
"jpeg",
"bmp",
"tga",
"psd",
"gif",
"hdr",
"pic",
"pnm" };
189 return typeid(std::vector<uint8_t>);
229std::optional<ImageData>
ImageReader::load(
const std::filesystem::path& path,
int desired_channels)
231 if (!std::filesystem::exists(path)) {
233 "Image file not found: {}", path.string());
237 std::ifstream file(path, std::ios::binary | std::ios::ate);
238 if (!file.is_open()) {
240 "Failed to open image file: {}", path.string());
244 std::streamsize file_size = file.tellg();
245 file.seekg(0, std::ios::beg);
247 std::vector<unsigned char> file_buffer(file_size);
248 if (!file.read(
reinterpret_cast<char*
>(file_buffer.data()), file_size)) {
250 "Failed to read image file: {}", path.string());
255 int width {}, height {}, channels {};
256 unsigned char* pixels = stbi_load_from_memory(
258 static_cast<int>(file_buffer.size()),
259 &width, &height, &channels,
264 "Failed to decode image: {} - {}",
265 path.string(), stbi_failure_reason());
285 "Unsupported channel count: {}", channels);
286 stbi_image_free(pixels);
292 size_t data_size =
static_cast<long>(width * height) * channels;
293 result.
pixels.resize(data_size);
294 std::memcpy(result.
pixels.data(), pixels, data_size);
296 result.
width = width;
300 stbi_image_free(pixels);
303 "Loaded image: {} ({}x{}, {} channels)",
304 path.filename().string(), width, height, channels);
311 return load(std::filesystem::path(path), desired_channels);
317 if (!data || size == 0) {
319 "Invalid memory buffer for image loading");
323 int width {}, height {}, channels {};
324 unsigned char* pixels = stbi_load_from_memory(
325 static_cast<const unsigned char*
>(data),
326 static_cast<int>(size),
327 &width, &height, &channels,
332 "Failed to decode image from memory: {}",
333 stbi_failure_reason());
353 "Unsupported channel count: {}", channels);
354 stbi_image_free(pixels);
359 size_t data_size =
static_cast<long>(width * height) * channels;
360 result.
pixels.resize(data_size);
361 std::memcpy(result.
pixels.data(), pixels, data_size);
363 result.
width = width;
367 stbi_image_free(pixels);
370 "Loaded image from memory ({}x{}, {} channels)",
371 width, height, channels);
378 auto image_data =
load(path, 4);
384 auto texture = mgr.create_2d(
388 image_data->pixels.data());
392 "Created GPU texture from image: {}", path);
410 auto tex_buffer = std::make_shared<Buffers::TextureBuffer>(
417 "Created TextureBuffer from image: {}x{} ({} bytes)",
430 if (!buffer || !buffer->is_initialized()) {
436 if (buffer->get_size_bytes() < required_size) {
447 "Loaded image into VKBuffer: {}x{} ({} bytes)",
#define MF_INFO(comp, ctx,...)
#define MF_ERROR(comp, ctx,...)
static std::optional< ImageData > load_from_memory(const void *data, size_t size)
Load image from memory (static utility)
std::type_index get_container_type() const override
Get the container type this reader creates.
std::shared_ptr< Kakshya::SignalSourceContainer > create_container() override
Create and initialize a container from the file.
std::vector< std::string > get_supported_extensions() const override
Get supported file extensions for this reader.
std::type_index get_data_type() const override
Get the data type this reader produces.
static std::optional< ImageData > load(const std::string &path, int desired_channels=4)
Load image from file (static utility)
std::optional< ImageData > m_image_data
bool is_open() const override
Check if a file is currently open.
bool supports_streaming() const override
Check if streaming is supported for the current file.
std::shared_ptr< Buffers::TextureBuffer > create_texture_buffer()
Create a VKBuffer containing the loaded image pixel data.
bool open(const std::string &filepath, FileReadOptions options=FileReadOptions::ALL) override
Open a file for reading.
size_t get_num_dimensions() const override
Get the dimensionality of the file data.
bool load_into_container(std::shared_ptr< Kakshya::SignalSourceContainer > container) override
Load file data into an existing container.
std::vector< Kakshya::DataVariant > read_region(const FileRegion ®ion) override
Read a specific region of data.
std::vector< Kakshya::DataVariant > read_all() override
Read all data from the file into memory.
std::vector< uint64_t > get_dimension_sizes() const override
Get size of each dimension in the file data.
std::optional< FileMetadata > get_metadata() const override
Get metadata from the open file.
std::vector< FileRegion > get_regions() const override
Get semantic regions from the file.
bool load_into_buffer(const std::shared_ptr< Buffers::VKBuffer > &buffer)
Load image directly into an existing VKBuffer.
bool seek(const std::vector< uint64_t > &position) override
Seek to a specific position in the file.
std::vector< uint64_t > get_read_position() const override
Get current read position in primary dimension.
void close() override
Close the currently open file.
bool can_read(const std::string &filepath) const override
Check if a file can be read by this reader.
std::optional< ImageData > get_image_data() const
Get the loaded image data.
static std::shared_ptr< Core::VKImage > load_texture(const std::string &path)
Load image directly into GPU texture (static utility)
std::string get_last_error() const override
Get the last error message.
uint64_t get_preferred_chunk_size() const override
Get the preferred chunk size for streaming.
void upload_to_gpu(const void *data, size_t size, const std::shared_ptr< VKBuffer > &target, const std::shared_ptr< VKBuffer > &staging)
Upload raw data to GPU buffer (auto-detects host-visible vs device-local)
FileReadOptions
Generic options for file reading behavior.
@ FileIO
Filesystem I/O operations.
@ IO
Networking, file handling, streaming.
@ IMAGE_COLOR
2D RGB/RGBA image
MAYAFLUX_API TextureLoom & get_texture_manager()
Get the global texture manager instance.
ImageFormat
User-friendly image format enum.
@ RGB8
Three channel 8-bit.
@ RGBA8
Four channel 8-bit.
@ R8
Single channel 8-bit.
std::vector< uint64_t > start_coordinates
N-dimensional start position (e.g., frame, x, y)
std::vector< uint64_t > end_coordinates
N-dimensional end position (inclusive)
Generic region descriptor for any file type.
Portal::Graphics::ImageFormat format
std::vector< uint8_t > pixels
Raw image data loaded from file.