about summary refs log tree commit diff
diff options
context:
space:
mode:
authorGenny <gen@nyble.dev>2021-10-11 03:36:38 -0500
committerGenny <gen@nyble.dev>2021-10-11 03:36:38 -0500
commit757eab88d67a425728b87286c763387f52367196 (patch)
treef1d61edb0a838787f6984accdd92df68a69d567a
parent9b7bd5696a21496fa0c38a17e69c5c0658acfe73 (diff)
downloadgifed-757eab88d67a425728b87286c763387f52367196.tar.gz
gifed-757eab88d67a425728b87286c763387f52367196.zip
Run rustfmt
-rw-r--r--.rustfmt.toml1
-rw-r--r--benches/lzw_encode.rs24
-rw-r--r--src/block/colortable.rs172
-rw-r--r--src/block/extension/application.rs18
-rw-r--r--src/block/extension/graphiccontrol.rs192
-rw-r--r--src/block/extension/mod.rs64
-rw-r--r--src/block/imagedescriptor.rs102
-rw-r--r--src/block/indexedimage.rs90
-rw-r--r--src/block/mod.rs8
-rw-r--r--src/block/screendescriptor.rs118
-rw-r--r--src/block/version.rs28
-rw-r--r--src/color.rs46
-rw-r--r--src/colorimage.rs90
-rw-r--r--src/gif.rs408
-rw-r--r--src/lib.rs32
-rw-r--r--src/lzw.rs282
-rw-r--r--src/reader/mod.rs526
-rw-r--r--src/writer/gifbuilder.rs190
-rw-r--r--src/writer/imagebuilder.rs246
19 files changed, 1319 insertions, 1318 deletions
diff --git a/.rustfmt.toml b/.rustfmt.toml
new file mode 100644
index 0000000..218e203
--- /dev/null
+++ b/.rustfmt.toml
@@ -0,0 +1 @@
+hard_tabs = true
diff --git a/benches/lzw_encode.rs b/benches/lzw_encode.rs
index aacf4a3..69ed275 100644
--- a/benches/lzw_encode.rs
+++ b/benches/lzw_encode.rs
@@ -4,19 +4,19 @@ use rand::{thread_rng, Rng};
 use weezl::{encode::Encoder, BitOrder};
 
 pub fn criterion_benchmark(c: &mut Criterion) {
-    let mut random = [0u8; 2048];
-    thread_rng().fill(&mut random[..]);
+	let mut random = [0u8; 2048];
+	thread_rng().fill(&mut random[..]);
 
-    c.bench_function("lzw encode 255bytes", |b| {
-        b.iter(|| LZW::encode(8, black_box(&random)))
-    });
-    c.bench_function("weezl encode 255bytes", |b| {
-        b.iter(|| {
-            Encoder::new(BitOrder::Msb, 8)
-                .encode(black_box(&random))
-                .unwrap()
-        })
-    });
+	c.bench_function("lzw encode 255bytes", |b| {
+		b.iter(|| LZW::encode(8, black_box(&random)))
+	});
+	c.bench_function("weezl encode 255bytes", |b| {
+		b.iter(|| {
+			Encoder::new(BitOrder::Msb, 8)
+				.encode(black_box(&random))
+				.unwrap()
+		})
+	});
 }
 
 criterion_group!(benches, criterion_benchmark);
diff --git a/src/block/colortable.rs b/src/block/colortable.rs
index d8241f7..01fe00b 100644
--- a/src/block/colortable.rs
+++ b/src/block/colortable.rs
@@ -1,117 +1,117 @@
 pub use crate::Color;
 use crate::EncodingError;
 use std::{
-    convert::{TryFrom, TryInto},
-    ops::Deref,
+	convert::{TryFrom, TryInto},
+	ops::Deref,
 };
 
 #[derive(Clone, Debug)]
 pub struct ColorTable {
-    table: Vec<Color>,
+	table: Vec<Color>,
 }
 
 impl ColorTable {
-    pub fn new() -> Self {
-        Self { table: vec![] }
-    }
-
-    /// Returns the number of colors in the color table as used by the packed
-    /// fields in the Logical Screen Descriptor and Image Descriptor. You can
-    /// get the actual size with the [`len`](struct.ColorTable.html#method.len) method.
-    pub fn packed_len(&self) -> u8 {
-        ((self.table.len() as f32).log2().ceil() - 1f32) as u8
-    }
-
-    /// Returns the number of items in the table
-    pub fn len(&self) -> usize {
-        self.table.len()
-    }
-
-    /// Pushes a color on to the end of the table
-    pub fn push(&mut self, color: Color) {
-        self.table.push(color);
-    }
-
-    pub fn get(&self, index: u8) -> Option<Color> {
-        self.table.get(index as usize).map(|v| v.clone())
-    }
-
-    pub fn from_color(&self, color: Color) -> Option<u8> {
-        for (i, &c) in self.table.iter().enumerate() {
-            if c == color {
-                return Some(i as u8);
-            }
-        }
-        None
-    }
+	pub fn new() -> Self {
+		Self { table: vec![] }
+	}
+
+	/// Returns the number of colors in the color table as used by the packed
+	/// fields in the Logical Screen Descriptor and Image Descriptor. You can
+	/// get the actual size with the [`len`](struct.ColorTable.html#method.len) method.
+	pub fn packed_len(&self) -> u8 {
+		((self.table.len() as f32).log2().ceil() - 1f32) as u8
+	}
+
+	/// Returns the number of items in the table
+	pub fn len(&self) -> usize {
+		self.table.len()
+	}
+
+	/// Pushes a color on to the end of the table
+	pub fn push(&mut self, color: Color) {
+		self.table.push(color);
+	}
+
+	pub fn get(&self, index: u8) -> Option<Color> {
+		self.table.get(index as usize).map(|v| v.clone())
+	}
+
+	pub fn from_color(&self, color: Color) -> Option<u8> {
+		for (i, &c) in self.table.iter().enumerate() {
+			if c == color {
+				return Some(i as u8);
+			}
+		}
+		None
+	}
 }
 
 impl Deref for ColorTable {
-    type Target = [Color];
+	type Target = [Color];
 
-    fn deref(&self) -> &Self::Target {
-        &self.table
-    }
+	fn deref(&self) -> &Self::Target {
+		&self.table
+	}
 }
 
 impl From<&ColorTable> for Box<[u8]> {
-    fn from(table: &ColorTable) -> Self {
-        let mut vec = vec![];
+	fn from(table: &ColorTable) -> Self {
+		let mut vec = vec![];
 
-        for color in table.iter() {
-            vec.extend_from_slice(&[color.r, color.g, color.b]);
-        }
+		for color in table.iter() {
+			vec.extend_from_slice(&[color.r, color.g, color.b]);
+		}
 
-        let packed_len = 2usize.pow(table.packed_len() as u32 + 1);
-        let padding = (packed_len as usize - table.len()) * 3;
-        if padding > 0 {
-            vec.extend_from_slice(&vec![0; padding]);
-        }
+		let packed_len = 2usize.pow(table.packed_len() as u32 + 1);
+		let padding = (packed_len as usize - table.len()) * 3;
+		if padding > 0 {
+			vec.extend_from_slice(&vec![0; padding]);
+		}
 
-        vec.into_boxed_slice()
-    }
+		vec.into_boxed_slice()
+	}
 }
 
 //TODO: TryFrom Vec<u8> (must be multiple of 3 len) and From Vec<Color>
 impl TryFrom<&[u8]> for ColorTable {
-    type Error = ();
-
-    fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
-        if value.len() % 3 != 0 {
-            return Err(());
-        } else {
-            Ok(Self {
-                table: value
-                    .chunks(3)
-                    .map(|slice| Color::from(TryInto::<[u8; 3]>::try_into(slice).unwrap()))
-                    .collect::<Vec<Color>>(),
-            })
-        }
-    }
+	type Error = ();
+
+	fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
+		if value.len() % 3 != 0 {
+			return Err(());
+		} else {
+			Ok(Self {
+				table: value
+					.chunks(3)
+					.map(|slice| Color::from(TryInto::<[u8; 3]>::try_into(slice).unwrap()))
+					.collect::<Vec<Color>>(),
+			})
+		}
+	}
 }
 
 impl TryFrom<Vec<Color>> for ColorTable {
-    type Error = EncodingError;
-
-    fn try_from(value: Vec<Color>) -> Result<Self, Self::Error> {
-        if value.len() > 256 {
-            Err(EncodingError::TooManyColors)
-        } else {
-            Ok(Self { table: value })
-        }
-    }
+	type Error = EncodingError;
+
+	fn try_from(value: Vec<Color>) -> Result<Self, Self::Error> {
+		if value.len() > 256 {
+			Err(EncodingError::TooManyColors)
+		} else {
+			Ok(Self { table: value })
+		}
+	}
 }
 
 impl TryFrom<Vec<(u8, u8, u8)>> for ColorTable {
-    type Error = EncodingError;
-
-    fn try_from(value: Vec<(u8, u8, u8)>) -> Result<Self, Self::Error> {
-        if value.len() > 256 {
-            Err(EncodingError::TooManyColors)
-        } else {
-            Ok(Self {
-                table: value.into_iter().map(|c| c.into()).collect(),
-            })
-        }
-    }
+	type Error = EncodingError;
+
+	fn try_from(value: Vec<(u8, u8, u8)>) -> Result<Self, Self::Error> {
+		if value.len() > 256 {
+			Err(EncodingError::TooManyColors)
+		} else {
+			Ok(Self {
+				table: value.into_iter().map(|c| c.into()).collect(),
+			})
+		}
+	}
 }
diff --git a/src/block/extension/application.rs b/src/block/extension/application.rs
index b3516d8..9ec1814 100644
--- a/src/block/extension/application.rs
+++ b/src/block/extension/application.rs
@@ -1,15 +1,15 @@
 pub struct Application {
-    pub(crate) identifier: String, // max len 8
-    pub(crate) authentication_code: [u8; 3],
-    pub(crate) data: Vec<u8>,
+	pub(crate) identifier: String, // max len 8
+	pub(crate) authentication_code: [u8; 3],
+	pub(crate) data: Vec<u8>,
 }
 
 impl Application {
-    pub fn identifier(&self) -> &str {
-        &self.identifier
-    }
+	pub fn identifier(&self) -> &str {
+		&self.identifier
+	}
 
-    pub fn authentication_code(&self) -> &[u8] {
-        &self.authentication_code
-    }
+	pub fn authentication_code(&self) -> &[u8] {
+		&self.authentication_code
+	}
 }
