|  | 
| 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