Skip to content

Commit f335858

Browse files
committed
Merge branch 'feat/dynamic-downsampling' of goldy.github.com:cloudy-org/roseate into feat/dynamic-downsampling
2 parents f1f7e03 + 8508c59 commit f335858

22 files changed

+1272
-604
lines changed

Cargo.toml

+12-3
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,15 @@ re_format = "0.20.0"
2727
cap = "0.1.2"
2828
clap = {version = "4.5.21", features = ["derive"]}
2929
rand = "0.8.5"
30-
display-info = "0.5.2"
3130
egui-notify = "0.17.0"
3231
svg_metadata = "0.5.1"
3332
textwrap = "0.16.1"
3433
dirs = "5.0.1"
3534
rayon = "1.10.0"
3635
serde_derive = "1.0.215"
36+
serde_json = "1.0"
37+
fs2 = "0.4.3"
38+
3739
toml = {workspace = true}
3840
serde = {workspace = true, features = ["derive"]}
3941

@@ -46,5 +48,12 @@ egui = "0.29.1"
4648
toml = "0.8.19"
4749
serde = {version = "1.0.215", features = ["derive"]}
4850

49-
[profile.dev.package."*"]
50-
opt-level = 3
51+
# I've now disabled compiling release builds of dependices to speed up dev compile time.
52+
#
53+
# THIS MEANS IMAGE PROCESSING WILL BE MUCH MUCH
54+
# SLOWER ON DEV BUILDS COMPARED TO RELEASE BUILDS
55+
#
56+
# So with that said ALWAYS compile release unless you are developing Roseate.
57+
#
58+
#[profile.dev.package."*"]
59+
#opt-level = 3

README.md

