Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- 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;
- }
Add Comment
Please, Sign In to add comment