benchmarks comparing the rust image processing ecosystem
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
#![feature(array_chunks)]
use fimg::Image;
use opencv::{core::CV_8UC3, prelude::*};

const SIZE: u32 = 5424;
const TO: u32 = 2712;

macro_rules! scale_opencv {
    ($name:ident => { scale($alg:literal) }) => {
        fn $name() {
            opencv::core::set_num_threads(1).unwrap();
            let mut data = iai::black_box(
                include_bytes!("../data.imgbuf")
                    .array_chunks::<3>()
                    .flat_map(|&[r, g, b]| [b, g, r])
                    .collect::<Vec<_>>(),
            );
            let mut o = unsafe { Mat::new_rows_cols(SIZE as i32, SIZE as i32, CV_8UC3).unwrap() };
            opencv::imgproc::resize(
                &unsafe {
                    Mat::new_size_with_data_def(
                        opencv::core::Size_ {
                            width: SIZE as i32,
                            height: SIZE as i32,
                        },
                        CV_8UC3,
                        data.as_mut_ptr() as *mut core::ffi::c_void,
                    )
                    .unwrap()
                },
                &mut o,
                opencv::core::Size_ {
                    width: TO as i32,
                    height: TO as i32,
                },
                0.0,
                0.0,
                $alg,
            )
            .unwrap();
            iai::black_box(&o);
        }
    };
}

macro_rules! scale_fimg {
    ($name:ident => { scale($alg: ident) }) => {
        fn $name() {
            #[allow(unused_mut)]
            let mut img = Image::<_, 3>::build(SIZE, SIZE)
                .buf(&iai::black_box(include_bytes!("../data.imgbuf"))[..]);
            img.scale::<fimg::scale::$alg>(TO, TO);
            iai::black_box(&img);
        }
    };
}

macro_rules! scale_resize {
    ($name:ident => { scale($alg: ident) }) => {
        fn $name() {
            use rgb::FromSlice;
            let src = iai::black_box(include_bytes!("../data.imgbuf").as_rgb());
            let mut dst = vec![0; TO as usize * TO as usize * 3];
            resize::new(
                SIZE as usize,
                SIZE as usize,
                TO as usize,
                TO as usize,
                resize::Pixel::RGB8,
                resize::Type::$alg,
            )
            .unwrap()
            .resize(src, dst.as_rgb_mut())
            .unwrap();
        }
    };
}

macro_rules! scale_img {
    ($name:ident => { scale($alg: ident) }) => {
        fn $name() {
            let img = image::RgbImage::from_raw(
                SIZE,
                SIZE,
                iai::black_box(include_bytes!("../data.imgbuf").to_vec()),
            )
            .unwrap();
            iai::black_box(image::imageops::resize(
                &img,
                TO,
                TO,
                image::imageops::FilterType::$alg,
            ));
        }
    };
}

scale_fimg!(nearest_fimg => { scale(Nearest) });
scale_img!(nearest_img => { scale(Nearest) });
scale_opencv!(nearest_opencv => { scale(6) });
scale_fimg!(lanczos_fimg => { scale(Lanczos3) });
scale_img!(lanczos_img => { scale(Lanczos3) });
scale_opencv!(lanczos_opencv => { scale(4) });
scale_resize!(lanczos_resize => { scale(Lanczos3 )});
scale_fimg!(bicubic_fimg => { scale(CatmullRom) });
scale_img!(bicubic_img => { scale(CatmullRom) });
scale_resize!(bicubic_resize => { scale(Catrom) });
scale_opencv!(bicubic_opencv => { scale(2) });

iai::main!(
    nearest_fimg,
    nearest_img,
    nearest_opencv,
    lanczos_fimg,
    lanczos_img,
    lanczos_resize,
    lanczos_opencv,
    bicubic_fimg,
    bicubic_img,
    bicubic_resize,
    bicubic_opencv,
);