#[non_exhaustive]pub enum ImageOrientation {
TopLeft,
TopRight,
BottomRight,
BottomLeft,
LeftTop,
RightTop,
RightBottom,
LeftBottom,
Other([i32; 9]),
}Expand description
Where the first stored row and column of a still belong on screen — the eight orientations EXIF names, tags 1 through 8.
§How it reaches us
Not through AVFrame.metadata, which is where an earlier reading of
libavcodec put it. Measured, against this build, by feeding
mjpeg a JPEG whose EXIF IFD carries each orientation in turn: for a
recognised tag (1..=8) the decoder emits an
AV_FRAME_DATA_DISPLAYMATRIX frame side-data entry and puts
nothing in the metadata dictionary; only an out-of-range tag (0,
9, …) is left to fall through to the dictionary, as the string
" 9". So the display matrix is the road, and the metadata
dictionary is where malformed tags go to be ignored.
The matrix that arrives is the one below, in units of 65536 (the
16.16 fixed point libavutil/display.h specifies), with
(a, b, c, d) the entries at indices 0, 1, 3, 4:
| tag | variant | a | b | c | d |
|---|---|---|---|---|---|
| 1 | TopLeft | 1 | 0 | 0 | 1 |
| 2 | TopRight | -1 | 0 | 0 | 1 |
| 3 | BottomRight | -1 | 0 | 0 | -1 |
| 4 | BottomLeft | 1 | 0 | 0 | -1 |
| 5 | LeftTop | 0 | 1 | 1 | 0 |
| 6 | RightTop | 0 | 1 | -1 | 0 |
| 7 | RightBottom | 0 | -1 | -1 | 0 |
| 8 | LeftBottom | 0 | -1 | 1 | 0 |
§Why a vocabulary of its own
mediaframe::frame::Rotation is this crate’s home for a quarter
turn and is reused by Self::rotation — but it names four values
and there are eight. The other four are mirrored, and a rotation
vocabulary cannot hold a reflection. The same gap shows up one
level down in FFmpeg’s own API: av_display_rotation_get answers
-180 for both tag 2 and tag 3, -90 for both 5 and 6, and
90 for both 7 and 8 — reading only the angle loses the mirror on
half the vocabulary. This type is the eight-value reading that does
not.
Variants (Non-exhaustive)§
This enum is marked as non-exhaustive
TopLeft
Tag 1 — stored as displayed. The default and the overwhelming majority of files.
TopRight
Tag 2 — mirrored horizontally.
BottomRight
Tag 3 — turned half way round.
BottomLeft
Tag 4 — mirrored vertically.
LeftTop
Tag 5 — transposed (mirrored, then a quarter turn clockwise).
RightTop
Tag 6 — a quarter turn clockwise.
RightBottom
Tag 7 — transverse (mirrored, then three quarter turns clockwise).
LeftBottom
Tag 8 — three quarter turns clockwise.
Other([i32; 9])
A display matrix none of the eight names, carried verbatim as all nine of its words.
Reachable: the display matrix is a general affine transform, and
a container (a MOV tkhd, a hand-built stream) may carry an
arbitrary one. Rather than answer TopLeft for a transform this
vocabulary cannot name — the silent-loss failure this crate
refuses everywhere else — the whole matrix rides along and
Self::to_exif_code admits it has no tag for it.
All nine words, not the four that carry the orientation. The
escape’s job is to lose nothing: a matrix with the right linear
part and a translation, or a perspective term, is not one of
the eight, and carrying only [a, b, c, d] would have thrown
away the very words that made it different. That is the same
collapse the escape exists to prevent, one level in.
Implementations§
Source§impl ImageOrientation
impl ImageOrientation
Sourcepub const fn is_top_left(&self) -> bool
pub const fn is_top_left(&self) -> bool
Returns true if this value is of type TopLeft. Returns false otherwise
Sourcepub const fn is_top_right(&self) -> bool
pub const fn is_top_right(&self) -> bool
Returns true if this value is of type TopRight. Returns false otherwise
Sourcepub const fn is_bottom_right(&self) -> bool
pub const fn is_bottom_right(&self) -> bool
Returns true if this value is of type BottomRight. Returns false otherwise
Sourcepub const fn is_bottom_left(&self) -> bool
pub const fn is_bottom_left(&self) -> bool
Returns true if this value is of type BottomLeft. Returns false otherwise
Sourcepub const fn is_left_top(&self) -> bool
pub const fn is_left_top(&self) -> bool
Returns true if this value is of type LeftTop. Returns false otherwise
Sourcepub const fn is_right_top(&self) -> bool
pub const fn is_right_top(&self) -> bool
Returns true if this value is of type RightTop. Returns false otherwise
Sourcepub const fn is_right_bottom(&self) -> bool
pub const fn is_right_bottom(&self) -> bool
Returns true if this value is of type RightBottom. Returns false otherwise
Sourcepub const fn is_left_bottom(&self) -> bool
pub const fn is_left_bottom(&self) -> bool
Returns true if this value is of type LeftBottom. Returns false otherwise
Source§impl ImageOrientation
impl ImageOrientation
Sourcepub const DISPLAY_MATRIX_BYTES: usize
pub const DISPLAY_MATRIX_BYTES: usize
The number of bytes an AV_FRAME_DATA_DISPLAYMATRIX entry
carries: nine int32_t, per libavutil/display.h.
Sourcepub const fn matrix(&self) -> [i32; 9]
pub const fn matrix(&self) -> [i32; 9]
The nine-word matrix a named orientation stands for — the exact
inverse of what Self::from_display_matrix reads, and for
Self::Other the words it was handed, unchanged.
libavutil/display.h lays the matrix out row-major as
| a b u | | 0 1 2 |
| c d v | = | 3 4 5 |
| x y w | | 6 7 8 |where a b c d x y are 16.16 fixed point and u v w are 2.30.
A named orientation puts the rotation-or-reflection in a b c d,
no translation in x y, no perspective in u v, and unity in
w.
Sourcepub fn from_display_matrix(bytes: &[u8]) -> Option<Self>
pub fn from_display_matrix(bytes: &[u8]) -> Option<Self>
Reads an orientation out of the raw bytes of an
AV_FRAME_DATA_DISPLAYMATRIX side-data entry.
None when bytes is not exactly
Self::DISPLAY_MATRIX_BYTES long — a malformed entry is not an
orientation, and guessing one from a truncated matrix would be
the invention this seat exists to avoid.
The entries are int32_t in native byte order: the side data
is a C array as it sits in memory, not a wire format.
Sourcepub const fn to_exif_code(&self) -> Option<u16>
pub const fn to_exif_code(&self) -> Option<u16>
The EXIF tag value, 1 through 8.
None for Self::Other: it names a transform EXIF has no tag
for, and there is no number to invent for it.
Sourcepub const fn from_exif_code(code: u16) -> Option<Self>
pub const fn from_exif_code(code: u16) -> Option<Self>
Decodes an EXIF tag value. None outside 1..=8 — never a silent
collapse onto Self::TopLeft, which is what a viewer that
clamps an out-of-range tag ends up showing.
Sourcepub const fn is_mirrored(&self) -> bool
pub const fn is_mirrored(&self) -> bool
true when displaying the picture correctly requires a
reflection as well as a turn — EXIF tags 2, 4, 5 and 7.
Read off the sign of the linear part’s determinant, which is what
a reflection is, so Self::Other answers too.
Sourcepub const fn rotation(&self) -> Option<Rotation>
pub const fn rotation(&self) -> Option<Rotation>
The quarter turn, clockwise, in the EXIF specification’s mirror-then-rotate decomposition — expressed in this workspace’s existing rotation vocabulary.
None for Self::Other, whose transform need not be a
multiple of 90° at all.
This is the specification’s decomposition, not a measurement:
what was measured here is which matrix carries which tag (see
the type’s own docs), and the tag’s meaning is EXIF’s to define.
Self::is_mirrored supplies the half a Rotation cannot
hold.
Sourcepub const fn linear(&self) -> [i32; 4]
pub const fn linear(&self) -> [i32; 4]
The linear part of the display matrix this orientation stands
for, [a, b, c, d] in 16.16 fixed point — matrix indices 0, 1, 3
and 4.
A projection, not the whole value: for Self::Other it
drops the five words that made the matrix unnameable. Use
Self::matrix when nothing may be lost; this is for the
rotation-and-reflection question, which the four words answer on
their own.
Trait Implementations§
Source§impl Clone for ImageOrientation
impl Clone for ImageOrientation
Source§fn clone(&self) -> ImageOrientation
fn clone(&self) -> ImageOrientation
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read more