1use stet_graphics::icc::{BpcMode, IccCache, IccCacheOptions};
2
3fn dump_profile_shape(bytes: &[u8]) {
4 use moxcms::{ColorProfile, LutWarehouse};
5 let profile = match ColorProfile::new_from_slice(bytes) {
6 Ok(p) => p,
7 Err(e) => {
8 eprintln!("parse error: {e:?}");
9 return;
10 }
11 };
12 eprintln!(
13 "profile: cs={:?} pcs={:?} version={:?}",
14 profile.color_space,
15 profile.pcs,
16 profile.version()
17 );
18 let names = [
19 (
20 "a_to_b_perceptual (A2B0)",
21 profile.lut_a_to_b_perceptual.as_ref(),
22 ),
23 (
24 "a_to_b_colorimetric (A2B1)",
25 profile.lut_a_to_b_colorimetric.as_ref(),
26 ),
27 (
28 "a_to_b_saturation (A2B2)",
29 profile.lut_a_to_b_saturation.as_ref(),
30 ),
31 (
32 "b_to_a_perceptual (B2A0)",
33 profile.lut_b_to_a_perceptual.as_ref(),
34 ),
35 ];
36 for (name, slot) in names {
37 match slot {
38 None => eprintln!(" {name}: missing"),
39 Some(LutWarehouse::Lut(lut)) => {
40 eprintln!(
41 " {name}: Lut(in={} out={} grid={} type={:?})",
42 lut.num_input_channels,
43 lut.num_output_channels,
44 lut.num_clut_grid_points,
45 lut.lut_type
46 );
47 }
48 Some(LutWarehouse::Multidimensional(m)) => {
49 eprintln!(
50 " {name}: mAB(in={} out={} grids={:?})",
51 m.num_input_channels, m.num_output_channels, m.grid_points
52 );
53 }
54 }
55 }
56}
57
58fn main() {
59 let path = std::env::args()
60 .nth(1)
61 .expect("usage: icc_probe <profile.icc>");
62 let bytes = std::fs::read(&path).expect("read profile");
63 dump_profile_shape(&bytes);
64 let cases: &[(f64, f64, f64, f64)] = &[
65 (0.15, 1.0, 1.0, 0.0),
66 (0.0, 0.6, 1.0, 0.0),
67 (0.0, 0.5, 0.9, 0.0),
68 (0.0, 0.7, 1.0, 0.0),
69 (0.15, 0.7, 1.0, 0.0),
70 (0.0, 1.0, 1.0, 0.0),
71 (0.0, 0.0, 0.0, 1.0),
72 (0.0, 0.0, 0.0, 0.0),
73 (0.15, 0.05, 0.30, 0.0),
75 (0.25, 0.10, 0.40, 0.0),
76 (0.40, 0.15, 0.50, 0.0),
77 (0.40, 0.0, 1.0, 0.0),
78 (0.60, 0.0, 0.80, 0.0),
79 (0.20, 0.20, 0.20, 0.0),
80 (1.0, 0.0, 0.0, 0.0),
82 (0.0, 1.0, 0.0, 0.0),
83 (0.0, 0.0, 1.0, 0.0),
84 (1.0, 1.0, 0.0, 0.0),
85 ];
86 for mode in [BpcMode::Off, BpcMode::On] {
87 println!("\n== BPC {:?} ==", mode);
88 let opts = IccCacheOptions {
89 bpc_mode: mode,
90 source_cmyk_profile: Some(bytes.clone()),
91 };
92 let cache = IccCache::new_with_options(opts);
93 for &(c, m, y, k) in cases {
94 let rgb = cache.convert_cmyk_readonly(c, m, y, k).expect("convert");
95 println!(
96 " CMYK({:.2},{:.2},{:.2},{:.2}) -> ({}, {}, {})",
97 c,
98 m,
99 y,
100 k,
101 (rgb.0 * 255.0).round() as u8,
102 (rgb.1 * 255.0).round() as u8,
103 (rgb.2 * 255.0).round() as u8,
104 );
105 }
106 }
107}