diff --git a/src/block/extension/graphiccontrol.rs b/src/block/extension/graphiccontrol.rs
index 830dff4..6bbe4ea 100644
--- a/src/block/extension/graphiccontrol.rs
+++ b/src/block/extension/graphiccontrol.rs
@@ -2,113 +2,113 @@ use std::{convert::TryInto, fmt};
 
 #[derive(Clone, Debug)]
 pub struct GraphicControl {
-    pub(crate) packed: u8,
-    pub(crate) delay_time: u16,
-    pub(crate) transparency_index: u8,
+	pub(crate) packed: u8,
+	pub(crate) delay_time: u16,
+	pub(crate) transparency_index: u8,
 }
 
 impl GraphicControl {
-    pub fn new(
-        disposal_method: DisposalMethod,
-        user_input_flag: bool,
-        transparency_flag: bool,
-        delay_time: u16,
-        transparency_index: u8,
-    ) -> Self {
-        let mut ret = Self {
-            packed: 0,
-            delay_time,
-            transparency_index,
-        };
-
-        ret.set_disposal_method(disposal_method);
-        ret.user_input(user_input_flag);
-        ret.transparency(transparency_flag);
-
-        ret
-    }
-
-    pub fn disposal_method(&self) -> Option<DisposalMethod> {
-        match self.packed & 0b000_111_00 {
-            0b000_000_00 => Some(DisposalMethod::NoAction),
-            0b000_100_00 => Some(DisposalMethod::DoNotDispose),
-            0b000_010_00 => Some(DisposalMethod::RestoreBackground),
-            0b000_110_00 => Some(DisposalMethod::RestorePrevious),
-            _ => None,
-        }
-    }
-
-    pub fn set_disposal_method(&mut self, method: DisposalMethod) {
-        match method {
-            DisposalMethod::NoAction => self.packed &= 0b111_000_1_1,
-            DisposalMethod::DoNotDispose => self.packed |= 0b000_100_0_0,
-            DisposalMethod::RestoreBackground => self.packed |= 0b000_010_0_0,
-            DisposalMethod::RestorePrevious => self.packed |= 0b000_110_0_0,
-        };
-    }
-
-    pub fn transparency_index(&self) -> u8 {
-        self.transparency_index
-    }
-
-    pub fn user_input(&mut self, flag: bool) {
-        if flag {
-            self.packed |= 0b000_000_1_0;
-        } else {
-            self.packed &= 0b111_111_0_1;
-        }
-    }
-
-    pub fn transparency(&mut self, flag: bool) {
-        if flag {
-            self.packed |= 0b000_000_0_1;
-        } else {
-            self.packed &= 0b111_111_1_0;
-        }
-    }
-
-    pub fn delay_time(&self) -> u16 {
-        self.delay_time
-    }
-
-    pub fn delay_time_mut(&mut self) -> &mut u16 {
-        &mut self.delay_time
-    }
-
-    //TODO: Transparency index setter
+	pub fn new(
+		disposal_method: DisposalMethod,
+		user_input_flag: bool,
+		transparency_flag: bool,
+		delay_time: u16,
+		transparency_index: u8,
+	) -> Self {
+		let mut ret = Self {
+			packed: 0,
+			delay_time,
+			transparency_index,
+		};
+
+		ret.set_disposal_method(disposal_method);
+		ret.user_input(user_input_flag);
+		ret.transparency(transparency_flag);
+
+		ret
+	}
+
+	pub fn disposal_method(&self) -> Option<DisposalMethod> {
+		match self.packed & 0b000_111_00 {
+			0b000_000_00 => Some(DisposalMethod::NoAction),
+			0b000_100_00 => Some(DisposalMethod::DoNotDispose),
+			0b000_010_00 => Some(DisposalMethod::RestoreBackground),
+			0b000_110_00 => Some(DisposalMethod::RestorePrevious),
+			_ => None,
+		}
+	}
+
+	pub fn set_disposal_method(&mut self, method: DisposalMethod) {
+		match method {
+			DisposalMethod::NoAction => self.packed &= 0b111_000_1_1,
+			DisposalMethod::DoNotDispose => self.packed |= 0b000_100_0_0,
+			DisposalMethod::RestoreBackground => self.packed |= 0b000_010_0_0,
+			DisposalMethod::RestorePrevious => self.packed |= 0b000_110_0_0,
+		};
+	}
+
+	pub fn transparency_index(&self) -> u8 {
+		self.transparency_index
+	}
+
+	pub fn user_input(&mut self, flag: bool) {
+		if flag {
+			self.packed |= 0b000_000_1_0;
+		} else {
+			self.packed &= 0b111_111_0_1;
+		}
+	}
+
+	pub fn transparency(&mut self, flag: bool) {
+		if flag {
+			self.packed |= 0b000_000_0_1;
+		} else {
+			self.packed &= 0b111_111_1_0;
+		}
+	}
+
+	pub fn delay_time(&self) -> u16 {
+		self.delay_time
+	}
+
+	pub fn delay_time_mut(&mut self) -> &mut u16 {
+		&mut self.delay_time
+	}
+
+	//TODO: Transparency index setter
 }
 
 impl From<[u8; 4]> for GraphicControl {
-    fn from(arr: [u8; 4]) -> Self {
-        let packed = arr[0];
-        let delay_time = u16::from_le_bytes(arr[1..3].try_into().unwrap());
-        let transparency_index = arr[3];
-
-        Self {
-            packed,
-            delay_time,
-            transparency_index,
-        }
-    }
+	fn from(arr: [u8; 4]) -> Self {
+		let packed = arr[0];
+		let delay_time = u16::from_le_bytes(arr[1..3].try_into().unwrap());
+		let transparency_index = arr[3];
+
+		Self {
+			packed,
+			delay_time,
+			transparency_index,
+		}
+	}
 }
 
 #[derive(Clone, Copy, Debug, PartialEq)]
 pub enum DisposalMethod {
-    NoAction,
-    DoNotDispose,
-    RestoreBackground,
-    RestorePrevious,
+	NoAction,
+	DoNotDispose,
+	RestoreBackground,
+	RestorePrevious,
 }
 
 impl fmt::Display for DisposalMethod {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        let st = match self {
-            DisposalMethod::NoAction => "Dispose as Normal",
-            DisposalMethod::DoNotDispose => "No Dispose",
-            DisposalMethod::RestoreBackground => "Restore to background",
-            DisposalMethod::RestorePrevious => "Restore previous image",
-        };
-
-        write!(f, "{}", st)
-    }
+	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+		let st = match self {
+			DisposalMethod::NoAction => "Dispose as Normal",
+			DisposalMethod::DoNotDispose => "No Dispose",
+			DisposalMethod::RestoreBackground => "Restore to background",
+			DisposalMethod::RestorePrevious => "Restore previous image",
+		};
+
+		write!(f, "{}", st)
+	}
 }
diff --git a/src/block/extension/mod.rs b/src/block/extension/mod.rs
index fa712a6..fb5eb20 100644
--- a/src/block/extension/mod.rs
+++ b/src/block/extension/mod.rs
@@ -6,44 +6,44 @@ pub use graphiccontrol::{DisposalMethod, GraphicControl};
 pub use self::application::Application;
 
 pub enum Extension {
-    GraphicControl(GraphicControl),
-    Looping(u16),
-    Comment(Vec<u8>), // Plain Text
-    Application(Application),
+	GraphicControl(GraphicControl),
+	Looping(u16),
+	Comment(Vec<u8>), // Plain Text
+	Application(Application),
 }
 
 impl From<&Extension> for Box<[u8]> {
-    fn from(ext: &Extension) -> Self {
-        let mut vec = vec![];
-        vec.push(0x21); // Push the extension introducer
+	fn from(ext: &Extension) -> Self {
+		let mut vec = vec![];
+		vec.push(0x21); // Push the extension introducer
 
-        match ext {
-            Extension::GraphicControl(gc) => {
-                vec.push(0xF9); // Graphic control label
-                vec.push(0x04); // Block size for this extension is always 4
-                vec.push(gc.packed);
-                vec.extend_from_slice(&gc.delay_time.to_le_bytes());
-                vec.push(gc.transparency_index);
-            }
-            Extension::Looping(count) => {
-                vec.push(0xFF); // Application extension label
-                vec.push(0x0B); // 11 bytes in this block
-                vec.extend_from_slice(b"NETSCAPE2.0"); // App. ident. and "auth code"
-                vec.push(0x03); // Sub-block length
-                vec.push(0x01); // Identifies netscape looping extension
-                vec.extend_from_slice(&count.to_le_bytes());
-            }
-            Extension::Comment(_) => todo!(),
-            Extension::Application(_) => todo!(),
-        }
+		match ext {
+			Extension::GraphicControl(gc) => {
+				vec.push(0xF9); // Graphic control label
+				vec.push(0x04); // Block size for this extension is always 4
+				vec.push(gc.packed);
+				vec.extend_from_slice(&gc.delay_time.to_le_bytes());
+				vec.push(gc.transparency_index);
+			}
+			Extension::Looping(count) => {
+				vec.push(0xFF); // Application extension label
+				vec.push(0x0B); // 11 bytes in this block
+				vec.extend_from_slice(b"NETSCAPE2.0"); // App. ident. and "auth code"
+				vec.push(0x03); // Sub-block length
+				vec.push(0x01); // Identifies netscape looping extension
+				vec.extend_from_slice(&count.to_le_bytes());
+			}
+			Extension::Comment(_) => todo!(),
+			Extension::Application(_) => todo!(),
+		}
 
-        vec.push(0x00); // Zero-length data block indicates end of extension
-        vec.into_boxed_slice()
-    }
+		vec.push(0x00); // Zero-length data block indicates end of extension
+		vec.into_boxed_slice()
+	}
 }
 
 impl From<GraphicControl> for Extension {
-    fn from(gce: GraphicControl) -> Self {
-        Extension::GraphicControl(gce)
-    }
+	fn from(gce: GraphicControl) -> Self {
+		Extension::GraphicControl(gce)
+	}
 }
diff --git a/src/block/imagedescriptor.rs b/src/block/imagedescriptor.rs
index 415bee7..25567b2 100644
--- a/src/block/imagedescriptor.rs
+++ b/src/block/imagedescriptor.rs
@@ -1,73 +1,73 @@
 use std::convert::TryInto;
 
 pub struct ImageDescriptor {
-    // Image Seperator 0x2C is the first byte //
-    pub left: u16,
-    pub top: u16,
-    pub width: u16,
-    pub height: u16,
-    pub packed: u8,
+	// Image Seperator 0x2C is the first byte //
+	pub left: u16,
+	pub top: u16,
+	pub width: u16,
+	pub height: u16,
+	pub packed: u8,
 }
 
 impl ImageDescriptor {
-    pub fn set_color_table_present(&mut self, is_present: bool) {
-        if is_present {
-            self.packed |= 0b1000_0000;
-        } else {
-            self.packed &= 0b0111_1111;
-        }
-    }
+	pub fn set_color_table_present(&mut self, is_present: bool) {
+		if is_present {
+			self.packed |= 0b1000_0000;
+		} else {
+			self.packed &= 0b0111_1111;
+		}
+	}
 
-    pub fn set_color_table_size(&mut self, size: u8) {
-        // GCT size is calulated by raising two to this number plus one,
-        // so we have to work backwards.
-        let size = (size as f32).log2().ceil() - 1f32;
-        self.packed |= size as u8;
-    }
+	pub fn set_color_table_size(&mut self, size: u8) {
+		// GCT size is calulated by raising two to this number plus one,
+		// so we have to work backwards.
+		let size = (size as f32).log2().ceil() - 1f32;
+		self.packed |= size as u8;
+	}
 
-    //TODO: Setter for sort flag in packed field
-    //TODO: Setter for interlace flag in packed field
+	//TODO: Setter for sort flag in packed field
+	//TODO: Setter for interlace flag in packed field
 
-    pub fn color_table_present(&self) -> bool {
-        self.packed & 0b1000_0000 != 0
-    }
+	pub fn color_table_present(&self) -> bool {
+		self.packed & 0b1000_0000 != 0
+	}
 
-    pub fn color_table_size(&self) -> usize {
-        crate::packed_to_color_table_length(self.packed & 0b0000_0111)
-    }
+	pub fn color_table_size(&self) -> usize {
+		crate::packed_to_color_table_length(self.packed & 0b0000_0111)
+	}
 }
 
 impl From<&ImageDescriptor> for Box<[u8]> {
-    fn from(desc: &ImageDescriptor) -> Self {
-        let mut vec = vec![];
+	fn from(desc: &ImageDescriptor) -> Self {
+		let mut vec = vec![];
 
-        vec.push(0x2C); // Image Seperator
-        vec.extend_from_slice(&desc.left.to_le_bytes());
-        vec.extend_from_slice(&desc.top.to_le_bytes());
-        vec.extend_from_slice(&desc.width.to_le_bytes());
-        vec.extend_from_slice(&desc.height.to_le_bytes());
-        vec.push(desc.packed);
+		vec.push(0x2C); // Image Seperator
+		vec.extend_from_slice(&desc.left.to_le_bytes());
+		vec.extend_from_slice(&desc.top.to_le_bytes());
+		vec.extend_from_slice(&desc.width.to_le_bytes());
+		vec.extend_from_slice(&desc.height.to_le_bytes());
+		vec.push(desc.packed);
 
-        vec.into_boxed_slice()
-    }
+		vec.into_boxed_slice()
+	}
 }
 
 impl From<[u8; 9]> for ImageDescriptor {
-    fn from(arr: [u8; 9]) -> Self {
-        let left = u16::from_le_bytes(arr[0..2].try_into().unwrap());
-        let top = u16::from_le_bytes(arr[2..4].try_into().unwrap());
-        let width = u16::from_le_bytes(arr[4..6].try_into().unwrap());
-        let height = u16::from_le_bytes(arr[6..8].try_into().unwrap());
-        let packed = arr[8];
+	fn from(arr: [u8; 9]) -> Self {
+		let left = u16::from_le_bytes(arr[0..2].try_into().unwrap());
+		let top = u16::from_le_bytes(arr[2..4].try_into().unwrap());
+		let width = u16::from_le_bytes(arr[4..6].try_into().unwrap());
+		let height = u16::from_le_bytes(arr[6..8].try_into().unwrap());
+		let packed = arr[8];
 
-        Self {
-            left,
-            top,
-            width,
-            height,
-            packed,
-        }
-    }
+		Self {
+			left,
+			top,
+			width,
+			height,
+			packed,
+		}
+	}
 }
 
 //TODO: Impl to allow changing the packed field easier
