1 /**
2 Copyright: Copyright (c) 2017-2018 Andrey Penechko.
3 License: $(WEB boost.org/LICENSE_1_0.txt, Boost License 1.0).
4 Authors: Andrey Penechko.
5 */
6 
7 module voxelman.graphics.bitmap;
8 
9 import voxelman.algorithm.arraycopy2d;
10 import voxelman.math;
11 import voxelman.graphics.color;
12 import dlib.image.image : ImageRGBA8, SuperImage;
13 import dlib.image.color;
14 
15 class Bitmap : ImageRGBA8
16 {
17 	public:
18 
19 	this(uint w, uint h)
20 	{
21 		super(w, h);
22 	}
23 
24 	this(SuperImage image)
25 	{
26 		super(0,0);
27 		this._width = image.width;
28 		this._height = image.height;
29 
30 		if (pixelFormat == image.pixelFormat)
31 		{
32 			this._bitDepth = image.bitDepth;
33 			this._channels = image.channels;
34 			this._pixelSize = image.pixelSize;
35 			this._data = image.data;
36 		}
37 		else
38 		{
39 			allocateData();
40 			foreach(x; 0..image.width)
41 			foreach(y; 0..image.height)
42 				this[x, y] = Color4ub(image[x, y].convert(8));
43 		}
44 	}
45 
46 	ivec2 size()
47 	{
48 		return ivec2(width, height);
49 	}
50 
51 	override Color4f opIndexAssign(Color4f c, int x, int y)
52 	{
53 		return super.opIndexAssign(c, x, y);
54 	}
55 
56 	void opIndexAssign(Color4ub color, int x, int y)
57 	{
58 		auto offset = (this._width * y + x) * 4;
59 		_data[offset+0] = color.r;
60 		_data[offset+1] = color.g;
61 		_data[offset+2] = color.b;
62 		_data[offset+3] = color.a;
63 	}
64 
65 	void resize(ivec2 newSize)
66 	{
67 		if (newSize == size) return;
68 
69 		auto newData = new ubyte[newSize.x * newSize.y * _pixelSize];
70 
71 		auto sourceSize = ivec2(_width * _pixelSize, _height);
72 		auto sourceSubRect = irect(ivec2(0,0), sourceSize);
73 
74 		auto destSize = ivec2(newSize.x * _pixelSize, newSize.y);
75 		auto destSubRectPos = ivec2(0,0);
76 
77 		setSubArray2d(_data, sourceSize, sourceSubRect,
78 			newData, destSize, destSubRectPos);
79 
80 		_data = newData;
81 		_width = newSize.x;
82 		_height = newSize.y;
83 	}
84 
85 	void fillSubRect(irect destRect, Color4ub color)
86 	{
87 		foreach(y; destRect.y..destRect.endY)
88 		foreach(x; destRect.x..destRect.endX)
89 		this[x, y] = color;
90 	}
91 
92 	void putSubRect(in Bitmap source, irect sourceSubRect, ivec2 destPos)
93 	{
94 		auto sourceSize = ivec2(source._width * source._pixelSize, source._height);
95 		auto destSize = ivec2(_width * _pixelSize, _height);
96 
97 		sourceSubRect.width *= source._pixelSize;
98 		sourceSubRect.x *= source._pixelSize;
99 		destPos.x *= _pixelSize;
100 
101 		setSubArray2d(source._data, sourceSize, sourceSubRect,
102 			_data, destSize, destPos);
103 	}
104 
105 	void putRect(in Bitmap source, ivec2 destPos)
106 	{
107 		auto sourceSize = ivec2(source._width * source._pixelSize, source._height);
108 		auto sourceSubRect = irect(ivec2(0,0), sourceSize);
109 
110 		auto destSize = ivec2(_width * _pixelSize, _height);
111 
112 		setSubArray2d(source._data, sourceSize, sourceSubRect,
113 			_data, destSize, destPos);
114 	}
115 }