前言:
此时各位老铁们对“window10聚焦变成图片了”都比较看重,朋友们都想要学习一些“window10聚焦变成图片了”的相关文章。那么小编同时在网络上网罗了一些对于“window10聚焦变成图片了””的相关文章,希望各位老铁们能喜欢,各位老铁们一起来学习一下吧!简介
Windows聚焦(Windows Spotlight)是Windows 10里新增的一个锁屏壁纸功能,它会自动下载并随机更换锁屏壁纸。Windows聚焦的照片精美震撼,但遗憾的是Windows聚焦只能在锁屏时使用,无法在桌面背景中使用。
本文使用Rust语言开发了一个Windows聚焦图片的保持工具,可自动保持Windows聚焦图片。
程序源代码可以访问下载。
Windows聚焦存储
Windows聚焦自动下载图片,下载的图片会临时存储在用户目录下:
Windows聚焦的存储目录为:C:\Users\XXX\AppData\Local\Packages\Microsoft.Windows.ContentDeliveryManager_cw5n1h2txyewy\LocalState\Assets
其中,XXX为用户名,该目录下字母与数字组成的无扩展名的文件即为图片文件。
程序设计思路
这里我希望能够开发一个程序,自动扫描Windows聚焦存储目录下的文件,发现有新的图片时拷贝存储到指定的图片目录中,图片的存储目录,可以在Windows背景图片中作为幻灯片放映的目录使用。
程序会被配置到Windows计划任务中,在开机时或定期执行,如果存储的图片较多的话,我们希望能够把历史图片归档到子目录中。
最终实现的工具命令如下:
PS> spotlight_save.exe -helpspotlight_save 1.0.0Steven Lee <leexgone@163.com>Save splotlight images in Win10.USAGE: spotlight_save.exe [FLAGS] [DIR]FLAGS: -a, --archive Archive images by year -h, --help Prints help information -V, --version Prints version information -v, --verbose Use verbose outputARGS: <DIR> Target image dir. Default dir is '${HOME}/Pictures/Spotlight/'代码开发
创建一个Rust工程,在Cargo.toml中引入我们需要的第三方包:
[dependencies]clap = "2.33"home = "0.5"image = "0.23"chrono = "0.4"
在main.rs文件中编写主逻辑代码:
use std::process;use spotlight_save::Config;fn main() { let config = Config::new().unwrap_or_else(|err| { eprintln!("Error when parsing arguments: {}", err); process::exit(1); }); if let Err(e) = spotlight_save::run(config) { eprintln!("Error when saving images: {}", e); process::exit(1); }}
在lib.rs中编写我们的主要逻辑代码:
use std::{error::Error, fmt::Display, fs, path::PathBuf};use chrono::{DateTime, Duration, Local};use clap::{App, Arg};use image::{GenericImageView, io::Reader};#[derive(Debug)]pub struct Config { target: PathBuf, verbose: bool, archive: bool,}impl Display for Config { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "[target = {}, verbose = {}, archive = {}]", self.target.display(), self.verbose, self.archive) }}impl Config { pub fn new() -> Result<Config, String> { let matches = App::new("spotlight_save") .version("1.0.0") .author("Steven Lee <leexgone@163.com>") .about("Save splotlight images in Win10.") .arg(Arg::with_name("DIR") .help("Target image dir. Default dir is '${HOME}/Pictures/Spotlight/'") .index(1)) .arg(Arg::with_name("verbose") .short("v") .long("verbose") .help("Use verbose output")) .arg(Arg::with_name("archive") .short("a") .long("archive") .help("Archive images by year")) .get_matches(); let verbose = matches.is_present("verbose"); let archive = matches.is_present("archive"); let target = if let Some(dir) = matches.value_of("DIR") { PathBuf::from(dir) } else { let home_dir = home::home_dir().unwrap(); let picture_dir = home_dir.join("Pictures"); if !picture_dir.is_dir() { let msg = format!("Can not find dir '{}'", picture_dir.display()); return Err(msg); } picture_dir.join("Spotlight") }; if !target.is_dir() { let msg = format!("target dir '{}' does not exist", target.display()); return Err(msg); } Ok(Config { target, verbose, archive, }) }}macro_rules! log { ($enabled:expr) => { {if $enabled { println!(); }} }; ($enabled:expr, $($arg:tt)*) => { {if $enabled { println!($($arg)*); }} };}pub fn run(config: Config) -> Result<(), Box<dyn Error>> { save_images(&config)?; if config.archive { archive_images(&config)?; } Ok(())}fn get_spotlight_dir() -> Result<PathBuf, Box<dyn Error>> { let home_dir = home::home_dir().unwrap(); let package_dir = home_dir.join("AppData\\Local\\Packages"); for entry in package_dir.read_dir()? { let entry = entry?; let path = entry.path(); if !path.is_dir() { continue; } let pathname = path.file_name().unwrap(); let pathname = pathname.to_str().unwrap(); if pathname.starts_with("Microsoft.Windows.ContentDeliveryManager_") { let image_dir = path.join("LocalState\\Assets"); return Ok(image_dir); } } let err = std::io::Error::new(std::io::ErrorKind::NotFound, String::from("Can not find Spotlight image dir")); Err(Box::new(err))}fn save_images(config: &Config) -> Result<(), Box<dyn Error>> { let spotlight_dir = get_spotlight_dir()?; log!(config.verbose, "Scan spotlight dir: {}", spotlight_dir.display()); let mut count = 0; for entry in spotlight_dir.read_dir()? { let entry = entry?; let path = entry.path(); if !path.is_file() { continue; } if save_image(config, &path) { count += 1; } } log!(config.verbose, "{} images saved!", count); Ok(())}fn save_image(config: &Config, filepath: &PathBuf) -> bool { log!(config.verbose, "Scan file: {}...", filepath.display()); let reader = if let Ok(reader) = Reader::open(filepath) { reader } else { return false; }; let reader = if let Ok(reader) = reader.with_guessed_format() { reader } else { return false; }; let format = if let Some(format) = reader.format() { format } else { return false; }; let image = if let Ok(image) = reader.decode() { image } else { return false; }; if image.width() < image.height() || image.width() < 800 || image.height() < 600 { return false; } let ext = format.extensions_str().first().unwrap(); let mut filename = String::from(filepath.file_name().unwrap().to_str().unwrap()); filename.push_str("."); filename.push_str(*ext); let target_file = config.target.join(filename); if target_file.exists() { return false; } log!(config.verbose, "Saving image: {} ...", target_file.display()); fs::copy(filepath, target_file).is_ok()}fn archive_images(config: &Config) -> Result<(), Box<dyn Error>> { log!(config.verbose, "Archive images in dir: {}", config.target.display()); let timeline = Local::today() - Duration::days(365); for entry in config.target.read_dir()? { let entry = entry?; let path = entry.path(); if !path.is_file() { continue; } if let Ok(metadata) = entry.metadata() { let filetime = if let Ok(modified) = metadata.modified() { modified } else if let Ok(created) = metadata.created() { created } else { continue; }; let filedate = DateTime::from(filetime).date(); if filedate < timeline { log!(config.verbose, "archive file: {} ...", path.display()); let year = filedate.format("%Y").to_string(); let dir = config.target.join(year); if !dir.exists() { fs::create_dir(&dir)?; } let bak_file = dir.join(path.file_name().unwrap()); fs::copy(&path, &bak_file)?; fs::remove_file(&path)?; } } } Ok(())}
使用cargo build --release编译生成工具。
配置计划任务并应用为壁纸
为了定制保持图片,我们在Windows计划任务中配置一个计划任务执行程序,这里我选择开机时执行。
在Windows背景壁纸中设置幻灯片放映,指定存储照片的目录即可。