diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Image/StreamingImageAsset.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Image/StreamingImageAsset.h index e934ac8bcf..f4dc891ff2 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Image/StreamingImageAsset.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Image/StreamingImageAsset.h @@ -92,6 +92,12 @@ namespace AZ //! Retrieve a region of image pixel values (float) for specified mip and slice void GetSubImagePixelValues(AZStd::pair topLeft, AZStd::pair bottomRight, AZStd::array_view outValues, uint32_t componentIndex = 0, uint32_t mip = 0, uint32_t slice = 0); + //! Retrieve a region of image pixel values (uint) for specified mip and slice + void GetSubImagePixelValues(AZStd::pair topLeft, AZStd::pair bottomRight, AZStd::array_view outValues, uint32_t componentIndex = 0, uint32_t mip = 0, uint32_t slice = 0); + + //! Retrieve a region of image pixel values (int) for specified mip and slice + void GetSubImagePixelValues(AZStd::pair topLeft, AZStd::pair bottomRight, AZStd::array_view outValues, uint32_t componentIndex = 0, uint32_t mip = 0, uint32_t slice = 0); + //! Returns streaming image pool asset id of the pool that will be used to create the streaming image. const Data::AssetId& GetPoolAssetId() const; @@ -134,6 +140,9 @@ namespace AZ uint32_t m_totalImageDataSize = 0; StreamingImageFlags m_flags = StreamingImageFlags::None; + + template + T GetSubImagePixelValueInternal(uint32_t x, uint32_t y, uint32_t componentIndex = 0, uint32_t mip = 0, uint32_t slice = 0); }; } } diff --git a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Image/StreamingImageAsset.cpp b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Image/StreamingImageAsset.cpp index e005fb7f9e..e21dd1f2c5 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Image/StreamingImageAsset.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Image/StreamingImageAsset.cpp @@ -45,6 +45,12 @@ namespace AZ return 0; } + template <> + AZ::s32 RetrieveIntValue([[maybe_unused]] const AZ::u8* mem, [[maybe_unused]] size_t index) + { + return 0; + } + template <> AZ::u32 RetrieveUintValue(const AZ::u8* mem, size_t index) { @@ -56,19 +62,27 @@ namespace AZ { // 16 bits per channel auto actualMem = reinterpret_cast(mem); - actualMem += index; - return *actualMem / static_cast(std::numeric_limits::max()); + return actualMem[index] / static_cast(std::numeric_limits::max()); } template <> - AZ::u32 RetrieveUintValue(const AZ::u8* mem, size_t index) + AZ::s32 RetrieveIntValue(const AZ::u8* mem, size_t index) + { + // 16 bits per channel + auto actualMem = reinterpret_cast(mem); + + return actualMem[index] / static_cast(std::numeric_limits::max()); + } + + template <> + float RetrieveFloatValue(const AZ::u8* mem, size_t index) { // 32 bits per channel - auto actualMem = reinterpret_cast(mem); + auto actualMem = reinterpret_cast(mem); actualMem += index; - return *actualMem / static_cast(std::numeric_limits::max()); + return *actualMem; } template <> @@ -85,6 +99,8 @@ namespace AZ { switch (format) { + case AZ::RHI::Format::R32_UINT: + return RetrieveFloatValue(mem, index); case AZ::RHI::Format::R32_FLOAT: return RetrieveFloatValue(mem, index); default: @@ -100,12 +116,21 @@ namespace AZ return RetrieveUintValue(mem, index); case AZ::RHI::Format::R16_UNORM: return RetrieveUintValue(mem, index); - case AZ::RHI::Format::R32_UINT: - return RetrieveUintValue(mem, index); default: return RetrieveUintValue(mem, index); } } + + AZ::s32 RetrieveIntValue(const AZ::u8* mem, size_t index, AZ::RHI::Format format) + { + switch (format) + { + case AZ::RHI::Format::R16_SINT: + return RetrieveIntValue(mem, index); + default: + return RetrieveIntValue(mem, index); + } + } } namespace RPI @@ -220,10 +245,10 @@ namespace AZ return mipChainAsset->GetSubImageData(mip - mipChain.m_mipOffset, slice); } - template<> - float StreamingImageAsset::GetSubImagePixelValue(uint32_t x, uint32_t y, uint32_t componentIndex, uint32_t mip, uint32_t slice) + template + T StreamingImageAsset::GetSubImagePixelValueInternal(uint32_t x, uint32_t y, uint32_t componentIndex, uint32_t mip, uint32_t slice) { - AZStd::vector values; + AZStd::vector values; auto position = AZStd::make_pair(x, y); GetSubImagePixelValues(position, position, values, componentIndex, mip, slice); @@ -233,27 +258,25 @@ namespace AZ return values[0]; } - return 0.0f; + return aznumeric_cast(0); + } + + template<> + float StreamingImageAsset::GetSubImagePixelValue(uint32_t x, uint32_t y, uint32_t componentIndex, uint32_t mip, uint32_t slice) + { + return GetSubImagePixelValueInternal(x, y, componentIndex, mip, slice); } template<> AZ::u32 StreamingImageAsset::GetSubImagePixelValue(uint32_t x, uint32_t y, uint32_t componentIndex, uint32_t mip, uint32_t slice) { - // TODO: Use the component index - (void)componentIndex; + return GetSubImagePixelValueInternal(x, y, componentIndex, mip, slice); + } - auto imageData = GetSubImageData(mip, slice); - - if (!imageData.empty()) - { - const AZ::RHI::ImageDescriptor imageDescriptor = GetImageDescriptor(); - auto width = imageDescriptor.m_size.m_width; - size_t index = (y * width) + x; - - return Internal::RetrieveUintValue(imageData.data(), index, imageDescriptor.m_format); - } - - return 0; + template<> + AZ::s32 StreamingImageAsset::GetSubImagePixelValue(uint32_t x, uint32_t y, uint32_t componentIndex, uint32_t mip, uint32_t slice) + { + return GetSubImagePixelValueInternal(x, y, componentIndex, mip, slice); } void StreamingImageAsset::GetSubImagePixelValues(AZStd::pair topLeft, AZStd::pair bottomRight, AZStd::array_view outValues, uint32_t componentIndex, uint32_t mip, uint32_t slice) @@ -281,5 +304,57 @@ namespace AZ } } } + + void StreamingImageAsset::GetSubImagePixelValues(AZStd::pair topLeft, AZStd::pair bottomRight, AZStd::array_view outValues, uint32_t componentIndex, uint32_t mip, uint32_t slice) + { + // TODO: Use the component index + (void)componentIndex; + + auto imageData = GetSubImageData(mip, slice); + + if (!imageData.empty()) + { + const AZ::RHI::ImageDescriptor imageDescriptor = GetImageDescriptor(); + auto width = imageDescriptor.m_size.m_width; + + size_t outValuesIndex = 0; + for (uint32_t x = topLeft.first; x < bottomRight.first; ++x) + { + for (uint32_t y = topLeft.second; y < bottomRight.second; ++y) + { + size_t imageDataIndex = (y * width) + x; + + auto& outValue = const_cast(outValues[outValuesIndex++]); + outValue = Internal::RetrieveUintValue(imageData.data(), imageDataIndex, imageDescriptor.m_format); + } + } + } + } + + void StreamingImageAsset::GetSubImagePixelValues(AZStd::pair topLeft, AZStd::pair bottomRight, AZStd::array_view outValues, uint32_t componentIndex, uint32_t mip, uint32_t slice) + { + // TODO: Use the component index + (void)componentIndex; + + auto imageData = GetSubImageData(mip, slice); + + if (!imageData.empty()) + { + const AZ::RHI::ImageDescriptor imageDescriptor = GetImageDescriptor(); + auto width = imageDescriptor.m_size.m_width; + + size_t outValuesIndex = 0; + for (uint32_t x = topLeft.first; x < bottomRight.first; ++x) + { + for (uint32_t y = topLeft.second; y < bottomRight.second; ++y) + { + size_t imageDataIndex = (y * width) + x; + + auto& outValue = const_cast(outValues[outValuesIndex++]); + outValue = Internal::RetrieveIntValue(imageData.data(), imageDataIndex, imageDescriptor.m_format); + } + } + } + } } }