Files
UnrealEngineUWP/Engine/Source/Runtime/ImageWriteQueue/Public/ImageWriteTask.h
charles bloom 04ffabc485 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]
2022-03-15 18:29:37 -04:00

218 lines
5.2 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include "Misc/CoreDefines.h"
#include "Math/Color.h"
#include "Math/Float16Color.h"
#include "Math/IntPoint.h"
#include "Templates/UniquePtr.h"
#include "IImageWrapper.h"
#include "ImagePixelData.h"
template<typename> struct TImageDataTraits;
typedef TUniqueFunction<void(FImagePixelData*)> FPixelPreProcessor;
/**
* Interface that is implemented in order to be able to asynchronously write images to disk
*/
class IImageWriteTaskBase
{
public:
/**
* Virtual destruction
*/
virtual ~IImageWriteTaskBase() {}
/**
*
*/
virtual bool RunTask() = 0;
/**
*
*/
virtual void OnAbandoned() = 0;
};
class FImageWriteTask
: public IImageWriteTaskBase
{
public:
/** The filename to write to */
FString Filename;
/** The desired image format to write out */
EImageFormat Format;
/** A compression quality setting specific to the desired image format */
int32 CompressionQuality;
/** True if this task is allowed to overwrite an existing file, false otherwise. */
bool bOverwriteFile;
/** A function to invoke on the game thread when the task has completed */
TFunction<void(bool)> OnCompleted;
/** The actual write operation. */
TUniquePtr<FImagePixelData> PixelData;
/** Array of preprocessors to apply serially to the pixel data when this task is executed. */
TArray<FPixelPreProcessor> PixelPreProcessors;
FImageWriteTask()
: Format(EImageFormat::BMP)
, CompressionQuality((int32)EImageCompressionQuality::Default)
, bOverwriteFile(true)
{}
public:
IMAGEWRITEQUEUE_API virtual bool RunTask() override final;
IMAGEWRITEQUEUE_API virtual void OnAbandoned() override final;
private:
/**
* Run the task, attempting to write out the raw data using the currently specified parameters
*
* @return true on success, false on any failure
*/
bool WriteToDisk();
/**
* Ensures that the desired output filename is writable, deleting an existing file if bOverwriteFile is true
*
* @return True if the file is writable and the task can proceed, false otherwise
*/
bool EnsureWritableFile();
/**
* Initialize the specified image wrapper with our raw data, ready for writing
*
* @param InWrapper The wrapper to initialize with our data
* @param WrapperFormat The desired image format to write out
* @return true on success, false on any failure
*/
bool InitializeWrapper(IImageWrapper* InWrapper, EImageFormat WrapperFormat);
/**
* Run over all the processors for the pixel data
*/
void PreProcess();
};
/**
* A pixel preprocessor for use with FImageWriteTask::PixelPreProcessor that overwrites the alpha channel with a fixed value as part of the threaded work
*/
template<typename PixelType> struct TAsyncAlphaWrite;
template<>
struct TAsyncAlphaWrite<FColor>
{
uint8 Alpha;
TAsyncAlphaWrite(uint8 InAlpha) : Alpha(InAlpha) {}
void operator()(FImagePixelData* PixelData)
{
check(PixelData->GetType() == EImagePixelType::Color);
TImagePixelData<FColor>* ColorData = static_cast<TImagePixelData<FColor>*>(PixelData);
for (FColor& Pixel : static_cast<TImagePixelData<FColor>*>(PixelData)->Pixels)
{
Pixel.A = Alpha;
}
}
};
template<>
struct TAsyncAlphaWrite<FFloat16Color>
{
FFloat16 Alpha;
TAsyncAlphaWrite(float InAlpha) : Alpha(InAlpha) {}
void operator()(FImagePixelData* PixelData)
{
check(PixelData->GetType() == EImagePixelType::Float16);
TImagePixelData<FFloat16Color>* Float16ColorData = static_cast<TImagePixelData<FFloat16Color>*>(PixelData);
for (FFloat16Color& Pixel : Float16ColorData->Pixels)
{
Pixel.A = Alpha;
}
}
};
template<>
struct TAsyncAlphaWrite<FLinearColor>
{
float Alpha;
TAsyncAlphaWrite(float InAlpha) : Alpha(InAlpha) {}
void operator()(FImagePixelData* PixelData)
{
check(PixelData->GetType() == EImagePixelType::Float32);
TImagePixelData<FLinearColor>* LinearColorData = static_cast<TImagePixelData<FLinearColor>*>(PixelData);
for (FLinearColor& Pixel : LinearColorData->Pixels)
{
Pixel.A = Alpha;
}
}
};
/**
* A pixel preprocessor for use with FImageWriteTask::PixelPreProcessor that inverts the alpha channel as part of the threaded work
*/
template<typename PixelType> struct TAsyncAlphaInvert;
template<>
struct TAsyncAlphaInvert<FColor>
{
void operator()(FImagePixelData* PixelData)
{
check(PixelData->GetType() == EImagePixelType::Color);
TImagePixelData<FColor>* ColorData = static_cast<TImagePixelData<FColor>*>(PixelData);
for (FColor& Pixel : static_cast<TImagePixelData<FColor>*>(PixelData)->Pixels)
{
Pixel.A = 255 - Pixel.A;
}
}
};
template<>
struct TAsyncAlphaInvert<FFloat16Color>
{
void operator()(FImagePixelData* PixelData)
{
check(PixelData->GetType() == EImagePixelType::Float16);
TImagePixelData<FFloat16Color>* Float16ColorData = static_cast<TImagePixelData<FFloat16Color>*>(PixelData);
for (FFloat16Color& Pixel : Float16ColorData->Pixels)
{
Pixel.A = FFloat16(1.f) - Pixel.A;
}
}
};
template<>
struct TAsyncAlphaInvert<FLinearColor>
{
void operator()(FImagePixelData* PixelData)
{
check(PixelData->GetType() == EImagePixelType::Float32);
TImagePixelData<FLinearColor>* LinearColorData = static_cast<TImagePixelData<FLinearColor>*>(PixelData);
for (FLinearColor& Pixel : LinearColorData->Pixels)
{
Pixel.A = 1.f - Pixel.A;
}
}
};