Reputation: 3401
I'm trying to re a Photoshop Adjustment Layer style process where image processing functions are representing by layers in a stack, where the result of the top/first process is fed into the next process. This could be represented as an array of processing functions, where the output of each function is fed into the next.
[Change Brightness(img)->Change Saturation(img)->Change Levels(img)]
How could I achieve this kind of 'handing off' of a value from a nonstatic array of functions in Rust?
fn op_a(mut a: Vec<u8>, p1: i32) -> Vec<u8> {
//process image
println!("Operation A on image with size: {}, and parameter1 val: {}", a.len(), p1);
a[0] = 10;
a
}
fn op_b(mut a: Vec<u8>, p1: i32, p2: i32) -> Vec<u8> {
//process image
println!("Operation B on image with size: {}, parameter 1 val: {}, parameter 2 val: {}", a.len(), p1, p2);
a[0] += 2;
a
}
fn op_c(mut a: Vec<u8>, p1: i32, p2: i32, p3: i32) -> Vec<u8> {
//process image
println!("Operation C on image with size: {}, parameter 1 val: {}, parameter 2 val: {}, parameter 3 val: {}", a.len(), p1, p2, p3);
a[0] *= 2;
a
}
fn pipe_function_array(initial_image: ImageBuffer, Vec<functions>)->ImageBuffer{
//executes an array of functions passing each to the next function in the array, with an initual input value of initial_image
}
fn main() {
let my_starting_value = *some Vec<u8>*;
let my_funcs = *an array of op_a, op_b, and op_c*;
let final_image = pipe_function_array(vec![0], my_funcs);
}
Upvotes: 1
Views: 100
Reputation: 4133
Your code basically works once you fix the obvious syntax errors.
fn op_a(mut a: Vec<u8>) -> Vec<u8> {
//process image
println!("Operation A on image with size: {}", a.len());
a[0] = 10;
a
}
fn op_b(mut a: Vec<u8>) -> Vec<u8> {
//process image
println!("Operation B on image with size: {}", a.len());
a[0] += 2;
a
}
fn op_c(mut a: Vec<u8>) -> Vec<u8> {
//process image
println!("Operation C on image with size: {}", a.len());
a[0] *= 2;
a
}
fn pipe_function_array(initial_image: Vec<u8>, a: Vec<fn(Vec<u8>) -> Vec<u8>>) -> Vec<u8> {
//Using fold here, but you can easily just use a for loop if you prefer.
a.iter()
.fold(initial_image, |image, operation| (operation)(image))
}
fn main() {
// You have to define the type of the Vec here,
// otherwise the compiler will throw some ambiguous errors.
let my_funcs: Vec<fn(Vec<u8>) -> Vec<u8>> = vec![op_a, op_b, op_c];
let final_image = pipe_function_array(vec![0], my_funcs);
dbg!(final_image);
}
Instead of directly passing function pointers however, I would suggest taking a different approach of using an array of enums.
enum Operations {
Saturation {
config: SaturationConfig,
},
Contrast {
config: ContrastConfig,
}
}
fn saturation(mut a: Vec<u8>, config: SaturationConfig) -> Vec<u8> {
//process image
a
}
fn contrast(mut a: Vec<u8>, config: ContrastConfig) -> Vec<u8> {
//process image
a
}
fn pipe_function_array(mut initial_image: Vec<u8>, a: Vec<Operations>) -> Vec<u8> {
a.iter()
.fold(initial_image, |image, operation| match operation {
Operations::Saturation { config } => saturation(image, config),
Operations::Contrast { config } => contrast(image, config),
})
}
Upvotes: 1