about summary refs log tree commit diff
diff options
context:
space:
mode:
authorgennyble <gen@nyble.dev>2023-06-11 12:32:05 -0500
committergennyble <gen@nyble.dev>2023-06-11 12:32:05 -0500
commit575dc25afbb57b30d0496830aa78817d66613b64 (patch)
treeda32c187e9f4ab50efb54e07b697d2290ead062e
parentec6b1351c8cc5720ee4818c42220626175e4df82 (diff)
downloadlri-rs-575dc25afbb57b30d0496830aa78817d66613b64.tar.gz
lri-rs-575dc25afbb57b30d0496830aa78817d66613b64.zip
lri-rs
-rw-r--r--.gitignore3
-rw-r--r--Cargo.toml2
-rw-r--r--lri-rs/.gitignore2
-rw-r--r--lri-rs/Cargo.lock380
-rw-r--r--lri-rs/Cargo.toml16
-rw-r--r--lri-rs/LICENSE21
-rw-r--r--lri-rs/README.md4
-rw-r--r--lri-rs/build.rs52
-rw-r--r--lri-rs/proto/camera_id.proto22
-rw-r--r--lri-rs/proto/camera_module.proto67
-rw-r--r--lri-rs/proto/color_calibration.proto47
-rw-r--r--lri-rs/proto/dead_pixel_map.proto9
-rw-r--r--lri-rs/proto/device_temp.proto11
-rw-r--r--lri-rs/proto/distortion.proto31
-rw-r--r--lri-rs/proto/face_data.proto18
-rw-r--r--lri-rs/proto/flash_calibration.proto12
-rw-r--r--lri-rs/proto/geometric_calibration.proto64
-rw-r--r--lri-rs/proto/gps_data.proto49
-rw-r--r--lri-rs/proto/hot_pixel_map.proto16
-rw-r--r--lri-rs/proto/hw_info.proto64
-rw-r--r--lri-rs/proto/imu_data.proto17
-rw-r--r--lri-rs/proto/lightheader.proto106
-rw-r--r--lri-rs/proto/matrix3x3f.proto15
-rw-r--r--lri-rs/proto/matrix4x4f.proto22
-rw-r--r--lri-rs/proto/mirror_system.proto50
-rw-r--r--lri-rs/proto/point2f.proto8
-rw-r--r--lri-rs/proto/point2i.proto8
-rw-r--r--lri-rs/proto/point3f.proto9
-rw-r--r--lri-rs/proto/proximity_sensors.proto11
-rw-r--r--lri-rs/proto/range2f.proto8
-rw-r--r--lri-rs/proto/rectanglei.proto10
-rw-r--r--lri-rs/proto/sensor_characterization.proto26
-rw-r--r--lri-rs/proto/sensor_type.proto12
-rw-r--r--lri-rs/proto/time_stamp.proto13
-rw-r--r--lri-rs/proto/tof_calibration.proto10
-rw-r--r--lri-rs/proto/view_preferences.proto94
-rw-r--r--lri-rs/proto/vignetting_characterization.proto30
-rw-r--r--lri-rs/src/lib.rs2
-rw-r--r--lri-rs/src/main.rs22
-rw-r--r--src/main.rs99
40 files changed, 1407 insertions, 55 deletions
diff --git a/.gitignore b/.gitignore
index c8e7442..fd7adfe 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,5 +2,8 @@
 *.png
 *.lri_part
 
+# MacOS you exhaust me. Leave me alone
+**/.DS_Store
+
 fordatadog.packed
 afterimg2
\ No newline at end of file
diff --git a/Cargo.toml b/Cargo.toml
index 42afe6a..16cb94e 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -7,7 +7,7 @@ edition = "2021"
 
 [dependencies]
 png = "0.17.8"
-lri-rs = { path = "../lri-rs" }
+lri-rs = { path = "lri-rs" }
 unpacker = { path = "unpacker" }
 rawproc = { git = "https://github.com/eclecticnybles/gaze" }
 rawloader = "0.37.1"
