|
3 | 3 | #include <algorithm> |
4 | 4 | #include <bit> |
5 | 5 | #include <cstring> |
| 6 | +#include <memory> |
6 | 7 | #include <span> |
7 | 8 |
|
8 | 9 | #ifdef SOURCEPP_BUILD_WITH_TBB |
|
11 | 12 |
|
12 | 13 | #include <Compressonator.h> |
13 | 14 | #include <sourcepp/math/Float.h> |
| 15 | +#include <stb_image.h> |
14 | 16 | #include <stb_image_resize2.h> |
15 | 17 | #include <stb_image_write.h> |
16 | 18 |
|
@@ -864,6 +866,87 @@ std::vector<std::byte> ImageConversion::convertImageDataToFile(std::span<const s |
864 | 866 | return out; |
865 | 867 | } |
866 | 868 |
|
| 869 | +std::vector<std::byte> ImageConversion::convertFileToImageData(std::span<const std::byte> fileData, ImageFormat& format, int& width, int& height, int& frameCount) { |
| 870 | + stbi_convert_iphone_png_to_rgb(true); |
| 871 | + |
| 872 | + format = ImageFormat::EMPTY; |
| 873 | + width = 0; |
| 874 | + height = 0; |
| 875 | + int channels = 0; |
| 876 | + frameCount = 1; |
| 877 | + |
| 878 | + if (stbi_is_hdr_from_memory(reinterpret_cast<const stbi_uc*>(fileData.data()), static_cast<int>(fileData.size()))) { |
| 879 | + std::unique_ptr<float, void(*)(void*)> stbImage{ |
| 880 | + stbi_loadf_from_memory(reinterpret_cast<const stbi_uc*>(fileData.data()), static_cast<int>(fileData.size()), &width, &height, &channels, 0), |
| 881 | + &stbi_image_free, |
| 882 | + }; |
| 883 | + if (!stbImage) { |
| 884 | + return {}; |
| 885 | + } |
| 886 | + |
| 887 | + switch (channels) { |
| 888 | + case 1: format = ImageFormat::R32F; break; |
| 889 | + case 3: format = ImageFormat::RGB323232F; break; |
| 890 | + case 4: format = ImageFormat::RGBA32323232F; break; |
| 891 | + default: return {}; |
| 892 | + } |
| 893 | + |
| 894 | + return {reinterpret_cast<std::byte*>(stbImage.get()), reinterpret_cast<std::byte*>(stbImage.get()) + ImageFormatDetails::getDataLength(format, width, height)}; |
| 895 | + } else if (stbi_is_16_bit_from_memory(reinterpret_cast<const stbi_uc*>(fileData.data()), static_cast<int>(fileData.size()))) { |
| 896 | + std::unique_ptr<stbi_us, void(*)(void*)> stbImage{ |
| 897 | + stbi_load_16_from_memory(reinterpret_cast<const stbi_uc*>(fileData.data()), static_cast<int>(fileData.size()), &width, &height, &channels, 0), |
| 898 | + &stbi_image_free, |
| 899 | + }; |
| 900 | + if (!stbImage) { |
| 901 | + return {}; |
| 902 | + } |
| 903 | + |
| 904 | + if (channels == 4) { |
| 905 | + format = ImageFormat::RGBA16161616; |
| 906 | + } else { |
| 907 | + return {}; |
| 908 | + } |
| 909 | + |
| 910 | + return {reinterpret_cast<std::byte*>(stbImage.get()), reinterpret_cast<std::byte*>(stbImage.get()) + ImageFormatDetails::getDataLength(format, width, height)}; |
| 911 | + } else if (fileData.size() >= 3 && static_cast<char>(fileData[0]) == 'G' && static_cast<char>(fileData[1]) == 'I' && static_cast<char>(fileData[2]) == 'F') { |
| 912 | + std::unique_ptr<stbi_uc, void(*)(void*)> stbImage{ |
| 913 | + stbi_load_gif_from_memory(reinterpret_cast<const stbi_uc*>(fileData.data()), static_cast<int>(fileData.size()), nullptr, &width, &height, &frameCount, &channels, 0), |
| 914 | + &stbi_image_free, |
| 915 | + }; |
| 916 | + if (!stbImage || !frameCount) { |
| 917 | + return {}; |
| 918 | + } |
| 919 | + |
| 920 | + switch (channels) { |
| 921 | + case 1: format = ImageFormat::I8; break; |
| 922 | + case 2: format = ImageFormat::UV88; break; |
| 923 | + case 3: format = ImageFormat::RGB888; break; |
| 924 | + case 4: format = ImageFormat::RGBA8888; break; |
| 925 | + default: return {}; |
| 926 | + } |
| 927 | + |
| 928 | + return {reinterpret_cast<std::byte*>(stbImage.get()), reinterpret_cast<std::byte*>(stbImage.get() + (ImageFormatDetails::getDataLength(format, width, height) * frameCount))}; |
| 929 | + } else { |
| 930 | + std::unique_ptr<stbi_uc, void(*)(void*)> stbImage{ |
| 931 | + stbi_load_from_memory(reinterpret_cast<const stbi_uc*>(fileData.data()), static_cast<int>(fileData.size()), &width, &height, &channels, 0), |
| 932 | + &stbi_image_free, |
| 933 | + }; |
| 934 | + if (!stbImage) { |
| 935 | + return {}; |
| 936 | + } |
| 937 | + |
| 938 | + switch (channels) { |
| 939 | + case 1: format = ImageFormat::I8; break; |
| 940 | + case 2: format = ImageFormat::UV88; break; |
| 941 | + case 3: format = ImageFormat::RGB888; break; |
| 942 | + case 4: format = ImageFormat::RGBA8888; break; |
| 943 | + default: return {}; |
| 944 | + } |
| 945 | + |
| 946 | + return {reinterpret_cast<std::byte*>(stbImage.get()), reinterpret_cast<std::byte*>(stbImage.get()) + ImageFormatDetails::getDataLength(format, width, height)}; |
| 947 | + } |
| 948 | +} |
| 949 | + |
867 | 950 | uint16_t ImageConversion::getResizedDim(uint16_t n, ResizeMethod method) { |
868 | 951 | switch (method) { |
869 | 952 | case ResizeMethod::NONE: break; |
|
0 commit comments