1 module armos.graphics.bitmap;
2 import armos.math;
3 import armos.graphics;
4 
5 /++
6 Bitmapデータを表すstructです.
7 画素を表すPixelの集合で構成されます.
8 +/
9 struct Bitmap(T){
10     public{
11         /++
12             領域を確保します.
13             Params:
14             size = Bitmapのサイズです.
15             colorType = Bitmapのカラーフォーマットを指定します.
16         +/
17         Bitmap allocate(armos.math.Vector2i size, armos.graphics.ColorFormat colorType){
18             _colorFormat = colorType;
19             allocate(size[0], size[1], colorType);
20             return this;
21         }
22 
23         /++
24             領域を確保します.
25             Params:
26             width = Bitmapの横幅です.
27             height = Bitmapの縦幅です.
28             colorType = Bitmapのカラーフォーマットを指定します.
29         +/
30         Bitmap allocate(int width, int height, armos.graphics.ColorFormat colorType){
31             import std.array:appender;
32             _size[0] = width;
33             _size[1] = height;
34             _colorFormat = colorType;
35             auto arraySize = width * height;
36             _data = new armos.graphics.Pixel!(T)[arraySize];
37             for (int i = 0; i < arraySize; i++) {
38                 _data[i] = armos.graphics.Pixel!T(colorType);
39             }
40             return this;
41         }
42 
43         /++
44             Set value to all pixels for the given index.
45 
46             全てのピクセルのindexで与えられた画素に値を代入します
47         +/
48         Bitmap setAllPixels(int index, T level){
49             foreach (pixel; _data) {
50                 pixel.element(index, level);
51             }
52             return this;
53         };
54 
55         /++
56             Set value to the pixel for the given index and position.
57 
58             positionとindexで指定された画素に値を代入します.
59         +/
60         Bitmap pixel(in int x, in int y, in int index, in T value){
61             _data[x+y*_size[0]].element(index, value);
62             return this;
63         };
64 
65         /++
66             Return the pixel for the given position.
67 
68             positionで指定された座標のpixelを返します.
69         +/
70         armos.graphics.Pixel!(T) pixel(in int x, in int y){
71             return _data[x+y*_size[0]];
72         };
73 
74         /++
75             Set pixel to the pixel for the given position.
76 
77             positionで指定された座標のpixelにpixelを設定します.
78         +/
79         Bitmap pixel(in int x, in int y, armos.graphics.Pixel!(T) pixel){
80             _data[x+y*_size[0]].element(pixel);
81             return this;
82         };
83 
84 
85         /++
86             Paste a arg bitmap into this for the given position.
87 
88             bitmapを指定した座標に貼り付けます.
89         +/
90         Bitmap pasteInto(ref Bitmap!(T) targetBitmap, in int x, in int y){
91             for (int i = 0; i < size[0]; i++) {
92                 for (int j = 0; j < size[1]; j++) {
93                     targetBitmap.pixel(i+x, j+y, pixel(i, j));
94                 }
95             }
96             return this;
97         }
98 
99         /++
100             Return the bitmap size;
101         +/
102         armos.math.Vector2i size()const{
103             return _size;
104         }
105 
106         /++
107             Return width.
108 
109             bitmapの幅を返します.
110         +/
111         int width()const{return _size[0];}
112 
113         /++
114             Return height.
115 
116             bitmapの高さを返します.
117         +/
118         int height()const{return _size[1];}
119 
120         /++
121             Return the number of Elements.
122 
123             pixelの要素の数を返します.
124         +/
125         int numElements()const{
126             return armos.graphics.numColorFormatElements(_colorFormat);
127         }
128         
129         /++
130             Generate a bitmap from the aligned pixels
131 
132             一次元配列からBitmapを生成します
133         +/
134         Bitmap setFromAlignedPixels(T* pixels, int width, int height, armos.graphics.ColorFormat format){
135             allocate(width, height, format);
136             auto size = width * height;
137             auto numChannels = armos.graphics.numColorFormatElements(format);
138             for (int i = 0; i < size*numChannels; i += numChannels) {
139                 for (int channel = 0; channel < numChannels; channel++){
140                     _data[i/numChannels].element(channel, pixels[channel+i]);
141                 }
142             }
143             return this;
144         }
145         
146 
147         /++
148             RとBのチャンネルを入れ替えます.
149         +/
150         Bitmap swapRAndB(){
151             if(numElements < 3){assert(0);}
152             foreach (ref pixel; _data) {
153                 auto r = pixel.element(0);
154                 auto b = pixel.element(2);
155                 pixel.element(0, b);
156                 pixel.element(2, r);
157             }
158             return this;
159         }
160 
161         /++
162             Bitmapのカラーフォーマットを返します.
163         +/
164         ColorFormat colorFormat()const{
165             return _colorFormat;
166         }
167     }
168 
169     private{
170         armos.math.Vector2i _size;
171         armos.graphics.Pixel!(T)[] _data;
172         armos.graphics.ColorFormat _colorFormat;
173     }
174 }