美文网首页
Unity Texture缩放 合成 解压

Unity Texture缩放 合成 解压

作者: 忆中异 | 来源:发表于2022-05-27 17:03 被阅读0次

图片缩放

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

  • 最邻近插值算法
    原理图:
    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 Texture缩放 合成 解压

      本文链接:https://www.haomeiwen.com/subject/zvzmprtx.html