diff options
author | 2021-09-29 19:26:46 +0200 | |
---|---|---|
committer | 2021-09-30 00:28:56 +0200 | |
commit | 82e3e316dd49884b06fea3ad3129e23faaa7588a (patch) | |
tree | 381279c554913feb693d1e57365df691aaba1eaa /wgpu | |
parent | 4d4c61b887e5721d9eff4085052b24722d1aa082 (diff) | |
download | iced-82e3e316dd49884b06fea3ad3129e23faaa7588a.tar.gz iced-82e3e316dd49884b06fea3ad3129e23faaa7588a.tar.bz2 iced-82e3e316dd49884b06fea3ad3129e23faaa7588a.zip |
Honor Exif orientation in `iced_wgpu::Image`
Diffstat (limited to 'wgpu')
-rw-r--r-- | wgpu/Cargo.toml | 1 | ||||
-rw-r--r-- | wgpu/src/image/raster.rs | 46 |
2 files changed, 45 insertions, 2 deletions
diff --git a/wgpu/Cargo.toml b/wgpu/Cargo.toml index 4c2a3e42..bee8dd49 100644 --- a/wgpu/Cargo.toml +++ b/wgpu/Cargo.toml @@ -34,6 +34,7 @@ raw-window-handle = "0.3" log = "0.4" guillotiere = "0.6" futures = "0.3" +kamadak-exif = "0.5" # TODO(akavel): cfg(only when jpeg enabled) ? [dependencies.bytemuck] version = "1.4" diff --git a/wgpu/src/image/raster.rs b/wgpu/src/image/raster.rs index d5c62545..2944cc41 100644 --- a/wgpu/src/image/raster.rs +++ b/wgpu/src/image/raster.rs @@ -43,14 +43,20 @@ impl Cache { let memory = match handle.data() { image::Data::Path(path) => { if let Ok(image) = ::image_rs::open(path) { - Memory::Host(image.to_bgra8()) + let orientation = std::fs::File::open(path) + .ok() + .map(std::io::BufReader::new) + .and_then(|mut reader| exif_orientation(&mut reader)); + Memory::Host(fix_orientation(image.to_bgra8(), orientation)) } else { Memory::NotFound } } image::Data::Bytes(bytes) => { if let Ok(image) = ::image_rs::load_from_memory(&bytes) { - Memory::Host(image.to_bgra8()) + let orientation = + exif_orientation(&mut std::io::Cursor::new(bytes)); + Memory::Host(fix_orientation(image.to_bgra8(), orientation)) } else { Memory::Invalid } @@ -132,3 +138,39 @@ impl Cache { self.map.contains_key(&handle.id()) } } + +fn fix_orientation( + mut img: ::image_rs::ImageBuffer<::image_rs::Bgra<u8>, Vec<u8>>, + orientation: Option<u32>, +) -> ::image_rs::ImageBuffer<::image_rs::Bgra<u8>, Vec<u8>> { + use ::image_rs::imageops::*; + match orientation.unwrap_or(1) { + 2 => flip_horizontal_in_place(&mut img), + 3 => rotate180_in_place(&mut img), + 4 => flip_vertical_in_place(&mut img), + 5 => { + img = rotate90(&img); + flip_horizontal_in_place(&mut img); + } + 6 => img = rotate90(&img), + 7 => { + img = rotate90(&img); + flip_vertical_in_place(&mut img); + } + 8 => img = rotate270(&img), + _ => {} + }; + img +} + +// Meaning of the returned value is described e.g. at: +// https://magnushoff.com/articles/jpeg-orientation/ +fn exif_orientation<R>(reader: &mut R) -> Option<u32> +where + R: std::io::BufRead + std::io::Seek, +{ + let exif = ::exif::Reader::new().read_from_container(reader).ok()?; + exif.get_field(::exif::Tag::Orientation, ::exif::In::PRIMARY)? + .value + .get_uint(0) +} |