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 version(RgbCachingOn) {
16 	RGBColor result;
17 
18 	static this() {
19 		result = new RGBColor(0, 0, 0);
20 	}
21 }
22 
23 // Точечная свертка
24 auto elementaryConvolution(Signal, Filter)(Signal signal, Filter filter)
25 {
26 
27 
28 
29 	version(RgbCachingOn) {
30 		result.setRed = 0;
31 		result.setGreen = 0;	
32 		result.setBlue = 0;
33 	}
34 	else {
35 		RGBColor result = new RGBColor(0, 0, 0);
36 	}
37 
38 
39 
40 	auto data = zip(signal, filter);
41 	alias PairType = ElementType!(typeof(data));
42 
43 	auto conv = delegate(PairType pair) {
44 		if(pair[1] != 0) {
45 			if(pair[1] < 0)
46 				result -= pair[0] * abs(pair[1]);
47 
48 			else if(pair[1] != 1)
49 				result += pair[0] * pair[1];
50 			else
51 				result += pair[0];
52 		}
53 	};
54 
55 	data.each!conv;
56 
57 
58 	
59 	version(RgbCachingOn) {
60 		return RGBColor.getColor(result);
61 	}
62 	else {
63 		return result;
64 	}
65 }
66 
67 // Свертка сигнала с линейным фильтром
68 alias convolution = convolutionNew;
69 alias convolve = convolveNew;
70 
71 
72 auto convolutionNew(Signal)(Signal signal, LinearFilter filter)
73 {
74 	// Выполнение свертки на одном фрагменте диапазона окрестностей
75 	auto performConvolution(Signal)(Signal signal, LinearFilter filter)
76 	{
77 		return filter.getOffset + filter.getDivider * elementaryConvolution(signal, filter.getKernel);
78 	}
79 	return signal.map!(a => performConvolution(a, filter));
80 }
81 
82 auto convolveNew(Surface surface, LinearFilter filter)
83 {
84 	auto image = surface
85 		.createFencesNew(filter.getWidth, filter.getHeight)
86 			.convolutionNew(filter)
87 			.toSurface(surface.getWidth!int, surface.getHeight!int);
88 	return image;
89 }