Unity图片处理类,包括压缩、截屏和滤镜
阅读原文时间:2020年09月21日阅读:4

先上代码:
1 using System.Threading;
using UnityEngine;
using System.IO;
using System.Collections;

public class TextureUtility
{
public class ThreadData
{
public int start;
public int end;
public ThreadData (int s, int e) {
start = s;
end = e;
}
}

 private static Color\[\] texColors;  
 private static Color\[\] newColors;  
 private static int w;  
 private static float ratioX;  
 private static float ratioY;  
 private static int w2;  
 private static int finishCount;  
 private static Mutex mutex;

 public static void ScalePoint (Texture2D tex, int newWidth, int newHeight)  
 {  
     ThreadedScale (tex, newWidth, newHeight, false);  
 }

 public static void ScaleBilinear (Texture2D tex, int newWidth, int newHeight)  
 {  
     ThreadedScale (tex, newWidth, newHeight, true);  
 }

 private static void ThreadedScale (Texture2D tex, int newWidth, int newHeight, bool useBilinear)  
 {  
     texColors = tex.GetPixels();  
     newColors = new Color\[newWidth \* newHeight\];  
     if (useBilinear)  
     {  
         ratioX = 1.0f / ((float)newWidth / (tex.width-));  
         ratioY = 1.0f / ((float)newHeight / (tex.height-));  
     }  
     else {  
         ratioX = ((float)tex.width) / newWidth;  
         ratioY = ((float)tex.height) / newHeight;  
     }  
     w = tex.width;  
     w2 = newWidth;  
     var cores = Mathf.Min(SystemInfo.processorCount, newHeight);  
     var slice = newHeight/cores;

     finishCount = ;  
     if (mutex == null) {  
         mutex = new Mutex(false);  
     }  
     if (cores > )  
     {  
         int i = ;  
         ThreadData threadData;  
         for (i = ; i < cores-; i++) {  
             threadData = new ThreadData(slice \* i, slice \* (i + ));  
             ParameterizedThreadStart ts = useBilinear ? new ParameterizedThreadStart(BilinearScale) : new ParameterizedThreadStart(PointScale);  
             Thread thread = new Thread(ts);  
             thread.Start(threadData);  
         }  
         threadData = new ThreadData(slice\*i, newHeight);  
         if (useBilinear)  
         {  
             BilinearScale(threadData);  
         }  
         else  
         {  
             PointScale(threadData);  
         }  
         while (finishCount < cores)  
         {  
             Thread.Sleep();  
         }  
     }  
     else  
     {  
         ThreadData threadData = new ThreadData(, newHeight);  
         if (useBilinear)  
         {  
             BilinearScale(threadData);  
         }  
         else  
         {  
             PointScale(threadData);  
         }  
     }

     tex.Resize(newWidth, newHeight);  
     tex.SetPixels(newColors);  
     tex.Apply();  
 }

 public static void BilinearScale (System.Object obj)  
 {  
     ThreadData threadData = (ThreadData) obj;  
     for (var y = threadData.start; y < threadData.end; y++)  
     {  
         int yFloor = (int)Mathf.Floor(y \* ratioY);  
         var y1 = yFloor \* w;  
         var y2 = (yFloor+) \* w;  
         var yw = y \* w2;

         for (var x = ; x < w2; x++) {  
             int xFloor = (int)Mathf.Floor(x \* ratioX);  
             var xLerp = x \* ratioX-xFloor;  
             newColors\[yw + x\] = ColorLerpUnclamped(ColorLerpUnclamped(texColors\[y1 + xFloor\], texColors\[y1 + xFloor+\], xLerp),  
                                                    ColorLerpUnclamped(texColors\[y2 + xFloor\], texColors\[y2 + xFloor+\], xLerp),  
                                                    y\*ratioY-yFloor);  
         }  
     }

     mutex.WaitOne();  
     finishCount++;  
     mutex.ReleaseMutex();  
 }

