zoukankan      html  css  js  c++  java
  • Unity图片处理类,包括压缩、截屏和滤镜

    http://www.cnblogs.com/EndOfYear/p/4334952.html

    先上代码:
    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-1));
    ratioY = 1.0f / ((float)newHeight / (tex.height-1));
    }
    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 = 0;
    if (mutex == null) {
    mutex = new Mutex(false);
    }
    if (cores > 1)
    {
    int i = 0;
    ThreadData threadData;
    for (i = 0; i < cores-1; i++) {
    threadData = new ThreadData(slice * i, slice * (i + 1));
    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(1);
    }
    }
    else
    {
    ThreadData threadData = new ThreadData(0, 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+1) * w;
    var yw = y * w2;

    for (var x = 0; 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+1], xLerp),
    ColorLerpUnclamped(texColors[y2 + xFloor], texColors[y2 + xFloor+1], 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 = 0; 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(2, 2,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 (0, 0, 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, 0, 0);
    tex.Apply();
    // 把图片数据转换为byte数组
    if (size != default(Vector2))
    {
    ScaleBilinear(tex, (int)size.x, (int)size.y);
    }

    byte[] buffer = tex.EncodeToJPG (100);
    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 = 0; 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 * 1, 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 = 0; i < colors.Length; i++)
    {
    float val = (colors [i].r + colors [i].g + colors [i].b) / 3;
    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(0, 0, 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 / 2;
    int offsetY = size / 2;
    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 = 0; i < colors.Length; i++)
    {
    pixel = colors[i];
    colors[i] = new Color(1 - pixel.r, 1 - pixel.g, 1 - 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 = 1; x < tex.width - 1; x++)
    for (int y = 1; y < tex.height - 1; y++)
    {
    int k = UnityEngine.Random.Range(0, 123456);
    //像素块大小
    int dx = x + k % 19;
    int dy = y + k % 19;
    if (dx >= tex.width)
    dx = tex.width - 1;
    if (dy >= tex.height)
    dy = tex.height - 1;
    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 = { 1, 2, 1, 2, 4, 2, 1, 2, 1 };
    for (int x = 1; x < tex.width - 1; x++)
    for (int y = 1; y < tex.height - 1; y++)
    {
    float r = 0, g = 0, b = 0;
    int Index = 0;
    for (int col = -1; col <= 1; col++)
    for (int row = -1; row <= 1; 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 /= 16;
    g /= 16;
    b /= 16;
    //处理颜色值溢出
    r = r > 1 ? 1 : r;
    r = r < 0 ? 0 : r;
    g = g > 1 ? 1 : g;
    g = g < 0 ? 0 : g;
    b = b > 1 ? 1 : b;
    b = b < 0 ? 0 : b;
    t.SetPixel(x - 1, y - 1, 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 ={ -1, -1, -1, -1, 9, -1, -1, -1, -1 };
    for (int x = 1; x < tex.width - 1; x++)
    for (int y = 1; y < tex.height - 1; y++)
    {
    float r = 0, g = 0, b = 0;
    int index = 0;
    for (int col = -1; col <= 1; col++)
    for (int row = -1; row <= 1; 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 > 1 ? 1 : r;
    r = r < 0 ? 0 : r;
    g = g > 1 ? 1 : g;
    g = g < 0 ? 0 : g;
    b = b > 1 ? 1 : b;
    b = b < 0 ? 0 : b;
    t.SetPixel(x - 1, y - 1, 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 = 0; x < tex.width - 1; x++)
    {
    for (int y = 0; y < tex.height - 1; y++)
    {
    float r = 0, g = 0, b = 0;
    Color pixel1 = tex.GetPixel(x, y);
    Color pixel2 = tex.GetPixel(x + 1, y + 1);
    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 > 1)
    r = 1;
    if (r < 0)
    r = 0;
    if (g > 1)
    g = 1;
    if (g < 0)
    g = 0;
    if (b > 1)
    b = 1;
    if (b < 0)
    b = 0;
    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)等。

  • 相关阅读:
    java通过ST4使用模板字符串
    使用 docker创建redis实例并且连接
    Docker 认证成功后还是无法push构建好的镜像
    记录一次在openwrt中折腾docker
    全局模式、PAC模式、直连模式的区别
    Vue Router中调用this.$router.push() 时,location使用path无法传入params
    liunx之系统
    liunx之通配符&正则表达式
    liunx之基础
    liunx之find命令
  • 原文地址:https://www.cnblogs.com/alps/p/7791739.html
Copyright © 2011-2022 走看看