Compare commits

..
Author SHA1 Message Date
4a5ffdbd96
style: avoid toml curly braces
else it causes messy diffs and is generally less writable and readable
2026-07-29 16:01:19 -07:00
5 changed files with 201 additions and 238 deletions

301
Cargo.lock generated
View file

@ -55,21 +55,6 @@ dependencies = [
"equator", "equator",
] ]
[[package]]
name = "alloc-no-stdlib"
version = "2.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cc7bb162ec39d46ab1ca8c77bf72e890535becd1751bb45f64c597edb4c8c6b3"
[[package]]
name = "alloc-stdlib"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0e76a019e91224d279006ff972f1e984179a6e9feb050adba6ce8274aef23195"
dependencies = [
"alloc-no-stdlib",
]
[[package]] [[package]]
name = "android-activity" name = "android-activity"
version = "0.6.1" version = "0.6.1"
@ -460,13 +445,28 @@ dependencies = [
] ]
[[package]] [[package]]
name = "brotli-decompressor" name = "bon"
version = "5.0.3" version = "3.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3a32acac15fe1967bc3986b2a6347dffc965602354ea6f450ad07e8bfd253583" checksum = "a602c73c7b0148ec6d12af6fd5cc7a46e2eacc8878271a999abac56eed12f561"
dependencies = [ dependencies = [
"alloc-no-stdlib", "bon-macros",
"alloc-stdlib", "rustversion",
]
[[package]]
name = "bon-macros"
version = "3.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6dee98b0db6a962de883bf5d20362dee4d7ca0d12fe39a7c6c73c844e1cd7c1f"
dependencies = [
"darling",
"ident_case",
"prettyplease",
"proc-macro2",
"quote",
"rustversion",
"syn",
] ]
[[package]] [[package]]
@ -847,6 +847,40 @@ version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f27ae1dd37df86211c42e150270f82743308803d90a6f6e6651cd730d5e1732f" checksum = "f27ae1dd37df86211c42e150270f82743308803d90a6f6e6651cd730d5e1732f"
[[package]]
name = "darling"
version = "0.23.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "25ae13da2f202d56bd7f91c25fba009e7717a1e4a1cc98a76d844b65ae912e9d"
dependencies = [
"darling_core",
"darling_macro",
]
[[package]]
name = "darling_core"
version = "0.23.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9865a50f7c335f53564bb694ef660825eb8610e0a53d3e11bf1b0d3df31e03b0"
dependencies = [
"ident_case",
"proc-macro2",
"quote",
"strsim",
"syn",
]
[[package]]
name = "darling_macro"
version = "0.23.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3984ec7bd6cfa798e62b4a642426a5be0e68f9401cfc2a01e3fa9ea2fcdb8d"
dependencies = [
"darling_core",
"quote",
"syn",
]
[[package]] [[package]]
name = "dav1d" name = "dav1d"
version = "0.11.1" version = "0.11.1"
@ -1723,6 +1757,12 @@ dependencies = [
"winit", "winit",
] ]
[[package]]
name = "ident_case"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
[[package]] [[package]]
name = "image" name = "image"
version = "0.25.10" version = "0.25.10"
@ -1766,7 +1806,7 @@ dependencies = [
"dirs", "dirs",
"iced", "iced",
"image", "image",
"jxl-oxide", "jpegxl-rs",
"rfd", "rfd",
] ]
@ -1874,6 +1914,29 @@ dependencies = [
"libc", "libc",
] ]
[[package]]
name = "jpegxl-rs"
version = "0.14.0+libjxl-0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b7d16fe73fb6d2e16b986392b716409c6ae6fabd35769d66bea391b016cdbc9"
dependencies = [
"bon",
"byteorder",
"half",
"image",
"jpegxl-sys",
"thiserror 2.0.18",
]
[[package]]
name = "jpegxl-sys"
version = "0.12.1+libjxl-0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "00cb4f7ffb45ee4327e9ec6ca1a732f3abef470ee008f7d4be3afb414075cd7d"
dependencies = [
"pkg-config",
]
[[package]] [[package]]
name = "js-sys" name = "js-sys"
version = "0.3.103" version = "0.3.103"
@ -1885,186 +1948,6 @@ dependencies = [
"wasm-bindgen", "wasm-bindgen",
] ]
[[package]]
name = "jxl-bitstream"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b480e752277e29eb4054f69546887a9b84656fe78c08f54ba5850ced98a378fe"
dependencies = [
"tracing",
]
[[package]]
name = "jxl-coding"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cd972bcd125e776f1eb241ac50e39f956095a1c2770c64736c968f8946bd9a3c"
dependencies = [
"jxl-bitstream",
"tracing",
]
[[package]]
name = "jxl-color"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f316b1358c1711755b3ee8e8cb5c4a1dad12e796233088a7a513440782de80b2"
dependencies = [
"jxl-bitstream",
"jxl-coding",
"jxl-grid",
"jxl-image",
"jxl-oxide-common",
"jxl-threadpool",
"tracing",
]
[[package]]
name = "jxl-frame"
version = "0.13.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2d967c6fd669c7c01060b5022d8835fa82fd46b06ffc98b549f17600a097c2b3"
dependencies = [
"jxl-bitstream",
"jxl-coding",
"jxl-grid",
"jxl-image",
"jxl-modular",
"jxl-oxide-common",
"jxl-threadpool",
"jxl-vardct",
"tracing",
]
[[package]]
name = "jxl-grid"
version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "01671307879a033bfa52e6e8784b941aca770b3f3a7d33830b455b6844f793fb"
dependencies = [
"tracing",
]
[[package]]
name = "jxl-image"
version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c5f752d62577c702a94dbbce4045caf08cb58639e8a4d56464b40ecf33ffe565"
dependencies = [
"jxl-bitstream",
"jxl-grid",
"jxl-oxide-common",
"tracing",
]
[[package]]
name = "jxl-jbr"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e35d032bcec660647828527ff42c6f5776d2fd44b8357f9f6d9ac6dc07218e46"
dependencies = [
"brotli-decompressor",
"jxl-bitstream",
"jxl-frame",
"jxl-grid",
"jxl-image",
"jxl-modular",
"jxl-oxide-common",
"jxl-threadpool",
"jxl-vardct",
"tracing",
]
[[package]]
name = "jxl-modular"
version = "0.11.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2a2f045b24c738dd91d482be385512b512721ae08a671bd4b27bf1c47f215235"
dependencies = [
"jxl-bitstream",
"jxl-coding",
"jxl-grid",
"jxl-oxide-common",
"jxl-threadpool",
"tracing",
]
[[package]]
name = "jxl-oxide"
version = "0.12.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d36c662923f47586880211f3bc7c0d83fb3a9b410d278c7bde93450748abeef3"
dependencies = [
"brotli-decompressor",
"bytemuck",
"image",
"jxl-bitstream",
"jxl-color",
"jxl-frame",
"jxl-grid",
"jxl-image",
"jxl-jbr",
"jxl-oxide-common",
"jxl-render",
"jxl-threadpool",
"tracing",
]
[[package]]
name = "jxl-oxide-common"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b62394c5021b3a9e7e0dbb2d639d555d019090c9946c39f6d3b09d390db4157b"
dependencies = [
"jxl-bitstream",
]
[[package]]
name = "jxl-render"
version = "0.12.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d34386bfdb6a19b5a30cc9beb4d475d537422c31ae8c39bb69640fcce3fcaf19"
dependencies = [
"bytemuck",
"jxl-bitstream",
"jxl-coding",
"jxl-color",
"jxl-frame",
"jxl-grid",
"jxl-image",
"jxl-modular",
"jxl-oxide-common",
"jxl-threadpool",
"jxl-vardct",
"tracing",
]
[[package]]
name = "jxl-threadpool"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "25f15eb830aa77a7f21148d72e153562a26bfe570139bd4922eab1908dd499d3"
dependencies = [
"rayon",
"rayon-core",
"tracing",
]
[[package]]
name = "jxl-vardct"
version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ce72a18c6d3a47172ab6c479be2bdb56f22066b5d7092663f03b4490820b4511"
dependencies = [
"jxl-bitstream",
"jxl-coding",
"jxl-grid",
"jxl-modular",
"jxl-oxide-common",
"jxl-threadpool",
"tracing",
]
[[package]] [[package]]
name = "kamadak-exif" name = "kamadak-exif"
version = "0.6.1" version = "0.6.1"
@ -3070,6 +2953,16 @@ version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e8cf8e6a8aa66ce33f63993ffc4ea4271eb5b0530a9002db8455ea6050c77bfa" checksum = "e8cf8e6a8aa66ce33f63993ffc4ea4271eb5b0530a9002db8455ea6050c77bfa"
[[package]]
name = "prettyplease"
version = "0.2.37"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b"
dependencies = [
"proc-macro2",
"syn",
]
[[package]] [[package]]
name = "proc-macro-crate" name = "proc-macro-crate"
version = "3.5.0" version = "3.5.0"
@ -3746,6 +3639,12 @@ version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6637bab7722d379c8b41ba849228d680cc12d0a45ba1fa2b48f2a30577a06731" checksum = "6637bab7722d379c8b41ba849228d680cc12d0a45ba1fa2b48f2a30577a06731"
[[package]]
name = "strsim"
version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
[[package]] [[package]]
name = "svg_fmt" name = "svg_fmt"
version = "0.4.5" version = "0.4.5"

View file

@ -7,6 +7,7 @@ license = "AGPL-3.0-or-later"
[dependencies] [dependencies]
dirs = "6.0.0" dirs = "6.0.0"
rfd = "0.17.2" rfd = "0.17.2"
jpegxl-rs = "0.14.0"
[dependencies.iced] [dependencies.iced]
version = "0.14.0" version = "0.14.0"
@ -15,8 +16,3 @@ features = [ "image" ]
[dependencies.image] [dependencies.image]
version = "0.25.10" version = "0.25.10"
features = [ "avif-native" ] features = [ "avif-native" ]
[dependencies.jxl-oxide]
version = "0.12.6"
# I really wish the image crate was named better
features = [ "image" ]

View file

@ -39,6 +39,7 @@
pkg-config pkg-config
]; ];
buildInputs = with pkgs; [ buildInputs = with pkgs; [
libjxl
dav1d dav1d
]; ];

View file

@ -175,8 +175,6 @@ impl State {
} }
fn main() -> Result<(), iced::Error> { fn main() -> Result<(), iced::Error> {
jxl_oxide::integration::register_image_decoding_hook();
iced::application(State::new, State::update, State::view) iced::application(State::new, State::update, State::view)
.subscription(State::subscription) .subscription(State::subscription)
.title(State::title) .title(State::title)

View file

@ -1,11 +1,48 @@
use std::path::{Path, PathBuf}; use std::{
ffi::OsStr,
fs,
io::Write,
path::{Path, PathBuf},
};
use image::{DynamicImage, ImageDecoder, ImageReader, RgbaImage}; use image::{DynamicImage, ImageDecoder, ImageReader, RgbaImage};
use jpegxl_rs::image::ToDynamic;
use rfd::FileDialog; use rfd::FileDialog;
pub fn load_image(path: impl AsRef<Path>) -> Result<RgbaImage, String> { pub fn load_image(path: impl AsRef<Path>) -> Result<RgbaImage, String> {
let path = path.as_ref(); let path = path.as_ref();
let decoded_image = match path.extension().map(OsStr::to_string_lossy).as_deref() {
Some("jxl") => {
let data = match std::fs::read(path) {
Ok(d) => d,
Err(e) => {
return Err(format!(
"failed to read data from '{}': {e}",
path.display()
));
}
};
match jpegxl_rs::decoder_builder()
.build()
.unwrap()
.decode_to_image(&data)
{
Ok(Some(decoded_image)) => decoded_image,
Ok(None) => {
return Err(format!(
"failed to convert jxl '{}' to DynamicImage",
path.display()
));
}
Err(e) => {
return Err(format!("failed to decode jxl '{}': {e}", path.display()));
}
}
}
_ => {
let reader = match ImageReader::open(path) { let reader = match ImageReader::open(path) {
Ok(r) => r, Ok(r) => r,
Err(e) => { Err(e) => {
@ -45,6 +82,10 @@ pub fn load_image(path: impl AsRef<Path>) -> Result<RgbaImage, String> {
decoded_image.apply_orientation(oreintation); decoded_image.apply_orientation(oreintation);
decoded_image
}
};
Ok(decoded_image.into_rgba8()) Ok(decoded_image.into_rgba8())
} }
pub fn pick_image() -> Result<PathBuf, String> { pub fn pick_image() -> Result<PathBuf, String> {
@ -73,9 +114,37 @@ pub fn save_image(image: Option<&RgbaImage>) -> Result<(), String> {
return Err("no path to save provided".into()); return Err("no path to save provided".into());
}; };
let mut file = match fs::File::create(&path) {
Ok(f) => f,
Err(e) => return Err(format!("failed to create file '{}': {e}", path.display())),
};
match path.extension().map(OsStr::to_string_lossy).as_deref() {
Some("jxl") => {
let mut encoder = jpegxl_rs::encoder_builder()
.speed(jpegxl_rs::encode::EncoderSpeed::Glacier)
.lossless(true)
.build()
.unwrap();
let rgb_image = DynamicImage::from(image.to_owned()).into_rgb8();
let jxl =
match encoder.encode::<u8, u8>(&rgb_image, rgb_image.width(), rgb_image.height()) {
Ok(j) => j,
Err(e) => {
return Err(format!("failed to encode jxl '{}': {e}", path.display()));
}
};
if let Err(e) = file.write(&jxl.data) {
return Err(format!("failed to write jxl to '{}': {e}", path.display()));
};
}
_ => {
if let Err(e) = image.save(&path) { if let Err(e) = image.save(&path) {
return Err(format!("failed to save '{}': {e}", path.display())); return Err(format!("failed to save '{}': {e}", path.display()));
}; };
}
};
Ok(()) Ok(())
} }