Hi. I’m trying to calculate the ratio 0-1 of black and white pixels in a material. I need this value to calculate a drag function to try and simulate aerodynamics. Unfortunately I can’t seem to find any information on how exactly I’d get that data and for the life of me I’m stumped.
Example image of what I’m working with attatched.
.h
will need include
#include “Structs.h”
ratio struct
USTRUCT(BlueprintType)
struct FRatios
{
GENERATED_BODY();
public:
UPROPERTY(BlueprintReadOnly, VisibleAnywhere, Transient, meta = (NoSpinbox = true))
int32 color1Ratio;
UPROPERTY(BlueprintReadOnly, VisibleAnywhere, Transient, meta = (NoSpinbox = true))
int32 color2Ratio;
};
UFUNCTION(BlueprintCallable)
static FRatios CalulateColorRatio(UTexture2D* PassedAsset, FColor Color1, FColor Color2);
Static function implementation in blueprintlibrary
FRatios UImageFunctionLibrary::CalulateColorRatio(UTexture2D* PassedAsset, FColor Color1, FColor Color2) {
int32 sizeX = PassedAsset->GetSizeX();
int32 sizeY = PassedAsset->GetSizeY();
FRatios ret;
ret.color1Ratio = 0;
ret.color2Ratio = 0;
int32 Color1Amount = 0;
int32 Color2Amount = 0;
if (PassedAsset != nullptr) {
TextureCompressionSettings OldCompressionSettings = PassedAsset->CompressionSettings; TextureMipGenSettings OldMipGenSettings = PassedAsset->MipGenSettings; bool OldSRGB = PassedAsset->SRGB;
PassedAsset->CompressionSettings = TextureCompressionSettings::TC_VectorDisplacementmap;
PassedAsset->MipGenSettings = TextureMipGenSettings::TMGS_NoMipmaps;
PassedAsset->SRGB = false;
PassedAsset->UpdateResource();
const FColor* FormatedImageData = reinterpret_cast<const FColor*>(PassedAsset->PlatformData->Mips[0].BulkData.LockReadOnly());
for (int32 X = 0; X < sizeX; X++)
{
for (int32 Y = 0; Y < sizeY; Y++)
{
FColor PixelColor = FormatedImageData[Y * sizeX + X];
if (PixelColor == Color1) {
Color1Amount++;
}
else if (PixelColor == Color2) {
Color2Amount++;
}
}
}
PassedAsset->PlatformData->Mips[0].BulkData.Unlock();
PassedAsset->CompressionSettings = OldCompressionSettings;
PassedAsset->MipGenSettings = OldMipGenSettings;
PassedAsset->SRGB = OldSRGB;
PassedAsset->UpdateResource();
int32 commonDiv = FMath::GreatestCommonDivisor(Color1Amount, Color2Amount);
if (commonDiv != 0) {
ret.color1Ratio = Color1Amount / commonDiv;
ret.color2Ratio = Color2Amount / commonDiv;
return ret;
}
}
return ret;
}
When passing in colors make sure the alpha is set to 1 otherwise the comparison will fail
OFC passed in 2 colors will be black and white color variables.
Pixel code reading sourced from
I didn’t put a strict division of the returned ratio x : y seeing it’s probably easier to just manipulate the returned values as needed.
Thanks, I found a blueprints based solution but it’s horrifically un-performant. I’ll have to get on this later to patch things up.