1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
// (c) Copyright 2019-2023 MIT
// this is manually created because it doesn't follow the standard from the introspection output

/// VipsLinear (linear), calculate (a * in + b)
/// inp: `&VipsImage` -> Input image
/// a: `&[f64]` -> Multiply by this. Must have equal len as b
/// b: `&[f64]` -> Add this. Must have equal len as a
/// returns `VipsImage` - Output image
pub fn linear(inp: &VipsImage, a: &mut[f64], b: &mut[f64]) -> Result<VipsImage> {
    unsafe {
        if a.len() != b.len() {
            return Err(Error::LinearError)
        }
        let inp_in: *mut bindings::VipsImage = inp.ctx;
        let a_in: *mut f64 = a.as_mut_ptr();
        let b_in: *mut f64 = b.as_mut_ptr();
        let mut out_out: *mut bindings::VipsImage = null_mut();

        let vips_op_response =
            bindings::vips_linear(inp_in, &mut out_out, a_in, b_in, b.len() as i32, NULL);
        utils::result(
            vips_op_response,
            VipsImage { ctx: out_out },
            Error::LinearError,
        )
    }
}

/// Options for linear operation
pub struct LinearOptions {
    /// uchar: `bool` -> Output should be uchar
    /// default: false
    pub uchar: bool,
}

impl std::default::Default for LinearOptions {
    fn default() -> Self {
        LinearOptions { uchar: false }
    }
}

/// VipsLinear (linear), calculate (a * in + b)
/// inp: `&VipsImage` -> Input image
/// a: `&[f64]` -> Multiply by this. Must have equal len as b
/// b: `&[f64]` -> Add this. Must have equal len as a
/// linear_options: `&LinearOptions` -> optional arguments
/// returns `VipsImage` - Output image
pub fn linear_with_opts(
    inp: &VipsImage,
    a: &mut [f64],
    b: &mut [f64],
    linear_options: &LinearOptions,
) -> Result<VipsImage> {
    unsafe {
        if a.len() != b.len() {
            return Err(Error::LinearError)
        }
        let inp_in: *mut bindings::VipsImage = inp.ctx;
        let a_in: *mut f64 = a.as_mut_ptr();
        let b_in: *mut f64 = b.as_mut_ptr();
        let mut out_out: *mut bindings::VipsImage = null_mut();

        let uchar_in: i32 = if linear_options.uchar { 1 } else { 0 };
        let uchar_in_name = utils::new_c_string("uchar")?;

        let vips_op_response = bindings::vips_linear(
            inp_in,
            &mut out_out,
            a_in,
            b_in,
            b.len() as i32,
            uchar_in_name.as_ptr(),
            uchar_in,
            NULL,
        );
        utils::result(
            vips_op_response,
            VipsImage { ctx: out_out },
            Error::LinearError,
        )
    }
}

/// VipsGetpoint (getpoint), read a point from an image
/// inp: `&VipsImage` -> Input image
/// x: `i32` -> Point to read
/// min: 0, max: 10000000, default: 0
/// y: `i32` -> Point to read
/// min: 0, max: 10000000, default: 0
/// returns `Vec<f64>` - Array of output values
pub fn getpoint(inp: &VipsImage, x: i32, y: i32) -> Result<Vec<f64>> {
    unsafe {
        let inp_in: *mut bindings::VipsImage = inp.ctx;
        let mut out_array_size: i32 = 0;
        let mut out_array: *mut f64 = null_mut();

        let vips_op_response = bindings::vips_getpoint(
            inp_in,
            &mut out_array,
            &mut out_array_size,
            x,
            y,
            NULL,
        );
        utils::result(
            vips_op_response,
            utils::new_double_array(out_array, out_array_size.try_into().unwrap()),
            Error::GetpointError,
        )
    }
}

/// VipsCase (case), use pixel values to pick cases from an array of images
/// index: `&VipsImage` -> Index image
/// cases: `&mut [VipsImage]` -> Array of case images
/// n: `i32` -> number of case images
/// returns `VipsImage` - Output image
pub fn case(index: &VipsImage, cases: &mut [VipsImage], n: i32) -> Result<VipsImage> {
    unsafe {
        let index_in: *mut bindings::VipsImage = index.ctx;
        let cases_in: *mut *mut bindings::VipsImage =
            cases.iter().map(|v| v.ctx).collect::<Vec<_>>().as_mut_ptr();
        let mut out_out: *mut bindings::VipsImage = null_mut();

        let vips_op_response = bindings::vips_case(index_in, cases_in, &mut out_out, n, NULL);
        utils::result(
            vips_op_response,
            VipsImage { ctx: out_out },
            Error::CaseError,
        )
    }
}