ImageWrapper and import/export refactor

FImage is now the standard preferred type for a bag of pixels
FImageView can point at pixels without owning an allocation
ERawImageFormat (FImage) converts to ETextureSourceFormat
FImageUtils provides generic load/save and get/set from FImage
major cleanup in the ImageWrappers
new preferred API is through ImageWrapperModule Compress/Decompress
SetRaw/GetRaw functions cleaned up to not have undefined behavior on unexpected formats
ImageWrapper output added for HDR,BMP,TGA
RGBA32F format added and supported throughout import/export
EditorFactories import/export made more generic, most image types handled the same way using FImage now
Deprecate old TSF RGBA order pixel formats
Fix many crashes or bad handling of unusual pixel formats
Pixel access functions should be used instead of switches on pixel type

#preflight 6230ade7e65a7e65d68a187c
#rb julien.stjean,martins.mozeiko,dan.thompson,fabian.giesen

[CL 19397199 by charles bloom in ue5-main branch]
This commit is contained in:
charles bloom
2022-03-15 18:29:37 -04:00
parent 49edd618d0
commit 04ffabc485
74 changed files with 3789 additions and 1607 deletions
@@ -115,27 +115,6 @@ namespace MediaRecorderHelpers
return MoveTemp(PixelData);
};
TUniquePtr<TImagePixelData<FColor>> ConvertSampleInterpretedAsFloat16ColorToFColor(TSharedPtr<IMediaTextureSample, ESPMode::ThreadSafe> InSample, const FIntPoint InSize, int32 InNumChannels)
{
const int64 NumberOfTexel = InSize.Y * InSize.X;
TUniquePtr<TImagePixelData<FColor>> PixelData = MakeUnique<TImagePixelData<FColor>>(InSize);
PixelData->Pixels.Reset(NumberOfTexel);
const FFloat16Color* Buffer = reinterpret_cast<const FFloat16Color*>(InSample->GetBuffer());
for (int64 i = 0 ; i < NumberOfTexel; i++)
{
FColor Output;
Output.R = (uint8)(FMath::Clamp<float>(Buffer[0].R, 0.0f, 1.0f) * 255);
Output.G = (uint8)(FMath::Clamp<float>(Buffer[0].G, 0.0f, 1.0f) * 255);
Output.B = (uint8)(FMath::Clamp<float>(Buffer[0].B, 0.0f, 1.0f) * 255);
Output.A = (uint8)(FMath::Clamp<float>(Buffer[0].A, 0.0f, 1.0f) * 255);
PixelData->Pixels.Add(Output);
Buffer++;
}
return MoveTemp(PixelData);
}
}
/* FMediaRecorder implementation
@@ -252,9 +231,6 @@ void FMediaRecorder::TickRecording()
continue;
}
bool bIsGammaCorrectionPreProcessingEnabled = (TargetImageFormat == EImageFormat::EXR && Sample->IsOutputSrgb());
bool IsFloatFormatConversionNeeded = ((Sample->GetFormat() == EMediaTextureSampleFormat::FloatRGBA) && (TargetImageFormat != EImageFormat::EXR));
TUniquePtr<FImageWriteTask> ImageTask = MakeUnique<FImageWriteTask>();
// Set PixelData
@@ -273,21 +249,14 @@ void FMediaRecorder::TickRecording()
}
// Should we move the color buffer into a raw image data container.
bool bUseFMediaImagePixelData = bSetAlpha || (Sample->GetStride() != Size.X * NumChannels) || bIsGammaCorrectionPreProcessingEnabled || IsFloatFormatConversionNeeded;
bool bUseFMediaImagePixelData = bSetAlpha || (Sample->GetStride() != Size.X * NumChannels * (BitDepth/8));
if (bUseFMediaImagePixelData)
{
const int32 NumberOfTexel = Size.Y * Size.X;
if (Sample->GetFormat() == EMediaTextureSampleFormat::FloatRGBA)
{
if (IsFloatFormatConversionNeeded)
{
ImageTask->PixelData = MediaRecorderHelpers::ConvertSampleInterpretedAsFloat16ColorToFColor(Sample, Size, NumChannels);
}
else
{
ImageTask->PixelData = MediaRecorderHelpers::CreatePixelData<FFloat16Color>(Sample, Size, NumChannels);
}
ImageTask->PixelData = MediaRecorderHelpers::CreatePixelData<FFloat16Color>(Sample, Size, NumChannels);
}
else
{
@@ -319,11 +288,11 @@ void FMediaRecorder::TickRecording()
}
}
}
if (bIsGammaCorrectionPreProcessingEnabled)
if (Sample->GetFormat() == EMediaTextureSampleFormat::CharBGRA)
{
const float DefaultGammaValue = 2.2f;
ImageTask->PixelPreProcessors.Add(TAsyncGammaCorrect<FColor>(DefaultGammaValue));
// IsOutputSrgb almost always true
ImageTask->PixelData->SetSRGB( Sample->IsOutputSrgb() );
}
ImageTask->Format = TargetImageFormat;