diff --git a/src/block/indexedimage.rs b/src/block/indexedimage.rs
index 0be066f..8ed0319 100644
--- a/src/block/indexedimage.rs
+++ b/src/block/indexedimage.rs
@@ -4,67 +4,67 @@ use super::{ColorTable, ImageDescriptor};
 use crate::LZW;
 
 pub struct IndexedImage {
-    pub image_descriptor: ImageDescriptor,
-    pub local_color_table: Option<ColorTable>,
-    pub indicies: Vec<u8>,
+	pub image_descriptor: ImageDescriptor,
+	pub local_color_table: Option<ColorTable>,
+	pub indicies: Vec<u8>,
 }
 
 impl IndexedImage {
-    pub fn left(&self) -> u16 {
-        self.image_descriptor.left
-    }
+	pub fn left(&self) -> u16 {
+		self.image_descriptor.left
+	}
 
-    pub fn top(&self) -> u16 {
-        self.image_descriptor.left
-    }
+	pub fn top(&self) -> u16 {
+		self.image_descriptor.left
+	}
 
-    pub fn width(&self) -> u16 {
-        self.image_descriptor.width
-    }
+	pub fn width(&self) -> u16 {
+		self.image_descriptor.width
+	}
 
-    pub fn height(&self) -> u16 {
-        self.image_descriptor.height
-    }
+	pub fn height(&self) -> u16 {
+		self.image_descriptor.height
+	}
 
-    pub fn as_boxed_slice(&self, minimum_code_size: u8) -> Box<[u8]> {
-        let mut out = vec![];
+	pub fn as_boxed_slice(&self, minimum_code_size: u8) -> Box<[u8]> {
+		let mut out = vec![];
 
-        let mut boxed: Box<[u8]> = (&self.image_descriptor).into();
-        out.extend_from_slice(&*boxed);
+		let mut boxed: Box<[u8]> = (&self.image_descriptor).into();
+		out.extend_from_slice(&*boxed);
 
-        // Get the mcs while we write out the color table
-        let mut mcs = if let Some(lct) = &self.local_color_table {
-            boxed = lct.into();
-            out.extend_from_slice(&*boxed);
+		// Get the mcs while we write out the color table
+		let mut mcs = if let Some(lct) = &self.local_color_table {
+			boxed = lct.into();
+			out.extend_from_slice(&*boxed);
 
-            lct.packed_len()
-        } else {
-            minimum_code_size + 1
-        };
+			lct.packed_len()
+		} else {
+			minimum_code_size + 1
+		};
 
-        if mcs < 2 {
-            mcs = 2; // Must be true: 0 <= mcs <= 8
-        }
+		if mcs < 2 {
+			mcs = 2; // Must be true: 0 <= mcs <= 8
+		}
 
-        // First write out the MCS
-        out.push(mcs);
+		// First write out the MCS
+		out.push(mcs);
 
-        let compressed = LZW::encode(mcs, &self.indicies);
+		let compressed = LZW::encode(mcs, &self.indicies);
 
-        for chunk in compressed.chunks(255) {
-            out.push(chunk.len() as u8);
-            out.extend_from_slice(chunk);
-        }
-        // Data block length 0 to indicate an end
-        out.push(0x00);
+		for chunk in compressed.chunks(255) {
+			out.push(chunk.len() as u8);
+			out.extend_from_slice(chunk);
+		}
+		// Data block length 0 to indicate an end
+		out.push(0x00);
 
-        out.into_boxed_slice()
-    }
+		out.into_boxed_slice()
+	}
 }
 
 pub struct CompressedImage {
-    pub image_descriptor: ImageDescriptor,
-    pub local_color_table: Option<ColorTable>,
-    pub lzw_minimum_code_size: u8,
-    pub blocks: Vec<Vec<u8>>,
+	pub image_descriptor: ImageDescriptor,
+	pub local_color_table: Option<ColorTable>,
+	pub lzw_minimum_code_size: u8,
+	pub blocks: Vec<Vec<u8>>,
 }
diff --git a/src/block/mod.rs b/src/block/mod.rs
index 645c11d..e35224b 100644
--- a/src/block/mod.rs
+++ b/src/block/mod.rs
@@ -15,11 +15,11 @@ pub use version::Version;
 use crate::writer::ImageBuilder;
 
 pub enum Block {
-    IndexedImage(IndexedImage),
-    Extension(extension::Extension),
+	IndexedImage(IndexedImage),
+	Extension(extension::Extension),
 }
 
 enum WriteBlock {
-    ImageBuilder(ImageBuilder),
-    Block(Block),
+	ImageBuilder(ImageBuilder),
+	Block(Block),
 }
diff --git a/src/block/screendescriptor.rs b/src/block/screendescriptor.rs
index 444b44f..dc0257d 100644
--- a/src/block/screendescriptor.rs
+++ b/src/block/screendescriptor.rs
@@ -1,79 +1,79 @@
 use std::convert::TryInto;
 
 pub struct ScreenDescriptor {
-    pub width: u16,
-    pub height: u16,
-    pub packed: u8,
-    pub background_color_index: u8,
-    pub pixel_aspect_ratio: u8,
+	pub width: u16,
+	pub height: u16,
+	pub packed: u8,
+	pub background_color_index: u8,
+	pub pixel_aspect_ratio: u8,
 }
 
 impl ScreenDescriptor {
-    pub fn new(width: u16, height: u16) -> Self {
-        Self {
-            width,
-            height,
-            packed: 0,
-            background_color_index: 0,
-            pixel_aspect_ratio: 0,
-        }
-    }
+	pub fn new(width: u16, height: u16) -> Self {
+		Self {
+			width,
+			height,
+			packed: 0,
+			background_color_index: 0,
+			pixel_aspect_ratio: 0,
+		}
+	}
 
-    pub fn set_color_table_present(&mut self, is_present: bool) {
-        if is_present {
-            self.packed |= 0b1000_0000;
-        } else {
-            self.packed &= 0b0111_1111;
-        }
-    }
+	pub fn set_color_table_present(&mut self, is_present: bool) {
+		if is_present {
+			self.packed |= 0b1000_0000;
+		} else {
+			self.packed &= 0b0111_1111;
+		}
+	}
 
-    pub fn set_color_table_size(&mut self, size: u8) {
-        println!("scts: {}", size);
-        // GCT size is calulated by raising two to this number plus one,
-        // so we have to work backwards.
-        let size = (size as f32).log2().ceil() - 1f32;
-        self.packed |= size as u8;
-    }
+	pub fn set_color_table_size(&mut self, size: u8) {
+		println!("scts: {}", size);
+		// GCT size is calulated by raising two to this number plus one,
+		// so we have to work backwards.
+		let size = (size as f32).log2().ceil() - 1f32;
+		self.packed |= size as u8;
+	}
 
-    //TODO: Setter for sort flag in packed field
-    //TODO: Setter for color resolution in packed field
+	//TODO: Setter for sort flag in packed field
+	//TODO: Setter for color resolution in packed field
 
-    pub fn color_table_present(&self) -> bool {
-        self.packed & 0b1000_0000 != 0
-    }
+	pub fn color_table_present(&self) -> bool {
+		self.packed & 0b1000_0000 != 0
+	}
 
-    pub fn color_table_len(&self) -> usize {
-        crate::packed_to_color_table_length(self.packed & 0b0000_0111)
-    }
+	pub fn color_table_len(&self) -> usize {
+		crate::packed_to_color_table_length(self.packed & 0b0000_0111)
+	}
 }
 
 impl From<&ScreenDescriptor> for Box<[u8]> {
-    fn from(lsd: &ScreenDescriptor) -> Self {
-        let mut vec = vec![];
-        vec.extend_from_slice(&lsd.width.to_le_bytes());
-        vec.extend_from_slice(&lsd.height.to_le_bytes());
-        vec.push(lsd.packed);
-        vec.push(lsd.background_color_index);
-        vec.push(lsd.pixel_aspect_ratio);
+	fn from(lsd: &ScreenDescriptor) -> Self {
+		let mut vec = vec![];
+		vec.extend_from_slice(&lsd.width.to_le_bytes());
+		vec.extend_from_slice(&lsd.height.to_le_bytes());
+		vec.push(lsd.packed);
+		vec.push(lsd.background_color_index);
+		vec.push(lsd.pixel_aspect_ratio);
 
-        vec.into_boxed_slice()
-    }
+		vec.into_boxed_slice()
+	}
 }
 
 impl From<[u8; 7]> for ScreenDescriptor {
-    fn from(arr: [u8; 7]) -> Self {
-        let width = u16::from_le_bytes(arr[0..2].try_into().unwrap());
-        let height = u16::from_le_bytes(arr[2..4].try_into().unwrap());
-        let packed = arr[4];
-        let background_color_index = arr[5];
-        let pixel_aspect_ratio = arr[6];
+	fn from(arr: [u8; 7]) -> Self {
+		let width = u16::from_le_bytes(arr[0..2].try_into().unwrap());
+		let height = u16::from_le_bytes(arr[2..4].try_into().unwrap());
+		let packed = arr[4];
+		let background_color_index = arr[5];
+		let pixel_aspect_ratio = arr[6];
 
-        Self {
-            width,
-            height,
-            packed,
-            background_color_index,
-            pixel_aspect_ratio,
-        }
-    }
+		Self {
+			width,
+			height,
+			packed,
+			background_color_index,
+			pixel_aspect_ratio,
+		}
+	}
 }
diff --git a/src/block/version.rs b/src/block/version.rs
index c52439c..0171ad4 100644
--- a/src/block/version.rs
+++ b/src/block/version.rs
@@ -2,24 +2,24 @@ use std::fmt;
 
 #[derive(Clone, Copy, Debug, PartialEq)]
 pub enum Version {
-    Gif87a,
-    Gif89a,
+	Gif87a,
+	Gif89a,
 }
 
 impl From<&Version> for &[u8] {
-    fn from(version: &Version) -> Self {
-        match version {
-            Version::Gif87a => b"GIF87a",
-            Version::Gif89a => b"GIF89a",
-        }
-    }
+	fn from(version: &Version) -> Self {
+		match version {
+			Version::Gif87a => b"GIF87a",
+			Version::Gif89a => b"GIF89a",
+		}
+	}
 }
 
 impl fmt::Display for Version {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match self {
-            Version::Gif87a => write!(f, "GIF87a"),
-            Version::Gif89a => write!(f, "GIF89a"),
-        }
-    }
+	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+		match self {
+			Version::Gif87a => write!(f, "GIF87a"),
+			Version::Gif89a => write!(f, "GIF89a"),
+		}
+	}
 }
