Unity Texture缩放 合成 解压
图片缩放图像放大有许多算法,关键在于对未知像素使用何种插值算法。
[*]最邻近插值算法
原理图:
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; }
页:
[1]