 public static void PointScale (System.Object obj)  
 {  
     ThreadData threadData = (ThreadData) obj;  
     for (var y = threadData.start; y < threadData.end; y++)  
     {  
         var thisY = (int)(ratioY \* y) \* w;  
         var yw = y \* w2;  
         for (var x = ; x < w2; x++) {  
             newColors\[yw + x\] = texColors\[(int)(thisY + ratioX\*x)\];  
         }  
     }

     mutex.WaitOne();  
     finishCount++;  
     mutex.ReleaseMutex();  
 }

 private static Color ColorLerpUnclamped (Color c1, Color c2, float value)  
 {  
     return new Color (c1.r + (c2.r - c1.r)\*value,  
                       c1.g + (c2.g - c1.g)\*value,  
                       c1.b + (c2.b - c1.b)\*value,  
                       c1.a + (c2.a - c1.a)\*value);  
 }

 public static Texture2D LoadTexture(string filePath) {  
     Texture2D tex = null;  
     byte\[\] fileData;

     if (File.Exists(filePath))     {  
         fileData = File.ReadAllBytes(filePath);  
         tex = new Texture2D(, ,TextureFormat.ARGB32,false);  
         tex.LoadImage(fileData);  
     }  
     return tex;  
 }

 // Save ScreenShot

 public static void SaveScreenShotAsync(string path, Vector2 size)  
 {  
     SWMain.sharedSWMain.StartCoroutine(TextureUtility.SaveScreenShot(path, size));  
 }

 public static void SaveScreenShotAsync(string path, Rect rect, Vector2 size)  
 {  
     SWMain.sharedSWMain.StartCoroutine(TextureUtility.SaveScreenShot(path, rect, size));  
 }

 public static IEnumerator SaveScreenShot(string path, Vector2 size)  
 {  
     Rect rect = new Rect (, , Screen.width, Screen.height);  
     yield return SWMain.sharedSWMain.StartCoroutine(TextureUtility.SaveScreenShot(path,rect, size));  
 }

 public static IEnumerator SaveScreenShot(string path, Rect rect, Vector2 size = default(Vector2))  
 {  
     // We should only read the screen bufferafter rendering is complete  
     yield return new WaitForEndOfFrame();  
     // 要保存图片的大小  
     Texture2D tex = new Texture2D ((int)rect.width, (int)rect.height, TextureFormat.RGB24, false);  
     // 截取的区域  
     tex.ReadPixels(rect, , );  
     tex.Apply();  
     // 把图片数据转换为byte数组  
     if (size != default(Vector2))  
     {  
         ScaleBilinear(tex, (int)size.x, (int)size.y);  
     }

     byte\[\] buffer = tex.EncodeToJPG ();  
     Object.Destroy(tex);  
     // 然后保存为图片  
     File.WriteAllBytes(path, buffer);  
 }

 public static Texture2D Copy(Texture2D tex)  
 {  
     return new Texture2D(tex.width, tex.height, tex.format, false);  
 }

 /// <summary>  
 /// Applies sepia effect to the texture.  
 /// </summary>  
 /// <param name="tex"> Texture to process.</param>  
 public static Texture2D SetSepia(Texture2D tex)  
 {  
     Texture2D t = Copy(tex);  
     Color\[\] colors = tex.GetPixels();

     for (int i = ; i < colors.Length; i++)  
     {  
         float alpha = colors\[i\].a;  
         float grayScale = ((colors\[i\].r \* .299f) + (colors\[i\].g \* .587f) + (colors\[i\].b \* .114f));  
         Color c = new Color(grayScale, grayScale, grayScale);  
         colors\[i\] = new Color(c.r \* , c.g \* 0.95f, c.b \* 0.82f, alpha);  
     }  
     t.SetPixels(colors);  
     t.Apply();  
     return t;  
 }

