Skip to content

Commit 059387a

Browse files
committed
perf: Introduce ImageView type
1 parent 2c52bd0 commit 059387a

File tree

3 files changed

+91
-19
lines changed

3 files changed

+91
-19
lines changed

src/image.rs

+70-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use thiserror::Error;
44

55
use crate::models::Color;
66

7-
pub trait Image {
7+
pub trait Image: Sized {
88
/// Get the width of the image, in pixels
99
fn width(&self) -> u32;
1010

@@ -193,3 +193,72 @@ impl TryFrom<(Vec<u8>, u32, u32)> for RawImage {
193193
})
194194
}
195195
}
196+
197+
pub struct ImageView<'i, T: Image> {
198+
inner: &'i T,
199+
xmin: u32,
200+
xmax: u32,
201+
ymin: u32,
202+
ymax: u32,
203+
}
204+
205+
impl<'i, T: Image> Image for ImageView<'i, T> {
206+
fn width(&self) -> u32 {
207+
self.xmax - self.xmin
208+
}
209+
210+
fn height(&self) -> u32 {
211+
self.ymax - self.ymin
212+
}
213+
214+
fn color_at(&self, x: u32, y: u32) -> Option<Color> {
215+
self.inner.color_at(x + self.xmin, y + self.ymin)
216+
}
217+
218+
unsafe fn color_at_unchecked(&self, x: u32, y: u32) -> Color {
219+
self.inner.color_at_unchecked(x + self.xmin, y + self.ymin)
220+
}
221+
222+
fn to_raw_image(&self) -> RawImage {
223+
let w = self.width();
224+
let h = self.height();
225+
let mut data = Vec::with_capacity((w * h * RawImage::CHANNELS) as usize);
226+
227+
unsafe {
228+
for y in 0..h {
229+
for x in 0..w {
230+
let (r, g, b) = self.color_at_unchecked(x, y).into_components();
231+
data.push(r);
232+
data.push(g);
233+
data.push(b);
234+
}
235+
}
236+
}
237+
238+
RawImage {
239+
data,
240+
width: w as _,
241+
height: h as _,
242+
}
243+
}
244+
}
245+
246+
pub trait ImageViewExt: Image {
247+
fn wrap(&self, x: std::ops::Range<u32>, y: std::ops::Range<u32>) -> ImageView<Self>;
248+
}
249+
250+
impl<T: Image> ImageViewExt for T {
251+
fn wrap(&self, x: std::ops::Range<u32>, y: std::ops::Range<u32>) -> ImageView<Self> {
252+
ImageView {
253+
inner: self,
254+
xmin: x.start,
255+
xmax: x.end,
256+
ymin: y.start,
257+
ymax: y.end,
258+
}
259+
}
260+
}
261+
262+
pub mod prelude {
263+
pub use super::{Image, ImageViewExt};
264+
}

src/instance/black_border_detector.rs

+9-10
Original file line numberDiff line numberDiff line change
@@ -192,19 +192,18 @@ impl BlackBorder {
192192
}
193193
}
194194

195-
pub fn get_ranges(&self, width: u32, height: u32) -> ((u32, u32), (u32, u32)) {
195+
pub fn get_ranges(
196+
&self,
197+
width: u32,
198+
height: u32,
199+
) -> (std::ops::Range<u32>, std::ops::Range<u32>) {
196200
if self.unknown {
197-
((0, width), (0, height))
201+
(0..width, 0..height)
198202
} else {
199203
(
200-
(
201-
self.vertical_size.min(width / 2),
202-
(width - self.vertical_size).max(width / 2),
203-
),
204-
(
205-
self.horizontal_size.min(height / 2),
206-
(height - self.horizontal_size).max(height / 2),
207-
),
204+
self.vertical_size.min(width / 2)..(width - self.vertical_size).max(width / 2),
205+
self.horizontal_size.min(height / 2)
206+
..(height - self.horizontal_size).max(height / 2),
208207
)
209208
}
210209
}

src/instance/core.rs

+12-8
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::{
22
color::{color_to16, ChannelAdjustments, ChannelAdjustmentsBuilder},
3-
image::Image,
3+
image::prelude::*,
44
models::{Color, Color16, InstanceConfig, Leds},
55
};
66

@@ -48,20 +48,24 @@ impl Core {
4848
let black_border = self.black_border_detector.current_border();
4949

5050
// Update the 16-bit color data from the LED ranges and the image
51-
let ((xmin, xmax), (ymin, ymax)) = black_border.get_ranges(image.width(), image.height());
52-
let width = (xmax - xmin) as f32;
53-
let height = (ymax - ymin) as f32;
51+
let image = {
52+
let (x, y) = black_border.get_ranges(image.width(), image.height());
53+
image.wrap(x, y)
54+
};
55+
56+
let width = image.width() as f32;
57+
let height = image.height() as f32;
5458
for (spec, value) in self.leds.leds.iter().zip(self.color_data.iter_mut()) {
5559
let mut r_acc = 0u64;
5660
let mut g_acc = 0u64;
5761
let mut b_acc = 0u64;
5862
let mut cnt = 0u64;
5963

6064
// TODO: Fixed point arithmetic
61-
let lxmin = spec.hmin * width + xmin as f32;
62-
let lxmax = spec.hmax * width + xmin as f32;
63-
let lymin = spec.vmin * height + ymin as f32;
64-
let lymax = spec.vmax * height + ymin as f32;
65+
let lxmin = spec.hmin * width;
66+
let lxmax = spec.hmax * width;
67+
let lymin = spec.vmin * height;
68+
let lymax = spec.vmax * height;
6569

6670
for y in lymin.floor() as u32..=(lymax.ceil() as u32).min(image.height() - 1) {
6771
let y_area = if (y as f32) < lymin {

0 commit comments

Comments
 (0)