564{
565 if (!data || size == 0) {
567 "Invalid memory buffer for image loading");
568 return std::nullopt;
569 }
570
571 const auto* bytes = static_cast<const unsigned char*>(data);
572
573 if (size >= 4
574 && bytes[0] == 0x76 && bytes[1] == 0x2F
575 && bytes[2] == 0x31 && bytes[3] == 0x01) {
576 return load_exr_from_memory(bytes, size);
577 }
578
579 int width {}, height {}, channels {};
580
581 stbi_info_from_memory(bytes, static_cast<int>(size),
582 &
width, &height, &channels);
583
584 int load_as = (channels == 3) ? 4 : 0;
585
586 unsigned char*
pixels = stbi_load_from_memory(
587 bytes,
588 static_cast<int>(size),
589 &
width, &height, &channels,
590 load_as);
591
594 "Failed to decode image from memory: {}",
595 stbi_failure_reason());
596 return std::nullopt;
597 }
598
599 int result_channels = (load_as != 0) ? load_as : channels;
600
602 "Loaded image from memory ({}x{}, {} channels{})",
603 width, height, result_channels,
604 (channels == 3 && result_channels == 4) ? " [RGB→RGBA]" : "");
605
606 ImageData result;
607 auto& buf = result.pixels.emplace<std::vector<uint8_t>>();
608 size_t data_size =
static_cast<size_t>(
width) * height * result_channels;
609 buf.resize(data_size);
610 std::memcpy(buf.data(),
pixels, data_size);
611
612 result.width =
width;
613 result.height = height;
614 result.channels = result_channels;
615
616 switch (result_channels) {
617 case 1:
619 break;
620 case 2:
622 break;
623 case 4:
625 break;
626 default:
628 "Unsupported channel count: {}", result_channels);
630 return std::nullopt;
631 }
632
634 return result;
635}
#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.