465{
466 if (!std::filesystem::exists(path)) {
468 "Image file not found: {}", path.string());
469 return std::nullopt;
470 }
471
472 std::ifstream file(path, std::ios::binary | std::ios::ate);
473 if (!file.is_open()) {
475 "Failed to open image file: {}", path.string());
476 return std::nullopt;
477 }
478
479 std::streamsize file_size = file.tellg();
480 file.seekg(0, std::ios::beg);
481
482 std::vector<unsigned char> file_buffer(file_size);
483 if (!file.read(reinterpret_cast<char*>(file_buffer.data()), file_size)) {
485 "Failed to read image file: {}", path.string());
486 return std::nullopt;
487 }
488 file.close();
489
490 if (extension_of(path) == "exr") {
491 (void)desired_channels;
492 return load_exr_from_memory(file_buffer.data(),
493 static_cast<size_t>(file_size));
494 }
495
496 int width {}, height {}, channels {};
497
498 if (desired_channels == 0) {
499 stbi_info_from_memory(file_buffer.data(), static_cast<int>(file_buffer.size()),
500 &
width, &height, &channels);
501 if (channels == 3) {
502 desired_channels = 4;
503 }
504 }
505
506 unsigned char*
pixels = stbi_load_from_memory(
507 file_buffer.data(),
508 static_cast<int>(file_buffer.size()),
509 &
width, &height, &channels,
510 desired_channels);
511
514 "Failed to decode image: {} - {}",
515 path.string(), stbi_failure_reason());
516 return std::nullopt;
517 }
518
519 int result_channels = (desired_channels != 0) ? desired_channels : channels;
520
522 "Loaded image: {} ({}x{}, {} channels{})",
523 path.filename().string(),
width, height, result_channels,
524 (channels == 3 && result_channels == 4) ? " [RGB→RGBA]" : "");
525
526 ImageData result;
527 auto& buf = result.pixels.emplace<std::vector<uint8_t>>();
528 size_t data_size =
static_cast<size_t>(
width) * height * result_channels;
529 buf.resize(data_size);
530 std::memcpy(buf.data(),
pixels, data_size);
531
532 result.width =
width;
533 result.height = height;
534 result.channels = result_channels;
535
536 switch (result_channels) {
537 case 1:
539 break;
540 case 2:
542 break;
543 case 4:
545 break;
546 default:
548 "Unsupported channel count: {}", result_channels);
550 return std::nullopt;
551 }
552
554 return result;
555}
#define MF_INFO(comp, ctx,...)
#define MF_ERROR(comp, ctx,...)
const std::vector< float > * pixels
@ FileIO
Filesystem I/O operations.
@ IO
Networking, file handling, streaming.
@ RGBA8
Four channel 8-bit.
@ R8
Single channel 8-bit.