Files
UnrealEngine/Engine/Plugins/Mutable/Source/MutableRuntime/Private/MuR/OpImageTransform.h
2025-05-18 13:04:45 +08:00

209 lines
7.2 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include "MuR/ImagePrivate.h"
#include "MuR/MutableTrace.h"
#include "MuR/OpImageTransformPrivate.h"
#include "Math/IntRect.h"
#include "Math/Box2D.h"
namespace mu
{
void ImageTransform(
FImage* pDestImage, const FImage* pImage,
FTransform2f Transform, float MipFactor, EAddressMode AddressMode, bool bUseVectorImplCvar)
{
MUTABLE_CPUPROFILER_SCOPE(ImageTransform);
if (!pImage->GetSizeX() || !pImage->GetSizeY())
{
return;
}
const FIntVector2 SrcSize = FIntVector2(pImage->GetSizeX(), pImage->GetSizeY());
const FIntVector2 DestSize = FIntVector2(pDestImage->GetSizeX(), pDestImage->GetSizeY());
const FIntRect DestCropRect = Invoke([&]()
{
if (AddressMode != EAddressMode::ClampToBlack)
{
return FIntRect(0, 0, DestSize.X, DestSize.Y);
}
FBox2f NormalizedCropRect(ForceInit);
NormalizedCropRect += Transform.TransformPoint(FVector2f(0.0f, 0.0f));
NormalizedCropRect += Transform.TransformPoint(FVector2f(1.0f, 0.0f));
NormalizedCropRect += Transform.TransformPoint(FVector2f(0.0f, 1.0f));
NormalizedCropRect += Transform.TransformPoint(FVector2f(1.0f, 1.0f));
const FIntRect CropRect(
FInt32Point(FMath::FloorToInt(NormalizedCropRect.Min.X * (float)DestSize.X),
FMath::FloorToInt(NormalizedCropRect.Min.Y * (float)DestSize.Y)),
FInt32Point(FMath::CeilToInt (NormalizedCropRect.Max.X * (float)DestSize.X),
FMath::CeilToInt (NormalizedCropRect.Max.Y * (float)DestSize.Y)));
return FIntRect(
FMath::Clamp(CropRect.Min.X, 0, DestSize.X), FMath::Clamp(CropRect.Min.Y, 0, DestSize.Y),
FMath::Clamp(CropRect.Max.X, 0, DestSize.X), FMath::Clamp(CropRect.Max.Y, 0, DestSize.Y));
});
if (AddressMode == EAddressMode::ClampToBlack)
{
pDestImage->Flags |= FImage::IF_HAS_RELEVANCY_MAP;
pDestImage->RelevancyMinY = DestCropRect.Min.Y;
pDestImage->RelevancyMaxY = FMath::Max(DestCropRect.Max.Y - 1, DestCropRect.Min.Y);
}
uint8* DestData = pDestImage->GetMipData(0);
const uint8* Src0Data = pImage->GetMipData(0);
const uint8* Src1Data = pImage->GetLODCount() > 1 ? pImage->GetMipData(1) : Src0Data;
const FIntVector2 Src0Size = FIntVector2(pImage->GetSizeX(), pImage->GetSizeY());
const FIntVector2 Src1Size = Src1Data != Src0Data ? pImage->CalculateMipSize(1) : Src0Size;
switch (pDestImage->GetFormat())
{
case EImageFormat::L_UByte:
{
if (bUseVectorImplCvar)
{
constexpr bool bUseVectorImpl = true;
switch (AddressMode)
{
case EAddressMode::ClampToBlack:
ImageTransformImpl<1, EAddressMode::ClampToBlack, bUseVectorImpl>(DestData, DestSize, DestCropRect, Src0Data, Src0Size, Src1Data, Src1Size, MipFactor, Transform);
break;
case EAddressMode::ClampToEdge:
ImageTransformImpl<1, EAddressMode::ClampToEdge, bUseVectorImpl>(DestData, DestSize, DestCropRect, Src0Data, Src0Size, Src1Data, Src1Size, MipFactor, Transform);
break;
case EAddressMode::Wrap:
ImageTransformImpl<1, EAddressMode::Wrap, bUseVectorImpl>(DestData, DestSize, DestCropRect, Src0Data, Src0Size, Src1Data, Src1Size, MipFactor, Transform);
break;
default:
check(false);
break;
}
}
else
{
constexpr bool bUseVectorImpl = false;
switch (AddressMode)
{
case EAddressMode::ClampToBlack:
ImageTransformImpl<1, EAddressMode::ClampToBlack, bUseVectorImpl>(DestData, DestSize, DestCropRect, Src0Data, Src0Size, Src1Data, Src1Size, MipFactor, Transform);
break;
case EAddressMode::ClampToEdge:
ImageTransformImpl<1, EAddressMode::ClampToEdge, bUseVectorImpl>(DestData, DestSize, DestCropRect, Src0Data, Src0Size, Src1Data, Src1Size, MipFactor, Transform);
break;
case EAddressMode::Wrap:
ImageTransformImpl<1, EAddressMode::Wrap, bUseVectorImpl>(DestData, DestSize, DestCropRect, Src0Data, Src0Size, Src1Data, Src1Size, MipFactor, Transform);
break;
default:
check(false);
break;
}
}
break;
}
case EImageFormat::RGB_UByte:
{
if (bUseVectorImplCvar)
{
constexpr bool bUseVectorImpl = true;
switch (AddressMode)
{
case EAddressMode::ClampToBlack:
ImageTransformImpl<3, EAddressMode::ClampToBlack, bUseVectorImpl>(DestData, DestSize, DestCropRect, Src0Data, Src0Size, Src1Data, Src1Size, MipFactor, Transform);
break;
case EAddressMode::ClampToEdge:
ImageTransformImpl<3, EAddressMode::ClampToEdge, bUseVectorImpl>(DestData, DestSize, DestCropRect, Src0Data, Src0Size, Src1Data, Src1Size, MipFactor, Transform);
break;
case EAddressMode::Wrap:
ImageTransformImpl<3, EAddressMode::Wrap, bUseVectorImpl>(DestData, DestSize, DestCropRect, Src0Data, Src0Size, Src1Data, Src1Size, MipFactor, Transform);
break;
default:
check(false);
break;
}
}
else
{
constexpr bool bUseVectorImpl = false;
switch (AddressMode)
{
case EAddressMode::ClampToBlack:
ImageTransformImpl<3, EAddressMode::ClampToBlack, bUseVectorImpl>(DestData, DestSize, DestCropRect, Src0Data, Src0Size, Src1Data, Src1Size, MipFactor, Transform);
break;
case EAddressMode::ClampToEdge:
ImageTransformImpl<3, EAddressMode::ClampToEdge, bUseVectorImpl>(DestData, DestSize, DestCropRect, Src0Data, Src0Size, Src1Data, Src1Size, MipFactor, Transform);
break;
case EAddressMode::Wrap:
ImageTransformImpl<3, EAddressMode::Wrap, bUseVectorImpl>(DestData, DestSize, DestCropRect, Src0Data, Src0Size, Src1Data, Src1Size, MipFactor, Transform);
break;
default:
check(false);
break;
}
}
break;
}
case EImageFormat::BGRA_UByte:
case EImageFormat::RGBA_UByte:
{
if (bUseVectorImplCvar)
{
constexpr bool bUseVectorImpl = true;
switch (AddressMode)
{
case EAddressMode::ClampToBlack:
ImageTransformImpl<4, EAddressMode::ClampToBlack, bUseVectorImpl>(DestData, DestSize, DestCropRect, Src0Data, Src0Size, Src1Data, Src1Size, MipFactor, Transform);
break;
case EAddressMode::ClampToEdge:
ImageTransformImpl<4, EAddressMode::ClampToEdge, bUseVectorImpl>(DestData, DestSize, DestCropRect, Src0Data, Src0Size, Src1Data, Src1Size, MipFactor, Transform);
break;
case EAddressMode::Wrap:
ImageTransformImpl<4, EAddressMode::Wrap, bUseVectorImpl>(DestData, DestSize, DestCropRect, Src0Data, Src0Size, Src1Data, Src1Size, MipFactor, Transform);
break;
default:
check(false);
break;
}
}
else
{
constexpr bool bUseVectorImpl = false;
switch (AddressMode)
{
case EAddressMode::ClampToBlack:
ImageTransformImpl<4, EAddressMode::ClampToBlack, bUseVectorImpl>(DestData, DestSize, DestCropRect, Src0Data, Src0Size, Src1Data, Src1Size, MipFactor, Transform);
break;
case EAddressMode::ClampToEdge:
ImageTransformImpl<4, EAddressMode::ClampToEdge, bUseVectorImpl>(DestData, DestSize, DestCropRect, Src0Data, Src0Size, Src1Data, Src1Size, MipFactor, Transform);
break;
case EAddressMode::Wrap:
ImageTransformImpl<4, EAddressMode::Wrap, bUseVectorImpl>(DestData, DestSize, DestCropRect, Src0Data, Src0Size, Src1Data, Src1Size, MipFactor, Transform);
break;
default:
check(false);
break;
}
}
break;
}
default:
// Case not implemented
check( false );
}
}
}