Skip to main content

rvlib/
view.rs

1use image::{GenericImageView, ImageBuffer, Rgb};
2
3use rvimage_domain::{BbF, Calc, PtF, ShapeI, TPtF, pos_transform};
4
5pub type ImageU8 = ImageBuffer<Rgb<u8>, Vec<u8>>;
6
7pub const START_WIDTH: u32 = 640;
8pub const START_HEIGHT: u32 = 480;
9
10/// Scales a coordinate from an axis of `size_from` to an axis of `size_to`
11pub fn scale_coord<T>(x: T, size_from: T, size_to: T) -> T
12where
13    T: Calc,
14{
15    x * size_to / size_from
16}
17
18fn coord_view_2_orig(x: TPtF, n_transformed: TPtF, n_orig: TPtF, off: TPtF) -> TPtF {
19    off + scale_coord(x, n_transformed, n_orig)
20}
21
22/// Converts the position of a pixel in the view to the coordinates of the original image
23pub fn pos_2_orig_pos(
24    view_pos: PtF,
25    shape_orig: ShapeI,
26    shape_win: ShapeI,
27    zoom_box: &Option<BbF>,
28) -> PtF {
29    pos_transform(view_pos, shape_orig, shape_win, zoom_box, coord_view_2_orig)
30}
31fn coord_orig_2_view(x: f64, n_transformed: f64, n_orig: f64, off: f64) -> f64 {
32    scale_coord(x - off, n_orig, n_transformed)
33}
34
35/// Converts the position of a pixel in the view to the coordinates of the original image
36pub fn pos_from_orig_pos(
37    orig_pos: PtF,
38    shape_orig: ShapeI,
39    shape_win: ShapeI,
40    zoom_box: &Option<BbF>,
41) -> Option<PtF> {
42    if let Some(zb) = zoom_box
43        && !zb.contains(orig_pos)
44    {
45        return None;
46    }
47    Some(pos_transform(
48        orig_pos,
49        shape_orig,
50        shape_win,
51        zoom_box,
52        coord_orig_2_view,
53    ))
54}
55#[must_use]
56pub fn from_orig(im_orig: &ImageU8, zoom_box: Option<BbF>) -> ImageU8 {
57    if let Some(zoom_box) = zoom_box {
58        let (img_w, img_h) = (im_orig.width(), im_orig.height());
59        let x = (zoom_box.x.round() as u32).min(img_w);
60        let y = (zoom_box.y.round() as u32).min(img_h);
61        let w = (zoom_box.w.round() as u32).min(img_w - x);
62        let h = (zoom_box.h.round() as u32).min(img_h - y);
63        im_orig.view(x, y, w, h).to_image()
64    } else {
65        im_orig.clone()
66    }
67}
68
69#[must_use]
70pub fn project_on_bb(p: PtF, bb: &BbF) -> PtF {
71    let x = p.x.max(bb.x).min(bb.x + bb.w - 1.0);
72    let y = p.y.max(bb.y).min(bb.y + bb.h - 1.0);
73    PtF { x, y }
74}
75
76#[test]
77fn test_project() {
78    let bb = BbF::from_arr(&[5.0, 5.0, 10.0, 10.0]);
79    assert_eq!(
80        PtF { x: 5.0, y: 5.0 },
81        project_on_bb((0.0, 0.0).into(), &bb)
82    );
83    assert_eq!(
84        PtF { x: 14.0, y: 14.0 },
85        project_on_bb((15.0, 20.0).into(), &bb)
86    );
87    assert_eq!(
88        PtF { x: 10.0, y: 14.0 },
89        project_on_bb((10.0, 15.0).into(), &bb)
90    );
91    assert_eq!(
92        PtF { x: 14.0, y: 14.0 },
93        project_on_bb((20.0, 15.0).into(), &bb)
94    );
95}