mod common;
use common::{load_ground_truth, test_data_path, test_fixture_path};
use rawshift_image::tiff::{TiffParser, TiffTag};
use std::fs::File;
use std::io::BufReader;
fn skip_if_no_test_data(filename: &str) -> bool {
let path = test_data_path(filename);
if !path.exists() {
eprintln!("Skipping test: test data file not found: {:?}", path);
return true;
}
false
}
#[test]
fn test_header_byte_order_jic7790() {
if skip_if_no_test_data("SONY/ILCE-6700/_JIC7790.ARW") {
return;
}
let gt =
load_ground_truth(&test_fixture_path("SONY/ILCE-6700/_JIC7790/expected.json")).unwrap();
let file = File::open(test_data_path("SONY/ILCE-6700/_JIC7790.ARW")).unwrap();
let reader = BufReader::new(file);
let parser = TiffParser::new(reader).unwrap();
let header = parser.header();
let actual_byte_order = header.byte_order.as_str();
assert_eq!(
actual_byte_order, gt.structure.byte_order,
"Byte order mismatch: expected {}, got {}",
gt.structure.byte_order, actual_byte_order
);
}
#[test]
fn test_header_byte_order_jic7792() {
if skip_if_no_test_data("SONY/ILCE-6700/_JIC7792.ARW") {
return;
}
let gt =
load_ground_truth(&test_fixture_path("SONY/ILCE-6700/_JIC7792/expected.json")).unwrap();
let file = File::open(test_data_path("SONY/ILCE-6700/_JIC7792.ARW")).unwrap();
let reader = BufReader::new(file);
let parser = TiffParser::new(reader).unwrap();
let header = parser.header();
assert_eq!(header.byte_order.as_str(), gt.structure.byte_order);
}
#[test]
fn test_is_not_bigtiff() {
if skip_if_no_test_data("SONY/ILCE-6700/_JIC7790.ARW") {
return;
}
let gt =
load_ground_truth(&test_fixture_path("SONY/ILCE-6700/_JIC7790/expected.json")).unwrap();
let file = File::open(test_data_path("SONY/ILCE-6700/_JIC7790.ARW")).unwrap();
let reader = BufReader::new(file);
let parser = TiffParser::new(reader).unwrap();
assert_eq!(parser.is_bigtiff(), gt.structure.is_big_tiff);
}
#[test]
fn test_magic_number() {
if skip_if_no_test_data("SONY/ILCE-6700/_JIC7790.ARW") {
return;
}
let file = File::open(test_data_path("SONY/ILCE-6700/_JIC7790.ARW")).unwrap();
let reader = BufReader::new(file);
let parser = TiffParser::new(reader).unwrap();
assert_eq!(parser.header().magic, 42);
}
#[test]
fn test_ifd_count_jic7790() {
if skip_if_no_test_data("SONY/ILCE-6700/_JIC7790.ARW") {
return;
}
let gt =
load_ground_truth(&test_fixture_path("SONY/ILCE-6700/_JIC7790/expected.json")).unwrap();
let file = File::open(test_data_path("SONY/ILCE-6700/_JIC7790.ARW")).unwrap();
let reader = BufReader::new(file);
let mut parser = TiffParser::new(reader).unwrap();
let ifds = parser.walk_ifd_chain().unwrap();
assert_eq!(
ifds.len(),
gt.structure.ifd_count,
"IFD count mismatch: expected {}, got {}",
gt.structure.ifd_count,
ifds.len()
);
}
#[test]
fn test_ifd_count_jic7792() {
if skip_if_no_test_data("SONY/ILCE-6700/_JIC7792.ARW") {
return;
}
let gt =
load_ground_truth(&test_fixture_path("SONY/ILCE-6700/_JIC7792/expected.json")).unwrap();
let file = File::open(test_data_path("SONY/ILCE-6700/_JIC7792.ARW")).unwrap();
let reader = BufReader::new(file);
let mut parser = TiffParser::new(reader).unwrap();
let ifds = parser.walk_ifd_chain().unwrap();
assert_eq!(ifds.len(), gt.structure.ifd_count);
}
#[test]
fn test_required_tags_present() {
if skip_if_no_test_data("SONY/ILCE-6700/_JIC7790.ARW") {
return;
}
let file = File::open(test_data_path("SONY/ILCE-6700/_JIC7790.ARW")).unwrap();
let reader = BufReader::new(file);
let mut parser = TiffParser::new(reader).unwrap();
let ifds = parser.walk_ifd_chain().unwrap();
let mut all_tags: Vec<u16> = Vec::new();
fn collect_tags(ifd: &rawshift_image::tiff::Ifd, tags: &mut Vec<u16>) {
tags.extend(ifd.all_tag_ids());
for sub_ifd in &ifd.sub_ifds {
collect_tags(sub_ifd, tags);
}
}
for ifd in &ifds {
collect_tags(ifd, &mut all_tags);
}
assert!(
all_tags.contains(&0x0100),
"Required tag ImageWidth (0x0100) not found in any IFD"
);
assert!(
all_tags.contains(&0x0111),
"Required tag StripOffsets (0x0111) not found in any IFD"
);
}
#[test]
fn test_sub_ifd_parsing() {
if skip_if_no_test_data("SONY/ILCE-6700/_JIC7790.ARW") {
return;
}
let file = File::open(test_data_path("SONY/ILCE-6700/_JIC7790.ARW")).unwrap();
let reader = BufReader::new(file);
let mut parser = TiffParser::new(reader).unwrap();
let ifd0 = parser.parse_ifd0().unwrap();
assert!(
!ifd0.sub_ifds.is_empty() || ifd0.contains(TiffTag::SubIFDs),
"IFD0 should have SubIFDs tag or parsed SubIFDs"
);
}
#[test]
fn test_raw_dimensions_jic7790() {
if skip_if_no_test_data("SONY/ILCE-6700/_JIC7790.ARW") {
return;
}
let gt =
load_ground_truth(&test_fixture_path("SONY/ILCE-6700/_JIC7790/expected.json")).unwrap();
let file = File::open(test_data_path("SONY/ILCE-6700/_JIC7790.ARW")).unwrap();
let reader = BufReader::new(file);
let mut parser = TiffParser::new(reader).unwrap();
let ifd0 = parser.parse_ifd0().unwrap();
let mut found = false;
for sub_ifd in &ifd0.sub_ifds {
if let Some(width_entry) = sub_ifd.get(TiffTag::ImageWidth) {
let width_value = parser.read_value(width_entry).unwrap();
if let Some(width) = width_value.as_u32()
&& width == gt.primary_raw_frame.width
{
found = true;
if let Some(height_entry) = sub_ifd.get(TiffTag::ImageLength) {
let height_value = parser.read_value(height_entry).unwrap();
if let Some(height) = height_value.as_u32() {
assert_eq!(
height, gt.primary_raw_frame.height,
"Height mismatch: expected {}, got {}",
gt.primary_raw_frame.height, height
);
}
}
break;
}
}
}
assert!(
found,
"Could not find SubIFD with expected width {}",
gt.primary_raw_frame.width
);
}
#[test]
fn test_bit_depth_jic7790() {
if skip_if_no_test_data("SONY/ILCE-6700/_JIC7790.ARW") {
return;
}
let gt =
load_ground_truth(&test_fixture_path("SONY/ILCE-6700/_JIC7790/expected.json")).unwrap();
let file = File::open(test_data_path("SONY/ILCE-6700/_JIC7790.ARW")).unwrap();
let reader = BufReader::new(file);
let mut parser = TiffParser::new(reader).unwrap();
let ifd0 = parser.parse_ifd0().unwrap();
for sub_ifd in &ifd0.sub_ifds {
if let Some(entry) = sub_ifd.get(TiffTag::BitsPerSample) {
let value = parser.read_value(entry).unwrap();
if let Some(bits) = value.as_u32()
&& bits == gt.primary_raw_frame.bit_depth as u32
{
return;
}
}
}
panic!(
"Could not find BitsPerSample matching expected value {}",
gt.primary_raw_frame.bit_depth
);
}
#[test]
fn test_strip_offsets_within_bounds_jic7790() {
if skip_if_no_test_data("SONY/ILCE-6700/_JIC7790.ARW") {
return;
}
let gt =
load_ground_truth(&test_fixture_path("SONY/ILCE-6700/_JIC7790/expected.json")).unwrap();
let file = File::open(test_data_path("SONY/ILCE-6700/_JIC7790.ARW")).unwrap();
let reader = BufReader::new(file);
let mut parser = TiffParser::new(reader).unwrap();
let ifd0 = parser.parse_ifd0().unwrap();
for sub_ifd in &ifd0.sub_ifds {
if let (Some(offset_entry), Some(count_entry)) = (
sub_ifd.get(TiffTag::StripOffsets),
sub_ifd.get(TiffTag::StripByteCounts),
) {
let offsets = parser.read_value(offset_entry).unwrap();
let counts = parser.read_value(count_entry).unwrap();
if let (Some(offset_vec), Some(count_vec)) = (offsets.as_u32_vec(), counts.as_u32_vec())
{
for (offset, count) in offset_vec.iter().zip(count_vec.iter()) {
let end = *offset as u64 + *count as u64;
assert!(
end <= gt.file_size,
"Strip data exceeds file size: offset {} + count {} = {} > file size {}",
offset,
count,
end,
gt.file_size
);
}
}
}
}
}
#[test]
fn test_make_model_extraction() {
if skip_if_no_test_data("SONY/ILCE-6700/_JIC7790.ARW") {
return;
}
let gt =
load_ground_truth(&test_fixture_path("SONY/ILCE-6700/_JIC7790/expected.json")).unwrap();
let file = File::open(test_data_path("SONY/ILCE-6700/_JIC7790.ARW")).unwrap();
let reader = BufReader::new(file);
let mut parser = TiffParser::new(reader).unwrap();
let ifd0 = parser.parse_ifd0().unwrap();
if let Some(make_entry) = ifd0.get(TiffTag::Make) {
let make_value = parser.read_value(make_entry).unwrap();
if let Some(make) = make_value.as_str()
&& let Some(ref camera_info) = gt.camera_info
{
assert!(
make.contains(&camera_info.make),
"Make mismatch: expected to contain '{}', got '{}'",
camera_info.make,
make
);
}
}
if let Some(model_entry) = ifd0.get(TiffTag::Model) {
let model_value = parser.read_value(model_entry).unwrap();
if let Some(model) = model_value.as_str()
&& let Some(ref camera_info) = gt.camera_info
{
assert!(
model.contains(&camera_info.model) || camera_info.model.contains(model),
"Model mismatch: expected to contain '{}', got '{}'",
camera_info.model,
model
);
}
}
}