<commit_before>//! The idea here is basically we provide a Game type,
//! which can swap between several different Scene types.
//! Ideally Scenes can be nested and we can build a stack
//! of them?  Or something.
//! We also need hooks: Load, unload... more finely grained?
//! Kinda tricky to separate create/destroy vs. load and unload,
//! KISS for now.

use ggez;
use ggez::GameResult;
use ggez::conf;
use ggez::event;
use ggez::game::GameState;

use std::collections::BTreeMap;
use std::time::Duration;

/// Arbitrary data that can be loaded to produce a Scene
/// of a particular type.  The T is the global data that
/// the Scene relies upon to function, such as your global
/// game state.
pub trait SavedScene<T> {
    fn load(&mut self) -> Box<Scene<T>>;
    fn name(&self) -> &str;
}

/// A Scene is sort of a stand-in GameState that can be
/// loaded and unloaded by the SceneManager.  When unloaded
/// it produces something implementing the SavedScene state,
/// which will re-produce the Scene when loaded.
///
/// Like a GameState, it has update() and draw() methods
/// (with a slightly different signature), as well as event
/// handlers.
pub trait Scene<T> {
    fn unload(&mut self) -> Box<SavedScene<T>>;

    /// Note this returns an Option<String>;
    /// if you want to switch to a new scene,
    /// return the name of the scene in the Option
    /// and it will be loaded.  Or None to just carry on.
    fn update(&mut self,
              _ctx: &mut ggez::Context,
              _dt: Duration,
              _state: &mut T)
              -> GameResult<Option<String>> {
        Ok(None)
    }

    fn draw(&mut self, _ctx: &mut ggez::Context, _state: &mut T) -> GameResult<()> {
        Ok(())
    }

    fn mouse_button_down_event(&mut self, _button: event::Mouse, _x: i32, _y: i32) {}

    fn mouse_button_up_event(&mut self, _button: event::Mouse, _x: i32, _y: i32) {}

    fn mouse_motion_event(&mut self,
                          _state: event::MouseState,
                          _x: i32,
                          _y: i32,
                          _xrel: i32,
                          _yrel: i32) {
    }

    fn mouse_wheel_event(&mut self, _x: i32, _y: i32) {}

    fn key_down_event(&mut self,
                      _keycode: Option<event::Keycode>,
                      _keymod: event::Mod,
                      _repeat: bool) {
    }

    fn key_up_event(&mut self,
                    _keycode: Option<event::Keycode>,
                    _keymod: event::Mod,
                    _repeat: bool) {
    }

    fn focus_event(&mut self, _gained: bool) {}

    /// Called upon a quit event.  If it returns true,
    /// the game does not exit.
    fn quit_event(&mut self) -> bool {
        println!("Quitting game");
        false
    }
}

/// The GameData trait just provides
/// a method to create a new object of type T, instantiating
/// your global game data.
///
/// It also provides a method that is called to generate
/// the first scene of your game.
pub trait GameData<T>
    where Self: Sized
{
    fn load(ctx: &mut ggez::Context, conf: &conf::Conf) -> GameResult<Self>;
    fn starting_scene() -> Box<SavedScene<T>>;
}

/// A SceneManager is a GameState that handles Scene's
/// and switches from one to another when requested.
///
/// The stuff you would normally store in your GameState
/// type should implement GameData and go into the T type.
pub struct SceneManager<T> {
    states: BTreeMap<String, Box<SavedScene<T>>>,
    current: Box<Scene<T>>,
    game_data: T,
    next_scene: Option<String>,
}

impl<T> GameState for SceneManager<T>
    where T: GameData<T>
{
    fn load(ctx: &mut ggez::Context, conf: &conf::Conf) -> GameResult<Self> {
        let starting_scene_state = T::starting_scene();
        let game_data = T::load(ctx, conf)?;

        Ok(Self::new(starting_scene_state, game_data))
    }

    fn update(&mut self, ctx: &mut ggez::Context, dt: Duration) -> GameResult<()> {
        // TODO: Get rid of this hacky clone!
        if let Some(ref scene_name) = self.next_scene.clone() {
            self.switch_scene(&scene_name)?;
        }
        self.next_scene = self.current.update(ctx, dt, &mut self.game_data)?;
        Ok(())
    }

    fn draw(&mut self, ctx: &mut ggez::Context) -> GameResult<()> {
        self.current.draw(ctx, &mut self.game_data)
    }

    fn mouse_button_down_event(&mut self, button: event::Mouse, x: i32, y: i32) {
        self.current.mouse_button_down_event(button, x, y)
    }

    fn mouse_button_up_event(&mut self, button: event::Mouse, x: i32, y: i32) {
        self.current.mouse_button_up_event(button, x, y)
    }

    fn mouse_motion_event(&mut self,
                          _state: event::MouseState,
                          _x: i32,
                          _y: i32,
                          _xrel: i32,
                          _yrel: i32) {
        self.current.mouse_motion_event(_state, _x, _y, _xrel, _yrel)
    }

    fn mouse_wheel_event(&mut self, _x: i32, _y: i32) {
        self.current.mouse_wheel_event(_x, _y)
    }

    fn key_down_event(&mut self,
                      _keycode: Option<event::Keycode>,
                      _keymod: event::Mod,
                      _repeat: bool) {
        self.current.key_down_event(_keycode, _keymod, _repeat)
    }

    fn key_up_event(&mut self,
                    _keycode: Option<event::Keycode>,
                    _keymod: event::Mod,
                    _repeat: bool) {
        self.current.key_up_event(_keycode, _keymod, _repeat)
    }

    fn focus_event(&mut self, _gained: bool) {
        self.current.focus_event(_gained)
    }

    /// Called upon a quit event.  If it returns true,
    /// the game does not exit.
    fn quit_event(&mut self) -> bool {
        self.current.quit_event()
    }
}

impl<T> SceneManager<T> {
    /// This lets us create a SceneManager by providing the data for it,
    /// instead of having it implicitly created via the GameData trait.
    fn new(mut starting_scene_state: Box<SavedScene<T>>, game_data: T) -> Self {
        let starting_scene = starting_scene_state.load();
        let mut scenes: BTreeMap<String, Box<SavedScene<T>>> = BTreeMap::new();
        scenes.insert(starting_scene_state.name().to_string(),
                      starting_scene_state);
        let sm = SceneManager {
            current: starting_scene,
            states: scenes,
            game_data: game_data,
            next_scene: None,
        };
        sm
    }

    pub fn game_data(&mut self) -> &mut T {
        &mut self.game_data
    }

    pub fn add<S: SavedScene<T> + 'static>(&mut self, scene_state: S) {
        self.states.insert(scene_state.name().to_string(), Box::new(scene_state));
    }

    pub fn current(&self) -> &Scene<T> {
        &*self.current
    }

    pub fn current_mut(&mut self) -> &mut Scene<T> {
        &mut *self.current
    }

    pub fn switch_scene(&mut self, scene_name: &str) -> GameResult<()> {
        // Save current scene
        let old_scene_state = self.current.unload();
        let old_scene_name = old_scene_state.name().to_string();
        self.states.insert(old_scene_name, old_scene_state);
        if let Some(scene_state) = self.states.get_mut(scene_name) {
            let new_scene = scene_state.load();
            self.current = new_scene;
            Ok(())
        } else {
            let msg = format!("SceneManager: Asked to load scene {} but it did not exist?",
                              scene_name);
            Err(ggez::GameError::ResourceNotFound(msg))
        }
    }
}

#[cfg(test)]
mod tests {
    use super::{Scene, SavedScene, SceneManager};

    #[derive(Clone, Debug)]
    struct TestSavedScene {
        value: i32,
        name: String,
    }

    impl SavedScene<()> for TestSavedScene {
        fn load(&mut self) -> Box<Scene<()>> {
            Box::new(TestScene(self.clone()))
        }
        fn name(&self) -> &str {
            &self.name
        }
    }

    #[derive(Clone, Debug)]
    struct TestScene(TestSavedScene);

    impl Scene<()> for TestScene {
        fn unload(&mut self) -> Box<SavedScene<()>> {
            Box::new(self.0.clone())
        }
    }

    #[test]
    fn test_scene_switching() {
        let default_scene = TestSavedScene {
            name: "default scene".to_string(),
            value: 42,
        };
        let new_scene = TestSavedScene {
            name: "other scene".to_string(),
            value: 23,
        };
        let mut sm = SceneManager::new(Box::new(default_scene), ());
        sm.add(new_scene);

        {
            let mut s = sm.current_mut().unload();
            assert_eq!(s.name(), "default scene");
        }

        let res = sm.switch_scene("other scene");
        assert!(res.is_ok());

        {
            let mut s = sm.current_mut().unload();
            assert_eq!(s.name(), "other scene");
        }

        let res = sm.switch_scene("non existent scene");
        assert!(res.is_err());
    }

}
<commit_msg>Diked out scene collection into its own thing<commit_after>//! The idea here is basically we provide a Game type,
//! which can swap between several different Scene types.
//! Ideally Scenes can be nested and we can build a stack
//! of them?  Or something.
//! We also need hooks: Load, unload... more finely grained?
//! Kinda tricky to separate create/destroy vs. load and unload,
//! KISS for now.

use ggez;
use ggez::GameResult;
use ggez::conf;
use ggez::event;
use ggez::game::GameState;

use std::collections::BTreeMap;
use std::time::Duration;

/// Arbitrary data that can be loaded to produce a Scene
/// of a particular type.  The T is the global data that
/// the Scene relies upon to function, such as your global
/// game state.
pub trait SavedScene<T> {
    fn load(&mut self) -> Box<Scene<T>>;
    fn name(&self) -> &str;
}

/// A Scene is sort of a stand-in GameState that can be
/// loaded and unloaded by the SceneManager.  When unloaded
/// it produces something implementing the SavedScene state,
/// which will re-produce the Scene when loaded.
///
/// Like a GameState, it has update() and draw() methods
/// (with a slightly different signature), as well as event
/// handlers.
pub trait Scene<T> {
    fn unload(&mut self) -> Box<SavedScene<T>>;

    /// Note this returns an Option<String>;
    /// if you want to switch to a new scene,
    /// return the name of the scene in the Option
    /// and it will be loaded.  Or None to just carry on.
    fn update(&mut self,
              _ctx: &mut ggez::Context,
              _dt: Duration,
              _state: &mut T)
              -> GameResult<Option<String>> {
        Ok(None)
    }

