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

150 lines
4.6 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include "MuR/ImagePrivate.h"
#include "MuR/Platform.h"
#include "MuR/ParallelExecutionUtils.h"
namespace mu
{
inline void ImageColourMap(FImage* DestImage, const FImage* SourceImage, const FImage* MaskImage, const FImage* MapImage, bool bOnlyOneMip)
{
check(SourceImage->GetSizeX() == MaskImage->GetSizeX());
check(SourceImage->GetSizeY() == MaskImage->GetSizeY());
check(SourceImage->GetLODCount() == MaskImage->GetLODCount() || bOnlyOneMip);
check(SourceImage->GetFormat() == DestImage->GetFormat());
check(SourceImage->GetSize() == DestImage->GetSize());
check(MaskImage->GetFormat() == EImageFormat::L_UByte);
// Generic implementation
// Make a palette for faster conversion
uint8 Palette[256][4];
for (int32 I = 0; I < 256; ++I)
{
FVector4f Color = MapImage->Sample(FVector2f(float(I)/255.0f, 0.0f));
Palette[I][0] = (uint8)FMath::Max(0, FMath::Min(255, int32(Color[0]*255.0f)));
Palette[I][1] = (uint8)FMath::Max(0, FMath::Min(255, int32(Color[1]*255.0f)));
Palette[I][2] = (uint8)FMath::Max(0, FMath::Min(255, int32(Color[2]*255.0f)));
Palette[I][3] = (uint8)FMath::Max(0, FMath::Min(255, int32(Color[3]*255.0f)));
}
const int32 LODBegin = 0;
const int32 LODEnd = bOnlyOneMip ? 1 : DestImage->GetLODCount();
constexpr int32 NumBatchElems = 1 << 14;
const int32 BytesPerElem = GetImageFormatData(DestImage->GetFormat()).BytesPerBlock;
check(GetImageFormatData(SourceImage->GetFormat()).BytesPerBlock == BytesPerElem);
const int32 NumBatches = DestImage->DataStorage.GetNumBatchesLODRange(NumBatchElems, BytesPerElem, LODBegin, LODEnd);
check(NumBatches == SourceImage->DataStorage.GetNumBatchesLODRange(NumBatchElems, BytesPerElem, LODBegin, LODEnd));
ParallelExecutionUtils::InvokeBatchParallelFor(NumBatches,
[
DestImage, SourceImage, MaskImage, Palette, NumBatchElems, BytesPerElem, LODBegin, LODEnd
](int32 BatchId)
{
TArrayView<uint8> DestView = DestImage->DataStorage.GetBatchLODRange(BatchId, NumBatchElems, BytesPerElem, LODBegin, LODEnd);
TArrayView<const uint8> SourceView = SourceImage->DataStorage.GetBatchLODRange(BatchId, NumBatchElems, BytesPerElem, LODBegin, LODEnd);
TArrayView<const uint8> MaskView = MaskImage->DataStorage.GetBatchLODRange(BatchId, NumBatchElems, 1, LODBegin, LODEnd);
const int32 NumElems = DestView.Num() / BytesPerElem;
check(SourceView.Num() / BytesPerElem == NumElems);
check(MaskView.Num() / 1 == NumElems);
uint8* DestBuf = DestView.GetData();
const uint8* SourceBuf = SourceView.GetData();
const uint8* MaskBuf = MaskView.GetData();
switch (SourceImage->GetFormat())
{
case EImageFormat::L_UByte:
{
for (int32 I = 0; I < NumElems; ++I)
{
if (MaskBuf[I] > 127)
{
DestBuf[I] = Palette[SourceBuf[I]][0];
}
else
{
DestBuf[I] = SourceBuf[I];
}
}
break;
}
case EImageFormat::RGB_UByte:
{
for (int32 I = 0; I < NumElems; ++I)
{
if (MaskBuf[I])
{
DestBuf[3*I + 0] = Palette[SourceBuf[3*I + 0]][0];
DestBuf[3*I + 1] = Palette[SourceBuf[3*I + 1]][1];
DestBuf[3*I + 2] = Palette[SourceBuf[3*I + 2]][2];
}
else
{
DestBuf[3*I + 0] = SourceBuf[3*I + 0];
DestBuf[3*I + 1] = SourceBuf[3*I + 1];
DestBuf[3*I + 2] = SourceBuf[3*I + 2];
}
}
break;
}
case EImageFormat::RGBA_UByte:
{
for (int32 I = 0; I < NumElems; ++I)
{
if (MaskBuf[I] > 127)
{
DestBuf[4*I + 0] = Palette[SourceBuf[4*I + 0]][0];
DestBuf[4*I + 1] = Palette[SourceBuf[4*I + 1]][1];
DestBuf[4*I + 2] = Palette[SourceBuf[4*I + 2]][2];
DestBuf[4*I + 3] = Palette[SourceBuf[4*I + 3]][3];
}
else
{
DestBuf[4*I + 0] = SourceBuf[4*I + 0];
DestBuf[4*I + 1] = SourceBuf[4*I + 1];
DestBuf[4*I + 2] = SourceBuf[4*I + 2];
DestBuf[4*I + 3] = SourceBuf[4*I + 3];
}
}
break;
}
case EImageFormat::BGRA_UByte:
{
for (int32 I = 0; I < NumElems; ++I)
{
if (MaskBuf[I] > 127)
{
DestBuf[4*I + 0] = Palette[SourceBuf[4*I + 0]][2];
DestBuf[4*I + 1] = Palette[SourceBuf[4*I + 1]][1];
DestBuf[4*I + 2] = Palette[SourceBuf[4*I + 2]][0];
DestBuf[4*I + 3] = Palette[SourceBuf[4*I + 3]][3];
}
else
{
DestBuf[4*I + 0] = SourceBuf[4*I + 0];
DestBuf[4*I + 1] = SourceBuf[4*I + 1];
DestBuf[4*I + 2] = SourceBuf[4*I + 2];
DestBuf[4*I + 3] = SourceBuf[4*I + 3];
}
}
break;
}
default:
check(false);
}
});
}
}