TextureScale.cs 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. // Only works on ARGB32, RGB24 and Alpha8 textures that are marked readable
  2. using System.Threading;
  3. using UnityEngine;
  4. namespace LunarCatsStudio.SuperCombiner
  5. {
  6. /// <summary>
  7. /// Create the textures atlas from all input textures
  8. /// </summary>
  9. public class TextureScale
  10. {
  11. public class ThreadData
  12. {
  13. public int _start;
  14. public int _end;
  15. public ThreadData (int s, int e) {
  16. _start = s;
  17. _end = e;
  18. }
  19. }
  20. private static Color[] _texColors;
  21. private static Color[] _newColors;
  22. private static int _w;
  23. private static float _ratioX;
  24. private static float _ratioY;
  25. private static int _w2;
  26. private static int _finishCount;
  27. private static Mutex _mutex;
  28. public static void Point (Texture2D tex, int newWidth, int newHeight)
  29. {
  30. ThreadedScale (tex, newWidth, newHeight, false);
  31. }
  32. public static void Bilinear (Texture2D tex, int newWidth, int newHeight)
  33. {
  34. ThreadedScale (tex, newWidth, newHeight, true);
  35. }
  36. private static void ThreadedScale (Texture2D tex, int newWidth, int newHeight, bool useBilinear)
  37. {
  38. _texColors = tex.GetPixels();
  39. _newColors = new Color[newWidth * newHeight];
  40. if (useBilinear)
  41. {
  42. _ratioX = 1.0f / ((float)newWidth / (tex.width-1));
  43. _ratioY = 1.0f / ((float)newHeight / (tex.height-1));
  44. }
  45. else {
  46. _ratioX = ((float)tex.width) / newWidth;
  47. _ratioY = ((float)tex.height) / newHeight;
  48. }
  49. _w = tex.width;
  50. _w2 = newWidth;
  51. var cores = Mathf.Min(Mathf.Max(SystemInfo.processorCount, 1), newHeight);
  52. var slice = newHeight/cores;
  53. _finishCount = 0;
  54. if (_mutex == null) {
  55. _mutex = new Mutex(false);
  56. }
  57. if (cores > 1)
  58. {
  59. int i = 0;
  60. ThreadData threadData;
  61. for (i = 0; i < cores-1; i++) {
  62. threadData = new ThreadData(slice * i, slice * (i + 1));
  63. ParameterizedThreadStart ts = useBilinear ? new ParameterizedThreadStart(BilinearScale) : new ParameterizedThreadStart(PointScale);
  64. Thread thread = new Thread(ts);
  65. thread.Start(threadData);
  66. }
  67. threadData = new ThreadData(slice*i, newHeight);
  68. if (useBilinear)
  69. {
  70. BilinearScale(threadData);
  71. }
  72. else
  73. {
  74. PointScale(threadData);
  75. }
  76. while (_finishCount < cores)
  77. {
  78. Thread.Sleep(1);
  79. }
  80. }
  81. else
  82. {
  83. ThreadData threadData = new ThreadData(0, newHeight);
  84. if (useBilinear)
  85. {
  86. BilinearScale(threadData);
  87. }
  88. else
  89. {
  90. PointScale(threadData);
  91. }
  92. }
  93. tex.Resize(newWidth, newHeight);
  94. tex.SetPixels(_newColors);
  95. tex.Apply();
  96. _texColors = null;
  97. _newColors = null;
  98. }
  99. public static void BilinearScale (System.Object obj)
  100. {
  101. ThreadData threadData = (ThreadData) obj;
  102. for (var y = threadData._start; y < threadData._end; y++)
  103. {
  104. int yFloor = (int)Mathf.Floor(y * _ratioY);
  105. var y1 = yFloor * _w;
  106. var y2 = (yFloor+1) * _w;
  107. var yw = y * _w2;
  108. for (var x = 0; x < _w2; x++) {
  109. int xFloor = (int)Mathf.Floor(x * _ratioX);
  110. var xLerp = x * _ratioX-xFloor;
  111. _newColors[yw + x] = ColorLerpUnclamped(ColorLerpUnclamped(_texColors[y1 + xFloor], _texColors[y1 + xFloor+1], xLerp),
  112. ColorLerpUnclamped(_texColors[y2 + xFloor], _texColors[y2 + xFloor+1], xLerp),
  113. y*_ratioY-yFloor);
  114. }
  115. }
  116. _mutex.WaitOne();
  117. _finishCount++;
  118. _mutex.ReleaseMutex();
  119. }
  120. public static void PointScale (System.Object obj)
  121. {
  122. ThreadData threadData = (ThreadData) obj;
  123. for (var y = threadData._start; y < threadData._end; y++)
  124. {
  125. var thisY = (int)(_ratioY * y) * _w;
  126. var yw = y * _w2;
  127. for (var x = 0; x < _w2; x++) {
  128. _newColors[yw + x] = _texColors[(int)(thisY + _ratioX*x)];
  129. }
  130. }
  131. _mutex.WaitOne();
  132. _finishCount++;
  133. _mutex.ReleaseMutex();
  134. }
  135. private static Color ColorLerpUnclamped (Color c1, Color c2, float value)
  136. {
  137. return new Color (c1.r + (c2.r - c1.r)*value,
  138. c1.g + (c2.g - c1.g)*value,
  139. c1.b + (c2.b - c1.b)*value,
  140. c1.a + (c2.a - c1.a)*value);
  141. }
  142. }
  143. }