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 }