From 7bb69c1d4cd351676fe5513d502f1d90c03f1d38 Mon Sep 17 00:00:00 2001 From: Moritz Firsching Date: Tue, 24 Sep 2024 13:31:25 +0200 Subject: [PATCH 1/6] add basic jxlinfo binary --- Cargo.lock | 200 ++++++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 2 +- jxlinfo/Cargo.toml | 12 +++ jxlinfo/src/main.rs | 112 +++++++++++++++++++++++++ 4 files changed, 325 insertions(+), 1 deletion(-) create mode 100644 jxlinfo/Cargo.toml create mode 100644 jxlinfo/src/main.rs diff --git a/Cargo.lock b/Cargo.lock index e0bec4d..659213f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,55 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "anstream" +version = "0.6.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64e15c1ab1f89faffbf04a634d5e1962e9074f2741eef6d97f3c4e322426d526" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1" + +[[package]] +name = "anstyle-parse" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb47de1e80c2b463c735db5b217a0ddc39d612e7ac9e2e96a5aed1f57616c1cb" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422a" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5bf74e1b6e971609db8ca7a9ce79fd5768ab6ae46441c572e46cf596f59e57f8" +dependencies = [ + "anstyle", + "windows-sys", +] + [[package]] name = "arbitrary" version = "1.3.2" @@ -35,12 +84,70 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" +[[package]] +name = "clap" +version = "4.5.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0956a43b323ac1afaffc053ed5c4b7c1f1800bacd1683c353aabbb752515dd3" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.5.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d72166dd41634086d5803a47eb71ae740e61d84709c36f3c34110173db3961b" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", +] + +[[package]] +name = "clap_derive" +version = "4.5.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn 2.0.77", +] + +[[package]] +name = "clap_lex" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97" + +[[package]] +name = "colorchoice" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0" + [[package]] name = "half" version = "1.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b43ede17f21864e81be2fa654110bf1e793774238d86ef8555c37e6519c0403" +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "is_terminal_polyfill" +version = "1.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" + [[package]] name = "jxl" version = "0.1.0" @@ -73,6 +180,14 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "jxlinfo" +version = "0.1.0" +dependencies = [ + "clap", + "jxl", +] + [[package]] name = "num-derive" version = "0.3.3" @@ -147,6 +262,12 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + [[package]] name = "syn" version = "1.0.109" @@ -226,8 +347,87 @@ version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" +[[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + [[package]] name = "version_check" version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" diff --git a/Cargo.toml b/Cargo.toml index f034c32..ffcc89b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,7 +2,7 @@ debug = true [workspace] -members = [ "jxl", "jxl_cli", "jxl_headers_derive"] +members = [ "jxl", "jxl_cli", "jxl_headers_derive", "jxlinfo"] resolver = "2" [workspace.lints.clippy] diff --git a/jxlinfo/Cargo.toml b/jxlinfo/Cargo.toml new file mode 100644 index 0000000..237dc91 --- /dev/null +++ b/jxlinfo/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "jxlinfo" +version = "0.1.0" +edition = "2021" + +[dependencies] +clap = { version = "4.5.18", features = ["derive"] } +jxl = { path = "../jxl" } + +[lints] +workspace = true + diff --git a/jxlinfo/src/main.rs b/jxlinfo/src/main.rs new file mode 100644 index 0000000..c451229 --- /dev/null +++ b/jxlinfo/src/main.rs @@ -0,0 +1,112 @@ +use clap::{Arg, Command}; +use jxl::bit_reader::BitReader; +use jxl::container::{ContainerParser, ParseEvent}; +use jxl::headers::FileHeaders; +use jxl::headers::JxlHeader; +use jxl::icc::read_icc; +use std::fs; +use std::io::Read; + +fn parse_jxl_codestream(data: &[u8], verbose: bool) -> Result<(), jxl::error::Error> { + let mut br = BitReader::new(data); + let fh = FileHeaders::read(&mut br)?; + + // Non-verbose output + if !verbose { + // let color_space = &fh.image_metadata.color_encoding; + let how_lossy = if fh.image_metadata.xyb_encoded { + "lossy" + } else { + "(possibly) lossless" + }; + + println!("{}x{}, {}", fh.size.xsize(), fh.size.ysize(), how_lossy,); + + // TODO(firsching): add non-verbose print for bit-depth + // TODO(firsching): add non-verbose print for color space + return Ok(()); + } + + // Verbose output: Use Debug trait to print the FileHeaders + println!("{:#?}", fh); + + let _icc = if fh.image_metadata.color_encoding.want_icc { + let icc_data = read_icc(&mut br)?; + println!("ICC profile length: {} bytes", icc_data.len()); + Some(icc_data) + } else { + None + }; + + // TODO(firsching): add frame header parsing for each frame + + Ok(()) +} + +fn main() { + let matches = Command::new("jxlinfo") + .about("Provides info about a JXL file") + .arg( + Arg::new("filename") + .help("The JXL file to analyze") + .required(true) + .index(1), + ) + .arg( + Arg::new("verbose") + .short('v') + .long("verbose") + .help("Provides more verbose output") + .num_args(0), + ) + .get_matches(); + + let filename = matches.get_one::("filename").unwrap(); + let verbose = matches.get_flag("verbose"); + + if verbose { + println!("Processing file: {}", filename); + } + + let mut file = fs::File::open(filename).expect("Cannot open file"); + + // Set up the container parser and buffers + let mut parser = ContainerParser::new(); + let mut buf = vec![0u8; 4096]; + let mut buf_valid = 0usize; + let mut codestream = Vec::new(); + + loop { + let count = file + .read(&mut buf[buf_valid..]) + .expect("Cannot read data from file"); + if count == 0 { + break; + } + buf_valid += count; + + for event in parser.process_bytes(&buf[..buf_valid]) { + match event { + Ok(ParseEvent::BitstreamKind(kind)) => { + println!("Bitstream kind: {kind:?}"); + } + Ok(ParseEvent::Codestream(data)) => { + codestream.extend_from_slice(data); + } + Err(err) => { + println!("Error parsing JXL codestream: {err}"); + return; + } + } + } + + let consumed = parser.previous_consumed_bytes(); + buf.copy_within(consumed..buf_valid, 0); + buf_valid -= consumed; + } + + let res = parse_jxl_codestream(&codestream, verbose); + if let Err(err) = res { + println!("Error parsing JXL codestream: {err}"); + } +} From 5c910b6eaa29fb844931df8d7e31b8f690de2620 Mon Sep 17 00:00:00 2001 From: Moritz Firsching Date: Tue, 24 Sep 2024 15:44:45 +0200 Subject: [PATCH 2/6] add to authors --- AUTHORS | 1 + 1 file changed, 1 insertion(+) diff --git a/AUTHORS b/AUTHORS index 46cd115..64502d8 100644 --- a/AUTHORS +++ b/AUTHORS @@ -19,6 +19,7 @@ Google LLC <*@google.com> Luca Versari Ewout ter Hoeven Sami Boukortt +Moritz Firsching Tomáš Král Wonwoo Choi Martin Bruse From 6c508b116e8b39301c89ab297a655f4176aaafb9 Mon Sep 17 00:00:00 2001 From: Moritz Firsching Date: Tue, 24 Sep 2024 15:46:41 +0200 Subject: [PATCH 3/6] copyright header --- jxlinfo/src/main.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/jxlinfo/src/main.rs b/jxlinfo/src/main.rs index c451229..b45c778 100644 --- a/jxlinfo/src/main.rs +++ b/jxlinfo/src/main.rs @@ -1,3 +1,8 @@ +// Copyright (c) the JPEG XL Project Authors. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + use clap::{Arg, Command}; use jxl::bit_reader::BitReader; use jxl::container::{ContainerParser, ParseEvent}; From 5b4702b7f2aae75a1d518cd716f035b7ecc0c8fe Mon Sep 17 00:00:00 2001 From: Moritz Firsching Date: Tue, 24 Sep 2024 15:57:04 +0200 Subject: [PATCH 4/6] move to jxl_cli --- Cargo.lock | 9 +-------- Cargo.toml | 2 +- jxl_cli/Cargo.toml | 1 + jxlinfo/src/main.rs => jxl_cli/src/bin/jxlinfo.rs | 0 jxlinfo/Cargo.toml | 12 ------------ 5 files changed, 3 insertions(+), 21 deletions(-) rename jxlinfo/src/main.rs => jxl_cli/src/bin/jxlinfo.rs (100%) delete mode 100644 jxlinfo/Cargo.toml diff --git a/Cargo.lock b/Cargo.lock index 659213f..eaca09e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -167,6 +167,7 @@ dependencies = [ name = "jxl_cli" version = "0.1.0" dependencies = [ + "clap", "jxl", ] @@ -180,14 +181,6 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "jxlinfo" -version = "0.1.0" -dependencies = [ - "clap", - "jxl", -] - [[package]] name = "num-derive" version = "0.3.3" diff --git a/Cargo.toml b/Cargo.toml index ffcc89b..f034c32 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,7 +2,7 @@ debug = true [workspace] -members = [ "jxl", "jxl_cli", "jxl_headers_derive", "jxlinfo"] +members = [ "jxl", "jxl_cli", "jxl_headers_derive"] resolver = "2" [workspace.lints.clippy] diff --git a/jxl_cli/Cargo.toml b/jxl_cli/Cargo.toml index 6dd6e60..5b8d142 100644 --- a/jxl_cli/Cargo.toml +++ b/jxl_cli/Cargo.toml @@ -5,6 +5,7 @@ edition = "2021" [dependencies] jxl = { path = "../jxl" } +clap = { version = "4.5.18", features = ["derive"] } [lints] workspace = true diff --git a/jxlinfo/src/main.rs b/jxl_cli/src/bin/jxlinfo.rs similarity index 100% rename from jxlinfo/src/main.rs rename to jxl_cli/src/bin/jxlinfo.rs diff --git a/jxlinfo/Cargo.toml b/jxlinfo/Cargo.toml deleted file mode 100644 index 237dc91..0000000 --- a/jxlinfo/Cargo.toml +++ /dev/null @@ -1,12 +0,0 @@ -[package] -name = "jxlinfo" -version = "0.1.0" -edition = "2021" - -[dependencies] -clap = { version = "4.5.18", features = ["derive"] } -jxl = { path = "../jxl" } - -[lints] -workspace = true - From 5388c4fb573c97326437fc2d51214ace558872f0 Mon Sep 17 00:00:00 2001 From: Moritz Firsching Date: Tue, 24 Sep 2024 16:10:10 +0200 Subject: [PATCH 5/6] remove leftovers --- jxl_cli/src/bin/jxlinfo.rs | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/jxl_cli/src/bin/jxlinfo.rs b/jxl_cli/src/bin/jxlinfo.rs index b45c778..6439ba3 100644 --- a/jxl_cli/src/bin/jxlinfo.rs +++ b/jxl_cli/src/bin/jxlinfo.rs @@ -18,7 +18,6 @@ fn parse_jxl_codestream(data: &[u8], verbose: bool) -> Result<(), jxl::error::Er // Non-verbose output if !verbose { - // let color_space = &fh.image_metadata.color_encoding; let how_lossy = if fh.image_metadata.xyb_encoded { "lossy" } else { @@ -35,14 +34,12 @@ fn parse_jxl_codestream(data: &[u8], verbose: bool) -> Result<(), jxl::error::Er // Verbose output: Use Debug trait to print the FileHeaders println!("{:#?}", fh); - let _icc = if fh.image_metadata.color_encoding.want_icc { + // TODO(firsching): consider printing more of less information for ICC + // for verbose/non-verbose cases + if fh.image_metadata.color_encoding.want_icc { let icc_data = read_icc(&mut br)?; println!("ICC profile length: {} bytes", icc_data.len()); - Some(icc_data) - } else { - None - }; - + } // TODO(firsching): add frame header parsing for each frame Ok(()) From 89aa6f0af5cf1e97d03c451798f02ec23d0bf4a8 Mon Sep 17 00:00:00 2001 From: Moritz Firsching Date: Tue, 24 Sep 2024 17:41:11 +0200 Subject: [PATCH 6/6] remove derive feature --- Cargo.lock | 19 ------------------- jxl_cli/Cargo.toml | 2 +- 2 files changed, 1 insertion(+), 20 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index eaca09e..e2e6538 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -91,7 +91,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b0956a43b323ac1afaffc053ed5c4b7c1f1800bacd1683c353aabbb752515dd3" dependencies = [ "clap_builder", - "clap_derive", ] [[package]] @@ -106,18 +105,6 @@ dependencies = [ "strsim", ] -[[package]] -name = "clap_derive" -version = "4.5.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab" -dependencies = [ - "heck", - "proc-macro2", - "quote", - "syn 2.0.77", -] - [[package]] name = "clap_lex" version = "0.7.2" @@ -136,12 +123,6 @@ version = "1.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b43ede17f21864e81be2fa654110bf1e793774238d86ef8555c37e6519c0403" -[[package]] -name = "heck" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" - [[package]] name = "is_terminal_polyfill" version = "1.70.1" diff --git a/jxl_cli/Cargo.toml b/jxl_cli/Cargo.toml index 5b8d142..cd7c6f8 100644 --- a/jxl_cli/Cargo.toml +++ b/jxl_cli/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] jxl = { path = "../jxl" } -clap = { version = "4.5.18", features = ["derive"] } +clap = { version = "4.5.18" } [lints] workspace = true