From ba1573c4880c68b5c9c705758ac947732b22db3c Mon Sep 17 00:00:00 2001 From: vkaytsanov Date: Sat, 1 Nov 2025 00:40:31 +0200 Subject: [PATCH] Add support for LoadFromEXRMemory as other formats --- Auxiliary/DirectXTexEXR.cpp | 246 +++++++++++++++++++++++------------- Auxiliary/DirectXTexEXR.h | 4 + 2 files changed, 159 insertions(+), 91 deletions(-) diff --git a/Auxiliary/DirectXTexEXR.cpp b/Auxiliary/DirectXTexEXR.cpp index f3569e2e..740beddc 100644 --- a/Auxiliary/DirectXTexEXR.cpp +++ b/Auxiliary/DirectXTexEXR.cpp @@ -82,10 +82,10 @@ namespace HRESULT result; }; - class InputStream : public Imf::IStream + class InputFileStream : public Imf::IStream { public: - InputStream(HANDLE hFile, const char fileName[]) : + InputFileStream(HANDLE hFile, const char fileName[]) : IStream(fileName), m_hFile(hFile) { const LARGE_INTEGER dist = {}; @@ -103,11 +103,11 @@ namespace } } - InputStream(const InputStream&) = delete; - InputStream& operator = (const InputStream&) = delete; + InputFileStream(const InputFileStream&) = delete; + InputFileStream& operator = (const InputFileStream&) = delete; - InputStream(InputStream&&) = delete; - InputStream& operator=(InputStream&&) = delete; + InputFileStream(InputFileStream&&) = delete; + InputFileStream& operator=(InputFileStream&&) = delete; bool read(char c[], int n) override { @@ -153,7 +153,7 @@ namespace SetLastError(0); } -#if COMBINED_OPENEXR_VERSION >= 30300 +#if COMBINED_OPENEXR_VERSION > 30300 int64_t read(void *buf, uint64_t sz, uint64_t offset) override { return Imf::IStream::read(buf, sz, offset); @@ -165,17 +165,17 @@ namespace LONGLONG m_EOF; }; - class OutputStream : public Imf::OStream + class OutputFileStream : public Imf::OStream { public: - OutputStream(HANDLE hFile, const char fileName[]) : + OutputFileStream(HANDLE hFile, const char fileName[]) : OStream(fileName), m_hFile(hFile) {} - OutputStream(const OutputStream&) = delete; - OutputStream& operator = (const OutputStream&) = delete; + OutputFileStream(const OutputFileStream&) = delete; + OutputFileStream& operator = (const OutputFileStream&) = delete; - OutputStream(OutputStream&&) = delete; - OutputStream& operator=(OutputStream&&) = delete; + OutputFileStream(OutputFileStream&&) = delete; + OutputFileStream& operator=(OutputFileStream&&) = delete; void write(const char c[], int n) override { @@ -210,60 +210,70 @@ namespace private: HANDLE m_hFile; }; -} -#endif // _WIN32 -//===================================================================================== -// Entry-points -//===================================================================================== + class InputStream : public Imf::IStream + { + public: + InputStream(const uint8_t* data, size_t size) + : IStream("InputStream") + , m_DataPtr(data) + , m_DataSize(size) + , m_Position(0) + {} + + bool read(char c[], int n) override + { + memcpy(c, m_DataPtr + m_Position, n); + m_Position += n; + + return m_Position < m_DataSize; + } + + uint64_t tellg() override + { + return m_Position; + } + + void seekg(uint64_t pos) override + { + m_Position = pos; + } + + #if COMBINED_OPENEXR_VERSION > 30300 + int64_t read(void *buf, uint64_t sz, uint64_t offset) override + { + return Imf::IStream::read(buf, sz, offset); + } + #endif + + private: + const uint8_t* m_DataPtr; + size_t m_DataSize; + size_t m_Position; + }; +} +#endif // _WIN32 //------------------------------------------------------------------------------------- -// Obtain metadata from EXR file on disk +// Load //------------------------------------------------------------------------------------- _Use_decl_annotations_ -HRESULT DirectX::GetMetadataFromEXRFile(const wchar_t* szFile, TexMetadata& metadata) +template +HRESULT LoadFromEXRCommon(StreamType& stream, TexMetadata* metadata, ScratchImage& image) { - if (!szFile) - return E_INVALIDARG; - -#ifdef _WIN32 - std::string fileName; - const int nameLength = WideCharToMultiByte(CP_UTF8, 0, szFile, -1, nullptr, 0, nullptr, nullptr); - if (nameLength > 0) - { - fileName.resize(static_cast(nameLength)); - const int result = WideCharToMultiByte(CP_UTF8, 0, szFile, -1, fileName.data(), nameLength, nullptr, nullptr); - if (result <= 0) - { - fileName.clear(); - } - } + image.Release(); - ScopedHandle hFile(safe_handle(CreateFile2( - szFile, - GENERIC_READ, FILE_SHARE_READ, OPEN_EXISTING, - nullptr))); - if (!hFile) + if (metadata) { - return HRESULT_FROM_WIN32(GetLastError()); + memset(metadata, 0, sizeof(TexMetadata)); } - InputStream stream(hFile.get(), fileName.c_str()); -#else - std::wstring wFileName(szFile); - std::string fileName(wFileName.cbegin(), wFileName.cend()); -#endif - HRESULT hr = S_OK; try { -#ifdef _WIN32 Imf::RgbaInputFile file(stream); -#else - Imf::RgbaInputFile file(fileName.c_str()); -#endif const auto dw = file.dataWindow(); @@ -283,19 +293,31 @@ HRESULT DirectX::GetMetadataFromEXRFile(const wchar_t* szFile, TexMetadata& meta } } - metadata.width = static_cast(width); - metadata.height = static_cast(height); - metadata.depth = metadata.mipLevels = 1; - metadata.arraySize = arraySize; - metadata.format = DXGI_FORMAT_R16G16B16A16_FLOAT; - metadata.dimension = TEX_DIMENSION_TEXTURE2D; + if (metadata) + { + metadata->width = static_cast(width); + metadata->height = static_cast(height); + metadata->depth = metadata->mipLevels = 1; + metadata->arraySize = arraySize; + metadata->format = DXGI_FORMAT_R16G16B16A16_FLOAT; + metadata->dimension = TEX_DIMENSION_TEXTURE2D; + } + + hr = image.Initialize2D(DXGI_FORMAT_R16G16B16A16_FLOAT, + static_cast(width), static_cast(height), arraySize, 1u); + + if (FAILED(hr)) + return hr; + + file.setFrameBuffer(reinterpret_cast(image.GetPixels()) - dw.min.x - dw.min.y * width, 1, static_cast(width)); + file.readPixels(dw.min.y, dw.max.y); } #ifdef _WIN32 catch (const com_exception& exc) { -#ifdef _DEBUG + #ifdef _DEBUG OutputDebugStringA(exc.what()); -#endif + #endif hr = exc.get_result(); } #endif @@ -316,26 +338,27 @@ HRESULT DirectX::GetMetadataFromEXRFile(const wchar_t* szFile, TexMetadata& meta hr = E_UNEXPECTED; } + if (FAILED(hr)) + { + image.Release(); + } + return hr; } +//===================================================================================== +// Entry-points +//===================================================================================== //------------------------------------------------------------------------------------- -// Load a EXR file from disk +// Obtain metadata from EXR file on disk //------------------------------------------------------------------------------------- _Use_decl_annotations_ -HRESULT DirectX::LoadFromEXRFile(const wchar_t* szFile, TexMetadata* metadata, ScratchImage& image) +HRESULT DirectX::GetMetadataFromEXRFile(const wchar_t* szFile, TexMetadata& metadata) { if (!szFile) return E_INVALIDARG; - image.Release(); - - if (metadata) - { - memset(metadata, 0, sizeof(TexMetadata)); - } - #ifdef _WIN32 std::string fileName; const int nameLength = WideCharToMultiByte(CP_UTF8, 0, szFile, -1, nullptr, 0, nullptr, nullptr); @@ -358,7 +381,7 @@ HRESULT DirectX::LoadFromEXRFile(const wchar_t* szFile, TexMetadata* metadata, S return HRESULT_FROM_WIN32(GetLastError()); } - InputStream stream(hFile.get(), fileName.c_str()); + InputFileStream stream(hFile.get(), fileName.c_str()); #else std::wstring wFileName(szFile); std::string fileName(wFileName.cbegin(), wFileName.cend()); @@ -392,24 +415,12 @@ HRESULT DirectX::LoadFromEXRFile(const wchar_t* szFile, TexMetadata* metadata, S } } - if (metadata) - { - metadata->width = static_cast(width); - metadata->height = static_cast(height); - metadata->depth = metadata->mipLevels = 1; - metadata->arraySize = arraySize; - metadata->format = DXGI_FORMAT_R16G16B16A16_FLOAT; - metadata->dimension = TEX_DIMENSION_TEXTURE2D; - } - - hr = image.Initialize2D(DXGI_FORMAT_R16G16B16A16_FLOAT, - static_cast(width), static_cast(height), arraySize, 1u); - - if (FAILED(hr)) - return hr; - - file.setFrameBuffer(reinterpret_cast(image.GetPixels()) - dw.min.x - dw.min.y * width, 1, static_cast(width)); - file.readPixels(dw.min.y, dw.max.y); + metadata.width = static_cast(width); + metadata.height = static_cast(height); + metadata.depth = metadata.mipLevels = 1; + metadata.arraySize = arraySize; + metadata.format = DXGI_FORMAT_R16G16B16A16_FLOAT; + metadata.dimension = TEX_DIMENSION_TEXTURE2D; } #ifdef _WIN32 catch (const com_exception& exc) @@ -437,12 +448,65 @@ HRESULT DirectX::LoadFromEXRFile(const wchar_t* szFile, TexMetadata* metadata, S hr = E_UNEXPECTED; } - if (FAILED(hr)) + return hr; +} + + +//------------------------------------------------------------------------------------- +// Load a EXR file from memory +//------------------------------------------------------------------------------------- +_Use_decl_annotations_ +HRESULT DirectX::LoadFromEXRMemory(const uint8_t* pSource, size_t size, TexMetadata* metadata, ScratchImage& image) +{ + if (!pSource || !size) + return E_INVALIDARG; + + InputStream stream(pSource, size); + return LoadFromEXRCommon(stream, metadata, image); +} + +//------------------------------------------------------------------------------------- +// Load a EXR file from disk +//------------------------------------------------------------------------------------- +_Use_decl_annotations_ +HRESULT DirectX::LoadFromEXRFile(const wchar_t* szFile, TexMetadata* metadata, ScratchImage& image) +{ + if (!szFile) + return E_INVALIDARG; + +#ifdef _WIN32 + std::string fileName; + const int nameLength = WideCharToMultiByte(CP_UTF8, 0, szFile, -1, nullptr, 0, nullptr, nullptr); + if (nameLength > 0) { - image.Release(); + fileName.resize(static_cast(nameLength)); + const int result = WideCharToMultiByte(CP_UTF8, 0, szFile, -1, fileName.data(), nameLength, nullptr, nullptr); + if (result <= 0) + { + fileName.clear(); + } } - return hr; + ScopedHandle hFile(safe_handle(CreateFile2( + szFile, + GENERIC_READ, FILE_SHARE_READ, OPEN_EXISTING, + nullptr))); + if (!hFile) + { + return HRESULT_FROM_WIN32(GetLastError()); + } + + InputFileStream stream(hFile.get(), fileName.c_str()); +#else + std::wstring wFileName(szFile); + std::string fileName(wFileName.cbegin(), wFileName.cend()); +#endif + +#ifdef _WIN32 + return LoadFromEXRCommon(stream, metadata, image); +#else + return LoadFromEXRCommon(fileName.c_str(), metadata, image); +#endif } @@ -503,7 +567,7 @@ HRESULT DirectX::SaveToEXRFile(const Image& image, const wchar_t* szFile) auto_delete_file delonfail(hFile.get()); - OutputStream stream(hFile.get(), fileName.c_str()); + OutputFileStream stream(hFile.get(), fileName.c_str()); #else std::wstring wFileName(szFile); std::string fileName(wFileName.cbegin(), wFileName.cend()); diff --git a/Auxiliary/DirectXTexEXR.h b/Auxiliary/DirectXTexEXR.h index 7808bb22..8ed9f12b 100644 --- a/Auxiliary/DirectXTexEXR.h +++ b/Auxiliary/DirectXTexEXR.h @@ -18,6 +18,10 @@ namespace DirectX _In_z_ const wchar_t* szFile, _Out_ TexMetadata& metadata); + DIRECTX_TEX_API HRESULT __cdecl LoadFromEXRMemory( + _In_reads_bytes_(size) const uint8_t* pSource, _In_ size_t size, + _Out_opt_ TexMetadata* metadata, _Out_ ScratchImage& image); + DIRECTX_TEX_API HRESULT __cdecl LoadFromEXRFile( _In_z_ const wchar_t* szFile, _Out_opt_ TexMetadata* metadata, _Out_ ScratchImage& image);