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 );
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								}
							 |