Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Text overlay #14

Merged
merged 1 commit into from
Sep 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,12 @@ publish = false


[dependencies]
ab_glyph = "0.2.28"
chrono = "0.4.38"
clap = { version = "4.5.4", features = ["derive"] }
confy = "0.6.1"
image = "0.25.2"
imageproc = "0.25.0"
reqwest = { version = "0.12.4", features = ["blocking", "json"] }
serde = "1.0.202"
serde_derive = "1.0.202"
Expand Down
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,10 @@ background.
* `image_dimension_width` The "width" dimension of the wallpaper
* `image_dimension_height` The "height" dimension of the wallpaper
* `target_filename` The location where is stored the wallpaper
* `text_overlay_position` (OPTIONAL) Add text overlay containing information about the picture. Value must be
surrounded with simple quote. Accepted values are: `BOTTOM_LEFT`, `BOTTOM_RIGHT`, `TOP_LEFT`, `TOP_RIGHT`
* `text_overlay_position_offset_x` (OPTIONAL) Applies an offset on the X-axis of the text overlay.
* `text_overlay_position_offset_y` (OPTIONAL) Applies an offset on the Y-axis of the text overlay.
* `exec_apply_wallpaper` (OPTIONAL) Command to execute for applying wallpaper, the
string accept following variables: `image_dimension_width`, `image_dimension_height`,
and `target_filename`
Expand Down
Binary file added res/font/Ubuntu-Regular.ttf
Binary file not shown.
27 changes: 19 additions & 8 deletions src/bingwallpaper/bingwallpaperchanger.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use chrono::{DateTime, Utc};
#[cfg(any(target_os = "linux", target_os = "freebsd", target_os = "netbsd", target_os = "openbsd"))]
use std::env;
#[cfg(target_os = "windows")]
Expand All @@ -11,9 +12,6 @@ use std::io::Write;
use std::path::Path;
use std::process::Command;
use std::time::SystemTime;

use chrono::{DateTime, Utc};

#[cfg(target_os = "windows")]
use winapi::ctypes::c_void;
#[cfg(target_os = "windows")]
Expand All @@ -23,7 +21,7 @@ use winvd::{get_desktop_count, get_desktops};
#[cfg(target_os = "windows")]
use winver::WindowsVersion;

use crate::bingwallpaper::{BingAPIClient, BingWallpaperConfiguration};
use crate::bingwallpaper::{BingAPIClient, BingWallpaperConfiguration, TextOverlay};