diff --git a/src/color.rs b/src/color.rs
index dd96280..e18ce58 100644
--- a/src/color.rs
+++ b/src/color.rs
@@ -1,38 +1,38 @@
 #[derive(Copy, Clone, Debug, PartialEq)]
 pub struct Color {
-    pub r: u8,
-    pub g: u8,
-    pub b: u8,
+	pub r: u8,
+	pub g: u8,
+	pub b: u8,
 }
 
 impl Color {
-    pub fn new(r: u8, g: u8, b: u8) -> Self {
-        Self { r, g, b }
-    }
+	pub fn new(r: u8, g: u8, b: u8) -> Self {
+		Self { r, g, b }
+	}
 }
 
 impl From<[u8; 3]> for Color {
-    fn from(arr: [u8; 3]) -> Self {
-        Self {
-            r: arr[0],
-            g: arr[1],
-            b: arr[2],
-        }
-    }
+	fn from(arr: [u8; 3]) -> Self {
+		Self {
+			r: arr[0],
+			g: arr[1],
+			b: arr[2],
+		}
+	}
 }
 
 impl From<(u8, u8, u8)> for Color {
-    fn from(t: (u8, u8, u8)) -> Self {
-        Self {
-            r: t.0,
-            g: t.1,
-            b: t.2,
-        }
-    }
+	fn from(t: (u8, u8, u8)) -> Self {
+		Self {
+			r: t.0,
+			g: t.1,
+			b: t.2,
+		}
+	}
 }
 
 impl Into<[u8; 3]> for Color {
-    fn into(self) -> [u8; 3] {
-        [self.r, self.g, self.b]
-    }
+	fn into(self) -> [u8; 3] {
+		[self.r, self.g, self.b]
+	}
 }
diff --git a/src/colorimage.rs b/src/colorimage.rs
index 1bdb273..69dac1e 100644
--- a/src/colorimage.rs
+++ b/src/colorimage.rs
@@ -3,59 +3,59 @@ use std::convert::TryFrom;
 use crate::{block::ColorTable, gif::Image, reader::DecodingError, Color};
 
 pub struct ColorImage {
-    width: u16,
-    height: u16,
-    data: Vec<Pixel>,
+	width: u16,
+	height: u16,
+	data: Vec<Pixel>,
 }
 
 impl ColorImage {
-    pub(crate) fn from_indicies(
-        width: u16,
-        height: u16,
-        indicies: &[u8],
-        table: &ColorTable,
-        transindex: Option<u8>,
-    ) -> Result<Self, DecodingError> {
-        let mut data = vec![Pixel::Transparent; (width * height) as usize];
-
-        for (image_index, color_index) in indicies.into_iter().enumerate() {
-            if let Some(trans) = transindex {
-                if trans == *color_index {
-                    data[image_index] = Pixel::Transparent;
-                }
-            } else {
-                data[image_index] = Pixel::Color(
-                    table
-                        .get(*color_index)
-                        .ok_or(DecodingError::ColorIndexOutOfBounds)?,
-                );
-            }
-        }
-
-        Ok(ColorImage {
-            width,
-            height,
-            data,
-        })
-    }
+	pub(crate) fn from_indicies(
+		width: u16,
+		height: u16,
+		indicies: &[u8],
+		table: &ColorTable,
+		transindex: Option<u8>,
+	) -> Result<Self, DecodingError> {
+		let mut data = vec![Pixel::Transparent; (width * height) as usize];
+
+		for (image_index, color_index) in indicies.into_iter().enumerate() {
+			if let Some(trans) = transindex {
+				if trans == *color_index {
+					data[image_index] = Pixel::Transparent;
+				}
+			} else {
+				data[image_index] = Pixel::Color(
+					table
+						.get(*color_index)
+						.ok_or(DecodingError::ColorIndexOutOfBounds)?,
+				);
+			}
+		}
+
+		Ok(ColorImage {
+			width,
+			height,
+			data,
+		})
+	}
 }
 
 impl<'a> TryFrom<Image<'a>> for ColorImage {
-    type Error = DecodingError;
-
-    fn try_from(img: Image<'a>) -> Result<Self, Self::Error> {
-        ColorImage::from_indicies(
-            img.width,
-            img.height,
-            img.indicies,
-            img.palette,
-            img.transparent_index,
-        )
-    }
+	type Error = DecodingError;
+
+	fn try_from(img: Image<'a>) -> Result<Self, Self::Error> {
+		ColorImage::from_indicies(
+			img.width,
+			img.height,
+			img.indicies,
+			img.palette,
+			img.transparent_index,
+		)
+	}
 }
 
 #[derive(Copy, Clone, Debug, PartialEq)]
 pub enum Pixel {
-    Color(Color),
-    Transparent,
+	Color(Color),
+	Transparent,
 }
diff --git a/src/gif.rs b/src/gif.rs
index 3a56850..da7a1d9 100644
--- a/src/gif.rs
+++ b/src/gif.rs
@@ -1,231 +1,231 @@
 use std::{fs::File, io::Write, path::Path};
 
 use crate::{
-    block::{extension::Extension, Block, ColorTable, ScreenDescriptor, Version},
-    colorimage,
-    writer::GifBuilder,
-    ColorImage,
+	block::{extension::Extension, Block, ColorTable, ScreenDescriptor, Version},
+	colorimage,
+	writer::GifBuilder,
+	ColorImage,
 };
 pub struct Gif {
-    pub header: Version,
-    pub screen_descriptor: ScreenDescriptor,
-    pub global_color_table: Option<ColorTable>,
-    pub blocks: Vec<Block>, // Trailer at the end of this struct is 0x3B //
+	pub header: Version,
+	pub screen_descriptor: ScreenDescriptor,
+	pub global_color_table: Option<ColorTable>,
+	pub blocks: Vec<Block>, // Trailer at the end of this struct is 0x3B //
 }
 
 impl Gif {
-    pub fn builder(width: u16, height: u16) -> GifBuilder {
-        GifBuilder::new(width, height)
-    }
-
-    pub fn to_vec(&self) -> Vec<u8> {
-        let mut out = vec![];
-
-        out.extend_from_slice((&self.header).into());
-
-        let mut boxed: Box<[u8]> = (&self.screen_descriptor).into();
-        out.extend_from_slice(&*boxed);
-
-        // While we output the color table, grab it's length to use when
-        // outputting the image, or 0 if we don't have a GCT
-        let mcs = if let Some(gct) = &self.global_color_table {
-            boxed = gct.into();
-            out.extend_from_slice(&*boxed);
-
-            gct.packed_len()
-        } else {
-            0
-        };
-
-        for block in self.blocks.iter() {
-            match block {
-                Block::IndexedImage(image) => {
-                    boxed = image.as_boxed_slice(mcs);
-                    out.extend_from_slice(&*boxed);
-                }
-                //Block::BlockedImage(_) => unreachable!(),
-                Block::Extension(ext) => {
-                    boxed = ext.into();
-                    out.extend_from_slice(&*boxed);
-                }
-            }
-        }
-
-        // Write Trailer
-        out.push(0x3B);
-
-        out
-    }
-
-    pub fn save<P: AsRef<Path>>(&self, path: P) -> std::io::Result<()> {
-        File::create(path.as_ref())?.write_all(&self.to_vec())
-    }
-
-    pub fn images<'a>(&'a self) -> ImageIterator<'a> {
-        ImageIterator { inner: self }
-    }
+	pub fn builder(width: u16, height: u16) -> GifBuilder {
+		GifBuilder::new(width, height)
+	}
+
+	pub fn to_vec(&self) -> Vec<u8> {
+		let mut out = vec![];
+
+		out.extend_from_slice((&self.header).into());
+
+		let mut boxed: Box<[u8]> = (&self.screen_descriptor).into();
+		out.extend_from_slice(&*boxed);
+
+		// While we output the color table, grab it's length to use when
+		// outputting the image, or 0 if we don't have a GCT
+		let mcs = if let Some(gct) = &self.global_color_table {
+			boxed = gct.into();
+			out.extend_from_slice(&*boxed);
+
+			gct.packed_len()
+		} else {
+			0
+		};
+
+		for block in self.blocks.iter() {
+			match block {
+				Block::IndexedImage(image) => {
+					boxed = image.as_boxed_slice(mcs);
+					out.extend_from_slice(&*boxed);
+				}
+				//Block::BlockedImage(_) => unreachable!(),
+				Block::Extension(ext) => {
+					boxed = ext.into();
+					out.extend_from_slice(&*boxed);
+				}
+			}
+		}
+
+		// Write Trailer
+		out.push(0x3B);
+
+		out
+	}
+
+	pub fn save<P: AsRef<Path>>(&self, path: P) -> std::io::Result<()> {
+		File::create(path.as_ref())?.write_all(&self.to_vec())
+	}
+
+	pub fn images<'a>(&'a self) -> ImageIterator<'a> {
+		ImageIterator { inner: self }
+	}
 }
 
 pub struct ImageIterator<'a> {
-    inner: &'a Gif,
+	inner: &'a Gif,
 }
 
 impl<'a> Iterator for ImageIterator<'a> {
-    type Item = Image<'a>;
+	type Item = Image<'a>;
 
-    fn next(&mut self) -> Option<Self::Item> {
-        todo!()
-    }
+	fn next(&mut self) -> Option<Self::Item> {
+		todo!()
+	}
 }
 
 pub struct Image<'a> {
