123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154 |
- // Only works on ARGB32, RGB24 and Alpha8 textures that are marked readable
- using System.Threading;
- using UnityEngine;
- namespace Imagine.WebAR{
- public class TextureScale
- {
- 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 Point (Texture2D tex, int newWidth, int newHeight)
- {
- ThreadedScale (tex, newWidth, newHeight, false);
- }
- public static void Bilinear (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.Reinitialize(newWidth, newHeight);
- tex.SetPixels(newColors);
- tex.Apply();
- texColors = null;
- newColors = null;
- }
- 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);
- }
- }
- }
|