pnglitcher 0.2.0

PNG glitcher
Documentation
#![deny(unsafe_code)]

#[macro_use]
extern crate bitflags;

use image;
pub mod chunk;
mod common;
mod encoder;
mod filter;
mod srgb;
pub mod text_metadata;
mod traits;
mod utils;
use std::fs::File;
use std::io::BufWriter;

pub use crate::{
    common::*,
    encoder::{Encoder, EncodingError, StreamWriter, Writer},
    filter::{AdaptiveFilterType, FilterType},
};

pub fn duplicate(input: &str, output: &str, filter: u8, occurence: usize, gap: usize) {
    let glitch_input = open_input(input);
    let title = define_output_name(output);
    let mut writer = open_output(&title, filter, &glitch_input);

    writer
        .duplicate(&glitch_input.buffer, occurence, gap)
        .unwrap();
}

pub fn duplicate_sample(input: &str, output: &str, occurence: usize, gap: usize) {
    let glitch_input = open_input(input);

    for n in 0..5 {
        let title = define_output_name_with_filter(output, filter_name(n));
        let mut writer = open_output(&title, n, &glitch_input);

        writer
            .duplicate(&glitch_input.buffer, occurence, gap)
            .unwrap();
    }
}

pub fn wrong_filter(input: &str, output: &str, filter: u8) {
    let glitch_input = open_input(input);
    let title = define_output_name(output);
    let mut writer = open_output(&title, 0, &glitch_input);
    writer.wrong_filter(&glitch_input.buffer, filter).unwrap();
}

pub fn wrong_filter_sample(input: &str, output: &str) {
    let glitch_input = open_input(input);

    for n in 0..5 {
        let title = define_output_name_with_filter(output, filter_name(n));
        let mut writer = open_output(&title, n, &glitch_input);
        writer.wrong_filter(&glitch_input.buffer, n).unwrap();
    }
}

pub fn variable_filter(input: &str, output: &str, random: bool) {
    let glitch_input = open_input(input);
    let title = define_output_name(output);
    let mut writer = open_output(&title, 0, &glitch_input);
    writer
        .variable_filter(&glitch_input.buffer, random)
        .unwrap();
}

pub fn replace(input: &str, output: &str, filter: u8, occurence: usize) {
    let glitch_input = open_input(input);

    let title = define_output_name(output);
    let mut writer = open_output(&title, filter, &glitch_input);

    writer.replace(&glitch_input.buffer, occurence).unwrap();
}

pub fn replace_sample(input: &str, output: &str, occurence: usize) {
    let glitch_input = open_input(input);

    for n in 0..5 {
        let title = define_output_name_with_filter(output, filter_name(n));
        let mut writer = open_output(&title, n, &glitch_input);

        writer.replace(&glitch_input.buffer, occurence).unwrap();
    }
}

fn define_output_name(output: &str) -> String {
    if output.ends_with(".png") || output.ends_with(".PNG") {
        output.to_string()
    } else {
        format!("{}.png", output).to_string()
    }
}

fn define_output_name_with_filter(output: &str, filter: &str) -> String {
    if output.ends_with(".png") {
        format!("{}_{}.png", output.trim_end_matches(".png"), filter)
    } else if output.ends_with(".PNG") {
        format!("{}_{}.png", output.trim_end_matches(".PNG"), filter)
    } else {
        format!("{}_{}.png", output, filter)
    }
}

fn open_input(input: &str) -> GlitchInput {
    let img = image::open(&input).unwrap().to_rgb8();
    let (imgx, imgy) = (img.dimensions().0, img.dimensions().1);
    let buffer = img.into_raw();
    let glitch_input = GlitchInput {
        imgx: imgx,
        imgy: imgy,
        buffer: buffer,
    };
    glitch_input
}

fn open_output(title: &str, filter: u8, glitch_input: &GlitchInput) -> Writer<BufWriter<File>> {
    let file = std::fs::File::create(&title).unwrap();
    let w = std::io::BufWriter::new(file);
    let mut enc = Encoder::new(w, glitch_input.imgx, glitch_input.imgy);
    enc.set_color(ColorType::Rgb);
    enc.set_filter(FilterType::from_u8(filter).unwrap());
    enc.write_header().unwrap()
}

struct GlitchInput {
    imgx: u32,
    imgy: u32,
    buffer: Vec<u8>,
}

fn filter_name(filter: u8) -> &'static str {
    let filters = ["none", "sub", "up", "avg", "paeth"];
    filters[usize::from(filter)]
}