+34-25
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,14 @@ As Roseate is in heavy development I won't offer packages and binaries yet so yo
2626
### Prerequisites:
2727
- [Rust](https://www.rust-lang.org/tools/install) and Cargo (Rust **`1.80.0`**+ is required!).
2828

29-
- Linux dependecies for [eframe](https://crates.io/crates/eframe):
29+
- Linux dependencies required by [eframe](https://crates.io/crates/eframe):
3030
- [libxcb](https://archlinux.org/packages/extra/x86_64/libxcb/)
3131
- [libxkbcommon](https://archlinux.org/packages/extra/x86_64/libxkbcommon/)
3232
- [openssl](https://archlinux.org/packages/core/x86_64/openssl/)
33+
- [libxrandr](https://archlinux.org/packages/extra/x86_64/libxrandr/) (required by [display-info](https://crates.io/crates/display-info) for smart downsampling)
34+
- [xdg-desktop-portal](https://github.com/flatpak/xdg-desktop-portal) (required by [rfd](https://docs.rs/rfd/latest/rfd/) for file dialog)
35+
36+
All of these deps are required on Linux. However they are *common* x11 / wayland dependencies so you most likely already have them installed.
3337

3438
1. Clone the repo.
3539
```sh
@@ -41,10 +45,37 @@ cd roseate
4145
git submodule update --init --recursive
4246
```
4347

48+
#### 🎀 Install into your system.
49+
Installing it to your system I advise you use GNU Make or else copy the commands from the "[Makefile](./Makefile)" (you will need to install Make if you haven't already).
50+
If you would like to run roseate for development continue ahead to the [next section](#%EF%B8%8F-for-development).
51+
52+
3. Build the release binary.
53+
```sh
54+
make
55+
```
56+
4. Install to your system.
57+
```sh
58+
sudo make install
59+
```
60+
5. Then the `roseate` binary will be available in your terminal.
61+
```sh
62+
roseate
63+
```
64+
65+
Open an image by passing its path.
66+
```sh
67+
roseate ./anime_girls.png
68+
```
69+
You might want to also set the binary at ``/usr/bin/roseate`` as your default image viewer so double clicking on images calls it.
70+
You can look up how to perform that for your desktop environment or operating system but on many popular Linux desktop environments, the [`roseate.desktop`](https://github.com/cloudy-org/roseate/blob/main/assets/roseate.desktop) file that is now installed on your system is your friend. 😉
71+
4472
#### ⚙️ For Development
45-
At this stage, for development, you would just run ``cargo run``. If you would like to install it to your system continue ahead to the [next section](#-install-into-your-system).
73+
> [!WARNING]
74+
> Building a development build WILL SIGNIFICANTLY KILL performance! Read more [here](https://github.com/cloudy-org/roseate/blob/6e7e638997110af0149f06ceadb87c3ec088cf84/Cargo.toml#L48-L53).
4675
47-
4. Run dev binary.
76+
Now for development, you would just run ``cargo run``.
77+
78+
3. Run dev binary.
4879
```sh
4980
cargo run
5081
```
@@ -68,28 +99,6 @@ RUST_LOG=DEBUG cargo run -- ./anime_girl.png
6899
... (truncated for the sanity of this readme)
69100
```
70101

71-
#### 🎀 Install into your system.
72-
Installing it to your system I advise you use GNU Make or else copy the commands from the "[Makefile](./Makefile)" (you will need to install Make if you haven't already).
73-
74-
4. Build the release binary.
75-
```sh
76-
make
77-
```
78-
5. Install to your system.
79-
```sh
80-
sudo make install
81-
```
82-
6. Then the `roseate` binary will be available in your terminal.
83-
```sh
84-
roseate
85-
```
86-
87-
Open an image by passing its path.
88-
```sh
89-
roseate ./anime_girls.png
90-
```
91-
You might want to also set the binary at ``/usr/bin/roseate`` as your default image viewer so double clicking on images calls it. You can look up how to perform that for your desktop environment or OS.
92-
93102
<br>
94103

95104
<div align="center">

assets/config.template.toml

+7-3
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,15 @@ ui_controls.toggle = "C"
3737
[misc]
3838
# All other configs that don't yet have a specific place or are experimental.
3939

40+
# override_monitor_size = {width = 1920, height = 1080}
41+
4042
[misc.experimental]
41-
# Settings to toggle experimental features that aren't yet ready to be
43+
# Settings to toggle experimental features that aren't yet ready yet to be
4244
# used by the wider user audience. This exists for the sole purpose of testing.
4345
#
4446
# Remember these are EXPERIMENTAL, bugs WILL be present.
4547

46-
use_fast_roseate_backend = false
47-
# Setting this to true will enable the experimental roseate image processing backend.
48+
# Setting this to true will enable the experimental lanczos roseate image processing backend
49+
# which is faster than the image-rs backend but may result in buggy/blocky images.
50+
# Disable this if the image looks weird.
51+
use_fast_roseate_backend = false

src/app.rs

+38-81
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,32 @@
11
use std::time::Duration;
22

33
use cirrus_theming::v1::{Colour, Theme};
4-
use eframe::egui::{self, Align, Color32, Context, CursorIcon, Frame, Layout, Margin, Rect, Shadow, Stroke, Style, TextStyle, Vec2};
4+
use eframe::egui::{self, Align, Color32, Context, CursorIcon, Frame, Layout, Margin, Rect, Stroke, Vec2};
55
use egui_notify::ToastLevel;
66

7-
use crate::{config::config::Config, files, image::image::Image, image_loader::ImageLoader, windows::info::InfoWindow, magnification_panel::MagnificationPanel, notifier::NotifierAPI, window_scaling::WindowScaling, windows::about::AboutWindow, zoom_pan::ZoomPan};
7+
use crate::{config::config::Config, files, image_handler::ImageHandler, magnification_panel::MagnificationPanel, monitor_size::MonitorSize, notifier::{self, NotifierAPI}, window_scaling::WindowScaling, windows::{about::AboutWindow, info::InfoWindow}, zoom_pan::ZoomPan};
88

99
pub struct Roseate<'a> {
1010
theme: Theme,
11-
image: Option<Image>,
1211
zoom_pan: ZoomPan,
1312
info_box: InfoWindow,
1413
about_box: AboutWindow<'a>,
1514
notifier: NotifierAPI,
1615
magnification_panel: MagnificationPanel,
1716
window_scaling: WindowScaling,
1817
last_window_rect: Rect,
19-
image_loader: ImageLoader,
18+
image_handler: ImageHandler,
19+
monitor_size: MonitorSize,
2020
config: Config,
2121
}
2222

2323
impl<'a> Roseate<'a> {
24-
pub fn new(image: Option<Image>, theme: Theme, mut notifier: NotifierAPI, config: Config) -> Self {
25-
let mut image_loader = ImageLoader::new();
26-
27-
if image.is_some() {
28-
image_loader.load_image(
29-
&mut image.clone().unwrap(),
24+
pub fn new(mut image_handler: ImageHandler, monitor_size: MonitorSize, mut notifier: NotifierAPI, theme: Theme, config: Config) -> Self {
25+
if image_handler.image.is_some() {
26+
image_handler.load_image(
3027
config.image.loading.initial.lazy_loading,
3128
&mut notifier,
29+
&monitor_size,
3230
config.misc.experimental.use_fast_roseate_backend
3331
);
3432
}
@@ -39,7 +37,6 @@ impl<'a> Roseate<'a> {
3937
let magnification_panel = MagnificationPanel::new(&config, &mut notifier);
4038

4139
Self {
42-
image,
4340
theme,
4441
notifier,
4542
zoom_pan,
@@ -48,52 +45,12 @@ impl<'a> Roseate<'a> {
4845
magnification_panel,
4946
window_scaling: WindowScaling::new(&config),
5047
last_window_rect: Rect::NOTHING,
51-
image_loader: image_loader,
48+
monitor_size,
49+
image_handler,
5250
config,
5351
}
5452
}
5553

56-
fn set_app_style(&self, ctx: &Context) {
57-
let mut custom_style = Style {
58-
override_text_style: Some(TextStyle::Monospace),
59-
..Default::default()
60-
};
61-
62-
// TODO: override more default
63-
// colours here with colours from our theme.
64-
65-
// Background colour styling.
66-
custom_style.visuals.panel_fill = Color32::from_hex(
67-
&self.theme.primary_colour.hex_code
68-
).unwrap();
69-
70-
// Window styling.
71-
custom_style.visuals.window_highlight_topmost = false;
72-
73-
custom_style.visuals.window_fill = Color32::from_hex(
74-
&self.theme.secondary_colour.hex_code
75-
).unwrap();
76-
custom_style.visuals.window_stroke = Stroke::new(
77-
1.0,
78-
Color32::from_hex(&self.theme.third_colour.hex_code).unwrap()
79-
);
80-
custom_style.visuals.window_shadow = Shadow::NONE;
81-
82-
custom_style.visuals.widgets.inactive.bg_fill =
83-
Color32::from_hex(
84-
&self.theme.primary_colour.hex_code
85-
).unwrap();
86-
87-
// Text styling.
88-
custom_style.visuals.override_text_color = Some(
89-
Color32::from_hex(
90-
&self.theme.text_colour.hex_code
91-
).unwrap()
92-
);
93-
94-
ctx.set_style(custom_style);
95-
}
96-
9754
fn draw_dotted_line(&self, ui: &egui::Painter, pos: &[egui::Pos2]) {
9855
ui.add(
9956
egui::Shape::dashed_line(
@@ -115,9 +72,7 @@ impl<'a> Roseate<'a> {
11572
impl eframe::App for Roseate<'_> {
11673

11774
fn update(&mut self, ctx: &Context, _frame: &mut eframe::Frame) {
118-
self.set_app_style(ctx);
119-
120-
self.info_box.init(&self.image);
75+
self.info_box.init(&self.image_handler.image);
12176
self.info_box.handle_input(ctx);
12277

12378
self.zoom_pan.handle_reset_input(ctx);
@@ -135,10 +90,11 @@ impl eframe::App for Roseate<'_> {
13590
}
13691

13792
self.notifier.update(ctx);
93+
self.monitor_size.update(ctx, &mut self.notifier);
13894
self.about_box.update(ctx); // we update this box here because we want
13995
// the about box is to be toggleable even without an image.
14096

141-
if self.image.is_none() {
97+
if self.image_handler.image.is_none() {
14298
// Collect dropped files.
14399
ctx.input(|i| {
144100
let dropped_files = &i.raw.dropped_files;
@@ -149,21 +105,19 @@ impl eframe::App for Roseate<'_> {
149105
.as_ref()
150106
.unwrap(); // gotta love rust ~ ananas
151107

152-
let mut image = match Image::from_path(path) {
153-
Ok(value) => value,
154-
Err(error) => {
155-
self.notifier.toasts.lock().unwrap().toast_and_log(
156-
error.into(), ToastLevel::Error
157-
);
158-
return;
159-
}
160-
};
108+
let result = self.image_handler.init_image(path, &self.monitor_size);
161109

162-
self.image = Some(image.clone());
163-
self.image_loader.load_image(
164-
&mut image,
110+
if let Err(error) = result {
111+
self.notifier.toasts.lock().unwrap().toast_and_log(
112+
error.into(), ToastLevel::Error
113+
);
114+
return;
115+
}
116+
117+
self.image_handler.load_image(
165118
true,
166119
&mut self.notifier,
120+
&self.monitor_size,
167121
self.config.misc.experimental.use_fast_roseate_backend
168122
);
169123
}
@@ -201,16 +155,14 @@ impl eframe::App for Roseate<'_> {
201155
rose_response.clone().on_hover_cursor(CursorIcon::PointingHand);
202156

203157
if rose_response.clicked() {
204-
let image_result = files::select_image();
205-
206-
match image_result {
207-
Ok(mut image) => {
208-
self.image = Some(image.clone());
158+
let result = self.image_handler.select_image(&self.monitor_size);
209159

210-
self.image_loader.load_image(
211-
&mut image,
160+
match result {
161+
Ok(_) => {
162+
self.image_handler.load_image(
212163
self.config.image.loading.gui.lazy_loading,
213164
&mut self.notifier,
165+
&self.monitor_size,
214166
self.config.misc.experimental.use_fast_roseate_backend
215167
);
216168
},
@@ -246,19 +198,25 @@ impl eframe::App for Roseate<'_> {
246198

247199
self.info_box.update(ctx);
248200
self.zoom_pan.update(ctx);
249-
self.image_loader.update();
201+
self.image_handler.update(&self.zoom_pan, &self.monitor_size);
250202
self.magnification_panel.update(ctx, &mut self.zoom_pan);
251203

252-
let image = self.image.clone().unwrap();
204+
let image = self.image_handler.image.clone().unwrap();
253205

254-
if self.image_loader.image_loaded {
206+
if self.image_handler.image_loaded {
255207
ui.centered_and_justified(|ui| {
256208
let scaled_image_size = self.window_scaling.relative_image_size(
257209
Vec2::new(image.image_size.width as f32, image.image_size.height as f32)
258210
);
259-
211+
212+
// TODO: umm I think we should move this to self.zoom_pan.update()
213+
// and then move that function in here as we need `scaled_image_size`.
260214
if self.zoom_pan.is_pan_out_of_bounds(scaled_image_size) {
261215
self.zoom_pan.schedule_pan_reset(Duration::from_millis(300));
216+
217+
// As resetting the pan will just snap us back to the center
218+
// of the image we might as well schedule a reset for image scale too.
219+
self.zoom_pan.schedule_scale_reset(Duration::from_millis(300));
262220
};
263221

264222
// NOTE: umm do we move this to window scaling... *probably* if we
@@ -330,5 +288,4 @@ impl eframe::App for Roseate<'_> {
330288
);
331289

332290
}
333-
334291
}

src/config/config.rs

+3
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,9 @@ impl Config {
3131

3232
let roseate_config_dir_path = local_config_dir.join("cloudy").join("roseate");
3333

34+
// TODO: switch to get_local_config_path function.
35+
// let roseate_config_path = files::get_local_config_path()?;
36+
3437
if !roseate_config_dir_path.exists() {
3538
debug!("Creating config directory for roseate...");
3639
if let Err(err) = fs::create_dir_all(&roseate_config_dir_path) {

src/config/models/misc.rs

+9
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ use serde::{Serialize, Deserialize};
22

33
#[derive(Serialize, Deserialize, Default)]
44
pub struct Misc {
5+
#[serde(default = "super::none_default")]
6+
pub override_monitor_size: Option<OverrideMonitorSize>,
57
pub experimental: Experimental,
68
}
79

@@ -18,4 +20,11 @@ impl Default for Experimental {
1820
use_fast_roseate_backend: false
1921
}
2022
}
23+
}
24+
25+
26+
#[derive(Serialize, Deserialize)]
27+
pub struct OverrideMonitorSize {
28+
pub width: u32,
29+
pub height: u32
2130
}

0 commit comments

Comments
 (0)