209 lines
7.2 KiB
C++
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 );
|
|
}
|
|
}
|
|
|
|
}
|