Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add basic jxlinfo binary #19

Merged
merged 6 commits into from
Sep 24, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions AUTHORS
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ Google LLC <*@google.com>
Luca Versari
Ewout ter Hoeven <[email protected]>
Sami Boukortt
Moritz Firsching
Tomáš Král <[email protected]>
Wonwoo Choi <[email protected]>
Martin Bruse <[email protected]>
200 changes: 200 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
debug = true

[workspace]
members = [ "jxl", "jxl_cli", "jxl_headers_derive"]
members = [ "jxl", "jxl_cli", "jxl_headers_derive", "jxlinfo"]
mo271 marked this conversation as resolved.
Show resolved Hide resolved
resolver = "2"

[workspace.lints.clippy]
Expand Down
12 changes: 12 additions & 0 deletions jxlinfo/Cargo.toml
Original file line number Diff line number Diff line change
@@ -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

112 changes: 112 additions & 0 deletions jxlinfo/src/main.rs
Original file line number Diff line number Diff line change
@@ -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::<String>("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}");
}
}
Loading