Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Help with figuring out simple algorithm

Discussion in 'Scripting' started by pretender, Dec 25, 2014.

  1. pretender

    pretender

    Joined:
    Mar 6, 2010
    Posts:
    862
    Hi, I am trying to get border pixels of a texture.
    Here is the script that I am using to generate 2D texture with random color (usually with 8 x 8 pixels) that is applied on the cube.

    Code (CSharp):
    1.  
    2. using UnityEngine;
    3. using System.Collections;
    4.  
    5. public class TextureController : MonoBehaviour
    6. {
    7.     private Renderer _target;
    8.  
    9.     private int _width;
    10.     private int _height;
    11.  
    12.     private Color[] _pixels;
    13.     private Texture2D _pixelTexture;
    14.  
    15.     void Start()
    16.     {
    17.      
    18.     }
    19.  
    20.     public void InitColorControl(Renderer target,int dim)
    21.     {
    22.         _target = target;
    23.         SetPixelDimensions(dim);
    24.     }
    25.  
    26.     public void SetPixelDimensions(int dimension)
    27.     {
    28.         _width = _height = dimension;
    29.         _pixels = new Color[_width * _height];
    30.  
    31.         SetRandomColor();
    32.         ApplyTexture();
    33.     }
    34.  
    35.     public void SetRandomColor()
    36.     {
    37.         for (int i = 0; i < _pixels.Length; i++)
    38.             _pixels[i] = new Color(Random.value, Random.value, Random.value, 1f);
    39.     }
    40.  
    41.     private void ApplyTexture()
    42.     {
    43.         var texture = new Texture2D(_width, _height)
    44.         {
    45.             filterMode = FilterMode.Point
    46.         };
    47.  
    48.         _target.material = new Material(Shader.Find("Diffuse"));
    49.         _target.sharedMaterial.mainTexture = texture;
    50.  
    51.         for (int i = 0; i < _width; i++)
    52.         {
    53.             for (int j = 0; j < _height; j++)
    54.             {
    55.                 var index = j + i * _height;
    56.                 texture.SetPixel(i, _height - 1 - j, _pixels[index]);
    57.             }
    58.         }
    59.         texture.Apply();
    60.     }
    61. }
    62.  
    in some other script I call this method with render target passed (cube) and dimensions
    Code (csharp):
    1.  
    2. textureController.InitColorControl(cube,8);
    3.  
    later on I am chaning individal pixel of the texture like this (this will change all texture pixels to black in the coroutine:
    Code (CSharp):
    1.     public IEnumerator ChangeAllPixels()
    2.     {
    3.             var texture = _target.sharedMaterial.mainTexture as Texture2D;
    4.             for (int i = 0; i < _pixels.Length; i++)
    5.             {
    6.                 _pixels[i] = Color.black;
    7.             }
    8.  
    9.             for (int i = 0; i < _width; i++)
    10.             {
    11.                 for (int j = 0; j < _height; j++)
    12.                 {
    13.                     var index = j + i*_height;
    14.  
    15.                     texture.SetPixel(i, _height - 1 - j, _pixels[index]);
    16.                     _target.sharedMaterial.mainTexture = texture;
    17.                     texture.Apply();
    18.  
    19.                     yield return null;
    20.                 }
    21.             }
    22.             _target.sharedMaterial.mainTexture = texture;
    23.             texture.Apply();
    24.     }
    I am not that good with algorithms, can somebody help me show me how to change only border pixels (it would be fairly simple for someone experienced)

    thanks!
     
  2. kietus

    kietus

    Joined:
    Jun 4, 2013
    Posts:
    54
    Hello,

    Pixels are "border pixel" when any of this case is true :
    Code (csharp):
    1.  
    2. if ( i == 0 || i == _width || j == 0 || j == _height )
    3. ...
    4.  
    You can improve the algorithm to parse only the border pixels, including a border width, but that's depends on what you want to do.
     
    BenZed likes this.
  3. pretender

    pretender

    Joined:
    Mar 6, 2010
    Posts:
    862
    Hi! Thanks for looking into this! This works, I can use this to mark border pixels. Although I can't use this to mark border pixels in sequence like lower horizontal border - right vertical border - top horizontal boder - left vertical border

    I managed to make this work but it's not the right way,any better or more efficient solution is appreciated! (commented out section is previous solution that doesn't mark border pixels in sequence):

    Code (CSharp):
    1. public IEnumerator ChangeBorderPixels(Color color)
    2.     {
    3.         float pause = 0.05f;
    4.  
    5.         var texture = _target.sharedMaterial.mainTexture as Texture2D;
    6.      
    7.         //for (int i = 0; i < _width; i++)
    8.         //{
    9.         //    for (int j = 0; j < _height; j++)
    10.         //    {
    11.         //        if (i == 0 || i == _width-1 || j == 0 || j == _height-1)
    12.         //        {
    13.         //            var index = j + i*_height;
    14.  
    15.         //            texture.SetPixel(i, _height - 1 - j, color);
    16.         //            _target.sharedMaterial.mainTexture = texture;
    17.         //            texture.Apply();
    18.         //            yield return new WaitForSeconds(0.1f);
    19.  
    20.         //            Debug.Log(i + " " + j);
    21.         //        }
    22.         //        //yield return null;
    23.              
    24.         //    }
    25.         //}
    26.  
    27.         //horizontal
    28.         for (int i = 0; i < _width; i++)
    29.         {
    30.             texture.SetPixel(0,i,color);
    31.             _target.sharedMaterial.mainTexture = texture;
    32.             texture.Apply();
    33.             yield return new WaitForSeconds(pause);
    34.         }
    35.  
    36.         //vertical
    37.         for (int i = 0; i < _height; i++)
    38.         {
    39.             texture.SetPixel(i, _height - 1, color);
    40.             _target.sharedMaterial.mainTexture = texture;
    41.             texture.Apply();
    42.             yield return new WaitForSeconds(pause);
    43.         }
    44.  
    45.         //horizontal
    46.         for (int i = _width - 1; i >= 0; i--)
    47.         {
    48.             texture.SetPixel(_width - 1, i, color);
    49.             _target.sharedMaterial.mainTexture = texture;
    50.             texture.Apply();
    51.             yield return new WaitForSeconds(pause);
    52.         }
    53.  
    54.         //vertical
    55.         for (int i = _height - 1; i >= 0; i--)
    56.         {
    57.             texture.SetPixel(i, 0, color);
    58.             _target.sharedMaterial.mainTexture = texture;
    59.             texture.Apply();
    60.             yield return new WaitForSeconds(pause);
    61.         }
    62.  
    63.         _target.sharedMaterial.mainTexture = texture;
    64.         texture.Apply();
    65.     }
     
  4. kietus

    kietus

    Joined:
    Jun 4, 2013
    Posts:
    54
    Hello,

    The border is left when i = 0, i=width-1 is right.
    You can use 4 loop to parse only the borders values (Assuming border is 1 pixel size).
    Code (csharp):
    1.  
    2. // - parse left border
    3. for (int h=0;i<_height<h++)
    4.   SetPixel(0,h);
    5. // - parse  top border
    6. for (int w=0;i<_width<w++)
    7.   SetPixel(w,_height-1);
    8. // etc ...
    9.  
    If you want to specify a border width, you can add a loop before the setPixel, something like
    Code (csharp):
    1.  
    2. for (int h=0;i<_height<h++)
    3.      for (int=0;i<borderWidth;i++)
    4.            SetPixel(i,h);
    5.  
    You can improve it later by creating a dedicated SetPixelBorder function.


    Ups didn't saw that's what you already done. Creating a function to wrap all the setPixel code will save you some lines.