-    pub(crate) width: u16,
-    pub(crate) height: u16,
-    left_offset: u16,
-    top_offset: u16,
-    pub(crate) palette: &'a ColorTable,
-    pub(crate) transparent_index: Option<u8>,
-    pub(crate) indicies: &'a [u8],
+	pub(crate) width: u16,
+	pub(crate) height: u16,
+	left_offset: u16,
+	top_offset: u16,
+	pub(crate) palette: &'a ColorTable,
+	pub(crate) transparent_index: Option<u8>,
+	pub(crate) indicies: &'a [u8],
 }
 
 impl<'a> Image<'a> {
-    pub fn dimesnions(&self) -> (u16, u16) {
-        (self.width, self.height)
-    }
+	pub fn dimesnions(&self) -> (u16, u16) {
+		(self.width, self.height)
+	}
 
-    pub fn position(&self) -> (u16, u16) {
-        (self.left_offset, self.top_offset)
-    }
+	pub fn position(&self) -> (u16, u16) {
+		(self.left_offset, self.top_offset)
+	}
 }
 
 #[cfg(test)]
 pub mod gif {
-    use std::convert::TryInto;
-    use std::io::Write;
-
-    use crate::block::extension::DisposalMethod;
-    use crate::writer::{GifBuilder, ImageBuilder};
-    use crate::Color;
-
-    #[test]
-    fn to_vec_gif87a() {
-        let gct = vec![Color::new(1, 2, 3), Color::new(253, 254, 255)];
-        let colortable = vec![Color::new(0, 0, 0), Color::new(128, 0, 255)];
-        let indicies = vec![0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0];
-
-        let expected_out = vec![
-            0x47,
-            0x49,
-            0x46,
-            0x38,
-            0x37,
-            0x61, // Version - GIF87a
-            0x04,
-            0x00,
-            0x04,
-            0x00,
-            0b1000_0000,
-            0x00,
-            0x00, // Logical Screen Descriptor
-            1,
-            2,
-            3,
-            253,
-            254,
-            255, // Global Color Table
-            0x2C,
-            0x00,
-            0x00,
-            0x00,
-            0x00,
-            0x04,
-            0x00,
-            0x04,
-            0x00,
-            0b1000_0000, // Image Descriptor 1
-            0,
-            0,
-            0,
-            128,
-            0,
-            255, // Color Table
-            0x02,
-            0x05,
-            0x84,
-            0x1D,
-            0x81,
-            0x7A,
-            0x50,
-            0x00, // Image Data 1
-            0x2C,
-            0x00,
-            0x00,
-            0x00,
-            0x00,
-            0x04,
-            0x00,
-            0x04,
-            0x00,
-            0b0000_0000, // Image Descriptor 2
-            0x02,
-            0x05,
-            0x84,
-            0x1D,
-            0x81,
-            0x7A,
-            0x50,
-            0x00, // Image Data 2
-            0x3B, // Trailer
-        ];
-
-        let actual = GifBuilder::new(4, 4)
-            .palette(gct.try_into().unwrap())
-            .image(
-                ImageBuilder::new(4, 4)
-                    .palette(colortable.try_into().unwrap())
-                    .indicies(&indicies),
-            )
-            .image(ImageBuilder::new(4, 4).indicies(&indicies));
-
-        let bytes = actual.build().unwrap().to_vec();
-        assert_eq!(bytes, expected_out);
-    }
-
-    #[test]
-    fn to_vec_gif89a() {
-        let gct = vec![Color::new(1, 2, 3), Color::new(253, 254, 255)];
-        let colortable = vec![Color::new(0, 0, 0), Color::new(128, 0, 255)];
-        let indicies = vec![0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0];
-
-        let expected_out = vec![
-            71, 73, 70, 56, 57, 97, 4, 0, 4, 0, 128, 0, 0, 1, 2, 3, 253, 254, 255, 33, 249, 4, 8,
-            64, 0, 0, 0, 44, 0, 0, 0, 0, 4, 0, 4, 0, 128, 0, 0, 0, 128, 0, 255, 2, 5, 132, 29, 129,
-            122, 80, 0, 44, 0, 0, 0, 0, 4, 0, 4, 0, 0, 2, 5, 132, 29, 129, 122, 80, 0, 59,
-        ];
-
-        let actual_out = GifBuilder::new(4, 4)
-            .palette(gct.try_into().unwrap())
-            .image(
-                ImageBuilder::new(4, 4)
-                    .palette(colortable.try_into().unwrap())
-                    .indicies(&indicies)
-                    .disposal_method(DisposalMethod::RestoreBackground)
-                    .delay(64),
-            )
-            .image(ImageBuilder::new(4, 4).indicies(&indicies))
-            .build()
-            .unwrap()
-            .to_vec();
-
-        std::fs::File::create("ah.gif")
-            .unwrap()
-            .write_all(&actual_out)
-            .unwrap();
-        std::fs::File::create("ah_hand.gif")
-            .unwrap()
-            .write_all(&expected_out)
-            .unwrap();
-
-        assert_eq!(actual_out, expected_out);
-    }
+	use std::convert::TryInto;
+	use std::io::Write;
+
+	use crate::block::extension::DisposalMethod;
+	use crate::writer::{GifBuilder, ImageBuilder};
+	use crate::Color;
+
+	#[test]
+	fn to_vec_gif87a() {
+		let gct = vec![Color::new(1, 2, 3), Color::new(253, 254, 255)];
+		let colortable = vec![Color::new(0, 0, 0), Color::new(128, 0, 255)];
+		let indicies = vec![0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0];
+
+		let expected_out = vec![
+			0x47,
+			0x49,
+			0x46,
+			0x38,
+			0x37,
+			0x61, // Version - GIF87a
+			0x04,
+			0x00,
+			0x04,
+			0x00,
+			0b1000_0000,
+			0x00,
+			0x00, // Logical Screen Descriptor
+			1,
+			2,
+			3,
+			253,
+			254,
+			255, // Global Color Table
+			0x2C,
+			0x00,
+			0x00,
+			0x00,
+			0x00,
+			0x04,
+			0x00,
+			0x04,
+			0x00,
+			0b1000_0000, // Image Descriptor 1
+			0,
+			0,
+			0,
+			128,
+			0,
+			255, // Color Table
+			0x02,
+			0x05,
+			0x84,
+			0x1D,
+			0x81,
+			0x7A,
+			0x50,
+			0x00, // Image Data 1
+			0x2C,
+			0x00,
+			0x00,
+			0x00,
+			0x00,
+			0x04,
+			0x00,
+			0x04,
+			0x00,
+			0b0000_0000, // Image Descriptor 2
+			0x02,
+			0x05,
+			0x84,
+			0x1D,
+			0x81,
+			0x7A,
+			0x50,
+			0x00, // Image Data 2
+			0x3B, // Trailer
+		];
+
+		let actual = GifBuilder::new(4, 4)
+			.palette(gct.try_into().unwrap())
+			.image(
+				ImageBuilder::new(4, 4)
+					.palette(colortable.try_into().unwrap())
+					.indicies(&indicies),
+			)
+			.image(ImageBuilder::new(4, 4).indicies(&indicies));
+
+		let bytes = actual.build().unwrap().to_vec();
+		assert_eq!(bytes, expected_out);
+	}
+
+	#[test]
+	fn to_vec_gif89a() {
+		let gct = vec![Color::new(1, 2, 3), Color::new(253, 254, 255)];
+		let colortable = vec![Color::new(0, 0, 0), Color::new(128, 0, 255)];
+		let indicies = vec![0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0];
+
+		let expected_out = vec![
+			71, 73, 70, 56, 57, 97, 4, 0, 4, 0, 128, 0, 0, 1, 2, 3, 253, 254, 255, 33, 249, 4, 8,
+			64, 0, 0, 0, 44, 0, 0, 0, 0, 4, 0, 4, 0, 128, 0, 0, 0, 128, 0, 255, 2, 5, 132, 29, 129,
+			122, 80, 0, 44, 0, 0, 0, 0, 4, 0, 4, 0, 0, 2, 5, 132, 29, 129, 122, 80, 0, 59,
+		];
+
+		let actual_out = GifBuilder::new(4, 4)
+			.palette(gct.try_into().unwrap())
+			.image(
+				ImageBuilder::new(4, 4)
+					.palette(colortable.try_into().unwrap())
+					.indicies(&indicies)
+					.disposal_method(DisposalMethod::RestoreBackground)
+					.delay(64),
+			)
+			.image(ImageBuilder::new(4, 4).indicies(&indicies))
+			.build()
+			.unwrap()
+			.to_vec();
+
+		std::fs::File::create("ah.gif")
+			.unwrap()
+			.write_all(&actual_out)
+			.unwrap();
+		std::fs::File::create("ah_hand.gif")
+			.unwrap()
+			.write_all(&expected_out)
+			.unwrap();
+
+		assert_eq!(actual_out, expected_out);
+	}
 }
diff --git a/src/lib.rs b/src/lib.rs
index c7d820d..0a11fdc 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -18,7 +18,7 @@ pub use lzw::LZW;
 /// Perform the algorithm to get the length of a color table from
 /// the value of the packed field. The max value here is 256
 pub(crate) fn packed_to_color_table_length(packed: u8) -> usize {
-    2usize.pow(packed as u32 + 1)
+	2usize.pow(packed as u32 + 1)
 }
 
 //TODO: Be sure to check that fields in LSD and Img. Desc. that were reserved
@@ -28,24 +28,24 @@ pub(crate) fn packed_to_color_table_length(packed: u8) -> usize {
 
 #[derive(Clone, Copy, Debug)]
 pub enum EncodingError {
-    TooManyColors,
-    NoColorTable,
-    IndicieSizeMismatch { expected: usize, got: usize },
+	TooManyColors,
+	NoColorTable,
+	IndicieSizeMismatch { expected: usize, got: usize },
 }
 
 impl fmt::Display for EncodingError {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match self {
-            Self::TooManyColors => write!(f, "A palette is limited to 256 colors"),
-            Self::NoColorTable => write!(
-                f,
-                "Refusing to set the background color index when no color table is set!"
-            ),
-            Self::IndicieSizeMismatch { expected, got } => {
-                write!(f, "Expected to have {} indicies but got {}", expected, got)
-            }
-        }
-    }
+	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+		match self {
+			Self::TooManyColors => write!(f, "A palette is limited to 256 colors"),
+			Self::NoColorTable => write!(
+				f,
+				"Refusing to set the background color index when no color table is set!"
+			),
+			Self::IndicieSizeMismatch { expected, got } => {
+				write!(f, "Expected to have {} indicies but got {}", expected, got)
+			}
+		}
+	}
 }
 
 impl Error for EncodingError {}