    fn draw(&mut self, _ctx: &mut ggez::Context, _state: &mut T) -> GameResult<()> {
        Ok(())
    }

    fn mouse_button_down_event(&mut self, _button: event::Mouse, _x: i32, _y: i32) {}

    fn mouse_button_up_event(&mut self, _button: event::Mouse, _x: i32, _y: i32) {}

    fn mouse_motion_event(&mut self,
                          _state: event::MouseState,
                          _x: i32,
                          _y: i32,
                          _xrel: i32,
                          _yrel: i32) {
    }

    fn mouse_wheel_event(&mut self, _x: i32, _y: i32) {}

    fn key_down_event(&mut self,
                      _keycode: Option<event::Keycode>,
                      _keymod: event::Mod,
                      _repeat: bool) {
    }

    fn key_up_event(&mut self,
                    _keycode: Option<event::Keycode>,
                    _keymod: event::Mod,
                    _repeat: bool) {
    }

    fn focus_event(&mut self, _gained: bool) {}

    /// Called upon a quit event.  If it returns true,
    /// the game does not exit.
    fn quit_event(&mut self) -> bool {
        println!("Quitting game");
        false
    }
}

/// The GameData trait just provides
/// a method to create a new object of type T, instantiating
/// your global game data.
///
/// It also provides a method that is called to generate
/// the first scene of your game.
pub trait GameData<T>
    where Self: Sized
{
    fn load(ctx: &mut ggez::Context, conf: &conf::Conf) -> GameResult<Self>;
    fn starting_scene() -> Box<SavedScene<T>>;
}

pub struct SceneStore<T> {
    states: BTreeMap<String, Box<SavedScene<T>>>,
}

impl<T> SceneStore<T> {
    pub fn add<S: SavedScene<T> + 'static>(&mut self, scene_state: S) {
        self.states.insert(scene_state.name().to_string(), Box::new(scene_state));
    }
}

/// A SceneManager is a GameState that handles Scene's
/// and switches from one to another when requested.
///
/// The stuff you would normally store in your GameState
/// type should implement GameData and go into the T type.
pub struct SceneManager<T> {
    store: SceneStore<T>,
    current: Box<Scene<T>>,
    game_data: T,
    next_scene: Option<String>,
}

impl<T> GameState for SceneManager<T>
    where T: GameData<T>
{
    fn load(ctx: &mut ggez::Context, conf: &conf::Conf) -> GameResult<Self> {
        let starting_scene_state = T::starting_scene();
        let game_data = T::load(ctx, conf)?;

        Ok(Self::new(starting_scene_state, game_data))
    }

    fn update(&mut self, ctx: &mut ggez::Context, dt: Duration) -> GameResult<()> {
        // TODO: Get rid of this hacky clone!
        if let Some(ref scene_name) = self.next_scene.clone() {
            self.switch_scene(&scene_name)?;
        }
        self.next_scene = self.current.update(ctx, dt, &mut self.game_data)?;
        Ok(())
    }

    fn draw(&mut self, ctx: &mut ggez::Context) -> GameResult<()> {
        self.current.draw(ctx, &mut self.game_data)
    }

    fn mouse_button_down_event(&mut self, button: event::Mouse, x: i32, y: i32) {
        self.current.mouse_button_down_event(button, x, y)
    }

    fn mouse_button_up_event(&mut self, button: event::Mouse, x: i32, y: i32) {
        self.current.mouse_button_up_event(button, x, y)
    }

    fn mouse_motion_event(&mut self,
                          _state: event::MouseState,
                          _x: i32,
                          _y: i32,
                          _xrel: i32,
                          _yrel: i32) {
        self.current.mouse_motion_event(_state, _x, _y, _xrel, _yrel)
    }

    fn mouse_wheel_event(&mut self, _x: i32, _y: i32) {
        self.current.mouse_wheel_event(_x, _y)
    }

    fn key_down_event(&mut self,
                      _keycode: Option<event::Keycode>,
                      _keymod: event::Mod,
                      _repeat: bool) {
        self.current.key_down_event(_keycode, _keymod, _repeat)
    }

    fn key_up_event(&mut self,
                    _keycode: Option<event::Keycode>,
                    _keymod: event::Mod,
                    _repeat: bool) {
        self.current.key_up_event(_keycode, _keymod, _repeat)
    }

    fn focus_event(&mut self, _gained: bool) {
        self.current.focus_event(_gained)
    }

    /// Called upon a quit event.  If it returns true,
    /// the game does not exit.
    fn quit_event(&mut self) -> bool {
        self.current.quit_event()
    }
}

impl<T> SceneManager<T> {
    /// This lets us create a SceneManager by providing the data for it,
    /// instead of having it implicitly created via the GameData trait.
    fn new(mut starting_scene_state: Box<SavedScene<T>>, game_data: T) -> Self {
        let starting_scene = starting_scene_state.load();
        let mut scenes: BTreeMap<String, Box<SavedScene<T>>> = BTreeMap::new();
        scenes.insert(starting_scene_state.name().to_string(),
                      starting_scene_state);
        let store = SceneStore { states: scenes };
        let sm = SceneManager {
            current: starting_scene,
            store: store,
            game_data: game_data,
            next_scene: None,
        };
        sm
    }

    pub fn game_data(&mut self) -> &mut T {
        &mut self.game_data
    }

    pub fn current(&self) -> &Scene<T> {
        &*self.current
    }

    pub fn current_mut(&mut self) -> &mut Scene<T> {
        &mut *self.current
    }

    pub fn switch_scene(&mut self, scene_name: &str) -> GameResult<()> {
        // Save current scene
        let old_scene_state = self.current.unload();
        let old_scene_name = old_scene_state.name().to_string();
        self.store.states.insert(old_scene_name, old_scene_state);
        if let Some(scene_state) = self.store.states.get_mut(scene_name) {
            let new_scene = scene_state.load();
            self.current = new_scene;
            Ok(())
        } else {
            let msg = format!("SceneManager: Asked to load scene {} but it did not exist?",
                              scene_name);
            Err(ggez::GameError::ResourceNotFound(msg))
        }
    }
}

#[cfg(test)]
mod tests {
    use super::{Scene, SavedScene, SceneManager};

    #[derive(Clone, Debug)]
    struct TestSavedScene {
        value: i32,
        name: String,
    }

    impl SavedScene<()> for TestSavedScene {
        fn load(&mut self) -> Box<Scene<()>> {
            Box::new(TestScene(self.clone()))
        }
        fn name(&self) -> &str {
            &self.name
        }
    }

    #[derive(Clone, Debug)]
    struct TestScene(TestSavedScene);

    impl Scene<()> for TestScene {
        fn unload(&mut self) -> Box<SavedScene<()>> {
            Box::new(self.0.clone())
        }
    }

    #[test]
    fn test_scene_switching() {
        let default_scene = TestSavedScene {
            name: "default scene".to_string(),
            value: 42,
        };
        let new_scene = TestSavedScene {
            name: "other scene".to_string(),
            value: 23,
        };
        let mut sm = SceneManager::new(Box::new(default_scene), ());
        sm.add(new_scene);

        {
            let mut s = sm.current_mut().unload();
            assert_eq!(s.name(), "default scene");
        }

        let res = sm.switch_scene("other scene");
        assert!(res.is_ok());

        {
            let mut s = sm.current_mut().unload();
            assert_eq!(s.name(), "other scene");
        }

        let res = sm.switch_scene("non existent scene");
        assert!(res.is_err());
    }

}
<|endoftext|>


<commit_before>use std::io::{Read, Write};

use result::{BfResult, Error};

/// The default number of 8-bit memory cells, as used by
/// [`State::new`](struct.State.html#method.new).
pub const DEFAULT_CAPACITY: usize = 30_000;

/// The BF machine state.
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct State {
    memory: Box<[u8]>,
    pointer: usize,
}

impl State {
    /// Creates a new BF machine state with capacity
    /// [`DEFAULT_CAPACITY`].
    pub fn new() -> Self {
        Self::with_capacity(DEFAULT_CAPACITY)
    }

    /// Creates a new BF machine state.
    pub fn with_capacity(capacity: usize) -> Self {
        State {
            memory: vec![0; capacity].into_boxed_slice(),
            pointer: 0,
        }
    }

    /// Decrements the pointer.
    ///
    /// # Errors
    ///
    /// Return `Err` if pointer would go below 0.
    #[inline]
    pub fn left(&mut self, count: usize) -> BfResult<()> {
        if self.check_neg_offset(count) {
            self.pointer -= count;
            Ok(())
        } else {
            Err(Error::PointerUnderflow)
        }
    }

    /// Increments the pointer.
    ///
    /// # Errors
    ///
    /// Return `Err` if pointer would go past the end of the memory.
    #[inline]
    pub fn right(&mut self, count: usize) -> BfResult<()> {
        if self.check_pos_offset(count) {
            self.pointer += count;
            Ok(())
        } else {
            Err(Error::PointerOverflow)
        }
    }

    #[inline]
    fn check_pos_offset(&self, offset: usize) -> bool {
        self.pointer + offset < self.memory.len()
    }

    #[inline]
    fn check_neg_offset(&self, offset: usize) -> bool {
        self.pointer >= offset
    }

    /// Increments the byte at the pointer.
    ///
    /// Wraps around modulo 256.
    #[inline]
    pub fn up(&mut self, count: u8) {
        let old = self.load();
        self.store(old.wrapping_add(count));
    }

    /// Decrements the byte at the pointer.
    ///
    /// Wraps around modulo 256.
    #[inline]
    pub fn down(&mut self, count: u8) {
        let old = self.load();
        self.store(old.wrapping_sub(count));
    }

    /// Gets the value of the point at the pointer.
    #[inline]
    pub fn load(&self) -> u8 {
        self.memory[self.pointer]
    }

    /// Sets the value of the byte at the pointer.
    #[inline]
    pub fn store(&mut self, value: u8) {
        self.memory[self.pointer] = value;
    }

    /// Adds the given value at the given positive offset from the pointer.
    #[inline]
    pub fn up_pos_offset(&mut self, offset: usize, value: u8) -> BfResult<()> {
        if self.check_pos_offset(offset) {
            let old = self.memory[self.pointer + offset];
            self.memory[self.pointer + offset] = old.wrapping_add(value);
            Ok(())
        } else {
            Err(Error::PointerOverflow)
        }
    }

