154 lines
3.6 KiB
C#
154 lines
3.6 KiB
C#
using System.Threading;
|
|
using UnityEngine;
|
|
|
|
namespace Gaia
|
|
{
|
|
public class ScaleTexture
|
|
{
|
|
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, useBilinear: false);
|
|
}
|
|
|
|
public static void Bilinear(Texture2D tex, int newWidth, int newHeight)
|
|
{
|
|
ThreadedScale(tex, newWidth, newHeight, useBilinear: true);
|
|
}
|
|
|
|
private static void ThreadedScale(Texture2D tex, int newWidth, int newHeight, bool useBilinear)
|
|
{
|
|
texColors = tex.GetPixels();
|
|
newColors = new Color[newWidth * newHeight];
|
|
if (useBilinear)
|
|
{
|
|
ratioX = 1f / ((float)newWidth / (float)(tex.width - 1));
|
|
ratioY = 1f / ((float)newHeight / (float)(tex.height - 1));
|
|
}
|
|
else
|
|
{
|
|
ratioX = (float)tex.width / (float)newWidth;
|
|
ratioY = (float)tex.height / (float)newHeight;
|
|
}
|
|
w = tex.width;
|
|
w2 = newWidth;
|
|
int num = Mathf.Min(SystemInfo.processorCount, newHeight);
|
|
int num2 = newHeight / num;
|
|
finishCount = 0;
|
|
if (mutex == null)
|
|
{
|
|
mutex = new Mutex(initiallyOwned: false);
|
|
}
|
|
if (num > 1)
|
|
{
|
|
int num3 = 0;
|
|
ThreadData parameter;
|
|
for (num3 = 0; num3 < num - 1; num3++)
|
|
{
|
|
parameter = new ThreadData(num2 * num3, num2 * (num3 + 1));
|
|
new Thread(useBilinear ? new ParameterizedThreadStart(BilinearScale) : new ParameterizedThreadStart(PointScale)).Start(parameter);
|
|
}
|
|
parameter = new ThreadData(num2 * num3, newHeight);
|
|
if (useBilinear)
|
|
{
|
|
BilinearScale(parameter);
|
|
}
|
|
else
|
|
{
|
|
PointScale(parameter);
|
|
}
|
|
while (finishCount < num)
|
|
{
|
|
Thread.Sleep(1);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ThreadData obj = new ThreadData(0, newHeight);
|
|
if (useBilinear)
|
|
{
|
|
BilinearScale(obj);
|
|
}
|
|
else
|
|
{
|
|
PointScale(obj);
|
|
}
|
|
}
|
|
tex.Reinitialize(newWidth, newHeight);
|
|
tex.SetPixels(newColors);
|
|
tex.Apply();
|
|
}
|
|
|
|
public static void BilinearScale(object obj)
|
|
{
|
|
ThreadData threadData = (ThreadData)obj;
|
|
for (int i = threadData.start; i < threadData.end; i++)
|
|
{
|
|
int num = (int)Mathf.Floor((float)i * ratioY);
|
|
int num2 = num * w;
|
|
int num3 = (num + 1) * w;
|
|
int num4 = i * w2;
|
|
for (int j = 0; j < w2; j++)
|
|
{
|
|
int num5 = (int)Mathf.Floor((float)j * ratioX);
|
|
float value = (float)j * ratioX - (float)num5;
|
|
newColors[num4 + j] = ColorLerpUnclamped(ColorLerpUnclamped(texColors[num2 + num5], texColors[num2 + num5 + 1], value), ColorLerpUnclamped(texColors[num3 + num5], texColors[num3 + num5 + 1], value), (float)i * ratioY - (float)num);
|
|
}
|
|
}
|
|
mutex.WaitOne();
|
|
finishCount++;
|
|
mutex.ReleaseMutex();
|
|
}
|
|
|
|
public static void PointScale(object obj)
|
|
{
|
|
ThreadData threadData = (ThreadData)obj;
|
|
for (int i = threadData.start; i < threadData.end; i++)
|
|
{
|
|
int num = (int)(ratioY * (float)i) * w;
|
|
int num2 = i * w2;
|
|
for (int j = 0; j < w2; j++)
|
|
{
|
|
newColors[num2 + j] = texColors[(int)((float)num + ratioX * (float)j)];
|
|
}
|
|
}
|
|
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);
|
|
}
|
|
}
|
|
}
|