diff --git a/src/lzw.rs b/src/lzw.rs
index 053c5c4..dce6a5d 100644
--- a/src/lzw.rs
+++ b/src/lzw.rs
@@ -2,172 +2,172 @@ use std::collections::HashMap;
 
 pub struct LZW {}
 impl LZW {
-    pub fn encode(minimum_size: u8, indicies: &[u8]) -> Vec<u8> {
-        let mut dictionary: HashMap<Vec<u8>, u16> = HashMap::new();
-
-        let cc = 2u16.pow(minimum_size as u32);
-        let eoi = cc + 1;
-
-        // Fill dictionary with self-descriptive values
-        for value in 0..cc {
-            dictionary.insert(vec![value as u8], value);
-        }
-
-        let mut next_code = eoi + 1;
-        let mut code_size = minimum_size + 1;
-
-        let mut iter = indicies.into_iter();
-        let mut out = BitStream::new();
-        let mut buffer = vec![*iter.next().unwrap()];
-
-        out.push_bits(code_size, cc);
-
-        for &indicie in iter {
-            buffer.push(indicie);
-
-            if !dictionary.contains_key(&buffer) {
-                buffer.pop();
-
-                if let Some(&code) = dictionary.get(&buffer) {
-                    out.push_bits(code_size, code);
-
-                    // Put the code back and add the vec to the dict
-                    buffer.push(indicie);
-                    dictionary.insert(buffer.clone(), next_code);
-                    next_code += 1;
-
-                    // If the next_code can't fit in the code_size, we have to increase it
-                    if next_code - 1 == 2u16.pow(code_size as u32) {
-                        code_size += 1;
-                    }
-
-                    buffer.clear();
-                    buffer.push(indicie);
-                } else {
-                    unreachable!()
-                }
-            }
-        }
-
-        if buffer.len() > 0 {
-            match dictionary.get(&buffer) {
-                Some(&code) => out.push_bits(code_size, code),
-                None => {
-                    panic!("Codes left in the buffer but the buffer is not a valid dictionary key!")
-                }
-            }
-        }
-        out.push_bits(code_size, eoi);
-
-        out.vec()
-    }
+	pub fn encode(minimum_size: u8, indicies: &[u8]) -> Vec<u8> {
+		let mut dictionary: HashMap<Vec<u8>, u16> = HashMap::new();
+
+		let cc = 2u16.pow(minimum_size as u32);
+		let eoi = cc + 1;
+
+		// Fill dictionary with self-descriptive values
+		for value in 0..cc {
+			dictionary.insert(vec![value as u8], value);
+		}
+
+		let mut next_code = eoi + 1;
+		let mut code_size = minimum_size + 1;
+
+		let mut iter = indicies.into_iter();
+		let mut out = BitStream::new();
+		let mut buffer = vec![*iter.next().unwrap()];
+
+		out.push_bits(code_size, cc);
+
+		for &indicie in iter {
+			buffer.push(indicie);
+
+			if !dictionary.contains_key(&buffer) {
+				buffer.pop();
+
+				if let Some(&code) = dictionary.get(&buffer) {
+					out.push_bits(code_size, code);
+
+					// Put the code back and add the vec to the dict
+					buffer.push(indicie);
+					dictionary.insert(buffer.clone(), next_code);
+					next_code += 1;
+
+					// If the next_code can't fit in the code_size, we have to increase it
+					if next_code - 1 == 2u16.pow(code_size as u32) {
+						code_size += 1;
+					}
+
+					buffer.clear();
+					buffer.push(indicie);
+				} else {
+					unreachable!()
+				}
+			}
+		}
+
+		if buffer.len() > 0 {
+			match dictionary.get(&buffer) {
+				Some(&code) => out.push_bits(code_size, code),
+				None => {
+					panic!("Codes left in the buffer but the buffer is not a valid dictionary key!")
+				}
+			}
+		}
+		out.push_bits(code_size, eoi);
+
+		out.vec()
+	}
 }
 
 #[cfg(test)]
 mod lzw_test {
-    use super::*;
+	use super::*;
 
-    #[test]
-    fn encode() {
-        let indicies = vec![0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0];
-        let output = vec![0x84, 0x1D, 0x81, 0x7A, 0x50];
+	#[test]
+	fn encode() {
+		let indicies = vec![0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0];
+		let output = vec![0x84, 0x1D, 0x81, 0x7A, 0x50];
 
-        let lzout = LZW::encode(2, &indicies);
+		let lzout = LZW::encode(2, &indicies);
 
-        assert_eq!(lzout, output);
-    }
+		assert_eq!(lzout, output);
+	}
 
-    #[test]
-    fn against_weezl() {
-        let indicies = vec![0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0];
-        let weezl = weezl::encode::Encoder::new(weezl::BitOrder::Lsb, 2)
-            .encode(&indicies)
-            .unwrap();
-        let us = LZW::encode(2, &indicies);
+	#[test]
+	fn against_weezl() {
+		let indicies = vec![0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0];
+		let weezl = weezl::encode::Encoder::new(weezl::BitOrder::Lsb, 2)
+			.encode(&indicies)
+			.unwrap();
+		let us = LZW::encode(2, &indicies);
 
-        assert_eq!(weezl, us);
-    }
+		assert_eq!(weezl, us);
+	}
 }
 
 struct BitStream {
-    formed: Vec<u8>,
-    current: u8,
-    index: u8,
+	formed: Vec<u8>,
+	current: u8,
+	index: u8,
 }
 
 impl BitStream {
-    fn new() -> Self {
-        Self {
-            formed: vec![],
-            current: 0,
-            index: 0,
-        }
-    }
-
-    fn push_bits(&mut self, count: u8, data: u16) {
-        let mut new_index = self.index + count;
-        let mut current32 = (self.current as u32) | ((data as u32) << self.index);
-
-        loop {
-            if new_index >= 8 {
-                self.formed.push(current32 as u8);
-                current32 = current32 >> 8;
-                new_index -= 8;
-            } else {
-                self.current = current32 as u8;
-                self.index = new_index;
-
-                break;
-            }
-        }
-    }
-
-    fn vec(self) -> Vec<u8> {
-        let mut out = self.formed;
-
-        if self.index != 0 {
-            out.push(self.current);
-        }
-
-        out
-    }
+	fn new() -> Self {
+		Self {
+			formed: vec![],
+			current: 0,
+			index: 0,
+		}
+	}
+
+	fn push_bits(&mut self, count: u8, data: u16) {
+		let mut new_index = self.index + count;
+		let mut current32 = (self.current as u32) | ((data as u32) << self.index);
+
+		loop {
+			if new_index >= 8 {
+				self.formed.push(current32 as u8);
+				current32 = current32 >> 8;
+				new_index -= 8;
+			} else {
+				self.current = current32 as u8;
+				self.index = new_index;
+
+				break;
+			}
+		}
+	}
+
+	fn vec(self) -> Vec<u8> {
+		let mut out = self.formed;
+
+		if self.index != 0 {
+			out.push(self.current);
+		}
+
+		out
+	}
 }
 
 #[cfg(test)]
 mod bitstream_test {
-    use super::*;
+	use super::*;
 
-    #[test]
-    fn short_push() {
-        let mut bs = BitStream::new();
-        bs.push_bits(2, 3);
-        bs.push_bits(2, 3);
-        bs.push_bits(3, 1);
-        bs.push_bits(2, 3);
+	#[test]
+	fn short_push() {
+		let mut bs = BitStream::new();
+		bs.push_bits(2, 3);
+		bs.push_bits(2, 3);
+		bs.push_bits(3, 1);
+		bs.push_bits(2, 3);
 
-        let bsvec = bs.vec();
+		let bsvec = bs.vec();
 
-        for byte in &bsvec {
-            print!("{:b} ", byte);
-        }
-        println!("");
+		for byte in &bsvec {
+			print!("{:b} ", byte);
+		}
+		println!("");
 
-        assert_eq!(bsvec, vec![0b1001_1111, 0b0000_0001]);
-    }
+		assert_eq!(bsvec, vec![0b1001_1111, 0b0000_0001]);
+	}
 
-    #[test]
-    fn long_push() {
-        let mut bs = BitStream::new();
-        bs.push_bits(1, 1);
-        bs.push_bits(12, 2049);
+	#[test]
+	fn long_push() {
+		let mut bs = BitStream::new();
+		bs.push_bits(1, 1);
+		bs.push_bits(12, 2049);
 
-        let bsvec = bs.vec();
+		let bsvec = bs.vec();
 
-        for byte in &bsvec {
-            print!("{:b} ", byte);
-        }
-        println!("");
+		for byte in &bsvec {
+			print!("{:b} ", byte);
+		}
+		println!("");
 
-        assert_eq!(bsvec, vec![0b0000_0011, 0b0001_0000]);
-    }
+		assert_eq!(bsvec, vec![0b0000_0011, 0b0001_0000]);
+	}
 }