    /// Adds the given value at the given negative offset from the pointer.
    #[inline]
    pub fn up_neg_offset(&mut self, offset: usize, value: u8) -> BfResult<()> {
        if self.check_neg_offset(offset) {
            let old = self.memory[self.pointer - offset];
            self.memory[self.pointer - offset] = old.wrapping_add(value);
            Ok(())
        } else {
            Err(Error::PointerUnderflow)
        }
    }

    /// Reads from a `Read` into the byte at the pointer.
    #[inline]
    pub fn read<R: Read>(&mut self, input: &mut R) {
        let mut byte = [0];
        let _ = input.read_exact(&mut byte);
        self.store(byte[0]);
    }

    /// Writes to a `Write` from the byte at the pointer.
    #[inline]
    pub fn write<W: Write>(&self, output: &mut W) {
        let _ = output.write_all(&[self.load()]);
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn right_moves_right() {
        let mut actual = make(&[0, 0, 0], 0);
        let expected = make(&[0, 0, 0], 1);

        actual.right(1).unwrap();

        assert_eq!(actual, expected);
    }

    #[test]
    fn right_then_left_restores() {
        let mut actual = make(&[0, 0, 0], 0);
        let expected = make(&[0, 0, 0], 0);

        actual.right(1).unwrap();
        actual.left(1).unwrap();

        assert_eq!(actual, expected);
    }

    #[test]
    fn up_goes_to_1() {
        let mut actual = make(&[0, 0, 0], 0);
        actual.up(1);
        assert_eq!(actual, make(&[1, 0, 0], 0))
    }

    #[test]
    fn down_goes_to_255() {
        let mut actual = make(&[0, 0, 0], 0);
        actual.down(1);
        assert_eq!(actual, make(&[255, 0, 0], 0))
    }

    #[test]
    fn load_reads() {
        assert_eq!(make(&[0, 0, 0], 0).load(), 0);
        assert_eq!(make(&[1, 0, 0], 0).load(), 1);
        assert_eq!(make(&[1, 2, 0], 1).load(), 2);
    }

    #[test]
    fn store_writes() {
        let mut actual = make(&[0, 0, 0], 0);
        actual.store(5);
        assert_eq!(actual, make(&[5, 0, 0], 0));
        actual.right(1).unwrap();
        actual.store(8);
        assert_eq!(actual, make(&[5, 8, 0], 1));
    }

    #[test]
    fn longer_sequence_of_actions() {
        let mut actual = make(&[0, 0, 0], 0);
        actual.up(1);
        assert_eq!(actual, make(&[1, 0, 0], 0));
        actual.up(1);
        assert_eq!(actual, make(&[2, 0, 0], 0));
        actual.right(1).unwrap();
        assert_eq!(actual, make(&[2, 0, 0], 1));
        actual.down(1);
        assert_eq!(actual, make(&[2, 255, 0], 1));
        actual.down(1);
        assert_eq!(actual, make(&[2, 254, 0], 1));
        actual.right(1).unwrap();
        assert_eq!(actual, make(&[2, 254, 0], 2));
        actual.store(77);
        assert_eq!(actual, make(&[2, 254, 77], 2));
    }

    #[test]
    fn right_to_right_edge_is_okay() {
        let mut actual = make(&[0, 0, 0], 0);
        actual.right(1).unwrap();
        actual.right(1).unwrap();
        assert_eq!(actual, make(&[0, 0, 0], 2));
    }

    #[test]
    #[should_panic]
    fn right_past_edge_is_error() {
        let mut actual = make(&[0, 0, 0], 0);
        actual.right(1).unwrap();
        actual.right(1).unwrap();
        actual.right(1).unwrap();
    }

    #[test]
    #[should_panic]
    fn move_left_is_error() {
        let mut machine = make(&[0, 0, 0], 0);
        machine.left(1).unwrap();
    }

    fn make(memory: &[u8], pointer: usize) -> State {
        State {
            memory: memory.to_vec().into_boxed_slice(),
            pointer: pointer,
        }
    }
}
<commit_msg>Simplified offsetting.<commit_after>use std::io::{Read, Write};

use result::{BfResult, Error};

/// The default number of 8-bit memory cells, as used by
/// [`State::new`](struct.State.html#method.new).
pub const DEFAULT_CAPACITY: usize = 30_000;

/// The BF machine state.
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct State {
    memory: Box<[u8]>,
    pointer: usize,
}

impl State {
    /// Creates a new BF machine state with capacity
    /// [`DEFAULT_CAPACITY`].
    pub fn new() -> Self {
        Self::with_capacity(DEFAULT_CAPACITY)
    }

    /// Creates a new BF machine state.
    pub fn with_capacity(capacity: usize) -> Self {
        State {
            memory: vec![0; capacity].into_boxed_slice(),
            pointer: 0,
        }
    }

    /// Decrements the pointer.
    ///
    /// # Errors
    ///
    /// Return `Err` if pointer would go below 0.
    #[inline]
    pub fn left(&mut self, count: usize) -> BfResult<()> {
        self.pointer = self.neg_offset(count)?;
        Ok(())
    }

    /// Increments the pointer.
    ///
    /// # Errors
    ///
    /// Return `Err` if pointer would go past the end of the memory.
    #[inline]
    pub fn right(&mut self, count: usize) -> BfResult<()> {
        self.pointer = self.pos_offset(count)?;
        Ok(())
    }

    #[inline]
    fn pos_offset(&self, offset: usize) -> BfResult<usize> {
        if self.pointer + offset < self.memory.len() {
            Ok(self.pointer + offset)
        } else {
            Err(Error::PointerOverflow)
        }
    }

    #[inline]
    fn neg_offset(&self, offset: usize) -> BfResult<usize> {
        if self.pointer >= offset {
            Ok(self.pointer - offset)
        } else {
            Err(Error::PointerUnderflow)
        }
    }

    /// Increments the byte at the pointer.
    ///
    /// Wraps around modulo 256.
    #[inline]
    pub fn up(&mut self, count: u8) {
        let old = self.load();
        self.store(old.wrapping_add(count));
    }

    /// Decrements the byte at the pointer.
    ///
    /// Wraps around modulo 256.
    #[inline]
    pub fn down(&mut self, count: u8) {
        let old = self.load();
        self.store(old.wrapping_sub(count));
    }

    /// Gets the value of the point at the pointer.
    #[inline]
    pub fn load(&self) -> u8 {
        self.memory[self.pointer]
    }

    /// Sets the value of the byte at the pointer.
    #[inline]
    pub fn store(&mut self, value: u8) {
        self.memory[self.pointer] = value;
    }

    /// Adds the given value at the given positive offset from the pointer.
    #[inline]
    pub fn up_pos_offset(&mut self, offset: usize, value: u8) -> BfResult<()> {
        let address = self.pos_offset(offset)?;
        let old = self.memory[address];
        self.memory[address] = old.wrapping_add(value);
        Ok(())
    }

    /// Adds the given value at the given negative offset from the pointer.
    #[inline]
    pub fn up_neg_offset(&mut self, offset: usize, value: u8) -> BfResult<()> {
        let address = self.neg_offset(offset)?;
        let old = self.memory[address];
        self.memory[address] = old.wrapping_add(value);
        Ok(())
    }

    /// Reads from a `Read` into the byte at the pointer.
    #[inline]
    pub fn read<R: Read>(&mut self, input: &mut R) {
        let mut byte = [0];
        let _ = input.read_exact(&mut byte);
        self.store(byte[0]);
    }

