diff --git a/src/commands/atlas.rs b/src/commands/atlas.rs
index 4611367785eedcf859eafafb6b96572a53ae24d0..6427a9ed4f5b3b61f6426124b70f965aa10402b5 100644
--- a/src/commands/atlas.rs
+++ b/src/commands/atlas.rs
@@ -1,4 +1,3 @@
-use crate::format::load_image;
 use clap::Parser;
 use etagere::{AllocId, AtlasAllocator, Rectangle, Size};
 use image::{image_dimensions, GenericImage, Rgba, RgbaImage};
@@ -9,6 +8,7 @@ use std::collections::HashMap;
 use std::fmt::Display;
 use std::fs::File;
 use std::path::PathBuf;
+use crunch_cli::utils::load_image;
 
 fn default_max_size() -> usize {
 	2048
diff --git a/src/commands/extrude.rs b/src/commands/extrude.rs
index 3c0e946abe6ee68eb06b10b0944a28a996b5529d..d69afe53ae9817108e06003611b313dfe30137d8 100644
--- a/src/commands/extrude.rs
+++ b/src/commands/extrude.rs
@@ -1,4 +1,3 @@
-use crate::utils::{RgbaOutputFormat, SpriteData};
 use clap::Parser;
 
 use image::math::Rect;
@@ -6,6 +5,7 @@ use image::{GenericImage, GenericImageView, Rgba, RgbaImage};
 
 use serde::{Deserialize, Serialize};
 use std::ops::Deref;
+use crunch_cli::utils::{RgbaOutputFormat, SpriteData};
 
 #[inline(always)]
 fn tile_size() -> u32 {
@@ -92,7 +92,8 @@ impl Extrude {
 		);
 		let mut new_image = RgbaImage::from_pixel(new_width, new_height, Rgba::from([0, 0, 0, 0]));
 		for sprite in views.iter() {
-			let (img_x, img_y, width, height) = sprite.data.bounds();
+			let (width, height) = sprite.data.dimensions();
+			let (img_x, img_y) = sprite.data.offsets();
 			let target_x = self.padding + img_x + (sprite.tx * self.space_x);
 			let target_y = self.padding + img_y + (sprite.ty * self.space_y);
 
diff --git a/src/commands/flip.rs b/src/commands/flip.rs
index 98b5375b230ddf59f3d5b3c47340b296c0a208d0..ec06849cd8dc5c1287c18865b9df5dde70497827 100644
--- a/src/commands/flip.rs
+++ b/src/commands/flip.rs
@@ -1,7 +1,7 @@
-use crate::utils::TypedOutputFormat;
 use clap::{Parser, ValueEnum};
 use image::{imageops, GenericImage, Pixel};
 use serde::{Deserialize, Serialize};
+use crunch_cli::utils::TypedOutputFormat;
 
 #[derive(Copy, Clone, Serialize, Deserialize, ValueEnum, Debug)]
 pub enum FlipDirection {
diff --git a/src/commands/pipeline.rs b/src/commands/pipeline.rs
index db801120cc5092ae9fb4e4d7ad822588efc6855f..4cf496c65e3b8c6f79cbfd964cd9df7c4f0d0c1e 100644
--- a/src/commands/pipeline.rs
+++ b/src/commands/pipeline.rs
@@ -5,12 +5,9 @@ use std::path::{Path, PathBuf};
 use rayon::prelude::*;
 use serde::{Deserialize, Serialize};
 use thiserror::Error;
-
+use crunch_cli::utils::{load_image, make_paths, normalize_path, ColourPalette, PaletteMap};
 use crate::cli_args::Args;
 use crate::commands::{Palette, Remap};
-use crate::format::make_paths;
-use crate::load_image;
-use crate::utils::normalize_path;
 
 #[derive(Error, Debug)]
 pub enum PipelineError {
@@ -135,10 +132,10 @@ impl Pipeline {
 					}
 					Args::Remap(remap) => {
 						let palette = result!(load_image(&remap.palette, None));
-						let image_palette = result!(Palette::extract_from(&file));
-						let target_palette = result!(Palette::extract_from(&palette));
+						let image_palette = ColourPalette::from(&file);
+						let target_palette = ColourPalette::from(&palette);
 
-						let mappings = Palette::calculate_mapping(&image_palette, &target_palette);
+						let mappings = PaletteMap::calculate_mapping(&image_palette, &target_palette);
 						file = result!(Remap::remap_image(file, mappings));
 					}
 					_ => {}
diff --git a/src/commands/reduce.rs b/src/commands/reduce.rs
index 5c4f496a986b4a8604a5c96c85bf5cea3290ca13..4a9b670e6d21621e6d899770ce5083048efa01b6 100644
--- a/src/commands/reduce.rs
+++ b/src/commands/reduce.rs
@@ -1,8 +1,8 @@
-use crate::utils::RgbaOutputFormat;
 use anyhow::Error;
 use clap::Parser;
 use image::GenericImage;
 use serde::{Deserialize, Serialize};
+use crunch_cli::utils::RgbaOutputFormat;
 
 /// Limit the number of colours by quantity or threshold
 #[derive(Debug, Clone, Parser, Serialize, Deserialize)]
diff --git a/src/commands/remap.rs b/src/commands/remap.rs
index 3dd30839d063bb943153e9c62ce1767cc4a92eca..eba054438a2dbaded986f7245e00820528ee5991 100644
--- a/src/commands/remap.rs
+++ b/src/commands/remap.rs
@@ -1,10 +1,8 @@
-use crate::commands::palette::ColourMapping;
 use clap::Parser;
 use image::{GenericImage, Pixel, Rgba};
 use num_traits::ToPrimitive;
 use serde::{Deserialize, Serialize};
-
-use crate::utils::{new_image, BasicRgba, OutputFormat};
+use crunch_cli::utils::{new_image, BasicRgba, OutputFormat, PaletteMap};
 
 /// Convert the colour space of an image to that of a given palette file
 #[derive(Debug, Clone, Parser, Serialize, Deserialize)]
@@ -25,7 +23,7 @@ pub struct Remap {
 impl Remap {
 	pub fn remap_image(
 		image: impl GenericImage,
-		mappings: ColourMapping,
+		mappings: PaletteMap,
 	) -> anyhow::Result<OutputFormat> {
 		let mut output = new_image(image.width(), image.height());
 		for (x, y, pixel) in image.pixels() {
diff --git a/src/commands/rotate.rs b/src/commands/rotate.rs
index 3531cb211e2c3d9625975aeda8c538ad22e86969..ba57825336bf4a35ebed26d06fa2b5e4e7c1c958 100644
--- a/src/commands/rotate.rs
+++ b/src/commands/rotate.rs
@@ -1,7 +1,7 @@
-use crate::utils::TypedOutputFormat;
 use clap::{Parser, ValueEnum};
 use image::{imageops, GenericImage, Pixel};
 use serde::{Deserialize, Serialize};
+use crunch_cli::utils::TypedOutputFormat;
 
 #[derive(Copy, Clone, Serialize, Deserialize, ValueEnum, Debug)]
 pub enum RotateDegree {
diff --git a/src/commands/scale.rs b/src/commands/scale.rs
index 256be4754bc42f2d5cc91bb13e56f788aed8e42a..81ce47418418f45e812b1fb4477f84cb5b63feac 100644
--- a/src/commands/scale.rs
+++ b/src/commands/scale.rs
@@ -1,8 +1,8 @@
-use crate::utils::TypedOutputFormat;
 use clap::Parser;
 use image::imageops::FilterType;
 use image::{imageops, GenericImage, Pixel};
 use serde::{Deserialize, Serialize};
+use crunch_cli::utils::TypedOutputFormat;
 
 #[inline(always)]
 fn one() -> f32 {