diff --git a/src/reader/mod.rs b/src/reader/mod.rs
index 1b52874..7cf1fe1 100644
--- a/src/reader/mod.rs
+++ b/src/reader/mod.rs
@@ -1,290 +1,290 @@
 use std::{
-    borrow::Cow,
-    convert::{TryFrom, TryInto},
-    error::Error,
-    fmt,
-    fs::File,
-    io::{BufRead, BufReader, Read},
-    path::Path,
+	borrow::Cow,
+	convert::{TryFrom, TryInto},
+	error::Error,
+	fmt,
+	fs::File,
+	io::{BufRead, BufReader, Read},
+	path::Path,
 };
 
 use crate::{
-    block::{
-        extension::{Application, Extension, GraphicControl},
-        Block, ColorTable, CompressedImage, ImageDescriptor, IndexedImage, ScreenDescriptor,
-        Version,
-    },
-    color, Gif,
+	block::{
+		extension::{Application, Extension, GraphicControl},
+		Block, ColorTable, CompressedImage, ImageDescriptor, IndexedImage, ScreenDescriptor,
+		Version,
+	},
+	color, Gif,
 };
 
 pub struct GifReader {}
 
 impl GifReader {
-    pub fn file<P: AsRef<Path>>(path: P) -> Result<Gif, DecodingError> {
-        let mut file = File::open(path)?;
-        let mut reader = SmartReader {
-            inner: vec![],
-            position: 0,
-        };
-        file.read_to_end(&mut reader.inner)?;
-
-        let mut gif = Self::read_required(&mut reader)?;
-
-        if gif.screen_descriptor.color_table_present() {
-            let gct_size = gif.screen_descriptor.color_table_len() * 3;
-            gif.global_color_table = Some(Self::read_color_table(&mut reader, gct_size)?);
-        }
-
-        loop {
-            match Self::read_block(&mut reader)? {
-                Some(block) => {
-                    /*match &block {
-                        Block::IndexedImage(_) => println!("Indexed Image"),
-                        Block::BlockedImage(_) => println!("Blocked Image"),
-                        Block::Extension(ext) => match ext {
-                            Extension::GraphicControl(_) => println!("Graphic Cotrol Extension"),
-                            Extension::Looping(_) => println!("Netscape Extension"),
-                            Extension::Comment(vec) => {
-                                println!("Comment Extension {:X}", vec.len())
-                            }
-                            Extension::Application(_) => todo!(),
-                        },
-                    }*/
-
-                    gif.blocks.push(block)
-                }
-                None => return Ok(gif),
-            }
-        }
-    }
-
-    fn read_required(reader: &mut SmartReader) -> Result<Gif, DecodingError> {
-        let version = match reader.take_lossy_utf8(6).as_deref() {
-            Some("GIF87a") => Version::Gif87a,
-            Some("GIF89a") => Version::Gif89a,
-            _ => return Err(DecodingError::UnknownVersionString),
-        };
-
-        let mut lsd_buffer: [u8; 7] = [0; 7];
-        reader
-            .read_exact(&mut lsd_buffer)
-            .ok_or(DecodingError::UnexpectedEof)?;
-
-        let lsd = ScreenDescriptor::from(lsd_buffer);
-
-        Ok(Gif {
-            header: version,
-            screen_descriptor: lsd,
-            global_color_table: None,
-            blocks: vec![],
-        })
-    }
-
-    fn read_color_table(
-        reader: &mut SmartReader,
-        size: usize,
-    ) -> Result<ColorTable, DecodingError> {
-        let buffer = reader
-            .take(size as usize)
-            .ok_or(DecodingError::UnexpectedEof)?;
-
-        // We get the size from the screen descriptor. This should never return Err
-        Ok(ColorTable::try_from(&buffer[..]).unwrap())
-    }
-
-    fn read_block(reader: &mut SmartReader) -> Result<Option<Block>, DecodingError> {
-        let block_id = reader.u8().ok_or(DecodingError::UnexpectedEof)?;
-
-        //TODO: remove panic
-        match block_id {
-            0x21 => Self::read_extension(reader).map(|block| Some(block)),
-            0x2C => Self::read_image(reader).map(|block| Some(block)),
-            0x3B => Ok(None),
-            _ => panic!(
-                "Unknown block identifier {:X} {:X}",
-                block_id, reader.position
-            ),
-        }
-    }
-
-    fn read_extension(reader: &mut SmartReader) -> Result<Block, DecodingError> {
-        let extension_id = reader.u8().expect("File ended early");
-
-        match extension_id {
-            0xF9 => {
-                reader.skip(1); // Skip block length, we know it
-                let mut data = [0u8; 4];
-                reader
-                    .read_exact(&mut data)
-                    .ok_or(DecodingError::UnexpectedEof)?;
-                reader.skip(1); // Skip block terminator
-
-                Ok(Block::Extension(Extension::GraphicControl(
-                    GraphicControl::from(data),
-                )))
-            }
-            0xFE => Ok(Block::Extension(Extension::Comment(
-                reader.take_and_collapse_subblocks(),
-            ))),
-            0x01 => todo!(), //TODO: do; plain text extension
-            0xFF => {
-                //TODO: error instead of unwraps
-                assert_eq!(Some(11), reader.u8());
-                let identifier = reader.take_lossy_utf8(8).unwrap().to_string();
-                let authentication_code: [u8; 3] =
-                    TryInto::try_into(reader.take(3).unwrap()).unwrap();
-                let data = reader.take_and_collapse_subblocks();
-
-                Ok(Block::Extension(Extension::Application(Application {
-                    identifier,
-                    authentication_code,
-                    data,
-                })))
-            }
-            _ => panic!("Unknown Extension Identifier!"),
-        }
-    }
-
-    fn read_image(mut reader: &mut SmartReader) -> Result<Block, DecodingError> {
-        let mut buffer = [0u8; 9];
-        reader
-            .read_exact(&mut buffer)
-            .ok_or(DecodingError::UnexpectedEof)?;
-        let descriptor = ImageDescriptor::from(buffer);
-
-        let color_table = if descriptor.color_table_present() {
-            let size = descriptor.color_table_size() * 3;
-            Some(Self::read_color_table(&mut reader, size)?)
-        } else {
-            None
-        };
-
-        let lzw_csize = reader.u8().ok_or(DecodingError::UnexpectedEof)?;
-
-        let compressed_data = reader.take_and_collapse_subblocks();
-        println!("c{}", compressed_data.len());
-
-        let mut decompress = weezl::decode::Decoder::new(weezl::BitOrder::Lsb, lzw_csize);
-        //TODO: remove unwrap
-        let mut decompressed_data = decompress.decode(&compressed_data).unwrap();
-
-        Ok(Block::IndexedImage(IndexedImage {
-            image_descriptor: descriptor,
-            local_color_table: color_table,
-            indicies: decompressed_data,
-        }))
-    }
+	pub fn file<P: AsRef<Path>>(path: P) -> Result<Gif, DecodingError> {
+		let mut file = File::open(path)?;
+		let mut reader = SmartReader {
+			inner: vec![],
+			position: 0,
+		};
+		file.read_to_end(&mut reader.inner)?;
+
+		let mut gif = Self::read_required(&mut reader)?;
+
+		if gif.screen_descriptor.color_table_present() {
+			let gct_size = gif.screen_descriptor.color_table_len() * 3;
+			gif.global_color_table = Some(Self::read_color_table(&mut reader, gct_size)?);
+		}
+
+		loop {
+			match Self::read_block(&mut reader)? {
+				Some(block) => {
+					/*match &block {
+						Block::IndexedImage(_) => println!("Indexed Image"),
+						Block::BlockedImage(_) => println!("Blocked Image"),
+						Block::Extension(ext) => match ext {
+							Extension::GraphicControl(_) => println!("Graphic Cotrol Extension"),
+							Extension::Looping(_) => println!("Netscape Extension"),
+							Extension::Comment(vec) => {
+								println!("Comment Extension {:X}", vec.len())
+							}
+							Extension::Application(_) => todo!(),
+						},
+					}*/
+
+					gif.blocks.push(block)
+				}
+				None => return Ok(gif),
+			}
+		}
+	}
+
+	fn read_required(reader: &mut SmartReader) -> Result<Gif, DecodingError> {
+		let version = match reader.take_lossy_utf8(6).as_deref() {
+			Some("GIF87a") => Version::Gif87a,
+			Some("GIF89a") => Version::Gif89a,
+			_ => return Err(DecodingError::UnknownVersionString),
+		};
+
+		let mut lsd_buffer: [u8; 7] = [0; 7];
+		reader
+			.read_exact(&mut lsd_buffer)
+			.ok_or(DecodingError::UnexpectedEof)?;
+
+		let lsd = ScreenDescriptor::from(lsd_buffer);
+
+		Ok(Gif {
+			header: version,
+			screen_descriptor: lsd,
+			global_color_table: None,
+			blocks: vec![],
+		})
+	}
+
+	fn read_color_table(
+		reader: &mut SmartReader,
+		size: usize,
+	) -> Result<ColorTable, DecodingError> {
+		let buffer = reader
+			.take(size as usize)
+			.ok_or(DecodingError::UnexpectedEof)?;
+
+		// We get the size from the screen descriptor. This should never return Err
+		Ok(ColorTable::try_from(&buffer[..]).unwrap())
+	}
+
+	fn read_block(reader: &mut SmartReader) -> Result<Option<Block>, DecodingError> {
+		let block_id = reader.u8().ok_or(DecodingError::UnexpectedEof)?;
+
+		//TODO: remove panic
+		match block_id {
+			0x21 => Self::read_extension(reader).map(|block| Some(block)),
+			0x2C => Self::read_image(reader).map(|block| Some(block)),
+			0x3B => Ok(None),
+			_ => panic!(
+				"Unknown block identifier {:X} {:X}",
+				block_id, reader.position
+			),
+		}
+	}
+
+	fn read_extension(reader: &mut SmartReader) -> Result<Block, DecodingError> {
+		let extension_id = reader.u8().expect("File ended early");
+
+		match extension_id {
+			0xF9 => {
+				reader.skip(1); // Skip block length, we know it
+				let mut data = [0u8; 4];
+				reader
+					.read_exact(&mut data)
+					.ok_or(DecodingError::UnexpectedEof)?;
+				reader.skip(1); // Skip block terminator
+
+				Ok(Block::Extension(Extension::GraphicControl(
+					GraphicControl::from(data),
+				)))
+			}
+			0xFE => Ok(Block::Extension(Extension::Comment(
+				reader.take_and_collapse_subblocks(),
+			))),
+			0x01 => todo!(), //TODO: do; plain text extension
+			0xFF => {
+				//TODO: error instead of unwraps
+				assert_eq!(Some(11), reader.u8());
+				let identifier = reader.take_lossy_utf8(8).unwrap().to_string();
+				let authentication_code: [u8; 3] =
+					TryInto::try_into(reader.take(3).unwrap()).unwrap();
+				let data = reader.take_and_collapse_subblocks();
+
+				Ok(Block::Extension(Extension::Application(Application {
+					identifier,
+					authentication_code,
+					data,
+				})))
+			}
+			_ => panic!("Unknown Extension Identifier!"),
+		}
+	}
+
+	fn read_image(mut reader: &mut SmartReader) -> Result<Block, DecodingError> {
+		let mut buffer = [0u8; 9];
+		reader
+			.read_exact(&mut buffer)
+			.ok_or(DecodingError::UnexpectedEof)?;
+		let descriptor = ImageDescriptor::from(buffer);
+
+		let color_table = if descriptor.color_table_present() {
+			let size = descriptor.color_table_size() * 3;
+			Some(Self::read_color_table(&mut reader, size)?)
+		} else {
+			None
+		};
+
+		let lzw_csize = reader.u8().ok_or(DecodingError::UnexpectedEof)?;
+
+		let compressed_data = reader.take_and_collapse_subblocks();
+		println!("c{}", compressed_data.len());
+
+		let mut decompress = weezl::decode::Decoder::new(weezl::BitOrder::Lsb, lzw_csize);
+		//TODO: remove unwrap
+		let mut decompressed_data = decompress.decode(&compressed_data).unwrap();
+
+		Ok(Block::IndexedImage(IndexedImage {
+			image_descriptor: descriptor,
+			local_color_table: color_table,
+			indicies: decompressed_data,
+		}))
+	}
 }
 
 #[derive(Debug)]
 pub enum DecodingError {
-    IoError(std::io::Error),
-    UnknownVersionString,
-    UnexpectedEof,
-    ColorIndexOutOfBounds,
+	IoError(std::io::Error),
+	UnknownVersionString,
+	UnexpectedEof,
+	ColorIndexOutOfBounds,
 }
 
 impl Error for DecodingError {}
 impl fmt::Display for DecodingError {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match self {
-            DecodingError::IoError(error) => write!(f, "{}", error),
-            DecodingError::UnknownVersionString => {
-                write!(f, "File did not start with a valid header")
-            }
-            DecodingError::UnexpectedEof => {
-                write!(f, "Found the end of the data at a weird spot")
-            }
-            DecodingError::ColorIndexOutOfBounds => {
-                write!(
-                    f,
-                    "The image contained an index not found in the color table"
-                )
-            }
-        }
-    }
+	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+		match self {
+			DecodingError::IoError(error) => write!(f, "{}", error),
+			DecodingError::UnknownVersionString => {
+				write!(f, "File did not start with a valid header")
+			}
+			DecodingError::UnexpectedEof => {
+				write!(f, "Found the end of the data at a weird spot")
+			}
+			DecodingError::ColorIndexOutOfBounds => {
+				write!(
+					f,
+					"The image contained an index not found in the color table"
+				)
+			}
+		}
+	}
 }
 
 impl From<std::io::Error> for DecodingError {
-    fn from(ioerror: std::io::Error) -> Self {
-        DecodingError::IoError(ioerror)
-    }
+	fn from(ioerror: std::io::Error) -> Self {
+		DecodingError::IoError(ioerror)
+	}
 }
 
 struct SmartReader {
-    inner: Vec<u8>,
-    position: usize,
+	inner: Vec<u8>,
+	position: usize,
 }
 
 impl SmartReader {
-    pub fn u8(&mut self) -> Option<u8> {
-        self.position += 1;
-        self.inner.get(self.position - 1).map(|b| *b)
-    }
-
-    pub fn u16(&mut self) -> Option<u16> {
-        self.position += 2;
-        self.inner
-            .get(self.position - 2..self.position)
-            .map(|bytes| u16::from_le_bytes(bytes.try_into().unwrap()))
-    }
-
-    pub fn skip(&mut self, size: usize) {
-        self.position += size;
-    }
-
-    pub fn take(&mut self, size: usize) -> Option<&[u8]> {
-        self.position += size;
-        self.inner.get(self.position - size..self.position)
-    }
-
-    //TODO: Result not Option when buffer len
-    pub fn read_exact(&mut self, buf: &mut [u8]) -> Option<()> {
-        if self.position + buf.len() > self.inner.len() {
-            None
-        } else {
-            self.position += buf.len();
-            buf.copy_from_slice(&self.inner[self.position - buf.len()..self.position]);
-            Some(())
-        }
-    }
-
-    pub fn take_vec(&mut self, size: usize) -> Option<Vec<u8>> {
-        self.position += size;
-        self.inner
-            .get(self.position - size..self.position)
-            .map(|bytes| bytes.to_vec())
-    }
-
-    pub fn take_lossy_utf8(&mut self, size: usize) -> Option<Cow<'_, str>> {
-        self.take(size).map(|bytes| String::from_utf8_lossy(bytes))
-    }
-
-    pub fn take_data_subblocks(&mut self) -> Vec<Vec<u8>> {
-        let mut blocks = vec![];
-
-        loop {
-            let block_size = self.u8().expect("Failed to read length of sublock");
-
-            if block_size == 0 {
-                return blocks;
-            }
-
-            let block = self
-                .take_vec(block_size as usize)
-                .expect("Failed to read sublock");
-
-            blocks.push(block);
-        }
-    }
-
-    pub fn take_and_collapse_subblocks(&mut self) -> Vec<u8> {
-        let blocks = self.take_data_subblocks();
-        let mut ret = vec![];
-        for block in blocks {
-            ret.extend_from_slice(&block)
-        }
-
-        ret
-    }
+	pub fn u8(&mut self) -> Option<u8> {
+		self.position += 1;
+		self.inner.get(self.position - 1).map(|b| *b)
+	}
+
+	pub fn u16(&mut self) -> Option<u16> {
+		self.position += 2;
+		self.inner
+			.get(self.position - 2..self.position)
+			.map(|bytes| u16::from_le_bytes(bytes.try_into().unwrap()))
+	}
+
+	pub fn skip(&mut self, size: usize) {
+		self.position += size;
+	}
+
+	pub fn take(&mut self, size: usize) -> Option<&[u8]> {
+		self.position += size;
+		self.inner.get(self.position - size..self.position)
+	}
+
+	//TODO: Result not Option when buffer len
+	pub fn read_exact(&mut self, buf: &mut [u8]) -> Option<()> {
+		if self.position + buf.len() > self.inner.len() {
+			None
+		} else {
+			self.position += buf.len();
+			buf.copy_from_slice(&self.inner[self.position - buf.len()..self.position]);
+			Some(())
+		}
+	}
+
+	pub fn take_vec(&mut self, size: usize) -> Option<Vec<u8>> {
+		self.position += size;
+		self.inner
+			.get(self.position - size..self.position)
+			.map(|bytes| bytes.to_vec())
+	}
+
+	pub fn take_lossy_utf8(&mut self, size: usize) -> Option<Cow<'_, str>> {
+		self.take(size).map(|bytes| String::from_utf8_lossy(bytes))
+	}
+
+	pub fn take_data_subblocks(&mut self) -> Vec<Vec<u8>> {
+		let mut blocks = vec![];
+
+		loop {
+			let block_size = self.u8().expect("Failed to read length of sublock");
+
+			if block_size == 0 {
+				return blocks;
+			}
+
+			let block = self
+				.take_vec(block_size as usize)
+				.expect("Failed to read sublock");
+
+			blocks.push(block);
+		}
+	}
+
+	pub fn take_and_collapse_subblocks(&mut self) -> Vec<u8> {
+		let blocks = self.take_data_subblocks();
+		let mut ret = vec![];
+		for block in blocks {
+			ret.extend_from_slice(&block)
+		}
+
+		ret
+	}
 }
