[niepce: 2/29] fwk+rust: mostly ported exempi.cpp to Rust
- From: Hubert Figuière <hub src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [niepce: 2/29] fwk+rust: mostly ported exempi.cpp to Rust
- Date: Fri, 22 Sep 2017 00:41:53 +0000 (UTC)
commit 0b2ad5a06f0b77e88718bd864292aae77d5a73c6
Author: Hubert Figuière <hub figuiere net>
Date: Sat Jun 3 14:15:00 2017 -0400
fwk+rust: mostly ported exempi.cpp to Rust
src/fwk/mod.rs | 20 ++++
src/fwk/utils/exempi.rs | 277 +++++++++++++++++++++++++++++++++++++++++++++++
src/fwk/utils/mod.rs | 20 ++++
src/lib.rs | 28 ++++-
4 files changed, 339 insertions(+), 6 deletions(-)
---
diff --git a/src/fwk/mod.rs b/src/fwk/mod.rs
new file mode 100644
index 0000000..78c0239
--- /dev/null
+++ b/src/fwk/mod.rs
@@ -0,0 +1,20 @@
+/*
+ * niepce - fwk/mod.rs
+ *
+ * Copyright (C) 2017 Hubert Figuière
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+mod utils;
diff --git a/src/fwk/utils/exempi.rs b/src/fwk/utils/exempi.rs
new file mode 100644
index 0000000..d697940
--- /dev/null
+++ b/src/fwk/utils/exempi.rs
@@ -0,0 +1,277 @@
+/*
+ * niepce - fwk/utils/exempi.rs
+ *
+ * Copyright (C) 2017 Hubert Figuière
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+use std::fs::File;
+use std::io::prelude::*;
+use std::path::Path;
+use exempi;
+use exempi::Xmp;
+
+
+static NIEPCE_XMP_NAMESPACE: &'static str = "http://xmlns.figuiere.net/ns/niepce/1.0";
+static NIEPCE_XMP_NS_PREFIX: &'static str = "niepce";
+static UFRAW_INTEROP_NAMESPACE: &'static str = "http://xmlns.figuiere.net/ns/ufraw_interop/1.0";
+static UFRAW_INTEROP_NS_PREFIX: &'static str = "ufrint";
+
+
+static NS_TIFF: &'static str = "http://ns.adobe.com/tiff/1.0/";
+static NS_XAP: &'static str = "http://ns.adobe.com/xap/1.0/";
+static NS_EXIF: &'static str = "http://ns.adobe.com/exif/1.0/";
+static NS_DC: &'static str = "http://purl.org/dc/elements/1.1/";
+
+pub struct NsDef {
+ ns: String,
+ prefix: String,
+}
+
+pub struct ExempiManager {
+}
+
+impl ExempiManager {
+ pub fn new(namespaces: Option<Vec<NsDef>>) -> ExempiManager {
+ if exempi::init() {
+ exempi::register_namespace(NIEPCE_XMP_NAMESPACE, NIEPCE_XMP_NS_PREFIX);
+ exempi::register_namespace(UFRAW_INTEROP_NAMESPACE, UFRAW_INTEROP_NS_PREFIX);
+ }
+ if let Some(nslist) = namespaces {
+ for nsdef in nslist {
+ // TOOD check the return value
+ exempi::register_namespace(nsdef.ns.as_str(), nsdef.prefix.as_str());
+ }
+ }
+ ExempiManager {}
+ }
+}
+
+impl Drop for ExempiManager {
+ fn drop(&mut self) {
+ exempi::terminate();
+ }
+}
+
+
+pub struct XmpMeta {
+ xmp: Xmp,
+}
+
+
+impl XmpMeta {
+ pub fn new() -> XmpMeta {
+ XmpMeta { xmp: exempi::Xmp::new() }
+ }
+
+ pub fn new_from_file(file: &String, sidecar_only: bool) -> Option<XmpMeta> {
+ if !sidecar_only {
+ let xmpfile = exempi::XmpFile::open_new(file.as_str(), exempi::OPEN_READ);
+ if xmpfile.is_some() {
+ let xmp = xmpfile.unwrap().get_new_xmp();
+ if xmp.is_some() {
+ return Some(XmpMeta { xmp: xmp.unwrap() });
+ }
+ }
+ }
+ let filepath = Path::new(file.as_str());
+ let sidecar = filepath.with_extension("xmp");
+ let sidecaropen = File::open(sidecar);
+ if let Some(mut sidecarfile) = sidecaropen.ok() {
+ let mut sidecarcontent = String::new();
+ let result = sidecarfile.read_to_string(&mut sidecarcontent);
+ if result.ok().is_some() {
+ let mut xmp = exempi::Xmp::new();
+ if xmp.parse(sidecarcontent.into_bytes().as_slice()) {
+ return Some(XmpMeta { xmp: xmp });
+ }
+ }
+ }
+ None
+ }
+
+ pub fn serialize_inline(&self) -> String {
+ if let Some(xmpstr) = self.xmp.serialize_and_format(
+ exempi::SERIAL_OMITPACKETWRAPPER | exempi::SERIAL_OMITALLFORMATTING,
+ 0, "", "", 0) {
+ let buf = String::from(xmpstr.to_str());
+ return buf;
+ }
+ String::new()
+ }
+
+ pub fn serialize(&self) -> String {
+ if let Some(xmpstr) = self.xmp.serialize_and_format(
+ exempi::SERIAL_OMITPACKETWRAPPER, 0, "\n", "", 0) {
+ let buf = String::from(xmpstr.to_str());
+ return buf;
+ }
+ String::new()
+ }
+
+ pub fn unserialize(&mut self, buf: &str) -> bool {
+ self.xmp.parse(buf.as_bytes())
+ }
+
+ pub fn orientation(&self) -> Option<i32> {
+ let mut flags: exempi::PropFlags = exempi::PropFlags::empty();
+ return self.xmp.get_property_i32(NS_TIFF, "Orientation", &mut flags);
+ }
+
+ pub fn label(&self) -> Option<String> {
+ let mut flags: exempi::PropFlags = exempi::PropFlags::empty();
+ if let Some(xmpstring) = self.xmp.get_property(NS_XAP, "Label", &mut flags) {
+ return Some(String::from(xmpstring.to_str()));
+ }
+ None
+ }
+
+ pub fn rating(&self) -> Option<i32> {
+ let mut flags: exempi::PropFlags = exempi::PropFlags::empty();
+ return self.xmp.get_property_i32(NS_XAP, "Rating", &mut flags);
+ }
+
+ pub fn flag(&self) -> Option<i32> {
+ let mut flags: exempi::PropFlags = exempi::PropFlags::empty();
+ return self.xmp.get_property_i32(NIEPCE_XMP_NAMESPACE, "Flag", &mut flags);
+ }
+
+ // XXX need fwk::Date()
+ // pub fn creation_date()
+
+ pub fn creation_date_str(&self) -> Option<String>
+ {
+ let mut flags: exempi::PropFlags = exempi::PropFlags::empty();
+ if let Some(xmpstring) = self.xmp.get_property(NS_EXIF, "DateTimeOriginal", &mut flags) {
+ return Some(String::from(xmpstring.to_str()));
+ }
+ None
+ }
+
+ // pub fn keywords
+}
+
+pub fn gps_coord_from_xmp(xmps: &str) -> Option<f64> {
+ let mut current: &str = xmps;
+ let degs: &str;
+
+ // step 1 - degrees
+ if let Some(sep) = current.find(',') {
+ let (d, remainder) = current.split_at(sep);
+ current = remainder;
+ degs = d;
+ } else {
+ return None;
+ }
+ // step 2 - minutes
+ if current.len() < 1 {
+ return None;
+ }
+ // get rid of the comma
+ let (_, current) = current.split_at(1);
+ let orientation = match current.chars().last() {
+ Some('N') | Some('E') =>
+ 1.0f64,
+ Some('S') | Some('W') =>
+ -1.0f64,
+ _ => return None,
+ };
+
+ // extract minutes. There are two formats
+ let fminutes: f64;
+ if let Some(sep) = current.find(',') {
+ // DD,mm,ss format
+ if sep >= (current.len() - 1) {
+ return None;
+ }
+ if current.len() <= 2 {
+ return None;
+ }
+ let (minutes, seconds) = current.split_at(sep);
+ let (_, seconds) = seconds.split_at(1);
+ let (seconds, _) = seconds.split_at(seconds.len() - 1);
+ if let Ok(m) = minutes.parse::<f64>() {
+ if let Ok(s) = seconds.parse::<f64>() {
+ fminutes = m + (s / 60f64);
+ } else {
+ return None;
+ }
+ } else {
+ return None;
+ }
+ } else {
+ // DD,mm.mm format
+ let (minutes, _) = current.split_at(current.len() - 1);
+ if let Ok(m) = minutes.parse::<f64>() {
+ fminutes = m;
+ } else {
+ return None;
+ }
+ }
+
+ if let Ok(mut deg) = degs.parse::<f64>() {
+ if deg > 180.0 {
+ return None;
+ }
+ deg += fminutes / 60.0;
+ deg *= orientation;
+
+ return Some(deg);
+ }
+ None
+}
+
+
+#[cfg(test)]
+mod tests {
+ #[test]
+ fn gps_coord_from_works() {
+ use super::gps_coord_from_xmp;
+
+ let mut output = gps_coord_from_xmp("foobar");
+ assert!(output.is_none());
+
+ // malformed 1
+ output = gps_coord_from_xmp("45,29.6681666667");
+ assert!(output.is_none());
+
+ // malformed 2
+ output = gps_coord_from_xmp("45,W");
+ assert!(output.is_none());
+
+ // malformed 3
+ output = gps_coord_from_xmp("45,29,N");
+ assert!(output.is_none());
+
+ // out of bounds
+ output = gps_coord_from_xmp("200,29.6681666667N");
+ assert!(output.is_none());
+
+ // well-formed 1
+ output = gps_coord_from_xmp("45,29.6681666667N");
+ assert!(output.is_some());
+ assert_eq!(output.unwrap(), 45.494469444445002181964810006320476531982421875);
+
+ // well-formed 2
+ output = gps_coord_from_xmp("73,38.2871666667W");
+ assert!(output.is_some());
+ assert_eq!(output.unwrap(), -73.6381194444449960201382054947316646575927734375);
+
+ // well-formed 3
+ output = gps_coord_from_xmp("45,29,30.45N");
+ assert!(output.is_some());
+ assert_eq!(output.unwrap(), 45.49179166666666418450404307805001735687255859375);
+ }
+}
diff --git a/src/fwk/utils/mod.rs b/src/fwk/utils/mod.rs
new file mode 100644
index 0000000..fefeea7
--- /dev/null
+++ b/src/fwk/utils/mod.rs
@@ -0,0 +1,20 @@
+/*
+ * niepce - fwk/utils/mod.rs
+ *
+ * Copyright (C) 2017 Hubert Figuière
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+pub mod exempi;
diff --git a/src/lib.rs b/src/lib.rs
index cdfbe1a..fc51214 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,6 +1,22 @@
-#[cfg(test)]
-mod tests {
- #[test]
- fn it_works() {
- }
-}
+/*
+ * niepce - lib.rs
+ *
+ * Copyright (C) 2017 Hubert Figuière
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+extern crate exempi;
+
+pub mod fwk;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]