diff --git a/src/background.rs b/src/background.rs
index a0bb337fc8c3a01e298ebac3a993fdf44f3b93de..73061570c44410e1f71ddae67859c66d98cb6c1e 100644
--- a/src/background.rs
+++ b/src/background.rs
@@ -1,3 +1,4 @@
+use std::io::Read;
 use std::process::Command;
 
 use dbus::blocking::Connection;
@@ -5,6 +6,7 @@ use dbus::Message;
 
 use crate::img_processors::process_image;
 use crate::result::MBGResult;
+use crate::TestingPic;
 
 pub fn reset_background_handler(_: (), _: &Connection, message: &Message) -> bool {
     let member_name = message.read1::<String>();
@@ -34,6 +36,18 @@ pub fn process_image_url(image_url: String) -> MBGResult<()> {
     Ok(())
 }
 
+pub fn test_processors(test_data: TestingPic) -> MBGResult<()> {
+    let mut img_file = std::fs::File::open(test_data.input.as_str())?;
+    let mut image_bytes = Vec::new();
+    img_file.read_to_end(&mut image_bytes)?;
+    let res = process_image(image_bytes)?;
+    res.save(test_data.output.as_str())?;
+    if test_data.wallpaper {
+        set_wallpaper(test_data.output.as_str());
+    }
+    Ok(())
+}
+
 pub fn set_wallpaper(path: &str) {
     debug!("Setting background");
     let out = Command::new("feh").arg("--bg-fill").arg(path).output();
diff --git a/src/cli.rs b/src/cli.rs
new file mode 100644
index 0000000000000000000000000000000000000000..13933cf4a8be668e1a6908ef3a128b76b63099d7
--- /dev/null
+++ b/src/cli.rs
@@ -0,0 +1,109 @@
+#[derive(Debug, StructOpt)]
+#[structopt(
+name = "music_bg",
+about = "Listens to your mpris interface and sets you a cool background"
+)]
+pub struct Opt {
+    #[structopt(subcommand)]
+    pub cmd: Option<RunMode>,
+}
+
+#[derive(StructOpt, Debug)]
+pub enum RunMode {
+    #[structopt(name = "run", about = "Run d-bus listener")]
+    Run,
+    #[structopt(
+    name = "config",
+    about = "Create or replace default configuration file"
+    )]
+    GenConf,
+    #[structopt(
+    name = "test",
+    about = "Process image file according to your ~/.mbg.toml"
+    )]
+    TestPic(TestingPic),
+    #[structopt(
+    name = "completions",
+    about = "Generate completion for your shell"
+    )]
+    GenComp(ShellType),
+}
+
+#[derive(StructOpt, Debug)]
+pub struct TestingPic {
+    #[structopt(
+    name = "input",
+    about = "Image file to process"
+    )]
+    pub input: String,
+    #[structopt(
+    long,
+    about = "Processed image output file",
+    name = "out",
+    default_value = "/dev/shm/test.png"
+    )]
+    pub output: String,
+    #[structopt(
+    short,
+    about = "Set processed image as wallpaper",
+    name = "wall"
+    )]
+    pub wallpaper: bool,
+}
+
+#[derive(StructOpt, Debug)]
+pub enum ShellType {
+    #[structopt(
+    about = "Generates a .bash completion file for the Bourne Again SHell (BASH)",
+    name = "bash"
+    )]
+    Bash,
+    #[structopt(
+    about = "Generates a .fish completion file for the Friendly Interactive SHell (fish)",
+    name = "fish"
+    )]
+    Fish,
+    #[structopt(
+    about = "Generates a completion file for the Z SHell (ZSH)",
+    name = "zsh"
+    )]
+    Zsh,
+    #[structopt(
+    about = "Generates a completion file for PowerShell",
+    name = "ps"
+    )]
+    PowerShell,
+    #[structopt(
+    about = "Generates a completion file for Elvish",
+    name = "elvish"
+    )]
+    Elvish,
+}
+
+impl From<ShellType> for Shell {
+    fn from(shell: ShellType) -> Self {
+        match shell {
+            ShellType::Bash => { Shell::Bash }
+            ShellType::Fish => { Shell::Fish }
+            ShellType::Zsh => { Shell::Zsh }
+            ShellType::PowerShell => { Shell::PowerShell }
+            ShellType::Elvish => { Shell::Elvish }
+        }
+    }
+}
+
+pub fn generate_completions(shell: ShellType) -> MBGResult<()> {
+    Opt::clap().gen_completions(env!("CARGO_PKG_NAME"), shell.into(), ".");
+    info!("Generated completion file in _music_bg");
+    Ok(())
+}
+
+pub fn run(opts: Opt) -> MBGResult<()> {
+    let mode = opts.cmd.unwrap_or_else(|| RunMode::Run);
+    match mode {
+        RunMode::Run => start_listen(),
+        RunMode::GenConf => Config::generate_config(),
+        RunMode::TestPic(data) => test_processors(data),
+        RunMode::GenComp(shell) => generate_completions(shell)
+    }
+}
\ No newline at end of file
diff --git a/src/img_processors/border.rs b/src/img_processors/border.rs
index b9b41c925bfc11ea5512503f478170aaf6a0d657..190fcbe9e896feb51fc733ecded4e159d92bc0ca 100644
--- a/src/img_processors/border.rs
+++ b/src/img_processors/border.rs
@@ -1,8 +1,8 @@
 use std::cmp::min;
 
