Raw-rs: Flip and rotate image based on camera orientation (#1954)

* add Orientation tag

* fix errors

* Apply the transformation to the image

* Fix BASE_PATH in raw-rs tests

* Create output folder if it doesn't exist

* Nit

---------

Co-authored-by: Keavon Chambers <keavon@keavon.com>
This commit is contained in:
Elbert Ronnie
2024-09-05 15:18:58 -07:00
committed by GitHub
co-authored by Keavon Chambers
parent 70dacac474
commit d9ae01bf90
12 changed files with 147 additions and 8 deletions
+1
View File
@@ -22,6 +22,7 @@ pub enum TagId {
Make = 0x10f,
Model = 0x110,
StripOffsets = 0x111,
Orientation = 0x112,
SamplesPerPixel = 0x115,
RowsPerStrip = 0x116,
StripByteCounts = 0x117,
+9 -1
View File
@@ -1,4 +1,4 @@
use super::types::{Array, ConstArray, TagType, TypeByte, TypeIfd, TypeLong, TypeNumber, TypeSRational, TypeSShort, TypeShort, TypeSonyToneCurve, TypeString};
use super::types::{Array, ConstArray, TagType, TypeByte, TypeIfd, TypeLong, TypeNumber, TypeOrientation, TypeSRational, TypeSShort, TypeShort, TypeSonyToneCurve, TypeString};
use super::{Ifd, TagId, TiffError, TiffRead};
use std::io::{Read, Seek};
@@ -18,6 +18,7 @@ pub struct PhotometricInterpretation;
pub struct Make;
pub struct Model;
pub struct StripOffsets;
pub struct Orientation;
pub struct SamplesPerPixel;
pub struct RowsPerStrip;
pub struct StripByteCounts;
@@ -89,6 +90,13 @@ impl SimpleTag for StripOffsets {
const NAME: &'static str = "Strip Offsets";
}
impl SimpleTag for Orientation {
type Type = TypeOrientation;
const ID: TagId = TagId::Orientation;
const NAME: &'static str = "Orientation";
}
impl SimpleTag for SamplesPerPixel {
type Type = TypeShort;
+20 -1
View File
@@ -1,7 +1,7 @@
use std::io::{Read, Seek};
use super::file::TiffRead;
use super::values::{CurveLookupTable, Rational};
use super::values::{CurveLookupTable, Rational, Transform};
use super::{Ifd, IfdTagType, TiffError};
pub struct TypeAscii;
@@ -357,6 +357,7 @@ impl<T: PrimitiveType, const N: usize> TagType for ConstArray<T, N> {
pub struct TypeString;
pub struct TypeSonyToneCurve;
pub struct TypeOrientation;
impl TagType for TypeString {
type Output = String;
@@ -378,3 +379,21 @@ impl TagType for TypeSonyToneCurve {
Ok(CurveLookupTable::from_sony_tone_table(values))
}
}
impl TagType for TypeOrientation {
type Output = Transform;
fn read<R: Read + Seek>(file: &mut TiffRead<R>) -> Result<Self::Output, TiffError> {
Ok(match TypeShort::read(file)? {
1 => Transform::Horizontal,
2 => Transform::MirrorHorizontal,
3 => Transform::Rotate180,
4 => Transform::MirrorVertical,
5 => Transform::MirrorHorizontalRotate270,
6 => Transform::Rotate90,
7 => Transform::MirrorHorizontalRotate90,
8 => Transform::Rotate270,
_ => return Err(TiffError::InvalidValue),
})
}
}
+27
View File
@@ -50,3 +50,30 @@ impl CurveLookupTable {
self.table[x]
}
}
#[derive(Copy, Clone, Eq, PartialEq)]
pub enum Transform {
Horizontal,
MirrorHorizontal,
Rotate180,
MirrorVertical,
MirrorHorizontalRotate270,
Rotate90,
MirrorHorizontalRotate90,
Rotate270,
}
impl Transform {
pub fn is_identity(&self) -> bool {
*self == Transform::Horizontal
}
pub fn will_swap_coordinates(&self) -> bool {
use Transform as Tr;
match *self {
Tr::Horizontal | Tr::MirrorHorizontal | Tr::Rotate180 | Tr::MirrorVertical => false,
Tr::MirrorHorizontalRotate270 | Tr::Rotate90 | Tr::MirrorHorizontalRotate90 | Tr::Rotate270 => true,
}
}
}