Search Unity

  1. Unity 2019.1 is now released.
    Dismiss Notice

[Contribution] Texture2D blur in c#

Discussion in 'Scripting' started by fogman, Jun 10, 2013.

  1. fogman

    fogman

    Joined:
    Jan 21, 2009
    Posts:
    71
    Based on this one from Eric Willis:
    http://notes.ericwillis.com/2009/10/blur-an-image-with-csharp/

    Code (csharp):
    1.  
    2.     private Texture2D Blur(Texture2D image, int blurSize)
    3.     {
    4.         Texture2D blurred = new Texture2D(image.width, image.height);
    5.      
    6.         // look at every pixel in the blur rectangle
    7.         for (int xx = 0; xx < image.width; xx++)
    8.         {
    9.             for (int yy = 0; yy < image.height; yy++)
    10.             {
    11.                 float avgR = 0, avgG = 0, avgB = 0, avgA = 0;
    12.                 int blurPixelCount = 0;
    13.      
    14.                 // average the color of the red, green and blue for each pixel in the
    15.                 // blur size while making sure you don't go outside the image bounds
    16.                 for (int x = xx; (x < xx + blurSize  x < image.width); x++)
    17.                 {
    18.                     for (int y = yy; (y < yy + blurSize  y < image.height); y++)
    19.                     {
    20.                         Color pixel = image.GetPixel(x, y);
    21.      
    22.                         avgR += pixel.r;
    23.                         avgG += pixel.g;
    24.                         avgB += pixel.b;
    25.                         avgA += pixel.a;
    26.      
    27.                         blurPixelCount++;
    28.                     }
    29.                 }
    30.      
    31.                 avgR = avgR / blurPixelCount;
    32.                 avgG = avgG / blurPixelCount;
    33.                 avgB = avgB / blurPixelCount;
    34.                 avgA = avgA / blurPixelCount;
    35.      
    36.                 // now that we know the average for the blur size, set each pixel to that color
    37.                 for (int x = xx; x < xx + blurSize  x < image.width; x++)
    38.                     for (int y = yy; y < yy + blurSize  y < image.height; y++)
    39.                         blurred.SetPixel(x, y, new Color(avgR, avgG, avgB, avgA));
    40.             }
    41.         }
    42.         blurred.Apply();
    43.         return blurred;
    44.     }
    45.  
     
  2. Steffan-Poulsen

    Steffan-Poulsen

    Joined:
    Dec 27, 2011
    Posts:
    123
    Thanks for this, it really helped me out!

    It was a bit slow for my liking, but I remembered stumbling across this page a few months ago, and thought I would give some optimisation a try.

    I've separated the blur into two passes, one horisontal and one vertical, as shown on the site. Furthermore I've made it blur in regards to pixels on all sides, and not just in front / on top. Oh, and I have converted your code to javascript.

    The best results i have had, in terms of getting a compromise between speed and quality, is by having a relatively low resolution texture and doing multiple blur iterations (2 iterations on a 128x128 texture), with a radius of 5.

    It's just a couple of hours work so far, and I'm sure it can be further improved upon! Thanks again :)


    Code (csharp):
    1. private var avgR : float = 0;
    2.     private var avgG : float = 0;
    3.     private var avgB : float = 0;
    4.     private var avgA : float = 0;
    5.     private var blurPixelCount = 0;
    6.  
    7.     function FastBlur(image : Texture2D, radius : int, iterations : int) : Texture2D {
    8.         var tex : Texture2D = image;
    9.         for (var i = 0; i < iterations; i++) {
    10.             tex = BlurImage(tex, radius, true);
    11.             tex = BlurImage(tex, radius, false);
    12.         }
    13.         return tex;
    14.     }
    15.  
    16.     function BlurImage(image : Texture2D, blurSize : int, horizontal : boolean) : Texture2D {
    17.         var blurred : Texture2D = new Texture2D(image.width, image.height);
    18.         var _W : int = image.width;
    19.         var _H : int = image.height;
    20.         var xx : int; var yy : int; var x : int; var y : int;
    21.  
    22.         if (horizontal) {
    23.         // Horizontal
    24.         for (yy = 0; yy < _H; yy++) {
    25.             for (xx = 0; xx < _W; xx++) {
    26.                 ResetPixel();
    27.                 //Right side of pixel
    28.                 for (x = xx; (x < xx + blurSize  x < _W); x++) {
    29.                     AddPixel(image.GetPixel(x, yy));
    30.                 }
    31.                 //Left side of pixel
    32.                 for (x = xx; (x > xx - blurSize  x > 0); x--) {
    33.                     AddPixel(image.GetPixel(x, yy));
    34.                 }
    35.                 CalcPixel();
    36.                 for (x = xx; x < xx + blurSize  x < _W; x++) {
    37.                     blurred.SetPixel(x, yy, new Color(avgR, avgG, avgB, 1.0));
    38.                 }
    39.             }
    40.         }
    41.         }
    42.         else {
    43.         // Vertical
    44.         for (xx = 0; xx < _W; xx++) {
    45.             for (yy = 0; yy < _H; yy++) {
    46.                 ResetPixel();
    47.                 //Over pixel
    48.                 for (y = yy; (y < yy + blurSize  y < _H); y++) {
    49.                     AddPixel(image.GetPixel(xx, y));
    50.                 }
    51.                 //Under pixel
    52.                 for (y = yy; (y > yy - blurSize  y > 0); y--) {
    53.                     AddPixel(image.GetPixel(xx, y));
    54.                 }
    55.                 CalcPixel();
    56.                 for (y = yy; y < yy + blurSize  y < _H; y++) {
    57.                     blurred.SetPixel(xx, y, new Color(avgR, avgG, avgB, 1.0));
    58.                 }
    59.             }
    60.         }
    61.         }
    62.  
    63.         blurred.Apply();
    64.         return blurred;
    65.     }
    66.  
    67.     function AddPixel(pixel : Color) {
    68.         avgR += pixel.r;
    69.         avgG += pixel.g;
    70.         avgB += pixel.b;
    71.         blurPixelCount++;
    72.     }
    73.  
    74.     function ResetPixel() {
    75.         avgR = 0.0;
    76.         avgG = 0.0;
    77.         avgB = 0.0;
    78.         blurPixelCount = 0;
    79.     }
    80.  
    81.     function CalcPixel() {
    82.         avgR = avgR / blurPixelCount;
    83.         avgG = avgG / blurPixelCount;
    84.         avgB = avgB / blurPixelCount;
    85.     }
     
  3. Elecman

    Elecman

    Joined:
    May 5, 2011
    Posts:
    1,311
    I tested Fogman's code but it shifts a solid circle as an input texture to the lower left corner. The bigger the blurSize, the bigger the shift.

    The code Steffan Poulsen provides doesn't have the shift bug and it is faster to boot. I converted it back into C# as well :cool:

    Code (csharp):
    1.  
    2.  
    3. private float avgR = 0;
    4. private float avgG = 0;
    5. private float avgB = 0;
    6. private float avgA = 0;
    7. private float blurPixelCount = 0;
    8.  
    9. Texture2D FastBlur(Texture2D image, int radius, int iterations){
    10.  
    11.     Texture2D tex = image;
    12.  
    13.     for (var i = 0; i < iterations; i++) {
    14.  
    15.         tex = BlurImage(tex, radius, true);
    16.         tex = BlurImage(tex, radius, false);
    17.     }
    18.  
    19.     return tex;
    20. }
    21.  
    22. Texture2D BlurImage(Texture2D image, int blurSize, bool horizontal){
    23.  
    24.     Texture2D blurred = new Texture2D(image.width, image.height);
    25.     int _W = image.width;
    26.     int _H = image.height;
    27.     int xx, yy, x, y;
    28.  
    29.     if (horizontal) {
    30.  
    31.         for (yy = 0; yy < _H; yy++) {
    32.  
    33.             for (xx = 0; xx < _W; xx++) {
    34.  
    35.                 ResetPixel();
    36.  
    37.                 //Right side of pixel
    38.                 for (x = xx; (x < xx + blurSize  x < _W); x++) {
    39.  
    40.                     AddPixel(image.GetPixel(x, yy));
    41.                 }
    42.  
    43.                 //Left side of pixel
    44.                 for (x = xx; (x > xx - blurSize  x > 0); x--) {
    45.  
    46.                     AddPixel(image.GetPixel(x, yy));
    47.                 }
    48.  
    49.                 CalcPixel();
    50.  
    51.                 for (x = xx; x < xx + blurSize  x < _W; x++) {
    52.  
    53.                     blurred.SetPixel(x, yy, new Color(avgR, avgG, avgB, 1.0f));
    54.                 }
    55.             }
    56.         }
    57.     }
    58.  
    59.     else {
    60.  
    61.         for (xx = 0; xx < _W; xx++) {
    62.  
    63.             for (yy = 0; yy < _H; yy++) {
    64.  
    65.                 ResetPixel();
    66.  
    67.                 //Over pixel
    68.                 for (y = yy; (y < yy + blurSize  y < _H); y++) {
    69.  
    70.                     AddPixel(image.GetPixel(xx, y));
    71.                 }
    72.  
    73.                 //Under pixel
    74.                 for (y = yy; (y > yy - blurSize  y > 0); y--) {
    75.  
    76.                     AddPixel(image.GetPixel(xx, y));
    77.                 }
    78.  
    79.                 CalcPixel();
    80.  
    81.                 for (y = yy; y < yy + blurSize  y < _H; y++) {
    82.  
    83.                     blurred.SetPixel(xx, y, new Color(avgR, avgG, avgB, 1.0f));
    84.                 }
    85.             }
    86.         }
    87.     }
    88.  
    89.     blurred.Apply();
    90.     return blurred;
    91. }
    92.  
    93. void AddPixel(Color pixel) {
    94.  
    95.     avgR += pixel.r;
    96.     avgG += pixel.g;
    97.     avgB += pixel.b;
    98.     blurPixelCount++;
    99. }
    100.  
    101. void ResetPixel() {
    102.  
    103.     avgR = 0.0f;
    104.     avgG = 0.0f;
    105.     avgB = 0.0f;
    106.     blurPixelCount = 0;
    107. }
    108.  
    109. void CalcPixel() {
    110.  
    111.     avgR = avgR / blurPixelCount;
    112.     avgG = avgG / blurPixelCount;
    113.     avgB = avgB / blurPixelCount;
    114. }
    115.  
     
  4. chelnok

    chelnok

    Joined:
    Jul 2, 2012
    Posts:
    673
    Small modification for @Elecman 's version:

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class Blur : MonoBehaviour {
    5.    
    6.     private float avgR = 0;
    7.     private float avgG = 0;
    8.     private float avgB = 0;
    9.     private float avgA = 0;
    10.     private float blurPixelCount = 0;
    11.    
    12.     public int radius =2;
    13.     public int iterations =2;
    14.    
    15.     private Texture2D tex;
    16.    
    17.     // Use this for initialization
    18.     void Start () {
    19.         tex = renderer.material.mainTexture as Texture2D;
    20.        
    21.     }
    22.    
    23.     // Update is called once per frame
    24.     void Update () {
    25.        
    26.         if (Input.GetKeyDown(KeyCode.Space))
    27.             renderer.material.mainTexture = FastBlur( tex, radius, iterations);
    28.     }
    29.    
    30.    
    31.     Texture2D FastBlur(Texture2D image, int radius, int iterations){
    32.         Texture2D tex = image;
    33.        
    34.         for (var i = 0; i < iterations; i++) {
    35.            
    36.             tex = BlurImage(tex, radius, true);
    37.             tex = BlurImage(tex, radius, false);
    38.            
    39.         }
    40.        
    41.         return tex;
    42.     }
    43.    
    44.    
    45.    
    46.     Texture2D BlurImage(Texture2D image, int blurSize, bool horizontal){
    47.        
    48.         Texture2D blurred = new Texture2D(image.width, image.height);
    49.         int _W = image.width;
    50.         int _H = image.height;
    51.         int xx, yy, x, y;
    52.        
    53.         if (horizontal) {
    54.             for (yy = 0; yy < _H; yy++) {
    55.                 for (xx = 0; xx < _W; xx++) {
    56.                     ResetPixel();
    57.                    
    58.                     //Right side of pixel
    59.                    
    60.                     for (x = xx; (x < xx + blurSize && x < _W); x++) {
    61.                         AddPixel(image.GetPixel(x, yy));
    62.                     }
    63.                    
    64.                     //Left side of pixel
    65.                    
    66.                     for (x = xx; (x > xx - blurSize && x > 0); x--) {
    67.                         AddPixel(image.GetPixel(x, yy));
    68.                        
    69.                     }
    70.                    
    71.                    
    72.                     CalcPixel();
    73.                    
    74.                     for (x = xx; x < xx + blurSize && x < _W; x++) {
    75.                         blurred.SetPixel(x, yy, new Color(avgR, avgG, avgB, 1.0f));
    76.                        
    77.                     }
    78.                 }
    79.             }
    80.         }
    81.        
    82.         else {
    83.             for (xx = 0; xx < _W; xx++) {
    84.                 for (yy = 0; yy < _H; yy++) {
    85.                     ResetPixel();
    86.                    
    87.                     //Over pixel
    88.                    
    89.                     for (y = yy; (y < yy + blurSize && y < _H); y++) {
    90.                         AddPixel(image.GetPixel(xx, y));
    91.                     }
    92.                     //Under pixel
    93.                    
    94.                     for (y = yy; (y > yy - blurSize && y > 0); y--) {
    95.                         AddPixel(image.GetPixel(xx, y));
    96.                     }
    97.                     CalcPixel();
    98.                     for (y = yy; y < yy + blurSize && y < _H; y++) {
    99.                         blurred.SetPixel(xx, y, new Color(avgR, avgG, avgB, 1.0f));
    100.                        
    101.                     }
    102.                 }
    103.             }
    104.         }
    105.        
    106.         blurred.Apply();
    107.         return blurred;
    108.     }
    109.     void AddPixel(Color pixel) {
    110.         avgR += pixel.r;
    111.         avgG += pixel.g;
    112.         avgB += pixel.b;
    113.         blurPixelCount++;
    114.     }
    115.    
    116.     void ResetPixel() {
    117.         avgR = 0.0f;
    118.         avgG = 0.0f;
    119.         avgB = 0.0f;
    120.         blurPixelCount = 0;
    121.     }
    122.    
    123.     void CalcPixel() {
    124.         avgR = avgR / blurPixelCount;
    125.         avgG = avgG / blurPixelCount;
    126.         avgB = avgB / blurPixelCount;
    127.     }
    128. }
    Add script and texture to quad or plane for example. Texture needs to be marked as read / write. Hit play and press space to blur.
     
    Last edited: Nov 14, 2014
  5. cherub

    cherub

    Joined:
    Apr 26, 2006
    Posts:
    487
    am i doing something wrong? all of these script fail at the first use of the variable x.
     
  6. chelnok

    chelnok

    Joined:
    Jul 2, 2012
    Posts:
    673
    Looks like new forum software has erased && symbols (double ampersand) from code. I edited my post, but if you wish to use other versions, you need to fix all this kind of parts from the code:

    Code (CSharp):
    1.  //Left side of pixel
    2.                 for (x = xx; (x > xx - blurSize  x > 0); x--) {
    TO:

    Code (CSharp):
    1.  //Left side of pixel
    2.                 for (x = xx; (x > xx - blurSize && x > 0); x--) {
     
  7. Cardinalby

    Cardinalby

    Joined:
    Oct 9, 2014
    Posts:
    1
    My optimized version

    Code (CSharp):
    1. class LinearBlur
    2.     {
    3.         private float _rSum = 0;
    4.         private float _gSum = 0;
    5.         private float _bSum = 0;
    6.  
    7.         private Texture2D _sourceImage;
    8.         private int _sourceWidth;
    9.         private int _sourceHeight;
    10.         private int _windowSize;
    11.  
    12.         public Texture2D Blur(Texture2D image, int radius, int iterations)
    13.         {
    14.             _windowSize = radius * 2 + 1;
    15.             _sourceWidth = image.width;
    16.             _sourceHeight = image.height;
    17.  
    18.             var tex = image;
    19.  
    20.             for (var i = 0; i < iterations; i++)
    21.             {
    22.                 tex = OneDimensialBlur(tex, radius, true);
    23.                 tex = OneDimensialBlur(tex, radius, false);
    24.             }
    25.  
    26.             return tex;
    27.         }
    28.  
    29.         private Texture2D OneDimensialBlur(Texture2D image, int radius, bool horizontal)
    30.         {
    31.             _sourceImage = image;
    32.  
    33.             var blurred = new Texture2D(image.width, image.height, image.format, false);
    34.  
    35.             if (horizontal)
    36.             {
    37.                 for (int imgY = 0; imgY < _sourceHeight; ++imgY)
    38.                 {
    39.                     ResetSum();
    40.  
    41.                     for (int imgX = 0; imgX < _sourceWidth; imgX++)
    42.                     {
    43.                         if (imgX == 0)
    44.                             for (int x = radius * -1; x <= radius; ++x)
    45.                                 AddPixel(GetPixelWithXCheck(x, imgY));
    46.                         else
    47.                         {
    48.                             var toExclude = GetPixelWithXCheck(imgX - radius - 1, imgY);
    49.                             var toInclude = GetPixelWithXCheck(imgX + radius, imgY);
    50.  
    51.                             SubstPixel(toExclude);
    52.                             AddPixel(toInclude);
    53.                         }
    54.  
    55.                         blurred.SetPixel(imgX, imgY, CalcPixelFromSum());
    56.                     }
    57.                 }
    58.             }
    59.  
    60.             else
    61.             {
    62.                 for (int imgX = 0; imgX < _sourceWidth; imgX++)
    63.                 {
    64.                     ResetSum();
    65.  
    66.                     for (int imgY = 0; imgY < _sourceHeight; ++imgY)
    67.                     {
    68.                         if (imgY == 0)
    69.                             for (int y = radius * -1; y <= radius; ++y)
    70.                                 AddPixel(GetPixelWithYCheck(imgX, y));
    71.                         else
    72.                         {
    73.                             var toExclude = GetPixelWithYCheck(imgX, imgY - radius - 1);
    74.                             var toInclude = GetPixelWithYCheck(imgX, imgY + radius);
    75.  
    76.                             SubstPixel(toExclude);
    77.                             AddPixel(toInclude);
    78.                         }
    79.  
    80.                         blurred.SetPixel(imgX, imgY, CalcPixelFromSum());
    81.                     }
    82.                 }
    83.             }
    84.  
    85.             blurred.Apply();
    86.             return blurred;
    87.         }
    88.  
    89.         private Color GetPixelWithXCheck(int x, int y)
    90.         {
    91.             if (x <= 0) return _sourceImage.GetPixel(0, y);
    92.             if (x >= _sourceWidth) return _sourceImage.GetPixel(_sourceWidth - 1, y);
    93.             return _sourceImage.GetPixel(x, y);
    94.         }
    95.  
    96.         private Color GetPixelWithYCheck(int x, int y)
    97.         {
    98.             if (y <= 0) return _sourceImage.GetPixel(x, 0);
    99.             if (y >= _sourceHeight) return _sourceImage.GetPixel(x, _sourceHeight - 1);
    100.             return _sourceImage.GetPixel(x, y);
    101.         }
    102.  
    103.         private void AddPixel(Color pixel)
    104.         {
    105.             _rSum += pixel.r;
    106.             _gSum += pixel.g;
    107.             _bSum += pixel.b;
    108.         }
    109.  
    110.         private void SubstPixel(Color pixel)
    111.         {
    112.             _rSum -= pixel.r;
    113.             _gSum -= pixel.g;
    114.             _bSum -= pixel.b;
    115.         }
    116.  
    117.         private void ResetSum()
    118.         {
    119.             _rSum = 0.0f;
    120.             _gSum = 0.0f;
    121.             _bSum = 0.0f;
    122.         }
    123.  
    124.         Color CalcPixelFromSum()
    125.         {
    126.             return new Color(_rSum / _windowSize, _gSum / _windowSize, _bSum / _windowSize);
    127.         }
    128.     }
     
  8. Hiti3

    Hiti3

    Joined:
    Jul 16, 2015
    Posts:
    7
    Is it any better/ more optimized than Elecman's code?
     
  9. Hiti3

    Hiti3

    Joined:
    Jul 16, 2015
    Posts:
    7
    Could someone please please explain how to test this? I have an image and I want to test it out in my scene, however when I want to set the mainTexture of the image it says its Read only. Im googling hours and hours, sorry I'm new to Unity, but I would really need your help.
     
  10. Hiti3

    Hiti3

    Joined:
    Jul 16, 2015
    Posts:
    7
    Could you tell me how did you magate to test this? Im using Raw image but I dont know how much to set for radius to have the whole image blurred... And nothing is vissible :(
     
  11. DayFall

    DayFall

    Joined:
    Jan 2, 2015
    Posts:
    1
    My small benchmark test shown that "LinearBlur" by @Cardinalby much FASTER than @Elecman 's blur (about 8 to 10 times faster!). May be it does not so nice blur, but speed was more important for me.
    However, posted code isn`t fully optimized and has a memory leak.
    Code (CSharp):
    1. var blurred = new Texture2D(image.width, image.height, image.format, false);
    Creating new Texture2D in loop is not a good idea. GC won`t get them, even if it`s a local variable. Memory allocates every time and you can free it by calling DestroyImmediate(blurred); (this is the only way AFAIK).
    So I`d suggest to make this class static and use 2 static textures for all purposes.
    Also we can avoid calling this every pass:
    Code (CSharp):
    1. blurred.Apply();
    and call it one time in the end.
     
  12. andrew-lukasik

    andrew-lukasik

    Joined:
    Jan 31, 2013
    Posts:
    119
    IJob + BurstCompiled

    Note: you can quite easily improve this job so it won't perform any conversions by getting rid of these pedestrian Color[] inputs/outputs completely and replacing them with just an input NativeArray of texture.GetRawTextureData<this texture-specific type>

    Code (CSharp):
    1. using Unity.Mathematics;
    2. using Unity.Collections;
    3.  
    4. [Unity.Burst.BurstCompile]
    5. struct LinearBlurJob : Unity.Jobs.IJob
    6. {
    7.     NativeArray<float4> source, blurred;//float4 is simd, Color isn't, hence in/out conversions (trading memory for speed here)
    8.     int width, height, boxSize, iterations, radius;
    9.     public ColorArrayJob ( UnityEngine.Color[] source , int width , int height , int radius , int iterations )
    10.     {
    11.         this.source = new NativeArray<float4>( source.Length , Allocator.TempJob , NativeArrayOptions.UninitializedMemory );
    12.         for( int i=source.Length-1 ; i!=-1 ; i-- )
    13.         {
    14.             var col = source[ i ];
    15.             this.source[ i ] = new float4{ x=col.r , y=col.g , z=col.b , w=col.a };
    16.         }
    17.         this.blurred = new NativeArray<float4>( this.source , Allocator.TempJob );
    18.         this.radius = radius;
    19.         this.boxSize = radius * 2 + 1;
    20.         this.width = width;
    21.         this.height = height;
    22.         this.iterations = iterations;
    23.     }
    24.     void Unity.Jobs.IJob.Execute ()
    25.     {
    26.         for( int iteration=0 ; iteration<iterations ; iteration++ )
    27.         {
    28.             // horizontal blur:
    29.             blurred.CopyTo( source );
    30.             for( int Y=0 ; Y<height ; ++Y )
    31.             {
    32.                 float4 sum = default(float4);
    33.                 {
    34.                     for( int x=-radius ; x<=radius ; ++x ) sum += GetValueSafe( source , x , Y );
    35.                     blurred[ To1dIndex(0,Y) ] = sum/boxSize;
    36.                 }
    37.                 for( int X=1 ; X<width ; X++ )
    38.                 {
    39.                     sum -= GetValueSafe( source , X-radius-1 , Y );
    40.                     sum += GetValueSafe( source , X + radius , Y );
    41.                     blurred[ To1dIndex(X,Y) ] = sum/boxSize;
    42.                 }
    43.             }
    44.             // vertical blur:
    45.             blurred.CopyTo( source );
    46.             for( int X=0 ; X<width ; X++ )
    47.             {
    48.                 float4 sum = default(float4);
    49.                 {
    50.                     for( int y=-radius ; y<=radius ; ++y ) sum += GetValueSafe( source , X , y );
    51.                     blurred[ To1dIndex(X,0) ] = sum/boxSize;
    52.                 }
    53.                 for( int Y=1 ; Y<height ; ++Y )
    54.                 {
    55.                     sum -= GetValueSafe( source , X , Y-radius-1 );
    56.                     sum += GetValueSafe( source , X , Y+radius );
    57.                     blurred[ To1dIndex(X,Y) ] = sum/boxSize;
    58.                 }
    59.             }
    60.         }
    61.     }
    62.     float4 GetValueSafe ( NativeArray<float4> array , int x , int y ) => array[ To1dIndex( math.clamp( x , 0 , width-1 ) , math.clamp( y , 0 , height-1 ) ) ];
    63.     int To1dIndex ( int x , int y ) => y * width + x;
    64.     public UnityEngine.Color[] GetResultsAndClose ()
    65.     {
    66.         UnityEngine.Color[] results = new UnityEngine.Color[ blurred.Length ];
    67.         for( int i=blurred.Length-1 ; i!=-1 ; i-- )
    68.         {
    69.             var f4 = blurred[ i ];
    70.             results[ i ] = new UnityEngine.Color{ r=f4.x , g=f4.y , b=f4.z , a=f4.w };
    71.         }
    72.         source.Dispose();
    73.         blurred.Dispose();
    74.         return results;
    75.     }
    76. }
    77.  
     
    Last edited: Apr 4, 2019
  13. andrew-lukasik

    andrew-lukasik

    Joined:
    Jan 31, 2013
    Posts:
    119
    Here is an example of a mentioned improved IJob that blurs texture.GetRawTextureData<UInt16> (aka ushort) where texture format is R16 (16bit grayscale):
    NativeUInt16Job