1 // Written in the D programming language. 2 /++ 3 + Authors: KanzakiKino 4 + Copyright: KanzakiKino 2018 5 + License: LGPL-3.0 6 ++/ 7 module g4d.util.bitmap; 8 import gl3n.linalg; 9 import std.algorithm, 10 std.conv; 11 import core.stdc.stdlib, 12 core.stdc..string; 13 14 /// A class of bitmap. 15 class Bitmap ( _Type = ubyte, size_t _LengthPerPixel = 4 ) 16 { 17 /// Type of the number that shows color. 18 alias Type = _Type; 19 20 /// Length to show the color of pixel. 21 enum LengthPerPixel = _LengthPerPixel; 22 23 protected Type* _data; 24 /// Readonly pointer to data. 25 const @property data () { return _data; } 26 27 protected size_t _width, _rows; 28 /// Width of the bitmap. 29 const @property width () { return _width; } 30 /// Height of the bitmap. 31 const @property rows () { return _rows; } 32 33 /// Size of the bitmap. 34 const @property size () 35 { 36 return vec2i( width.to!int, rows.to!int ); 37 } 38 39 /// Length of the bitmap data. 40 const @property dataLength () 41 { 42 return _width*_rows*LengthPerPixel; 43 } 44 /// Size of the bitmap data in byte. 45 const @property dataByteSize () 46 { 47 return dataLength * Type.sizeof; 48 } 49 50 /// 51 this ( vec2i sz ) 52 { 53 _data = null; 54 resize( sz ); 55 clear(); 56 } 57 /// 58 this ( vec2i sz, Type* src ) 59 { 60 this( sz ); 61 memcpy( _data, src, dataByteSize ); 62 } 63 /// 64 this ( vec2i sz, Type[] src ) 65 { 66 this( sz ); 67 memcpy( _data, src.ptr, dataByteSize ); 68 } 69 70 /// 71 ~this () 72 { 73 dispose(); 74 } 75 /// Releases all memories. 76 void dispose () 77 { 78 if ( _data ) { 79 free( _data ); 80 _data = null; 81 } 82 _width = 0; 83 _rows = 0; 84 } 85 86 protected void resize ( vec2i sz ) 87 { 88 dispose(); 89 _width = sz.x.to!uint; 90 _rows = sz.y.to!uint; 91 _data = cast(Type*)malloc( dataByteSize ); 92 } 93 94 /// Creates resized bitmap with the same format. 95 const auto conservativeResize ( vec2i sz ) 96 { 97 enum lpp = LengthPerPixel; 98 99 const srcw = width, srch = rows; 100 const src = data; 101 102 auto result = new Bitmap!(Type,lpp)( sz ); 103 const dstw = result.width, dsth = result.rows; 104 auto dst = result._data; 105 106 size_t dstx = 0, dsty = 0, 107 srci = 0, dsti = 0; 108 109 for ( dsty = 0; dsty < dsth; dsty++ ) { 110 for ( dstx = 0; dstx < dstw; dstx++ ) { 111 if ( dstx >= srcw || dsty >= srch ) { 112 static foreach ( j; 0..lpp ) { 113 dst[dsti++] = 0; 114 } 115 } else { 116 static foreach ( j; 0..lpp ) { 117 dst[dsti++] = src[srci++]; 118 } 119 } 120 } 121 } 122 return result; 123 } 124 125 /// Modifies a part of the bitmap. 126 void overwrite ( vec2i offset, typeof(this) bmp ) 127 { 128 enum lpp = LengthPerPixel; 129 130 const srcl = offset.x, srct = offset.y; 131 const srcr = srcl+bmp.width, srcb = srct+bmp.rows; 132 const src = bmp.data; 133 134 const dstw = width, dsth = rows; 135 auto dst = _data; 136 137 assert( srcl >= 0 && srct >= 0 ); 138 assert( srcr <= dstw && srcb <= dsth ); 139 140 size_t dstx = srcl, dsty = srct, 141 srci = 0, dsti = 0; 142 143 for ( dsty = srct; dsty < srcb; dsty++ ) { 144 dsti = (dsty*dstw + srcl)*lpp; 145 for ( dstx = srcl; dstx < srcr; dstx++ ) { 146 static foreach ( j; 0..lpp ) { 147 dst[dsti++] = src[srci++]; 148 } 149 } 150 } 151 } 152 153 /// Fills the bitmap data with 0. 154 void clear () 155 { 156 memset( _data, 0, dataByteSize ); 157 } 158 159 /// To prove this is bitmap. 160 enum this_is_a_bitmap_class_of_g4d = true; 161 } 162 163 /// 164 alias BitmapA = Bitmap!(ubyte,1); 165 /// 166 alias BitmapRGB = Bitmap!(ubyte,3); 167 /// 168 alias BitmapRGBA = Bitmap!(ubyte,4); 169 170 /// 171 alias BitmapAf = Bitmap!(float,1); 172 /// 173 alias BitmapRGBf = Bitmap!(float,3); 174 /// 175 alias BitmapRGBAf = Bitmap!(float,4); 176 177 /// Checks if T is bitmap. 178 enum isBitmap(T) = 179 __traits(hasMember,T,"this_is_a_bitmap_class_of_g4d");