1 module rip.analysis.histogram; 2 3 private { 4 import std.algorithm; 5 import std.range; 6 import std.math; 7 8 import rip.concepts.color; 9 import rip.concepts.surface; 10 import rip.concepts.channel; 11 import rip.concepts.ranges : toSurface; 12 } 13 14 struct Histogram { 15 uint[] data; 16 17 const Channel channel; 18 19 alias data this; 20 21 this(Channel channel) { 22 this.channel = channel; 23 data = new uint[channel.getRangeSize!uint()]; 24 } 25 } 26 27 Histogram takeHistogram(Range)(in Range pixelRange, Channel channel) 28 if(isPixelRange!Range) 29 { 30 auto histogram = Histogram(channel); 31 32 pixelRange 33 // .getPixels() 34 .each!( 35 (color) => histogram[ channel.getIndex(color) ]++ 36 ); 37 38 return histogram; 39 } 40 41 //std.algorithm.max не приспособлен для диапазонов 42 //TODO: убрать это отсюда. Ну позязя :p 43 T maxValue(T)(T[] args...) { 44 T max = args[0]; 45 46 foreach(value; args) { 47 if(value > max) 48 max = value; 49 } 50 51 return max; 52 } 53 54 Surface drawHistogram( Histogram histogram, 55 RGBColor background = new RGBColor(255, 255, 255), 56 RGBColor pencil = new RGBColor(0, 0, 0)) { 57 uint width = histogram.channel.getRangeSize!uint; 58 uint height = cast(uint) 59 (maxValue(histogram.data) / histogram.channel.getRangeSize!float); 60 61 auto surface = new Surface(width, height); 62 63 foreach(i; 0..width) { 64 foreach(j; 0..height) { 65 if(j <= histogram[i] / histogram.channel.getRangeSize!float()) { 66 surface[i, height - j - 1] = pencil; 67 } 68 else { 69 surface[i, height - j - 1] = background; 70 } 71 } 72 } 73 74 return surface; 75 } 76 77 auto equalizeHistogram(Histogram histogram) { 78 Histogram equalizedHistogram = histogram; 79 80 uint pixelsNumber = histogram.data.reduce!"a + b"; 81 82 auto probability = histogram 83 .data 84 .map!(( float a) => a / pixelsNumber) 85 .array; 86 87 int i = 1; 88 foreach(ref el; probability[1..$-1]) { 89 el += probability[i-1]; 90 i++; 91 } 92 93 uint size = histogram.channel.getRangeSize!uint; 94 95 equalizedHistogram = probability.map!(a => cast(uint)(a * size)).array; 96 return equalizedHistogram; 97 } 98 99 Surface appearHistogramToSurface(Histogram histogram, Surface sur) { 100 import rip.concepts; 101 102 auto channel = histogram.channel; 103 104 auto getNewColor(in RGBColor color) { 105 return channel.injectValue(color, channel.getValue(color)); 106 } 107 108 return sur 109 //функция ниже отзеркаливает картинку по диагонали 110 .createFences(1,1) 111 .map!(a => a.front) 112 .map!getNewColor 113 //функция ниже отзеркаливает картинку по диагонали 114 .toSurface(sur.getWidth!size_t, sur.getHeight!size_t); 115 }