254 lines
5.3 KiB
C#
254 lines
5.3 KiB
C#
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using Godot;
|
|
using System;
|
|
using System.Threading.Tasks;
|
|
|
|
using System.Linq;
|
|
using TriangleNet.Geometry;
|
|
|
|
namespace Rokojori
|
|
{
|
|
public class CPUTextureDilater
|
|
{
|
|
public static async Task<Texture2D> Dilate( Texture2D texture, Func<Task> waiting, float alphaTreshold = 250f/255f )
|
|
{
|
|
var dilater = new CPUTextureDilater();
|
|
dilater.alphaTreshold = alphaTreshold;
|
|
dilater.waiting = waiting;
|
|
|
|
var t = await dilater._Dilate( texture );
|
|
|
|
return t;
|
|
}
|
|
|
|
TextureCombinerBuffer _buffer;
|
|
Func<Task> waiting;
|
|
|
|
async Task<Texture2D> _Dilate( Texture2D texture )
|
|
{
|
|
_buffer = TextureCombinerBuffer.From( texture );
|
|
|
|
await _Process();
|
|
|
|
return _buffer.CreateImageTexture();
|
|
}
|
|
|
|
public float alphaTreshold = 250f/255f;
|
|
|
|
HashSet<int> _processed = new HashSet<int>();
|
|
HashSet<int> _unprocessed = new HashSet<int>();
|
|
HashSet<int> _edges = new HashSet<int>();
|
|
|
|
|
|
|
|
async Task _Process()
|
|
{
|
|
_buffer.UnblendBlack();
|
|
|
|
GrabInitialPixels();
|
|
|
|
|
|
if ( _unprocessed.Count == _buffer.numPixels )
|
|
{
|
|
return;
|
|
}
|
|
|
|
int maxMessages = 100;
|
|
int messageCounter = 0;
|
|
int messageLimit = 200000;
|
|
|
|
int max = 1000 * 1000;
|
|
int it = 0;
|
|
|
|
var random = LCG.WithSeed( 1984 );
|
|
|
|
while ( _edges.Count > 0 && it < max )
|
|
{
|
|
it++;
|
|
|
|
if ( messageCounter >= messageLimit )
|
|
{
|
|
await waiting();
|
|
messageCounter = 0;
|
|
RJLog.Log(
|
|
RegexUtility._FF( 100f *_processed.Count / _buffer.numPixels ) + "%",
|
|
"Valid: ", ( _processed.Count + _edges.Count + _unprocessed.Count ) == _buffer.numPixels,
|
|
"P", _processed.Count, "E",_edges.Count, "U", _unprocessed.Count
|
|
);
|
|
}
|
|
else
|
|
{
|
|
messageCounter ++;
|
|
}
|
|
|
|
var edge = _edges.ElementAt( random.IntegerExclusive( _edges.Count ) );
|
|
_edges.Remove( edge );
|
|
|
|
if ( ! _processed.Contains( edge ) )
|
|
{
|
|
var edgeColor = ComputeColor( edge );
|
|
_processed.Add( edge );
|
|
_buffer.SetIndexed( edge, edgeColor );
|
|
}
|
|
|
|
AddEdgeNeighbors( edge );
|
|
|
|
}
|
|
|
|
if ( _edges.Count > 0 && it == max )
|
|
{
|
|
RJLog.Log( "Aborted, too many entries" );
|
|
}
|
|
|
|
}
|
|
|
|
void GrabInitialPixels()
|
|
{
|
|
for ( int i = 0; i < _buffer.numPixels; i++ )
|
|
{
|
|
if ( ! HasColor( i ) )
|
|
{
|
|
_unprocessed.Add( i );
|
|
}
|
|
else
|
|
{
|
|
if ( IsEdge( i ) )
|
|
{
|
|
_edges.Add( i );
|
|
}
|
|
|
|
_processed.Add( i );
|
|
}
|
|
}
|
|
}
|
|
|
|
void AddEdgeNeighbors( int i )
|
|
{
|
|
var position = _buffer.ComputePositionFromIndex( i );
|
|
|
|
for ( int x = -1; x <= 1; x++ )
|
|
{
|
|
for ( int y = -1; y <= 1; y++ )
|
|
{
|
|
if ( x == 0 && y == 0 )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
var index = _buffer.ComputeIndexFromPosition( position.X + x, position.Y + y );
|
|
|
|
if ( index < 0 || index >= _buffer.numPixels )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if ( ! _unprocessed.Contains( index ) )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
_unprocessed.Remove( index );
|
|
_edges.Add( index );
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
bool HasColor( int x, int y )
|
|
{
|
|
return HasColor( _buffer.ComputeIndexFromPosition( x, y ) );
|
|
}
|
|
|
|
bool HasColor( int i )
|
|
{
|
|
if ( i < 0 || i >= _buffer.numPixels )
|
|
{
|
|
return false;
|
|
}
|
|
|
|
var pixel = _buffer.GetIndexed( i );
|
|
|
|
if ( pixel.A > alphaTreshold )
|
|
{
|
|
return true;
|
|
}
|
|
|
|
return _processed.Contains( i );
|
|
}
|
|
|
|
|
|
|
|
bool IsEdge( int i )
|
|
{
|
|
if ( ! HasColor( i ) )
|
|
{
|
|
return false;
|
|
}
|
|
|
|
var position = _buffer.ComputePositionFromIndex( i );
|
|
|
|
for ( int x = -1; x <= 1; x++ )
|
|
{
|
|
for ( int y = -1; y <= 1; y++ )
|
|
{
|
|
if ( x == 0 && y == 0 )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if ( ! HasColor( position.X + x, position.Y + y ) )
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
Color ComputeColor( int i )
|
|
{
|
|
var position = _buffer.ComputePositionFromIndex( i );
|
|
|
|
var pixel = _buffer.GetIndexed( i );
|
|
var distance = 10f;
|
|
var closestPixel = -1;
|
|
|
|
for ( int x = -1; x <= 1; x++ )
|
|
{
|
|
for ( int y = -1; y <= 1; y++ )
|
|
{
|
|
if ( ( x == 0 && y == 0 ) || ! HasColor( position.X + x, position.Y + y ) )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
var d = new Vector2( x, y ).Length();
|
|
|
|
if ( d >= distance )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
distance = d;
|
|
closestPixel = _buffer.ComputeIndexFromPosition( position.X + x, position.Y + y );
|
|
|
|
// var pixelColor = _buffer.GetAt( position.X + x, position.Y + y );
|
|
// rawColor += new Vector3( pixelColor.R, pixelColor.G, pixelColor.B);
|
|
// numColors ++;
|
|
}
|
|
}
|
|
|
|
// rawColor /= numColors;
|
|
|
|
var rawColor = _buffer.GetIndexed( closestPixel );
|
|
|
|
|
|
|
|
return new Color( rawColor.R, rawColor.G, rawColor.B, pixel.A );
|
|
}
|
|
}
|
|
|
|
} |