Created
June 22, 2018 05:08
-
-
Save hexagit/d507c00c3f97218f3fb747d7f1c52f08 to your computer and use it in GitHub Desktop.
ニアレストネイバー法
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Threading; | |
using UnityEngine; | |
using UnityEngine.Assertions; | |
public partial class Bitmap | |
{ | |
public uint width { get { return _width; } } | |
public uint height { get { return _height; } } | |
public uint count { get { return _width * _height; } } | |
public Color[] pixels { get { return _pixels; } } | |
public Color this[int x, int y] | |
{ | |
get { return _pixels[_width * y + x]; } | |
set { _pixels[_width * y + x] = value; } | |
} | |
public Color this[int index] | |
{ | |
get { return _pixels[index]; } | |
set { _pixels[index] = value; } | |
} | |
public Bitmap(Texture2D texture) | |
: this(texture.GetPixels(), (uint)texture.width, (uint)texture.height) | |
{ | |
} | |
public Bitmap(uint width, uint height) | |
: this(new Color[width * height], width, height) | |
{ | |
} | |
public Bitmap(Color[] pixels, uint width, uint height) | |
{ | |
Assert.IsTrue(pixels.Length == width * height); | |
_width = width; | |
_height = height; | |
_pixels = pixels; | |
} | |
public Bitmap copy() | |
{ | |
var bitmap = new Bitmap(_width, _height); | |
_pixels.CopyTo(bitmap._pixels, 0); | |
return bitmap; | |
} | |
public Texture2D createTexture() | |
{ | |
var texture = new Texture2D((int)_width, (int)_height, TextureFormat.RGBA32, false); | |
texture.SetPixels(_pixels); | |
texture.Apply(); | |
return texture; | |
} | |
public Color get(int x, int y) | |
{ | |
x = clamp(x, 0, (int)_width - 1); | |
y = clamp(y, 0, (int)_height - 1); | |
return this[x, y]; | |
} | |
private Bitmap resizeNearestNeighbor(uint width, uint height) | |
{ | |
var bitmap = new Bitmap(width, height); | |
// スケール | |
var scaleX = (float)width / _width; | |
var scaleY = (float)height / _height; | |
// 単位を原画像の座標系に変換 | |
var unitX = 1.0f / scaleX; | |
var unitY = 1.0f / scaleY; | |
// 1ピクセル幅を考慮した座標の補正 | |
var correctionX = unitX * 0.5f; | |
var correctionY = unitY * 0.5f; | |
parallelFor(0, (int)bitmap._height, y => { | |
for(int x = 0; x < bitmap._width; ++x) { | |
// 原画像の座標系に変換 | |
var srcX = unitX * x + correctionX; | |
var srcY = unitY * y + correctionY; | |
bitmap[x, y] = get((int)srcX, (int)srcY); | |
} | |
}); | |
return bitmap; | |
} | |
private static int clamp(int value, int min, int max) | |
{ | |
if(value > max) return max; | |
if(value < min) return min; | |
return value; | |
} | |
private static void parallelFor(int start, int end, Action<int> action) | |
{ | |
var length = Math.Abs(end - start); | |
if(length == 0) return; | |
// start <= endを保証する | |
if(start > end) { | |
var tmp = start; | |
start = end; | |
end = tmp; | |
} | |
extendHandlePoolCapacity(length); | |
// 並列タスクの生成と同期オブジェクトの取得 | |
var index = 0; | |
var handles = new ManualResetEvent[length]; | |
for(int i = start; i < end; ++i) { | |
var arg = i; | |
var handle = popHandle(); | |
ThreadPool.QueueUserWorkItem(state => { | |
action(arg); | |
handle.Set(); | |
}); | |
handles[index++] = handle; | |
} | |
// 並列タスクの終了待ち | |
foreach(var handle in handles) { | |
handle.WaitOne(); | |
pushHandle(handle); | |
} | |
} | |
private static void extendHandlePoolCapacity(int capacity) | |
{ | |
if(_handlePool.Capacity < capacity) { | |
_handlePool.Capacity = capacity; | |
} | |
} | |
private static void pushHandle(ManualResetEvent handle) | |
{ | |
_handlePool.Add(handle); | |
} | |
private static ManualResetEvent popHandle() | |
{ | |
if(_handlePool.Count <= 0) { | |
return new ManualResetEvent(false); | |
} | |
var lastIndex = _handlePool.Count - 1; | |
var handle = _handlePool[lastIndex]; | |
_handlePool.RemoveAt(lastIndex); | |
handle.Reset(); | |
return handle; | |
} | |
private static readonly List<ManualResetEvent> _handlePool = new List<ManualResetEvent>(); | |
private uint _width = 0u; | |
private uint _height = 0u; | |
private Color[] _pixels = null; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment