前天朋友遇到一個這樣的需求,而且比較棘手讓我幫忙解決。需求就是棋牌類的游戲,玩家的個人資料中包括自己的頭像而且可以瀏覽相冊中的圖片或者使用相機拍照設置。關於這個問題我也查閱一些資料,由於涉及安卓部分知識,首先要了解Unity和安卓是如何通信的。
首先看到的是雨松老師的博客:http://www.xuanyusong.com/archives/1480咱們可以一起參考下這篇博客。好了,廢話就不多說了,夜已深,開始擼代碼吧!
1 新建空的工程
2,頭像顯示當然要用圖片了,就用UGUI的RawImage吧。
3,准備工作基本上結束了,接下來就是完成瀏覽相冊和拍照上傳了。這部分就不詳細介紹了網上有很多教程,借助Eclipse完成瀏覽相冊和拍照的邏輯,導出jar包在Unity中調用即可。插件已經導出,稍后會把工程共享給大家!
接下來該調用瀏覽相冊和拍照的功能了,簡單的測試,就這樣吧!
void OnGUI() { if (GUI.Button(new Rect(10, 10, 100, 100), "Take Photo")) { OpenCamera(); } if (GUI.Button(new Rect(220, 10, 100, 100), "Photo view")) { OpenPick(); } if (Input.GetKeyDown(KeyCode.Escape) || Input.GetKeyDown(KeyCode.Home)) { Application.Quit();
} }
4,既然是圓角頭像,那么還要處理圓角了。首先想到的是Shader做個裁剪即可。
是不是很神奇,上一秒還是方的哦!
5,接下來開始測試了,要打包真機測試的,請稍后打包中,,,,
6,哇咔咔,接下來要真機測試了。
對了,上面日志顯示兩個圖片字節數值而且相差很大的,你看到的是對的。由於要考慮網絡傳輸,傳輸的數據包要盡可能的小,這樣才會節省流量和提高效率,第一個值是圖片真是的字節數,第二個數值表示壓縮后的圖片字節數:2119,除以1024也就是2.07kb。這個數據還是可以接受的。
接下來是壓縮的實現方法:
using UnityEngine; using UnityEngine.UI; using System.Collections; using System.Threading; public class TextureTools : MonoBehaviour { 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 Texture2D Point(Texture2D tex, int newWidth, int newHeight, bool flipH, bool flipV) { return ThreadedScale(tex, newWidth, newHeight, false, flipH, flipV); } public static Texture2D Bilinear(Texture2D tex, int newWidth, int newHeight, bool flipH, bool flipV) { return ThreadedScale(tex, newWidth, newHeight, true, flipH, flipV); } private static Texture2D ThreadedScale(Texture2D tex, int newWidth, int newHeight, bool useBilinear, bool flipH, bool flipV) { 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(); Texture2D orig = new Texture2D(tex.width, tex.height); if (flipV) { int xN = tex.width; int yN = tex.width; for (int i = 0; i < xN; i++) { for (int j = 0; j < yN; j++) { // tex.SetPixel(xN - i - 1, j, orig.GetPixel(i, j)); orig.SetPixel(i, yN - j - 1, tex.GetPixel(i, j)); } } orig.Apply(); } else if (flipH) { int xN = tex.width; int yN = tex.width; for (int i = 0; i < xN; i++) { for (int j = 0; j < yN; j++) { // tex.SetPixel(xN - i - 1, j, orig.GetPixel(i, j)); orig.SetPixel(xN - i - 1, j, tex.GetPixel(i, j)); } } orig.Apply(); } else { orig = tex; } return orig; } 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); } }
OK,實用的小功能已做完,大家如果有問題可以給我留言,猿類要技術共享哦!
傳送門:git@github.com:wuzhangwuzhang/UnityHeadIconSet.git