You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
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]
218 lines
5.2 KiB
C++
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;
|
|
}
|
|
}
|
|
};
|