rustbitmap/bitmap/
bit_data.rs

1use super::bit_depth::BitDepth;
2use super::image::BitMap;
3use super::info_header::InfoHeader;
4use super::rgb_quad::RgbQuad;
5use super::rgba::Rgba;
6
7///
8/// Used for working with binary data when the image is read in or converted to
9/// a bit map with a bit depth of 1, 4, or 8. Each byte points to a color inside
10/// of colors.
11///
12pub struct BitData {
13    /// width of the image
14    width: u32,
15    /// height of the image
16    #[allow(dead_code)]
17    height: u32,
18    /// list of colors that are used in the image
19    colors: Vec<Rgba>,
20    /// list of bytes that point to colors. Each byte could be point to 1 or
21    /// more colors, depending on the bit depth
22    bytes: Vec<u8>,
23    /// bit depth of the image
24    bit_depth: BitDepth,
25}
26
27impl BitData {
28    ///
29    /// Create bit data from from_slice of bytes
30    ///
31    pub fn from_slice(
32        bit_stream: &[u8],
33        info: &InfoHeader,
34        bit_depth: BitDepth,
35        colors: &RgbQuad,
36    ) -> BitData {
37        let mut bytes = Vec::new();
38        for index in 0..bit_stream.len() {
39            bytes.push(bit_stream[index]);
40        }
41        BitData {
42            width: info.get_width(),
43            height: info.get_height(),
44            bit_depth,
45            colors: colors.clone_colors(),
46            bytes,
47        }
48    }
49
50    ///
51    /// Create bit data from a bitmap
52    ///
53    pub fn from_bitmap(bitmap: &BitMap, bit_depth: BitDepth) -> BitData {
54        let unique_colors = bitmap.get_all_unique_colors().clone();
55        let step = bit_depth.get_step_counter();
56
57        // figure out how much padding is on each row
58        // this is needed because for each row of a bmp image needs to finish
59        // with a width of bytes that is divisible by 4. Here we are figuring out
60        // how much bit padding and byte padding we need.
61        let bit_width = bitmap.get_width() * bit_depth.get_step_counter();
62        let bit_padding = match bit_width % 8 {
63            0 => 0,
64            _ => 8 - (bit_width % 8),
65        };
66        let byte_width = (bit_width + bit_padding) / 8;
67        let byte_padding = match byte_width % 4 {
68            0 => 0,
69            _ => 4 - (byte_width % 4),
70        };
71        let mut bytes =
72            Vec::with_capacity(((byte_width + byte_padding) * bitmap.get_height()) as usize);
73
74        let step = step as u8;
75        let mut byte: u8 = 0;
76        let mut counter: u32 = 0;
77        let mut shift: u32 = 0;
78        for i in 0..bitmap.get_pixels().len() {
79            let pixel = bitmap.get_pixels()[i];
80            let color_index = unique_colors.iter().position(|&c| c == pixel).unwrap() as u8;
81            counter += step as u32;
82            shift = counter % 8;
83            if step != 8 {
84                byte = byte << step;
85            }
86            // if bit_depth is a Color2Bit then we want to push the bit onto the byte
87            byte += color_index;
88
89            // push byte into data
90            if shift == 0 && i != 0 && bit_width >= 8 {
91                bytes.push(byte);
92                byte = 0;
93            }
94            // add padding to row
95            if counter % bit_width == 0 && i != 0 {
96                if bit_padding != 0 {
97                    byte = byte << bit_padding;
98                    bytes.push(byte);
99                }
100                byte = 0;
101                counter = 0;
102
103                for _ in 0..byte_padding {
104                    bytes.push(0);
105                }
106            }
107        }
108        if shift != 0 || (bit_depth == BitDepth::Color256Bit && bitmap.get_size() == 1) {
109            if step != 8 {
110                byte = byte << (8 - shift);
111            }
112            bytes.push(byte);
113        }
114        if bytes.len() % 4 != 0 {
115            for _ in 0..byte_padding {
116                bytes.push(0);
117            }
118        }
119
120        BitData {
121            width: bitmap.get_width(),
122            height: bitmap.get_height(),
123            bit_depth,
124            colors: unique_colors,
125            bytes,
126        }
127    }
128
129    ///
130    /// Pass the bit data back as a from_slice of bytes
131    ///
132    pub fn as_bytes(&self) -> Vec<u8> {
133        self.bytes.clone()
134    }
135
136    ///
137    /// Convert bits into array of colors
138    ///
139    pub fn as_rgba(&self) -> Vec<Rgba> {
140        let mut pixels = Vec::new();
141        let step = self.bit_depth.get_step_counter();
142        // figure out how much padding is on each row
143        // this is needed because for each row of a bmp image needs to finish
144        // with a width of bytes that is divisible by 4. Here we are figuring out
145        // how much bit padding and byte padding we need.
146        // TODO: move to it's own class
147        let bit_width = self.width * self.bit_depth.get_step_counter();
148        let bit_padding = match bit_width % 8 {
149            0 => 0,
150            _ => 8 - (self.width % 8),
151        };
152        let byte_width = (bit_width + bit_padding) / 8;
153        let byte_padding = match byte_width % 4 {
154            0 => 0,
155            _ => 4 - (byte_width % 4),
156        };
157
158        // loop through all the bytes
159        let mut byte_padding_counter = 0;
160        let mut start_reading_again = false;
161        for byte in &self.bytes {
162            if byte_padding_counter > 0 {
163                byte_padding_counter = byte_padding_counter - 1;
164                continue;
165            }
166            // loop through the bits of the byte
167            for byte_indexes in (0..(8 / step)).rev() {
168                // so this works on every time after the pixels length
169                // reaches 72. We need a way to tell it that it is a new line
170                // (at lease once)
171                if pixels.len() as u32 % self.width == 0
172                    && pixels.len() != 0
173                    && !start_reading_again
174                {
175                    break;
176                }
177                // bits could be:
178                // (1) -> 0 1 2 3 4 5 6 7
179                // (4) -> 0 1
180                // (8) -> 0
181                let starting_bit = byte_indexes * step;
182                let ending_bit = starting_bit + step;
183                let mut index: usize = 0;
184                for bit_index in (starting_bit..ending_bit).rev() {
185                    index = index << 1;
186                    let next_bit = (byte >> bit_index) & 1;
187                    index = index + next_bit as usize;
188                }
189                pixels.push(self.colors[index]);
190            }
191            if start_reading_again {
192                start_reading_again = false;
193            }
194            if (pixels.len() as u32) % self.width == 0
195                && pixels.len() != 0
196                && start_reading_again == false
197            {
198                start_reading_again = true;
199                byte_padding_counter = byte_padding;
200            }
201        }
202        pixels
203    }
204
205    ///
206    /// Get the total length of bit data
207    ///
208    pub fn len(&self) -> usize {
209        self.bytes.len()
210    }
211
212    ///
213    /// Get the size of bit data in bytes
214    ///
215    pub fn get_bytes_size(&self) -> u32 {
216        self.bytes.len() as u32
217    }
218}
219
220#[cfg(debug_assertions)]
221impl std::fmt::Display for BitData {
222    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
223        for p in (0..self.bytes.len()).rev() {
224            write!(f, "{}:\t{:#b}\n", p, self.bytes[p]).unwrap();
225        }
226        write!(f, "")
227    }
228}
229
230#[cfg(test)]
231mod test {
232    use super::BitData;
233    use super::BitDepth;
234    use super::BitMap;
235    use super::Rgba;
236
237    #[test]
238    fn get_length_of_bit_data_length_2_bit_depth() {
239        let b = BitMap::new(10, 10);
240        let data = BitData::from_bitmap(&b, BitDepth::Color2Bit);
241        assert_eq!(data.len(), 43);
242        assert_eq!(data.get_bytes_size(), 43);
243        let b = BitMap::new(1, 1);
244        let data = BitData::from_bitmap(&b, BitDepth::Color2Bit);
245        assert_eq!(data.len(), 4);
246        assert_eq!(data.get_bytes_size(), 4);
247    }
248
249    #[test]
250    fn get_length_of_bit_data_length_16_bit_depth() {
251        let b = BitMap::new(10, 10);
252        let data = BitData::from_bitmap(&b, BitDepth::Color16Bit);
253        assert_eq!(data.len(), 80);
254        assert_eq!(data.get_bytes_size(), 80);
255        let b = BitMap::new(1, 1);
256        let data = BitData::from_bitmap(&b, BitDepth::Color16Bit);
257        assert_eq!(data.len(), 4);
258        assert_eq!(data.get_bytes_size(), 4);
259    }
260
261    #[test]
262    fn get_length_of_bit_data_length_256_bit_depth() {
263        let b = BitMap::new(10, 10);
264        let data = BitData::from_bitmap(&b, BitDepth::Color256Bit);
265        assert_eq!(data.len(), 121);
266        assert_eq!(data.get_bytes_size(), 121);
267        let b = BitMap::new(1, 1);
268        let data = BitData::from_bitmap(&b, BitDepth::Color256Bit);
269        assert_eq!(data.len(), 4);
270        assert_eq!(data.get_bytes_size(), 4);
271    }
272
273    #[test]
274    fn get_bit_data_as_rgb_bit_depth_2() {
275        let b = BitMap::new(10, 10);
276        let data = BitData::from_bitmap(&b, BitDepth::Color2Bit);
277        let colors = data.as_rgba();
278        for i in 0..b.get_size() {
279            assert!(&colors[i as usize] == &Rgba::white());
280        }
281
282        let mut b = BitMap::new(2, 1);
283        b.set_pixel(0, 0, Rgba::black()).unwrap();
284        let data = BitData::from_bitmap(&b, BitDepth::Color2Bit);
285        let colors = data.as_rgba();
286        assert!(&colors[0] == &Rgba::black());
287        assert!(&colors[1] == &Rgba::white());
288    }
289
290    #[test]
291    fn get_bit_data_as_rgb_bit_depth_16() {
292        let b = BitMap::new(10, 10);
293        let data = BitData::from_bitmap(&b, BitDepth::Color16Bit);
294        let colors = data.as_rgba();
295        for i in 0..b.get_size() {
296            assert!(&colors[i as usize] == &Rgba::white());
297        }
298
299        let mut b = BitMap::new(4, 1);
300        b.set_pixel(0, 0, Rgba::black()).unwrap();
301        b.set_pixel(1, 0, Rgba::rgb(255, 0, 0)).unwrap();
302        b.set_pixel(2, 0, Rgba::rgb(0, 0, 255)).unwrap();
303        let data = BitData::from_bitmap(&b, BitDepth::Color16Bit);
304        let colors = data.as_rgba();
305        assert!(&colors[0] == &Rgba::black());
306        assert!(&colors[1] == &Rgba::rgb(255, 0, 0));
307        assert!(&colors[2] == &Rgba::rgb(0, 0, 255));
308        assert!(&colors[3] == &Rgba::white());
309    }
310
311    #[test]
312    fn get_bit_data_as_rgb_bit_depth_256() {
313        let b = BitMap::new(10, 10);
314        let data = BitData::from_bitmap(&b, BitDepth::Color256Bit);
315        let colors = data.as_rgba();
316        for i in 0..b.get_size() {
317            assert!(&colors[i as usize] == &Rgba::white());
318        }
319    }
320
321    #[test]
322    fn get_bit_data_as_bytes() {
323        let b = BitMap::new(10, 10);
324
325        let data = BitData::from_bitmap(&b, BitDepth::Color2Bit);
326        for i in 0..data.as_bytes().len() {
327            assert!(data.as_bytes()[i] == 0);
328        }
329        let data = BitData::from_bitmap(&b, BitDepth::Color16Bit);
330        for i in 0..data.as_bytes().len() {
331            assert!(data.as_bytes()[i] == 0);
332        }
333        let data = BitData::from_bitmap(&b, BitDepth::Color256Bit);
334        for i in 0..data.as_bytes().len() {
335            assert!(data.as_bytes()[i] == 0);
336        }
337    }
338}