🏡 index : ~doyle/shalom.git

author Jordan Doyle <jordan@doyle.la> 2024-01-03 19:22:57.0 +00:00:00
committer Jordan Doyle <jordan@doyle.la> 2024-01-03 19:22:57.0 +00:00:00
commit
18f5cc459df09145600ebee7f591ad9e7550e6b8 [patch]
tree
aae9d1ef33250ba83ffded7122916ab8947b95b8
parent
7ff01f1471c2da126638a0e0051dfd2725564762
download
18f5cc459df09145600ebee7f591ad9e7550e6b8.tar.gz

Move to stackblur for performance



Diff

 Cargo.lock                          | 41 ++++++++++++++++++++++++++++++++++++++-
 shalom/Cargo.toml                   |  1 +-
 shalom/src/pages/room/listen.rs     |  3 +--
 shalom/src/theme.rs                 | 33 ++++++++++++++++++++++++++++++-
 shalom/src/widgets/colour_picker.rs | 17 +++++++++-------
 5 files changed, 85 insertions(+), 10 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index 1738165..df3aa62 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -206,6 +206,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07"

[[package]]
name = "blend-srgb"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b8a187f5213b0a15f4344b1850bf1bd1f5cbe98eaf61d9914406723a9a2e6426"

[[package]]
name = "block"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1454,6 +1460,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "029d73f573d8e8d63e6d5020011d3255b28c3ba85d6cf870a07184ed23de9284"

[[package]]
name = "imgref"
version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "90d944e334f00f4449c9640b440a171f816be0152305c12ef90424fc35fd035c"

[[package]]
name = "imgref-iter"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "58112733c0ee178b66dceba49e0445d0b293268719de579d2c7dd4c2290976aa"
dependencies = [
 "imgref",
]

[[package]]
name = "indexmap"
version = "1.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2921,6 +2942,7 @@ dependencies = [
 "serde",
 "serde_json",
 "serde_with",
 "stackblur-iter",
 "strum",
 "time",
 "tokio",
@@ -3079,6 +3101,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"

[[package]]
name = "stackblur-iter"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712b7bee292d3d0ac59c5110f826d3d8aaafd8f39e455319acebe06c0eae3e7f"
dependencies = [
 "blend-srgb",
 "imgref",
 "imgref-iter",
 "rayon",
 "unique",
]

[[package]]
name = "static_assertions"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -3632,6 +3667,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c"

[[package]]
name = "unique"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d360722e1f3884f5b14d332185f02ff111f771f0c76a313268fe6af1409aba96"