diff --git a/lri-rs/.gitignore b/lri-rs/.gitignore
new file mode 100644
index 0000000..3d74ae9
--- /dev/null
+++ b/lri-rs/.gitignore
@@ -0,0 +1,2 @@
+/target
+src/proto
diff --git a/lri-rs/Cargo.lock b/lri-rs/Cargo.lock
new file mode 100644
index 0000000..74c59a9
--- /dev/null
+++ b/lri-rs/Cargo.lock
@@ -0,0 +1,380 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+[[package]]
+name = "adler"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
+
+[[package]]
+name = "adler32"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "aae1277d39aeec15cb388266ecc24b11c80469deae6067e17a1a7aa9e5c1f234"
+
+[[package]]
+name = "anyhow"
+version = "1.0.38"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "afddf7f520a80dbf76e6f50a35bca42a2331ef227a28b3b6dc5c2e2338d114b1"
+
+[[package]]
+name = "autocfg"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
+
+[[package]]
+name = "bitflags"
+version = "1.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
+
+[[package]]
+name = "bytemuck"
+version = "1.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bed57e2090563b83ba8f83366628ce535a7584c9afa4c9fc0612a03925c6df58"
+
+[[package]]
+name = "byteorder"
+version = "1.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
+
+[[package]]
+name = "bytes"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b700ce4376041dcd0a327fd0097c41095743c4c8af8887265942faf1100bd040"
+
+[[package]]
+name = "cfg-if"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
+
+[[package]]
+name = "color_quant"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b"
+
+[[package]]
+name = "crc32fast"
+version = "1.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "81156fece84ab6a9f2afdb109ce3ae577e42b1228441eded99bd77f627953b1a"
+dependencies = [
+ "cfg-if",
+]
+
+[[package]]
+name = "crossbeam-channel"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dca26ee1f8d361640700bde38b2c37d8c22b3ce2d360e1fc1c74ea4b0aa7d775"
+dependencies = [
+ "cfg-if",
+ "crossbeam-utils",
+]
+
+[[package]]
+name = "crossbeam-deque"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "94af6efb46fef72616855b036a624cf27ba656ffc9be1b9a3c931cfc7749a9a9"
+dependencies = [
+ "cfg-if",
+ "crossbeam-epoch",
+ "crossbeam-utils",
+]
+
+[[package]]
+name = "crossbeam-epoch"
+version = "0.9.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2584f639eb95fea8c798496315b297cf81b9b58b6d30ab066a75455333cf4b12"
+dependencies = [
+ "cfg-if",
+ "crossbeam-utils",
+ "lazy_static",
+ "memoffset",
+ "scopeguard",
+]
+
+[[package]]
+name = "crossbeam-utils"
+version = "0.8.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e7e9d99fa91428effe99c5c6d4634cdeba32b8cf784fc428a2a687f61a952c49"
+dependencies = [
+ "autocfg",
+ "cfg-if",
+ "lazy_static",
+]
+
+[[package]]
+name = "deflate"
+version = "0.8.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "73770f8e1fe7d64df17ca66ad28994a0a623ea497fa69486e14984e715c5d174"
+dependencies = [
+ "adler32",
+ "byteorder",
+]
+
+[[package]]
+name = "either"
+version = "1.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
+
+[[package]]
+name = "gif"
+version = "0.11.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "02efba560f227847cb41463a7395c514d127d4f74fff12ef0137fff1b84b96c4"
+dependencies = [
+ "color_quant",
+ "weezl",
+]
+
+[[package]]
+name = "hermit-abi"
+version = "0.1.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "322f4de77956e22ed0e5032c359a0f1273f1f7f0d79bfa3b8ffbc730d7fbcc5c"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "image"
+version = "0.23.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "24ffcb7e7244a9bf19d35bf2883b9c080c4ced3c07a9895572178cdb8f13f6a1"
+dependencies = [
+ "bytemuck",
+ "byteorder",
+ "color_quant",
+ "gif",
+ "jpeg-decoder",
+ "num-iter",
+ "num-rational",
+ "num-traits",
+ "png",
+ "scoped_threadpool",
+ "tiff",
+]
+
+[[package]]
+name = "jpeg-decoder"
+version = "0.1.22"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "229d53d58899083193af11e15917b5640cd40b29ff475a1fe4ef725deb02d0f2"
+dependencies = [
+ "rayon",
+]
+
+[[package]]
+name = "lazy_static"
+version = "1.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
+
+[[package]]
+name = "libc"
+version = "0.2.88"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "03b07a082330a35e43f63177cc01689da34fbffa0105e1246cf0311472cac73a"
+
+[[package]]
+name = "lri-rs"
+version = "0.1.0"
+dependencies = [
+ "anyhow",
+ "image",
+ "protobuf",
+ "protobuf-codegen-pure",
+ "serde",
+]
+
+[[package]]
+name = "memoffset"
+version = "0.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "157b4208e3059a8f9e78d559edc658e13df41410cb3ae03979c83130067fdd87"
+dependencies = [
+ "autocfg",
+]
+
+[[package]]
+name = "miniz_oxide"
+version = "0.3.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "791daaae1ed6889560f8c4359194f56648355540573244a5448a83ba1ecc7435"
+dependencies = [
+ "adler32",
+]
+
+[[package]]
+name = "miniz_oxide"
+version = "0.4.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a92518e98c078586bc6c934028adcca4c92a53d6a958196de835170a01d84e4b"
+dependencies = [
+ "adler",
+ "autocfg",
+]
+
+[[package]]
+name = "num-integer"
+version = "0.1.44"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db"
+dependencies = [
+ "autocfg",
+ "num-traits",
+]
+
+[[package]]
+name = "num-iter"
+version = "0.1.42"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b2021c8337a54d21aca0d59a92577a029af9431cb59b909b03252b9c164fad59"
+dependencies = [
+ "autocfg",
+ "num-integer",
+ "num-traits",
+]
+
+[[package]]
+name = "num-rational"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "12ac428b1cb17fce6f731001d307d351ec70a6d202fc2e60f7d4c5e42d8f4f07"
+dependencies = [
+ "autocfg",
+ "num-integer",
+ "num-traits",
+]
+
+[[package]]
+name = "num-traits"
+version = "0.2.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290"
+dependencies = [
+ "autocfg",
+]
+
+[[package]]
+name = "num_cpus"
+version = "1.13.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3"
+dependencies = [
+ "hermit-abi",
+ "libc",
+]
+
+[[package]]
+name = "png"
+version = "0.16.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3c3287920cb847dee3de33d301c463fba14dda99db24214ddf93f83d3021f4c6"
+dependencies = [
+ "bitflags",
+ "crc32fast",
+ "deflate",
+ "miniz_oxide 0.3.7",
+]
+
+[[package]]
+name = "protobuf"
+version = "2.22.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "73f72884896d22e0da0e5b266cb9a780b791f6c3b2f5beab6368d6cd4f0dbb86"
+dependencies = [
+ "bytes",
+]
+
+[[package]]
+name = "protobuf-codegen"
+version = "2.22.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e8217a1652dbc91d19c509c558234145faed729191a966896414e5889f62d543"
+dependencies = [
+ "protobuf",
+]
+
+[[package]]
+name = "protobuf-codegen-pure"
+version = "2.22.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1f239d71417bdc5f8d83c07aeb265f911346e5540a1a6c4285f9c3d1966ed6e3"
+dependencies = [
+ "protobuf",
+ "protobuf-codegen",
+]
+
+[[package]]
+name = "rayon"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8b0d8e0819fadc20c74ea8373106ead0600e3a67ef1fe8da56e39b9ae7275674"
+dependencies = [
+ "autocfg",
+ "crossbeam-deque",
+ "either",
+ "rayon-core",
+]
+
+[[package]]
+name = "rayon-core"
+version = "1.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9ab346ac5921dc62ffa9f89b7a773907511cdfa5490c572ae9be1be33e8afa4a"
+dependencies = [
+ "crossbeam-channel",
+ "crossbeam-deque",
+ "crossbeam-utils",
+ "lazy_static",
+ "num_cpus",
+]
+
+[[package]]
+name = "scoped_threadpool"
+version = "0.1.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1d51f5df5af43ab3f1360b429fa5e0152ac5ce8c0bd6485cae490332e96846a8"
+
+[[package]]
+name = "scopeguard"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
+
+[[package]]
+name = "serde"
+version = "1.0.124"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bd761ff957cb2a45fbb9ab3da6512de9de55872866160b23c25f1a841e99d29f"
+
+[[package]]
+name = "tiff"
+version = "0.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9a53f4706d65497df0c4349241deddf35f84cee19c87ed86ea8ca590f4464437"
+dependencies = [
+ "jpeg-decoder",
+ "miniz_oxide 0.4.4",
+ "weezl",
+]
+
+[[package]]
+name = "weezl"
+version = "0.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4a32b378380f4e9869b22f0b5177c68a5519f03b3454fde0b291455ddbae266c"
diff --git a/lri-rs/Cargo.toml b/lri-rs/Cargo.toml
new file mode 100644
index 0000000..a93f7a3
--- /dev/null
+++ b/lri-rs/Cargo.toml
@@ -0,0 +1,16 @@
+[package]
+name = "lri-rs"
+version = "0.1.0"
+authors = ["Daniel L. Lu <daniel@lawrence.lu>"]
+edition = "2018"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
+protobuf = { version = "2.22.0", features = ["with-bytes"] }
+serde = "1.0"
+image = "0.23.14"
+anyhow = "1.0"
+
+[build-dependencies]
+protobuf-codegen-pure = "2.22.0"
diff --git a/lri-rs/LICENSE b/lri-rs/LICENSE
new file mode 100644
index 0000000..b5ef890
--- /dev/null
+++ b/lri-rs/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2021 Daniel Lawrence Lu
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/lri-rs/README.md b/lri-rs/README.md
new file mode 100644
index 0000000..6bc9c52
--- /dev/null
+++ b/lri-rs/README.md
@@ -0,0 +1,4 @@
+## Hey, hi! This is [dllu/lri-rs](https://github.com/dllu/lri-rs) with an added minimal `lib.rs`.
+
+# lri-rs
+Rust code to deal with .lri files from Light L16 camera
diff --git a/lri-rs/build.rs b/lri-rs/build.rs
new file mode 100644
index 0000000..559ba5c
--- /dev/null
+++ b/lri-rs/build.rs
@@ -0,0 +1,52 @@
+use std::fs;
+
+use protobuf_codegen_pure::Customize;
+use std::path::Path;
+
+fn main() {
+    let proto_dir = "src/proto";
+
+    if Path::new(&proto_dir).exists() {
+        fs::remove_dir_all(&proto_dir).unwrap();
+    }
+    fs::create_dir(&proto_dir).unwrap();
+
+    protobuf_codegen_pure::Codegen::new()
+        .customize(Customize {
+            gen_mod_rs: Some(true),
+            ..Default::default()
+        })
+        .out_dir(proto_dir)
+        .input("proto/camera_id.proto")
+        .input("proto/camera_module.proto")
+        .input("proto/color_calibration.proto")
+        .input("proto/dead_pixel_map.proto")
+        .input("proto/device_temp.proto")
+        .input("proto/distortion.proto")
+        .input("proto/face_data.proto")
+        .input("proto/flash_calibration.proto")
+        .input("proto/geometric_calibration.proto")
+        .input("proto/gps_data.proto")
+        .input("proto/hot_pixel_map.proto")
+        .input("proto/hw_info.proto")
+        .input("proto/imu_data.proto")
+        .input("proto/lightheader.proto")
+        .input("proto/matrix3x3f.proto")
+        .input("proto/matrix4x4f.proto")
+        .input("proto/mirror_system.proto")
+        .input("proto/point2f.proto")
+        .input("proto/point2i.proto")
+        .input("proto/point3f.proto")
+        .input("proto/proximity_sensors.proto")
+        .input("proto/range2f.proto")
+        .input("proto/rectanglei.proto")
+        .input("proto/sensor_characterization.proto")
+        .input("proto/sensor_type.proto")
+        .input("proto/time_stamp.proto")
+        .input("proto/tof_calibration.proto")
+        .input("proto/view_preferences.proto")
+        .input("proto/vignetting_characterization.proto")
+        .include("proto")
+        .run()
+        .unwrap();
+}
diff --git a/lri-rs/proto/camera_id.proto b/lri-rs/proto/camera_id.proto
new file mode 100644
index 0000000..f34e474
--- /dev/null
+++ b/lri-rs/proto/camera_id.proto
@@ -0,0 +1,22 @@
+syntax = "proto2";
+
+package ltpb;
+
+enum CameraID {
+    A1 = 0;
+    A2 = 1;
+    A3 = 2;
+    A4 = 3;
+    A5 = 4;
+    B1 = 5;
+    B2 = 6;
+    B3 = 7;
+    B4 = 8;
+    B5 = 9;
+    C1 = 10;
+    C2 = 11;
+    C3 = 12;
+    C4 = 13;
+    C5 = 14;
+    C6 = 15;
+}
diff --git a/lri-rs/proto/camera_module.proto b/lri-rs/proto/camera_module.proto
new file mode 100644
index 0000000..9506941
--- /dev/null
+++ b/lri-rs/proto/camera_module.proto
@@ -0,0 +1,67 @@
+syntax = "proto2";
+
+package ltpb;
+
+import "camera_id.proto";
+import "point2i.proto";
+import "point2f.proto";
+
+message CameraModule {
+    optional AFInfo af_info = 1;
+    message AFInfo {
+        required AFMode mode = 1;
+        enum AFMode {
+            AUTO = 0;
+        }
+        
+        optional Point2F roi_center = 2;
+        optional float disparity_focus_distance = 3;
+        optional float contrast_focus_distance = 4;
+        optional bool lens_timeout = 5;
+        optional bool mirror_timeout = 6;
+        optional int32 mirror_position = 7;
+    }
+    
+    required CameraID id = 2;
+    optional bool is_enabled = 3 [default = true];
+    optional int32 mirror_position = 4 [default = 0];
+    required int32 lens_position = 5;
+    required float sensor_analog_gain = 7;
+    required uint64 sensor_exposure = 8;
+    
+    required Surface sensor_data_surface = 9;
+    message Surface {
+        required Point2I start = 1;
+        required Point2I size = 2;
+        
+        required FormatType format = 3;
+        enum FormatType {
+            RAW_BAYER_JPEG = 0;
+            RAW_RESERVED_0 = 1;
+            RAW_RESERVED_1 = 2;
+            RAW_RESERVED_2 = 3;
+            RAW_RESERVED_3 = 4;
+            RAW_RESERVED_4 = 5;
+            RAW_RESERVED_5 = 6;
+            RAW_PACKED_10BPP = 7;
+            RAW_PACKED_12BPP = 8;
+            RAW_PACKED_14BPP = 9;
+        }
+        
+        required uint32 row_stride = 4;
+        required uint64 data_offset = 5;
+        optional Point2F data_scale = 6;
+    }
+    
+    optional sint32 sensor_temparature = 10;
+    optional bool sensor_is_horizontal_flip = 11 [default = false];
+    optional bool sensor_is_vertical_flip = 12 [default = false];
+    optional Point2I sensor_bayer_red_override = 13;
+    optional float sensor_digital_gain = 14;
+    optional uint32 frame_index = 15;
+    optional bool sensor_dpc_on = 16 [default = true];
+    optional sint32 sensor_exp_start_offset = 17;
+    optional float sensor_scan_speed = 18;
+    
+    reserved 6;
+}
diff --git a/lri-rs/proto/color_calibration.proto b/lri-rs/proto/color_calibration.proto
new file mode 100644
index 0000000..bef82f7
--- /dev/null
+++ b/lri-rs/proto/color_calibration.proto
@@ -0,0 +1,47 @@
+syntax = "proto2";
+
+package ltpb;
+
+import "matrix3x3f.proto";
+import "point3f.proto";
+import "point2f.proto";
+
+message ColorCalibration {
+    required IlluminantType type = 1;
+    enum IlluminantType {
+        A = 0;
+        D50 = 1;
+        D65 = 2;
+        D75 = 3;
+        F2 = 4;
+        F7 = 5;
+        F11 = 6;
+        TL84 = 7;
+        UNKNOWN = 99;
+    }
+    
+    required Matrix3x3F forward_matrix = 2;
+    required Matrix3x3F color_matrix = 3;
+    required float rg_ratio = 4;
+    required float bg_ratio = 5;
+    repeated Point3F macbeth_data = 6;
+    repeated Point2F illuminant_spd = 7;
+    
+    optional SpectralData spectral_data = 8;
+    message SpectralData {
+        required ChannelFormat format = 1;
+        enum ChannelFormat {
+            MONO = 0;
+            RGB = 1;
+            BAYER_RGGB = 2;
+        }
+        
+        repeated SpectralSensitivity channel_data = 2;
+    }
+    
+    message SpectralSensitivity {
+        required uint32 start = 1;
+        required uint32 end = 2;
+        repeated float data = 3 [packed = true];
+    }
+}
diff --git a/lri-rs/proto/dead_pixel_map.proto b/lri-rs/proto/dead_pixel_map.proto
new file mode 100644
index 0000000..b4df63b
--- /dev/null
+++ b/lri-rs/proto/dead_pixel_map.proto
@@ -0,0 +1,9 @@
+syntax = "proto2";
+
+package ltpb;
+
+message DeadPixelMap {
+    required uint64 data_offset = 1;
+    required uint32 data_size = 2;
+    optional float black_level_threshold = 3;
+}
diff --git a/lri-rs/proto/device_temp.proto b/lri-rs/proto/device_temp.proto
new file mode 100644
index 0000000..1412a82
--- /dev/null
+++ b/lri-rs/proto/device_temp.proto
@@ -0,0 +1,11 @@
+syntax = "proto2";
+
+package ltpb;
+
+message DeviceTemp {
+    optional sint32 sensor_1 = 1;
+    optional sint32 sensor_2 = 2;
+    optional sint32 sensor_3 = 3;
+    optional sint32 sensor_4 = 4;
+    optional sint32 flex_sensor_1 = 5;
+}
diff --git a/lri-rs/proto/distortion.proto b/lri-rs/proto/distortion.proto
new file mode 100644
index 0000000..cdd8f33
--- /dev/null
+++ b/lri-rs/proto/distortion.proto
@@ -0,0 +1,31 @@
+syntax = "proto2";
+
+package ltpb;
+
+import "point2f.proto";
+import "rectanglei.proto";
+
+message Distortion {
+    optional Polynomial polynomial = 1;
+    message Polynomial {
+        required Point2F distortion_center = 1;
+        required Point2F normalization = 2;
+        repeated float coeffs = 3 [packed = true];
+        optional float fit_cost = 4;
+        optional RectangleI valid_roi = 5;
+    }
+    
+    optional CRA cra = 2;
+    message CRA {
+        required Point2F distortion_center = 1;
+        required float sensor_distance = 2;
+        required float exit_pupil_distance = 3;
+        required float pixel_size = 4;
+        repeated Point2F cra = 5;
+        repeated Point2F coeffs = 6;
+        optional float fit_cost = 7;
+        optional RectangleI valid_roi = 8;
+        optional float lens_hall_code = 9;
+        optional float distance_hall_ratio = 10;
+    }
+}
diff --git a/lri-rs/proto/face_data.proto b/lri-rs/proto/face_data.proto
new file mode 100644
index 0000000..669970a
--- /dev/null
+++ b/lri-rs/proto/face_data.proto
@@ -0,0 +1,18 @@
+syntax = "proto2";
+
+package ltpb;
+
+import "camera_id.proto";
+import "rectanglei.proto";
+
+message FaceData {
+    required CameraID id = 1;
+    required uint32 frame_index = 2;
+    
+    repeated ROI rois = 3;
+    message ROI {
+        optional uint32 id = 1;
+        optional RectangleI roi = 2;
+        optional float confidence = 3;
+    }
+}
diff --git a/lri-rs/proto/flash_calibration.proto b/lri-rs/proto/flash_calibration.proto
new file mode 100644
index 0000000..1327442
--- /dev/null
+++ b/lri-rs/proto/flash_calibration.proto
@@ -0,0 +1,12 @@
+syntax = "proto2";
+
+package ltpb;
+
+message FlashCalibration {
+    required float ledcool_lux = 1;
+    required float ledcool_max_lumens = 2;
+    required float ledcool_cct = 3;
+    required float ledwarm_lux = 4;
+    required float ledwarm_max_lumens = 5;
+    required float ledwarm_cct = 6;
+}
diff --git a/lri-rs/proto/geometric_calibration.proto b/lri-rs/proto/geometric_calibration.proto
new file mode 100644
index 0000000..d89d2e7
--- /dev/null
+++ b/lri-rs/proto/geometric_calibration.proto
@@ -0,0 +1,64 @@
+syntax = "proto2";
+
+package ltpb;
+
+import "mirror_system.proto";
+import "matrix3x3f.proto";
+import "point3f.proto";
+import "distortion.proto";
+import "range2f.proto";
+import "device_temp.proto";
+import "point2f.proto";
+
+message GeometricCalibration {
+    optional MirrorType mirror_type = 1;
+    enum MirrorType {
+        NONE = 0;
+        GLUED = 1;
+        MOVABLE = 2;
+    }
+    
+    repeated CalibrationFocusBundle per_focus_calibration = 2;
+    message CalibrationFocusBundle {
+        required float focus_distance = 1;
+        optional Intrinsics intrinsics = 2;
+        optional Extrinsics extrinsics = 3;
+        optional sint32 sensor_temp = 4;
+        optional DeviceTemp device_temp = 5;
+        optional float focus_hall_code = 6;
+    }
+    
+    optional Distortion distortion = 3;
+    optional Range2F lens_hall_code_range = 4;
+    optional Range2F focus_distance_range = 5;
+    
+    optional AngleOpticalCenterMapping angle_optical_center_mapping = 6;
+    message AngleOpticalCenterMapping {
+        required Point2F center_start = 1;
+        required Point2F center_end = 2;
+        required float angle_offset = 3;
+        required float t_scale = 4;
+        required float t_offset = 5;
+    }
+    
+    message Intrinsics {
+        required Matrix3x3F k_mat = 1;
+        optional float rms_error = 2;
+    }
+    
+    message Extrinsics {
+        optional CanonicalFormat canonical = 1;
+        message CanonicalFormat {
+            required Matrix3x3F rotation = 1;
+            required Point3F translation = 2;
+            optional float stereo_error = 3;
+            optional float reprojection_error = 4;
+        }
+        
+        optional MovableMirrorFormat moveable_mirror = 2;
+        message MovableMirrorFormat {
+            optional MirrorSystem mirror_system = 1;
+            optional MirrorActuatorMapping mirror_actuator_mapping = 2;
+        }
+    }
+}
diff --git a/lri-rs/proto/gps_data.proto b/lri-rs/proto/gps_data.proto
new file mode 100644
index 0000000..bc57f14
--- /dev/null
+++ b/lri-rs/proto/gps_data.proto
@@ -0,0 +1,49 @@
+syntax = "proto2";
+
+package ltpb;
+
+message GPSData {
+    optional double latitude = 1;
+    optional double longitude = 2;
+    optional uint64 timestamp = 3;
+    optional double dop = 4;
+    
+    optional Track track = 5;
+    message Track {
+        required double value = 1;
+        required ReferenceNorth ref = 2;
+    }
+    
+    optional Heading heading = 6;
+    message Heading {
+        required double value = 1;
+        required ReferenceNorth ref = 2;
+    }
+    
+    optional Altitude altitude = 7;
+    message Altitude {
+        required double value = 1;
+        required ReferenceAltitude ref = 2;
+    }
+    
+    optional double speed = 8;
+    
+    optional ProcessingMethod processing_method = 9;
+    enum ProcessingMethod {
+        PROCESSING_METHOD_UNKNOWN = 0;
+        PROCESSING_METHOD_GPS = 1;
+        PROCESSING_METHOD_CELLID = 2;
+        PROCESSING_METHOD_WLAN = 3;
+        PROCESSING_METHOD_MANUAL = 4;
+        PROCESSING_METHOD_FUSED = 5;
+    }
+    
+    enum ReferenceNorth {
+        REFERENCE_NORTH_MAGNETIC = 0;
+        REFERENCE_NORTH_TRUE = 1;
+    }
+    
+    enum ReferenceAltitude {
+        REFERENCE_ALTITUDE_SEA_LEVEL = 0;
+    }
+}
diff --git a/lri-rs/proto/hot_pixel_map.proto b/lri-rs/proto/hot_pixel_map.proto
new file mode 100644
index 0000000..4cd53dc
--- /dev/null
+++ b/lri-rs/proto/hot_pixel_map.proto
@@ -0,0 +1,16 @@
+syntax = "proto2";
+
+package ltpb;
+
+message HotPixelMap {
+    repeated HotPixelMeasurement data = 1;
+    message HotPixelMeasurement {
+        required uint64 data_offset = 1;
+        required uint32 data_size = 2;
+        required uint32 data_exposure = 3;
+        required int32 sensor_temparature = 4;
+        required float sensor_gain = 5;
+        optional float pixel_variance = 6;
+        optional float threshold = 7;
+    }
+}
diff --git a/lri-rs/proto/hw_info.proto b/lri-rs/proto/hw_info.proto
new file mode 100644
index 0000000..70bd90f
--- /dev/null
+++ b/lri-rs/proto/hw_info.proto
@@ -0,0 +1,64 @@
+syntax = "proto2";
+
+package ltpb;
+
+import "sensor_type.proto";
+import "camera_id.proto";
+
+message CameraModuleHwInfo {
+    required CameraID id = 1;
+    required SensorType sensor = 2;
+    
+    optional LensType lens = 3 [default = LENS_UNKNOWN];
+    enum LensType {
+        LENS_UNKNOWN = 0;
+        LENS_SHOWIN = 1;
+        LENS_LARGAN = 2;
+        LENS_SUNNY = 3;
+        LENS_KANTATSU = 4;
+    }
+    
+    optional MirrorActuatorType mirror_actuator = 4 [default = MIRROR_ACTUATOR_UNKNOWN];
+    enum MirrorActuatorType {
+        MIRROR_ACTUATOR_UNKNOWN = 0;
+        MIRROR_ACTUATOR_PZT = 1;
+    }
+    
+    optional MirrorType mirror = 5 [default = MIRROR_UNKNOWN];
+    enum MirrorType {
+        MIRROR_UNKNOWN = 0;
+        MIRROR_DIELECTRIC_SNX = 1;
+        MIRROR_SILVER_ZUISHO = 2;
+    }
+    
+    enum LensActuatorType {
+        LENS_ACTUATOR_UNKNOWN = 0;
+        LENS_ACTUATOR_SHICOH = 1;
+        LENS_ACTUATOR_PZT = 2;
+    }
+}
+
+message HwInfo {
+    repeated CameraModuleHwInfo camera = 1;
+    
+    optional FlashType flash = 2 [default = FLASH_UNKNOWN];
+    enum FlashType {
+        FLASH_UNKNOWN = 0;
+        FLASH_OSRAM_CBLPM1 = 1;
+    }
+    
+    optional ToFType tof = 3 [default = TOF_UNKNOWN];
+    enum ToFType {
+        TOF_UNKNOWN = 0;
+        TOF_STMICRO_VL53L0 = 1;
+    }
+    
+    optional ModelType model = 4;
+    enum ModelType {
+        MODEL_P1 = 0;
+        MODEL_P1_1 = 1;
+        MODEL_P2 = 2;
+    }
+    
+    optional string manufacturer = 5;
+}
diff --git a/lri-rs/proto/imu_data.proto b/lri-rs/proto/imu_data.proto
new file mode 100644
index 0000000..7106fa3
--- /dev/null
+++ b/lri-rs/proto/imu_data.proto
@@ -0,0 +1,17 @@
+syntax = "proto2";
+
+package ltpb;
+
+import "point3f.proto";
+
+message IMUData {
+    required uint32 frame_index = 1;
+    
+    repeated Sample accelerometer = 2;
+    message Sample {
+        required uint32 row_idx = 1;
+        required Point3F data = 2;
+    }
+    
+    repeated Sample gyroscope = 3;
+}
diff --git a/lri-rs/proto/lightheader.proto b/lri-rs/proto/lightheader.proto
new file mode 100644
index 0000000..6a729bb
--- /dev/null
+++ b/lri-rs/proto/lightheader.proto
@@ -0,0 +1,106 @@
+syntax = "proto2";
+
+package ltpb;
+
+import "camera_module.proto";
+import "camera_id.proto";
+import "time_stamp.proto";
+import "geometric_calibration.proto";
+import "color_calibration.proto";
+import "sensor_characterization.proto";
+import "vignetting_characterization.proto";
+import "hot_pixel_map.proto";
+import "device_temp.proto";
+import "dead_pixel_map.proto";
+import "tof_calibration.proto";
+import "flash_calibration.proto";
+import "sensor_type.proto";
+import "hw_info.proto";
+import "view_preferences.proto";
+import "proximity_sensors.proto";
+import "imu_data.proto";
+import "gps_data.proto";
+import "face_data.proto";
+
+message FactoryDeviceCalibration {
+    optional FlashCalibration flash = 1;
+    optional ToFCalibration tof = 2;
+    optional TimeStamp time_stamp = 3;
+}
+
+message FactoryModuleCalibration {
+    required CameraID camera_id = 1;
+    repeated ColorCalibration color = 2;
+    optional GeometricCalibration geometry = 3;
+    optional VignettingCharacterization vignetting = 4;
+    optional HotPixelMap hot_pixel_map = 5;
+    optional DeadPixelMap dead_pixel_map = 6;
+    optional TimeStamp time_stamp = 7;
+}
+
+message ColorCalibrationGold {
+    required CameraID camera_id = 1;
+    repeated ColorCalibration data = 2;
+    optional TimeStamp time_stamp = 3;
+}
+
+message SensorData {
+    required SensorType type = 1;
+    required SensorCharacterization data = 2;
+    optional TimeStamp time_stamp = 3;
+}
+
+message FlashData {
+    required Mode mode = 1;
+    enum Mode {
+        NOFLASH = 0;
+        FLASH = 1;
+        TORCH = 2;
+    }
+    
+    optional uint32 ledcool_current = 2;
+    optional uint32 ledwarm_current = 3;
+    optional uint32 flash_duration = 4;
+    optional int32 offset_duration = 5;
+}
+
+message AFDebugInfo {
+    optional bool focus_achieved = 1;
+    optional int32 image_focal_length = 2;
+}
+
+message Compatibility {
+    required uint32 version = 1;
+    repeated string features = 2;
+}
+
+message LightHeader {
+    optional uint64 image_unique_id_low = 1;
+    optional uint64 image_unique_id_high = 2;
+    optional TimeStamp image_time_stamp = 3;
+    optional int32 image_focal_length = 4;
+    optional CameraID image_reference_camera = 5;
+    optional uint64 device_unique_id_low = 6;
+    optional uint64 device_unique_id_high = 7;
+    optional string device_model_name = 8;
+    optional string device_fw_version = 9;
+    optional string device_asic_fw_version = 10;
+    optional DeviceTemp device_temperature = 11;
+    repeated CameraModule modules = 12;
+    repeated FactoryModuleCalibration module_calibration = 13;
+    optional FactoryDeviceCalibration device_calibration = 14;
+    repeated ColorCalibrationGold gold_cc = 15;
+    repeated SensorData sensor_data = 16;
+    optional float tof_range = 17;
+    optional HwInfo hw_info = 18;
+    optional ViewPreferences view_preferences = 19;
+    optional ProximitySensors proximity_sensors = 20;
+    optional FlashData flash_data = 22;
+    repeated IMUData imu_data = 23;
+    optional AFDebugInfo af_info = 24;
+    optional GPSData gps_data = 25;
+    optional Compatibility compatibility = 26;
+    repeated FaceData face_data = 27;
+    
+    reserved 21;
+}
diff --git a/lri-rs/proto/matrix3x3f.proto b/lri-rs/proto/matrix3x3f.proto
new file mode 100644
index 0000000..a1558b2
--- /dev/null
+++ b/lri-rs/proto/matrix3x3f.proto
@@ -0,0 +1,15 @@
+syntax = "proto2";
+
+package ltpb;
+
+message Matrix3x3F {
+    required float x00 = 1;
+    required float x01 = 2;
+    required float x02 = 3;
+    required float x10 = 4;
+    required float x11 = 5;
+    required float x12 = 6;
+    required float x20 = 7;
+    required float x21 = 8;
+    required float x22 = 9;
+}
diff --git a/lri-rs/proto/matrix4x4f.proto b/lri-rs/proto/matrix4x4f.proto
new file mode 100644
index 0000000..de2de61
--- /dev/null
+++ b/lri-rs/proto/matrix4x4f.proto
@@ -0,0 +1,22 @@
+syntax = "proto2";
+
+package ltpb;
+
+message Matrix4x4F {
+    required float x00 = 1;
+    required float x01 = 2;
+    required float x02 = 3;
+    required float x03 = 4;
+    required float x10 = 5;
+    required float x11 = 6;
+    required float x12 = 7;
+    required float x13 = 8;
+    required float x20 = 9;
+    required float x21 = 10;
+    required float x22 = 11;
+    required float x23 = 12;
+    required float x30 = 13;
+    required float x31 = 14;
+    required float x32 = 15;
+    required float x33 = 16;
+}
diff --git a/lri-rs/proto/mirror_system.proto b/lri-rs/proto/mirror_system.proto
new file mode 100644
index 0000000..4bb057e
--- /dev/null
+++ b/lri-rs/proto/mirror_system.proto
@@ -0,0 +1,50 @@
+syntax = "proto2";
+
+package ltpb;
+
+import "matrix3x3f.proto";
+import "point3f.proto";
+import "range2f.proto";
+
+message MirrorSystem {
+    required Point3F real_camera_location = 1;
+    required Matrix3x3F real_camera_orientation = 2;
+    required Point3F rotation_axis = 3;
+    required Point3F point_on_rotation_axis = 4;
+    required float distance_mirror_plane_to_point_on_rotation_axis = 5;
+    required Point3F mirror_normal_at_zero_degrees = 6;
+    required bool flip_img_around_x = 7;
+    required Range2F mirror_angle_range = 8;
+    optional float reprojection_error = 9;
+}
+
+message MirrorActuatorMapping {
+    required TransformationType transformation_type = 1;
+    enum TransformationType {
+        MEAN_STD_NORMALIZE = 0;
+        TAN_HALF_THETA = 1;
+    }
+    
+    required float actuator_length_offset = 2;
+    required float actuator_length_scale = 3;
+    required float mirror_angle_offset = 4;
+    required float mirror_angle_scale = 5;
+    
+    repeated ActuatorAnglePair actuator_angle_pair_vec = 6;
+    message ActuatorAnglePair {
+        required int32 hall_code = 1;
+        required float angle = 2;
+    }
+    
+    required QuadraticModel quadratic_model = 7;
+    message QuadraticModel {
+        required bool use_rplus_for_left_segment = 1;
+        required bool use_rplus_for_right_segment = 2;
+        required float inflection_value = 3;
+        repeated float model_coeffs = 4 [packed = true];
+    }
+    
+    optional float angle_to_hall_code_error = 8;
+    optional float hall_code_to_angle_error = 9;
+    optional Range2F hall_code_range = 10;
+}
diff --git a/lri-rs/proto/point2f.proto b/lri-rs/proto/point2f.proto
new file mode 100644
index 0000000..726d594
--- /dev/null
+++ b/lri-rs/proto/point2f.proto
@@ -0,0 +1,8 @@
+syntax = "proto2";
+
+package ltpb;
+
+message Point2F {
+    required float x = 1;
+    required float y = 2;
+}
diff --git a/lri-rs/proto/point2i.proto b/lri-rs/proto/point2i.proto
new file mode 100644
index 0000000..3da325d
--- /dev/null
+++ b/lri-rs/proto/point2i.proto
@@ -0,0 +1,8 @@
+syntax = "proto2";
+
+package ltpb;
+
+message Point2I {
+    required int32 x = 1;
+    required int32 y = 2;
+}
diff --git a/lri-rs/proto/point3f.proto b/lri-rs/proto/point3f.proto
new file mode 100644
index 0000000..71e5cbd
--- /dev/null
+++ b/lri-rs/proto/point3f.proto
@@ -0,0 +1,9 @@
+syntax = "proto2";
+
+package ltpb;
+
+message Point3F {
+    required float x = 1;
+    required float y = 2;
+    required float z = 3;
+}
diff --git a/lri-rs/proto/proximity_sensors.proto b/lri-rs/proto/proximity_sensors.proto
new file mode 100644
index 0000000..e7c6ab4
--- /dev/null
+++ b/lri-rs/proto/proximity_sensors.proto
@@ -0,0 +1,11 @@
+syntax = "proto2";
+
+package ltpb;
+
+message ProximitySensors {
+    required bool sensor_1 = 1;
+    required bool sensor_2 = 2;
+    required bool sensor_3 = 3;
+    required bool sensor_4 = 4;
+    required bool sensor_5 = 5;
+}
diff --git a/lri-rs/proto/range2f.proto b/lri-rs/proto/range2f.proto
new file mode 100644
index 0000000..8c905fe
--- /dev/null
+++ b/lri-rs/proto/range2f.proto
@@ -0,0 +1,8 @@
+syntax = "proto2";
+
+package ltpb;
+
+message Range2F {
+    required float min_val = 1;
+    required float max_val = 2;
+}
diff --git a/lri-rs/proto/rectanglei.proto b/lri-rs/proto/rectanglei.proto
new file mode 100644
index 0000000..8360ee4
--- /dev/null
+++ b/lri-rs/proto/rectanglei.proto
@@ -0,0 +1,10 @@
+syntax = "proto2";
+
+package ltpb;
+
+message RectangleI {
+    required int32 x = 1;
+    required int32 y = 2;
+    required int32 width = 3;
+    required int32 height = 4;
+}
diff --git a/lri-rs/proto/sensor_characterization.proto b/lri-rs/proto/sensor_characterization.proto
new file mode 100644
index 0000000..d66aa4a
--- /dev/null
+++ b/lri-rs/proto/sensor_characterization.proto
@@ -0,0 +1,26 @@
+syntax = "proto2";
+
+package ltpb;
+
+message SensorCharacterization {
+    required float black_level = 1;
+    required float white_level = 2;
+    optional float cliff_slope = 3;
+    
+    repeated VstNoiseModel vst_model = 4;
+    message VstNoiseModel {
+        required uint32 gain = 1;
+        required float threshold = 2;
+        required float scale = 3;
+        
+        required VstModel red = 4;
+        message VstModel {
+            required float a = 1;
+            required float b = 2;
+        }
+        
+        required VstModel green = 5;
+        required VstModel blue = 6;
+        optional VstModel panchromatic = 7;
+    }
+}
diff --git a/lri-rs/proto/sensor_type.proto b/lri-rs/proto/sensor_type.proto
new file mode 100644
index 0000000..98cc824
--- /dev/null
+++ b/lri-rs/proto/sensor_type.proto
@@ -0,0 +1,12 @@
+syntax = "proto2";
+
+package ltpb;
+
+enum SensorType {
+    SENSOR_UNKNOWN = 0;
+    SENSOR_AR835 = 1;
+    SENSOR_AR1335 = 2;
+    SENSOR_AR1335_MONO = 3;
+    SENSOR_IMX386 = 4;
+    SENSOR_IMX386_MONO = 5;
+}
diff --git a/lri-rs/proto/time_stamp.proto b/lri-rs/proto/time_stamp.proto
new file mode 100644
index 0000000..238eebe
--- /dev/null
+++ b/lri-rs/proto/time_stamp.proto
@@ -0,0 +1,13 @@
+syntax = "proto2";
+
+package ltpb;
+
+message TimeStamp {
+    required uint32 year = 1;
+    required uint32 month = 2;
+    required uint32 day = 3;
+    required uint32 hour = 4;
+    required uint32 minute = 5;
+    required uint32 second = 6;
+    optional sint32 tz_offset = 7;
+}
diff --git a/lri-rs/proto/tof_calibration.proto b/lri-rs/proto/tof_calibration.proto
new file mode 100644
index 0000000..441eb5e
--- /dev/null
+++ b/lri-rs/proto/tof_calibration.proto
@@ -0,0 +1,10 @@
+syntax = "proto2";
+
+package ltpb;
+
+message ToFCalibration {
+    required float offset_distance = 1;
+    required float offset_measurement = 2;
+    required float xtalk_distance = 3;
+    required float xtalk_measurement = 4;
+}
diff --git a/lri-rs/proto/view_preferences.proto b/lri-rs/proto/view_preferences.proto
new file mode 100644
index 0000000..592fc6f
--- /dev/null
+++ b/lri-rs/proto/view_preferences.proto
@@ -0,0 +1,94 @@
+syntax = "proto2";
+
+package ltpb;
+
+import "point2f.proto";
+
+message ViewPreferences {
+    optional float f_number = 1;
+    optional float ev_offset = 2;
+    optional bool disable_cropping = 3;
+    
+    optional HDRMode hdr_mode = 4;
+    enum HDRMode {
+        HDR_MODE_NONE = 0;
+        HDR_MODE_DEFAULT = 1;
+        HDR_MODE_NATURAL = 2;
+        HDR_MODE_SURREAL = 3;
+    }
+    
+    optional ViewPresets view_preset = 5;
+    enum ViewPresets {
+        VIEW_PRESET_NONE = 0;
+        VIEW_PRESET_NATURAL = 1;
+        VIEW_PRESET_FAITHFUL = 2;
+        VIEW_PRESET_LANDSCAPE = 3;
+        VIEW_PRESET_PORTRAIT = 4;
+    }
+    
+    optional SceneMode scene_mode = 6;
+    enum SceneMode {
+        SCENE_MODE_PORTRAIT = 0;
+        SCENE_MODE_LANDSCAPE = 1;
+        SCENE_MODE_SPORT = 2;
+        SCENE_MODE_MACRO = 3;
+        SCENE_MODE_NIGHT = 4;
+        SCENE_MODE_NONE = 5;
+    }
+    
+    optional AWBMode awb_mode = 7;
+    enum AWBMode {
+        AWB_MODE_AUTO = 0;
+        AWB_MODE_DAYLIGHT = 1;
+        AWB_MODE_SHADE = 2;
+        AWB_MODE_CLOUDY = 3;
+        AWB_MODE_TUNGSTEN = 4;
+        AWB_MODE_FLUORESCENT = 5;
+        AWB_MODE_FLASH = 6;
+        AWB_MODE_CUSTOM = 7;
+        AWB_MODE_KELVIN = 8;
+    }
+    
+    optional Orientation orientation = 9;
+    enum Orientation {
+        ORIENTATION_NORMAL = 0;
+        ORIENTATION_ROT90_CW = 1;
+        ORIENTATION_ROT90_CCW = 2;
+        ORIENTATION_ROT90_CW_VFLIP = 3;
+        ORIENTATION_ROT90_CCW_VFLIP = 4;
+        ORIENTATION_VFLIP = 5;
+        ORIENTATION_HFLIP = 6;
+        ORIENTATION_ROT180 = 7;
+    }
+    
+    optional float image_gain = 10;
+    optional uint64 image_integration_time_ns = 11;
+    optional uint32 user_rating = 12;
+    
+    optional AspectRatio aspect_ratio = 13;
+    enum AspectRatio {
+        ASPECT_RATIO_4_3 = 0;
+        ASPECT_RATIO_16_9 = 1;
+    }
+    
+    optional Crop crop = 14;
+    message Crop {
+        required Point2F start = 1;
+        required Point2F size = 2;
+    }
+    
+    optional ChannelGain awb_gains = 15;
+    message ChannelGain {
+        required float r = 1;
+        required float g_r = 2;
+        required float g_b = 3;
+        required float b = 4;
+    }
+    
+    optional bool is_on_tripod = 16;
+    optional float qc_lux_index = 17;
+    optional float display_gain = 18;
+    optional uint64 display_integration_time_ns = 19;
+    
+    reserved 8;
+}
diff --git a/lri-rs/proto/vignetting_characterization.proto b/lri-rs/proto/vignetting_characterization.proto
new file mode 100644
index 0000000..ccf93ec
--- /dev/null
+++ b/lri-rs/proto/vignetting_characterization.proto
@@ -0,0 +1,30 @@
+syntax = "proto2";
+
+package ltpb;
+
+import "matrix4x4f.proto";
+
+message VignettingCharacterization {
+    required CrosstalkModel crosstalk = 1;
+    message CrosstalkModel {
+        required uint32 width = 1;
+        required uint32 height = 2;
+        repeated Matrix4x4F data = 3;
+        repeated float data_packed = 4 [packed = true];
+    }
+    
+    repeated MirrorVignettingModel vignetting = 2;
+    message MirrorVignettingModel {
+        required int32 hall_code = 1;
+        required VignettingModel vignetting = 2;
+    }
+    
+    optional float relative_brightness = 3;
+    optional int32 lens_hall_code = 4;
+    
+    message VignettingModel {
+        required uint32 width = 1;
+        required uint32 height = 2;
+        repeated float data = 3 [packed = true];
+    }
+}
diff --git a/lri-rs/src/lib.rs b/lri-rs/src/lib.rs
new file mode 100644
index 0000000..0a86fab
--- /dev/null
+++ b/lri-rs/src/lib.rs
@@ -0,0 +1,2 @@
+pub mod proto;
+pub use protobuf::Message;
diff --git a/lri-rs/src/main.rs b/lri-rs/src/main.rs
new file mode 100644
index 0000000..1fd2fac
--- /dev/null
+++ b/lri-rs/src/main.rs
@@ -0,0 +1,22 @@
+mod proto;
+
+use std::io::Read;
+
+use protobuf::Message;
+
+use proto::lightheader::LightHeader;
+
+fn read() -> anyhow::Result<()> {
+    let mut f = std::fs::File::open("/home/dllu/pictures/l16/L16_00078.lri")?;
+    let mut buf = Vec::new();
+    f.read_to_end(&mut buf)?;
+
+    let asdf = LightHeader::parse_from_bytes(&buf)?;
+    dbg!(&asdf.get_device_model_name());
+    dbg!(&asdf.get_device_fw_version());
+    Ok(())
+}
+
+fn main() {
+    read().unwrap();
+}
diff --git a/src/main.rs b/src/main.rs
index 7253ef1..172489c 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -52,13 +52,17 @@ fn main() {
 		}
 	}
 
