From 736294124519d736876c7286cae10a73d8e652fe Mon Sep 17 00:00:00 2001 From: "B. Petersen" Date: Mon, 15 Jun 2020 00:32:13 +0200 Subject: [PATCH 1/4] add kamadak-exif crate --- Cargo.lock | 16 ++++++++++++++++ Cargo.toml | 1 + 2 files changed, 17 insertions(+) diff --git a/Cargo.lock b/Cargo.lock index 467759302..e083f7589 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -826,6 +826,7 @@ dependencies = [ "image-meta", "indexmap", "itertools", + "kamadak-exif", "lazy_static", "lettre_email", "libc", @@ -1619,6 +1620,15 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "kamadak-exif" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a5e66d5b5469321038611f7f0e845a48989e4fd54987b6e5bb4c8ae3adbace7" +dependencies = [ + "mutate_once", +] + [[package]] name = "keccak" version = "0.1.0" @@ -1816,6 +1826,12 @@ dependencies = [ "adler32", ] +[[package]] +name = "mutate_once" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16cf681a23b4d0a43fc35024c176437f9dcd818db34e0f42ab456a0ee5ad497b" + [[package]] name = "native-tls" version = "0.2.4" diff --git a/Cargo.toml b/Cargo.toml index 1a51cd505..cdfefa6eb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -33,6 +33,7 @@ serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" chrono = "0.4.6" indexmap = "1.3.0" +kamadak-exif = "0.5" lazy_static = "1.4.0" regex = "1.1.6" rusqlite = { version = "0.23", features = ["bundled"] } From 9307f2d49faa01cc5bcc63a3921f30e449c449aa Mon Sep 17 00:00:00 2001 From: "B. Petersen" Date: Mon, 15 Jun 2020 00:33:50 +0200 Subject: [PATCH 2/4] rotate image pixels, prototype a function to get exif data --- src/blob.rs | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/blob.rs b/src/blob.rs index c417dd129..2946f882e 100644 --- a/src/blob.rs +++ b/src/blob.rs @@ -14,6 +14,7 @@ use thiserror::Error; use crate::config::Config; use crate::constants::*; use crate::context::Context; +use crate::error::Error; use crate::events::Event; use crate::message; @@ -408,7 +409,13 @@ impl<'a> BlobObject<'a> { return Ok(()); } - let img = img.thumbnail(img_wh, img_wh); + let mut img = img.thumbnail(img_wh, img_wh); + match self.get_exif_orientation() { + Ok(90) => img = img.rotate90(), + Ok(180) => img = img.rotate180(), + Ok(270) => img = img.rotate270(), + _ => {} + } img.save(&blob_abs).map_err(|err| BlobError::WriteFailure { blobdir: context.get_blobdir().to_path_buf(), @@ -418,6 +425,10 @@ impl<'a> BlobObject<'a> { Ok(()) } + + pub fn get_exif_orientation(&self) -> Result { + Ok(0) + } } impl<'a> fmt::Display for BlobObject<'a> { From d2320394cab526372926a07d6648ad08fe21377f Mon Sep 17 00:00:00 2001 From: "B. Petersen" Date: Mon, 15 Jun 2020 01:13:11 +0200 Subject: [PATCH 3/4] convert exif orientation to desired pixel rotation --- src/blob.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/blob.rs b/src/blob.rs index 2946f882e..fbf83bae8 100644 --- a/src/blob.rs +++ b/src/blob.rs @@ -427,6 +427,18 @@ impl<'a> BlobObject<'a> { } pub fn get_exif_orientation(&self) -> Result { + let file = std::fs::File::open(self.to_abs_path())?; + let mut bufreader = std::io::BufReader::new(&file); + let exifreader = exif::Reader::new(); + let exif = exifreader.read_from_container(&mut bufreader)?; + if let Some(orientation) = exif.get_field(exif::Tag::Orientation, exif::In::PRIMARY) { + match orientation.value.get_uint(0) { + Some(3) => return Ok(180), + Some(6) => return Ok(90), + Some(8) => return Ok(270), + _ => {} + } + } Ok(0) } } From 519e1c1cd0bc13aa4aaf63b8addad74ca44a14d1 Mon Sep 17 00:00:00 2001 From: "B. Petersen" Date: Mon, 15 Jun 2020 02:18:48 +0200 Subject: [PATCH 4/4] warn about unused orientation values, add a comment about the orientation values --- src/blob.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/blob.rs b/src/blob.rs index fbf83bae8..e412af7cb 100644 --- a/src/blob.rs +++ b/src/blob.rs @@ -410,7 +410,7 @@ impl<'a> BlobObject<'a> { } let mut img = img.thumbnail(img_wh, img_wh); - match self.get_exif_orientation() { + match self.get_exif_orientation(context) { Ok(90) => img = img.rotate90(), Ok(180) => img = img.rotate180(), Ok(270) => img = img.rotate270(), @@ -426,17 +426,19 @@ impl<'a> BlobObject<'a> { Ok(()) } - pub fn get_exif_orientation(&self) -> Result { + pub fn get_exif_orientation(&self, context: &Context) -> Result { let file = std::fs::File::open(self.to_abs_path())?; let mut bufreader = std::io::BufReader::new(&file); let exifreader = exif::Reader::new(); let exif = exifreader.read_from_container(&mut bufreader)?; if let Some(orientation) = exif.get_field(exif::Tag::Orientation, exif::In::PRIMARY) { + // possible orientation values are described at http://sylvana.net/jpegcrop/exif_orientation.html + // we only use rotation, in practise, flipping is not used. match orientation.value.get_uint(0) { Some(3) => return Ok(180), Some(6) => return Ok(90), Some(8) => return Ok(270), - _ => {} + other => warn!(context, "exif orientation value ignored: {:?}", other), } } Ok(0)