[[package]]
name = "untrusted"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/shalom/Cargo.toml b/shalom/Cargo.toml
index 21b9f54..82f5de1 100644
--- a/shalom/Cargo.toml
+++ b/shalom/Cargo.toml
@@ -22,6 +22,7 @@ reqwest = { version = "0.11.22", default-features = false, features = ["rustls-t
serde = { version = "1.0", features = ["derive"] }
serde_with = { version = "3.4", features = ["macros"] }
serde_json = { version = "1.0", features = ["raw_value"] }
stackblur-iter = { version = "0.2.0", features = ["blend-srgb", "rayon"] }
strum = { version = "0.25", features = ["derive"] }
tokio = { version = "1.33", features = ["net", "sync", "rt", "macros", "time", "fs"] }
tokio-stream = {  version = "0.1", features = ["sync"] }
diff --git a/shalom/src/pages/room/listen.rs b/shalom/src/pages/room/listen.rs
index 0186a9b..7f30573 100644
--- a/shalom/src/pages/room/listen.rs
+++ b/shalom/src/pages/room/listen.rs
@@ -6,7 +6,6 @@ use iced::{
    widget::{container, image::Handle, Column},
    Element, Renderer, Subscription,
};
use image::imageops::blur;
use url::Url;

use crate::{
@@ -202,7 +201,7 @@ impl Listen {
            if let Some(MaybePendingImage::Loading(url)) = &self.background {
                download_image(
                    url.clone(),
                    |image| blur(&darken_image(image, 0.3), 5.0),
                    |image| crate::theme::blur(&darken_image(image, 0.3), 15),
                    Message::BackgroundDownloaded,
                )
            } else {
diff --git a/shalom/src/theme.rs b/shalom/src/theme.rs
index 06640be..12a6910 100644
--- a/shalom/src/theme.rs
+++ b/shalom/src/theme.rs
@@ -1,9 +1,10 @@
use ::image::{GenericImageView, Pixel, RgbaImage};
use ::image::{GenericImageView, Pixel, Rgba, RgbaImage};
use iced::{
    advanced::svg::Handle,
    widget::{image, svg},
};
use once_cell::sync::Lazy;
use stackblur_iter::imgref::Img;

pub mod colours {
    use iced::Color;
@@ -171,3 +172,33 @@ pub fn darken_image(mut img: RgbaImage, factor: f32) -> RgbaImage {

    img
}

#[allow(clippy::many_single_char_names)]
pub fn blur(img: &RgbaImage, radius: usize) -> RgbaImage {
    let width = img.width();
    let height = img.height();

    let mut raw = img
        .pixels()
        .map(|p| u32::from_be_bytes([p.0[3], p.0[0], p.0[1], p.0[2]]))
        .collect::<Vec<_>>();

    stackblur_iter::par_blur_srgb(
        &mut Img::new(
            &mut raw,
            width.try_into().unwrap(),
            height.try_into().unwrap(),
        ),
        radius,
    );

    let mut image = RgbaImage::new(width, height);
    for (i, &pixel) in raw.iter().enumerate() {
        let x = u32::try_from(i).unwrap_or(u32::MAX) % width;
        let y = u32::try_from(i).unwrap_or(u32::MAX) / width;
        let [a, r, g, b] = pixel.to_be_bytes();
        image.put_pixel(x, y, Rgba([r, g, b, a]));
    }

    image
}
diff --git a/shalom/src/widgets/colour_picker.rs b/shalom/src/widgets/colour_picker.rs
index 39e99d9..1e10b8e 100644
--- a/shalom/src/widgets/colour_picker.rs
+++ b/shalom/src/widgets/colour_picker.rs
@@ -15,20 +15,20 @@ use palette::IntoColor;

use crate::widgets::forced_rounded::forced_rounded;

pub struct ColourPicker<Event> {
pub struct ColourPicker<Event, F> {
    hue: f32,
    saturation: f32,
    brightness: f32,
    on_change: fn(f32, f32, f32) -> Event,
    on_change: F,
    on_mouse_up: Event,
}

impl<Event> ColourPicker<Event> {
impl<Event, F> ColourPicker<Event, F> {
    pub fn new(
        hue: f32,
        saturation: f32,
        brightness: f32,
        on_change: fn(f32, f32, f32) -> Event,
        on_change: F,
        on_mouse_up: Event,
    ) -> Self {
        Self {
@@ -41,7 +41,9 @@ impl<Event> ColourPicker<Event> {
    }
}

impl<Event: Clone> Component<Event, Renderer> for ColourPicker<Event> {
impl<Event: Clone, F: Fn(f32, f32, f32) -> Event> Component<Event, Renderer>
    for ColourPicker<Event, F>
{
    type State = ();
    type Event = Message;

@@ -88,11 +90,12 @@ impl<Event: Clone> Component<Event, Renderer> for ColourPicker<Event> {
    }
}

impl<'a, M> From<ColourPicker<M>> for Element<'a, M, Renderer>
impl<'a, M, F> From<ColourPicker<M, F>> for Element<'a, M, Renderer>
where
    M: 'a + Clone,
    F: Fn(f32, f32, f32) -> M + 'a,
{
    fn from(card: ColourPicker<M>) -> Self {
    fn from(card: ColourPicker<M, F>) -> Self {
        component(card)
    }
}