+	// Grabbed, quickly, from the sensor datasheets. (or in the case of the
+	// imx386 on some random website (canwe have a datasheet? shit)).
 	let ar835 = 3264 * 2448;
 	let ar835_6mp = 3264 * 1836;
-	let ar1335_crop = 4160 * 3120;
 	let ar1335 = 4208 * 3120;
 	let imx386 = 4032 * 3024;
 
-	let known_res = vec![ar835, ar835_6mp, ar1335, imx386];
+	// Determined by lak experimentally
+	let ar1335_crop = 4160 * 3120;
+
+	let known_res = vec![ar835, ar835_6mp, ar1335, imx386, ar1335_crop];
 
 	println!("\nFound {} LightHeaders", heads.len());
 
@@ -134,63 +138,50 @@ fn main() {
 		println!("Found stamp in {idx}");
 	}
 
-	println!("\nAttemtping to unpack image in idx2");
-	let head = &heads[1];
-	let msg = body(head, &data);
-	let mut up = Unpacker::new();
-	for idx in (0..16224000).rev() {
-		up.push(msg[idx]);
-	}
-	up.finish();
+	println!("\nAttemtping to unpack image in idx0");
+	let head = &heads[0];
+	let mut msg = body(head, &data);
+	for AHH in 0..2 {
+		let mut up = Unpacker::new();
+		for idx in (0..16224000).rev() {
+			up.push(msg[idx]);
+		}
+		up.finish();
 
-	dump(&msg[..16224000], "fordatadog.packed");
+		dump(&msg[..16224000], "fordatadog.packed");
 
-	let mut imgdata = vec![];
-	for (idx, chnk) in up.out.chunks(2).enumerate() {
-		let mut sixteen = (u16::from_le_bytes([chnk[0], chnk[1]]) as f32 / 1024.0) * 255.0;
+		let mut imgdata = vec![];
+		for (idx, chnk) in up.out.chunks(2).enumerate() {
+			let mut sixteen = (u16::from_le_bytes([chnk[0], chnk[1]]) as f32 / 1024.0) * 255.0;
 
-		// Bad bayer to grayscale (color corrrect)
-		/*let row = idx / 4160;
-		if row % 2 == 0 {
-			if idx % 2 == 0 {
-				sixteen *= 1.35;
-			}
-		} else {
-			if idx % 2 == 1 {
-				sixteen *= 1.95;
-			}
-		}*/
+			imgdata.push(sixteen.min(255.0) as u8);
+		}
 
-		imgdata.push(sixteen.min(255.0) as u8);
-	}
+		let rawimg: Image<u8, BayerRgb> = Image::from_raw_parts(
+			4160,
+			3120,
+			RawMetadata {
+				whitebalance: [1.0, 1.0, 1.35],
+				whitelevels: [1024, 1024, 1024],
+				crop: None,
+				cfa: CFA::new("BGGR"),
+				cam_to_xyz: Matrix3::new(1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0),
+			},
+			imgdata.clone(),
+		);
+		let mut img = rawimg.debayer();
 
-	let rawimg: Image<u8, BayerRgb> = Image::from_raw_parts(
-		4160,
-		3120,
-		RawMetadata {
-			whitebalance: [1.0, 1.0, 1.0],
-			whitelevels: [512, 1024, 768],
-			crop: None,
-			cfa: CFA::new("BGGR"),
-			cam_to_xyz: Matrix3::new(1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0),
-		},
-		imgdata.clone(),
-	);
-	let mut img = rawimg.debayer();
+		for px in img.data.chunks_mut(3) {
+			px[0] = (px[0] as f32 * 1.95).min(255.0) as u8;
+			px[2] = (px[2] as f32 * 1.36).min(255.0) as u8;
+		}
 
-	for px in img.data.chunks_mut(3) {
-		px[0] = (px[0] as f32 * 1.95).min(255.0) as u8;
-		px[2] = (px[2] as f32 * 1.36).min(255.0) as u8;
-	}
+		let png = format!("image_{AHH}.png");
+		make_png(&png, 4160, 3120, ColorType::Rgb, BitDepth::Eight, &img.data);
+		println!("Wrote {png}");
 
-	make_png(
-		"image.png",
-		4160,
-		3120,
-		ColorType::Rgb,
-		BitDepth::Eight,
-		&img.data,
-	);
+		msg = &msg[16224000..]; // + head.header.message_length as usize * 2..];
+	}
 
 	let msg = &msg[16224000..16224000 + head.header.message_length as usize];
 	dump(msg, "afterimg2");
@@ -203,14 +194,14 @@ fn main() {
 	let question = &msg[..4352];
 	let next = &msg[4352..];
 
-	println!(
+	/*println!(
 		"Up out is {} bytes. Expecte {}. Difference {} [work: {:0b} - idx {}]",
 		up.out.len(),
 		ar1335_crop * 2,
 		up.out.len() as isize - (ar1335_crop * 2) as isize,
 		up.work,
 		up.work_idx
-	);
+	);*/
 
 	println!("\nDumping the Message of idx 4");
 	dump_body(&heads[4], &data, "msg4.lri_part");