 /// <summary>  
 /// Applies grayscale effect to the texture and changes colors to grayscale.  
 /// </summary>  
 /// <param name="tex"> Texture to process.</param>  
 public static Texture2D SetGrayscale(Texture2D tex)  
 {  
     Texture2D t = Copy(tex);

     Color\[\] colors = tex.GetPixels();  
     for (int i = ; i < colors.Length; i++)  
     {  
         float val = (colors \[i\].r + colors \[i\].g + colors \[i\].b) / ;  
         colors \[i\] = new Color(val, val, val);  
     }  
     t.SetPixels(colors);  
     t.Apply();  
     return t;  
 }

 /// <summary>  
 /// Pixelates the texture.  
 /// </summary>  
 /// <param name="tex"> Texture to process.</param>  
 /// <param name="size"> Size of the pixel.</param>  
 public static Texture2D SetPixelate(Texture2D tex, int size)  
 {  
     Texture2D t = Copy(tex);  
     Rect rectangle = new Rect(, , tex.width, tex.height);  
     for (int xx = (int)rectangle.x; xx < rectangle.x + rectangle.width && xx < tex.width; xx += size)  
     {  
         for (int yy = (int)rectangle.y; yy < rectangle.y + rectangle.height && yy < tex.height; yy += size)  
         {  
             int offsetX = size / ;  
             int offsetY = size / ;  
             while (xx + offsetX >= tex.width) offsetX--;  
             while (yy + offsetY >= tex.height) offsetY--;  
             Color pixel = tex.GetPixel(xx + offsetX, yy + offsetY);  
             for (int x = xx; x < xx + size && x < tex.width; x++)  
                 for (int y = yy; y < yy + size && y < tex.height; y++)  
                     t.SetPixel(x, y, pixel);  
         }  
     }

     t.Apply();  
     return t;  
 }

 /// <summary>  
 /// Inverts colors of the texture.  
 /// </summary>  
 /// <param name="tex"> Texture to process.</param>  
 public static Texture2D SetNegative(Texture2D tex)  
 {  
     Texture2D t = Copy(tex);  
     Color\[\] colors = tex.GetPixels();  
     Color pixel;

     for (int i = ; i < colors.Length; i++)  
     {  
         pixel = colors\[i\];  
         colors\[i\] = new Color( - pixel.r,  - pixel.g,  - pixel.b);  
     }  
     t.SetPixels(colors);  
     t.Apply();  
     return t;  
 }

 /// <summary>  
 /// Sets the foggy effect.雾化效果  
 /// </summary>  
 /// <returns>texture processed.</returns>  
 /// <param name="tex">texture to process.</param>  
 public static Texture2D SetFoggy(Texture2D tex)  
 {  
     Texture2D t = Copy(tex);  
     Color pixel;

     for (int x = ; x < tex.width - ; x++)  
         for (int y = ; y < tex.height - ; y++)  
     {  
         int k = UnityEngine.Random.Range(, );  
         //像素块大小  
         int dx = x + k % ;  
         int dy = y + k % ;  
         if (dx >= tex.width)  
             dx = tex.width - ;  
         if (dy >= tex.height)  
             dy = tex.height - ;  
         pixel = tex.GetPixel(dx, dy);  
         t.SetPixel(x, y, pixel);  
     }

     t.Apply();

     return t;  
 }

 /// <summary>  
 /// Sets the soft effect.柔化效果  
 /// </summary>  
 /// <returns>texture processed.</returns>  
 /// <param name="tex">texture to process.</param>  
 public static Texture2D SetSoft(Texture2D tex)  
 {  
     Texture2D t = Copy(tex);  
     int\[\] Gauss = { , , , , , , , ,  };  
     for (int x = ; x < tex.width - ; x++)  
         for (int y = ; y < tex.height - ; y++)  
     {  
         float r = , g = , b = ;  
         int Index = ;  
         for (int col = -; col <= ; col++)  
             for (int row = -; row <= ; row++)  
         {  
             Color pixel = tex.GetPixel(x + row, y + col);  
             r += pixel.r \* Gauss\[Index\];  
             g += pixel.g \* Gauss\[Index\];  
             b += pixel.b \* Gauss\[Index\];  
             Index++;  
         }  
         r /= ;  
         g /= ;  
         b /= ;  
         //处理颜色值溢出  
         r = r >  ?  : r;  
         r = r <  ?  : r;  
         g = g >  ?  : g;  
         g = g <  ?  : g;  
         b = b >  ?  : b;  
         b = b <  ?  : b;  
         t.SetPixel(x - , y - , new Color(r, g, b));  
     }

     t.Apply();

     return t;  
 }

