找回密码
 立即注册
查看: 316|回复: 0

Unity Texture缩放 合成 解压

[复制链接]
发表于 2022-5-27 16:58 | 显示全部楼层 |阅读模式
图片缩放


图像放大有许多算法,关键在于对未知像素使用何种插值算法。

  • 最邻近插值算法
    原理图:

    image.png


选取对应原图位置距离最近的点,当然,距离相等的点的选取,需要自定一些规则。
模块效应严重。

  • 双线性插值算法
    原理:
    0<x<1,0<y<1;
    f(x,y) = (1-x)(1-y)f(0,0)+x(1-y)f(1,0)+(1-x)yf(0,1)+xyf(1,1);
    在原图中找到所属位置对应边界的四个点,将距离作为权重,加权平均。
    加入了低通滤波器消除块效应,所以也会使原图受损。
  • 三线性卷积插值算法
    原理:

image

效果良好,但效率较低。

我运用的是双线性插值算法
/// <summary>        /// 图片缩放(双线性Bilinear算法,用Unity GetPixelBilinear 接口)        /// </summary>        /// <param name="source"></param>        /// <param name="targetWidth"></param>        /// <param name="targetHeight"></param>        /// <returns></returns>        public static Texture2D ScaleTexture(Texture2D source, int targetWidth, int targetHeight)        {            //needs to be ARGB32, RGBA32, RGB24, R8, Alpha8 or one of float formats            Texture2D result = new Texture2D(targetWidth, targetHeight, TextureFormat.ARGB32, false);            for (int i = 0; i < result.height; ++i)            {                for (int j = 0; j < result.width; ++j)                {                    Color newColor = source.GetPixelBilinear((float)j / (float)result.width, (float)i / (float)result.height);                    result.SetPixel(j, i, newColor);                }            }            result.Apply();            return result;        }        /// <summary>        /// 图片缩放(双线性Bilinear算法)        /// </summary>        /// <param name="source"></param>        /// <param name="targetWidth"></param>        /// <param name="targetHeight"></param>        /// <returns></returns>        Texture2D ScaleTextureBilinear(Texture2D source, int targetWidth, int targetHeight)        {            Vector2 scaleFactor = new Vector2(targetWidth / source.width, targetHeight / source.height);            Texture2D newTexture = new Texture2D(Mathf.CeilToInt(source.width * scaleFactor.x), Mathf.CeilToInt(source.height * scaleFactor.y));            float scaleW = 1.0f / scaleFactor.x;            float scaleH = 1.0f / scaleFactor.y;            int maxX = source.width - 1;            int maxY = source.height - 1;            for (int y = 0; y < newTexture.height; y++)            {                for (int x = 0; x < newTexture.width; x++)                {                    // Bilinear Interpolation                    float targetX = x * scaleW;                    float targetY = y * scaleH;                    int x1 = Mathf.Min(maxX, Mathf.FloorToInt(targetX));                    int y1 = Mathf.Min(maxY, Mathf.FloorToInt(targetY));                    int x2 = Mathf.Min(maxX, x1 + 1);                    int y2 = Mathf.Min(maxY, y1 + 1);                    float u = targetX - x1;                    float v = targetY - y1;                    float w1 = (1 - u) * (1 - v);                    float w2 = u * (1 - v);                    float w3 = (1 - u) * v;                    float w4 = u * v;                    Color color1 = source.GetPixel(x1, y1);                    Color color2 = source.GetPixel(x2, y1);                    Color color3 = source.GetPixel(x1, y2);                    Color color4 = source.GetPixel(x2, y2);                    Color color = new Color(Mathf.Clamp01(color1.r * w1 + color2.r * w2 + color3.r * w3 + color4.r * w4),                        Mathf.Clamp01(color1.g * w1 + color2.g * w2 + color3.g * w3 + color4.g * w4),                        Mathf.Clamp01(color1.b * w1 + color2.b * w2 + color3.b * w3 + color4.b * w4),                        Mathf.Clamp01(color1.a * w1 + color2.a * w2 + color3.a * w3 + color4.a * w4)                        );                    newTexture.SetPixel(x, y, color);                }            }            return newTexture;        }                                                                原图

image.png

                                                          放大两倍后效果

image.png

图片合成


小图像素绘制到大图上
/// <summary>        ///  图片合成        /// </summary>        /// <param name="BigTexture"></param>        /// <param name="SmallTexture"></param>        /// <param name="alpha">是否保留small图片通道</param>        /// <returns></returns>        public static Texture2D ComplexTwoTextures(Texture2D BigTexture, Texture2D SmallTexture,bool alpha = false)        {            /////needs to be ARGB32, RGBA32, RGB24, R8, Alpha8 or one of float formats            Texture2D tex = new Texture2D(BigTexture.width, BigTexture.height, TextureFormat.RGBA32, false);            tex.SetPixels(BigTexture.GetPixels());            int startWidth = BigTexture.width/2 - SmallTexture.height /2;            int startHeight = BigTexture.height / 2 - SmallTexture.height / 2;            if(alpha)                tex.SetPixels32(startWidth, startHeight, SmallTexture.width, SmallTexture.height, SmallTexture.GetPixels32());            else            {                for(int i = 0; i < SmallTexture.width; i++)                {                    for(int j = 0; j < SmallTexture.height; j++)                    {                        //Color color = SmallTexture.GetPixelBilinear((float)i /(float)SmallTexture.width,(float)j / (float)SmallTexture.height);                        Color color = SmallTexture.GetPixel(i,j);                        if (color.a == 0) continue;                        tex.SetPixel(i+startWidth, j+startHeight, color);                    }                }            }            tex.Apply();            return tex;        }图片解压

/// <summary>        /// 图片解压        /// </summary>        /// <param name="source"></param>        /// <returns></returns>        public static Texture2D DeCompress(Texture2D source)        {            RenderTexture renderTex = RenderTexture.GetTemporary(                        source.width,                        source.height,                        0,                        RenderTextureFormat.Default,                        RenderTextureReadWrite.Linear);            Graphics.Blit(source, renderTex);            RenderTexture previous = RenderTexture.active;            RenderTexture.active = renderTex;            Texture2D readableText = new Texture2D(source.width, source.height);            readableText.ReadPixels(new Rect(0, 0, renderTex.width, renderTex.height), 0, 0);            readableText.Apply();            RenderTexture.active = previous;            RenderTexture.ReleaseTemporary(renderTex);            return readableText;        }

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Unity开发者联盟 ( 粤ICP备20003399号 )

GMT+8, 2024-9-22 09:46 , Processed in 0.088620 second(s), 26 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表