    /// Writes to a `Write` from the byte at the pointer.
    #[inline]
    pub fn write<W: Write>(&self, output: &mut W) {
        let _ = output.write_all(&[self.load()]);
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn right_moves_right() {
        let mut actual = make(&[0, 0, 0], 0);
        let expected = make(&[0, 0, 0], 1);

        actual.right(1).unwrap();

        assert_eq!(actual, expected);
    }

    #[test]
    fn right_then_left_restores() {
        let mut actual = make(&[0, 0, 0], 0);
        let expected = make(&[0, 0, 0], 0);

        actual.right(1).unwrap();
        actual.left(1).unwrap();

        assert_eq!(actual, expected);
    }

    #[test]
    fn up_goes_to_1() {
        let mut actual = make(&[0, 0, 0], 0);
        actual.up(1);
        assert_eq!(actual, make(&[1, 0, 0], 0))
    }

    #[test]
    fn down_goes_to_255() {
        let mut actual = make(&[0, 0, 0], 0);
        actual.down(1);
        assert_eq!(actual, make(&[255, 0, 0], 0))
    }

    #[test]
    fn load_reads() {
        assert_eq!(make(&[0, 0, 0], 0).load(), 0);
        assert_eq!(make(&[1, 0, 0], 0).load(), 1);
        assert_eq!(make(&[1, 2, 0], 1).load(), 2);
    }

    #[test]
    fn store_writes() {
        let mut actual = make(&[0, 0, 0], 0);
        actual.store(5);
        assert_eq!(actual, make(&[5, 0, 0], 0));
        actual.right(1).unwrap();
        actual.store(8);
        assert_eq!(actual, make(&[5, 8, 0], 1));
    }

    #[test]
    fn longer_sequence_of_actions() {
        let mut actual = make(&[0, 0, 0], 0);
        actual.up(1);
        assert_eq!(actual, make(&[1, 0, 0], 0));
        actual.up(1);
        assert_eq!(actual, make(&[2, 0, 0], 0));
        actual.right(1).unwrap();
        assert_eq!(actual, make(&[2, 0, 0], 1));
        actual.down(1);
        assert_eq!(actual, make(&[2, 255, 0], 1));
        actual.down(1);
        assert_eq!(actual, make(&[2, 254, 0], 1));
        actual.right(1).unwrap();
        assert_eq!(actual, make(&[2, 254, 0], 2));
        actual.store(77);
        assert_eq!(actual, make(&[2, 254, 77], 2));
    }

    #[test]
    fn right_to_right_edge_is_okay() {
        let mut actual = make(&[0, 0, 0], 0);
        actual.right(1).unwrap();
        actual.right(1).unwrap();
        assert_eq!(actual, make(&[0, 0, 0], 2));
    }

    #[test]
    #[should_panic]
    fn right_past_edge_is_error() {
        let mut actual = make(&[0, 0, 0], 0);
        actual.right(1).unwrap();
        actual.right(1).unwrap();
        actual.right(1).unwrap();
    }

    #[test]
    #[should_panic]
    fn move_left_is_error() {
        let mut machine = make(&[0, 0, 0], 0);
        machine.left(1).unwrap();
    }

    fn make(memory: &[u8], pointer: usize) -> State {
        State {
            memory: memory.to_vec().into_boxed_slice(),
            pointer: pointer,
        }
    }
}
<|endoftext|>


<commit_before>//! Statistical properties of images.

use crate::definitions::Image;
use crate::math::cast;
use conv::ValueInto;
use image::{GenericImage, GrayImage, Pixel, Primitive};
use num::Bounded;

/// A set of per-channel histograms from an image with 8 bits per channel.
pub struct ChannelHistogram {
    /// Per-channel histograms.
    pub channels: Vec<[u32; 256]>,
}

/// Returns a vector of per-channel histograms.
pub fn histogram<P>(image: &Image<P>) -> ChannelHistogram
where
    P: Pixel<Subpixel = u8> + 'static,
{
    let mut hist = vec![[0u32; 256]; P::CHANNEL_COUNT as usize];

    for pix in image.pixels() {
        for (i, c) in pix.channels().iter().enumerate() {
            hist[i][*c as usize] += 1;
        }
    }

    ChannelHistogram { channels: hist }
}

/// A set of per-channel cumulative histograms from an image with 8 bits per channel.
pub struct CumulativeChannelHistogram {
    /// Per-channel cumulative histograms.
    pub channels: Vec<[u32; 256]>,
}

/// Returns per-channel cumulative histograms.
pub fn cumulative_histogram<P>(image: &Image<P>) -> CumulativeChannelHistogram
where
    P: Pixel<Subpixel = u8> + 'static,
{
    let mut hist = histogram(image);

    for c in 0..hist.channels.len() {
        for i in 1..hist.channels[c].len() {
            hist.channels[c][i] += hist.channels[c][i - 1];
        }
    }

    CumulativeChannelHistogram {
        channels: hist.channels,
    }
}

/// Returns the `p`th percentile of the pixel intensities in an image.
///
/// We define the `p`th percentile intensity to be the least `x` such
/// that at least `p`% of image pixels have intensity less than or
/// equal to `x`.
///
/// # Panics
/// If `p > 100`.
///
/// # Examples
/// ```
/// # extern crate image;
/// # #[macro_use]
/// # extern crate imageproc;
/// # fn main() {
/// use imageproc::stats::percentile;
///
/// let image = gray_image!(
///     1, 2, 3, 4, 5;
///     6, 7, 8, 9, 10);
///
/// // The 0th percentile is always 0
/// assert_eq!(percentile(&image, 0), 0);
///
/// // Exactly 10% of pixels have intensity <= 1.
/// assert_eq!(percentile(&image, 10), 1);
///
/// // Fewer than 15% of pixels have intensity <=1, so the 15th percentile is 2.
/// assert_eq!(percentile(&image, 15), 2);
///
/// // All pixels have intensity <= 10.
/// assert_eq!(percentile(&image, 100), 10);
/// # }
/// ```
pub fn percentile(image: &GrayImage, p: u8) -> u8 {
    assert!(p <= 100, "requested percentile must be <= 100");

    let cum_hist = cumulative_histogram(&image).channels[0];
    let total = cum_hist[255] as u64;

    for i in 0..256 {
        if 100 * cum_hist[i] as u64 / total >= p as u64 {
            return i as u8;
        }
    }

    unreachable!();
}

/// Returns the square root of the mean of the squares of differences
/// between all subpixels in left and right. All channels are considered
/// equally. If you do not want this (e.g. if using RGBA) then change
/// image formats first.
pub fn root_mean_squared_error<I, J, P>(left: &I, right: &J) -> f64
where
    I: GenericImage<Pixel = P>,
    J: GenericImage<Pixel = P>,
    P: Pixel,
    P::Subpixel: ValueInto<f64>,
{
    mean_squared_error(left, right).sqrt()
}

/// Returns the peak signal to noise ratio for a clean image and its noisy
/// aproximation. All channels are considered equally. If you do not want this
/// (e.g. if using RGBA) then change image formats first.
/// See also [peak signal-to-noise ratio (wikipedia)](https://en.wikipedia.org/wiki/Peak_signal-to-noise_ratio).
pub fn peak_signal_to_noise_ratio<I, J, P>(original: &I, noisy: &J) -> f64
where
    I: GenericImage<Pixel = P>,
    J: GenericImage<Pixel = P>,
    P: Pixel,
    P::Subpixel: ValueInto<f64> + Primitive,
{
    let max: f64 = cast(<P::Subpixel as Bounded>::max_value());
    let mse = mean_squared_error(original, noisy);
    20f64 * max.log(10f64) - 10f64 * mse.log(10f64)
}

fn mean_squared_error<I, J, P>(left: &I, right: &J) -> f64
where
    I: GenericImage<Pixel = P>,
    J: GenericImage<Pixel = P>,
    P: Pixel,
    P::Subpixel: ValueInto<f64>,
{
    assert_dimensions_match!(left, right);
    let mut sum_squared_diffs = 0f64;
    for (p, q) in left.pixels().zip(right.pixels()) {
        for (c, d) in p.2.channels().iter().zip(q.2.channels().iter()) {
            let fc: f64 = cast(*c);
            let fd: f64 = cast(*d);
            let diff = fc - fd;
            sum_squared_diffs += diff * diff;
        }
    }
    let count = (left.width() * left.height() * P::CHANNEL_COUNT as u32) as f64;
    sum_squared_diffs / count
}

#[cfg(test)]
mod tests {
    use super::*;
    use image::{GrayImage, Luma, Rgb, RgbImage};
    use test::Bencher;

    #[test]
    fn test_cumulative_histogram() {
        let image = gray_image!(1u8, 2u8, 3u8, 2u8, 1u8);
        let hist = cumulative_histogram(&image).channels[0];

        assert_eq!(hist[0..4], [0, 2, 4, 5]);
        assert!(hist.iter().skip(4).all(|x| *x == 5));
    }

    #[test]
    fn test_cumulative_histogram_rgb() {
        let image = rgb_image!(
            [1u8, 10u8, 1u8],
            [2u8, 20u8, 2u8],
            [3u8, 30u8, 3u8],
            [2u8, 20u8, 2u8],
            [1u8, 10u8, 1u8]
        );

        let hist = cumulative_histogram(&image);
        let r = hist.channels[0];
        let g = hist.channels[1];
        let b = hist.channels[2];

        assert_eq!(r[0..4], [0, 2, 4, 5]);
        assert!(r.iter().skip(4).all(|x| *x == 5));

        assert_eq!(g[0..10], [0; 10]);
        assert_eq!(g[10..20], [2; 10]);
        assert_eq!(g[20..30], [4; 10]);
        assert_eq!(g[30], 5);
        assert!(b.iter().skip(30).all(|x| *x == 5));

        assert_eq!(b[0..4], [0, 2, 4, 5]);
        assert!(b.iter().skip(4).all(|x| *x == 5));
    }

    #[test]
    fn test_histogram() {
        let image = gray_image!(1u8, 2u8, 3u8, 2u8, 1u8);
        let hist = histogram(&image).channels[0];

        assert_eq!(hist[0..4], [0, 2, 2, 1]);
    }

    #[test]
    fn test_histogram_rgb() {
        let image = rgb_image!(
            [1u8, 10u8, 1u8],
            [2u8, 20u8, 2u8],
            [3u8, 30u8, 3u8],
            [2u8, 20u8, 2u8],
            [1u8, 10u8, 1u8]
        );

        let hist = histogram(&image);
        let r = hist.channels[0];
        let g = hist.channels[1];
        let b = hist.channels[2];

        assert_eq!(r[0..4], [0, 2, 2, 1]);
        assert!(r.iter().skip(4).all(|x| *x == 0));

        assert_eq!(g[0..10], [0; 10]);
        assert_eq!(g[10], 2);
        assert_eq!(g[11..20], [0; 9]);
        assert_eq!(g[20], 2);
        assert_eq!(g[21..30], [0; 9]);
        assert_eq!(g[30], 1);
        assert!(b.iter().skip(30).all(|x| *x == 0));

        assert_eq!(b[0..4], [0, 2, 2, 1]);
        assert!(b.iter().skip(4).all(|x| *x == 0));
    }

    #[test]
    fn test_root_mean_squared_error_grayscale() {
        let left = gray_image!(
            1, 2, 3;
            4, 5, 6);

        let right = gray_image!(
            8, 4, 7;
            6, 9, 1);

        let rms = root_mean_squared_error(&left, &right);
        let expected = (114f64 / 6f64).sqrt();
        assert_eq!(rms, expected);
    }

    #[test]
    fn test_root_mean_squared_error_rgb() {
        let left = rgb_image!([1, 2, 3], [4, 5, 6]);
        let right = rgb_image!([8, 4, 7], [6, 9, 1]);
        let rms = root_mean_squared_error(&left, &right);
        let expected = (114f64 / 6f64).sqrt();
        assert_eq!(rms, expected);
    }

    #[test]
    #[should_panic]
    fn test_root_mean_squares_rejects_mismatched_dimensions() {
        let left = gray_image!(1, 2);
        let right = gray_image!(8; 4);
        let _ = root_mean_squared_error(&left, &right);
    }

    fn left_image_rgb(width: u32, height: u32) -> RgbImage {
        RgbImage::from_fn(width, height, |x, y| Rgb([x as u8, y as u8, (x + y) as u8]))
    }

    fn right_image_rgb(width: u32, height: u32) -> RgbImage {
        RgbImage::from_fn(width, height, |x, y| Rgb([(x + y) as u8, x as u8, y as u8]))
    }

    #[bench]
    fn bench_root_mean_squared_error_rgb(b: &mut Bencher) {
        let left = left_image_rgb(50, 50);
        let right = right_image_rgb(50, 50);

        b.iter(|| {
            let error = root_mean_squared_error(&left, &right);
            test::black_box(error);
        });
    }

    fn left_image_gray(width: u32, height: u32) -> GrayImage {
        GrayImage::from_fn(width, height, |x, _| Luma([x as u8]))
    }