 /// <summary>  
 /// Sets the sharp.锐化效果  
 /// </summary>  
 /// <returns>The sharp.</returns>  
 /// <param name="tex">Tex.</param>  
 public static Texture2D SetSharp(Texture2D tex)  
 {  
     Texture2D t = Copy(tex);  
     Color pixel;  
     //拉普拉斯模板  
     int\[\] Laplacian ={ -, -, -, -, , -, -, -, - };  
     for (int x = ; x < tex.width - ; x++)  
         for (int y = ; y < tex.height - ; y++)  
     {  
         float r = , g = , b = ;  
         int index = ;  
         for (int col = -; col <= ; col++)  
             for (int row = -; row <= ; row++)  
         {  
             pixel = tex.GetPixel(x + row, y + col); r += pixel.r \* Laplacian\[index\];  
             g += pixel.g \* Laplacian\[index\];  
             b += pixel.b \* Laplacian\[index\];  
             index++;  
         }  
         //处理颜色值溢出  
         r = r >  ?  : r;  
         r = r <  ?  : r;  
         g = g >  ?  : g;  
         g = g <  ?  : g;  
         b = b >  ?  : b;  
         b = b <  ?  : b;  
         t.SetPixel(x - , y - , new Color(r, g, b));  
     }

     t.Apply();  
     return t;  
 }

 /// <summary>  
 /// Sets the relief.浮雕效果  
 /// </summary>  
 /// <returns>The relief.</returns>  
 /// <param name="tex">Tex.</param>  
 public static Texture2D SetRelief(Texture2D tex)  
 {  
     Texture2D t = Copy(tex);

     for (int x = ; x < tex.width - ; x++)  
     {  
         for (int y = ; y < tex.height - ; y++)  
         {  
             float r = , g = , b = ;  
             Color pixel1 = tex.GetPixel(x, y);  
             Color pixel2 = tex.GetPixel(x + , y + );  
             r = Mathf.Abs(pixel1.r - pixel2.r + 0.5f);  
             g = Mathf.Abs(pixel1.g - pixel2.g + 0.5f);  
             b = Mathf.Abs(pixel1.b - pixel2.b + 0.5f);  
             if (r > )  
                 r = ;  
             if (r < )  
                 r = ;  
             if (g > )  
                 g = ;  
             if (g < )  
                 g = ;  
             if (b > )  
                 b = ;  
             if (b < )  
                 b = ;  
             t.SetPixel(x, y, new Color(r, g, b));  
         }  
     }

     t.Apply();  
     return t;  
 }

}
如何调用:
1. 压缩图片:
  TextureUtility.ScalePoint(Texture2D tex, int newWidth, int newHeight),第一个参数是要传入的Texture2D, 第二个参数是新的图片的宽度,第三个参数则是新的图片的高度。也可以调用TextureUtility.ScaleBilinear(Texture2D tex, int newWidth, int newHeight)。
2. 截屏:
yield return StartCoroutine(TextureUtility.SaveScreenShot(string path, Vector2 size, Vector2 size = default(Vector2)))
或者调用异步方法TextureUtility.SaveScreenShotAsync(string path, Rect rect, Vector2 size)
3. 图片滤镜:
如灰阶滤镜:TextureUtility.SetGrayscale(Texture2D tex);
底片滤镜:TextureUtility.SetNegative(Texture2D tex)等。

手机扫一扫

移动阅读更方便

阿里云服务器
腾讯云服务器
七牛云服务器

你可能感兴趣的文章