From f095160817596d7fe9f64a6f89c32198e232381f Mon Sep 17 00:00:00 2001 From: Sijmen Date: Tue, 2 May 2023 15:47:41 +0200 Subject: [PATCH] Scale images before sending to the browser --- Cargo.lock | 163 ++++++++++++++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 1 + src/main.rs | 25 ++++++-- 3 files changed, 183 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ff9f506..0bdf870 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,12 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + [[package]] name = "aead" version = "0.3.2" @@ -436,11 +442,26 @@ version = "3.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b1ce199063694f33ffb7dd4e0ee620741495c32833cde5aa08f02a0bf96f0c8" +[[package]] +name = "bytemuck" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17febce684fd15d89027105661fec94afb475cb995fbc59d2865198446ba2eea" + +[[package]] +name = "byteorder" +version = "1.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" + [[package]] name = "cc" version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" +dependencies = [ + "jobserver", +] [[package]] name = "cfg-if" @@ -489,6 +510,12 @@ dependencies = [ "unicode-width", ] +[[package]] +name = "color_quant" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" + [[package]] name = "concurrent-queue" version = "2.2.0" @@ -548,6 +575,15 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dcb25d077389e53838a8158c8e99174c5a9d902dee4904320db714f3c653ffba" +[[package]] +name = "crc32fast" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" +dependencies = [ + "cfg-if 1.0.0", +] + [[package]] name = "crossbeam-utils" version = "0.8.15" @@ -663,6 +699,7 @@ dependencies = [ "askama", "askama_tide", "async-std", + "image", "infer 0.13.0", "mpdrs", "percent-encoding", @@ -719,6 +756,15 @@ dependencies = [ "instant", ] +[[package]] +name = "fdeflate" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d329bdeac514ee06249dabc27877490f17f5d371ec693360768b838e19f3ae10" +dependencies = [ + "simd-adler32", +] + [[package]] name = "femme" version = "2.2.1" @@ -735,6 +781,16 @@ dependencies = [ "web-sys", ] +[[package]] +name = "flate2" +version = "1.0.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b9429470923de8e8cbd4d2dc513535400b4b3fef0319fb5c4e1f520a7bef743" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + [[package]] name = "form_urlencoded" version = "1.1.0" @@ -984,6 +1040,23 @@ dependencies = [ "unicode-normalization", ] +[[package]] +name = "image" +version = "0.24.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "527909aa81e20ac3a44803521443a765550f09b5130c2c2fa1ea59c2f8f50a3a" +dependencies = [ + "bytemuck", + "byteorder", + "color_quant", + "jpeg-decoder", + "num-rational", + "num-traits", + "png", + "tiff", + "webp", +] + [[package]] name = "infer" version = "0.2.3" @@ -1022,6 +1095,21 @@ version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" +[[package]] +name = "jobserver" +version = "0.1.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "936cfd212a0155903bcbc060e316fb6cc7cbf2e1907329391ebadc1fe0ce77c2" +dependencies = [ + "libc", +] + +[[package]] +name = "jpeg-decoder" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc0000e42512c92e31c2252315bda326620a4e034105e900c98ec492fa077b3e" + [[package]] name = "js-sys" version = "0.3.61" @@ -1058,6 +1146,15 @@ version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "348108ab3fba42ec82ff6e9564fc4ca0247bdccdc68dd8af9764bbc79c3c8ffb" +[[package]] +name = "libwebp-sys" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439fd1885aa28937e7edcd68d2e793cb4a22f8733460d2519fbafd2b215672bf" +dependencies = [ + "cc", +] + [[package]] name = "link-cplusplus" version = "1.0.8" @@ -1112,6 +1209,16 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" +[[package]] +name = "miniz_oxide" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" +dependencies = [ + "adler", + "simd-adler32", +] + [[package]] name = "mpdrs" version = "0.1.0" @@ -1141,6 +1248,17 @@ dependencies = [ "num-traits", ] +[[package]] +name = "num-rational" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + [[package]] name = "num-traits" version = "0.2.15" @@ -1212,6 +1330,19 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "png" +version = "0.17.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aaeebc51f9e7d2c150d3f3bfeb667f2aa985db5ef1e3d212847bdedb488beeaa" +dependencies = [ + "bitflags", + "crc32fast", + "fdeflate", + "flate2", + "miniz_oxide", +] + [[package]] name = "polling" version = "2.8.0" @@ -1526,6 +1657,12 @@ dependencies = [ "libc", ] +[[package]] +name = "simd-adler32" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "238abfbb77c1915110ad968465608b68e869e0772622c9656714e73e5a1a522f" + [[package]] name = "simple-mutex" version = "1.1.5" @@ -1723,6 +1860,17 @@ dependencies = [ "tracing-futures", ] +[[package]] +name = "tiff" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7449334f9ff2baf290d55d73983a7d6fa15e01198faef72af07e2a8db851e471" +dependencies = [ + "flate2", + "jpeg-decoder", + "weezl", +] + [[package]] name = "time" version = "0.1.45" @@ -2026,6 +2174,21 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "webp" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf022f821f166079a407d000ab57e84de020e66ffbbf4edde999bc7d6e371cae" +dependencies = [ + "libwebp-sys", +] + +[[package]] +name = "weezl" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9193164d4de03a926d909d3bc7c30543cecb35400c02114792c2cae20d5e2dbb" + [[package]] name = "winapi" version = "0.3.9" diff --git a/Cargo.toml b/Cargo.toml index ad4fca7..bfe2a34 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,6 +10,7 @@ anyhow = "1.0.70" askama = { version = "0.12.0", default-features = false } askama_tide = "0.15.0" async-std = { version = "1.12.0", features = ["attributes"] } +image = { version = "0.24.6", default-features = false, features = ["bmp", "jpeg", "png", "webp", "webp-encoder", "tiff"] } infer = { version = "0.13.0", default-features = false } mpdrs = "0.1.0" percent-encoding = "2.2.0" diff --git a/src/main.rs b/src/main.rs index 566c79a..03e8bb3 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,7 @@ use std::path::Path; use askama::Template; +use image::{imageops::FilterType, ImageFormat}; use percent_encoding::percent_decode_str; use serde::Deserialize; @@ -142,17 +143,29 @@ async fn post_queue_move(mut req: tide::Request<()>) -> tide::Result { Ok("".into()) } +#[derive(Deserialize, Default)] +#[serde(default)] +struct ArtQuery { + path: String, + resolution: Option<(u32, u32)>, +} + async fn get_art(req: tide::Request<()>) -> tide::Result { - let query: IndexQuery = req.query()?; + let query: ArtQuery = req.query()?; let path = percent_decode_str(&query.path).decode_utf8_lossy(); + println!("reading"); let resp = if let Ok(art) = mpd::connect()?.albumart(&path) { - let mime = infer::get(&art) - .map(|k| k.mime_type()) - .unwrap_or("application/octet-stream"); + let image = image::load_from_memory(&art)?; + let image = image.resize(512, 512, FilterType::Nearest); + + let mut writer = std::io::BufWriter::new(std::io::Cursor::new(Vec::new())); + image.write_to(&mut writer, ImageFormat::WebP)?; + + let inner = writer.into_inner()?.into_inner(); tide::Response::builder(tide::StatusCode::Ok) - .body(art) - .content_type(mime) + .content_type("image/webp") + .body(inner) .header("cache-control", "max-age=3600") } else { tide::Response::builder(tide::StatusCode::NotFound)