Add project files.
This commit is contained in:
144
Assets/EricHaines/TextureScale.cs
Normal file
144
Assets/EricHaines/TextureScale.cs
Normal file
@@ -0,0 +1,144 @@
|
||||
namespace EricHaines {
|
||||
// Only works on ARGB32, RGB24 and Alpha8 textures that are marked readable
|
||||
|
||||
using System.Threading;
|
||||
using UnityEngine;
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
#if UNITY_2021_2_OR_NEWER
|
||||
tex.Reinitialize(newWidth, newHeight);
|
||||
#else
|
||||
tex.Resize(newWidth, newHeight);
|
||||
#endif
|
||||
tex.SetPixels(newColors);
|
||||
tex.Apply();
|
||||
|
||||
texColors = null;
|
||||
newColors = null;
|
||||
}
|
||||
|
||||
public static void BilinearScale(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(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
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user