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 a function to apply Exif rotation #2299

Merged
merged 20 commits into from
Sep 13, 2024
Merged
Changes from 5 commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
d9b4517
Add in-place 180 degree rotation to DynamicImage
Shnatsel Jul 27, 2024
da93b9d
Doc comment: when rotating 180 degrees, direction doesn't matter
Shnatsel Jul 27, 2024
f8cea83
Add in-place flips to DynamicImage
Shnatsel Jul 27, 2024
a799736
Add a function to apply Exif rotation
Shnatsel Jul 30, 2024
fb1ccaf
Do not promise to implement complex algorithms that aren't currently …
Shnatsel Jul 30, 2024
d3a8acf
Create a type to encode image orientation, accept it in the function …
Shnatsel Sep 1, 2024
91f15b1
Make newly added in-place transformation functions private
Shnatsel Sep 9, 2024
92d2ec2
Change doc comment following review comment
Shnatsel Sep 9, 2024
ecdf8f5
Rename flip orientations to make them more explicit
Shnatsel Sep 9, 2024
fad5aaa
Document apply_orientation as an alternative to non-in-place functions
Shnatsel Sep 9, 2024
c3cec8c
Suppress Clippy false positive
Shnatsel Sep 9, 2024
873c410
Link to Clippy lint issue instead of just handwaving
Shnatsel Sep 9, 2024
644b68e
Merge branch 'image-rs:main' into exif-rotation
Shnatsel Sep 9, 2024
9d1a694
Make apply_orientation infallible now that it accepts an enum
Shnatsel Sep 9, 2024
25bd5eb
Fix incorrect doc comment
Shnatsel Sep 12, 2024
b4cb2d6
Fix erroneous exif conversion for value 7
Shnatsel Sep 13, 2024
9c0d517
Add a function to convert from Orientation to Exif values
Shnatsel Sep 13, 2024
005844d
Rename the module with `Orientation` struct to `metadata`
Shnatsel Sep 13, 2024
c461e99
Fix doclinks
Shnatsel Sep 13, 2024
6dad395
Link from Orientation struct to the function that applies it
Shnatsel Sep 13, 2024
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
53 changes: 52 additions & 1 deletion src/dynimage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -878,30 +878,81 @@ impl DynamicImage {
dynamic_map!(*self, ref p => imageops::flip_vertical(p))
}

/// Flip this image vertically in place
pub fn flipv_in_place(&mut self) {
Shnatsel marked this conversation as resolved.
Show resolved Hide resolved
dynamic_map!(*self, ref mut p, imageops::flip_vertical_in_place(p))
}

/// Flip this image horizontally
Shnatsel marked this conversation as resolved.
Show resolved Hide resolved
#[must_use]
pub fn fliph(&self) -> DynamicImage {
dynamic_map!(*self, ref p => imageops::flip_horizontal(p))
}

/// Flip this image horizontally in place
pub fn fliph_in_place(&mut self) {
Shnatsel marked this conversation as resolved.
Show resolved Hide resolved
dynamic_map!(*self, ref mut p, imageops::flip_horizontal_in_place(p))
}

/// Rotate this image 90 degrees clockwise.
#[must_use]
pub fn rotate90(&self) -> DynamicImage {
dynamic_map!(*self, ref p => imageops::rotate90(p))
}

/// Rotate this image 180 degrees clockwise.
/// Rotate this image 180 degrees.
#[must_use]
pub fn rotate180(&self) -> DynamicImage {
dynamic_map!(*self, ref p => imageops::rotate180(p))
}

/// Rotate this image 180 degrees in place.
pub fn rotate180_in_place(&mut self) {
Shnatsel marked this conversation as resolved.
Show resolved Hide resolved
dynamic_map!(*self, ref mut p, imageops::rotate180_in_place(p))
}

/// Rotate this image 270 degrees clockwise.
#[must_use]
pub fn rotate270(&self) -> DynamicImage {
dynamic_map!(*self, ref p => imageops::rotate270(p))
}

/// Applies the [Exif orientation](https://web.archive.org/web/20200412005226/https://www.impulseadventure.com/photo/exif-orientation.html) to the image.
///
/// Orientation is specified in the Exif metadata, and is often written by cameras.
/// It is expressed as an integer in the range 1..=8; passing other values will return an error.
///
/// Due to an implementation detail, orientations 5..=8 copy the image internally.
pub fn apply_exif_orientation_in_place(&mut self, orientation: u8) -> Result<(), ImageError> {
Shnatsel marked this conversation as resolved.
Show resolved Hide resolved
// Verified against `convert -auto-orient`
let image = self;
match orientation {
1 => Ok(()), // no transformations needed
2 => Ok(image.fliph_in_place()),
3 => Ok(image.rotate180_in_place()),
4 => Ok(image.flipv_in_place()),
5 => {
let mut new_image = image.rotate90();
new_image.fliph_in_place();
*image = new_image;
Ok(())
}
6 => Ok(*image = image.rotate90()),
7 => {
let mut new_image = image.rotate270();
new_image.fliph_in_place();
*image = new_image;
Ok(())
}
8 => Ok(*image = image.rotate270()),
0 | 9.. => {
return Err(ImageError::Parameter(ParameterError::from_kind(
ParameterErrorKind::Generic(format!("Invalid exif orientation: {orientation}")),
)))
}
}
}

/// Encode this image and write it to ```w```.
///
/// Assumes the writer is buffered. In most cases,
Expand Down
Loading