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]
313 lines
7.6 KiB
C++
313 lines
7.6 KiB
C++
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
#pragma once
|
|
|
|
#include "Misc/CoreDefines.h"
|
|
#include "Math/IntPoint.h"
|
|
#include "IImageWrapper.h"
|
|
#include "Templates/UniquePtr.h"
|
|
#include "ImageCore.h"
|
|
|
|
class FFloat16Color;
|
|
template<typename PixelType> struct TImagePixelDataTraits;
|
|
|
|
|
|
// todo : use ImageCore ERawImageFormat instead
|
|
enum class EImagePixelType
|
|
{
|
|
Color,
|
|
Float16,
|
|
Float32,
|
|
};
|
|
|
|
struct IImagePixelDataPayload
|
|
{
|
|
virtual ~IImagePixelDataPayload() {}
|
|
};
|
|
|
|
typedef TSharedPtr<IImagePixelDataPayload, ESPMode::ThreadSafe> FImagePixelPayloadPtr;
|
|
|
|
|
|
// todo : use ImageCore FImage instead
|
|
// get rid of this whole class and TImagePixelData too
|
|
// just use an FImage instead
|
|
struct FImagePixelData
|
|
{
|
|
virtual ~FImagePixelData() {}
|
|
|
|
// NOTE : before, U8 would be written to EXR *linear*
|
|
// now it will get gamma corrected if bSRGB (which is on by default)
|
|
|
|
/**
|
|
* Retrieve the type of this data
|
|
*/
|
|
EImagePixelType GetType() const
|
|
{
|
|
return Type;
|
|
}
|
|
|
|
/**
|
|
* Retrieve the size of this data
|
|
*/
|
|
FIntPoint GetSize() const
|
|
{
|
|
return Size;
|
|
}
|
|
|
|
/**
|
|
* Retrieve the pixel layout of this data
|
|
*/
|
|
ERGBFormat GetPixelLayout() const
|
|
{
|
|
return PixelLayout;
|
|
}
|
|
|
|
/**
|
|
* Retrieve the number of bits per each channel of color in the data
|
|
*/
|
|
uint8 GetBitDepth() const
|
|
{
|
|
return BitDepth;
|
|
}
|
|
|
|
/**
|
|
* Retrieve the number of channels in the data
|
|
*/
|
|
uint8 GetNumChannels() const
|
|
{
|
|
return NumChannels;
|
|
}
|
|
|
|
/**
|
|
* Get the pixel data as an FImage
|
|
*/
|
|
FImageView GetImageView() const
|
|
{
|
|
const void* RawPtr = nullptr;
|
|
int64 SizeBytes = 0;
|
|
|
|
FImageView Ret;
|
|
|
|
if ( ! GetRawData(RawPtr, SizeBytes) )
|
|
{
|
|
return FImageView();
|
|
}
|
|
|
|
check( NumChannels == 4 );
|
|
|
|
switch(Type)
|
|
{
|
|
case EImagePixelType::Color:
|
|
check(PixelLayout == ERGBFormat::BGRA );
|
|
check(BitDepth == 8 );
|
|
Ret = FImageView( (const FColor *)RawPtr, Size.X, Size.Y, bSRGB ? EGammaSpace::sRGB : EGammaSpace::Linear );
|
|
break;
|
|
|
|
case EImagePixelType::Float16:
|
|
check(PixelLayout == ERGBFormat::RGBAF );
|
|
check(BitDepth == 16 );
|
|
Ret = FImageView( (const FFloat16Color *)RawPtr, Size.X, Size.Y );
|
|
break;
|
|
|
|
case EImagePixelType::Float32:
|
|
check(PixelLayout == ERGBFormat::RGBAF );
|
|
check(BitDepth == 32 );
|
|
Ret = FImageView( (const FLinearColor *)RawPtr, Size.X, Size.Y );
|
|
break;
|
|
|
|
default:
|
|
check(0);
|
|
return FImageView();
|
|
}
|
|
|
|
check( Ret.GetImageSizeBytes() == SizeBytes );
|
|
return Ret;
|
|
}
|
|
|
|
/**
|
|
* Check that this data is the size it should be
|
|
*/
|
|
bool IsDataWellFormed() const
|
|
{
|
|
const void* RawPtr = nullptr;
|
|
int64 SizeBytes = 0;
|
|
|
|
return GetRawData(RawPtr, SizeBytes);
|
|
}
|
|
|
|
/**
|
|
* Get the data and its size only if it is well formed
|
|
*/
|
|
bool GetRawData(const void*& OutRawData, int64& OutSizeBytes) const
|
|
{
|
|
const void* RawPtr = nullptr;
|
|
int64 SizeBytes = 0;
|
|
|
|
RetrieveData(RawPtr, SizeBytes);
|
|
|
|
int64 FoundTotalSize = int64(Size.X)*int64(Size.Y)*int64(BitDepth / 8)*int64(NumChannels);
|
|
if (RawPtr && SizeBytes == FoundTotalSize)
|
|
{
|
|
OutRawData = RawPtr;
|
|
OutSizeBytes = SizeBytes;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Get the size in bytes, regardless of if it is well formed.
|
|
*/
|
|
int64 GetRawDataSizeInBytes() const
|
|
{
|
|
const void* RawPtr = nullptr;
|
|
int64 SizeBytes = 0;
|
|
|
|
RetrieveData(RawPtr, SizeBytes);
|
|
return SizeBytes;
|
|
}
|
|
|
|
/**
|
|
* Copy this whole image buffer. This can be very costly for large images.
|
|
*/
|
|
TUniquePtr<FImagePixelData> CopyImageData() const
|
|
{
|
|
return Copy();
|
|
}
|
|
|
|
/**
|
|
* Move this whole image buffer to a new allocation.
|
|
*/
|
|
TUniquePtr<FImagePixelData> MoveImageDataToNew()
|
|
{
|
|
return Move();
|
|
}
|
|
|
|
/**
|
|
* Return a pointer to the Payload stored in this data.
|
|
*/
|
|
template<typename T>
|
|
T* GetPayload() { return static_cast<T*>(Payload.Get()); }
|
|
|
|
/**
|
|
* Return a const pointer to the Payload stored in this data.
|
|
*/
|
|
template<typename T>
|
|
const T* GetPayload() const { return static_cast<T*>(Payload.Get()); }
|
|
|
|
bool GetSRGB() const { return bSRGB; }
|
|
void SetSRGB(bool InSRGB) { bSRGB = InSRGB; }
|
|
|
|
protected:
|
|
|
|
FImagePixelData(const FIntPoint& InSize, EImagePixelType InPixelType, ERGBFormat InPixelLayout, uint8 InBitDepth, uint8 InNumChannels, FImagePixelPayloadPtr InPayload)
|
|
: Size(InSize)
|
|
, Type(InPixelType)
|
|
, PixelLayout(InPixelLayout)
|
|
, BitDepth(InBitDepth)
|
|
, NumChannels(InNumChannels)
|
|
, Payload(InPayload)
|
|
{
|
|
// FColor is sRGB by default, floats are Linear
|
|
bSRGB = ( InPixelType == EImagePixelType::Color );
|
|
}
|
|
|
|
private:
|
|
|
|
/**
|
|
* Retrieve the raw pixel data
|
|
*/
|
|
virtual void RetrieveData(const void*& OutDataPtr, int64& OutSizeBytes) const = 0;
|
|
virtual TUniquePtr<FImagePixelData> Copy() const = 0;
|
|
virtual TUniquePtr<FImagePixelData> Move() = 0;
|
|
|
|
/** The size of the pixel data */
|
|
FIntPoint Size;
|
|
|
|
/** The type of the derived data */
|
|
EImagePixelType Type;
|
|
|
|
/** The pixel layout of this data */
|
|
ERGBFormat PixelLayout;
|
|
|
|
/** The number of bits per each channel of color in the data */
|
|
uint8 BitDepth;
|
|
|
|
/** Number of channels in the data */
|
|
uint8 NumChannels;
|
|
|
|
/** Is FColor SRGB or Linear? Floats are always Linear and ignore this */
|
|
bool bSRGB;
|
|
|
|
/** Optional user-specified payload */
|
|
FImagePixelPayloadPtr Payload;
|
|
};
|
|
|
|
/**
|
|
* Templated pixel data - currently supports FColor, FFloat16Color and FLinearColor
|
|
*/
|
|
template<typename PixelType>
|
|
struct TImagePixelData : FImagePixelData
|
|
{
|
|
TArray64<PixelType> Pixels;
|
|
|
|
TImagePixelData(const FIntPoint& InSize)
|
|
: FImagePixelData(InSize, TImagePixelDataTraits<PixelType>::PixelType, TImagePixelDataTraits<PixelType>::PixelLayout, TImagePixelDataTraits<PixelType>::BitDepth, TImagePixelDataTraits<PixelType>::NumChannels, nullptr)
|
|
{}
|
|
|
|
TImagePixelData(const FIntPoint& InSize, TArray64<PixelType>&& InPixels)
|
|
: FImagePixelData(InSize, TImagePixelDataTraits<PixelType>::PixelType, TImagePixelDataTraits<PixelType>::PixelLayout, TImagePixelDataTraits<PixelType>::BitDepth, TImagePixelDataTraits<PixelType>::NumChannels, nullptr)
|
|
, Pixels(MoveTemp(InPixels))
|
|
{}
|
|
|
|
TImagePixelData(const FIntPoint& InSize, FImagePixelPayloadPtr InPayload)
|
|
: FImagePixelData(InSize, TImagePixelDataTraits<PixelType>::PixelType, TImagePixelDataTraits<PixelType>::PixelLayout, TImagePixelDataTraits<PixelType>::BitDepth, TImagePixelDataTraits<PixelType>::NumChannels, InPayload)
|
|
{}
|
|
|
|
TImagePixelData(const FIntPoint& InSize, TArray64<PixelType>&& InPixels, FImagePixelPayloadPtr InPayload)
|
|
: FImagePixelData(InSize, TImagePixelDataTraits<PixelType>::PixelType, TImagePixelDataTraits<PixelType>::PixelLayout, TImagePixelDataTraits<PixelType>::BitDepth, TImagePixelDataTraits<PixelType>::NumChannels, InPayload)
|
|
, Pixels(MoveTemp(InPixels))
|
|
{}
|
|
|
|
virtual TUniquePtr<FImagePixelData> Move() override
|
|
{
|
|
return MakeUnique<TImagePixelData<PixelType>>(MoveTemp(*this));
|
|
}
|
|
|
|
virtual TUniquePtr<FImagePixelData> Copy() const override
|
|
{
|
|
return MakeUnique<TImagePixelData<PixelType>>(*this);
|
|
}
|
|
|
|
virtual void RetrieveData(const void*& OutDataPtr, int64& OutSizeBytes) const override
|
|
{
|
|
OutDataPtr = static_cast<const void*>(&Pixels[0]);
|
|
OutSizeBytes = Pixels.Num() * sizeof(PixelType);
|
|
}
|
|
};
|
|
|
|
template<> struct TImagePixelDataTraits<FColor>
|
|
{
|
|
static const ERGBFormat PixelLayout = ERGBFormat::BGRA;
|
|
static const EImagePixelType PixelType = EImagePixelType::Color;
|
|
|
|
enum { BitDepth = 8, NumChannels = 4 };
|
|
};
|
|
|
|
template<> struct TImagePixelDataTraits<FFloat16Color>
|
|
{
|
|
static const ERGBFormat PixelLayout = ERGBFormat::RGBAF;
|
|
static const EImagePixelType PixelType = EImagePixelType::Float16;
|
|
|
|
enum { BitDepth = 16, NumChannels = 4 };
|
|
};
|
|
|
|
template<> struct TImagePixelDataTraits<FLinearColor>
|
|
{
|
|
static const ERGBFormat PixelLayout = ERGBFormat::RGBAF;
|
|
static const EImagePixelType PixelType = EImagePixelType::Float32;
|
|
|
|
enum { BitDepth = 32, NumChannels = 4 };
|
|
};
|
|
|