Guest User

Untitled

a guest
Jun 23rd, 2018
85
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 3.63 KB | None | 0 0
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Threading;
  4. using UnityEngine;
  5. using UnityEngine.Assertions;
  6.  
  7. public partial class Bitmap
  8. {
  9. public uint width { get { return _width; } }
  10. public uint height { get { return _height; } }
  11.  
  12. public uint count { get { return _width * _height; } }
  13.  
  14. public Color[] pixels { get { return _pixels; } }
  15.  
  16. public Color this[int x, int y]
  17. {
  18. get { return _pixels[_width * y + x]; }
  19. set { _pixels[_width * y + x] = value; }
  20. }
  21.  
  22. public Color this[int index]
  23. {
  24. get { return _pixels[index]; }
  25. set { _pixels[index] = value; }
  26. }
  27.  
  28. public Bitmap(Texture2D texture)
  29. : this(texture.GetPixels(), (uint)texture.width, (uint)texture.height)
  30. {
  31. }
  32.  
  33. public Bitmap(uint width, uint height)
  34. : this(new Color[width * height], width, height)
  35. {
  36. }
  37.  
  38. public Bitmap(Color[] pixels, uint width, uint height)
  39. {
  40. Assert.IsTrue(pixels.Length == width * height);
  41.  
  42. _width = width;
  43. _height = height;
  44. _pixels = pixels;
  45. }
  46.  
  47. public Bitmap copy()
  48. {
  49. var bitmap = new Bitmap(_width, _height);
  50. _pixels.CopyTo(bitmap._pixels, 0);
  51. return bitmap;
  52. }
  53.  
  54. public Texture2D createTexture()
  55. {
  56. var texture = new Texture2D((int)_width, (int)_height, TextureFormat.RGBA32, false);
  57. texture.SetPixels(_pixels);
  58. texture.Apply();
  59. return texture;
  60. }
  61.  
  62. public Color get(int x, int y)
  63. {
  64. x = clamp(x, 0, (int)_width - 1);
  65. y = clamp(y, 0, (int)_height - 1);
  66. return this[x, y];
  67. }
  68.  
  69. private Bitmap resizeNearestNeighbor(uint width, uint height)
  70. {
  71. var bitmap = new Bitmap(width, height);
  72.  
  73. // スケール
  74. var scaleX = (float)width / _width;
  75. var scaleY = (float)height / _height;
  76.  
  77. // 単位を原画像の座標系に変換
  78. var unitX = 1.0f / scaleX;
  79. var unitY = 1.0f / scaleY;
  80.  
  81. // 1ピクセル幅を考慮した座標の補正
  82. var correctionX = unitX * 0.5f;
  83. var correctionY = unitY * 0.5f;
  84.  
  85. parallelFor(0, (int)bitmap._height, y => {
  86. for(int x = 0; x < bitmap._width; ++x) {
  87. // 原画像の座標系に変換
  88. var srcX = unitX * x + correctionX;
  89. var srcY = unitY * y + correctionY;
  90.  
  91. bitmap[x, y] = get((int)srcX, (int)srcY);
  92. }
  93. });
  94.  
  95. return bitmap;
  96. }
  97.  
  98. private static int clamp(int value, int min, int max)
  99. {
  100. if(value > max) return max;
  101. if(value < min) return min;
  102. return value;
  103. }
  104.  
  105. private static void parallelFor(int start, int end, Action<int> action)
  106. {
  107. var length = Math.Abs(end - start);
  108. if(length == 0) return;
  109.  
  110. // start <= endを保証する
  111. if(start > end) {
  112. var tmp = start;
  113. start = end;
  114. end = tmp;
  115. }
  116.  
  117. extendHandlePoolCapacity(length);
  118.  
  119. // 並列タスクの生成と同期オブジェクトの取得
  120. var index = 0;
  121. var handles = new ManualResetEvent[length];
  122. for(int i = start; i < end; ++i) {
  123. var arg = i;
  124. var handle = popHandle();
  125. ThreadPool.QueueUserWorkItem(state => {
  126. action(arg);
  127. handle.Set();
  128. });
  129.  
  130. handles[index++] = handle;
  131. }
  132.  
  133. // 並列タスクの終了待ち
  134. foreach(var handle in handles) {
  135. handle.WaitOne();
  136. pushHandle(handle);
  137. }
  138. }
  139.  
  140. private static void extendHandlePoolCapacity(int capacity)
  141. {
  142. if(_handlePool.Capacity < capacity) {
  143. _handlePool.Capacity = capacity;
  144. }
  145. }
  146.  
  147. private static void pushHandle(ManualResetEvent handle)
  148. {
  149. _handlePool.Add(handle);
  150. }
  151.  
  152. private static ManualResetEvent popHandle()
  153. {
  154. if(_handlePool.Count <= 0) {
  155. return new ManualResetEvent(false);
  156. }
  157.  
  158. var lastIndex = _handlePool.Count - 1;
  159. var handle = _handlePool[lastIndex];
  160. _handlePool.RemoveAt(lastIndex);
  161. handle.Reset();
  162. return handle;
  163. }
  164.  
  165. private static readonly List<ManualResetEvent> _handlePool = new List<ManualResetEvent>();
  166.  
  167. private uint _width = 0u;
  168. private uint _height = 0u;
  169.  
  170. private Color[] _pixels = null;
  171. }
Add Comment
Please, Sign In to add comment