diff --git a/src/writer/gifbuilder.rs b/src/writer/gifbuilder.rs
index 1466f76..57a62e3 100644
--- a/src/writer/gifbuilder.rs
+++ b/src/writer/gifbuilder.rs
@@ -5,102 +5,102 @@ use crate::writer::ImageBuilder;
 use crate::{EncodingError, Gif};
 
 pub struct GifBuilder {
-    version: Version,
-    width: u16,
-    height: u16,
-    background_color_index: u8,
-    global_color_table: Option<ColorTable>,
-    blocks: Vec<Block>,
-    error: Option<EncodingError>,
+	version: Version,
+	width: u16,
+	height: u16,
+	background_color_index: u8,
+	global_color_table: Option<ColorTable>,
+	blocks: Vec<Block>,
+	error: Option<EncodingError>,
 }
 
 impl GifBuilder {
-    pub fn new(width: u16, height: u16) -> Self {
-        Self {
-            version: Version::Gif87a,
-            width,
-            height,
-            background_color_index: 0,
-            global_color_table: None,
-            blocks: vec![],
-            error: None,
-        }
-    }
-
-    pub fn palette(mut self, palette: ColorTable) -> Self {
-        self.global_color_table = Some(palette);
-        self
-    }
-
-    pub fn background_index(mut self, ind: u8) -> Self {
-        if self.error.is_some() {
-            return self;
-        }
-
-        if self.global_color_table.is_none() {
-            self.error = Some(EncodingError::NoColorTable);
-        } else {
-            self.background_color_index = ind;
-        }
-        self
-    }
-
-    pub fn image(mut self, ib: ImageBuilder) -> Self {
-        if self.error.is_some() {
-            return self;
-        }
-
-        if ib.required_version() == Version::Gif89a {
-            self.version = Version::Gif89a;
-        }
-
-        if let Some(gce) = ib.get_graphic_control() {
-            self.blocks.push(Block::Extension(gce.into()));
-        }
-
-        match ib.build() {
-            Ok(image) => self.blocks.push(Block::IndexedImage(image)),
-            Err(e) => self.error = Some(e),
-        }
-
-        self
-    }
-
-    /*pub fn extension(mut self, ext: Extension) -> Self {
-        self.blocks.push(Block::Extension(ext));
-        self
-    }*/
-
-    pub fn repeat(mut self, count: u16) -> Self {
-        self.blocks
-            .push(Block::Extension(Extension::Looping(count)));
-        self
-    }
-
-    pub fn build(self) -> Result<Gif, EncodingError> {
-        if let Some(error) = self.error {
-            return Err(error);
-        }
-
-        let mut lsd = ScreenDescriptor {
-            width: self.width,
-            height: self.height,
-            packed: 0, // Set later
-            background_color_index: self.background_color_index,
-            pixel_aspect_ratio: 0, //TODO: Allow configuring
-        };
-
-        if let Some(gct) = &self.global_color_table {
-            println!("build {}", gct.len());
-            lsd.set_color_table_present(true);
-            lsd.set_color_table_size((gct.len() - 1) as u8);
-        }
-
-        Ok(Gif {
-            header: self.version,
-            screen_descriptor: lsd,
-            global_color_table: self.global_color_table,
-            blocks: self.blocks,
-        })
-    }
+	pub fn new(width: u16, height: u16) -> Self {
+		Self {
+			version: Version::Gif87a,
+			width,
+			height,
+			background_color_index: 0,
+			global_color_table: None,
+			blocks: vec![],
+			error: None,
+		}
+	}
+
+	pub fn palette(mut self, palette: ColorTable) -> Self {
+		self.global_color_table = Some(palette);
+		self
+	}
+
+	pub fn background_index(mut self, ind: u8) -> Self {
+		if self.error.is_some() {
+			return self;
+		}
+
+		if self.global_color_table.is_none() {
+			self.error = Some(EncodingError::NoColorTable);
+		} else {
+			self.background_color_index = ind;
+		}
+		self
+	}
+
+	pub fn image(mut self, ib: ImageBuilder) -> Self {
+		if self.error.is_some() {
+			return self;
+		}
+
+		if ib.required_version() == Version::Gif89a {
+			self.version = Version::Gif89a;
+		}
+
+		if let Some(gce) = ib.get_graphic_control() {
+			self.blocks.push(Block::Extension(gce.into()));
+		}
+
+		match ib.build() {
+			Ok(image) => self.blocks.push(Block::IndexedImage(image)),
+			Err(e) => self.error = Some(e),
+		}
+
+		self
+	}
+
+	/*pub fn extension(mut self, ext: Extension) -> Self {
+		self.blocks.push(Block::Extension(ext));
+		self
+	}*/
+
+	pub fn repeat(mut self, count: u16) -> Self {
+		self.blocks
+			.push(Block::Extension(Extension::Looping(count)));
+		self
+	}
+
+	pub fn build(self) -> Result<Gif, EncodingError> {
+		if let Some(error) = self.error {
+			return Err(error);
+		}
+
+		let mut lsd = ScreenDescriptor {
+			width: self.width,
+			height: self.height,
+			packed: 0, // Set later
+			background_color_index: self.background_color_index,
+			pixel_aspect_ratio: 0, //TODO: Allow configuring
+		};
+
+		if let Some(gct) = &self.global_color_table {
+			println!("build {}", gct.len());
+			lsd.set_color_table_present(true);
+			lsd.set_color_table_size((gct.len() - 1) as u8);
+		}
+
+		Ok(Gif {
+			header: self.version,
+			screen_descriptor: lsd,
+			global_color_table: self.global_color_table,
+			blocks: self.blocks,
+		})
+	}
 }
diff --git a/src/writer/imagebuilder.rs b/src/writer/imagebuilder.rs
index 42c94f8..f5c9e2b 100644
--- a/src/writer/imagebuilder.rs
+++ b/src/writer/imagebuilder.rs
@@ -1,133 +1,133 @@
 use crate::{
-    block::{
-        extension::{DisposalMethod, GraphicControl},
-        ColorTable, ImageDescriptor, IndexedImage, Version,
-    },
-    EncodingError,
+	block::{
+		extension::{DisposalMethod, GraphicControl},
+		ColorTable, ImageDescriptor, IndexedImage, Version,
+	},
+	EncodingError,
 };
 
 pub struct ImageBuilder {
-    left_offset: u16,
-    top_offset: u16,
-    width: u16,
-    height: u16,
-    color_table: Option<ColorTable>,
+	left_offset: u16,
+	top_offset: u16,
+	width: u16,
+	height: u16,
+	color_table: Option<ColorTable>,
 
-    delay: u16,
-    disposal_method: DisposalMethod,
-    transparent_index: Option<u8>,
+	delay: u16,
+	disposal_method: DisposalMethod,
+	transparent_index: Option<u8>,
 
-    indicies: Vec<u8>,
+	indicies: Vec<u8>,
 }
 
 impl ImageBuilder {
-    pub fn new(width: u16, height: u16) -> Self {
-        Self {
-            left_offset: 0,
-            top_offset: 0,
-            width,
-            height,
-            color_table: None,
-            delay: 0,
-            disposal_method: DisposalMethod::NoAction,
-            transparent_index: None,
-            indicies: vec![],
-        }
-    }
-
-    pub fn offset(mut self, left: u16, top: u16) -> Self {
-        self.left_offset = left;
-        self.top_offset = top;
-        self
-    }
-
-    pub fn palette(mut self, table: ColorTable) -> Self {
-        self.color_table = Some(table);
-        self
-    }
-
-    /// Time to wait, in hundreths of a second, before this image is drawn
-    pub fn delay(mut self, hundreths: u16) -> Self {
-        self.delay = hundreths;
-        self
-    }
-
-    pub fn disposal_method(mut self, method: DisposalMethod) -> Self {
-        self.disposal_method = method;
-        self
-    }
-
-    pub fn transparent_index(mut self, index: Option<u8>) -> Self {
-        self.transparent_index = index;
-        self
-    }
-
-    pub fn required_version(&self) -> Version {
-        if self.delay > 0
-            || self.disposal_method != DisposalMethod::NoAction
-            || self.transparent_index.is_some()
-        {
-            Version::Gif89a
-        } else {
-            Version::Gif87a
-        }
-    }
-
-    pub fn get_graphic_control(&self) -> Option<GraphicControl> {
-        if self.required_version() == Version::Gif89a {
-            if let Some(transindex) = self.transparent_index {
-                Some(GraphicControl::new(
-                    self.disposal_method,
-                    false,
-                    true,
-                    self.delay,
-                    transindex,
-                ))
-            } else {
-                Some(GraphicControl::new(
-                    self.disposal_method,
-                    false,
-                    false,
-                    self.delay,
-                    0,
-                ))
-            }
-        } else {
-            None
-        }
-    }
-
-    pub fn indicies(mut self, indicies: &[u8]) -> Self {
-        self.indicies = indicies.to_vec();
-        self
-    }
-
-    pub fn build(self) -> Result<IndexedImage, EncodingError> {
-        let expected_len = self.width as usize * self.height as usize;
-        if self.indicies.len() != expected_len {
-            return Err(EncodingError::IndicieSizeMismatch {
-                expected: expected_len,
-                got: self.indicies.len(),
-            });
-        }
-
-        let mut imgdesc = ImageDescriptor {
-            left: self.left_offset,
-            top: self.top_offset,
-            width: self.width,
-            height: self.height,
-            packed: 0, // Set later
-        };
-
-        if let Some(lct) = &self.color_table {
-            imgdesc.set_color_table_present(true);
-            imgdesc.set_color_table_size(lct.packed_len());
-        }
-
-        Ok(IndexedImage {
-            image_descriptor: imgdesc,
-            local_color_table: self.color_table,
-            indicies: self.indicies,
-        })
-    }
+	pub fn new(width: u16, height: u16) -> Self {
+		Self {
+			left_offset: 0,
+			top_offset: 0,
+			width,
+			height,
+			color_table: None,
+			delay: 0,
+			disposal_method: DisposalMethod::NoAction,
+			transparent_index: None,
+			indicies: vec![],
+		}
+	}
+
+	pub fn offset(mut self, left: u16, top: u16) -> Self {
+		self.left_offset = left;
+		self.top_offset = top;
+		self
+	}
+
+	pub fn palette(mut self, table: ColorTable) -> Self {
+		self.color_table = Some(table);
+		self
+	}
+
+	/// Time to wait, in hundreths of a second, before this image is drawn
+	pub fn delay(mut self, hundreths: u16) -> Self {
+		self.delay = hundreths;
+		self
+	}
+
+	pub fn disposal_method(mut self, method: DisposalMethod) -> Self {
+		self.disposal_method = method;
+		self
+	}
+
+	pub fn transparent_index(mut self, index: Option<u8>) -> Self {
+		self.transparent_index = index;
+		self
+	}
+
+	pub fn required_version(&self) -> Version {
+		if self.delay > 0
+			|| self.disposal_method != DisposalMethod::NoAction
+			|| self.transparent_index.is_some()
+		{
+			Version::Gif89a
+		} else {
+			Version::Gif87a
+		}
+	}
+
+	pub fn get_graphic_control(&self) -> Option<GraphicControl> {
+		if self.required_version() == Version::Gif89a {
+			if let Some(transindex) = self.transparent_index {
+				Some(GraphicControl::new(
+					self.disposal_method,
+					false,
+					true,
+					self.delay,
+					transindex,
+				))
+			} else {
+				Some(GraphicControl::new(
+					self.disposal_method,
+					false,
+					false,
+					self.delay,
+					0,
+				))
+			}
+		} else {
+			None
+		}
+	}
+
+	pub fn indicies(mut self, indicies: &[u8]) -> Self {
+		self.indicies = indicies.to_vec();
+		self
+	}
+
+	pub fn build(self) -> Result<IndexedImage, EncodingError> {
+		let expected_len = self.width as usize * self.height as usize;
+		if self.indicies.len() != expected_len {
+			return Err(EncodingError::IndicieSizeMismatch {
+				expected: expected_len,
+				got: self.indicies.len(),
+			});
+		}
+
+		let mut imgdesc = ImageDescriptor {
+			left: self.left_offset,
+			top: self.top_offset,
+			width: self.width,
+			height: self.height,
+			packed: 0, // Set later
+		};
+
+		if let Some(lct) = &self.color_table {
+			imgdesc.set_color_table_present(true);
+			imgdesc.set_color_table_size(lct.packed_len());
+		}
+
+		Ok(IndexedImage {
+			image_descriptor: imgdesc,
+			local_color_table: self.color_table,
+			indicies: self.indicies,
+		})
+	}
 }