snitch/lib.rs
1//! snitch: read, strip and credit image metadata, and check text for hidden characters.
2//!
3//! Three separate jobs that people usually conflate:
4//!
5//! ```text
6//! snitch read everything and say plainly what is there
7//! credit write credit in, and optionally stamp it into the pixels
8//! no-comment take metadata out
9//! ```
10//!
11//! STRIPPING IS SEGMENT SURGERY, NOT RE-ENCODING. Dropping JPEG APPn/COM markers and keeping only
12//! the required PNG chunks leaves the decoded pixels byte-identical, and `strip::pixels_identical`
13//! proves it per run rather than asserting it. Re-encoding to "clear" metadata throws away image
14//! quality for no reason, and this tool will not do it.
15//!
16//! STAMPING DOES re-encode, because it has to: it changes pixels. That is stated at the call site
17//! and in the CLI output, because a user deserves to know which operation costs them quality.
18//!
19//! HOUSE STYLE. No async, no web framework, no CLI framework, seven direct dependencies, and the
20//! two obvious crates for C2PA and MCP were measured and refused. See Cargo.toml for the numbers.
21
22pub mod c2pa;
23pub mod cli;
24pub mod exif;
25pub mod inspect;
26pub mod jpeg;
27pub mod mcp;
28pub mod png;
29pub mod sign;
30pub mod stamp;
31pub mod strip;
32pub mod survival;
33pub mod text;
34
35pub const VERSION: &str = env!("CARGO_PKG_VERSION");
36
37/// Licence presets, exactly as the Python shipped them.
38pub const LICENCES: [(&str, &str, Option<&str>); 8] = [
39 (
40 "cc-by",
41 "CC BY 4.0",
42 Some("https://creativecommons.org/licenses/by/4.0/"),
43 ),
44 (
45 "cc-by-sa",
46 "CC BY-SA 4.0",
47 Some("https://creativecommons.org/licenses/by-sa/4.0/"),
48 ),
49 (
50 "cc-by-nd",
51 "CC BY-ND 4.0",
52 Some("https://creativecommons.org/licenses/by-nd/4.0/"),
53 ),
54 (
55 "cc-by-nc",
56 "CC BY-NC 4.0",
57 Some("https://creativecommons.org/licenses/by-nc/4.0/"),
58 ),
59 (
60 "cc-by-nc-sa",
61 "CC BY-NC-SA 4.0",
62 Some("https://creativecommons.org/licenses/by-nc-sa/4.0/"),
63 ),
64 (
65 "cc-by-nc-nd",
66 "CC BY-NC-ND 4.0",
67 Some("https://creativecommons.org/licenses/by-nc-nd/4.0/"),
68 ),
69 (
70 "cc0",
71 "CC0 1.0",
72 Some("https://creativecommons.org/publicdomain/zero/1.0/"),
73 ),
74 ("arr", "All rights reserved", None),
75];
76
77pub fn licence(key: &str) -> Option<(&'static str, Option<&'static str>)> {
78 LICENCES
79 .iter()
80 .find(|(k, _, _)| *k == key)
81 .map(|(_, name, url)| (*name, *url))
82}
83
84pub fn licence_keys() -> String {
85 LICENCES
86 .iter()
87 .map(|(k, _, _)| *k)
88 .collect::<Vec<_>>()
89 .join(", ")
90}