/// Retrieves from Bing API and applies the wallpaper of the day.
///
Expand All @@ -43,7 +41,7 @@ impl BingWallpaperChanger {
/// Creates a new instance.
///
/// Arguments
/// * `configuration` - The configuration to use
/// * `configuration` - The Bing Wallpaper configuration to use
///
/// # Examples
///
Expand Down Expand Up @@ -102,6 +100,9 @@ impl BingWallpaperChanger {
self.bing_api_client.download_image(&bing_image, &self.configuration.target_filename)?;
}

// Overlay
TextOverlay::apply_overlay(&self.configuration, bing_image.title, bing_image.copyright);

// Change current wallpaper (if requested)
if must_change_wallpaper {
return self.change_wallpaper();
Expand All @@ -118,7 +119,7 @@ impl BingWallpaperChanger {

/// Returns the date (UTC) as a String following the format "%Y%m%d" of the current wallpaper.
///
/// In case of current wallpaper does not exists, "00000000" will be return.
/// In case of current wallpaper does not exist, "00000000" will be return.
fn get_date_current_wallpaper(&self) -> String {
match Path::new(self.configuration.target_filename.as_str()).metadata() {
Err(_) => String::from("00000000"),
Expand All @@ -137,7 +138,12 @@ impl BingWallpaperChanger {
if self.configuration.exec_apply_wallpaper.is_some() {
self.exec_apply_wallpaper();
} else {
#[cfg(any(target_os = "linux", target_os = "freebsd", target_os = "netbsd", target_os = "openbsd"))] {
#[cfg(any(
target_os = "linux",
target_os = "freebsd",
target_os = "netbsd",
target_os = "openbsd"
))] {
self.change_wallpaper_linux();
}

Expand Down Expand Up @@ -186,7 +192,12 @@ impl BingWallpaperChanger {
}

/// Changes the wallpaper with the given picture on Linux.
#[cfg(any(target_os = "linux", target_os = "freebsd", target_os = "netbsd", target_os = "openbsd"))]
#[cfg(any(
target_os = "linux",
target_os = "freebsd",
target_os = "netbsd",
target_os = "openbsd"
))]
fn change_wallpaper_linux(&self) {
let session = env::var("DESKTOP_SESSION").unwrap();

Expand Down
8 changes: 7 additions & 1 deletion src/bingwallpaper/configuration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ pub struct BingWallpaperConfiguration {
pub(crate) image_dimension_width: u32,
pub(crate) image_dimension_height: u32,
pub(crate) target_filename: String,
pub(crate) text_overlay_position: Option<String>,
pub(crate) text_overlay_position_offset_x: Option<u32>,
pub(crate) text_overlay_position_offset_y: Option<u32>,
pub(crate) exec_apply_wallpaper: Option<String>,
pub(crate) proxy_url: Option<String>,
}
Expand All @@ -25,7 +28,10 @@ impl Default for BingWallpaperConfiguration {
loop_interval_second: 900.into(),
image_dimension_height: 1080,
image_dimension_width: 1920,
target_filename: "/tmp/bingwallpaper.png".into(),
target_filename: "/tmp/bingwallpaper.jpg".into(),
text_overlay_position: None,
text_overlay_position_offset_x: None,
text_overlay_position_offset_y: None,
exec_apply_wallpaper: None,
proxy_url: None,
}
Expand Down
2 changes: 2 additions & 0 deletions src/bingwallpaper/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@ pub use self::arguments::BingWallpaperArguments;
pub use self::bingapiclient::BingAPIClient;
pub use self::bingwallpaperchanger::BingWallpaperChanger;
pub use self::configuration::BingWallpaperConfiguration;
pub use self::textoverlay::TextOverlay;

mod arguments;
mod bingapiclient;
mod bingwallpaperchanger;
mod configuration;
mod textoverlay;
55 changes: 55 additions & 0 deletions src/bingwallpaper/textoverlay.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
use crate::bingwallpaper::BingWallpaperConfiguration;
use ab_glyph::{FontRef, PxScale};
use image::{ImageReader, Rgb, RgbImage};
use imageproc::drawing::draw_text;

/// Text overlay
pub struct TextOverlay {}

impl TextOverlay {
/// Applies text overlay.
///
/// # Arguments
/// * `configuration - The Bing Wallpaper configuration to use
/// * `line1` - First line of text
/// * `line2` - Second line of text
///
/// # Examples
///
/// ```
/// use textoverlay::TextOverlay;
///
/// TextOverlay::apply_overlay(configuration, "Title", "Description")
/// ```
pub fn apply_overlay(configuration: &BingWallpaperConfiguration, line1: String, line2: String) {
if configuration.text_overlay_position.is_none() {
return;
}

let font = FontRef::try_from_slice(include_bytes!("../../res/font/Ubuntu-Regular.ttf")).unwrap();
let font_scale = PxScale::from(30.0);
let (mut pos_x, mut pos_y) = match configuration.text_overlay_position.clone().unwrap().to_uppercase().as_str() {
"TOP_LEFT" => (60i32, 60i32),
"BOTTOM_LEFT" => (60i32,
configuration.image_dimension_height as i32 - (font_scale.x as i32 * 2) - 60 - 5),
"TOP_RIGHT" => (configuration.image_dimension_width as i32 - (12i32 * line2.len() as i32) - 55,
60i32),
"BOTTOM_RIGHT" => (configuration.image_dimension_width as i32 - (12i32 * line2.len() as i32) - 55,
configuration.image_dimension_height as i32 - (font_scale.x as i32 * 2) - 60 - 5),
_ => (60i32, 60i32),
};

if configuration.text_overlay_position_offset_x.is_some() {
pos_x += configuration.text_overlay_position_offset_x.unwrap() as i32
}
if configuration.text_overlay_position_offset_y.is_some() {
pos_y += configuration.text_overlay_position_offset_y.unwrap() as i32;
}

let image = ImageReader::open(&configuration.target_filename).unwrap().decode().unwrap();
let image = RgbImage::from(image);
let image = draw_text(&image, Rgb([255u8, 255u8, 255u8]), pos_x, pos_y, font_scale, &font, &line1);
let image = draw_text(&image, Rgb([255u8, 255u8, 255u8]), pos_x, pos_y + font_scale.x as i32 + 5, font_scale, &font, &line2);
image.save(&configuration.target_filename).unwrap();
}
}
Loading