#pragma once #include "CoreMinimal.h" /** * Luminance statistics of a screenshot, the numbers of the shot sidecar JSON (DESIGN_UE.md section 9.2). * All values are of the sRGB-ENCODED pixels (what a person sees in the PNG), scaled to 0..1, with Rec.709 * weights: luma = 0.2126 R + 0.7152 G + 0.0722 B. Pure functions, no engine state, so tests can feed synthetic images. */ struct FDescentLumaStats { int32 Width = 0; int32 Height = 0; /** Mean luma of the whole frame. */ double MeanLuma = 0.0; /** Mean luma of the central 40 percent x 40 percent of the frame (x and y from 30 to 70 percent). */ double CentreLuma = 0.0; /** Fraction of pixels with any channel above 8/255. Near 0 means a black or unrendered frame. */ double NonBlack = 0.0; /** 99th percentile of the per-pixel luma (resolution 1/1020). */ double P99Luma = 0.0; /** Mean of each channel, 0..1. */ double MeanR = 0.0; double MeanG = 0.0; double MeanB = 0.0; /** * How much there is to see in the central 40 x 40 percent (fix list after M3, requirement V1: rock in the lamp must read as rock). * The rectangle is cut into blocks of Width / 160 pixels (8 at 1280), which averages film grain away. * CentreDetail: the mean Michelson contrast |a - b| / (a + b + 0.02) of neighbouring blocks: edges, facets, veins. A smooth gradient * (the lamp's own falloff) gives almost 0, a flat grey disc 0. CentreRms: standard deviation / mean of the block lumas (includes the falloff). */ double CentreDetail = 0.0; double CentreRms = 0.0; }; namespace Descent::Image { /** Luma of one pixel, 0..1. */ THEDESCENT_API double Luma01(const FColor& C); /** Whole-frame statistics. Pixels is row-major, top row first, Width * Height long; an empty or mismatched image gives zeros. */ THEDESCENT_API FDescentLumaStats ComputeStats(TConstArrayView64 Pixels, int32 Width, int32 Height); /** Mean luma of the rectangle X0..X1 x Y0..Y1 given as fractions of the frame (0..1, origin top left). */ THEDESCENT_API double MeanLumaRect(TConstArrayView64 Pixels, int32 Width, int32 Height, double X0, double Y0, double X1, double Y1); /** Block contrast of a rectangle given as fractions of the frame: see FDescentLumaStats::CentreDetail / CentreRms. */ THEDESCENT_API void BlockContrastRect(TConstArrayView64 Pixels, int32 Width, int32 Height, double X0, double Y0, double X1, double Y1, double& OutDetail, double& OutRms); /** Mean luma of the pixels whose centre is between R0 and R1 pixels from (Cx, Cy) (pixels, origin top left). */ THEDESCENT_API double MeanLumaRing(TConstArrayView64 Pixels, int32 Width, int32 Height, double Cx, double Cy, double R0, double R1); }