use super::bit_depth::BitDepth;
use super::image::BitMap;
use super::info_header::InfoHeader;
use super::rgb_quad::RgbQuad;
use super::rgba::Rgba;
pub struct BitData {
width: u32,
#[allow(dead_code)]
height: u32,
colors: Vec<Rgba>,
bytes: Vec<u8>,
bit_depth: BitDepth,
}
impl BitData {
pub fn from_slice(
bit_stream: &[u8],
info: &InfoHeader,
bit_depth: BitDepth,
colors: &RgbQuad,
) -> BitData {
let mut bytes = Vec::new();
for index in 0..bit_stream.len() {
bytes.push(bit_stream[index]);
}
BitData {
width: info.get_width(),
height: info.get_height(),
bit_depth,
colors: colors.clone_colors(),
bytes,
}
}
pub fn from_bitmap(bitmap: &BitMap, bit_depth: BitDepth) -> BitData {
let unique_colors = bitmap.get_all_unique_colors().clone();
let step = bit_depth.get_step_counter();
let bit_width = bitmap.get_width() * bit_depth.get_step_counter();
let bit_padding = match bit_width % 8 {
0 => 0,
_ => 8 - (bit_width % 8),
};
let byte_width = (bit_width + bit_padding) / 8;
let byte_padding = match byte_width % 4 {
0 => 0,
_ => 4 - (byte_width % 4),
};
let mut bytes =
Vec::with_capacity(((byte_width + byte_padding) * bitmap.get_height()) as usize);
let step = step as u8;
let mut byte: u8 = 0;
let mut counter: u32 = 0;
let mut shift: u32 = 0;
for i in 0..bitmap.get_pixels().len() {
let pixel = bitmap.get_pixels()[i];
let color_index = unique_colors.iter().position(|&c| c == pixel).unwrap() as u8;
counter += step as u32;
shift = counter % 8;
if step != 8 {
byte = byte << step;
}
byte += color_index;
if shift == 0 && i != 0 && bit_width >= 8 {
bytes.push(byte);
byte = 0;
}
if counter % bit_width == 0 && i != 0 {
if bit_padding != 0 {
byte = byte << bit_padding;
bytes.push(byte);
}
byte = 0;
counter = 0;
for _ in 0..byte_padding {
bytes.push(0);
}
}
}
if shift != 0 || (bit_depth == BitDepth::Color256Bit && bitmap.get_size() == 1) {
if step != 8 {
byte = byte << (8 - shift);
}
bytes.push(byte);
}
if bytes.len() % 4 != 0 {
for _ in 0..byte_padding {
bytes.push(0);
}
}
BitData {
width: bitmap.get_width(),
height: bitmap.get_height(),
bit_depth,
colors: unique_colors,
bytes,
}
}
pub fn as_bytes(&self) -> Vec<u8> {
self.bytes.clone()
}
pub fn as_rgba(&self) -> Vec<Rgba> {
let mut pixels = Vec::new();
let step = self.bit_depth.get_step_counter();
let bit_width = self.width * self.bit_depth.get_step_counter();
let bit_padding = match bit_width % 8 {
0 => 0,
_ => 8 - (self.width % 8),
};
let byte_width = (bit_width + bit_padding) / 8;
let byte_padding = match byte_width % 4 {
0 => 0,
_ => 4 - (byte_width % 4),
};
let mut byte_padding_counter = 0;
let mut start_reading_again = false;
for byte in &self.bytes {
if byte_padding_counter > 0 {
byte_padding_counter = byte_padding_counter - 1;
continue;
}
for byte_indexes in (0..(8 / step)).rev() {
if pixels.len() as u32 % self.width == 0
&& pixels.len() != 0
&& !start_reading_again
{
break;
}
let starting_bit = byte_indexes * step;
let ending_bit = starting_bit + step;
let mut index: usize = 0;
for bit_index in (starting_bit..ending_bit).rev() {
index = index << 1;
let next_bit = (byte >> bit_index) & 1;
index = index + next_bit as usize;
}
pixels.push(self.colors[index]);
}
if start_reading_again {
start_reading_again = false;
}
if (pixels.len() as u32) % self.width == 0
&& pixels.len() != 0
&& start_reading_again == false
{
start_reading_again = true;
byte_padding_counter = byte_padding;
}
}
pixels
}
pub fn len(&self) -> usize {
self.bytes.len()
}
pub fn get_bytes_size(&self) -> u32 {
self.bytes.len() as u32
}
}
#[cfg(debug_assertions)]
impl std::fmt::Display for BitData {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
for p in (0..self.bytes.len()).rev() {
write!(f, "{}:\t{:#b}\n", p, self.bytes[p]).unwrap();
}
write!(f, "")
}
}
#[cfg(test)]
mod test {
use super::BitData;
use super::BitDepth;
use super::BitMap;
use super::Rgba;
#[test]
fn get_length_of_bit_data_length_2_bit_depth() {
let b = BitMap::new(10, 10);
let data = BitData::from_bitmap(&b, BitDepth::Color2Bit);
assert_eq!(data.len(), 43);
assert_eq!(data.get_bytes_size(), 43);
let b = BitMap::new(1, 1);
let data = BitData::from_bitmap(&b, BitDepth::Color2Bit);
assert_eq!(data.len(), 4);
assert_eq!(data.get_bytes_size(), 4);
}
#[test]
fn get_length_of_bit_data_length_16_bit_depth() {
let b = BitMap::new(10, 10);
let data = BitData::from_bitmap(&b, BitDepth::Color16Bit);
assert_eq!(data.len(), 80);
assert_eq!(data.get_bytes_size(), 80);
let b = BitMap::new(1, 1);
let data = BitData::from_bitmap(&b, BitDepth::Color16Bit);
assert_eq!(data.len(), 4);
assert_eq!(data.get_bytes_size(), 4);
}
#[test]
fn get_length_of_bit_data_length_256_bit_depth() {
let b = BitMap::new(10, 10);
let data = BitData::from_bitmap(&b, BitDepth::Color256Bit);
assert_eq!(data.len(), 121);
assert_eq!(data.get_bytes_size(), 121);
let b = BitMap::new(1, 1);
let data = BitData::from_bitmap(&b, BitDepth::Color256Bit);
assert_eq!(data.len(), 4);
assert_eq!(data.get_bytes_size(), 4);
}
#[test]
fn get_bit_data_as_rgb_bit_depth_2() {
let b = BitMap::new(10, 10);
let data = BitData::from_bitmap(&b, BitDepth::Color2Bit);
let colors = data.as_rgba();
for i in 0..b.get_size() {
assert!(&colors[i as usize] == &Rgba::white());
}
let mut b = BitMap::new(2, 1);
b.set_pixel(0, 0, Rgba::black()).unwrap();
let data = BitData::from_bitmap(&b, BitDepth::Color2Bit);
let colors = data.as_rgba();
assert!(&colors[0] == &Rgba::black());
assert!(&colors[1] == &Rgba::white());
}
#[test]
fn get_bit_data_as_rgb_bit_depth_16() {
let b = BitMap::new(10, 10);
let data = BitData::from_bitmap(&b, BitDepth::Color16Bit);
let colors = data.as_rgba();
for i in 0..b.get_size() {
assert!(&colors[i as usize] == &Rgba::white());
}
let mut b = BitMap::new(4, 1);
b.set_pixel(0, 0, Rgba::black()).unwrap();
b.set_pixel(1, 0, Rgba::rgb(255, 0, 0)).unwrap();
b.set_pixel(2, 0, Rgba::rgb(0, 0, 255)).unwrap();
let data = BitData::from_bitmap(&b, BitDepth::Color16Bit);
let colors = data.as_rgba();
assert!(&colors[0] == &Rgba::black());
assert!(&colors[1] == &Rgba::rgb(255, 0, 0));
assert!(&colors[2] == &Rgba::rgb(0, 0, 255));
assert!(&colors[3] == &Rgba::white());
}
#[test]
fn get_bit_data_as_rgb_bit_depth_256() {
let b = BitMap::new(10, 10);
let data = BitData::from_bitmap(&b, BitDepth::Color256Bit);
let colors = data.as_rgba();
for i in 0..b.get_size() {
assert!(&colors[i as usize] == &Rgba::white());
}
}
#[test]
fn get_bit_data_as_bytes() {
let b = BitMap::new(10, 10);
let data = BitData::from_bitmap(&b, BitDepth::Color2Bit);
for i in 0..data.as_bytes().len() {
assert!(data.as_bytes()[i] == 0);
}
let data = BitData::from_bitmap(&b, BitDepth::Color16Bit);
for i in 0..data.as_bytes().len() {
assert!(data.as_bytes()[i] == 0);
}
let data = BitData::from_bitmap(&b, BitDepth::Color256Bit);
for i in 0..data.as_bytes().len() {
assert!(data.as_bytes()[i] == 0);
}
}
}