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 }