1 module des.il.func; 2 3 import std.algorithm; 4 import std.traits; 5 import std.range; 6 7 import des.il.util; 8 import des.il.image; 9 import des.il.region; 10 11 import des.math.linear.vector; 12 13 import std.c.string : memcpy; 14 15 /// copy image region to new image 16 auto imCopy(size_t N,T)( in Image!N img, in Region!(N,T) r ) 17 if( isIntegral!T ) 18 { 19 auto ret = Image!N( r.size, img.info ); 20 21 alias Reg = Region!(N,CoordType); 22 alias SV = SizeVector!N; 23 24 auto crop = Reg( SV(), img.size ).overlapLocal(r); 25 auto bpe = img.info.bpe; 26 27 auto count = reduce!((s,v)=>s*=v)( crop.size ); 28 29 foreach( i; 0 .. count ) 30 { 31 auto lccrd = CoordVector!N( getCoord( crop.size, i ) ); 32 auto ret_crd = -SV(r.pos) + crop.pos + lccrd; 33 auto img_crd = crop.pos + lccrd; 34 auto ret_offset = getIndex( ret.size, ret_crd ); 35 auto img_offset = getIndex( img.size, img_crd ); 36 memcpy( ret.data.ptr + ret_offset * bpe, 37 img.data.ptr + img_offset * bpe, bpe ); 38 } 39 40 return ret; 41 } 42 43 /// 44 unittest 45 { 46 auto a = Image1( [5], ElemInfo( DataType.FLOAT, 2 ) ); 47 a.pixel!vec2(3) = vec2(1,1); 48 a.pixel!vec2(4) = vec2(2,2); 49 auto b = imCopy( a, Region!(1,int)(3,2) ); 50 assert( b.pixel!vec2(0) == a.pixel!vec2(3) ); 51 assert( b.pixel!vec2(1) == a.pixel!vec2(4) ); 52 } 53 54 /// 55 unittest 56 { 57 ubyte[] data = 58 [ 59 2, 1, 3, 5, 2, 60 9, 1, 2, 6, 0, 61 2, 5, 2, 9, 1, 62 8, 3, 6, 3, 0, 63 6, 2, 8, 1, 5 64 ]; 65 66 ubyte[] datav1 = 67 [ 68 0, 0, 0, 0, 0, 0, 0, 69 0, 2, 1, 3, 5, 2, 0, 70 0, 9, 1, 2, 6, 0, 0, 71 0, 2, 5, 2, 9, 1, 0, 72 0, 8, 3, 6, 3, 0, 0, 73 0, 6, 2, 8, 1, 5, 0, 74 0, 0, 0, 0, 0, 0, 0 75 ]; 76 77 ubyte[] datav2 = 78 [ 79 1, 2, 6, 80 5, 2, 9, 81 3, 6, 3 82 ]; 83 84 ubyte[] datav3 = 85 [ 86 0, 0, 0, 0, 87 0, 2, 1, 3, 88 0, 9, 1, 2, 89 0, 2, 5, 2 90 ]; 91 92 ubyte[] datav4 = 93 [ 94 0, 0, 0, 0, 95 3, 5, 2, 0, 96 2, 6, 0, 0, 97 2, 9, 1, 0 98 ]; 99 100 ubyte[] datav5 = 101 [ 102 0, 2, 5, 2, 103 0, 8, 3, 6, 104 0, 6, 2, 8, 105 0, 0, 0, 0 106 ]; 107 108 ubyte[] datav6 = 109 [ 110 2, 9, 1, 0, 111 6, 3, 0, 0, 112 8, 1, 5, 0, 113 0, 0, 0, 0 114 ]; 115 116 auto orig = Image2( [5,5], DataType.UBYTE, 1, data ); 117 auto im = imCopy( orig, iRegion2( 0, 0, 5, 5 ) ); 118 assert( orig == im ); 119 120 auto imv1 = Image2( ivec2( 7, 7 ), DataType.UBYTE, 1, datav1 ); 121 assert( imCopy( orig, iRegion2( -1, -1, 7, 7 ) ) == imv1 ); 122 123 auto imv2 = Image2( [3,3], DataType.UBYTE, 1, datav2 ); 124 assert( imCopy( orig, iRegion2( 1, 1, 3, 3 ) ) == imv2 ); 125 126 auto imv3 = Image2( ivec2(4,4), DataType.UBYTE, 1, datav3 ); 127 assert( imCopy( orig, iRegion2( -1, -1, 4, 4 ) ) == imv3 ); 128 129 auto imv4 = Image2( ivec2(4,4), DataType.UBYTE, 1, datav4 ); 130 assert( imCopy( orig, iRegion2( 2, -1, 4, 4 ) ) == imv4 ); 131 132 auto imv5 = Image2( ivec2(4,4), DataType.UBYTE, 1, datav5 ); 133 assert( imCopy( orig, iRegion2( -1, 2, 4, 4 ) ) == imv5 ); 134 135 auto imv6 = Image2( [4,4], DataType.UBYTE, 1, datav6 ); 136 assert( imCopy( orig, iRegion2( 2, 2, 4, 4 ) ) == imv6 ); 137 } 138 139 /// paste in image other image 140 void imPaste(size_t N,V)( ref Image!N img, in V pos, in Image!N pim ) 141 if( isCompatibleVector!(N,size_t,V) ) 142 { 143 enforce( pim.info == img.info, 144 new ImageException( "Image info is wrong for paste." ) ); 145 146 alias Reg = Region!(N,CoordType); 147 alias SV = SizeVector!N; 148 149 auto pim_reg = Reg( pos, pim.size ); 150 151 auto crop = Reg( SV(), img.size ).overlapLocal( pim_reg ); 152 auto bpe = img.info.bpe; 153 154 auto count = reduce!((s,v)=>s*=v)( crop.size ); 155 156 foreach( i; 0 .. count ) 157 { 158 auto lccrd = CoordVector!N( getCoord( crop.size, i ) ); 159 auto pim_crd = -SV(pos) + crop.pos + lccrd; 160 auto img_crd = crop.pos + lccrd; 161 auto pim_offset = getIndex( pim.size, pim_crd ); 162 auto img_offset = getIndex( img.size, img_crd ); 163 memcpy( img.data.ptr + img_offset * bpe, 164 pim.data.ptr + pim_offset * bpe, bpe ); 165 } 166 } 167 168 /// 169 unittest 170 { 171 ubyte[] data = 172 [ 173 2, 1, 3, 5, 2, 174 9, 1, 2, 6, 3, 175 2, 5, 2, 9, 1, 176 8, 3, 6, 3, 0, 177 6, 2, 8, 1, 5 178 ]; 179 180 ubyte[] datav1 = 181 [ 182 1, 2, 6, 3, 0, 0, 0, 183 5, 2, 9, 1, 0, 0, 0, 184 3, 6, 3, 0, 0, 0, 0, 185 2, 8, 1, 5, 0, 0, 0, 186 0, 0, 0, 0, 0, 0, 0, 187 0, 0, 0, 0, 0, 0, 0, 188 0, 0, 0, 0, 0, 0, 0 189 ]; 190 191 ubyte[] datav2 = 192 [ 193 0, 0, 0, 0, 0, 0, 0, 194 0, 2, 1, 3, 5, 2, 0, 195 0, 9, 1, 2, 6, 3, 0, 196 0, 2, 5, 2, 9, 1, 0, 197 0, 8, 3, 6, 3, 0, 0, 198 0, 6, 2, 8, 1, 5, 0, 199 0, 0, 0, 0, 0, 0, 0 200 ]; 201 202 203 auto orig = Image2( ivec2( 7, 7 ), ElemInfo( DataType.UBYTE, 1 ) ); 204 auto im = Image2( ivec2( 5, 5 ), DataType.UBYTE, 1, data ); 205 206 auto res = Image2(orig); 207 imPaste( res, ivec2(-1,-1), im ); 208 assert( res.data == datav1 ); 209 210 res = Image2(orig); 211 imPaste( res, ivec2(1,1), im ); 212 assert( res.data == datav2 ); 213 } 214 215 /// 216 unittest 217 { 218 ubyte[] src_data = 219 [ 220 1,2,3, 221 4,5,6, 222 7,8,9 223 ]; 224 225 ubyte[] dst1_data = 226 [ 227 0,0,0, 228 0,0,0, 229 0,0,0, 230 1,2,3, 231 4,5,6, 232 7,8,9, 233 0,0,0, 234 0,0,0, 235 0,0,0 236 ]; 237 238 ubyte[] dst2_data = 239 [ 240 0,1,0, 241 0,2,0, 242 0,3,0, 243 0,4,0, 244 0,5,0, 245 0,6,0, 246 0,7,0, 247 0,8,0, 248 0,9,0 249 ]; 250 251 auto src = Image2( ivec2(3,3), ElemInfo( DataType.UBYTE, 1 ), src_data ); 252 auto dst = Image3( ivec3(3,3,3), ElemInfo( DataType.UBYTE, 1 ) ); 253 imPaste( dst, ivec3(0,0,1), Image3( src ) ); 254 assert( dst.data == dst1_data ); 255 dst.clear(); 256 imPaste( dst, ivec3(1,0,0), Image3(src,0) ); 257 assert( dst.data == dst2_data ); 258 } 259 260 /// 261 unittest 262 { 263 ubyte[] dt = 264 [ 265 0,0,0,0, 266 0,0,0,0, 267 0,0,0,0, 268 0,0,0,0, 269 270 0,0,0,0, 271 0,1,2,0, 272 0,3,4,0, 273 0,0,0,0, 274 275 0,0,0,0, 276 0,5,6,0, 277 0,7,8,0, 278 0,0,0,0, 279 280 0,0,0,0, 281 0,0,0,0, 282 0,0,0,0, 283 0,0,0,0 284 ]; 285 286 ubyte[] cp = 287 [ 288 1,2,1,2, 289 3,4,3,4, 290 1,2,1,2, 291 3,4,3,4, 292 293 5,6,5,6, 294 7,8,7,8, 295 5,6,5,6, 296 7,8,7,8, 297 298 1,2,1,2, 299 3,4,3,4, 300 1,2,1,2, 301 3,4,3,4, 302 303 5,6,5,6, 304 7,8,7,8, 305 5,6,5,6, 306 7,8,7,8, 307 ]; 308 309 ubyte[] rs = 310 [ 311 8,7, 312 6,5, 313 4,3, 314 2,1 315 ]; 316 317 ubyte[] nnd = [ 0,0, 0,0, 0,0, 0,8 ]; 318 319 auto a = Image3( [4,4,4], ElemInfo( DataType.UBYTE, 1 ), dt ); 320 auto b = Image3( [4,4,4], ElemInfo( DataType.UBYTE, 1 ), cp ); 321 auto c = Image3( [4,4,4], ElemInfo( DataType.UBYTE, 1 ) ); 322 323 auto part = imCopy( a, iRegion3( ivec3(1,1,1), ivec3(2,2,2) ) ); 324 325 imPaste( c, ivec3(0,0,0), part ); 326 imPaste( c, ivec3(0,2,0), part ); 327 imPaste( c, ivec3(2,0,0), part ); 328 imPaste( c, ivec3(2,2,0), part ); 329 330 imPaste( c, ivec3(0,0,2), part ); 331 imPaste( c, ivec3(0,2,2), part ); 332 imPaste( c, ivec3(2,0,2), part ); 333 imPaste( c, ivec3(2,2,2), part ); 334 335 assert( b == c ); 336 337 auto part2 = imCopy( b, iRegion3(ivec3(1,1,1), ivec3(2,2,2)) ); 338 auto rr = Image3( ivec3(2,2,2), ElemInfo( DataType.UBYTE, 1 ), rs ); 339 assert( rr == part2 ); 340 341 auto nn = imCopy( rr, iRegion3( ivec3(-1,-1,-1), ivec3(2,2,2) ) ); 342 auto nndi = Image3( ivec3(2,2,2), ElemInfo( DataType.UBYTE,1 ), nnd ); 343 344 assert( nn == nndi ); 345 } 346 347 /++ get histogram convolution 348 +/ 349 Image!(N-1) imHistoConv(size_t N)( in Image!N img, size_t K ) pure 350 if( N > 1 ) 351 in { assert( K < N ); } body 352 { 353 auto ret = Image!(N-1)( removeStat( img.size, K ), img.info ); 354 355 auto bpe = img.info.bpe; 356 357 foreach( i; 0 .. ret.header.pixelCount ) 358 { 359 auto buf = ret.data.ptr + i * bpe; 360 utDataAssign( img.info, buf, 0 ); 361 foreach( j; 0 .. img.size[K] ) 362 utDataOp!"+"( img.info, buf, 363 cast(void*)( img.data.ptr + getOrigIndexByLayerCoord(img.size,K,i,j) * bpe ) ); 364 } 365 366 return ret; 367 } 368 369 /// 370 unittest 371 { 372 ubyte[] img_data = 373 [ 374 1,2,5,8, 375 4,3,1,1 376 ]; 377 378 ubyte[] hi_x_data = [ 16, 9 ]; 379 ubyte[] hi_y_data = [ 5, 5, 6, 9 ]; 380 381 auto img = Image2( [4,2], ElemInfo( DataType.UBYTE, 1 ), img_data ); 382 auto hi_x = Image1( [2], ElemInfo( DataType.UBYTE, 1 ), hi_x_data ); 383 auto hi_y = Image1( [4], ElemInfo( DataType.UBYTE, 1 ), hi_y_data ); 384 385 assert( imHistoConv(img,0) == hi_x ); 386 assert( imHistoConv(img,1) == hi_y ); 387 } 388 389 /++ get layer of image 390 +/ 391 Image!(N-1) imLayer(size_t N)( Image!N img, size_t K, size_t lno ) pure 392 { 393 auto ret = Image!(N-1)( removeStat( img.size, K ), img.info ); 394 auto bpe = img.info.bpe; 395 foreach( i; 0 .. ret.header.pixelCount ) 396 memcpy( ret.data.ptr + i * bpe, img.data.ptr + getOrigIndexByLayerCoord(img.size,K,i,lno) * bpe, bpe ); 397 return ret; 398 } 399 400 /// 401 unittest 402 { 403 ubyte[] img_data = 404 [ 405 1,2,3, 406 4,5,6, 407 408 7,8,9, 409 10,11,12, 410 ]; 411 412 auto info = ElemInfo( DataType.UBYTE, 1 ); 413 414 ubyte[] d2l0 = [ 1,2,3,4,5,6 ]; 415 ubyte[] d2l1 = [ 7,8,9,10,11,12 ]; 416 417 ubyte[] d1l0 = [ 1,2,3,7,8,9 ]; 418 ubyte[] d1l1 = [ 4,5,6,10,11,12 ]; 419 420 ubyte[] d0l0 = [ 1, 4, 7, 10 ]; 421 ubyte[] d0l1 = [ 2, 5, 8, 11 ]; 422 423 auto img = Image3( [3,2,2], info, img_data ); 424 auto id2l0 = Image2( [3,2], info, d2l0 ); 425 auto id2l1 = Image2( [3,2], info, d2l1 ); 426 auto id1l0 = Image2( [3,2], info, d1l0 ); 427 auto id1l1 = Image2( [3,2], info, d1l1 ); 428 auto id0l0 = Image2( [2,2], info, d0l0 ); 429 auto id0l1 = Image2( [2,2], info, d0l1 ); 430 431 assert( imLayer(img,2,0) == id2l0 ); 432 assert( imLayer(img,2,1) == id2l1 ); 433 434 assert( imLayer(img,1,0) == id1l0 ); 435 assert( imLayer(img,1,1) == id1l1 ); 436 437 assert( imLayer(img,0,0) == id0l0 ); 438 assert( imLayer(img,0,1) == id0l1 ); 439 }