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