summaryrefslogtreecommitdiffstats
path: root/wgpu
diff options
context:
space:
mode:
authorLibravatar Mateusz Czapliński <czapkofan@gmail.com>2021-09-29 19:26:46 +0200
committerLibravatar Mateusz Czapliński <czapkofan@gmail.com>2021-09-30 00:28:56 +0200
commit82e3e316dd49884b06fea3ad3129e23faaa7588a (patch)
tree381279c554913feb693d1e57365df691aaba1eaa /wgpu
parent4d4c61b887e5721d9eff4085052b24722d1aa082 (diff)
downloadiced-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.toml1
-rw-r--r--wgpu/src/image/raster.rs46
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)
+}