1 module rip.processing.bitPlane;
2 
3 private {
4     import std.algorithm;
5     import std.stdio;
6 
7     import rip.concepts;
8     import rip.concepts.channel;
9 }
10 
11 pure T getBitMask(T)(ubyte bitIndex) {
12     //Берём еденицу и сдвигаем её на bitIndex бит влево
13     //получаем 2 в степени bitIndex
14     return cast(T) (1 << bitIndex);
15 }
16 
17 pure T getInvertBitMask(T) (ubyte bitIndex) {
18     return ~getBitMask!(T) (bitIndex);
19 }
20 
21 bool getBit(T) (T value, ubyte index) {
22     return cast(bool)(value & getBitMask!T(index));
23 }
24 
25 auto generateBitRange(Range) (Range pixels, Channel channel, ubyte bitIndex)
26     if(isPixelRange!Range)
27 {
28     auto range = pixels
29         .map!((a) => channel.getValue(a).getBit(bitIndex));
30 
31     return range;
32 }
33 
34 auto generateBitRange(Surface surface, Channel channel, ubyte index) {
35     return surface
36         //FIXME: Не работает через createFences
37         .getPixelsRange
38         .generateBitRange(channel, index);
39 }
40 
41 auto drawBitRange(BitRange)(BitRange range) {
42     return range
43         .map!(a => a ? new RGBColor(255, 255, 255) : new RGBColor(0, 0, 0));
44 }
45 
46 enum BitOperation {
47     AND = "&",
48     OR = "|",
49     NOT = "~",
50     XOR = "^"
51 }
52 
53 auto cutBitPlane(Range) (Range range, Channel channel, ubyte bitIndex)
54     if(isPixelRange!Range)
55 {
56     ubyte mask = getInvertBitMask!ubyte(bitIndex);
57 
58 	auto appMask(in RGBColor color) {
59         ubyte value = cast(ubyte)channel.getValue(color);
60         ubyte newValue = value & mask;
61 
62         return channel.injectValue(color, newValue);
63     }
64 
65     auto newRange = range
66         .map!appMask;
67 
68     return newRange;
69 }
70 
71 auto injectBitPlane(BitRange, PixelRange) (PixelRange pixels, BitRange bits,
72                     Channel channel, ubyte bitIndex)
73     if(isPixelRange!PixelRange)
74 {
75 
76     auto appMask(T)(T pair) {
77 
78         auto color = pair[1];
79         ubyte channelValue = cast(ubyte)channel.getValue(color);
80 
81         ubyte mask;
82         ubyte newValue;
83         bool _bit = pair[0];
84 
85         if(_bit == true) {
86             mask = getBitMask!ubyte(bitIndex);
87             newValue = channelValue | mask;
88         }
89         else {
90             mask = getInvertBitMask!ubyte(bitIndex);
91             newValue = channelValue & mask;
92         }
93 
94         return channel.injectValue(color, newValue);
95     }
96 
97     return zip(bits, pixels).map!appMask;
98 }
99 
100 auto processBitPlane(BitOperation op, Range1, Range2)
101     (Range1 range1, Range2 range2) {
102 
103     mixin(
104         "return zip(range1, range2)
105             .map!((pair) => pair[0] " ~ op ~" pair[1]);"
106     );
107 }