(39) 's Extra Blueprint Nodes for You as a Plugin, No C++ Required!

I am mostly just using UE4 API functions for , so I am not sure what the cause of the is.

Here is the relevant portion of the source code for node:



bool UVictoryBPFunctionLibrary::Victory_SavePixels(const FString& FullFilePath,int32 Width, int32 Height, const TArray<FLinearColor>& ImagePixels, FString& ErrorString)
{
	//Create FColor version
	TArray<FColor> ColorArray;
	for(const FLinearColor& Each : ImagePixels)
	{
		ColorArray.Add(Each.ToFColor(true));
	} 
	 
	if(ColorArray.Num() != Width * Height) 
	{
		ErrorString = "Error ~ height x width is not equal to the total pixel array length!";
		return false;
	}
	  
	TArray<uint8> CompressedPNG;
	FImageUtils::CompressImageArray( 
		Width, 
		Height, 
		ColorArray, 
		CompressedPNG
	);
	    
	return FFileHelper::SaveArrayToFile(CompressedPNG, *FinalFilename);


There’s not much room here for me to make mistakes of my own, its really just API calls.

But clearly something is amiss, I tested saving as a bmp and got the same unusual results as with compressed png:

I did a test with 0.25 and got 137 as well, instead of what you’d expect, 63.75 (255 * 0.25).

I tested 0.715 and got 220 instead of 182.325

The culprit appears to be the ToFColor function:



//Create FColor version
TArray<FColor> ColorArray;
for(const FLinearColor& Each : ImagePixels)
{
	ColorArray.Add(Each.ToFColor(true)); 
	UE_LOG(LogTemp,Error,TEXT("float is %f, byte added as %d"), Each.R, ColorArray.Last().R); 
} 


yields :



LogTemp:Error: float is 0.000000, byte added as 0
LogTemp:Error: float is 0.250000, byte added as 137
LogTemp:Error: float is 0.000000, byte added as 0
LogTemp:Error: float is 0.000000, byte added as 0
LogTemp:Error: float is 1.000000, byte added as 255
LogTemp:Error: float is 0.000000, byte added as 0
LogTemp:Error: float is 0.000000, byte added as 0
LogTemp:Error: float is 0.715000, byte added as 220
LogTemp:Error: float is 0.000000, byte added as 0


So the conversion you are not enjoying is being by FLinearColor::ToFColor

ToFColor has sRGB option:



/** Quantizes the linear color and returns the result as a FColor with optional sRGB conversion and quality as goal. */
FColor FLinearColor::ToFColor(const bool bSRGB) const
{


The sRGB conversion algorithm can be found in Color.cpp if you want to see it for yourself!

When I set that to false then the values you’d expect are returned:



LogTemp:Error: float is 0.000000, byte added as 0
LogTemp:Error: float is 0.250000, byte added as 63
LogTemp:Error: float is 0.000000, byte added as 0
LogTemp:Error: float is 0.000000, byte added as 0
LogTemp:Error: float is 1.000000, byte added as 255
LogTemp:Error: float is 0.000000, byte added as 0
LogTemp:Error: float is 0.000000, byte added as 0
LogTemp:Error: float is 0.715000, byte added as 183
LogTemp:Error: float is 0.000000, byte added as 0


You can read about sRGB here:

I’ve now made sRGB conversion optional, and off by default :slight_smile:

The update will be in my next plugin release

:slight_smile: