diff --git a/Cargo.lock b/Cargo.lock index 154a922..dff73db 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -946,8 +946,8 @@ dependencies = [ [[package]] name = "glycin" -version = "4.0.0-alpha.1" -source = "git+https://gitlab.gnome.org/GNOME/glycin.git?rev=32083724ee730fb6b35b6382fb8af7b6ab1f2992#32083724ee730fb6b35b6382fb8af7b6ab1f2992" +version = "4.0.0-alpha.7" +source = "git+https://gitlab.gnome.org/GNOME/glycin.git?rev=882965515fc0de4f00f52318f2c35098a76855c9#882965515fc0de4f00f52318f2c35098a76855c9" dependencies = [ "glycin-builtin", "glycin-external", @@ -955,8 +955,8 @@ dependencies = [ [[package]] name = "glycin-builtin" -version = "4.0.0-alpha.1" -source = "git+https://gitlab.gnome.org/GNOME/glycin.git?rev=32083724ee730fb6b35b6382fb8af7b6ab1f2992#32083724ee730fb6b35b6382fb8af7b6ab1f2992" +version = "4.0.0-alpha.7" +source = "git+https://gitlab.gnome.org/GNOME/glycin.git?rev=882965515fc0de4f00f52318f2c35098a76855c9#882965515fc0de4f00f52318f2c35098a76855c9" dependencies = [ "glycin-core", ] @@ -964,7 +964,7 @@ dependencies = [ [[package]] name = "glycin-common" version = "2.0.0-alpha.1" -source = "git+https://gitlab.gnome.org/GNOME/glycin.git?rev=32083724ee730fb6b35b6382fb8af7b6ab1f2992#32083724ee730fb6b35b6382fb8af7b6ab1f2992" +source = "git+https://gitlab.gnome.org/GNOME/glycin.git?rev=882965515fc0de4f00f52318f2c35098a76855c9#882965515fc0de4f00f52318f2c35098a76855c9" dependencies = [ "bitflags 2.13.0", "gufo-common", @@ -981,8 +981,8 @@ dependencies = [ [[package]] name = "glycin-core" -version = "4.0.0-alpha.1" -source = "git+https://gitlab.gnome.org/GNOME/glycin.git?rev=32083724ee730fb6b35b6382fb8af7b6ab1f2992#32083724ee730fb6b35b6382fb8af7b6ab1f2992" +version = "4.0.0-alpha.7" +source = "git+https://gitlab.gnome.org/GNOME/glycin.git?rev=882965515fc0de4f00f52318f2c35098a76855c9#882965515fc0de4f00f52318f2c35098a76855c9" dependencies = [ "async-fs", "async-global-executor", @@ -1019,16 +1019,16 @@ dependencies = [ [[package]] name = "glycin-external" -version = "4.0.0-alpha.1" -source = "git+https://gitlab.gnome.org/GNOME/glycin.git?rev=32083724ee730fb6b35b6382fb8af7b6ab1f2992#32083724ee730fb6b35b6382fb8af7b6ab1f2992" +version = "4.0.0-alpha.7" +source = "git+https://gitlab.gnome.org/GNOME/glycin.git?rev=882965515fc0de4f00f52318f2c35098a76855c9#882965515fc0de4f00f52318f2c35098a76855c9" dependencies = [ "glycin-core", ] [[package]] name = "glycin-image-rs" -version = "2.2.0-alpha.6" -source = "git+https://gitlab.gnome.org/GNOME/glycin.git?rev=32083724ee730fb6b35b6382fb8af7b6ab1f2992#32083724ee730fb6b35b6382fb8af7b6ab1f2992" +version = "2.2.0-alpha.7" +source = "git+https://gitlab.gnome.org/GNOME/glycin.git?rev=882965515fc0de4f00f52318f2c35098a76855c9#882965515fc0de4f00f52318f2c35098a76855c9" dependencies = [ "bytemuck", "exr", @@ -1050,7 +1050,7 @@ dependencies = [ [[package]] name = "glycin-utils" version = "5.0.0-alpha.1" -source = "git+https://gitlab.gnome.org/GNOME/glycin.git?rev=32083724ee730fb6b35b6382fb8af7b6ab1f2992#32083724ee730fb6b35b6382fb8af7b6ab1f2992" +source = "git+https://gitlab.gnome.org/GNOME/glycin.git?rev=882965515fc0de4f00f52318f2c35098a76855c9#882965515fc0de4f00f52318f2c35098a76855c9" dependencies = [ "async-lock", "bitflags 2.13.0", @@ -1196,7 +1196,7 @@ dependencies = [ [[package]] name = "gufo" version = "0.5.0-alpha.4" -source = "git+https://github.com/gufo-rs/gufo.git#2079c478a108141d4507e93d2d74360b353f5d83" +source = "git+https://github.com/gufo-rs/gufo.git?rev=25ae7f4d68532314fe8b43b0f27360b952d5a0b6#25ae7f4d68532314fe8b43b0f27360b952d5a0b6" dependencies = [ "chrono", "gufo-common", @@ -1213,7 +1213,7 @@ dependencies = [ [[package]] name = "gufo-common" version = "2.0.0-alpha.2" -source = "git+https://github.com/gufo-rs/gufo.git#2079c478a108141d4507e93d2d74360b353f5d83" +source = "git+https://github.com/gufo-rs/gufo.git?rev=25ae7f4d68532314fe8b43b0f27360b952d5a0b6#25ae7f4d68532314fe8b43b0f27360b952d5a0b6" dependencies = [ "chrono", "paste", @@ -1239,7 +1239,7 @@ dependencies = [ [[package]] name = "gufo-exif" version = "0.5.0-alpha.4" -source = "git+https://github.com/gufo-rs/gufo.git#2079c478a108141d4507e93d2d74360b353f5d83" +source = "git+https://github.com/gufo-rs/gufo.git?rev=25ae7f4d68532314fe8b43b0f27360b952d5a0b6#25ae7f4d68532314fe8b43b0f27360b952d5a0b6" dependencies = [ "chrono", "gufo-common", @@ -1267,7 +1267,7 @@ dependencies = [ [[package]] name = "gufo-jpeg" version = "0.5.0-alpha.4" -source = "git+https://github.com/gufo-rs/gufo.git#2079c478a108141d4507e93d2d74360b353f5d83" +source = "git+https://github.com/gufo-rs/gufo.git?rev=25ae7f4d68532314fe8b43b0f27360b952d5a0b6#25ae7f4d68532314fe8b43b0f27360b952d5a0b6" dependencies = [ "gufo-common", "indexmap", @@ -1279,7 +1279,7 @@ dependencies = [ [[package]] name = "gufo-png" version = "0.5.0-alpha.4" -source = "git+https://github.com/gufo-rs/gufo.git#2079c478a108141d4507e93d2d74360b353f5d83" +source = "git+https://github.com/gufo-rs/gufo.git?rev=25ae7f4d68532314fe8b43b0f27360b952d5a0b6#25ae7f4d68532314fe8b43b0f27360b952d5a0b6" dependencies = [ "crc32fast", "encoding_rs", @@ -1292,7 +1292,7 @@ dependencies = [ [[package]] name = "gufo-tiff" version = "0.5.0-alpha.4" -source = "git+https://github.com/gufo-rs/gufo.git#2079c478a108141d4507e93d2d74360b353f5d83" +source = "git+https://github.com/gufo-rs/gufo.git?rev=25ae7f4d68532314fe8b43b0f27360b952d5a0b6#25ae7f4d68532314fe8b43b0f27360b952d5a0b6" dependencies = [ "gufo-common", "thiserror", @@ -1301,7 +1301,7 @@ dependencies = [ [[package]] name = "gufo-webp" version = "0.5.0-alpha.4" -source = "git+https://github.com/gufo-rs/gufo.git#2079c478a108141d4507e93d2d74360b353f5d83" +source = "git+https://github.com/gufo-rs/gufo.git?rev=25ae7f4d68532314fe8b43b0f27360b952d5a0b6#25ae7f4d68532314fe8b43b0f27360b952d5a0b6" dependencies = [ "gufo-common", "thiserror", @@ -1310,7 +1310,7 @@ dependencies = [ [[package]] name = "gufo-xmp" version = "0.5.0-alpha.4" -source = "git+https://github.com/gufo-rs/gufo.git#2079c478a108141d4507e93d2d74360b353f5d83" +source = "git+https://github.com/gufo-rs/gufo.git?rev=25ae7f4d68532314fe8b43b0f27360b952d5a0b6#25ae7f4d68532314fe8b43b0f27360b952d5a0b6" dependencies = [ "chrono", "gufo-common", @@ -1653,6 +1653,7 @@ dependencies = [ "libadwaita", "libc", "libgweather", + "moxcms", "strum", "thiserror", "tracing", diff --git a/Cargo.toml b/Cargo.toml index 9855d5b..731a5e5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,9 +6,9 @@ rust-version = "1.93" license = "GPL-3.0-or-later" [patch.crates-io] -glycin = { git = "https://gitlab.gnome.org/GNOME/glycin.git", rev = "32083724ee730fb6b35b6382fb8af7b6ab1f2992" } -gufo = { git = "https://github.com/gufo-rs/gufo.git" } -gufo-common = { git = "https://github.com/gufo-rs/gufo.git" } +glycin = { git = "https://gitlab.gnome.org/GNOME/glycin.git", rev = "882965515fc0de4f00f52318f2c35098a76855c9" } +gufo = { git = "https://github.com/gufo-rs/gufo.git", rev = "25ae7f4d68532314fe8b43b0f27360b952d5a0b6" } +gufo-common = { git = "https://github.com/gufo-rs/gufo.git", rev = "25ae7f4d68532314fe8b43b0f27360b952d5a0b6" } [profile.release] lto = true @@ -17,6 +17,9 @@ codegen-units = 1 [features] x11 = ["ashpd/gtk4_x11"] +[lints.clippy] +dbg_macro = "warn" + [dependencies] adw = { package = "libadwaita", version = "0.9.0", features = ["v1_8"] } anyhow = { version = "1.0.66" } @@ -43,6 +46,7 @@ gvdb-macros = "0.1.6" indexmap = "2.0.0" libc = "0.2.158" libgweather = "4.8.0" +moxcms = "0.8.1" strum = { version = "0.28.0", features = ["derive"] } thiserror = "2.0.3" tracing = "0.1.44" diff --git a/news.d/51.beta/added-color-profile-info b/news.d/51.beta/added-color-profile-info new file mode 100644 index 0000000..3fdcbcf --- /dev/null +++ b/news.d/51.beta/added-color-profile-info @@ -0,0 +1 @@ +Show ICC profile description or generated CICP description if applicable. diff --git a/src/metadata.rs b/src/metadata.rs index 10ef9d1..755ec5c 100644 --- a/src/metadata.rs +++ b/src/metadata.rs @@ -28,6 +28,7 @@ use chrono::prelude::*; pub use file::FileInfo; use glib::TimeZone; use glycin::{Frame, FrameDetails, ImageDetails, MemoryFormat}; +use gufo::common::cicp; use gufo::common::datetime::DateTime; use gufo::common::orientation::Orientation; use gufo::common::physical_dimension; @@ -44,6 +45,8 @@ pub struct Metadata { image_info: Option, frame_info: Option, memory_format: Option, + icc_profile: Option, + cicp: Option, } impl Metadata { @@ -87,6 +90,17 @@ impl Metadata { pub fn set_frame_metadata(&mut self, frame: &Frame) { self.frame_info = Some(frame.details().clone()); self.memory_format = Some(frame.memory_format()); + if let Some(iccp) = frame.details().color_icc_profile() { + match moxcms::ColorProfile::new_from_slice(iccp) { + Err(err) => { + tracing::warn!("Couldn't parse color profile: {err}"); + } + Ok(profile) => { + self.icc_profile = Some(profile); + } + } + } + self.cicp = frame.details().color_cicp(); } pub fn set_file_info(&mut self, file_info: FileInfo) { @@ -116,6 +130,12 @@ impl Metadata { if self.memory_format.is_none() { self.memory_format = other.memory_format; } + if self.icc_profile.is_none() { + self.icc_profile = other.icc_profile; + } + if self.cicp.is_none() { + self.cicp = other.cicp; + } } pub fn mime_type(&self) -> Option { @@ -435,4 +455,86 @@ impl Metadata { pub fn physical_size(&self) -> Option { self.frame_info.as_ref().and_then(|x| x.physical_size()) } + + pub fn icc_profile_description(&self) -> Option { + if self.prefer_cicp() && self.cicp.is_some() { + return None; + } + + if let Some(icc_profile) = &self.icc_profile { + icc_profile.description.as_ref().and_then(Self::icc_string) + } else { + None + } + } + + fn icc_string(text: &moxcms::ProfileText) -> Option { + let s = match text { + moxcms::ProfileText::Description(desc) => Some(desc.unicode_string.clone()), + moxcms::ProfileText::Localizable(local) => local.first().map(|x| x.value.clone()), + moxcms::ProfileText::PlainString(s) => Some(s.to_owned()), + }; + + if let Some(s) = s { + let s = s.trim().replace('\0', ""); + if s.is_empty() { None } else { Some(s) } + } else { + None + } + } + + pub fn cicp_description(&self) -> Option { + if !self.prefer_cicp() && self.icc_profile.is_some() { + return None; + } + + if let Some(cicp) = self.cicp { + let primaries = match cicp.color_primaries { + cicp::ColorPrimaries::DciP3 => gettext("DCI P3"), + cicp::ColorPrimaries::DisplayP3 => gettext("Display P3"), + cicp::ColorPrimaries::Rec2020 => gettext("Rec.2020"), + cicp::ColorPrimaries::Srgb => gettext("sRGB"), + cicp::ColorPrimaries::Unspecified => gettext("Unspecified"), + cicp::ColorPrimaries::Unknown(n) => gettext_f("Unknown ({})", [n.to_string()]), + _ => String::new(), + }; + + let coefficients = match cicp.matrix_coefficients { + cicp::MatrixCoefficients::Identity => None, + cicp::MatrixCoefficients::ICtCp => Some(gettext("ICtCp")), + cicp::MatrixCoefficients::Unspecified => Some(gettext("Unspecified")), + cicp::MatrixCoefficients::Unknown(n) => { + Some(gettext_f("Unknown ({})", [n.to_string()])) + } + _ => None, + }; + + let transfer = match cicp.transfer_characteristics { + cicp::TransferCharacteristics::Dci => gettext("DCI"), + cicp::TransferCharacteristics::Pq => gettext("PQ"), + cicp::TransferCharacteristics::Gamma24 => gettext("Gamma 2.4"), + cicp::TransferCharacteristics::Unknown(n) => { + gettext_f("Unknown ({})", [n.to_string()]) + } + _ => String::new(), + }; + + if let Some(coefficients) = coefficients { + Some(format!("{primaries}, {transfer}, {coefficients}")) + } else { + Some(format!("{primaries}, {transfer}")) + } + } else { + None + } + } + + pub fn prefer_cicp(&self) -> bool { + !matches!( + self.frame_info + .as_ref() + .map(|x| x.color_profile_preference()), + Some(glycin::ColorProfilePreference::IccProfile) + ) + } } diff --git a/src/util.rs b/src/util.rs index 0ebf2c7..159c9a8 100644 --- a/src/util.rs +++ b/src/util.rs @@ -277,7 +277,7 @@ pub fn locale_uses_inch() -> bool { .and_then(|x| x.get(0..2)) && (locale == b"US" || locale == b"LR") { - dbg!(true) + true } else { false } diff --git a/src/widgets/properties_view.rs b/src/widgets/properties_view.rs index 7ca7e39..07e87f9 100644 --- a/src/widgets/properties_view.rs +++ b/src/widgets/properties_view.rs @@ -97,6 +97,10 @@ mod imp { lens: TemplateChild, #[template_child] software: TemplateChild, + #[template_child] + icc_profile: TemplateChild, + #[template_child] + cicp: TemplateChild, } #[glib::object_subclass] @@ -253,6 +257,8 @@ mod imp { Self::update_row(&self.maker_model, metadata.maker_model()), Self::update_row(&self.lens, metadata.lens()), Self::update_row(&self.software, metadata.software()), + Self::update_row(&self.icc_profile, metadata.icc_profile_description()), + Self::update_row(&self.cicp, metadata.cicp_description()), ] .iter() .any(|x| *x); diff --git a/src/widgets/properties_view.ui b/src/widgets/properties_view.ui index 30a8fd1..1ce3f55 100644 --- a/src/widgets/properties_view.ui +++ b/src/widgets/properties_view.ui @@ -274,6 +274,26 @@ + + + ICC Profile + True + False + + + + + + CICP + True + False + + +