1use std::fs;
2use std::convert::TryInto;
3use std::collections::VecDeque;
4use std::fmt;
5use std::collections::HashMap;
6use std::io::Write;
7use std::f64::consts::PI;
8const HEADER_OFFSET: usize = 14;
20
21#[derive(PartialEq)]
23pub enum ErrorKind {
24  NotFound,
25  OutOfBounds,
26  Unsupported,
27  DoesNotExist,
28  WrongFileType,
29  UseExtraBitMasks,
30  FailedToWrite,
31  Missing,
32  InvalidParameter(String)
33}
34
35impl ErrorKind {
36  fn get_text(&self) -> String {
37    match &*self {
38      ErrorKind::NotFound => "File not found".to_string(),
39      ErrorKind::OutOfBounds => "x or y coord exceeds width or height of image".to_string(),
40      ErrorKind::Unsupported => "File is unsupported".to_string(),
41      ErrorKind::DoesNotExist => "Requested object does not exist".to_string(),
42      ErrorKind::WrongFileType => "Wrong file type. Must be a .bmp file".to_string(),
43      ErrorKind::UseExtraBitMasks => "Use extra bit masks instead".to_string(),
44      ErrorKind::FailedToWrite => "Failed to write to file".to_string(),
45      ErrorKind::Missing => "Missing expected parameter or object".to_string(),
46      ErrorKind::InvalidParameter(reason) => "Invalid Parameter: ".to_owned()+reason,
47    }
48  }
49}
50
51impl fmt::Debug for ErrorKind {
52  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
53    write!(f, "{:?}", self.get_text())
54  }
55}
56
57impl fmt::Display for ErrorKind {
58  fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
59    write!(f, "Error: {}", self.get_text())
60  }
61}
62
63pub enum RGBAChannel {
65  Red,
66  Green,
67  Blue,
68  Alpha,
69}
70
71#[derive(Debug)]
73pub struct PixelDiff {
74  pub coord: [u16; 2],
75  pub color1: Option<[u8; 4]>,
76  pub color2: Option<[u8; 4]>,
77}
78
79#[derive(Debug)]
81pub struct ImageDiff {
82  pub image1_size: [u32; 2],
83  pub image2_size: [u32; 2],
84  pub diff: Vec<PixelDiff>,
85}
86
87impl IntoIterator for ImageDiff {
88  type Item = PixelDiff;
89  type IntoIter = std::vec::IntoIter<Self::Item>;
90
91  fn into_iter(self) -> Self::IntoIter {
92    self.diff.into_iter()
93  }
94}
95
96impl std::ops::Index<usize> for ImageDiff {
97  type Output = PixelDiff;
98
99  fn index(&self, index: usize) -> &Self::Output {
100    &self.diff[index]
101  }
102}
103
104impl ImageDiff {
105  pub fn is_same_size(&self) -> bool {
106    if self.image1_size == self.image2_size {
107      true
108    } else {
109      false
110    }
111  }
112}
113
114#[allow(non_snake_case)]
117#[derive(Clone)]
118pub struct BITMAPFILEHEADER {
119  pub bfType: String,
120  pub bfSize: u32,
121  pub bfReserved1: Vec<u8>,
122  pub bfReserved2: Vec<u8>,
123  pub bfOffBits: u32,
124}
125
126impl IntoIterator for BITMAPFILEHEADER {
127  type Item = u8;
128  type IntoIter = std::array::IntoIter<u8, 14>;
129
130  fn into_iter(self) -> Self::IntoIter {
131    let bytes_vec = [self.bfType.as_bytes(), &self.bfSize.to_le_bytes(), &BMP::vec_to_2u8_array(self.bfReserved1), &BMP::vec_to_2u8_array(self.bfReserved2), &self.bfOffBits.to_le_bytes()].concat();
132    let mut bytes_array: [u8; 14] = [0u8; 14];
133    for i in 0..bytes_vec.len() {
135      bytes_array[i] = bytes_vec[i];
136    }
137    return IntoIterator::into_iter(bytes_array);
140  }
141}
142
143#[allow(non_snake_case)]
237#[derive(Clone)]
238pub struct DIBHEADER {
239  pub size: u32,
240  pub width: u32,
241  pub height: i32,
242  pub planes: u16,
243  pub bitcount: u16,
244  pub compression: Option<String>,
245  pub sizeimage: Option<u32>,
246  pub XPelsPerMeter: Option<u32>,
247  pub YPelsPerMeter: Option<u32>,
248  pub ClrUsed: Option<u32>,
249  pub ClrImportant: Option<u32>,
250  pub RedMask: Option<u32>,
251  pub GreenMask: Option<u32>,
252  pub BlueMask: Option<u32>,
253  pub AlphaMask: Option<u32>,
254  pub CSType: Option<String>,
255  pub Endpoints: Option<[[i32; 3]; 3]>,
256  pub GammaRed: Option<u32>,
257  pub GammaGreen: Option<u32>,
258  pub GammaBlue: Option<u32>,
259  pub Intent: Option<String>,
260  pub ProfileData: Option<u16>,
261  pub ProfileSize: Option<u16>,
262  pub Reserved: Option<Vec<u8>>,
263}
264
265impl IntoIterator for DIBHEADER {
267  type Item = u8;
269  type IntoIter = std::array::IntoIter<u8, 124>;
270
271  fn into_iter(self) -> Self::IntoIter {
272    let mut bytes_vec = [&self.size.to_le_bytes()[..], &self.width.to_le_bytes(), &self.height.to_le_bytes(), &self.planes.to_le_bytes(), &self.bitcount.to_le_bytes()].concat();
274    if self.size > 12 {
275      let compression_table: HashMap<String, u32> = HashMap::from([
276        ("BI_RGB".to_string(), 0),
277        ("BI_RLE8".to_string(), 1),
278        ("BI_RLE4".to_string(), 2),
279        ("BI_BITFIELDS".to_string(), 3),
280        ("BI_JPEG".to_string(), 4),
281        ("BI_PNG".to_string(), 5),
282        ("BI_ALPHABITFIELDS".to_string(), 6)
283      ]);
284      let compression: u32 = *compression_table.get(&self.compression.unwrap()).unwrap();
285      bytes_vec.append(&mut [&compression.to_le_bytes()[..], &self.sizeimage.unwrap().to_le_bytes(), &self.XPelsPerMeter.unwrap().to_le_bytes(), &self.YPelsPerMeter.unwrap().to_le_bytes(), &self.ClrUsed.unwrap().to_le_bytes(), &self.ClrImportant.unwrap().to_le_bytes()].concat());
286    }
287    if self.size > 40 {
288      let mut endpoints_l: [u8; 36] = [0u8; 36];
289      let endpoints = self.Endpoints.unwrap();
290      for i in 0..3 {
292        for ii in 0..3 {
293          endpoints_l[(i*3+ii*4) as usize] = endpoints[i as usize][ii as usize].to_le_bytes()[0];
295          endpoints_l[(i*3+ii*4+1) as usize] = endpoints[i as usize][ii as usize].to_le_bytes()[1];
296          endpoints_l[(i*3+ii*4+2) as usize] = endpoints[i as usize][ii as usize].to_le_bytes()[2];
297          endpoints_l[(i*3+ii*4+3) as usize] = endpoints[i as usize][ii as usize].to_le_bytes()[3];
298        }
299      }
300      bytes_vec.append(&mut [&self.RedMask.unwrap().to_le_bytes(), &self.GreenMask.unwrap().to_le_bytes(), &self.BlueMask.unwrap().to_le_bytes(), &self.AlphaMask.unwrap().to_le_bytes(), self.CSType.unwrap().as_bytes(), &endpoints_l[..], &self.GammaRed.unwrap().to_le_bytes(), &self.GammaGreen.unwrap().to_le_bytes(), &self.GammaBlue.unwrap().to_le_bytes()].concat());
303    }
304    if self.size > 108 {
305      let mut reserved_l: [u8; 4] = [0u8; 4];
307      let reserved = self.Reserved.unwrap();
308      for i in 0..4 {
309        reserved_l[i as usize] = reserved[i as usize];
310      }
311      let intent_table: HashMap<String, u32> = HashMap::from([
313        ("LCS_GM_ABS_COLORIMETRIC".to_string(), 0),
314        ("LCS_GM_BUSINESS".to_string(), 1),
315        ("LCS_WINDOWS_COLOR_SPACE".to_string(), 2),
316        ("LCS_GM_GRAPHICS".to_string(), 3),
317        ("LCS_GM_IMAGES".to_string(), 4)
318      ]);
319      let intent: u32 = *intent_table.get(&self.Intent.unwrap()).unwrap();
320      bytes_vec.append(&mut [&intent.to_le_bytes()[..], &self.ProfileData.unwrap().to_le_bytes(), &self.ProfileSize.unwrap().to_le_bytes(), &reserved_l[..]].concat());
321    }
322    let mut bytes_array: [u8; 124] = [0u8; 124];
323    for i in 0..bytes_vec.len() {
325      bytes_array[i] = bytes_vec[i];
326    }
327    return IntoIterator::into_iter(bytes_array);
330  }
331}
332  
333pub enum ColorTable {
336  RGBTRIPLE(Vec<[u8; 3]>),
337  RGBQUAD(Vec<[u8; 4]>),
338}
339
340#[allow(non_camel_case_types)]
342pub struct BI_BITFIELDS_MASKS {
343  pub red: u32,
344  pub green: u32,
345  pub blue: u32,
346}
347
348#[allow(non_camel_case_types)]
349pub struct BI_ALPHABITFIELDS_MASKS {
350  pub red: u32,
351  pub green: u32,
352  pub blue: u32,
353  pub alpha: u32,
354}
355
356#[allow(non_camel_case_types)]
357enum EXTRA_BIT_MASKS {
358  BI_BITFIELDS_MASKS(BI_BITFIELDS_MASKS),
359  BI_ALPHABITFIELDS_MASKS(BI_ALPHABITFIELDS_MASKS),
360}
361
362pub struct BMP {
367  pub contents: Vec<u8>,
368  from_file: bool,
369  }
372
373impl PartialEq for BMP {
374  fn eq(&self, other: &BMP) -> bool {
375    self.contents == other.contents
376  }
377}
378
379impl Clone for BMP {
380  fn clone(&self) -> BMP {
381    let mut clone_bmp = BMP::new(1, 1, None);
382    clone_bmp.contents = self.contents.to_vec();
383    return clone_bmp;
384  }
385}
386
387impl BMP {
388  pub fn new(height: i32, width: u32, default_color: Option<[u8; 4]>) -> BMP {
390    let mut contents = Vec::new();
391    let offset: u32 = 14+124;
393    let size: u32 = offset+(height.abs() as u32 * width)*4;
394    let file_header = BITMAPFILEHEADER {
395      bfType: "BM".to_string(),
396      bfSize: size,
397      bfReserved1: vec![0, 0],
398      bfReserved2: vec![0, 0],
399      bfOffBits: offset,
400    };
401    contents.extend(file_header);
403    let dib_header = DIBHEADER {
405      size: 124,
406      width: width,
407      height: height,
408      planes: 1,
409      bitcount: 32,
410      compression: Some("BI_BITFIELDS".to_string()),
411      sizeimage: Some(size),
412      XPelsPerMeter: Some(3780),
414      YPelsPerMeter: Some(3780),
415      ClrUsed: Some(0),
417      ClrImportant: Some(0),
418      RedMask: Some(16711680),
420      GreenMask: Some(65280),
421      BlueMask: Some(255),
422      AlphaMask: Some(4278190080),
423      CSType: Some("BGRs".to_string()),
425      Endpoints: Some([[687194752, 354334816, 32212256], [322122560, 644245120, 107374144], [161061280, 64424508, 848256036]]),
427      GammaRed: Some(0),
428      GammaGreen: Some(0),
429      GammaBlue: Some(0),
430      Intent: Some("LCS_GM_IMAGES".to_string()),
431      ProfileData: Some(0),
432      ProfileSize: Some(0),
433      Reserved: Some(vec![0, 0, 0, 0]),
434    };
435    contents.extend(dib_header);
436    for _pixel_num in 0..(width*height as u32) {
439      if default_color.is_some() {
441        let mut bgr_default_color = default_color.unwrap().clone();
443        bgr_default_color[0] = default_color.unwrap()[2];
444        bgr_default_color[2] = default_color.unwrap()[0];
445        contents.extend(bgr_default_color);
446      } else {
447        contents.extend([255, 255, 255, 255]);
448      }
449    }
450    return BMP { contents: contents, from_file: false };
452  }
453  pub fn new_from_file(file_path: &str) -> Result<BMP, ErrorKind> {
455    let contents = fs::read(file_path).map_err(|_| ErrorKind::NotFound)?;
456    Ok(BMP { contents: contents, from_file: true })
457  }
458  fn bytes_to_int(bytes: [u8; 4]) -> u32 {
460    u32::from_le_bytes(bytes)
461  }
462  fn two_bytes_to_int(bytes: [u8; 2]) -> u16 {
463    u16::from_le_bytes(bytes)
464  }
465  fn byte_to_int(byte: u8) -> u8 {
466    u8::from_le_bytes([byte])
467  }
468  fn two_bytes_to_signed_int(bytes: [u8; 2]) -> i16 {
469    i16::from_le_bytes(bytes)
470  }
471  fn bytes_to_signed_int(bytes: [u8; 4]) -> i32 {
472    i32::from_le_bytes(bytes)
473  }
474  fn bytes_to_string(bytes: &[u8]) -> String {
475    String::from_utf8_lossy(&bytes).to_string()
476  }
477  pub fn num_bytes_to_kilobytes(bytes: u32) -> u32 {
479    bytes/1024
481  }
482  fn vec_to_4u8_array(vector: Vec<u8>) -> [u8; 4] {
483    let mut array: [u8; 4] = [0u8; 4];
484    for i in 0..vector.len() {
486      array[i] = vector[i];
487    }
488    return array;
489  }
490  fn vec_to_2u8_array(vector: Vec<u8>) -> [u8; 2] {
491    let mut array: [u8; 2] = [0u8; 2];
492    for i in 0..vector.len() {
494      array[i] = vector[i];
495    }
496    return array;
497  }
498  fn vec_to_1u8_array(vector: Vec<u8>) -> [u8; 1] {
499    let mut array: [u8; 1] = [0u8; 1];
500    for i in 0..vector.len() {
502      array[i] = vector[i];
503    }
504    return array;
505  }
506  fn int_to_compression(int: u32) -> String {
507    let compression_table: HashMap<u32, String> = HashMap::from([
508      (0, "BI_RGB".to_string()),
509      (1, "BI_RLE8".to_string()),
510      (2, "BI_RLE4".to_string()),
511      (3, "BI_BITFIELDS".to_string()),
512      (4, "BI_JPEG".to_string()),
513      (5, "BI_PNG".to_string()),
514      (6, "BI_ALPHABITFIELDS".to_string())
515    ]);
516    return compression_table.get(&int).unwrap().to_string();
517  }
518  fn int_to_intent(int: u32) -> String {
519    let intent_table: HashMap<u32, String> = HashMap::from([
520      (0, "LCS_GM_ABS_COLORIMETRIC".to_string()),
521      (1, "LCS_GM_BUSINESS".to_string()),
522      (2, "LCS_WINDOWS_COLOR_SPACE".to_string()),
523      (3, "LCS_GM_GRAPHICS".to_string()),
524      (4, "LCS_GM_IMAGES".to_string())
525    ]);
526    return intent_table.get(&int).unwrap().to_string();
527  }
528  fn deg_to_rad(deg: f64) -> f64 {
530    return deg/180.0*PI;
531  }
532  fn rotate_point(rad: f64, point: [u16; 2], center: [u16; 2]) -> (i32, i32) {
533    let x2: i32 = ((f64::from(point[0])-f64::from(center[0])) * rad.cos() - (f64::from(point[1])-f64::from(center[1])) * rad.sin()).round() as i32 + i32::from(center[0]);
535    let y2: i32 = ((f64::from(point[1])-f64::from(center[1])) * rad.cos() + (f64::from(point[0])-f64::from(center[0])) * rad.sin()).round() as i32 + i32::from(center[1]);
537    return (x2, y2);
538  }
539  pub fn point_in_enclosure(point: [u16; 2], enclosure: &Vec<[u16; 2]>) -> bool {
541    if enclosure.contains(&point) {
544      return false;
545    }
546    let same_y_count_right = enclosure.into_iter().filter(|item| {
548      item[1] == point[1] && item[0] > point[0]
549    }).count();
550    return same_y_count_right % 2 == 1;
552  }
553  fn alpha_to_percentage(alpha: u8) -> f64 {
555    return (f64::from(alpha)/255.0).into();
557  }
558  fn percentage_to_alpha(percentage: f64) -> u8 {
559    return (percentage * 255.0).round() as u8;
560  }
561  pub fn rgba_to_hex(rgba: [u8; 4]) -> String {
611    let hex_chars: [char; 16] = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'];
612    let mut hex: String = String::new();
613    for i in 0..rgba.len() {
615      let num = rgba[i];
616      hex += &hex_chars[(f64::from(num) / 16.0).floor() as usize].to_string();
617      hex += &hex_chars[(num % 16) as usize].to_string();
618    }
619    return hex;
620  }
621  pub fn hex_to_rgba(hex: String) -> [u8; 4] {
623    let hex_chars: [char; 16] = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'];
624    let mut rgba: [u8; 4] = [0; 4];
625    let mut current_num: u8 = 0;
626    for (i, c) in hex.chars().enumerate() {
627      if i%2 == 0 {
628        current_num += 16*hex_chars.iter().position(|c_h| c_h == &c).unwrap() as u8;
629      } else {
630        current_num += hex_chars.iter().position(|c_h| c_h == &c).unwrap() as u8;
631        rgba[(i as f64 / 2.0).floor() as usize] = current_num;
632        current_num = 0;
633      }
634    }
635    return rgba;
636  }
637  pub fn hsl_to_rgb(hsl: [f64; 3]) -> Result<[u8; 3], ErrorKind> {
639    let hue = hsl[0];
641    let sat = hsl[1];
642    let lig = hsl[2];
643    if hue > 360.0 || hue < 0.0 {
644      return Err(ErrorKind::InvalidParameter("Hue cannot be greater than 360 or less than 0".to_string()));
645    } else if sat > 1.0 || sat < 0.0 {
646      return Err(ErrorKind::InvalidParameter("Saturation cannot be greater than 1 or less than 0".to_string()));
647    } else if lig > 1.0 || lig < 0.0 {
648      return Err(ErrorKind::InvalidParameter("Lightness cannot be greater than 1 or less than 0".to_string()));
649    }
650    let chroma: f64 = (1.0 - (2.0 * lig - 1.0).abs()) * sat;
652    let hprime: f64 = hue / 60.0;
654    let x: f64 = chroma * (1.0 - (hprime % 2.0 - 1.0).abs());
656    let color1: [f64; 3];
657    if hprime < 1.0 {
658      color1 = [chroma, x, 0.0];
660    } else if hprime < 2.0 {
661      color1 = [x, chroma, 0.0];
663    } else if hprime < 3.0 {
664      color1 = [0.0, chroma, x];
666    } else if hprime < 4.0 {
667      color1 = [0.0, x, chroma];
669    } else if hprime < 5.0 {
670      color1 = [x, 0.0, chroma];
672    } else {
673      color1 = [chroma, 0.0, x];
676    }
677    let m: f64 = lig - chroma / 2.0;
679    let rgb_color: [u8; 3] = [(255.0 * (color1[0] + m)).round() as u8, (255.0 * (color1[1] + m)).round() as u8, (255.0 * (color1[2] + m)).round() as u8];
680    return Ok(rgb_color);
681  }
682  pub fn composite_colors(color1: [u8; 4], color2: [u8; 4]) -> [u8; 4] {
683    let a1 = BMP::alpha_to_percentage(color1[3]);
685    let a2 = BMP::alpha_to_percentage(color2[3]);
686    let a0 = a1+a2*(1.0 - a1);
688    let c0_0: f64 = (f64::from(color1[0])*a1 + f64::from(color2[0])*a2*(1.0-a1))/a0;
690    let c0_1: f64 = (f64::from(color1[1])*a1 + f64::from(color2[1])*a2*(1.0-a1))/a0;
691    let c0_2: f64 = (f64::from(color1[2])*a1 + f64::from(color2[2])*a2*(1.0-a1))/a0;
692    return [c0_0.round() as u8, c0_1.round() as u8, c0_2.round() as u8, BMP::percentage_to_alpha(a0)];
693  }
694  pub fn rgb_to_grayscale(rgba: [u8; 4]) -> [u8; 4] {
695    let gray: u8 = (0.2126*f64::from(rgba[0]) + 0.7152*f64::from(rgba[1]) + 0.0722*f64::from(rgba[2])).round() as u8;
698    return [gray, gray, gray, rgba[3]];
699  }
700  fn get_header_bytes(&self) -> &[u8; 14] {
702    self.contents[..14].try_into().unwrap()
704  }
705  pub fn get_header(&self) -> BITMAPFILEHEADER {
707    let header_bytes: &[u8; 14] = self.get_header_bytes();
708    return BITMAPFILEHEADER {
709      bfType: BMP::bytes_to_string(&header_bytes[..2]),
710      bfSize: BMP::bytes_to_int(header_bytes[2..6].try_into().unwrap()),
711      bfReserved1: header_bytes[6..8].try_into().unwrap(),
712      bfReserved2: header_bytes[8..10].try_into().unwrap(),
713      bfOffBits: BMP::bytes_to_int(header_bytes[10..14].try_into().unwrap()),
714    };
715  }
716  pub fn get_offset(&self) -> u32 {
718    self.get_header().bfOffBits
719  }
720  pub fn get_size(&self, use_header: bool) -> u32 {
722    if use_header {
723      return self.get_header().bfSize;
724    } else {
725      return self.contents.len().try_into().unwrap();
726    }
727  }
728  pub fn diff(bmp1: &BMP, bmp2: &BMP) -> Result<ImageDiff, ErrorKind> {
731    let dib_header1 = bmp1.get_dib_header();
734    let dib_header1 = match dib_header1 {
735      Ok(returned_dib_header) => returned_dib_header,
736      Err(e) => return Err(e),
737    };
738    let dib_header2 = bmp2.get_dib_header();
739    let dib_header2 = match dib_header2 {
740      Ok(returned_dib_header) => returned_dib_header,
741      Err(e) => return Err(e),
742    };
743    let pixel_data1 = bmp1.get_pixel_data();
744    let pixel_data1 = match pixel_data1 {
745      Ok(returned_pixel_data) => returned_pixel_data,
746      Err(e) => return Err(e),
747    };
748    let pixel_data2 = bmp2.get_pixel_data();
749    let pixel_data2 = match pixel_data2 {
750      Ok(returned_pixel_data) => returned_pixel_data,
751      Err(e) => return Err(e),
752    };
753    let largest_height: u32;
754    if dib_header1.height.abs() > dib_header2.height.abs() {
755      largest_height = dib_header1.height.abs() as u32;
756    } else {
757      largest_height = dib_header2.height.abs() as u32;
760    }
761    let largest_width: u32;
762    if dib_header1.width > dib_header2.width {
763      largest_width = dib_header1.width;
764    } else {
765      largest_width = dib_header2.width;
766    }
767    let mut diff_pixels: Vec<PixelDiff> = Vec::new();
769    for y in 0..largest_height {
770      for x in 0..largest_width {
771        let color1: Option<[u8; 4]>;
772        let color2: Option<[u8; 4]>;
773        if x >= dib_header1.width || y >= dib_header1.height.abs() as u32 {
774          color1 = None;
775        } else {
776          color1 = Some(bmp1.get_color_of_px_efficient(x as usize, y as usize, &dib_header1, &pixel_data1).unwrap());
777        }
778        if x >= dib_header2.width || y >= dib_header2.height.abs() as u32 {
779          color2 = None;
780        } else {
781          color2 = Some(bmp2.get_color_of_px_efficient(x as usize, y as usize, &dib_header2, &pixel_data2).unwrap());
782        }
783        if color1 != color2 {
784          diff_pixels.push(PixelDiff {
785            coord: [x as u16, y as u16],
786            color1,
787            color2,
788          });
789        }
790      }
791    }
792    return Ok(ImageDiff {
793      image1_size: [dib_header1.width, dib_header1.height.abs() as u32],
794      image2_size: [dib_header2.width, dib_header2.height.abs() as u32],
795      diff: diff_pixels,
796    });
797  }
798  pub fn is_from_file(&self) -> bool {
801    self.from_file
802  }
803  pub fn get_dib_header(&self) -> Result<DIBHEADER, ErrorKind> {
809    let dib_size: u32 = BMP::bytes_to_int(self.contents[HEADER_OFFSET..HEADER_OFFSET+4].try_into().unwrap());
813    let dib_header: DIBHEADER;
814    match dib_size {
815      12 => {
816        dib_header = DIBHEADER {
818          size: dib_size,
819          width: u32::from(BMP::two_bytes_to_int(self.contents[HEADER_OFFSET+4..HEADER_OFFSET+6].try_into().unwrap())),
820          height: i32::from(BMP::two_bytes_to_signed_int(self.contents[HEADER_OFFSET+6..HEADER_OFFSET+8].try_into().unwrap())),
821          planes: BMP::two_bytes_to_int(self.contents[HEADER_OFFSET+8..HEADER_OFFSET+10].try_into().unwrap()),
822          bitcount: BMP::two_bytes_to_int(self.contents[HEADER_OFFSET+10..HEADER_OFFSET+12].try_into().unwrap()),
823          compression: None,
824          sizeimage: None,
825          XPelsPerMeter: None,
826          YPelsPerMeter: None,
827          ClrUsed: None,
828          ClrImportant: None,
829          RedMask: None,
830          GreenMask: None,
831          BlueMask: None,
832          AlphaMask: None,
833          CSType: None,
834          Endpoints: None,
835          GammaRed: None,
836          GammaGreen: None,
837          GammaBlue: None,
838          Intent: None,
839          ProfileData: None,
840          ProfileSize: None,
841          Reserved: None,
842        };
843      },
844      40 => {
845        dib_header = DIBHEADER {
847          size: dib_size,
848          width: BMP::bytes_to_int(self.contents[HEADER_OFFSET+4..HEADER_OFFSET+8].try_into().unwrap()),
849          height: BMP::bytes_to_signed_int(self.contents[HEADER_OFFSET+8..HEADER_OFFSET+12].try_into().unwrap()),
850          planes: BMP::two_bytes_to_int(self.contents[HEADER_OFFSET+12..HEADER_OFFSET+14].try_into().unwrap()),
851          bitcount: BMP::two_bytes_to_int(self.contents[HEADER_OFFSET+14..HEADER_OFFSET+16].try_into().unwrap()),
852          compression: Some(BMP::int_to_compression(BMP::bytes_to_int(self.contents[HEADER_OFFSET+16..HEADER_OFFSET+20].try_into().unwrap()))),
853          sizeimage: Some(BMP::bytes_to_int(self.contents[HEADER_OFFSET+20..HEADER_OFFSET+24].try_into().unwrap())),
854          XPelsPerMeter: Some(BMP::bytes_to_int(self.contents[HEADER_OFFSET+24..HEADER_OFFSET+28].try_into().unwrap())),
855          YPelsPerMeter: Some(BMP::bytes_to_int(self.contents[HEADER_OFFSET+28..HEADER_OFFSET+32].try_into().unwrap())),
856          ClrUsed: Some(BMP::bytes_to_int(self.contents[HEADER_OFFSET+32..HEADER_OFFSET+36].try_into().unwrap())),
857          ClrImportant: Some(BMP::bytes_to_int(self.contents[HEADER_OFFSET+36..HEADER_OFFSET+40].try_into().unwrap())),
858          RedMask: None,
859          GreenMask: None,
860          BlueMask: None,
861          AlphaMask: None,
862          CSType: None,
863          Endpoints: None,
864          GammaRed: None,
865          GammaGreen: None,
866          GammaBlue: None,
867          Intent: None,
868          ProfileData: None,
869          ProfileSize: None,
870          Reserved: None,
871        };
872      },
873      108 => {
874        dib_header = DIBHEADER {
876          size: dib_size,
877          width: BMP::bytes_to_int(self.contents[HEADER_OFFSET+4..HEADER_OFFSET+8].try_into().unwrap()),
878          height: BMP::bytes_to_signed_int(self.contents[HEADER_OFFSET+8..HEADER_OFFSET+12].try_into().unwrap()),
879          planes: BMP::two_bytes_to_int(self.contents[HEADER_OFFSET+12..HEADER_OFFSET+14].try_into().unwrap()),
880          bitcount: BMP::two_bytes_to_int(self.contents[HEADER_OFFSET+14..HEADER_OFFSET+16].try_into().unwrap()),
881          compression: Some(BMP::int_to_compression(BMP::bytes_to_int(self.contents[HEADER_OFFSET+16..HEADER_OFFSET+20].try_into().unwrap()))),
882          sizeimage: Some(BMP::bytes_to_int(self.contents[HEADER_OFFSET+20..HEADER_OFFSET+24].try_into().unwrap())),
883          XPelsPerMeter: Some(BMP::bytes_to_int(self.contents[HEADER_OFFSET+24..HEADER_OFFSET+28].try_into().unwrap())),
884          YPelsPerMeter: Some(BMP::bytes_to_int(self.contents[HEADER_OFFSET+28..HEADER_OFFSET+32].try_into().unwrap())),
885          ClrUsed: Some(BMP::bytes_to_int(self.contents[HEADER_OFFSET+32..HEADER_OFFSET+36].try_into().unwrap())),
886          ClrImportant: Some(BMP::bytes_to_int(self.contents[HEADER_OFFSET+36..HEADER_OFFSET+40].try_into().unwrap())),
887          RedMask: Some(BMP::bytes_to_int(self.contents[HEADER_OFFSET+40..HEADER_OFFSET+44].try_into().unwrap())),
888          GreenMask: Some(BMP::bytes_to_int(self.contents[HEADER_OFFSET+44..HEADER_OFFSET+48].try_into().unwrap())),
889          BlueMask: Some(BMP::bytes_to_int(self.contents[HEADER_OFFSET+48..HEADER_OFFSET+52].try_into().unwrap())),
890          AlphaMask: Some(BMP::bytes_to_int(self.contents[HEADER_OFFSET+52..HEADER_OFFSET+56].try_into().unwrap())),
891          CSType: Some(BMP::bytes_to_string(&self.contents[HEADER_OFFSET+56..HEADER_OFFSET+60])),
892          Endpoints: Some([[BMP::bytes_to_signed_int(self.contents[HEADER_OFFSET+60..HEADER_OFFSET+64].try_into().unwrap()), BMP::bytes_to_signed_int(self.contents[HEADER_OFFSET+64..HEADER_OFFSET+68].try_into().unwrap()), BMP::bytes_to_signed_int(self.contents[HEADER_OFFSET+68..HEADER_OFFSET+72].try_into().unwrap())], [BMP::bytes_to_signed_int(self.contents[HEADER_OFFSET+72..HEADER_OFFSET+76].try_into().unwrap()), BMP::bytes_to_signed_int(self.contents[HEADER_OFFSET+76..HEADER_OFFSET+80].try_into().unwrap()), BMP::bytes_to_signed_int(self.contents[HEADER_OFFSET+80..HEADER_OFFSET+84].try_into().unwrap())], [BMP::bytes_to_signed_int(self.contents[HEADER_OFFSET+84..HEADER_OFFSET+88].try_into().unwrap()), BMP::bytes_to_signed_int(self.contents[HEADER_OFFSET+88..HEADER_OFFSET+92].try_into().unwrap()), BMP::bytes_to_signed_int(self.contents[HEADER_OFFSET+92..HEADER_OFFSET+96].try_into().unwrap())]]),
894          GammaRed: Some(BMP::bytes_to_int(self.contents[HEADER_OFFSET+96..HEADER_OFFSET+100].try_into().unwrap())),
895          GammaGreen: Some(BMP::bytes_to_int(self.contents[HEADER_OFFSET+100..HEADER_OFFSET+104].try_into().unwrap())),
896          GammaBlue: Some(BMP::bytes_to_int(self.contents[HEADER_OFFSET+104..HEADER_OFFSET+108].try_into().unwrap())),
897          Intent: None,
898          ProfileData: None,
899          ProfileSize: None,
900          Reserved: None,
901        };
902      },
903      124 => {
904        dib_header = DIBHEADER {
909          size: dib_size,
910          width: BMP::bytes_to_int(self.contents[HEADER_OFFSET+4..HEADER_OFFSET+8].try_into().unwrap()),
911          height: BMP::bytes_to_signed_int(self.contents[HEADER_OFFSET+8..HEADER_OFFSET+12].try_into().unwrap()),
912          planes: BMP::two_bytes_to_int(self.contents[HEADER_OFFSET+12..HEADER_OFFSET+14].try_into().unwrap()),
913          bitcount: BMP::two_bytes_to_int(self.contents[HEADER_OFFSET+14..HEADER_OFFSET+16].try_into().unwrap()),
914          compression: Some(BMP::int_to_compression(BMP::bytes_to_int(self.contents[HEADER_OFFSET+16..HEADER_OFFSET+20].try_into().unwrap()))),
915          sizeimage: Some(BMP::bytes_to_int(self.contents[HEADER_OFFSET+20..HEADER_OFFSET+24].try_into().unwrap())),
916          XPelsPerMeter: Some(BMP::bytes_to_int(self.contents[HEADER_OFFSET+24..HEADER_OFFSET+28].try_into().unwrap())),
917          YPelsPerMeter: Some(BMP::bytes_to_int(self.contents[HEADER_OFFSET+28..HEADER_OFFSET+32].try_into().unwrap())),
918          ClrUsed: Some(BMP::bytes_to_int(self.contents[HEADER_OFFSET+32..HEADER_OFFSET+36].try_into().unwrap())),
919          ClrImportant: Some(BMP::bytes_to_int(self.contents[HEADER_OFFSET+36..HEADER_OFFSET+40].try_into().unwrap())),
920          RedMask: Some(BMP::bytes_to_int(self.contents[HEADER_OFFSET+40..HEADER_OFFSET+44].try_into().unwrap())),
921          GreenMask: Some(BMP::bytes_to_int(self.contents[HEADER_OFFSET+44..HEADER_OFFSET+48].try_into().unwrap())),
922          BlueMask: Some(BMP::bytes_to_int(self.contents[HEADER_OFFSET+48..HEADER_OFFSET+52].try_into().unwrap())),
923          AlphaMask: Some(BMP::bytes_to_int(self.contents[HEADER_OFFSET+52..HEADER_OFFSET+56].try_into().unwrap())),
924          CSType: Some(BMP::bytes_to_string(&self.contents[HEADER_OFFSET+56..HEADER_OFFSET+60])),
925          Endpoints: Some([[BMP::bytes_to_signed_int(self.contents[HEADER_OFFSET+60..HEADER_OFFSET+64].try_into().unwrap()), BMP::bytes_to_signed_int(self.contents[HEADER_OFFSET+64..HEADER_OFFSET+68].try_into().unwrap()), BMP::bytes_to_signed_int(self.contents[HEADER_OFFSET+68..HEADER_OFFSET+72].try_into().unwrap())],  [BMP::bytes_to_signed_int(self.contents[HEADER_OFFSET+72..HEADER_OFFSET+76].try_into().unwrap()), BMP::bytes_to_signed_int(self.contents[HEADER_OFFSET+76..HEADER_OFFSET+80].try_into().unwrap()), BMP::bytes_to_signed_int(self.contents[HEADER_OFFSET+80..HEADER_OFFSET+84].try_into().unwrap())], [BMP::bytes_to_signed_int(self.contents[HEADER_OFFSET+84..HEADER_OFFSET+88].try_into().unwrap()), BMP::bytes_to_signed_int(self.contents[HEADER_OFFSET+88..HEADER_OFFSET+92].try_into().unwrap()), BMP::bytes_to_signed_int(self.contents[HEADER_OFFSET+92..HEADER_OFFSET+96].try_into().unwrap())]]),
927          GammaRed: Some(BMP::bytes_to_int(self.contents[HEADER_OFFSET+96..HEADER_OFFSET+100].try_into().unwrap())),
928          GammaGreen: Some(BMP::bytes_to_int(self.contents[HEADER_OFFSET+100..HEADER_OFFSET+104].try_into().unwrap())),
929          GammaBlue: Some(BMP::bytes_to_int(self.contents[HEADER_OFFSET+104..HEADER_OFFSET+108].try_into().unwrap())),
930          Intent: Some(BMP::int_to_intent(BMP::bytes_to_int(self.contents[HEADER_OFFSET+108..HEADER_OFFSET+112].try_into().unwrap()))),
931          ProfileData: Some(BMP::bytes_to_int(self.contents[HEADER_OFFSET+112..HEADER_OFFSET+116].try_into().unwrap()) as u16),
933          ProfileSize: Some(BMP::bytes_to_int(self.contents[HEADER_OFFSET+116..HEADER_OFFSET+120].try_into().unwrap()) as u16),
934          Reserved: Some(self.contents[HEADER_OFFSET+120..HEADER_OFFSET+124].try_into().unwrap()),
935        };
936      },
937      _ => {
938        return Err(ErrorKind::Unsupported);
940      },
941    }
942    return Ok(dib_header);
943  }
944  fn get_extra_bit_masks(&self) -> Result<EXTRA_BIT_MASKS, ErrorKind> {
946    let dib_header = self.get_dib_header();
948    let dib_header = match dib_header {
949      Ok(returned_dib_header) => returned_dib_header,
950      Err(e) => return Err(e),
951    };
952    match dib_header.size {
953      40 => {
954        const TOTAL_OFFSET: usize = 54;
957        let compression = dib_header.compression.unwrap();
958        if compression == "BI_BITFIELDS" {
959          return Ok(EXTRA_BIT_MASKS::BI_BITFIELDS_MASKS(BI_BITFIELDS_MASKS {
960            red: BMP::bytes_to_int(self.contents[TOTAL_OFFSET..TOTAL_OFFSET+4].try_into().unwrap()),
961            green: BMP::bytes_to_int(self.contents[TOTAL_OFFSET+4..TOTAL_OFFSET+8].try_into().unwrap()),
962            blue: BMP::bytes_to_int(self.contents[TOTAL_OFFSET+8..TOTAL_OFFSET+12].try_into().unwrap()),
963          }));
964        } else if compression == "BI_ALPHABITFIELDS" {
965          return Ok(EXTRA_BIT_MASKS::BI_ALPHABITFIELDS_MASKS(BI_ALPHABITFIELDS_MASKS {
966            red: BMP::bytes_to_int(self.contents[TOTAL_OFFSET..TOTAL_OFFSET+4].try_into().unwrap()),
967            green: BMP::bytes_to_int(self.contents[TOTAL_OFFSET+4..TOTAL_OFFSET+8].try_into().unwrap()),
968            blue: BMP::bytes_to_int(self.contents[TOTAL_OFFSET+8..TOTAL_OFFSET+12].try_into().unwrap()),
969            alpha: BMP::bytes_to_int(self.contents[TOTAL_OFFSET+12..TOTAL_OFFSET+16].try_into().unwrap()),
970          }));
971        } else {
972          return Err(ErrorKind::DoesNotExist);
973        }
974      },
975      _ => return Err(ErrorKind::DoesNotExist),
976    }
977  }
978  fn get_color_table(&self) -> Result<ColorTable, ErrorKind> {
983    let dib_header = self.get_dib_header();
984    let dib_header = match dib_header {
985      Ok(returned_dib_header) => returned_dib_header,
986      Err(e) => return Err(e),
987    };
988    let mut offset: u32 = 14;
991    let end: u32;
993    let data_type: &str;
995    match dib_header.size {
997      12 => {
1001        offset += dib_header.size;
1003        end = self.get_header().bfOffBits;
1004        data_type = "rgbtriple";
1006      },
1007      40 | 108 | 124 => {
1008        offset += dib_header.size;
1010        end = self.get_header().bfOffBits;
1011        let compression = dib_header.compression.unwrap();
1015        if compression == "BI_BITFIELDS" && (dib_header.bitcount == 16 || dib_header.bitcount == 32) {
1016          return Err(ErrorKind::UseExtraBitMasks);
1018        } else if compression == "BI_RGB" && dib_header.bitcount >= 16 {
1019          return Err(ErrorKind::DoesNotExist);
1022        } else {
1023          data_type = "rgbquad";
1024        }
1025      },
1026      _ => {
1027        return Err(ErrorKind::DoesNotExist);
1028      },
1029    };
1030    let color_table: ColorTable;
1031    if data_type == "rgbtriple" {
1032      let mut color_table_vec: Vec::<[u8; 3]> = Vec::new();
1033      for i in 0..(f64::from((end-offset)/3).floor() as i64) {
1035        let ii = i as u32;
1036        color_table_vec.push([BMP::byte_to_int(self.contents[(offset+ii*3) as usize]) as u8, BMP::byte_to_int(self.contents[(offset+ii*3+1) as usize]) as u8, BMP::byte_to_int(self.contents[(offset+ii*3+2) as usize]) as u8]);
1037      }
1038      color_table = ColorTable::RGBTRIPLE(color_table_vec);
1039    } else {
1040      let mut color_table_vec: Vec::<[u8; 4]> = Vec::new();
1041      for i in 0..(f64::from((end-offset)/4).floor() as i64) {
1043        let ii = i as u32;
1044        color_table_vec.push([BMP::byte_to_int(self.contents[(offset+ii*4) as usize]) as u8, BMP::byte_to_int(self.contents[(offset+ii*4+1) as usize]) as u8, BMP::byte_to_int(self.contents[(offset+ii*4+2) as usize]) as u8, BMP::byte_to_int(self.contents[(offset+ii*4+3) as usize]) as u8]);
1045      }
1046      color_table = ColorTable::RGBQUAD(color_table_vec);
1047    }
1048    return Ok(color_table);
1049  }
1050  pub fn get_pixel_data(&self) -> Result<VecDeque<Vec<Vec<u8>>>, ErrorKind> {
1055    let dib_header = self.get_dib_header();
1058    let dib_header = match dib_header {
1059      Ok(returned_dib_header) => returned_dib_header,
1060      Err(e) => return Err(e),
1061    };
1062    let mut rows: VecDeque<Vec<Vec<u8>>> = VecDeque::new();
1069    let header = self.get_header();
1070    if dib_header.height < 0 {
1071      let row_length = f64::from(dib_header.bitcount*dib_header.width as u16/32).ceil() as u32 * 4;
1076      let rows_num = (self.contents.len() as u32-header.bfOffBits)/row_length;
1078      for row_num in 0..rows_num {
1079        let mut row: Vec<Vec<u8>> = Vec::new();
1081        for pixel in 0..dib_header.width {
1082          if dib_header.bitcount >= 8 {
1083            let start: u32 = (header.bfOffBits)+(row_num)*row_length+(pixel)*((dib_header.bitcount/8) as u32);
1084            row.push(self.contents[start as usize..(start+(dib_header.bitcount/8) as u32) as usize].to_vec());
1085          } else {
1086            let start: u32 = (header.bfOffBits)+(row_num)*row_length+(pixel)*(((dib_header.bitcount/8) as f64).ceil() as u32);
1088            let byte: u8 = self.contents[start as usize];
1089            if dib_header.bitcount == 1 {
1090              let split_bits: [u8; 8] = [byte >> 7, (byte & 0b01000000) >> 6, (byte & 0b00100000) >> 5, (byte & 0b00010000) >> 4, (byte & 0b00001000) >> 3, (byte & 0b00000100) >> 2, (byte & 0b00000010) >> 1, byte & 0b00000001];
1091              row.push(vec![split_bits[(pixel % ((8/dib_header.bitcount) as u32)) as usize]]);
1092            } else if dib_header.bitcount == 2 {
1093              let split_bits: [u8; 4] = [byte >> 6, (byte & 0b00110000) >> 4, (byte & 0b00001100) >> 2, byte & 0b00000011];
1094              row.push(vec![split_bits[(pixel % ((8/dib_header.bitcount) as u32)) as usize]]);
1095            } else if dib_header.bitcount == 4 {
1096              let split_bits: [u8; 2] = [byte >> 4, byte & 0b00001111];
1097              row.push(vec![split_bits[(pixel % ((8/dib_header.bitcount) as u32)) as usize]]);
1098            }
1099          }
1100        }
1101        rows.push_back(row);
1102      }
1103      } else if dib_header.height > 0 {
1105      let row_length = f64::from(dib_header.bitcount*dib_header.width as u16/32).ceil() as u32 * 4;
1109      let rows_num: u32 = (self.contents.len() as u32-header.bfOffBits)/row_length;
1110      for row_num in 0..rows_num {
1111        let mut row: Vec<Vec<u8>> = Vec::new();
1112        for pixel in 0..dib_header.width {
1113          if dib_header.bitcount >= 8 {
1114            let start: u32 = (header.bfOffBits)+row_num*row_length+pixel*((dib_header.bitcount/8) as u32);
1115            row.push(self.contents[start as usize..(start+(dib_header.bitcount/8) as u32) as usize].to_vec());
1116          } else {
1117            let start: u32 = (header.bfOffBits)+row_num*row_length+pixel*(((dib_header.bitcount/8) as f64).ceil() as u32);
1119            let byte: u8 = self.contents[start as usize];
1120            if dib_header.bitcount == 1 {
1121              let split_bits: [u8; 8] = [byte >> 7, (byte & 0b01000000) >> 6, (byte & 0b00100000) >> 5, (byte & 0b00010000) >> 4, (byte & 0b00001000) >> 3, (byte & 0b00000100) >> 2, (byte & 0b00000010) >> 1, byte & 0b00000001];
1122              row.push(vec![split_bits[(pixel % ((8/dib_header.bitcount) as u32)) as usize]]);
1123            } else if dib_header.bitcount == 2 {
1124              let split_bits: [u8; 4] = [byte >> 6, (byte & 0b00110000) >> 4, (byte & 0b00001100) >> 2, byte & 0b00000011];
1125              row.push(vec![split_bits[(pixel % ((8/dib_header.bitcount) as u32)) as usize]]);
1126            } else if dib_header.bitcount == 4 {
1127              let split_bits: [u8; 2] = [byte >> 4, byte & 0b00001111];
1128              row.push(vec![split_bits[(pixel % ((8/dib_header.bitcount) as u32)) as usize]]);
1129            }
1130          }
1131        }
1132        rows.push_front(row);
1133      }
1134    }
1135    return Ok(rows);
1136  }
1137  fn get_color_profile(&self) -> Result<Vec<u8>, ErrorKind> {
1140    let dib_header = self.get_dib_header();
1145    let dib_header = match dib_header {
1146      Ok(returned_dib_header) => returned_dib_header,
1147      Err(e) => return Err(e),
1148    };
1149    match dib_header.size {
1150      124 => {
1151        let cstype = dib_header.CSType.unwrap();
1152        if cstype == "PROFILE_EMBEDDED" || cstype == "PROFILE_LINKED" {
1153          return Ok(self.contents[dib_header.ProfileData.unwrap() as usize..].to_vec());
1154          } else {
1156          return Err(ErrorKind::DoesNotExist);
1157        }
1158      },
1159      _ => return Err(ErrorKind::DoesNotExist),
1160    }
1161    }
1166  pub fn get_color_of_pixel(&self, x: usize, y: usize) -> Result<[u8; 4], ErrorKind> {
1170    let dib_header = self.get_dib_header();
1171    let dib_header = match dib_header {
1172      Ok(returned_dib_header) => returned_dib_header,
1173      Err(e) => return Err(e),
1174    };
1175    if x >= (dib_header.width as usize) || y >= (dib_header.height as usize) {
1176      return Err(ErrorKind::OutOfBounds);
1177    }
1178    let pixel_data = self.get_pixel_data();
1180    let pixel_data = match pixel_data {
1181      Ok(returned_pixel_data) => returned_pixel_data,
1182      Err(e) => return Err(e),
1183    };
1184    let pixel: &Vec<u8> = &pixel_data[y][x];
1185    let pixel: Vec<u8> = pixel.to_vec();
1186    if dib_header.bitcount == 16 {
1192      let compression = dib_header.compression.unwrap();
1193      if compression == "BI_BITFIELDS" && (dib_header.RedMask.is_some() && dib_header.GreenMask.is_some() && dib_header.BlueMask.is_some()) {
1194        let rgba: [u8; 4];
1197        let red_mask: u32 = dib_header.RedMask.unwrap();
1199        let blue_mask: u32 = dib_header.BlueMask.unwrap();
1201        if red_mask < blue_mask {
1202          rgba = [BMP::byte_to_int(pixel[0]), BMP::byte_to_int(pixel[1]), BMP::byte_to_int(pixel[2]), 255];
1204        } else {
1205          rgba = [BMP::byte_to_int(pixel[2]), BMP::byte_to_int(pixel[1]), BMP::byte_to_int(pixel[0]), 255];
1207        }
1208        return Ok(rgba);
1209      } else {
1210        return Ok([0, 0, 0, 255]);
1214      }
1215    } else if dib_header.bitcount == 24 {
1216      let rgba: [u8; 4] = [BMP::byte_to_int(pixel[2]), BMP::byte_to_int(pixel[1]), BMP::byte_to_int(pixel[0]), 255];
1220      return Ok(rgba);
1221    } else if dib_header.bitcount == 32 {
1222      let compression = dib_header.compression.unwrap();
1224      if (compression == "BI_BITFIELDS" || compression == "BI_ALPHABITFIELDS") && (dib_header.RedMask.is_some() && dib_header.GreenMask.is_some() && dib_header.BlueMask.is_some()) {
1225        let rgba: [u8; 4];
1230        let red_mask: u32 = dib_header.RedMask.unwrap();
1231        let blue_mask: u32 = dib_header.BlueMask.unwrap();
1233        let alpha_mask: u32 = dib_header.AlphaMask.unwrap();
1234        if alpha_mask < red_mask {
1235          if red_mask < blue_mask {
1237            rgba = [BMP::byte_to_int(pixel[1]), BMP::byte_to_int(pixel[2]), BMP::byte_to_int(pixel[3]), BMP::byte_to_int(pixel[0])];
1239          } else {
1240            rgba = [BMP::byte_to_int(pixel[3]), BMP::byte_to_int(pixel[2]), BMP::byte_to_int(pixel[1]), BMP::byte_to_int(pixel[0])];
1242          }
1243        } else {
1244          if red_mask < blue_mask {
1246            rgba = [BMP::byte_to_int(pixel[0]), BMP::byte_to_int(pixel[1]), BMP::byte_to_int(pixel[2]), BMP::byte_to_int(pixel[3])];
1248          } else {
1249            rgba = [BMP::byte_to_int(pixel[2]), BMP::byte_to_int(pixel[1]), BMP::byte_to_int(pixel[0]), BMP::byte_to_int(pixel[3])];
1251          }
1252        }
1253        return Ok(rgba);
1254      } else {
1255        let rgba: [u8; 4] = [BMP::byte_to_int(pixel[0]), BMP::byte_to_int(pixel[1]), BMP::byte_to_int(pixel[2]), BMP::byte_to_int(pixel[3])];
1256        return Ok(rgba);
1257      }
1258    } else {
1259      let color_table = self.get_color_table();
1261      let color_table = match color_table {
1262        Ok(returned_color_table) => returned_color_table,
1263        Err(e) => return Err(e),
1264      };
1265      let index;
1267      if dib_header.bitcount == 16 {
1268        index = BMP::two_bytes_to_int(BMP::vec_to_2u8_array(pixel));
1269      } else {
1270        index = u16::from(BMP::byte_to_int(pixel[0]));
1271      }
1272      let rgba: [u8; 4];
1273      match color_table {
1274        ColorTable::RGBTRIPLE(vec) => {
1275          let rgb: [u8; 3] = vec[index as usize];
1276          let mut rgb = rgb.to_vec();
1278          rgb.push(255);
1279          rgba = BMP::vec_to_4u8_array(rgb);
1280        },
1281        ColorTable::RGBQUAD(vec) => {
1282          rgba = vec[index as usize];
1283        }
1284      }
1285      return Ok(rgba);
1286    }
1287  }
1288  pub fn get_color_of_px(&self, x: usize, y: usize) -> Result<[u8; 4], ErrorKind> {
1289    self.get_color_of_pixel(x, y)
1290  }
1291  pub fn get_color_of_pixel_efficient(&self, x: usize, y: usize, dib_header: &DIBHEADER, pixel_data: &VecDeque<Vec<Vec<u8>>>) -> Result<[u8; 4], ErrorKind> {
1293    if x >= (dib_header.width as usize) || y >= (dib_header.height as usize) {
1294      return Err(ErrorKind::OutOfBounds);
1295    }
1296    let pixel: &Vec<u8> = &pixel_data[y][x];
1297    let pixel: Vec<u8> = pixel.to_vec();
1298    if dib_header.bitcount == 16 {
1304      let compression = dib_header.compression.as_ref().unwrap();
1305      if compression == "BI_BITFIELDS" && (dib_header.RedMask.is_some() && dib_header.GreenMask.is_some() && dib_header.BlueMask.is_some()) {
1306        let rgba: [u8; 4];
1309        let red_mask: u32 = dib_header.RedMask.unwrap();
1311        let blue_mask: u32 = dib_header.BlueMask.unwrap();
1313        if red_mask < blue_mask {
1314          rgba = [BMP::byte_to_int(pixel[0]), BMP::byte_to_int(pixel[1]), BMP::byte_to_int(pixel[2]), 255];
1316        } else {
1317          rgba = [BMP::byte_to_int(pixel[2]), BMP::byte_to_int(pixel[1]), BMP::byte_to_int(pixel[0]), 255];
1319        }
1320        return Ok(rgba);
1321      } else {
1322        return Ok([0, 0, 0, 255]);
1326      }
1327    } else if dib_header.bitcount == 24 {
1328      let rgba: [u8; 4] = [BMP::byte_to_int(pixel[2]), BMP::byte_to_int(pixel[1]), BMP::byte_to_int(pixel[0]), 255];
1332      return Ok(rgba);
1333    } else if dib_header.bitcount == 32 {
1334      let compression = dib_header.compression.as_ref().unwrap();
1336      if (compression == "BI_BITFIELDS" || compression == "BI_ALPHABITFIELDS") && (dib_header.RedMask.is_some() && dib_header.GreenMask.is_some() && dib_header.BlueMask.is_some()) {
1337        let rgba: [u8; 4];
1342        let red_mask: u32 = dib_header.RedMask.unwrap();
1343        let blue_mask: u32 = dib_header.BlueMask.unwrap();
1345        let alpha_mask: u32 = dib_header.AlphaMask.unwrap();
1346        if alpha_mask < red_mask {
1347          if red_mask < blue_mask {
1349            rgba = [BMP::byte_to_int(pixel[1]), BMP::byte_to_int(pixel[2]), BMP::byte_to_int(pixel[3]), BMP::byte_to_int(pixel[0])];
1351          } else {
1352            rgba = [BMP::byte_to_int(pixel[3]), BMP::byte_to_int(pixel[2]), BMP::byte_to_int(pixel[1]), BMP::byte_to_int(pixel[0])];
1354          }
1355        } else {
1356          if red_mask < blue_mask {
1358            rgba = [BMP::byte_to_int(pixel[0]), BMP::byte_to_int(pixel[1]), BMP::byte_to_int(pixel[2]), BMP::byte_to_int(pixel[3])];
1360          } else {
1361            rgba = [BMP::byte_to_int(pixel[2]), BMP::byte_to_int(pixel[1]), BMP::byte_to_int(pixel[0]), BMP::byte_to_int(pixel[3])];
1363          }
1364        }
1365        return Ok(rgba);
1366      } else {
1367        let rgba: [u8; 4] = [BMP::byte_to_int(pixel[0]), BMP::byte_to_int(pixel[1]), BMP::byte_to_int(pixel[2]), BMP::byte_to_int(pixel[3])];
1368        return Ok(rgba);
1369      }
1370    } else {
1371      let color_table = self.get_color_table();
1373      let color_table = match color_table {
1374        Ok(returned_color_table) => returned_color_table,
1375        Err(e) => return Err(e),
1376      };
1377      let index;
1379      if dib_header.bitcount == 16 {
1380        index = BMP::two_bytes_to_int(BMP::vec_to_2u8_array(pixel));
1381      } else {
1382        index = u16::from(BMP::byte_to_int(pixel[0]));
1383      }
1384      let rgba: [u8; 4];
1385      match color_table {
1386        ColorTable::RGBTRIPLE(vec) => {
1387          let rgb: [u8; 3] = vec[index as usize];
1388          let mut rgb = rgb.to_vec();
1390          rgb.push(255);
1391          rgba = BMP::vec_to_4u8_array(rgb);
1392        },
1393        ColorTable::RGBQUAD(vec) => {
1394          rgba = vec[index as usize];
1395        }
1396      }
1397      return Ok(rgba);
1398    }
1399  }
1400  pub fn get_color_of_px_efficient(&self, x: usize, y: usize, dib_header: &DIBHEADER, pixel_data: &VecDeque<Vec<Vec<u8>>>) -> Result<[u8; 4], ErrorKind> {
1401    self.get_color_of_pixel_efficient(x, y, dib_header, pixel_data)
1402  }
1403  pub fn get_format(&self) -> String {
1407    let dib_header = self.get_dib_header().unwrap();
1408    if dib_header.bitcount == 16 {
1409      let compression = dib_header.compression.unwrap();
1410      if compression == "BI_BITFIELDS" && (dib_header.RedMask.is_some() && dib_header.GreenMask.is_some() && dib_header.BlueMask.is_some()) {
1411        let red_mask: u32 = dib_header.RedMask.unwrap();
1415        let blue_mask: u32 = dib_header.BlueMask.unwrap();
1417        if red_mask < blue_mask {
1418          return "rgb".to_string();
1420        } else {
1421          return "brg".to_string();
1423        }
1424      } else {
1425        return "rgb".to_string();
1429      }
1430    } else if dib_header.bitcount == 24 {
1431      return "bgr".to_string();
1432    } else if dib_header.bitcount == 32 {
1433      let compression = dib_header.compression.unwrap();
1435      if (compression == "BI_BITFIELDS" || compression == "BI_ALPHABITFIELDS") && (dib_header.RedMask.is_some() && dib_header.GreenMask.is_some() && dib_header.BlueMask.is_some()) {
1436        let red_mask: u32 = dib_header.RedMask.unwrap();
1437        let blue_mask: u32 = dib_header.BlueMask.unwrap();
1439        let alpha_mask: u32 = dib_header.AlphaMask.unwrap();
1440        if alpha_mask < red_mask {
1441          if red_mask < blue_mask {
1443            return "argb".to_string();
1445          } else {
1446            return "abgr".to_string();
1448          }
1449        } else {
1450          if red_mask < blue_mask {
1452            return "rgba".to_string();
1454          } else {
1455            return "bgra".to_string();
1457          }
1458        }
1459      } else {
1460        return "rgba".to_string();
1461      }
1462    } else {
1463      return "color table".to_string();
1464    }
1465  }
1466  pub fn change_color_of_pixel(&mut self, x: u16, mut y: u16, new_color: [u8; 4]) -> Result<(), ErrorKind> {
1472    let dib_header = self.get_dib_header();
1475    let dib_header = match dib_header {
1476      Ok(returned_dib_header) => returned_dib_header,
1477      Err(e) => return Err(e),
1478    };
1479    if u32::from(x) >= dib_header.width || i32::from(y) >= dib_header.height {
1480      return Err(ErrorKind::OutOfBounds);
1481    }
1482    let header = self.get_header();
1483    let bitcount = dib_header.bitcount;
1485    if bitcount != 24 && bitcount != 32 {
1487      return Err(ErrorKind::Unsupported);
1489    }
1490    if dib_header.height > 0 {
1492      y = dib_header.height as u16 - y - 1;
1494    }
1495    let row_length = (f64::from((bitcount/8) as u16*dib_header.width as u16/4).ceil() as u32 * 4) as u16;
1497    let start = u32::from(y)*u32::from(row_length)+header.bfOffBits+(bitcount/8) as u32*u32::from(x);
1500    if bitcount == 24 {
1504      self.contents[start as usize] = new_color[2];
1507      self.contents[(start+1) as usize] = new_color[1];
1508      self.contents[(start+2) as usize] = new_color[0];
1509    } else if bitcount == 32 {
1510      let red_mask: u32 = dib_header.RedMask.unwrap();
1511      let blue_mask: u32 = dib_header.BlueMask.unwrap();
1513      let alpha_mask: u32 = dib_header.AlphaMask.unwrap();
1514      if alpha_mask < red_mask {
1516        if red_mask < blue_mask {
1518          self.contents[start as usize] = new_color[3];
1520          self.contents[(start+1) as usize] = new_color[0];
1521          self.contents[(start+2) as usize] = new_color[1];
1522          self.contents[(start+3) as usize] = new_color[2];
1523        } else {
1524          self.contents[start as usize] = new_color[3];
1526          self.contents[(start+1) as usize] = new_color[2];
1527          self.contents[(start+2) as usize] = new_color[1];
1528          self.contents[(start+3) as usize] = new_color[0];
1529        }
1530      } else {
1531        if red_mask < blue_mask {
1533          self.contents[start as usize] = new_color[0];
1535          self.contents[(start+1) as usize] = new_color[1];
1536          self.contents[(start+2) as usize] = new_color[2];
1537          self.contents[(start+3) as usize] = new_color[3];
1538        } else {
1539          self.contents[start as usize] = new_color[2];
1541          self.contents[(start+1) as usize] = new_color[1];
1542          self.contents[(start+2) as usize] = new_color[0];
1543          self.contents[(start+3) as usize] = new_color[3];
1544        }
1545      }
1546    }
1547    return Ok(());
1548  }
1549  pub fn change_color_of_pixel_efficient(&mut self, x: u16, mut y: u16, new_color: [u8; 4], dib_header: &DIBHEADER, header: &BITMAPFILEHEADER) -> Result<(), ErrorKind> {
1551    if u32::from(x) >= dib_header.width || i32::from(y) >= dib_header.height {
1552      return Err(ErrorKind::OutOfBounds);
1553    }
1554    let bitcount = dib_header.bitcount;
1556    if bitcount != 24 && bitcount != 32 {
1558      return Err(ErrorKind::Unsupported);
1560    }
1561    if dib_header.height > 0 {
1563      y = dib_header.height as u16 - y - 1;
1565    }
1566    let row_length = (f64::from((bitcount/8) as u16*dib_header.width as u16/4).ceil() as u32 * 4) as u16;
1568    let start = u32::from(y)*u32::from(row_length)+header.bfOffBits+(bitcount/8) as u32*x as u32;
1571    if bitcount == 24 {
1575      self.contents[start as usize] = new_color[2];
1578      self.contents[(start+1) as usize] = new_color[1];
1579      self.contents[(start+2) as usize] = new_color[0];
1580    } else if bitcount == 32 {
1581      let red_mask: u32 = dib_header.RedMask.unwrap();
1582      let blue_mask: u32 = dib_header.BlueMask.unwrap();
1584      let alpha_mask: u32 = dib_header.AlphaMask.unwrap();
1585      if alpha_mask < red_mask {
1587        if red_mask < blue_mask {
1589          self.contents[start as usize] = new_color[3];
1591          self.contents[(start+1) as usize] = new_color[0];
1592          self.contents[(start+2) as usize] = new_color[1];
1593          self.contents[(start+3) as usize] = new_color[2];
1594        } else {
1595          self.contents[start as usize] = new_color[3];
1597          self.contents[(start+1) as usize] = new_color[2];
1598          self.contents[(start+2) as usize] = new_color[1];
1599          self.contents[(start+3) as usize] = new_color[0];
1600        }
1601      } else {
1602        if red_mask < blue_mask {
1604          self.contents[start as usize] = new_color[0];
1606          self.contents[(start+1) as usize] = new_color[1];
1607          self.contents[(start+2) as usize] = new_color[2];
1608          self.contents[(start+3) as usize] = new_color[3];
1609        } else {
1610          self.contents[start as usize] = new_color[2];
1612          self.contents[(start+1) as usize] = new_color[1];
1613          self.contents[(start+2) as usize] = new_color[0];
1614          self.contents[(start+3) as usize] = new_color[3];
1615        }
1616      }
1617    }
1618    return Ok(());
1619  }
1620  pub fn change_color_of_pixels(&mut self, pixels: Vec<[u16; 2]>, new_color: [u8; 4]) -> Result<(), ErrorKind> {
1623    let dib_header = self.get_dib_header();
1626    let dib_header = match dib_header {
1627      Ok(returned_dib_header) => returned_dib_header,
1628      Err(e) => return Err(e),
1629    };
1630    let header = self.get_header();
1631    let bitcount = dib_header.bitcount;
1632    if bitcount != 24 && bitcount != 32 {
1633      return Err(ErrorKind::Unsupported);
1634    }
1635    let row_length = (f64::from((bitcount/8) as u16*dib_header.width as u16/4).ceil() as u32 * 4) as u16;
1636    for pixel in pixels {
1637      let x = pixel[0];
1638      let mut y = pixel[1];
1639      if dib_header.height > 0 {
1640        y = dib_header.height as u16 - y - 1;
1641      }
1642      let start = y*row_length+header.bfOffBits as u16+(bitcount/8)*x;
1643      if bitcount == 24 {
1644        self.contents[start as usize] = new_color[2];
1645        self.contents[(start+1) as usize] = new_color[1];
1646        self.contents[(start+2) as usize] = new_color[0];
1647      } else if bitcount == 32 {
1648        let red_mask: u32 = dib_header.RedMask.unwrap();
1649        let blue_mask: u32 = dib_header.BlueMask.unwrap();
1650        let alpha_mask: u32 = dib_header.AlphaMask.unwrap();
1651        if alpha_mask < red_mask {
1652          if red_mask < blue_mask {
1653            self.contents[start as usize] = new_color[3];
1655            self.contents[(start+1) as usize] = new_color[0];
1656            self.contents[(start+2) as usize] = new_color[1];
1657            self.contents[(start+3) as usize] = new_color[2];
1658          } else {
1659            self.contents[start as usize] = new_color[3];
1661            self.contents[(start+1) as usize] = new_color[2];
1662            self.contents[(start+2) as usize] = new_color[1];
1663            self.contents[(start+3) as usize] = new_color[0];
1664          }
1665        } else {
1666          if red_mask < blue_mask {
1667            self.contents[start as usize] = new_color[0];
1669            self.contents[(start+1) as usize] = new_color[1];
1670            self.contents[(start+2) as usize] = new_color[2];
1671            self.contents[(start+3) as usize] = new_color[3];
1672          } else {
1673            self.contents[start as usize] = new_color[2];
1675            self.contents[(start+1) as usize] = new_color[1];
1676            self.contents[(start+2) as usize] = new_color[0];
1677            self.contents[(start+3) as usize] = new_color[3];
1678          }
1679        }
1680      }
1681    }
1682    return Ok(());
1683  }
1684  pub fn draw_image(&mut self, x: u16, y: u16, bmp2: BMP)  -> Result<(), ErrorKind> {
1687    let dib_header = self.get_dib_header().unwrap();
1688    let pixel_data = self.get_pixel_data();
1689    let pixel_data = match pixel_data {
1690      Ok(returned_pixel_data) => returned_pixel_data,
1691      Err(e) => return Err(e),
1692    };
1693    let bmp2_dib_header = bmp2.get_dib_header().unwrap();
1695    let bmp2_height = (bmp2_dib_header.height).abs();
1696    let bmp2_width = bmp2_dib_header.width;
1697    let bmp2_pixel_data = bmp2.get_pixel_data();
1698    let bmp2_pixel_data = match bmp2_pixel_data {
1699      Ok(returned_pixel_data) => returned_pixel_data,
1700      Err(e) => return Err(e),
1701    };
1702    for i in 0..bmp2_height {
1703      for j in 0..bmp2_width {
1704        let new_pixel = [x+j as u16, y+i as u16];
1705        let old_color = self.get_color_of_px_efficient(i as usize, j as usize, &dib_header, &pixel_data).unwrap();
1706        let new_color = bmp2.get_color_of_px_efficient(i as usize, j as usize, &bmp2_dib_header, &bmp2_pixel_data).unwrap();
1707        if old_color[3] == 255 && new_color[3] == 255 {
1708          self.change_color_of_pixel(new_pixel[0], new_pixel[1], new_color)?;
1709        } else {
1710          self.change_color_of_pixel(new_pixel[0], new_pixel[1], BMP::composite_colors(new_color, old_color))?;
1711        }
1712      }
1713    }
1714    return Ok(());
1715  }
1716  pub fn change_opacity(&mut self, opacity: u8) -> Result<(), ErrorKind> {
1718    let dib_header = self.get_dib_header();
1720    let dib_header = match dib_header {
1721      Ok(returned_dib_header) => returned_dib_header,
1722      Err(e) => return Err(e),
1723    };
1724    let height: u16 = dib_header.height.abs() as u16;
1725    let width: u16 = dib_header.width as u16;
1726    let pixel_data = self.get_pixel_data();
1727    let pixel_data = match pixel_data {
1728      Ok(returned_pixel_data) => returned_pixel_data,
1729      Err(e) => return Err(e),
1730    };
1731    for y in 0..height {
1733      for x in 0..width {
1734        let old_color = self.get_color_of_px_efficient(x as usize, y as usize, &dib_header, &pixel_data);
1736        let old_color: [u8; 4] = match old_color {
1737          Ok(returned_color) => returned_color,
1738          Err(e) => return Err(e),
1739        };
1740        let new_fill: [u8; 4] = [old_color[0], old_color[1], old_color[2], opacity];
1741        self.change_color_of_pixel(x, y, new_fill)?;
1743      }
1744    }
1745    return Ok(());
1746  }
1747  pub fn invert(&mut self, invert_alpha: Option<bool>) -> Result<(), ErrorKind> {
1749    let dib_header = self.get_dib_header();
1751    let dib_header = match dib_header {
1752      Ok(returned_dib_header) => returned_dib_header,
1753      Err(e) => return Err(e),
1754    };
1755    let height: u16 = dib_header.height.abs() as u16;
1756    let width: u16 = dib_header.width as u16;
1757    let pixel_data = self.get_pixel_data();
1758    let pixel_data = match pixel_data {
1759      Ok(returned_pixel_data) => returned_pixel_data,
1760      Err(e) => return Err(e),
1761    };
1762    let header = self.get_header();
1763    for y in 0..height {
1765      for x in 0..width {
1766        let old_color = self.get_color_of_px_efficient(x as usize, y as usize, &dib_header, &pixel_data);
1769        let old_color: [u8; 4] = match old_color {
1770          Ok(returned_color) => returned_color,
1771          Err(e) => return Err(e),
1772        };
1773        let mut new_fill: [u8; 4] = [255 - old_color[0], 255 - old_color[1], 255 - old_color[2], old_color[3]];
1774        if invert_alpha.is_some() {
1775          let invert_alpha_unwrapped = invert_alpha.unwrap();
1776          if invert_alpha_unwrapped {
1777            new_fill = [255 - old_color[0], 255 - old_color[1], 255 - old_color[2], 255 - old_color[3]];
1778          }
1779        }
1780        self.change_color_of_pixel_efficient(x, y, new_fill, &dib_header, &header)?;
1782      }
1783    }
1784    return Ok(());
1785  }
1786  pub fn translate(&mut self, x: i16, y: i16) -> Result<(), ErrorKind> {
1789    let dib_header = self.get_dib_header();
1790    let dib_header = match dib_header {
1791      Ok(returned_dib_header) => returned_dib_header,
1792      Err(e) => return Err(e),
1793    };
1794    let og_bmp: BMP = self.clone();
1796    let height = dib_header.height.abs() as i16;
1797    let width = dib_header.width as i16;
1798    let og_pixel_data = self.get_pixel_data();
1799    let og_pixel_data = match og_pixel_data {
1800      Ok(returned_pixel_data) => returned_pixel_data,
1801      Err(e) => return Err(e),
1802    };
1803    self.contents = BMP::new(dib_header.height, dib_header.width, Some([255, 255, 255, 0])).contents;
1805    for row in 0..height {
1806      for column in 0..width {
1807        let temp_x: i16 = column+x;
1808        let temp_y: i16 = row+y;
1809        if temp_y < 0 || temp_y >= height || temp_x < 0 || temp_x >= width {
1810          continue;
1811        }
1812        let color = og_bmp.get_color_of_px_efficient(column as usize, row as usize, &dib_header, &og_pixel_data).unwrap();
1813        self.change_color_of_pixel(temp_x as u16, temp_y as u16, color)?;
1814      }
1815    }
1816    return Ok(());
1817  }
1818  pub fn rotate(&mut self, deg: f64, center_option: Option<[u16; 2]>) -> Result<(), ErrorKind> {
1820    let center: [u16; 2];
1821    if center_option.is_none() {
1822      center = [0, 0];
1823    } else {
1824      center = center_option.unwrap();
1825    }
1826    let rad: f64 = BMP::deg_to_rad(deg);
1828    let dib_header = self.get_dib_header();
1829    let dib_header = match dib_header {
1830      Ok(returned_dib_header) => returned_dib_header,
1831      Err(e) => return Err(e),
1832    };
1833    let og_bmp: BMP = self.clone();
1834    let height = dib_header.height.abs() as u16;
1835    let width = dib_header.width as u16;
1836    let og_pixel_data = self.get_pixel_data();
1837    let og_pixel_data = match og_pixel_data {
1838      Ok(returned_pixel_data) => returned_pixel_data,
1839      Err(e) => return Err(e),
1840    };
1841    self.contents = BMP::new(dib_header.height, dib_header.width, Some([255, 255, 255, 0])).contents;
1842    for row in 0..height {
1843      for column in 0..width {
1844        let (x2, y2) = BMP::rotate_point(rad, [column, row], center);
1845        if y2 < 0 || y2 >= i32::from(height) || x2 < 0 || x2 >= i32::from(width) {
1847          continue;
1848        }
1849        let color = og_bmp.get_color_of_px_efficient(column as usize, row as usize, &dib_header, &og_pixel_data).unwrap();
1851        self.change_color_of_pixel(x2 as u16, y2 as u16, color)?;
1853      }
1854      }
1856    return Ok(());
1857  }
1858  pub fn separable_blur(&mut self, radius: u8, gen_distribution: impl Fn(u8, u8) -> u16, horizontal: Option<bool>, vertical: Option<bool>) -> Result<(), ErrorKind> {
1860    let mut do_horizontal: bool = true;
1865    let mut do_vertical: bool = true;
1866    if horizontal.is_some() {
1867      do_horizontal = horizontal.unwrap();
1868    }
1869    if vertical.is_some() {
1870      do_vertical = vertical.unwrap();
1871    }
1872    let dib_header = self.get_dib_header();
1873    let dib_header = match dib_header {
1874      Ok(returned_dib_header) => returned_dib_header,
1875      Err(e) => return Err(e),
1876    };
1877    let height: u16 = dib_header.height.abs() as u16;
1878    let width: u16 = dib_header.width as u16;
1879    if radius > 16 || radius == 0 {
1880      return Err(ErrorKind::InvalidParameter("Blur/filter radius is invalid since bigger than 16 or is 0".to_string()));
1881    }
1882    let pixel_data = self.get_pixel_data();
1885    let pixel_data = match pixel_data {
1886      Ok(returned_pixel_data) => returned_pixel_data,
1887      Err(e) => return Err(e),
1888    };
1889    if do_horizontal {
1890      let mut weights: Vec<u16> = Vec::new();
1892      for l in 0..radius {
1893        weights.push(gen_distribution(radius, radius-l));
1895      }
1896      weights.push(gen_distribution(radius, 0));
1897      for r in 0..radius {
1898        weights.push(gen_distribution(radius, r+1));
1900      }
1901      for y in 0..height {
1902        for x in 0..width {
1903          let mut total_weight: u16 = 0;
1904          for w in &weights {
1905            total_weight += w;
1906          }
1907          let mut total_weight_h = total_weight;
1908          for hl_b in 1..radius+1 {
1910            if x < u16::from(hl_b) {
1911              total_weight_h -= weights[(radius-hl_b) as usize];
1913            }
1914          }
1915          for hr_b in 1..radius+1 {
1916            if x+u16::from(hr_b) >= width {
1917              total_weight_h -= weights[(radius+hr_b) as usize];
1919            }
1920          }
1921          let mut new_r_h: f64 = 0.0;
1923          let mut new_g_h: f64 = 0.0;
1924          let mut new_b_h: f64 = 0.0;
1925          let mut new_a_h: f64 = 0.0;
1926          for hl in 1..radius+1 {
1927            if x >= u16::from(hl) {
1928              let hl_color = self.get_color_of_px_efficient((x-u16::from(hl)) as usize, y as usize, &dib_header, &pixel_data).unwrap();
1930              new_r_h += hl_color[0] as f64 * (weights[(radius-hl) as usize] as f64) / total_weight_h as f64;
1931              new_g_h += hl_color[1] as f64 * (weights[(radius-hl) as usize] as f64) / total_weight_h as f64;
1932              new_b_h += hl_color[2] as f64 * (weights[(radius-hl) as usize] as f64) / total_weight_h as f64;
1933              new_a_h += hl_color[3] as f64 * (weights[(radius-hl) as usize] as f64) / total_weight_h as f64;
1934            }
1935          }
1936          let center_color = self.get_color_of_px_efficient(x as usize, y as usize, &dib_header, &pixel_data).unwrap();
1937          new_r_h += center_color[0] as f64 * (weights[(radius) as usize] as f64) / total_weight_h as f64;
1938          new_g_h += center_color[1] as f64 * (weights[(radius) as usize] as f64) / total_weight_h as f64;
1939          new_b_h += center_color[2] as f64 * (weights[(radius) as usize] as f64) / total_weight_h as f64;
1940          new_a_h += center_color[3] as f64 * (weights[(radius) as usize] as f64) / total_weight_h as f64;
1941          for hr in 1..radius+1 {
1942            if x+u16::from(hr) < width {
1943              let hr_color = self.get_color_of_px_efficient((x+u16::from(hr)) as usize, y as usize, &dib_header, &pixel_data).unwrap();
1945              new_r_h += hr_color[0] as f64 * (weights[(radius-hr) as usize] as f64) / total_weight_h as f64;
1946              new_g_h += hr_color[1] as f64 * (weights[(radius-hr) as usize] as f64) / total_weight_h as f64;
1947              new_b_h += hr_color[2] as f64 * (weights[(radius-hr) as usize] as f64) / total_weight_h as f64;
1948              new_a_h += hr_color[3] as f64 * (weights[(radius-hr) as usize] as f64) / total_weight_h as f64;
1949            }
1950          }
1951          let new_color: [u8; 4] = [new_r_h.round() as u8, new_g_h.round() as u8, new_b_h.round() as u8, new_a_h.round() as u8];
1953          self.change_color_of_pixel(x, y, new_color).unwrap();
1955        }
1956      }
1957    }
1958    let pixel_data = self.get_pixel_data();
1961    let pixel_data = match pixel_data {
1962      Ok(returned_pixel_data) => returned_pixel_data,
1963      Err(e) => return Err(e),
1964    };
1965    if do_vertical {
1966      let mut weights: Vec<u16> = Vec::new();
1968      for l in 0..radius {
1969        weights.push(gen_distribution(radius, radius-l));
1971      }
1972      weights.push(gen_distribution(radius, 0));
1973      for r in 0..radius {
1974        weights.push(gen_distribution(radius, r+1));
1976      }
1977      for y in 0..height {
1978        for x in 0..width {
1979          let mut total_weight: u16 = 0;
1980          for w in &weights {
1981            total_weight += w;
1982          }
1983          let mut total_weight_v = total_weight;
1984          for vu_b in 1..radius+1 {
1986            if y < u16::from(vu_b) {
1987              total_weight_v -= weights[(radius-vu_b) as usize];
1989            }
1990          }
1991          for vd_b in 1..radius+1 {
1992            if y+u16::from(vd_b) >= height {
1993              total_weight_v -= weights[(radius+vd_b) as usize];
1995            }
1996          }
1997          let mut new_r_h: f64 = 0.0;
1999          let mut new_g_h: f64 = 0.0;
2000          let mut new_b_h: f64 = 0.0;
2001          let mut new_a_h: f64 = 0.0;
2002          for vu in 1..radius+1 {
2003            if y >= u16::from(vu) {
2004              let vu_color = self.get_color_of_px_efficient(x as usize, (y-u16::from(vu)) as usize, &dib_header, &pixel_data).unwrap();
2006              new_r_h += f64::from(vu_color[0]) * f64::from(weights[(radius-vu) as usize]) / f64::from(total_weight_v);
2007              new_g_h += f64::from(vu_color[1]) * f64::from(weights[(radius-vu) as usize]) / f64::from(total_weight_v);
2008              new_b_h += f64::from(vu_color[2]) * f64::from(weights[(radius-vu) as usize]) / f64::from(total_weight_v);
2009              new_a_h += f64::from(vu_color[3]) * f64::from(weights[(radius-vu) as usize]) / f64::from(total_weight_v);
2010            }
2011          }
2012          let center_color = self.get_color_of_px_efficient(x as usize, y as usize, &dib_header, &pixel_data).unwrap();
2014          new_r_h += f64::from(center_color[0]) * f64::from(weights[(radius) as usize]) / f64::from(total_weight_v);
2015          new_g_h += f64::from(center_color[1]) * f64::from(weights[(radius) as usize]) / f64::from(total_weight_v);
2016          new_b_h += f64::from(center_color[2]) * f64::from(weights[(radius) as usize]) / f64::from(total_weight_v);
2017          new_a_h += f64::from(center_color[3]) * f64::from(weights[(radius) as usize]) / f64::from(total_weight_v);
2018          for vd in 1..radius+1 {
2019            if y+u16::from(vd) < height {
2020              let vd_color = self.get_color_of_px_efficient(x as usize, (y+u16::from(vd)) as usize, &dib_header, &pixel_data).unwrap();
2022              new_r_h += f64::from(vd_color[0]) * f64::from(weights[(radius-vd) as usize]) / f64::from(total_weight_v);
2023              new_g_h += f64::from(vd_color[1]) * f64::from(weights[(radius-vd) as usize]) / f64::from(total_weight_v);
2024              new_b_h += f64::from(vd_color[2]) * f64::from(weights[(radius-vd) as usize]) / f64::from(total_weight_v);
2025              new_a_h += f64::from(vd_color[3]) * f64::from(weights[(radius-vd) as usize]) / f64::from(total_weight_v);
2026            }
2027          }
2028          let new_color: [u8; 4] = [new_r_h.round() as u8, new_g_h.round() as u8, new_b_h.round() as u8, new_a_h.round() as u8];
2030          self.change_color_of_pixel(x, y, new_color).unwrap();
2032        }
2033      }
2034    }
2035    return Ok(());
2036  }
2037  pub fn box_blur(&mut self, radius: u8) -> Result<(), ErrorKind> {
2045    let gen_box_distribution = |_radius: u8, _distance: u8| -> u16 {
2047      1u16
2048    };
2049    return self.separable_blur(radius, gen_box_distribution, None, None);
2050  }
2051  pub fn gaussian_blur(&mut self, radius: u8) -> Result<(), ErrorKind> {
2057    let gen_gaussian_distribution = |radius: u8, distance: u8| -> u16 {
2059      if distance == radius {
2061        return 1u16;
2063      }
2064      let n = radius*2+1-1;
2066      let k = radius-distance;
2067      let mut term: f64 = 1.0;
2068      for i in 1..radius+2 {
2069        term = term * ((n+1-i) as f64/f64::from(i));
2070        if i == k {
2071          break;
2072        }
2073      }
2074      return term as u16;
2075    };
2076    return self.separable_blur(radius, gen_gaussian_distribution, None, None);
2077  }
2078  pub fn grayscale(&mut self) -> Result<(), ErrorKind> {
2081    let dib_header = self.get_dib_header();
2082    let dib_header = match dib_header {
2083      Ok(returned_dib_header) => returned_dib_header,
2084      Err(e) => return Err(e),
2085    };
2086    let height: u16 = dib_header.height.abs() as u16;
2087    let width: u16 = dib_header.width as u16;
2088    let pixel_data = self.get_pixel_data();
2089    let pixel_data = match pixel_data {
2090      Ok(returned_pixel_data) => returned_pixel_data,
2091      Err(e) => return Err(e),
2092    };
2093    let header = self.get_header();
2094    for y in 0..height {
2096      for x in 0..width {
2097        let old_color = self.get_color_of_px_efficient(x as usize, y as usize, &dib_header, &pixel_data);
2100        let old_color: [u8; 4] = match old_color {
2101          Ok(returned_color) => returned_color,
2102          Err(e) => return Err(e),
2103        };
2104        self.change_color_of_pixel_efficient(x, y, BMP::rgb_to_grayscale(old_color), &dib_header, &header)?;
2106      }
2107    }
2108    return Ok(());
2109  }
2110  pub fn greyscale(&mut self) -> Result<(), ErrorKind> {
2111    self.grayscale()
2113  }
2114  pub fn channel_grayscale(&mut self, channel: RGBAChannel) -> Result<(), ErrorKind> {
2116    let dib_header = self.get_dib_header();
2118    let dib_header = match dib_header {
2119      Ok(returned_dib_header) => returned_dib_header,
2120      Err(e) => return Err(e),
2121    };
2122    let height: u16 = dib_header.height.abs() as u16;
2123    let width: u16 = dib_header.width as u16;
2124    let pixel_data = self.get_pixel_data();
2125    let pixel_data = match pixel_data {
2126      Ok(returned_pixel_data) => returned_pixel_data,
2127      Err(e) => return Err(e),
2128    };
2129    let header = self.get_header();
2130    for y in 0..height {
2132      for x in 0..width {
2133        let old_color = self.get_color_of_px_efficient(x as usize, y as usize, &dib_header, &pixel_data);
2136        let old_color: [u8; 4] = match old_color {
2137          Ok(returned_color) => returned_color,
2138          Err(e) => return Err(e),
2139        };
2140        let use_color: u8;
2141        match channel {
2142          RGBAChannel::Red => use_color = old_color[0],
2143          RGBAChannel::Green => use_color = old_color[1],
2144          RGBAChannel::Blue => use_color = old_color[2],
2145          RGBAChannel::Alpha => {
2146            use_color = old_color[3];
2147            self.change_color_of_pixel_efficient(x, y, [use_color, use_color, use_color, use_color], &dib_header, &header)?;
2148            return Ok(());
2149          },
2150        }
2151        self.change_color_of_pixel_efficient(x, y, [use_color, use_color, use_color, old_color[3]], &dib_header, &header)?;
2153      }
2154    }
2155    return Ok(());
2156  }
2157  pub fn surround_filter(&mut self, radius: u8, get_new_pixel: impl Fn(Vec<[u8; 4]>) -> [u8; 4]) -> Result<(), ErrorKind> {
2158    let dib_header = self.get_dib_header();
2160    let dib_header = match dib_header {
2161      Ok(returned_dib_header) => returned_dib_header,
2162      Err(e) => return Err(e),
2163    };
2164    let height: u16 = dib_header.height.abs() as u16;
2165    let width: u16 = dib_header.width as u16;
2166    if radius > 16 || radius == 0 {
2167      return Err(ErrorKind::InvalidParameter("Blur/filter radius is invalid since bigger than 16 or is 0".to_string()));
2168    }
2169    let pixel_data = self.get_pixel_data();
2170    let pixel_data = match pixel_data {
2171      Ok(returned_pixel_data) => returned_pixel_data,
2172      Err(e) => return Err(e),
2173    };
2174    let header = self.get_header();
2175    for y in 0..height {
2176      for x in 0..width {
2177        let mut surrounding_colors: Vec<[u8; 4]> = Vec::new();
2178        let rows: i16 = i16::from(radius*2+1);
2180        for row in 0..rows {
2181          let row_y = y as i16-(i16::from(radius)-row);
2182          if row_y < 0 {
2183            continue;
2184          } else if row_y as u16 >= height {
2185            continue;
2186          }
2187          for left_num in 1..u16::from(radius+1) {
2189            if (i32::from(x)-i32::from(left_num)) < 0 {
2190              continue;
2191            }
2192            let left_pixel_color = self.get_color_of_pixel_efficient((x-left_num) as usize, row_y as usize, &dib_header, &pixel_data)?;
2193            surrounding_colors.push(left_pixel_color);
2194          }
2195          let center_pixel_color = self.get_color_of_pixel_efficient(x as usize, row_y as usize, &dib_header, &pixel_data)?;
2197          surrounding_colors.push(center_pixel_color);
2198          for right_num in 1..u16::from(radius+1) {
2200            if (x+right_num) >= width {
2201              continue;
2202            }
2203            let right_pixel_color = self.get_color_of_pixel_efficient((x+right_num) as usize, row_y as usize, &dib_header, &pixel_data)?;
2204            surrounding_colors.push(right_pixel_color);
2205          }
2206        }
2207        self.change_color_of_pixel_efficient(x, y, get_new_pixel(surrounding_colors), &dib_header, &header)?;
2208      }
2209    }
2210    return Ok(());
2211  }
2212  pub fn median_filter(&mut self, radius: u8) -> Result<(), ErrorKind> {
2218    let get_median_pixel = |surrounding_pixels: Vec<[u8; 4]>| -> [u8; 4] {
2220      let iter_surrounding = (&surrounding_pixels).into_iter();
2221      let mut r_vec = iter_surrounding.clone().map(|item| item[0]).collect::<Vec<u8>>();
2222      r_vec.sort();
2223      let mut g_vec = iter_surrounding.clone().map(|item| item[1]).collect::<Vec<u8>>();
2224      g_vec.sort();
2225      let mut b_vec = iter_surrounding.clone().map(|item| item[2]).collect::<Vec<u8>>();
2226      b_vec.sort();
2227      let mut a_vec = iter_surrounding.clone().map(|item| item[3]).collect::<Vec<u8>>();
2228      a_vec.sort();
2229      [r_vec[r_vec.len()/2], g_vec[g_vec.len()/2], b_vec[b_vec.len()/2], a_vec[a_vec.len()/2]]
2232    };
2233    return self.surround_filter(radius, get_median_pixel);
2234  }
2235  pub fn mean_filter(&mut self, radius: u8) -> Result<(), ErrorKind> {
2237    let get_mean_pixel = |surrounding_pixels: Vec<[u8; 4]>| -> [u8; 4] {
2238      let iter_surrounding = (&surrounding_pixels).into_iter();
2239      let total_r: f64 = f64::from(iter_surrounding.clone().map(|item| u16::from(item[0])).reduce(|prev_total, current| prev_total+current).unwrap());
2240      let total_g: f64 = f64::from(iter_surrounding.clone().map(|item| u16::from(item[1])).reduce(|prev_total, current| prev_total+current).unwrap());
2241      let total_b: f64 = f64::from(iter_surrounding.clone().map(|item| u16::from(item[2])).reduce(|prev_total, current| prev_total+current).unwrap());
2242      let total_a: f64 = f64::from(iter_surrounding.clone().map(|item| u16::from(item[3])).reduce(|prev_total, current| prev_total+current).unwrap());
2243      let average_r: u8 = (total_r/(&surrounding_pixels).len() as f64).round() as u8;
2244      let average_g: u8 = (total_g/(&surrounding_pixels).len() as f64).round() as u8;
2245      let average_b: u8 = (total_b/(&surrounding_pixels).len() as f64).round() as u8;
2246      let average_a: u8 = (total_a/(&surrounding_pixels).len() as f64).round() as u8;
2247      [average_r, average_g, average_b, average_a]
2248    };
2249    return self.surround_filter(radius, get_mean_pixel);
2250  }
2251  pub fn draw_line(&mut self, fill: [u8; 4], p1: [u16; 2], p2: [u16; 2]) -> Result<(), ErrorKind> {
2254    if p1[0] == p2[0] {
2255      for ay in 0..(p2[1] as i16 - p1[1] as i16 + 1).abs() as u16 {
2257        if p1[1] < p2[1] {
2259          self.change_color_of_pixel(p1[0], p1[1]+ay, fill)?;
2260        } else {
2261          self.change_color_of_pixel(p2[0], p2[1]+ay, fill)?;
2262        }
2263      }
2264    } else if p1[1] == p2[1] {
2265      for ax in 0..(p2[0] as i16 - p1[0] as i16 + 1).abs() as u16 {
2267        if p1[0] < p2[0] {
2269          self.change_color_of_pixel(p1[0]+ax, p1[1], fill)?;
2270        } else {
2271          self.change_color_of_pixel(p2[0]+ax, p2[1], fill)?;
2272        }
2273      }
2274    } else {
2275      let vertical_diff: u16 = ((p2[1] as i16 - p1[1] as i16).abs() + 1) as u16;
2276      let horizontal_diff: u16 = ((p2[0] as i16 - p1[0] as i16).abs() + 1) as u16;
2277      let leftmost_p;
2279      let rightmost_p;
2280      if p1[0] < p2[0] {
2281        leftmost_p = p1;
2282        rightmost_p = p2;
2283      } else {
2284        leftmost_p = p2;
2285        rightmost_p = p1;
2286      }
2287      let highest_p;
2288      let lowest_p;
2289      if p1[1] < p2[1] {
2290        highest_p = p1;
2291        lowest_p = p2;
2292      } else {
2293        highest_p = p2;
2294        lowest_p = p1;
2295      }
2296      if vertical_diff >= 2 {
2298        let middle_segment_length: u16;
2299        let two_ends_combined_length;
2300        if horizontal_diff >= vertical_diff {
2301          middle_segment_length = f64::from((horizontal_diff)/(vertical_diff)).floor() as u16;
2303          two_ends_combined_length = horizontal_diff - (middle_segment_length*(vertical_diff-2));
2305        } else {
2306          middle_segment_length = f64::from((vertical_diff)/(horizontal_diff)).floor() as u16;
2309          two_ends_combined_length = vertical_diff - (middle_segment_length*(horizontal_diff-2));
2311        }
2312        if two_ends_combined_length == 1 {
2315          self.change_color_of_pixel(leftmost_p[0], leftmost_p[1], fill)?;
2319          for j in 0..(vertical_diff-2) {
2321            for ji in 0..middle_segment_length {
2322              if j == vertical_diff-3 && ji == middle_segment_length-1 {
2324                continue;
2325              }
2326              if highest_p == leftmost_p {
2327                self.change_color_of_pixel(leftmost_p[0]+ji+j*middle_segment_length, rightmost_p[1]+j, fill)?;
2328              } else {
2329                self.change_color_of_pixel(leftmost_p[0]+ji+j*middle_segment_length, rightmost_p[1]-j, fill)?;
2330              }
2331            }
2332          }
2333          self.change_color_of_pixel(rightmost_p[0], rightmost_p[1], fill)?;
2335        } else if horizontal_diff >= vertical_diff {
2336          let end_segment_length = two_ends_combined_length/2;
2337          for i in 0..end_segment_length {
2340            self.change_color_of_pixel(leftmost_p[0]+i, leftmost_p[1], fill)?;
2341          }
2342          for j in 0..(vertical_diff-2) {
2344            for ji in 0..middle_segment_length {
2345              if highest_p == leftmost_p {
2346                self.change_color_of_pixel(leftmost_p[0]+ji+j*middle_segment_length+end_segment_length, leftmost_p[1]+j+1, fill)?;
2347              } else {
2348                self.change_color_of_pixel(leftmost_p[0]+ji+j*middle_segment_length, rightmost_p[1]-j, fill)?;
2349              }
2350            }
2351          }
2352          for k in 0..end_segment_length {
2354            self.change_color_of_pixel(rightmost_p[0]-k, rightmost_p[1], fill)?;
2355          }
2356        } else if horizontal_diff < vertical_diff {
2357          let end_segment_length = two_ends_combined_length/2;
2358          for i in 0..end_segment_length {
2361            self.change_color_of_pixel(leftmost_p[0], leftmost_p[1]+i, fill)?;
2362          }
2363          for j in 0..(horizontal_diff-2) {
2365            for ji in 0..middle_segment_length {
2366              if highest_p == leftmost_p {
2367                self.change_color_of_pixel(leftmost_p[0]+j+1, leftmost_p[1]+ji+j*middle_segment_length+end_segment_length, fill)?;
2369              } else {
2370                self.change_color_of_pixel(leftmost_p[0]-j, rightmost_p[1]+ji+j*middle_segment_length, fill)?;
2372              }
2373            }
2374          }
2375          for k in 0..end_segment_length {
2377            self.change_color_of_pixel(lowest_p[0], lowest_p[1]-k, fill)?;
2378          }
2379        }
2380      } else {
2381        let first_segment: u16 = (f64::from(horizontal_diff/2)).floor() as u16;
2383        let second_segment: u16 = (f64::from(horizontal_diff/2)).ceil() as u16;
2384        for i in 0..first_segment {
2385          self.change_color_of_pixel(leftmost_p[0]+i, leftmost_p[1], fill)?;
2386        }
2387        for j in 0..second_segment {
2388          self.change_color_of_pixel(rightmost_p[0]-j, rightmost_p[1], fill)?;
2389        }
2390      }
2391    }
2392    return Ok(());
2393  }
2394  pub fn draw_rectangle(&mut self, fill: Option<[u8; 4]>, stroke: Option<[u8; 4]>, p1: [u16; 2], p2: [u16; 2]) -> Result<(), ErrorKind> {
2397    if stroke.is_some() {
2398      let unwrapped_stroke = stroke.unwrap();
2399      self.draw_line(unwrapped_stroke, p1, [p2[0], p1[1]])?;
2401      self.draw_line(unwrapped_stroke, [p1[0], p2[1]], [p2[0], p2[1]])?;
2403      self.draw_line(unwrapped_stroke, p1, [p1[0], p2[1]])?;
2405      self.draw_line(unwrapped_stroke, [p2[0], p1[1]], [p2[0], p2[1]])?;
2407    }
2408    if fill.is_some() {
2410      let dib_header = self.get_dib_header();
2411      let dib_header = match dib_header {
2412        Ok(returned_dib_header) => returned_dib_header,
2413        Err(e) => return Err(e),
2414      };
2415      let header = self.get_header();
2416      let unwrapped_fill = fill.unwrap();
2417      let p1_mod = [p1[0]+1, p1[1]+1];
2418      let p2_mod = [p2[0]-1, p2[1]-1];
2419      for y in 0..(p2_mod[1]-p1_mod[1]+1) {
2420        for x in 0..(p2_mod[0]-p1_mod[0]+1) {
2421          self.change_color_of_pixel_efficient(p1_mod[0]+x, p1_mod[1]+y, unwrapped_fill, &dib_header, &header)?;
2422        }
2423      }
2424    }
2425    return Ok(());
2426  }
2427  pub fn draw_ellipse(&mut self, center: [u16; 2], xlength: u16, ylength: u16, stroke: [u8; 4], fill: Option<[u8; 4]>, guess: bool) -> Result<(), ErrorKind> {
2432    let mut enclosure_all: Vec<[u16; 2]> = Vec::new();
2434    let xlength_2: f64 = i32::pow(xlength.into(), 2) as f64;
2439    let ylength_2: f64 = i32::pow(ylength.into(), 2) as f64;
2441    let mut prev_y = 0;
2442    for il in 1..xlength+1 {
2443      let c_x = il;
2444      let c_x_2: f64 = i32::pow(c_x.into(), 2) as f64;
2445      let y = (((1 as f64-c_x_2/xlength_2)*ylength_2) as f64).sqrt().round() as u16;
2446      self.change_color_of_pixel(center[0]-c_x, center[1]+y, stroke)?;
2447      self.change_color_of_pixel(center[0]-c_x, center[1]-y, stroke)?;
2448      enclosure_all.extend([[center[0]-c_x, center[1]+y], [center[0]-c_x, center[1]-y]]);
2449      let diff = (prev_y as i16-y as i16).abs() as u16;
2450      if diff > 1 && il != 1 && guess {
2451        for d in 1..diff+1 {
2452          self.change_color_of_pixel(center[0]-c_x+1, center[1]+y+d, stroke)?;
2453          self.change_color_of_pixel(center[0]-c_x+1, center[1]-y-d, stroke)?;
2454          enclosure_all.extend([[center[0]-c_x+1, center[1]+y+d], [center[0]-c_x+1, center[1]-y-d]]);
2455        }
2456      }
2457      prev_y = y;
2458    }
2459    for ir in 1..xlength+1 {
2460      let c_x = ir;
2461      let c_x_2: f64 = i32::pow(c_x.into(), 2) as f64;
2462      let y = (((1.0-c_x_2/xlength_2)*ylength_2) as f64).sqrt().round() as u16;
2463      self.change_color_of_pixel(center[0]+c_x, center[1]+y, stroke)?;
2464      self.change_color_of_pixel(center[0]+c_x, center[1]-y, stroke)?;
2465      enclosure_all.extend([[center[0]+c_x, center[1]+y], [center[0]+c_x, center[1]-y]]);
2466      let diff = (prev_y as i16-y as i16).abs() as u16;
2467      if diff > 1 && ir != 1 && guess {
2468        for d in 1..diff+1 {
2469          self.change_color_of_pixel(center[0]+c_x-1, center[1]+y+d, stroke)?;
2470          self.change_color_of_pixel(center[0]+c_x-1, center[1]-y-d, stroke)?;
2471          enclosure_all.extend([[center[0]+c_x-1, center[1]+y+d], [center[0]+c_x-1, center[1]-y-d]]);
2472        }
2473      }
2474      prev_y = y;
2475    }
2476    self.change_color_of_pixel(center[0], center[1]+ylength, stroke)?;
2477    self.change_color_of_pixel(center[0], center[1]-ylength, stroke)?;
2478    enclosure_all.extend([[center[0], center[1]+ylength], [center[0], center[1]-ylength]]);
2479    if fill.is_some() {
2480      let mut enclosure: Vec<[u16; 2]> = Vec::new();
2482      for coord in enclosure_all {
2483        if !enclosure.contains(&coord) {
2484          if coord[0] != 0 {
2485            if enclosure.contains(&[coord[0]-1, coord[1]]) {
2486              continue;
2487            }
2488          }
2489          if enclosure.contains(&[coord[0]+1, coord[1]]) {
2490            continue;
2491          }
2492          enclosure.push(coord);
2493        }
2494      }
2495      let unwrapped_fill = fill.unwrap();
2496      for y1 in 0..ylength*2+1 {
2498        for x1 in 0..xlength*2+1 {
2499          let point1: [i32; 2] = [i32::from(center[0])+i32::from(x1)-i32::from(xlength), i32::from(center[1])+i32::from(y1)-i32::from(ylength)];
2500          if point1[0] < 0 || point1[1] < 0 {
2501            continue;
2502          }
2503          let point1: [u16; 2] = [point1[0] as u16, point1[1] as u16];
2504          let point_inside = BMP::point_in_enclosure(point1, &enclosure);
2505          if point_inside {
2506            self.change_color_of_pixel(point1[0], point1[1], unwrapped_fill)?;
2507          }
2508        }
2509      }
2510    }
2511    return Ok(());
2512  }
2513  pub fn fill_bucket(&mut self, fill: [u8; 4], x: usize, y: usize) -> Result<Vec<[u16; 2]>, ErrorKind> {
2515    let dib_header = self.get_dib_header();
2519    let dib_header = match dib_header {
2520      Ok(returned_dib_header) => returned_dib_header,
2521      Err(e) => return Err(e),
2522    };
2523    let pixel_data = self.get_pixel_data();
2524    let pixel_data = match pixel_data {
2525      Ok(returned_pixel_data) => returned_pixel_data,
2526      Err(e) => return Err(e),
2527    };
2528    let replace_color = self.get_color_of_px(x, y);
2529    let replace_color: [u8; 4] = match replace_color {
2530      Ok(returned_replace_color) => returned_replace_color,
2531      Err(e) => return Err(e),
2532    };
2533    let mut visited: Vec<[u16; 2]> = Vec::new();
2534    let mut queue: Vec<[u16; 2]> = Vec::new();
2535    queue.push([x as u16, y as u16]);
2537    while queue.len() > 0 {
2538      let x2: u16 = queue[0][0];
2541      let y2: u16 = queue[0][1];
2542      if y2+1 < dib_header.height as u16 {
2548        if !visited.contains(&[x2, y2+1]) && !queue.contains(&[x2, y2+1]) {
2549          let down_color = self.get_color_of_px_efficient(x2 as usize, (y2+1) as usize, &dib_header, &pixel_data)?;
2550          if down_color == replace_color {
2551            queue.push([x2, y2+1]);
2552          }
2553        }
2554      }
2555      if y2 != 0 {
2556        if !visited.contains(&[x2, y2-1]) && !queue.contains(&[x2, y2-1]) {
2557          let up_color = self.get_color_of_px_efficient(x2 as usize, (y2-1) as usize, &dib_header, &pixel_data)?;
2559          if up_color == replace_color {
2560            queue.push([x2, y2-1]);
2561          }
2562        }
2563      }
2564      if x2 != 0 {
2565        if !visited.contains(&[x2-1, y2]) && !queue.contains(&[x2-1, y2]) {
2566          let left_color = self.get_color_of_px_efficient((x2-1) as usize, y2 as usize, &dib_header, &pixel_data)?;
2567          if left_color == replace_color {
2568            queue.push([x2-1, y2]);
2569          }
2570        }
2571      }
2572      if x2+1 < dib_header.width as u16 {
2573        if !visited.contains(&[x2+1, y2]) && !queue.contains(&[x2+1, y2]) {
2574          let right_color = self.get_color_of_px_efficient((x2+1) as usize, y2 as usize, &dib_header, &pixel_data)?;
2575          if right_color == replace_color {
2576            queue.push([x2+1, y2]);
2577          }
2578        }
2579      }
2580      visited.push(queue[0]);
2582      queue.remove(0);
2583    }
2584    let header = self.get_header();
2586    for px in &visited {
2587      self.change_color_of_pixel_efficient(px[0], px[1], fill, &dib_header, &header)?;
2588    }
2589    return Ok(visited);
2591  }
2592  pub fn save_to_new(self, file_path: &str) -> Result<(), ErrorKind> {
2595    let mut new_file = fs::File::create(&std::path::Path::new(file_path)).unwrap();
2596    let write_op = new_file.write_all(&self.contents);
2597    match write_op {
2598      Ok(_file) => return Ok(()),
2599      Err(_e) => return Err(ErrorKind::FailedToWrite),
2600    };
2601  }
2602}
2603
2604#[test]
2609fn non_existent_file() {
2610  assert!(BMP::new_from_file("doesnotexist.bmp") == Err(ErrorKind::NotFound));
2611}
2612
2613#[test]
2614fn out_of_bounds_access() {
2615  let mut b = BMP::new(150, 150, None);
2616  assert!(b.get_color_of_pixel(0, 150) == Err(ErrorKind::OutOfBounds));
2617  assert!(b.get_color_of_pixel(150, 0).is_err());
2618  assert!(b.get_color_of_pixel(150, 150).is_err());
2619  assert!(b.get_color_of_pixel(149, 149).is_ok());
2620  assert!(b.change_color_of_pixel(149, 149, [128, 128, 128, 255]).is_ok());
2621  assert!(b.change_color_of_pixel(150, 150, [128, 128, 128, 255]).is_err());
2622}