namespace XFEEDToolBox.Core.Rendering;
/// <summary>Rejects flat empty cubes and sharp scene geometry in original environment-map candidates.</summary>
public static class SkyboxPixels
{
public readonly record struct Metrics(double Mean,int LongestEdge,int LargestEdgeComponent);
public static Metrics Inspect(byte[] bgra,int width,int height)
{
if(width<8||height<8||bgra.Length!=(long)width*height*4)throw new ArgumentException("Invalid skybox inspection pixels.");
var luminance=new float[width*height];var edges=new bool[luminance.Length];double sum=0;
for(var i=0;i<luminance.Length;i++){var p=i*4;luminance[i]=(bgra[p]*.114f+bgra[p+1]*.587f+bgra[p+2]*.299f)/255;sum+=luminance[i];}
var longest=0;
for(var y=1;y<height;y++)
{
var run=0;
for(var x=1;x<width;x++)
{
var i=y*width+x;var vertical=Math.Abs(luminance[i]-luminance[i-width])>.035f;
edges[i]=vertical||Math.Abs(luminance[i]-luminance[i-1])>.035f;
run=vertical?run+1:0;longest=Math.Max(longest,run);
}
}
for(var x=1;x<width;x++)
{
var run=0;for(var y=1;y<height;y++){var i=y*width+x;run=Math.Abs(luminance[i]-luminance[i-1])>.035f?run+1:0;longest=Math.Max(longest,run);}
}
var queue=new int[luminance.Length];var largest=0;
for(var i=0;i<edges.Length;i++)
{
if(!edges[i])continue;edges[i]=false;var read=0;var count=1;queue[0]=i;
while(read<count)
{
var pixel=queue[read++];
void Visit(int next){if(edges[next]){edges[next]=false;queue[count++]=next;}}
if(pixel%width>0)Visit(pixel-1);if(pixel%width<width-1)Visit(pixel+1);
if(pixel>=width)Visit(pixel-width);if(pixel+width<edges.Length)Visit(pixel+width);
}
largest=Math.Max(largest,count);
}
return new(sum/luminance.Length,longest,largest);
}
}
namespace XFEEDToolBox.Core.Rendering;
/// <summary>Rejects flat empty cubes and sharp scene geometry in original environment-map candidates.</summary>
public static class SkyboxPixels
{
public readonly record struct Metrics(double Mean,int LongestEdge,int LargestEdgeComponent);
public static Metrics Inspect(byte[] bgra,int width,int height)
{
if(width<8||height<8||bgra.Length!=(long)width*height*4)throw new ArgumentException("Invalid skybox inspection pixels.");
var luminance=new float[width*height];var edges=new bool[luminance.Length];double sum=0;
for(var i=0;i<luminance.Length;i++){var p=i*4;luminance[i]=(bgra[p]*.114f+bgra[p+1]*.587f+bgra[p+2]*.299f)/255;sum+=luminance[i];}
var longest=0;
for(var y=1;y<height;y++)
{
var run=0;
for(var x=1;x<width;x++)
{
var i=y*width+x;var vertical=Math.Abs(luminance[i]-luminance[i-width])>.035f;
edges[i]=vertical||Math.Abs(luminance[i]-luminance[i-1])>.035f;
run=vertical?run+1:0;longest=Math.Max(longest,run);
}
}
for(var x=1;x<width;x++)
{
var run=0;for(var y=1;y<height;y++){var i=y*width+x;run=Math.Abs(luminance[i]-luminance[i-1])>.035f?run+1:0;longest=Math.Max(longest,run);}
}
var queue=new int[luminance.Length];var largest=0;
for(var i=0;i<edges.Length;i++)
{
if(!edges[i])continue;edges[i]=false;var read=0;var count=1;queue[0]=i;
while(read<count)
{
var pixel=queue[read++];
void Visit(int next){if(edges[next]){edges[next]=false;queue[count++]=next;}}
if(pixel%width>0)Visit(pixel-1);if(pixel%width<width-1)Visit(pixel+1);
if(pixel>=width)Visit(pixel-width);if(pixel+width<edges.Length)Visit(pixel+width);
}
largest=Math.Max(largest,count);
}
return new(sum/luminance.Length,longest,largest);
}
}