Skip to content

Commit e1f2dc8

Browse files
committed
Propagate copy_from through SubImage
Backport-Of: cf4dbaf
1 parent b92fbaa commit e1f2dc8

File tree

2 files changed

+90
-4
lines changed

2 files changed

+90
-4
lines changed

benches/copy_from.rs

Lines changed: 78 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,88 @@ use criterion::{black_box, criterion_group, criterion_main, Criterion};
22
use image::{GenericImage, ImageBuffer, Rgba};
33

44
pub fn bench_copy_from(c: &mut Criterion) {
5+
let at = image::math::Rect::from_xy_ranges(256..1280, 256..1280);
6+
7+
let mut target = ImageBuffer::from_pixel(2048, 2048, Rgba([0u8, 0, 0, 255]));
58
let src = ImageBuffer::from_pixel(2048, 2048, Rgba([255u8, 0, 0, 255]));
6-
let mut dst = ImageBuffer::from_pixel(2048, 2048, Rgba([0u8, 0, 0, 255]));
9+
let part = ImageBuffer::from_pixel(at.width, at.height, Rgba([255u8, 0, 0, 255]));
10+
11+
let view = image::GenericImageView::view(&src, at.x, at.y, at.width, at.height);
12+
13+
const BG: Rgba<u8> = Rgba([0u8, 0, 0, 255]);
14+
let samples = image::flat::FlatSamples::with_monocolor(&BG, at.width, at.height);
15+
let singular = samples.as_view().unwrap();
16+
17+
let mut samples = src.as_flat_samples();
18+
samples.layout.width = 1024;
19+
samples.layout.width_stride *= 2;
20+
samples.layout.height = 1024;
21+
samples.layout.height_stride *= 2;
22+
let skip = samples.as_view().unwrap();
723

824
c.bench_function("copy_from", |b| {
9-
b.iter(|| dst.copy_from(black_box(&src), 0, 0));
25+
b.iter(|| target.copy_from(black_box(&src), 0, 0));
26+
});
27+
28+
c.bench_function("copy_at", |b| {
29+
b.iter(|| target.copy_from(black_box(&part), at.x, at.y));
30+
});
31+
32+
c.bench_function("copy_view", |b| {
33+
b.iter(|| target.copy_from(black_box(&*view), at.x, at.y));
34+
});
35+
36+
c.bench_function("copy_fill", |b| {
37+
b.iter(|| target.copy_from(black_box(&singular), at.x, at.y));
38+
});
39+
40+
c.bench_function("copy_strides", |b| {
41+
b.iter(|| target.copy_from(black_box(&skip), at.x, at.y));
42+
});
43+
}
44+
45+
pub fn bench_copy_subimage_from(c: &mut Criterion) {
46+
let vp = image::math::Rect::from_xy_ranges(256..1280, 256..1280);
47+
let at = image::math::Rect::from_xy_ranges(128..512, 128..512);
48+
49+
let mut target = ImageBuffer::from_pixel(2048, 2048, Rgba([0u8, 0, 0, 255]));
50+
let mut target = target.sub_image(vp.x, vp.y, vp.width, vp.height);
51+
52+
let src = ImageBuffer::from_pixel(vp.width, vp.height, Rgba([255u8, 0, 0, 255]));
53+
let part = ImageBuffer::from_pixel(at.width, at.height, Rgba([255u8, 0, 0, 255]));
54+
let view = image::GenericImageView::view(&src, at.x, at.y, at.width, at.height);
55+
56+
const BG: Rgba<u8> = Rgba([0u8, 0, 0, 255]);
57+
let samples = image::flat::FlatSamples::with_monocolor(&BG, at.width, at.height);
58+
let singular = samples.as_view().unwrap();
59+
60+
let mut samples = src.as_flat_samples();
61+
samples.layout.width = at.width / 2;
62+
samples.layout.width_stride *= 2;
63+
samples.layout.height = at.height / 2;
64+
samples.layout.height_stride *= 2;
65+
let skip = samples.as_view().unwrap();
66+
67+
c.bench_function("copy_subimage_from", |b| {
68+
b.iter(|| target.copy_from(black_box(&src), 0, 0));
69+
});
70+
71+
c.bench_function("copy_subimage_at", |b| {
72+
b.iter(|| target.copy_from(black_box(&part), at.x, at.y));
73+
});
74+
75+
c.bench_function("copy_subimage_view", |b| {
76+
b.iter(|| target.copy_from(black_box(&*view), at.x, at.y));
77+
});
78+
79+
c.bench_function("copy_subimage_fill", |b| {
80+
b.iter(|| target.copy_from(black_box(&singular), at.x, at.y));
81+
});
82+
83+
c.bench_function("copy_subimage_strides", |b| {
84+
b.iter(|| target.copy_from(black_box(&skip), at.x, at.y));
1085
});
1186
}
1287

13-
criterion_group!(benches, bench_copy_from);
88+
criterion_group!(benches, bench_copy_from, bench_copy_subimage_from);
1489
criterion_main!(benches);

src/images/sub_image.rs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::{flat::ViewOfPixel, GenericImage, GenericImageView, ImageBuffer, Pixel};
1+
use crate::{flat::ViewOfPixel, math::Rect, GenericImage, GenericImageView, ImageBuffer, Pixel};
22
use std::ops::{Deref, DerefMut};
33

44
/// A View into another image
@@ -244,6 +244,17 @@ where
244244
self.image
245245
.blend_pixel(x + self.xoffset, y + self.yoffset, pixel);
246246
}
247+
248+
fn copy_from<O>(&mut self, other: &O, x: u32, y: u32) -> Result<(), crate::ImageError>
249+
where
250+
O: GenericImageView<Pixel = Self::Pixel>,
251+
{
252+
Rect::from_image_at(other, x, y).test_in_bounds(self)?;
253+
// Dispatch the inner images `copy_from` method with adjusted offsets. this ensures its
254+
// potentially optimized implementation gets used.
255+
self.image
256+
.copy_from(other, x + self.xoffset, y + self.yoffset)
257+
}
247258
}
248259

249260
#[cfg(test)]

0 commit comments

Comments
 (0)