+use image::imageops::{overlay, FilterType};
 use image::{DynamicImage, GenericImageView, Rgba, RgbaImage};
-use image::imageops::{FilterType, overlay};
-use imageproc::drawing::{Blend, Canvas, draw_filled_circle_mut};
+use imageproc::drawing::{draw_filled_circle_mut, Blend, Canvas};
 
 use crate::config::image_processors::ProcessorParams;
 use crate::img_processors::ImageProcessor;
@@ -15,18 +15,22 @@ pub struct Border {
     pub width: u32,
 }
 
-
 impl Border {
     fn crop_circle(&self, img: &DynamicImage) -> MBGResult<DynamicImage> {
         let img_height = image::GenericImageView::height(img);
         let img_width = image::GenericImageView::width(img);
         let transparent_pixel = Rgba([0u8, 0u8, 0u8, 0u8]);
-        let mut mask = Blend(RgbaImage::from_pixel(img_width * 3, img_height * 3, transparent_pixel));
+        let mut mask = Blend(RgbaImage::from_pixel(
+            img_width,
+            img_height,
+            transparent_pixel,
+        ));
         let center = ((mask.width() / 2) as i32, (mask.height() / 2) as i32);
         let radius = min(center.0, center.1);
         let black_pixel = Rgba([0u8, 0u8, 0u8, 255u8]);
         draw_filled_circle_mut(&mut mask, center, radius, black_pixel);
         let mut mask = DynamicImage::ImageRgba8(mask.0);
+        debug!("{}x{}", img_width, img_height);
         mask = mask.resize(img_width, img_height, FilterType::Nearest);
         let mut res = mask.clone();
         for (x, y, pix) in mask.pixels() {
@@ -39,17 +43,20 @@ impl Border {
     fn draw_border(&self, img: &DynamicImage) -> MBGResult<DynamicImage> {
         let img_width = image::GenericImageView::width(img);
         let img_height = image::GenericImageView::height(img);
-        let center = (((img_width / 2) + self.width), ((img_height / 2) + self.width));
+        let center = (
+            ((img_width / 2) + self.width),
+            ((img_height / 2) + self.width),
+        );
         let target_color = read_color::rgb_maybe_a(&mut self.color.chars());
         if target_color.is_none() {
-            return Err(
-                MBGError::ConfigErr(String::from("Can't parse border color. Please use hex value."))
-            );
+            return Err(MBGError::ConfigErr(String::from(
+                "Can't parse border color. Please use hex value.",
+            )));
         }
         let target_color = target_color.unwrap();
         let target_color = match target_color {
-            ([r, g, b, ], Some(a)) => Rgba([r, g, b, a]),
-            ([r, g, b, ], None) => Rgba([r, g, b, 255u8]),
+            ([r, g, b], Some(a)) => Rgba([r, g, b, a]),
+            ([r, g, b], None) => Rgba([r, g, b, 255u8]),
         };
         if self.circle {
             let mut mask = DynamicImage::ImageRgba8(RgbaImage::from_pixel(
@@ -76,6 +83,7 @@ impl Border {
 
 impl ImageProcessor for Border {
     fn process(&self, img: &DynamicImage) -> MBGResult<DynamicImage> {
+        debug!("Setting border");
         let mut res = img.clone();
         if self.circle {
             res = self.crop_circle(&res)?;
diff --git a/src/img_processors/mod.rs b/src/img_processors/mod.rs
index d9d13e38de41a5a7d41e30c39120a11cb1e84d7d..adf94250722c93c2b0b0d829a265a9e11ccef942 100644
--- a/src/img_processors/mod.rs
+++ b/src/img_processors/mod.rs
@@ -142,4 +142,4 @@ fn mapper(
             width,
         }),
     }
-}
\ No newline at end of file
+}
diff --git a/src/img_processors/scale.rs b/src/img_processors/scale.rs
index e1c20e3d6748ec21593d9d098110689e79c557ae..8592aefa8cacf358d0c16627ccab973c66c21a1b 100644
--- a/src/img_processors/scale.rs
+++ b/src/img_processors/scale.rs
@@ -1,5 +1,5 @@
-use image::imageops::FilterType;
 use image::{DynamicImage, GenericImageView};
+use image::imageops::FilterType;
 
 use crate::config::image_processors::ProcessorParams;
 use crate::result::MBGResult;
@@ -13,12 +13,11 @@ pub struct ScaleProcessor {
 impl super::ImageProcessor for ScaleProcessor {
     fn process(&self, img: &DynamicImage) -> MBGResult<DynamicImage> {
         let abs_width = self.screen_width.abs() as u32;
-        let scale_factor = ((abs_width / img.width()) as f32) * self.params.strength;
-        let scale_factor = scale_factor.ceil() as u32;
+        let scale_factor = (abs_width as f32 / img.width() as f32) * self.params.strength;
         debug!("Scaling image by {} times", scale_factor);
         Ok(img.resize(
-            img.width() * scale_factor,
-            img.height() * scale_factor,
+            (img.width() as f32 * scale_factor) as u32,
+            (img.height() as f32 * scale_factor) as u32,
             FilterType::Nearest,
         ))
     }
diff --git a/src/main.rs b/src/main.rs
index af98e4d430e4141194fe76588a6e77980a462d54..cbabcac7f22bd628ef5506eb0c1b96620f63319f 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -9,10 +9,12 @@ extern crate serde_derive;
 
 use structopt::StructOpt;
 
+use crate::background::test_processors;
 use crate::config::Config;
 use crate::logging::setup_logger;
 use crate::player_dbus::start_listen;
 use crate::result::{MBGError, MBGResult};
+use structopt::clap::Shell;
 
 pub mod background;
 pub mod config;
@@ -23,30 +25,10 @@ pub mod logging;
 pub mod player_dbus;
 pub mod result;
 
-#[derive(Debug, StructOpt)]
-#[structopt(
-    name = "music_bg",
-    about = "Listens to your mpris interface and sets you a cool background."
-)]
-struct Opt {
-    #[structopt(subcommand)]
-    cmd: Option<RunMode>,
-}
-
-#[derive(StructOpt, Debug)]
-enum RunMode {
-    #[structopt(name = "run", about = "Run d-bus listener")]
-    Run,
-    #[structopt(
-        name = "config",
-        about = "Create or replace default configuration file."
-    )]
-    GenConf,
-}
+include!("cli.rs");
 
 fn main() -> MBGResult<()> {
     let opt: Opt = Opt::from_args();
-    let mode = opt.cmd.unwrap_or_else(|| RunMode::Run);
     let logger = setup_logger();
     if let Err(error) = logger {
         error!("Failed to create pretty logger");
@@ -57,9 +39,5 @@ fn main() -> MBGResult<()> {
     if res.is_err() {
         return Err(MBGError::X11Error(String::from("Could not connect to GTK")));
     }
-
-    match mode {
-        RunMode::Run => start_listen(),
-        RunMode::GenConf => Config::generate_config(),
-    }
+    run(opt)
 }