1 module rip.processing.convolution;
2 
3 private
4 {
5 	import std.algorithm;
6 	import std.math;
7 	import std.range;
8 
9 	import rip.concepts.color;
10 	import rip.concepts.ranges;
11 	import rip.concepts.surface;
12 	import rip.processing.filters.linear;
13 }
14 
15 // Точечная свертка
16 auto elementaryConvolution(Signal, Filter)(Signal signal, Filter filter)
17 {
18 
19 	RGBColor result = new RGBColor(0, 0, 0);
20 
21 	auto data = zip(signal, filter);
22 	alias PairType = ElementType!(typeof(data));
23 
24 	auto conv = delegate(PairType pair) {
25 		if(pair[1] != 0) {
26 			if(pair[1] < 0)
27 				result -= pair[0] * abs(pair[1]);
28 
29 			else if(pair[1] != 1)
30 				result += pair[0] * pair[1];
31 			else
32 				result += pair[0];
33 		}
34 	};
35 
36 	data.each!conv;
37 
38 	return result;
39 }
40 
41 // Свертка сигнала с линейным фильтром
42 auto convolution(Signal)(Signal signal, LinearFilter filter)
43 {
44 	// Выполнение свертки на одном фрагменте диапазона окрестностей
45 	auto performConvolution(Signal)(Signal signal, LinearFilter filter)
46 	{
47 		return filter.getOffset + filter.getDivider * elementaryConvolution(signal, filter.getKernel);
48 	}
49 
50 	auto convolutionRange = map!(a => performConvolution(a, filter))(signal).array;
51 	return convolutionRange;
52 }
53 
54 auto convolve(Surface surface, LinearFilter filter)
55 {
56 	auto image = surface
57 		.createFences(filter.getWidth, filter.getHeight)
58 			.convolution(filter)
59 			.toSurface(surface.getWidth!int, surface.getHeight!int);
60 	return image;
61 }
62 
63 auto convolveNew(Surface surface, LinearFilter filter)
64 {
65 	auto image = surface
66 		.createFencesNew(filter.getWidth, filter.getHeight)
67 			.convolution(filter)
68 			.toSurface(surface.getWidth!int, surface.getHeight!int);
69 	return image;
70 }