rexpaint 0.1.2

This crate provides functionality for reading and writing .xp files of the Grid Sage Games REXPaint ASCII art editor
Documentation
//! noise generation demo
extern crate noise;
extern crate rexpaint;

use noise::{NoiseFn, Perlin, Turbulence};
use rand::random;
use rexpaint::{XpColor, XpFile};
use std::env;
use std::fs::File;

#[cfg_attr(rustfmt, rustfmt_skip)]
const CMAP_FIRE: &'static [XpColor] = &[
    XpColor { r: 0, g: 0, b: 0 },
    XpColor { r: 255, g: 0, b: 0 },
    XpColor { r: 255, g: 255, b: 0 },
    XpColor { r: 255, g: 255, b: 255 },
];

#[cfg_attr(rustfmt, rustfmt_skip)]
const CMAP_NEBULA: &'static [XpColor] = &[
    XpColor { r: 0, g: 0, b: 0 },
    XpColor { r: 0, g: 0, b: 128 },
    XpColor { r: 128, g: 0, b: 254 },
];

fn lerp(a: XpColor, b: XpColor, i: f32) -> XpColor {
    if i <= 0.0 {
        a
    } else if i >= 1.0 {
        b
    } else {
        XpColor::new(
            ((a.r as f32) * (1.0 - i) + (b.r as f32) * i) as u8,
            ((a.g as f32) * (1.0 - i) + (b.g as f32) * i) as u8,
            ((a.b as f32) * (1.0 - i) + (b.b as f32) * i) as u8,
        )
    }
}

fn cmap_lookup(cmap: &[XpColor], value: f32) -> XpColor {
    let i = ((value + 1.0) / 2.0) * ((cmap.len() - 1) as f32);
    let n = (i as i32).max(0).min((cmap.len() as i32) - 2); /* could use .clamp later */
    lerp(cmap[n as usize], cmap[n as usize + 1], i - n as f32)
}

fn main() {
    let args: Vec<String> = env::args().collect();
    let width = args
        .get(1)
        .and_then(|x| x.parse::<usize>().ok())
        .unwrap_or(80);
    let height = args
        .get(2)
        .and_then(|x| x.parse::<usize>().ok())
        .unwrap_or(60);
    let cmap_name = args.get(3).cloned().unwrap_or("fire".to_string());
    let mut xp = XpFile::new(width, height);
    let cmap = if cmap_name == "fire" {
        CMAP_FIRE
    } else if cmap_name == "nebula" {
        CMAP_NEBULA
    } else {
        panic!("unknown color map {}", cmap_name);
    };

    println!(
        "generating {}×{} noise.xp, color map \"{}\"",
        width, height, cmap_name
    );

    // Create some Turbulence noise
    let perlin = Perlin::new(random());
    let turbulence = Turbulence::<_, Perlin>::new(&perlin);

    for y in 0..height {
        for x in 0..width {
            let val = turbulence.get([
                (x as f64) / ((width - 1) as f64),
                (y as f64) / ((height - 1) as f64),
            ]) as f32;
            let cell = xp.layers[0].get_mut(x, y).unwrap();
            cell.bg = cmap_lookup(cmap, val);
        }
    }

    let mut f = File::create("noise.xp").unwrap();
    xp.write(&mut f).unwrap();
}