Add EXIF auto-orient and aspect ratio lock toggle
- Implement auto_orient_from_exif() that reads EXIF Orientation tag and applies the correct rotation/flip for all 8 EXIF orientations - Add aspect ratio lock toggle to resize step Width/Height mode - When lock is active, changing width auto-calculates height from the first loaded image's aspect ratio, and vice versa - Uses recursive update guard (Cell<bool>) to prevent infinite loops
This commit is contained in:
@@ -331,7 +331,7 @@ impl PipelineExecutor {
|
||||
Rotation::Cw90 => img.rotate90(),
|
||||
Rotation::Cw180 => img.rotate180(),
|
||||
Rotation::Cw270 => img.rotate270(),
|
||||
Rotation::AutoOrient => img,
|
||||
Rotation::AutoOrient => auto_orient_from_exif(img, &source.path),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -502,6 +502,49 @@ fn num_cpus() -> usize {
|
||||
.unwrap_or(1)
|
||||
}
|
||||
|
||||
/// Read EXIF orientation tag and apply the appropriate rotation/flip.
|
||||
/// EXIF orientation values:
|
||||
/// 1 = Normal, 2 = Flipped horizontal, 3 = Rotated 180,
|
||||
/// 4 = Flipped vertical, 5 = Transposed (flip H + rotate 270),
|
||||
/// 6 = Rotated 90 CW, 7 = Transverse (flip H + rotate 90),
|
||||
/// 8 = Rotated 270 CW
|
||||
fn auto_orient_from_exif(
|
||||
img: image::DynamicImage,
|
||||
path: &std::path::Path,
|
||||
) -> image::DynamicImage {
|
||||
let Ok(metadata) = little_exif::metadata::Metadata::new_from_path(path) else {
|
||||
return img;
|
||||
};
|
||||
|
||||
let endian = metadata.get_endian();
|
||||
let Some(tag) = metadata.get_tag(&little_exif::exif_tag::ExifTag::Orientation(Vec::new())) else {
|
||||
return img;
|
||||
};
|
||||
|
||||
let bytes = tag.value_as_u8_vec(endian);
|
||||
if bytes.len() < 2 {
|
||||
return img;
|
||||
}
|
||||
|
||||
// Orientation is a 16-bit unsigned integer
|
||||
let orientation = match endian {
|
||||
little_exif::endian::Endian::Little => u16::from_le_bytes([bytes[0], bytes[1]]),
|
||||
little_exif::endian::Endian::Big => u16::from_be_bytes([bytes[0], bytes[1]]),
|
||||
};
|
||||
|
||||
match orientation {
|
||||
1 => img, // Normal
|
||||
2 => img.fliph(), // Flipped horizontal
|
||||
3 => img.rotate180(), // Rotated 180
|
||||
4 => img.flipv(), // Flipped vertical
|
||||
5 => img.fliph().rotate270(), // Transposed
|
||||
6 => img.rotate90(), // Rotated 90 CW
|
||||
7 => img.fliph().rotate90(), // Transverse
|
||||
8 => img.rotate270(), // Rotated 270 CW
|
||||
_ => img,
|
||||
}
|
||||
}
|
||||
|
||||
fn find_unique_path(path: &std::path::Path) -> std::path::PathBuf {
|
||||
let stem = path
|
||||
.file_stem()
|
||||
|
||||
Reference in New Issue
Block a user