Skip to content

Commit

Permalink
Texture Loader: added option to detect and clip uniform images
Browse files Browse the repository at this point in the history
  • Loading branch information
TheMostDiligent committed Oct 10, 2024
1 parent c546d12 commit d5069a7
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 3 deletions.
3 changes: 3 additions & 0 deletions TextureLoader/interface/Image.h
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,9 @@ struct Image : public ObjectBase<IObject>

static IMAGE_FILE_FORMAT GetFileFormat(const Uint8* pData, size_t Size, const char* FilePath = nullptr);

/// Returns true if the image is uniform, i.e. all pixels have the same value
bool IsUniform() const;

private:
template <typename AllocatorType, typename ObjectType>
friend class MakeNewRCObj;
Expand Down
9 changes: 8 additions & 1 deletion TextureLoader/interface/TextureLoader.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2019-2023 Diligent Graphics LLC
* Copyright 2019-2024 Diligent Graphics LLC
* Copyright 2015-2019 Egor Yusov
*
* Licensed under the Apache License, Version 2.0 (the "License");
Expand Down Expand Up @@ -136,6 +136,13 @@ struct TextureLoadInfo
/// - Two-channel source image is replicated to RG channels, B channel is set to 0.
TextureComponentMapping Swizzle DEFAULT_INITIALIZER(TextureComponentMapping::Identity());

/// When non-zero, specifies the dimension that uniform images should be clipped to.
///
/// \remarks When this parameter is non-zero, the loader will check if all pixels
/// in the image have the same value. If this is the case, the image will
/// be clipped to the specified dimension.
Uint32 UniformImageClipDim DEFAULT_INITIALIZER(0);

#if DILIGENT_CPP_INTERFACE
explicit TextureLoadInfo(const Char* _Name,
USAGE _Usage = TextureLoadInfo{}.Usage,
Expand Down
53 changes: 53 additions & 0 deletions TextureLoader/src/Image.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -589,6 +589,59 @@ IMAGE_FILE_FORMAT Image::GetFileFormat(const Uint8* pData, size_t Size, const ch
return IMAGE_FILE_FORMAT_UNKNOWN;
}

template <typename T>
bool IsImageUniform(const void* pData, Uint32 Width, Uint32 Height, Uint32 NumComponents, Uint32 RowStride)
{
if (Width == 0 || Height == 0 || NumComponents == 0)
return false;

const T* pFirstPixel = static_cast<const T*>(pData);
for (Uint32 Pass = 0; Pass < 2; ++Pass)
{
// On the first pass, sparsely sample the image to quickly detect non-uniform images
const Uint32 Step = (Pass == 0) ? 32 : 1;
for (Uint32 y = 0; y < Height; y += Step)
{
const T* pRow = reinterpret_cast<const T*>(static_cast<const Uint8*>(pData) + y * RowStride);
for (Uint32 x = 0; x < Width; x += Step)
{
for (Uint32 c = 0; c < NumComponents; ++c)
{
if (pRow[x * NumComponents + c] != pFirstPixel[c])
return false;
}
}
}
}

return true;
}

bool Image::IsUniform() const
{
if (!m_pData)
return false;

Uint32 ComponentSize = GetValueSize(m_Desc.ComponentType);
switch (ComponentSize)
{
case 1:
return IsImageUniform<Uint8>(m_pData->GetConstDataPtr(), m_Desc.Width, m_Desc.Height, m_Desc.NumComponents, m_Desc.RowStride);

case 2:
return IsImageUniform<Uint16>(m_pData->GetConstDataPtr(), m_Desc.Width, m_Desc.Height, m_Desc.NumComponents, m_Desc.RowStride);

case 4:
return IsImageUniform<Uint32>(m_pData->GetConstDataPtr(), m_Desc.Width, m_Desc.Height, m_Desc.NumComponents, m_Desc.RowStride);

case 8:
return IsImageUniform<Uint64>(m_pData->GetConstDataPtr(), m_Desc.Width, m_Desc.Height, m_Desc.NumComponents, m_Desc.RowStride);

default:
UNEXPECTED("Unexpected component size (", ComponentSize, ")");
return false;
}
}

IMAGE_FILE_FORMAT CreateImageFromFile(const Char* FilePath,
Image** ppImage,
Expand Down
10 changes: 8 additions & 2 deletions TextureLoader/src/TextureLoaderImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -199,8 +199,12 @@ void TextureLoaderImpl::LoadFromImage(Image* pImage, const TextureLoadInfo& TexL
{
VERIFY_EXPR(pImage != nullptr);

const ImageDesc& ImgDesc = pImage->GetDesc();
const Uint32 CompSize = GetValueSize(ImgDesc.ComponentType);
ImageDesc ImgDesc = pImage->GetDesc();
if (TexLoadInfo.UniformImageClipDim != 0 && pImage->IsUniform())
{
ImgDesc.Width = std::min(ImgDesc.Width, TexLoadInfo.UniformImageClipDim);
ImgDesc.Height = std::min(ImgDesc.Height, TexLoadInfo.UniformImageClipDim);
}

m_TexDesc.Type = RESOURCE_DIM_TEX_2D;
m_TexDesc.Width = ImgDesc.Width;
Expand All @@ -209,6 +213,8 @@ void TextureLoaderImpl::LoadFromImage(Image* pImage, const TextureLoadInfo& TexL
if (TexLoadInfo.MipLevels > 0)
m_TexDesc.MipLevels = std::min(m_TexDesc.MipLevels, TexLoadInfo.MipLevels);

const Uint32 CompSize = GetValueSize(ImgDesc.ComponentType);

if (m_TexDesc.Format == TEX_FORMAT_UNKNOWN)
{
Uint32 NumComponents = ImgDesc.NumComponents;
Expand Down

0 comments on commit d5069a7

Please sign in to comment.