    fn right_image_gray(width: u32, height: u32) -> GrayImage {
        GrayImage::from_fn(width, height, |_, y| Luma([y as u8]))
    }

    #[bench]
    fn bench_root_mean_squared_error_gray(b: &mut Bencher) {
        let left = left_image_gray(50, 50);
        let right = right_image_gray(50, 50);

        b.iter(|| {
            let error = root_mean_squared_error(&left, &right);
            test::black_box(error);
        });
    }
}
<commit_msg>Update stats function to take GenericImageView (#427)<commit_after>//! Statistical properties of images.

use crate::definitions::Image;
use crate::math::cast;
use conv::ValueInto;
use image::{GenericImageView, GrayImage, Pixel, Primitive};
use num::Bounded;

/// A set of per-channel histograms from an image with 8 bits per channel.
pub struct ChannelHistogram {
    /// Per-channel histograms.
    pub channels: Vec<[u32; 256]>,
}

/// Returns a vector of per-channel histograms.
pub fn histogram<P>(image: &Image<P>) -> ChannelHistogram
where
    P: Pixel<Subpixel = u8> + 'static,
{
    let mut hist = vec![[0u32; 256]; P::CHANNEL_COUNT as usize];

    for pix in image.pixels() {
        for (i, c) in pix.channels().iter().enumerate() {
            hist[i][*c as usize] += 1;
        }
    }

    ChannelHistogram { channels: hist }
}

/// A set of per-channel cumulative histograms from an image with 8 bits per channel.
pub struct CumulativeChannelHistogram {
    /// Per-channel cumulative histograms.
    pub channels: Vec<[u32; 256]>,
}

/// Returns per-channel cumulative histograms.
pub fn cumulative_histogram<P>(image: &Image<P>) -> CumulativeChannelHistogram
where
    P: Pixel<Subpixel = u8> + 'static,
{
    let mut hist = histogram(image);

    for c in 0..hist.channels.len() {
        for i in 1..hist.channels[c].len() {
            hist.channels[c][i] += hist.channels[c][i - 1];
        }
    }

    CumulativeChannelHistogram {
        channels: hist.channels,
    }
}

/// Returns the `p`th percentile of the pixel intensities in an image.
///
/// We define the `p`th percentile intensity to be the least `x` such
/// that at least `p`% of image pixels have intensity less than or
/// equal to `x`.
///
/// # Panics
/// If `p > 100`.
///
/// # Examples
/// ```
/// # extern crate image;
/// # #[macro_use]
/// # extern crate imageproc;
/// # fn main() {
/// use imageproc::stats::percentile;
///
/// let image = gray_image!(
///     1, 2, 3, 4, 5;
///     6, 7, 8, 9, 10);
///
/// // The 0th percentile is always 0
/// assert_eq!(percentile(&image, 0), 0);
///
/// // Exactly 10% of pixels have intensity <= 1.
/// assert_eq!(percentile(&image, 10), 1);
///
/// // Fewer than 15% of pixels have intensity <=1, so the 15th percentile is 2.
/// assert_eq!(percentile(&image, 15), 2);
///
/// // All pixels have intensity <= 10.
/// assert_eq!(percentile(&image, 100), 10);
/// # }
/// ```
pub fn percentile(image: &GrayImage, p: u8) -> u8 {
    assert!(p <= 100, "requested percentile must be <= 100");

    let cum_hist = cumulative_histogram(&image).channels[0];
    let total = cum_hist[255] as u64;

    for i in 0..256 {
        if 100 * cum_hist[i] as u64 / total >= p as u64 {
            return i as u8;
        }
    }

    unreachable!();
}

/// Returns the square root of the mean of the squares of differences
/// between all subpixels in left and right. All channels are considered
/// equally. If you do not want this (e.g. if using RGBA) then change
/// image formats first.
pub fn root_mean_squared_error<I, J, P>(left: &I, right: &J) -> f64
where
    I: GenericImageView<Pixel = P>,
    J: GenericImageView<Pixel = P>,
    P: Pixel,
    P::Subpixel: ValueInto<f64>,
{
    mean_squared_error(left, right).sqrt()
}

/// Returns the peak signal to noise ratio for a clean image and its noisy
/// aproximation. All channels are considered equally. If you do not want this
/// (e.g. if using RGBA) then change image formats first.
/// See also [peak signal-to-noise ratio (wikipedia)](https://en.wikipedia.org/wiki/Peak_signal-to-noise_ratio).
pub fn peak_signal_to_noise_ratio<I, J, P>(original: &I, noisy: &J) -> f64
where
    I: GenericImageView<Pixel = P>,
    J: GenericImageView<Pixel = P>,
    P: Pixel,
    P::Subpixel: ValueInto<f64> + Primitive,
{
    let max: f64 = cast(<P::Subpixel as Bounded>::max_value());
    let mse = mean_squared_error(original, noisy);
    20f64 * max.log(10f64) - 10f64 * mse.log(10f64)
}

fn mean_squared_error<I, J, P>(left: &I, right: &J) -> f64
where
    I: GenericImageView<Pixel = P>,
    J: GenericImageView<Pixel = P>,
    P: Pixel,
    P::Subpixel: ValueInto<f64>,
{
    assert_dimensions_match!(left, right);
    let mut sum_squared_diffs = 0f64;
    for (p, q) in left.pixels().zip(right.pixels()) {
        for (c, d) in p.2.channels().iter().zip(q.2.channels().iter()) {
            let fc: f64 = cast(*c);
            let fd: f64 = cast(*d);
            let diff = fc - fd;
            sum_squared_diffs += diff * diff;
        }
    }
    let count = (left.width() * left.height() * P::CHANNEL_COUNT as u32) as f64;
    sum_squared_diffs / count
}

#[cfg(test)]
mod tests {
    use super::*;
    use image::{GrayImage, Luma, Rgb, RgbImage};
    use test::Bencher;

    #[test]
    fn test_cumulative_histogram() {
        let image = gray_image!(1u8, 2u8, 3u8, 2u8, 1u8);
        let hist = cumulative_histogram(&image).channels[0];

        assert_eq!(hist[0..4], [0, 2, 4, 5]);
        assert!(hist.iter().skip(4).all(|x| *x == 5));
    }

    #[test]
    fn test_cumulative_histogram_rgb() {
        let image = rgb_image!(
            [1u8, 10u8, 1u8],
            [2u8, 20u8, 2u8],
            [3u8, 30u8, 3u8],
            [2u8, 20u8, 2u8],
            [1u8, 10u8, 1u8]
        );

        let hist = cumulative_histogram(&image);
        let r = hist.channels[0];
        let g = hist.channels[1];
        let b = hist.channels[2];

        assert_eq!(r[0..4], [0, 2, 4, 5]);
        assert!(r.iter().skip(4).all(|x| *x == 5));

        assert_eq!(g[0..10], [0; 10]);
        assert_eq!(g[10..20], [2; 10]);
        assert_eq!(g[20..30], [4; 10]);
        assert_eq!(g[30], 5);
        assert!(b.iter().skip(30).all(|x| *x == 5));

        assert_eq!(b[0..4], [0, 2, 4, 5]);
        assert!(b.iter().skip(4).all(|x| *x == 5));
    }

    #[test]
    fn test_histogram() {
        let image = gray_image!(1u8, 2u8, 3u8, 2u8, 1u8);
        let hist = histogram(&image).channels[0];

        assert_eq!(hist[0..4], [0, 2, 2, 1]);
    }

    #[test]
    fn test_histogram_rgb() {
        let image = rgb_image!(
            [1u8, 10u8, 1u8],
            [2u8, 20u8, 2u8],
            [3u8, 30u8, 3u8],
            [2u8, 20u8, 2u8],
            [1u8, 10u8, 1u8]
        );

        let hist = histogram(&image);
        let r = hist.channels[0];
        let g = hist.channels[1];
        let b = hist.channels[2];

        assert_eq!(r[0..4], [0, 2, 2, 1]);
        assert!(r.iter().skip(4).all(|x| *x == 0));

        assert_eq!(g[0..10], [0; 10]);
        assert_eq!(g[10], 2);
        assert_eq!(g[11..20], [0; 9]);
        assert_eq!(g[20], 2);
        assert_eq!(g[21..30], [0; 9]);
        assert_eq!(g[30], 1);
        assert!(b.iter().skip(30).all(|x| *x == 0));

        assert_eq!(b[0..4], [0, 2, 2, 1]);
        assert!(b.iter().skip(4).all(|x| *x == 0));
    }

    #[test]
    fn test_root_mean_squared_error_grayscale() {
        let left = gray_image!(
            1, 2, 3;
            4, 5, 6);

        let right = gray_image!(
            8, 4, 7;
            6, 9, 1);

        let rms = root_mean_squared_error(&left, &right);
        let expected = (114f64 / 6f64).sqrt();
        assert_eq!(rms, expected);
    }

    #[test]
    fn test_root_mean_squared_error_rgb() {
        let left = rgb_image!([1, 2, 3], [4, 5, 6]);
        let right = rgb_image!([8, 4, 7], [6, 9, 1]);
        let rms = root_mean_squared_error(&left, &right);
        let expected = (114f64 / 6f64).sqrt();
        assert_eq!(rms, expected);
    }

    #[test]
    #[should_panic]
    fn test_root_mean_squares_rejects_mismatched_dimensions() {
        let left = gray_image!(1, 2);
        let right = gray_image!(8; 4);
        let _ = root_mean_squared_error(&left, &right);
    }

    fn left_image_rgb(width: u32, height: u32) -> RgbImage {
        RgbImage::from_fn(width, height, |x, y| Rgb([x as u8, y as u8, (x + y) as u8]))
    }

    fn right_image_rgb(width: u32, height: u32) -> RgbImage {
        RgbImage::from_fn(width, height, |x, y| Rgb([(x + y) as u8, x as u8, y as u8]))
    }

    #[bench]
    fn bench_root_mean_squared_error_rgb(b: &mut Bencher) {
        let left = left_image_rgb(50, 50);
        let right = right_image_rgb(50, 50);

        b.iter(|| {
            let error = root_mean_squared_error(&left, &right);
            test::black_box(error);
        });
    }

    fn left_image_gray(width: u32, height: u32) -> GrayImage {
        GrayImage::from_fn(width, height, |x, _| Luma([x as u8]))
    }

    fn right_image_gray(width: u32, height: u32) -> GrayImage {
        GrayImage::from_fn(width, height, |_, y| Luma([y as u8]))
    }

    #[bench]
    fn bench_root_mean_squared_error_gray(b: &mut Bencher) {
        let left = left_image_gray(50, 50);
        let right = right_image_gray(50, 50);

        b.iter(|| {
            let error = root_mean_squared_error(&left, &right);
            test::black_box(error);
        });
    }
}
<|endoftext|>


<commit_before>
#[cfg(test)]
mod rasterization {
    use cgmath::{Point2, Point3};
    use rasterization::triangle;
    use shader::{Shader, ShaderType, MAX_OUT_VALUES};

    fn triangle_test(a_screen: Point2<f32>, b_screen: Point2<f32>, c_screen: Point2<f32>, buffer_except: Vec<u32>) {
        let a = Point3::new(a_screen.x, a_screen.y, 0.5_f32);
        let b = Point3::new(b_screen.x, b_screen.y, 0.5_f32);
        let c = Point3::new(c_screen.x, c_screen.y, 0.5_f32);
        let x_size: usize = 7;
        let y_size: usize = 5;
        let mut cbuffer: Vec<u32> = vec![0; x_size * y_size];
        let mut zbuffer: Vec<f32> = vec![0.0_f32; x_size * y_size];
        let mut shader = Shader::new(ShaderType::Default);
        triangle(&mut cbuffer, &mut zbuffer, x_size, y_size, [a, b, c], [[0.0_f32;MAX_OUT_VALUES]; 3], 0, &mut shader);

        println!("");
        println!("real: ");
        for y in (0..y_size) {
            print!("   ");
            for x in (0..x_size) {
                print!("{}",if cbuffer[(y_size - y - 1) * x_size + x]==0 {0} else {1});
            }
            println!("");
        }
        println!("except: ");
        for y in (0..y_size) {
            print!("   ");
            for x in (0..x_size) {
                print!("{}",if buffer_except[y * x_size + x]==0 {0} else {1});
            }
            println!("");
        }
        for y in 0..y_size {
            for x in 0..x_size {
                let val_real = cbuffer[y * x_size + x];
                let val_except = buffer_except[(y_size - y - 1) * x_size + x];
                debug_assert!((val_real==0) == (val_except==0),
                              "real = {}, except = {}, x = {} y = {}",
                              val_real, val_except, x, y);
            }
        }
    }

    #[test]
    fn triangle_00() {
        triangle_test(Point2::new(1.0,4.0), Point2::new(2.0,1.0), Point2::new(6.0,3.0),
                      vec![0,0,0,0,0,0,0,
                           0,1,1,0,0,0,0,
                           0,1,1,1,1,0,0,
                           0,0,1,0,0,0,0,
                           0,0,0,0,0,0,0]);
    }

    #[test]
    fn triangle_01() {
        triangle_test(Point2::new(1.4,1.6), Point2::new(2.4,1.6), Point2::new(2.4,2.6),
                      vec![0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0]);
    }

    #[test]
    fn triangle_02() {
        triangle_test(Point2::new(3.5,1.5), Point2::new(4.5,1.5), Point2::new(4.5,2.5),
                      vec![0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0]);
    }

    #[test]
    fn triangle_03() {
        triangle_test(Point2::new(2.5,2.5), Point2::new(2.5,2.5), Point2::new(2.5,2.5),
                      vec![0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0]);
    }

    #[test]
    fn triangle_04() {
        triangle_test(Point2::new(0.0,0.0), Point2::new(4.0,0.0), Point2::new(6.0,2.0),
                      vec![0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,1,0,0,
                           0,1,1,1,0,0,0]);
    }

    #[test]
    fn triangle_05() {
        triangle_test(Point2::new(1.0,2.0), Point2::new(4.0,1.0), Point2::new(3.0,4.0),
                      vec![0,0,0,0,0,0,0,
                           0,0,1,0,0,0,0,
                           0,1,1,0,0,0,0,
                           0,0,1,1,0,0,0,
                           0,0,0,0,0,0,0]);
    }

    #[test]
    fn triangle_06() {
        triangle_test(Point2::new(5.5,2.5), Point2::new(4.0,1.0), Point2::new(3.0,4.0),
                      vec![0,0,0,0,0,0,0,
                           0,0,0,1,0,0,0,
                           0,0,0,1,1,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0]);
    }

    #[test]
    fn triangle_07() {
        triangle_test(Point2::new(1.5,0.5), Point2::new(2.5,0.5), Point2::new(1.5,-2.0),
                      vec![0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,1,0,0,0,0,0]);
    }

    #[test]
    fn triangle_08() {
        triangle_test(Point2::new(0.7,3.5), Point2::new(2.5,0.7), Point2::new(4.6,3.5),
                      vec![0,0,0,0,0,0,0,
                           0,1,1,1,1,0,0,
                           0,1,1,1,0,0,0,
                           0,0,1,0,0,0,0,
                           0,0,0,0,0,0,0]);
    }

    #[test]
    fn triangle_09() {
        triangle_test(Point2::new(0.7,1.5), Point2::new(2.7,3.2), Point2::new(4.7,1.5),
                      vec![0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,1,1,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0]);
    }

    #[test]
    fn triangle_10() {
        triangle_test(Point2::new(0.5,0.5), Point2::new(0.5,2.5), Point2::new(1.5,1.5),
                      vec![0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           1,0,0,0,0,0,0,
                           0,0,0,0,0,0,0]);
    }

    #[test]
    fn triangle_11() {
        triangle_test(Point2::new(0.5,0.5), Point2::new(0.5,2.5), Point2::new(2.5,2.5),
                      vec![0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           1,1,0,0,0,0,0,
                           1,0,0,0,0,0,0,
                           0,0,0,0,0,0,0]);
    }

    #[test]
    fn triangle_12() {
        triangle_test(Point2::new(0.5,0.5), Point2::new(2.5,2.5), Point2::new(2.5,0.5),
                      vec![0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,1,0,0,0,0,0,
                           0,0,0,0,0,0,0]);
    }

    #[test]
    fn triangle_13() {
        triangle_test(Point2::new(0.5,3.5), Point2::new(1.5,2.5), Point2::new(1.5,0.5),
                      vec![0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0]);
    }

    #[test]
    fn triangle_14() {
        triangle_test(Point2::new(0.5,3.5), Point2::new(1.5,2.5), Point2::new(2.0,5.0),
                      vec![0,1,0,0,0,0,0,
                           1,1,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0]);
    }

    #[test]
    fn triangle_15() {
        triangle_test(Point2::new(0.5,0.5), Point2::new(2.5,0.5), Point2::new(0.5,2.5),
                      vec![0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           1,0,0,0,0,0,0,
                           0,0,0,0,0,0,0]);
    }

    #[test]
    fn triangle_16() {
        triangle_test(Point2::new(2.5,2.5), Point2::new(2.5,0.5), Point2::new(0.5,2.5),
                      vec![0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           1,1,0,0,0,0,0,
                           0,1,0,0,0,0,0,
                           0,0,0,0,0,0,0]);
    }

    #[test]
    fn triangle_17() {
        triangle_test(Point2::new(5.0,2.0), Point2::new(5.0,-2.0), Point2::new(10.0,2.0),
                      vec![0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,1,1,
                           0,0,0,0,0,1,1]);
    }

    #[test]
    fn triangle_18() {
        triangle_test(Point2::new(5.0,3.0), Point2::new(5.0,10.0), Point2::new(10.0,3.0),
                      vec![0,0,0,0,0,1,1,
                           0,0,0,0,0,1,1,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0]);
    }
}
<commit_msg>fix tests<commit_after>
#[cfg(test)]
mod rasterization {
    use cgmath::{Point2, Point3};
    use rasterization::triangle;
    use shader::{Shader, ShaderType, MAX_OUT_VALUES};

    fn triangle_test(a_screen: Point2<f32>, b_screen: Point2<f32>, c_screen: Point2<f32>, buffer_except: Vec<u32>) {
        let a = Point3::new(a_screen.x, a_screen.y, 0.5_f32);
        let b = Point3::new(b_screen.x, b_screen.y, 0.5_f32);
        let c = Point3::new(c_screen.x, c_screen.y, 0.5_f32);
        let x_size: usize = 7;
        let y_size: usize = 5;
        let mut cbuffer: Vec<u32> = vec![0; x_size * y_size];
        let mut zbuffer: Vec<f32> = vec![0.0_f32; x_size * y_size];
        let mut shader = Shader::new(ShaderType::Default);
        shader.vertex_out_len = 3;
        triangle(&mut cbuffer, &mut zbuffer, x_size, y_size, [a, b, c], [[0.0_f32;MAX_OUT_VALUES]; 3], &mut shader);

        println!("");
        println!("real: ");
        for y in (0..y_size) {
            print!("   ");
            for x in (0..x_size) {
                print!("{}",if cbuffer[(y_size - y - 1) * x_size + x]==0 {0} else {1});
            }
            println!("");
        }
        println!("except: ");
        for y in (0..y_size) {
            print!("   ");
            for x in (0..x_size) {
                print!("{}",if buffer_except[y * x_size + x]==0 {0} else {1});
            }
            println!("");
        }
        for y in 0..y_size {
            for x in 0..x_size {
                let val_real = cbuffer[y * x_size + x];
                let val_except = buffer_except[(y_size - y - 1) * x_size + x];
                debug_assert!((val_real==0) == (val_except==0),
                              "real = {}, except = {}, x = {} y = {}",
                              val_real, val_except, x, y);
            }
        }
    }

    #[test]
    fn triangle_00() {
        triangle_test(Point2::new(1.0,4.0), Point2::new(2.0,1.0), Point2::new(6.0,3.0),
                      vec![0,0,0,0,0,0,0,
                           0,1,1,0,0,0,0,
                           0,1,1,1,1,0,0,
                           0,0,1,0,0,0,0,
                           0,0,0,0,0,0,0]);
    }

    #[test]
    fn triangle_01() {
        triangle_test(Point2::new(1.4,1.6), Point2::new(2.4,1.6), Point2::new(2.4,2.6),
                      vec![0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0]);
    }

    #[test]
    fn triangle_02() {
        triangle_test(Point2::new(3.5,1.5), Point2::new(4.5,1.5), Point2::new(4.5,2.5),
                      vec![0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0]);
    }

    #[test]
    fn triangle_03() {
        triangle_test(Point2::new(2.5,2.5), Point2::new(2.5,2.5), Point2::new(2.5,2.5),
                      vec![0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0]);
    }

    #[test]
    fn triangle_04() {
        triangle_test(Point2::new(0.0,0.0), Point2::new(4.0,0.0), Point2::new(6.0,2.0),
                      vec![0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,1,0,0,
                           0,1,1,1,0,0,0]);
    }

    #[test]
    fn triangle_05() {
        triangle_test(Point2::new(1.0,2.0), Point2::new(4.0,1.0), Point2::new(3.0,4.0),
                      vec![0,0,0,0,0,0,0,
                           0,0,1,0,0,0,0,
                           0,1,1,0,0,0,0,
                           0,0,1,1,0,0,0,
                           0,0,0,0,0,0,0]);
    }

    #[test]
    fn triangle_06() {
        triangle_test(Point2::new(5.5,2.5), Point2::new(4.0,1.0), Point2::new(3.0,4.0),
                      vec![0,0,0,0,0,0,0,
                           0,0,0,1,0,0,0,
                           0,0,0,1,1,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0]);
    }

    #[test]
    fn triangle_07() {
        triangle_test(Point2::new(1.5,0.5), Point2::new(2.5,0.5), Point2::new(1.5,-2.0),
                      vec![0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,1,0,0,0,0,0]);
    }

    #[test]
    fn triangle_08() {
        triangle_test(Point2::new(0.7,3.5), Point2::new(2.5,0.7), Point2::new(4.6,3.5),
                      vec![0,0,0,0,0,0,0,
                           0,1,1,1,1,0,0,
                           0,1,1,1,0,0,0,
                           0,0,1,0,0,0,0,
                           0,0,0,0,0,0,0]);
    }

    #[test]
    fn triangle_09() {
        triangle_test(Point2::new(0.7,1.5), Point2::new(2.7,3.2), Point2::new(4.7,1.5),
                      vec![0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,1,1,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0]);
    }

    #[test]
    fn triangle_10() {
        triangle_test(Point2::new(0.5,0.5), Point2::new(0.5,2.5), Point2::new(1.5,1.5),
                      vec![0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           1,0,0,0,0,0,0,
                           0,0,0,0,0,0,0]);
    }

    #[test]
    fn triangle_11() {
        triangle_test(Point2::new(0.5,0.5), Point2::new(0.5,2.5), Point2::new(2.5,2.5),
                      vec![0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           1,1,0,0,0,0,0,
                           1,0,0,0,0,0,0,
                           0,0,0,0,0,0,0]);
    }

    #[test]
    fn triangle_12() {
        triangle_test(Point2::new(0.5,0.5), Point2::new(2.5,2.5), Point2::new(2.5,0.5),
                      vec![0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,1,0,0,0,0,0,
                           0,0,0,0,0,0,0]);
    }

    #[test]
    fn triangle_13() {
        triangle_test(Point2::new(0.5,3.5), Point2::new(1.5,2.5), Point2::new(1.5,0.5),
                      vec![0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0]);
    }

    #[test]
    fn triangle_14() {
        triangle_test(Point2::new(0.5,3.5), Point2::new(1.5,2.5), Point2::new(2.0,5.0),
                      vec![0,1,0,0,0,0,0,
                           1,1,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0]);
    }

    #[test]
    fn triangle_15() {
        triangle_test(Point2::new(0.5,0.5), Point2::new(2.5,0.5), Point2::new(0.5,2.5),
                      vec![0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           1,0,0,0,0,0,0,
                           0,0,0,0,0,0,0]);
    }

    #[test]
    fn triangle_16() {
        triangle_test(Point2::new(2.5,2.5), Point2::new(2.5,0.5), Point2::new(0.5,2.5),
                      vec![0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           1,1,0,0,0,0,0,
                           0,1,0,0,0,0,0,
                           0,0,0,0,0,0,0]);
    }

    #[test]
    fn triangle_17() {
        triangle_test(Point2::new(5.0,2.0), Point2::new(5.0,-2.0), Point2::new(10.0,2.0),
                      vec![0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,1,1,
                           0,0,0,0,0,1,1]);
    }

    #[test]
    fn triangle_18() {
        triangle_test(Point2::new(5.0,3.0), Point2::new(5.0,10.0), Point2::new(10.0,3.0),
                      vec![0,0,0,0,0,1,1,
                           0,0,0,0,0,1,1,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0]);
    }
}
<|endoftext|>


<commit_before>use std::collections::{HashSet, HashMap};
use std::iter::FromIterator;
use std::cmp::min;
use std::error::Error;
use rand::{thread_rng, Rng};
use image::{GenericImage, DynamicImage, ImageBuffer, Luma, FilterType};
use image::imageops::rotate270;
use image::imageops::colorops::grayscale;

pub fn slice(count: u32, limit: u32) -> Result<HashSet<u32>, Box<Error>> {
    let mut indexes: Vec<u32> = (0..count).collect();

    if limit < count {
        let mut rng = thread_rng();
        rng.shuffle(&mut indexes);
        let len = indexes.len();
        indexes.truncate(min(len, limit as usize));
    }

    Ok(HashSet::from_iter(indexes.iter().cloned()))
}

fn convert(im: &DynamicImage,
           size: Option<u32>)
           -> Result<(f32, ImageBuffer<Luma<u8>, Vec<u8>>), Box<Error>> {
    let mut conv = im.clone();

    match size {
        Some(size) => {
            let (w, h) = conv.dimensions();

            let mul = match w > size || h > size {
                true => {
                    conv = conv.resize(size, size, FilterType::Lanczos3);
                    match w > h {
                        true => w as f32 / size as f32,
                        false => h as f32 / size as f32,
                    }
                }
                false => 1.0,
            };

            Ok((mul, grayscale(&conv)))
        }
        None => Ok((1.0, grayscale(&conv))),
    }
}

fn chop(conv: &mut ImageBuffer<Luma<u8>, Vec<u8>>,
        limit: u32)
        -> Result<ImageBuffer<Luma<u8>, Vec<u8>>, Box<Error>> {
    let (w, h) = conv.dimensions();
    let rows = slice(w, limit)?;
    let mut strips: ImageBuffer<Luma<u8>, Vec<u8>> = ImageBuffer::new(rows.len() as u32, h);
    for (i, row) in rows.iter().enumerate() {
        strips.copy_from(&conv.sub_image(*row, 0, 1, h), i as u32, 0);
    }

    Ok(strips)
}

fn entropy(strip: &mut ImageBuffer<Luma<u8>, Vec<u8>>,
           x: u32,
           y: u32,
           width: u32,
           height: u32)
           -> Result<f32, Box<Error>> {
    let sub = strip.sub_image(x, y, width, height);
    let (w, h) = sub.dimensions();
    let len = (w * h) as f32;

    let hm = sub.pixels().fold(HashMap::new(), |mut acc, e| {
        *acc.entry(e.2.data[0]).or_insert(0) += 1;
        acc
    });

    Ok(hm.values().fold(0f32, |acc, &x| {
        let f = x as f32 / len;
        acc - (f * f.log2())
    }))
}

pub fn scan(im: &DynamicImage,
            size: Option<u32>,
            columns: Option<u32>,
            depth: Option<f32>,
            threshold: Option<f32>,
            deep: Option<bool>)
            -> Result<Vec<u32>, Box<Error>> {
    let threshold = threshold.unwrap_or(0.5);
    let (mul, mut conv) = convert(im, size)?;
    let mut borders = Vec::new();

    for side in 0..4 {
        let mut strips = match columns {
            Some(columns) => chop(&mut conv, columns)?,
            None => conv.clone(),
        };
        let (w, h) = strips.dimensions();
        let height = (depth.unwrap_or(0.25) * h as f32).round() as u32;
        let mut border = 0;

        loop {
            let mut start = border + 1;
            for center in (border + 1)..height {
                if entropy(&mut strips, 0, border, w, center)? > 0.0 {
                    start = center;
                    break;
                }
            }

            let mut sub = 0;
            let mut delta = threshold;
            for center in (start..height).rev() {
                let upper = entropy(&mut strips, 0, border, w, center - border)?;
                let lower = entropy(&mut strips, 0, center, w, center - border)?;
                let diff = match lower != 0.0 {
                    true => upper as f32 / lower as f32,
                    false => delta,
                };
                if diff < delta && diff < threshold {
                    delta = diff;
                    sub = center;
                }
            }

            if sub == 0 || border == sub {
                break;
            }

            border = sub;

            if !deep.unwrap_or(true) {
                break;
            }
        }

        borders.push((border as f32 * mul) as u32);

        if side != 3 {
            conv = rotate270(&conv);
        }
    }

    Ok(borders)
}
<commit_msg>opt params<commit_after>use std::collections::{HashSet, HashMap};
use std::iter::FromIterator;
use std::cmp::min;
use std::error::Error;
use rand::{thread_rng, Rng};
use image::{GenericImage, DynamicImage, ImageBuffer, Luma, FilterType};
use image::imageops::rotate270;
use image::imageops::colorops::grayscale;

pub fn slice(count: u32, limit: u32) -> Result<HashSet<u32>, Box<Error>> {
    let mut indexes: Vec<u32> = (0..count).collect();

    if limit < count {
        let mut rng = thread_rng();
        rng.shuffle(&mut indexes);
        let len = indexes.len();
        indexes.truncate(min(len, limit as usize));
    }

    Ok(HashSet::from_iter(indexes.iter().cloned()))
}

fn convert(im: &DynamicImage,
           size: Option<u32>)
           -> Result<(f32, ImageBuffer<Luma<u8>, Vec<u8>>), Box<Error>> {
    let mut conv = im.clone();

    match size {
        Some(size) => {
            let (w, h) = conv.dimensions();

            let mul = match w > size || h > size {
                true => {
                    conv = conv.resize(size, size, FilterType::Lanczos3);
                    match w > h {
                        true => w as f32 / size as f32,
                        false => h as f32 / size as f32,
                    }
                }
                false => 1.0,
            };

            Ok((mul, grayscale(&conv)))
        }
        None => Ok((1.0, grayscale(&conv))),
    }
}

fn chop(conv: &mut ImageBuffer<Luma<u8>, Vec<u8>>,
        limit: u32)
        -> Result<ImageBuffer<Luma<u8>, Vec<u8>>, Box<Error>> {
    let (w, h) = conv.dimensions();
    let rows = slice(w, limit)?;
    let mut strips: ImageBuffer<Luma<u8>, Vec<u8>> = ImageBuffer::new(rows.len() as u32, h);
    for (i, row) in rows.iter().enumerate() {
        strips.copy_from(&conv.sub_image(*row, 0, 1, h), i as u32, 0);
    }

    Ok(strips)
}

fn entropy(strip: &mut ImageBuffer<Luma<u8>, Vec<u8>>,
           x: u32,
           y: u32,
           width: u32,
           height: u32)
           -> Result<f32, Box<Error>> {
    let sub = strip.sub_image(x, y, width, height);
    let (w, h) = sub.dimensions();
    let len = (w * h) as f32;

    let hm = sub.pixels().fold(HashMap::new(), |mut acc, e| {
        *acc.entry(e.2.data[0]).or_insert(0) += 1;
        acc
    });

    Ok(hm.values().fold(0f32, |acc, &x| {
        let f = x as f32 / len;
        acc - (f * f.log2())
    }))
}

pub fn scan(im: &DynamicImage,
            size: Option<u32>,
            columns: Option<u32>,
            depth: Option<f32>,
            threshold: Option<f32>,
            deep: Option<bool>)
            -> Result<Vec<u32>, Box<Error>> {
    let threshold = threshold.unwrap_or(0.5);
    let (mul, mut conv) = convert(im, size)?;
    let mut borders = Vec::new();
    let depth = depth.unwrap_or(0.25);
    let deep = deep.unwrap_or(true);

    for side in 0..4 {
        let mut strips = match columns {
            Some(columns) => chop(&mut conv, columns)?,
            None => conv.clone(),
        };
        let (w, h) = strips.dimensions();
        let height = (depth * h as f32).round() as u32;
        let mut border = 0;

        loop {
            let mut start = border + 1;
            for center in (border + 1)..height {
                if entropy(&mut strips, 0, border, w, center)? > 0.0 {
                    start = center;
                    break;
                }
            }

            let mut sub = 0;
            let mut delta = threshold;
            for center in (start..height).rev() {
                let upper = entropy(&mut strips, 0, border, w, center - border)?;
                let lower = entropy(&mut strips, 0, center, w, center - border)?;
                let diff = match lower != 0.0 {
                    true => upper as f32 / lower as f32,
                    false => delta,
                };
                if diff < delta && diff < threshold {
                    delta = diff;
                    sub = center;
                }
            }

            if sub == 0 || border == sub {
                break;
            }

            border = sub;

            if !deep {
                break;
            }
        }

        borders.push((border as f32 * mul) as u32);

        if side != 3 {
            conv = rotate270(&conv);
        }
    }

    Ok(borders)
}
<|endoftext|>


<commit_before>//! Types representing for data which will be retrieved from the database.
//! Currently this data is expected to look like a JSON object but this may be
//! changed in the future. Driver authors must cast the data they retrieve from
//! the database to these types.

use std::collections::BTreeMap;
use structure::Collection;

/// The atomic level of a pointer.
pub type Key = String;

/// Represents a JSON pointer to a document property.
pub type Pointer = Vec<Key>;

/// Various value types. Based on types in the [JSON standard][1] (see section
/// 5).
///
/// [1]: http://ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf
pub enum Value {
  /// The abscense of any value.
  Null,
  /// True or false.
  Boolean(bool),
  /// A numeric value, float, integer, whatever.
  Number(f64),
  /// A list of characters.
  String(String),
  /// A list of values.
  Array(Vec<Value>),
  /// A map of key/value pairs.
  Object(BTreeMap<Key, Value>)
}

/// A schema detailing what the data received from the database (or inserted
/// into the database) should be. Inspired after [JSON Schema][1]. A reference
/// on JSON Schema type-specific validations used in this enum may be found
/// [here][2].
///
/// [1]: http://json-schema.org
/// [2]: http://spacetelescope.github.io/understanding-json-schema/reference/type.html
pub enum Schema {
  /// Represents the absence of any value.
  Null,
  /// Represents a binary true/false value.
  Boolean,
  /// Represents a numeric type.
  Number {
    /// Forces the number to be a multiple of another. This helps in specifying
    /// integers if this value is `Some(1)` for example.
    multiple_of: Option<f32>,
    /// The minimum value the number can be.
    minimum: Option<f64>,
    /// The maximum value the number can be.
    maximum: Option<f64>
  },
  String {
    /// The mimimum length of characters in the string.
    min_length: Option<u64>,
    /// The maximum length of characters in the string.
    max_length: Option<u64>,
    /// A regular expression pattern to validate the string against.
    // TODO: Use a regex crate.
    pattern: Option<String>
  },
  /// Represents a set of any type.
  Array {
    /// A schema which all items in the array must match.
    items: Option<Box<Schema>>
  },
  /// Represents a set of key/value pairs.
  Object {
    /// Schemas associated to the object properties.
    properties: BTreeMap<String, Schema>,
    /// Properties that are required to be in the object.
    required: Vec<String>,
    /// Whether or not there may be extra properties outside of the ones
    /// defined by the properties map.
    additional_properties: bool
  },
  /// Represents a value which *must* be one of the defined values.
  Enum(Vec<Value>)
}

/// Different database collection property updates.
pub enum Patch {
  /// Set a property to a new value.
  Set(Pointer, Value),
  /// Reset a property to its default value.
  Reset(Pointer),
  /// Remove a property from the database entirely.
  Remove(Pointer)
}

/// A recursive filter condition for a `Value`.
pub enum Filter {
  /// Combine multiple filters with an “and” operator.
  And(Vec<Filter>),
  /// Combine multiple filters with an “or” operator.
  Or(Vec<Filter>),
  /// Inverts the filter.
  Not(Box<Filter>),
  /// The basic condition of a filter.
  Condition(Pointer, FilterCondition)
}

pub enum FilterCondition {
  Equal(Value),
  OneOf(Vec<Value>),
  GreaterThan(Value),
  LessThan(Value)
}

/// A single way in which to order a collection of documents.
pub struct Ordering(Pointer, OrderDirection);

pub enum OrderDirection {
  Ascending,
  Descending
}

// TODO: Find a more Rust idiomatic solution for ranges.
pub struct Range {
  from: Option<u32>,
  to: Option<u32>
}
<commit_msg>Add tuple to schema enum.<commit_after>//! Types representing for data which will be retrieved from the database.
//! Currently this data is expected to look like a JSON object but this may be
//! changed in the future. Driver authors must cast the data they retrieve from
//! the database to these types.

use std::collections::BTreeMap;
use structure::Collection;

/// The atomic level of a pointer.
pub type Key = String;

/// Represents a JSON pointer to a document property.
pub type Pointer = Vec<Key>;

/// Various value types. Based on types in the [JSON standard][1] (see section
/// 5).
///
/// [1]: http://ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf
pub enum Value {
  /// The abscense of any value.
  Null,
  /// True or false.
  Boolean(bool),
  /// A numeric value, float, integer, whatever.
  Number(f64),
  /// A list of characters.
  String(String),
  /// A list of values.
  Array(Vec<Value>),
  /// A map of key/value pairs.
  Object(BTreeMap<Key, Value>)
}

/// A schema detailing what the data received from the database (or inserted
/// into the database) should be. Inspired after [JSON Schema][1]. A reference
/// on JSON Schema type-specific validations used in this enum may be found
/// [here][2].
///
/// [1]: http://json-schema.org
/// [2]: http://spacetelescope.github.io/understanding-json-schema/reference/type.html
pub enum Schema {
  /// Represents the absence of any value.
  Null,
  /// Represents a binary true/false value.
  Boolean,
  /// Represents a numeric type.
  Number {
    /// Forces the number to be a multiple of another. This helps in specifying
    /// integers if this value is `Some(1)` for example.
    multiple_of: Option<f32>,
    /// The minimum value the number can be.
    minimum: Option<f64>,
    /// The maximum value the number can be.
    maximum: Option<f64>
  },
  String {
    /// The mimimum length of characters in the string.
    min_length: Option<u64>,
    /// The maximum length of characters in the string.
    max_length: Option<u64>,
    /// A regular expression pattern to validate the string against.
    // TODO: Use a regex crate.
    pattern: Option<String>
  },
  /// Represents a set of any type.
  Array {
    /// A schema which all items in the array must match.
    items: Option<Box<Schema>>
  },
  /// Represents any tuple of values.
  Tuple {
    /// Schemas which each tuple value (in the same place) must comply with.
    items: Vec<Schema>,
    /// Whether or not there can be more items in the tuple.
    additional_items: bool
  },
  /// Represents a set of key/value pairs.
  Object {
    /// Schemas associated to the object properties.
    properties: BTreeMap<String, Schema>,
    /// Properties that are required to be in the object.
    required: Vec<String>,
    /// Whether or not there may be extra properties outside of the ones
    /// defined by the properties map.
    additional_properties: bool
  },
  /// Represents a value which *must* be one of the defined values.
  Enum(Vec<Value>)
}

/// Different database collection property updates.
pub enum Patch {
  /// Set a property to a new value.
  Set(Pointer, Value),
  /// Reset a property to its default value.
  Reset(Pointer),
  /// Remove a property from the database entirely.
  Remove(Pointer)
}

/// A recursive filter condition for a `Value`.
pub enum Filter {
  /// Combine multiple filters with an “and” operator.
  And(Vec<Filter>),
  /// Combine multiple filters with an “or” operator.
  Or(Vec<Filter>),
  /// Inverts the filter.
  Not(Box<Filter>),
  /// The basic condition of a filter.
  Condition(Pointer, FilterCondition)
}

pub enum FilterCondition {
  Equal(Value),
  OneOf(Vec<Value>),
  GreaterThan(Value),
  LessThan(Value)
}

/// A single way in which to order a collection of documents.
pub struct Ordering(Pointer, OrderDirection);

pub enum OrderDirection {
  Ascending,
  Descending
}

// TODO: Find a more Rust idiomatic solution for ranges.
pub struct Range {
  from: Option<u32>,
  to: Option<u32>
}
<|endoftext|>