diff --git a/config.toml.example b/config.toml.example
index 7d9e794d6e9de50701bd9922bfcc5ce0e8c98b89..109e6d26fa5e6417fb1d79cb97baf2aa95f5652d 100644
--- a/config.toml.example
+++ b/config.toml.example
@@ -11,6 +11,9 @@ paths = [
 # must be 6 characters or less
 callsign = "NOCALL"
 
+# Max image dimension. Comment this out to send full-sized images
+max_img_dimension = 1024
+
 # Comment this section out if you're not using
 # APRS for control
 [control]
diff --git a/src/config.rs b/src/config.rs
index 97de0df44d0b728e3c0bc33d190d3d35d2fb1d46..f9057d1311a3d90aad91706b3eeb0804e563038b 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -14,6 +14,7 @@ pub struct ControlConfig {
 pub struct Config {
     pub paths: Vec<PathBuf>,
     pub callsign: String,
+    pub max_img_dimension: Option<u32>,
 
     pub control: Option<ControlConfig>,
 }
diff --git a/src/control.rs b/src/control.rs
index 2d388935ce9a17f733aa6d633b43094e91fe7187..62acf444fbb0958eba8b8da0438025330bee0449 100644
--- a/src/control.rs
+++ b/src/control.rs
@@ -41,7 +41,7 @@ impl Controller {
         let mut manager = ImgManager::new(self.config.paths.clone(), cmd_rx);
 
         loop {
-            while let Some((idx, bytes)) = manager.next() {
+            while let Some((idx, bytes)) = manager.next(self.config.max_img_dimension) {
                 if let Err(e) = self.process_image(&bytes, idx, &img_tx) {
                     eprintln!("Error processing image: {e}");
                 }
diff --git a/src/img.rs b/src/img.rs
index 61ceb08fb2c50af5b7d10d53677f130a4afb80ff..607dbf4b9afeb2015ae93d6233f498f647425b76 100644
--- a/src/img.rs
+++ b/src/img.rs
@@ -1,7 +1,6 @@
 use image::{imageops::FilterType, io::Reader as ImageReader, ImageOutputFormat};
 use std::{cmp::max, fs, io::Cursor, path::PathBuf, sync::mpsc::Receiver};
 
-const IMG_DIM: u32 = 1024;
 const IMG_MAX_SIZE: u32 = 2048;
 const JPEG_QUALITY: u8 = 100; // let ssdv do the compression
 
@@ -15,12 +14,12 @@ struct ImgInfo {
 }
 
 impl ImgInfo {
-    pub fn compressed_jpeg_bytes(&self) -> anyhow::Result<Vec<u8>> {
+    pub fn compressed_jpeg_bytes(&self, dim: u32) -> anyhow::Result<Vec<u8>> {
         let img = ImageReader::open(&self.path)?.decode()?;
 
         // want a imagine that's 512 on one side
         // resize so that the larger dimension is 512
-        let (mut w, mut h) = resize_dimensions(img.width(), img.height(), IMG_DIM, IMG_DIM, false);
+        let (mut w, mut h) = resize_dimensions(img.width(), img.height(), dim, dim, false);
 
         let img = img.resize_exact(w, h, FilterType::Triangle);
 
@@ -65,7 +64,7 @@ pub struct ImgManager {
     path_idx: usize,
     found: bool,
     tx_idx: u8,
-    // map between sent image ids, the the images
+    // map between sent image ids, and the images
     // in the array above
     // used for decoding rx requests
     img_map: [usize; 256],
@@ -89,7 +88,7 @@ impl ImgManager {
     // not making this an iterator since
     // it's entirely valid to have a Some(...)
     // after a None
-    pub fn next(&mut self) -> Option<(u8, Vec<u8>)> {
+    pub fn next(&mut self, dim: Option<u32>) -> Option<(u8, Vec<u8>)> {
         loop {
             if let Ok(req) = self.rx.try_recv() {
                 let img = self
@@ -123,7 +122,10 @@ impl ImgManager {
 
             if let Some((new_id, new)) = new {
                 new.txed = true;
-                let bytes = new.compressed_jpeg_bytes();
+                let bytes = match dim {
+                    Some(d) => new.compressed_jpeg_bytes(d),
+                    None => new.lossless_jpeg_bytes(),
+                };
 
                 self.inc_iter(true);
 
@@ -145,7 +147,10 @@ impl ImgManager {
 
             if let Some((old_idx, old)) = old {
                 old.txed = true;
-                let bytes = old.compressed_jpeg_bytes();
+                let bytes = match dim {
+                    Some(d) => old.compressed_jpeg_bytes(d),
+                    None => old.lossless_jpeg_bytes(),
+                };
 
                 self.inc_iter(true);