第一次提交

This commit is contained in:
xin
2025-06-12 09:35:09 +08:00
commit 1aba741f67
16 changed files with 27886 additions and 0 deletions

View File

@ -0,0 +1,7 @@
[package]
name = "iris_rust"
version = "0.1.0"
edition = "2024"
[dependencies]
serde_json = "1.0.140"

View File

@ -0,0 +1,160 @@
use crate::{read, structures::{ImageInfo, OneIRISData, OtherInfo, SpectralData, SpectralInfo, TimeStruct, DATA_TYPE_FLOAT64}, write};
use std::{io::{Cursor, Write}, vec};
pub fn spectral_data_roundtrip() {
// Create sample data
let mut time = TimeStruct::new();
time.year = 2023;
time.month = 6;
time.day = 15;
let mut spectral_data = SpectralData::new();
spectral_data.name = "Sample Spectrum".to_string();
spectral_data.sensor_id = "SENSOR-001".to_string();
spectral_data.collection_time = time;
spectral_data.bands = 256;
spectral_data.spectral_data = vec![0u8; 256];
// Write to buffer
let mut buffer = Vec::new();
write::write_spectral_data(&spectral_data, &mut buffer).unwrap();
// Read back from buffer
let mut reader = Cursor::new(buffer);
let read_data = read::read_spectral_data(&mut reader).unwrap();
// Verify roundtrip
assert_eq!(spectral_data.name, read_data.name);
assert_eq!(spectral_data.bands, read_data.bands);
assert_eq!(spectral_data.spectral_data.len(), read_data.spectral_data.len());
println!("Roundtrip test passed successfully!");
}
pub fn spectral_info_roundtrip() {
// Create sample spectral info
let mut info = SpectralInfo::new();
info.sensor_id = "SENSOR-001".to_string();
info.wave_coeff = [400.0, 0.5, 0.01, 0.001];
// Write to buffer
let mut buffer = Vec::new();
write::write_spectral_info(&info, &mut buffer).unwrap();
// Read back from buffer
let mut reader = Cursor::new(buffer);
let read_info = read::read_spectral_info(&mut reader).unwrap();
// Verify roundtrip
assert_eq!(info.sensor_id, read_info.sensor_id);
assert_eq!(info.wave_coeff, read_info.wave_coeff);
println!("Spectral info roundtrip test passed successfully!");
}
pub fn other_info_roundtrip() {
// Create sample other info
let mut info = OtherInfo::new();
info.info_type = 1;
info.data = vec![1, 2, 3, 4, 5];
// Write to buffer
let mut buffer = Vec::new();
write::write_other_info(&info, &mut buffer).unwrap();
// Read back from buffer
let mut reader = Cursor::new(buffer);
let read_info = read::read_other_info(&mut reader).unwrap();
// Verify roundtrip
assert_eq!(info.info_type, read_info.info_type);
assert_eq!(info.data, read_info.data);
println!("Other info roundtrip test passed successfully!");
}
pub fn image_info_roundtrip() {
// Create sample image info
let mut info = ImageInfo::new();
info.name = "Sample Image".to_string();
info.data_length = 256;
info.image_data = vec![0u8; 256];
// Write to buffer
let mut buffer = Vec::new();
write::write_image_info(&info, &mut buffer).unwrap();
// Read back from buffer
let mut reader = Cursor::new(buffer);
let read_info = read::read_image_info(&mut reader).unwrap();
// Verify roundtrip
assert_eq!(info.name, read_info.name);
assert_eq!(info.data_length, read_info.data_length);
assert_eq!(info.image_data.len(), read_info.image_data.len());
println!("Image info roundtrip test passed successfully!");
}
pub fn read_iris_file_example() {
// Create a test file in memory instead of reading from disk
// let mut test_data = OneIRISData::new();
// // Add some test spectral data
// let mut spectral = SpectralData::new();
// spectral.name = "Test Spectrum".to_string();
// spectral.bands = 256;
// spectral.spectral_data = vec![0u8; 256];
// test_data.spectral_data_section.push(spectral);
// Write to a temporary file
let path = "iris_data_example.iris";
// {
// let file = std::fs::File::create(path).unwrap();
// let mut writer = std::io::BufWriter::new(file);
// // Write magic number
// writer.write_all(&[0x49, 0x52, 0x49, 0x53]).unwrap();
// // Write version
// writer.write_all(&[0x01, 0x00]).unwrap();
// // Write spectral data section
// writer.write_all(&0x00FF00FFu32.to_le_bytes()).unwrap();
// writer.write_all(&(12u64 + 4 + 338 + 8 + 256).to_le_bytes()).unwrap(); // Section length
// writer.write_all(&1u32.to_le_bytes()).unwrap(); // 1 spectral data entry
// write::write_spectral_data(&test_data.spectral_data_section[0], &mut writer).unwrap();
// }
// Now read it back
let mut read=match read::read_iris_file(path) {
Ok(data) => {
println!("Successfully read IRIS file:");
println!("- Spectral Data Entries: {}", data.spectral_data_section.len());
println!("- Spectral Info Entries: {}", data.spectral_info_section.len());
println!("- Other Info Entries: {}", data.other_info_section.len());
println!("- Image Info Entries: {}", data.image_info_section.len());
if data.spectral_data_section.is_empty() {
println!("Note: File appears to be empty or in unexpected format");
}
data
}
Err(e) => {
println!("Failed to read IRIS file: {}", e);
println!("This may be due to:");
println!("1. File not in expected binary format");
println!("2. File created by different version of software");
println!("3. File corruption");
OneIRISData::new()
}
};
let mut aaa=read.spectral_data_section[2].Get_Spectral_Data();
let mut bbb =vec![0f64; 256];
//随机生成一些数据
for i in 0..256 {
bbb[i] = i as f64 * 0.1; // Example data
}
read.spectral_data_section[2].Set_Spectral_Data(bbb,DATA_TYPE_FLOAT64);
let ccc= read.spectral_data_section[2].Get_Spectral_Data();
println!("Spectral Data Length: {}", ccc.len());
write::wirte_iris_data(&read, "output_iris_data1.iris").unwrap();
}

View File

@ -0,0 +1,9 @@
pub mod structures;
pub mod read;
pub mod write;
pub mod examples;
pub use structures::{TimeStruct, SpectralData, SpectralInfo, OtherInfo, ImageInfo, OneIRISData};
pub use read::{read_time, read_spectral_data, read_spectral_info, read_other_info, read_image_info, read_iris_file};
pub use write::*;
pub use examples::{spectral_data_roundtrip, spectral_info_roundtrip};

View File

@ -0,0 +1,28 @@
use iris_rust::examples::{
spectral_data_roundtrip,
spectral_info_roundtrip,
other_info_roundtrip,
image_info_roundtrip,
read_iris_file_example
};
fn main() {
// println!("Running iris_rust examples...");
// println!("\nTesting spectral data...");
// spectral_data_roundtrip();
// println!("\nTesting spectral info...");
// spectral_info_roundtrip();
// println!("\nTesting other info...");
// other_info_roundtrip();
// println!("\nTesting image info...");
// image_info_roundtrip();
println!("\nReading IRIS file...");
read_iris_file_example();
println!("\nAll examples completed successfully!");
}

264
rust/iris_rust/src/read.rs Normal file
View File

@ -0,0 +1,264 @@
use std::io::{Read, Result, BufReader};
use std::fs::File;
use std::convert::TryInto;
use super::structures::{TimeStruct, SpectralData, SpectralInfo, OtherInfo, ImageInfo, OneIRISData};
use serde_json::Value;
pub fn read_time<R: Read>(reader: &mut R) -> Result<TimeStruct> {
let mut buffer = [0u8; 10]; // Corrected buffer size to 10 bytes
reader.read_exact(&mut buffer)?;
Ok(TimeStruct {
time_zone: buffer[0] as i8,
year: u16::from_le_bytes([buffer[1], buffer[2]]),
month: buffer[3],
day: buffer[4],
hour: buffer[5],
minute: buffer[6],
second: buffer[7],
millisecond: u16::from_le_bytes([buffer[8], buffer[9]]), // Indices 8 and 9 are correct for 10-byte buffer
})
}
pub fn read_spectral_info<R: Read>(reader: &mut R) -> Result<SpectralInfo> {
let mut info = SpectralInfo::new();
// Read sensor ID
let mut sensor_buf = [0u8; 50];
reader.read_exact(&mut sensor_buf)?;
info.sensor_id = String::from_utf8_lossy(&sensor_buf).trim_end_matches('\0').to_string();
// Read wave coefficients
for i in 0..4 {
let mut float_buf = [0u8; 8];
reader.read_exact(&mut float_buf)?;
info.wave_coeff[i] = f64::from_le_bytes(float_buf);
}
Ok(info)
}
pub fn read_image_info<R: Read>(reader: &mut R) -> Result<ImageInfo> {
let mut info = ImageInfo::new();
// Read data length
let mut len_buf = [0u8; 8];
reader.read_exact(&mut len_buf)?;
info.data_length = u64::from_le_bytes(len_buf);
// Read name (fixed size 100 bytes)
let mut name_buf = [0u8; 100];
reader.read_exact(&mut name_buf)?;
info.name = String::from_utf8_lossy(&name_buf).trim_end_matches('\0').to_string();
// Read collection time
info.collection_time = read_time(reader)?;
// Read info type
let mut type_buf = [0u8; 1];
reader.read_exact(&mut type_buf)?;
info.info_type = type_buf[0];
let imagedatlenth= info.data_length as u64- 100-10-1; // Adjusted to account for the size of TimeStruct and info_type
// Read image data
info.image_data.resize(imagedatlenth as usize, 0);
reader.read_exact(&mut info.image_data)?;
Ok(info)
}
pub fn read_iris_file(path: &str) -> Result<OneIRISData> {
let file = File::open(path)?;
let mut reader = BufReader::new(file);
// Read and verify magic number
// let mut magic = [0u8; 4];
// reader.read_exact(&mut magic)?;
// if magic != [0x49, 0x52, 0x49, 0x53] { // "IRIS" in ASCII
// return Err(std::io::Error::new(
// std::io::ErrorKind::InvalidData,
// "Not a valid IRIS file"
// ));
// }
let mut iris_data = OneIRISData::new();
// // Read file version
// let mut version = [0u8; 2];
// reader.read_exact(&mut version)?;
// Read sections until EOF
loop {
let mut section_header = [0u8; 12]; // type (4) + length (8)
if reader.read_exact(&mut section_header).is_err() {
break; // EOF reached
}
let section_type = u32::from_le_bytes(section_header[0..4].try_into().unwrap());
let section_length = u64::from_le_bytes(section_header[4..12].try_into().unwrap());
match section_type {
0x00FF00FF => { // Spectral data section
let count = read_section_count(&mut reader)?;
let mut data = Vec::with_capacity(count);
for _ in 0..count {
data.push(read_spectral_data(&mut reader)?);
}
iris_data.spectral_data_section = data;
},
0xFF00FF00 => { // Spectral info section
let count = read_section_count(&mut reader)?;
let mut data = Vec::with_capacity(count);
for _ in 0..count {
let mut tempbuffer = [0u8; 3]; // Adjust size as needed
reader.read_exact(&mut tempbuffer)?;
let lenth = u16::from_le_bytes([tempbuffer[0],tempbuffer[1]]) as usize;
let datatype= u8::from_le_bytes([tempbuffer[2]]);
let mut tempvector = vec![0u8; lenth];
reader.read_exact(&mut tempvector)?;
// Convert to String
let json_string = String::from_utf8(tempvector).unwrap_or_default();
let json_string = json_string.trim_end_matches('\0').to_string();
//print!("JSON String: {}", json_string);
let json:Value = match serde_json::from_str(&json_string){
Ok(json) => json,
Err(e) => {
eprintln!("Error parsing JSON: {}", e);
continue; // Skip this entry if parsing fails
}
}; // Handle parsing error gracefully
//println!("Parsed JSON: {:?}", json);
let mut data_entry = SpectralInfo::new();
data_entry.sensor_id = json.get("SensorId").and_then(Value::as_str).unwrap_or_default().to_string();
data_entry.wave_coeff[0]=json["WaveCoeff"]["a1"].as_f64().unwrap_or(0.0);
data_entry.wave_coeff[1]=json["WaveCoeff"]["a2"].as_f64().unwrap_or(0.0);
data_entry.wave_coeff[2]=json["WaveCoeff"]["a3"].as_f64().unwrap_or(0.0);
data_entry.wave_coeff[3]=json["WaveCoeff"]["a4"].as_f64().unwrap_or(0.0);
data.push(data_entry);
// Parse JSON string
}
iris_data.spectral_info_section = data;
},
0xF0F0F0F0 => { // Other info section
if section_length == 0 {
iris_data.other_info_section = Vec::new(); // Handle empty section
continue; // Skip empty section
}
let count = read_section_count(&mut reader)?;
let mut data = Vec::with_capacity(count);
for _ in 0..count {
data.push(read_other_info(&mut reader)?);
}
iris_data.other_info_section = data;
},
0x0F0F0F0F => { // Image info section
if section_length== 0 {
iris_data.image_info_section= Vec::new(); // Handle empty section
continue; // Skip empty section
}
let count = read_section_count(&mut reader)?;
let mut data = Vec::with_capacity(count);
for _ in 0..count {
data.push(read_image_info(&mut reader)?);
}
iris_data.image_info_section = data;
},
_ => {
// Skip unknown sections
let mut buf = vec![0u8; section_length as usize];
reader.read_exact(&mut buf)?;
}
}
}
Ok(iris_data)
}
fn read_section_count<R: Read>(reader: &mut R) -> Result<usize> {
let mut count_buf = [0u8; 2];
reader.read_exact(&mut count_buf)?;
Ok(u16::from_le_bytes(count_buf) as usize)
}
pub fn read_other_info<R: Read>(reader: &mut R) -> Result<OtherInfo> {
let mut info = OtherInfo::new();
// Read info type
let mut type_buf = [0u8; 1];
reader.read_exact(&mut type_buf)?;
info.info_type = type_buf[0];
// Read data length
let mut len_buf = [0u8; 8];
reader.read_exact(&mut len_buf)?;
let data_len = u64::from_le_bytes(len_buf) as usize;
// Read data
info.data.resize(data_len, 0);
reader.read_exact(&mut info.data)?;
Ok(info)
}
pub fn read_spectral_data<R: Read>(reader: &mut R) -> Result<SpectralData> {
let mut data = SpectralData::new();
// Read fixed-size fields
let mut name_buf = [0u8; 100];
reader.read_exact(&mut name_buf)?;
name_buf[99] = 0; // Ensure null termination
let temp= String::from_utf8_lossy(&name_buf);
data.name = temp.trim_end_matches('\0').to_string();
let mut sensor_buf = [0u8; 50];
reader.read_exact(&mut sensor_buf)?;
data.sensor_id = String::from_utf8_lossy(&sensor_buf).trim_end_matches('\0').to_string();
let mut uint8_buf = [0u8; 1];
reader.read_exact(&mut uint8_buf)?;
data.fiber_id = uint8_buf[0];
data.collection_time = read_time(reader)?;
let mut float_buf = [0u8; 8];
reader.read_exact(&mut float_buf)?;
data.exposure = f64::from_le_bytes(float_buf);
let mut float_buf = [0u8; 4];
reader.read_exact(&mut float_buf)?;
data.gain = f32::from_le_bytes(float_buf);
let mut byte_buf = [0u8; 1];
reader.read_exact(&mut byte_buf)?;
data.data_type = byte_buf[0];
reader.read_exact(&mut byte_buf)?;
data.pixel_size = byte_buf[0];
reader.read_exact(&mut byte_buf)?;
data.ground_type = byte_buf[0];
let mut short_buf = [0u8; 2];
reader.read_exact(&mut short_buf)?;
data.bands = u16::from_le_bytes(short_buf);
reader.read_exact(&mut byte_buf)?;
data.valid_flag = byte_buf[0];
let data_len=data.pixel_size as usize * data.bands as usize;
// Read the length of the spectral_data vector
// let mut len_buf = [0u8; 8];
// reader.read_exact(&mut len_buf)?;
// let data_len = u64::from_le_bytes(len_buf) as usize;
// Read the spectral_data vector
data.spectral_data.resize(data_len, 0);
reader.read_exact(&mut data.spectral_data)?;
Ok(data)
}

View File

@ -0,0 +1,408 @@
pub const DATA_TYPE_UINT8: u8 = 0x10;
pub const DATA_TYPE_INT16: u8 = 0x11;
pub const DATA_TYPE_UINT16: u8 = 0x12;
pub const DATA_TYPE_INT32: u8 = 0x13;
pub const DATA_TYPE_UINT32: u8 = 0x14;
pub const DATA_TYPE_FLOAT32: u8 = 0x20;
pub const DATA_TYPE_FLOAT64: u8 = 0x21;
/* 0 dn 1 rad 2 ref 3 irad 4 califile 5 flat_ref 6 dark_dn 7 flat_dn */
pub const Target_Spectral_Type_DN:u8 = 0x00;
pub const Target_Spectral_Type_Rad:u8 = 0x01;
pub const Target_Spectral_Type_Ref:u8 = 0x02;
pub const Target_Spectral_Type_IRad:u8 = 0x03;
pub const Target_Spectral_Type_CaliFile:u8 = 0x04;
pub const Target_Spectral_Type_FlatRef:u8 = 0x05;
pub const Target_Spectral_Type_DarkDN:u8 = 0x06;
pub const Target_Spectral_Type_FlatDN:u8 = 0x07;
#[derive(Debug, Clone, PartialEq)]
pub struct TimeStruct {
pub time_zone: i8,
pub year: u16,
pub month: u8,
pub day: u8,
pub hour: u8,
pub minute: u8,
pub second: u8,
pub millisecond: u16,
}
impl TimeStruct {
pub fn new() -> Self {
TimeStruct {
time_zone: 0,
year: 0,
month: 1,
day: 1,
hour: 0,
minute: 0,
second: 0,
millisecond: 0,
}
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct SpectralData {
pub name: String,
pub sensor_id: String,
pub fiber_id: u8,
pub collection_time: TimeStruct,
pub exposure: f64,
pub gain: f32,
pub data_type: u8,
pub pixel_size: u8,
pub ground_type: u8,
pub bands: u16,
pub valid_flag: u8,
pub spectral_data: Vec<u8>,
}
impl SpectralData {
pub fn new() -> Self {
SpectralData {
name: String::new(),
sensor_id: String::new(),
fiber_id:0,
collection_time: TimeStruct::new(),
exposure: 0.0,
gain: 0.0,
data_type: 0,
pixel_size: 0,
ground_type: 0,
bands: 0,
valid_flag: 0,
spectral_data: Vec::new(),
}
}
pub fn Get_Spectral_Data(&self)-> Vec<f64> {
let mut retrun_data: Vec<f64> = Vec::new();
let datatype = self.data_type;
let bands = self.bands as usize;
match datatype {
DATA_TYPE_UINT8 => {
// uint8
for i in 0..bands {
retrun_data.push(self.spectral_data[i] as f64);
}
}
DATA_TYPE_INT16 => {
// int16
self.spectral_data.chunks(2).for_each(|chunk| {
if chunk.len() == 2 {
let value = i16::from_le_bytes([chunk[0], chunk[1]]);
retrun_data.push(value as f64);
}
});
}
DATA_TYPE_UINT16 => {
// uint16
self.spectral_data.chunks(2).for_each(|chunk| {
if chunk.len() == 2 {
let value = u16::from_le_bytes([chunk[0], chunk[1]]);
retrun_data.push(value as f64);
}
});
}
DATA_TYPE_INT32 => {
// int32
self.spectral_data.chunks(4).for_each(|chunk| {
if chunk.len() == 4 {
let value = i32::from_le_bytes([
chunk[0],
chunk[1],
chunk[2],
chunk[3],
]);
retrun_data.push(value as f64);
}
});
}
DATA_TYPE_UINT32 => {
// uint32
for i in (0..self.spectral_data.len()).step_by(4) {
let value = u32::from_le_bytes([
self.spectral_data[i],
self.spectral_data[i + 1],
self.spectral_data[i + 2],
self.spectral_data[i + 3],
]);
retrun_data.push(value as f64);
}
}
DATA_TYPE_FLOAT32 => {
// float32
for i in (0..self.spectral_data.len()).step_by(4) {
let value = f32::from_le_bytes([
self.spectral_data[i],
self.spectral_data[i + 1],
self.spectral_data[i + 2],
self.spectral_data[i + 3],
]);
retrun_data.push(value as f64);
}
}
DATA_TYPE_FLOAT64 => {
// float64
for i in (0..self.spectral_data.len()).step_by(8) {
let value = f64::from_le_bytes([
self.spectral_data[i],
self.spectral_data[i + 1],
self.spectral_data[i + 2],
self.spectral_data[i + 3],
self.spectral_data[i + 4],
self.spectral_data[i + 5],
self.spectral_data[i + 6],
self.spectral_data[i + 7],
]);
retrun_data.push(value);
}
}
_ => {
// Unsupported data type
panic!("Unsupported data type: {}", datatype);
}
}
retrun_data
}
pub fn Set_Spectral_Data(&mut self, data: Vec<f64>,datatype: u8) {
self.data_type = datatype;
self.bands = data.len() as u16;
self.spectral_data.clear();
// let datatype = self.data_type;
let bands = self.bands as usize;
match datatype {
DATA_TYPE_UINT8 => {
// uint8
self.pixel_size = 1;
self.spectral_data.clear();
for i in 0..bands {
if i < data.len() {
self.spectral_data.push(data[i] as u8);
} else {
self.spectral_data.push(0);
}
}
}
DATA_TYPE_INT16 => {
// int16
self.pixel_size = 2;
self.spectral_data.clear();
for i in 0..bands {
if i < data.len() {
let value = data[i] as i16;
self.spectral_data.extend_from_slice(&value.to_le_bytes());
} else {
self.spectral_data.extend_from_slice(&[0, 0]);
}
}
}
DATA_TYPE_UINT16 => {
// uint16
self.pixel_size = 2;
self.spectral_data.clear();
for i in 0..bands {
if i < data.len() {
let value = data[i] as u16;
self.spectral_data.extend_from_slice(&value.to_le_bytes());
} else {
self.spectral_data.extend_from_slice(&[0, 0]);
}
}
}
DATA_TYPE_INT32 => {
// int32
self.pixel_size = 4;
self.spectral_data.clear();
for i in 0..bands {
if i < data.len() {
let value = data[i] as i32;
self.spectral_data.extend_from_slice(&value.to_le_bytes());
} else {
self.spectral_data.extend_from_slice(&[0, 0, 0, 0]);
}
}
}
DATA_TYPE_UINT32 => {
// uint32
self.pixel_size = 4;
self.spectral_data.clear();
for i in 0..bands {
if i < data.len() {
let value = data[i] as u32;
self.spectral_data.extend_from_slice(&value.to_le_bytes());
} else {
self.spectral_data.extend_from_slice(&[0, 0, 0, 0]);
}
}
}
DATA_TYPE_FLOAT32 => {
// float32
self.pixel_size = 4;
self.spectral_data.clear();
for i in 0..bands {
if i < data.len() {
let value = data[i] as f32;
self.spectral_data.extend_from_slice(&value.to_le_bytes());
} else {
self.spectral_data.extend_from_slice(&[0, 0, 0, 0]);
}
}
}
DATA_TYPE_FLOAT64 => {
// float64
self.pixel_size = 8;
self.spectral_data.clear();
for i in 0..bands {
if i < data.len() {
let value = data[i];
self.spectral_data.extend_from_slice(&value.to_le_bytes());
} else {
self.spectral_data.extend_from_slice(&[0, 0, 0, 0, 0, 0, 0, 0]);
}
}
}
_ => {
// Unsupported data type
panic!("Unsupported data type: {}", datatype);
}
}
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct OtherInfo {
pub info_type: u8,
pub data: Vec<u8>, // Assuming the data is variable length
}
impl OtherInfo {
pub fn new() -> Self {
OtherInfo {
info_type: 0,
data: Vec::new(),
}
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct OneIRISData {
pub spectral_data_section: Vec<SpectralData>,
pub spectral_info_section: Vec<SpectralInfo>,
pub other_info_section: Vec<OtherInfo>,
pub image_info_section: Vec<ImageInfo>,
}
impl OneIRISData {
pub fn new() -> Self {
OneIRISData {
spectral_data_section: Vec::new(),
spectral_info_section: Vec::new(),
other_info_section: Vec::new(),
image_info_section: Vec::new(),
}
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct SpectralInfo {
pub sensor_id: String,
pub wave_coeff: [f64; 4],
}
impl SpectralInfo {
pub fn new() -> Self {
SpectralInfo {
sensor_id: String::new(),
wave_coeff: [0.0; 4],
}
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct ImageInfo {
pub data_length: u64,
pub name: String,
pub collection_time: TimeStruct,
pub info_type: u8,
pub image_data: Vec<u8>, // Assuming the data is variable length
}
impl ImageInfo {
pub fn new() -> Self {
ImageInfo {
data_length: 0,
name: String::new(),
collection_time: TimeStruct::new(),
info_type: 0,
image_data: Vec::new(),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_time_struct() {
let time = TimeStruct::new();
assert_eq!(time.time_zone, 0);
assert_eq!(time.year, 0);
assert_eq!(time.month, 1);
}
#[test]
fn test_spectral_data() {
let data = SpectralData::new();
assert_eq!(data.name, "");
assert_eq!(data.bands, 0);
assert!(data.spectral_data.is_empty());
}
#[test]
fn test_spectral_info() {
let info = SpectralInfo::new();
assert_eq!(info.sensor_id, "");
assert_eq!(info.wave_coeff, [0.0; 4]);
}
#[test]
fn test_other_info() {
let info = OtherInfo::new();
assert_eq!(info.info_type, 0);
assert!(info.data.is_empty());
}
#[test]
fn test_image_info() {
let info = ImageInfo::new();
assert_eq!(info.data_length, 0);
assert_eq!(info.name, "");
assert!(info.image_data.is_empty());
}
}

254
rust/iris_rust/src/write.rs Normal file
View File

@ -0,0 +1,254 @@
use std::fs::File;
use std::io::{self, Write, Result};
use std::vec;
use serde_json::json;
use crate::write;
use super::structures::{TimeStruct, SpectralData, SpectralInfo, OtherInfo, ImageInfo,OneIRISData};
// Internal writer functions remain the same
fn write_time<W: Write>(time: &TimeStruct, writer: &mut W) -> Result<()> {
writer.write_all(&[time.time_zone as u8])?;
writer.write_all(&time.year.to_le_bytes())?;
writer.write_all(&[time.month])?;
writer.write_all(&[time.day])?;
writer.write_all(&[time.hour])?;
writer.write_all(&[time.minute])?;
writer.write_all(&[time.second])?;
writer.write_all(&time.millisecond.to_le_bytes())?;
Ok(())
}
pub fn write_spectral_info<W: Write>(info: &SpectralInfo, writer: &mut W) -> Result<()> {
// Write sensor ID
let mut sensor_buf = [0u8; 50];
sensor_buf[..info.sensor_id.len().min(49)].copy_from_slice(info.sensor_id.as_bytes());
writer.write_all(&sensor_buf)?;
// Write wave coefficients
for coeff in &info.wave_coeff {
writer.write_all(&coeff.to_le_bytes())?;
}
Ok(())
}
pub fn write_image_info<W: Write>(info: &ImageInfo, writer: &mut W) -> Result<()> {
// Write data length
writer.write_all(&info.data_length.to_le_bytes())?;
// Write name (fixed size 100 bytes)
let mut name_buf = [0u8; 100];
let name_bytes = info.name.as_bytes();
name_buf[..info.name.len().min(99)].copy_from_slice(name_bytes[0..name_bytes.len().min(99)].as_ref());
writer.write_all(&name_buf)?;
// Write collection time
write_time(&info.collection_time, writer)?;
// Write info type
writer.write_all(&[info.info_type])?;
// Write image data
writer.write_all(&info.image_data)?;
Ok(())
}
pub fn write_other_info<W: Write>(info: &OtherInfo, writer: &mut W) -> Result<()> {
// Write info type
writer.write_all(&[info.info_type])?;
// Write data length
writer.write_all(&(info.data.len() as u64).to_le_bytes())?;
// Write data
writer.write_all(&info.data)?;
Ok(())
}
pub fn write_spectral_data<W: Write>(data: &SpectralData, writer: &mut W) -> Result<()> {
// Write fixed-size fields
let mut name_buf = [0u8; 100];
let namebyte= data.name.as_bytes();
name_buf[..data.name.len().min(99)].copy_from_slice(namebyte[0..namebyte.len().min(99)].as_ref());
writer.write_all(&name_buf)?;
let mut sensor_buf = [0u8; 50];
let sensor_id_bytes = data.sensor_id.as_bytes();
sensor_buf[..data.sensor_id.len().min(49)].copy_from_slice(sensor_id_bytes[0..sensor_id_bytes.len().min(49)].as_ref());
writer.write_all(&sensor_buf)?;
writer.write_all(&[data.fiber_id])?;
write_time(&data.collection_time, writer)?;
writer.write_all(&data.exposure.to_le_bytes())?;
writer.write_all(&data.gain.to_le_bytes())?;
writer.write_all(&[data.data_type])?;
writer.write_all(&[data.pixel_size])?;
writer.write_all(&[data.ground_type])?;
writer.write_all(&data.bands.to_le_bytes())?;
writer.write_all(&[data.valid_flag])?;
// // Write the length of the spectral_data vector
// writer.write_all(&(data.spectral_data.len() as u64).to_le_bytes())?;
// Write the spectral_data vector
writer.write_all(&data.spectral_data)?;
Ok(())
}
pub fn caculate_spectral_data_length(data: &Vec<SpectralData>) -> u64 {
let mut lenth:u64 = 0;
//加上u16的长度
lenth += 2; // bands
//加上u8的长度
// let numberofspectral=data.len();
for datatemp in data {
lenth += 100; // name
lenth += 50; // sensor_id
lenth += 1 ; // fiber_id
lenth += 10; // time_zone
lenth += 8; // exposure
lenth += 4; // gain
lenth += 1; // data_type
lenth += 1; // pixel_size
lenth += 1; // ground_type
lenth += 2; // bands
lenth += 1; // valid_flag
lenth += datatemp.spectral_data.len() as u64;
}
lenth
}
pub fn caculate_image_info_length(data: &Vec<ImageInfo>) -> u64 {
let mut lenth: u64 = 0;
if data.is_empty() {
return lenth;
}
lenth +=2;
for info in data {
lenth += 8; // data_length
lenth += 100; // name
lenth += 10; // time_zone
lenth += 1; // info_type
lenth += info.image_data.len() as u64; // image_data length
}
lenth
}
pub fn cacluate_other_info_length(data: &Vec<OtherInfo>) -> (Vec<u8>, u64) {
let mut lenth: u64 = 0;
let mut vecback= Vec::new();
if data.is_empty() {
return (vecback, lenth);
}
// for info in data {
// lenth+=1; // info_type
// lenth+=8; // data length
// lenth += info.data.len() as u64; // data length
// vecback.push(info.info_type);
// vecback.extend_from_slice(&(info.data.len() as u64).to_le_bytes());
// vecback.extend_from_slice(&info.data);
// }
(vecback, lenth)
}
pub fn caculate_spectral_info_length(data: &Vec<SpectralInfo>) -> (Vec<u8>, u64) {
let mut lenth: u64 = 0;
let mut vecback= Vec::new();
if data.is_empty() {
return (vecback, lenth);
}
lenth+=2; // sensor_id
let lenthofinfo=data.len() as u16;
vecback.extend_from_slice(&lenthofinfo.to_le_bytes()); // Number of spectral info entries
for info in data {
lenth+=2;
lenth+=1;
let mut lenthofthisinfo:u16=0;
let json=json!({
"SensorId": info.sensor_id,
"WaveCoeff": {
"a1": info.wave_coeff[0],
"a2": info.wave_coeff[1],
"a3": info.wave_coeff[2],
"a4": info.wave_coeff[3]
}
});
let json_string = serde_json::to_string(&json).unwrap();
let json_bytes = json_string.as_bytes();
lenthofthisinfo= json_bytes.len() as u16+1;
lenth += lenthofthisinfo as u64 ;
// 将长度转换为字节并添加到 vecback
vecback.extend_from_slice(&lenthofthisinfo.to_le_bytes());
vecback.push(0x00); // json 标识
vecback.extend_from_slice(json_bytes);
vecback.push(0x00); // 添加一个字节的0x00
}
(vecback, lenth)
}
pub fn wirte_iris_data(data:&OneIRISData,filepath:&str) -> Result<()> {
let mut file = File::create(filepath)?;
//写入光谱数据header
let SPectralData_Flag:u32=0x00FF00FF;
file.write_all(&SPectralData_Flag.to_le_bytes())?;
let mut sectionlenth: u64 = caculate_spectral_data_length(&data.spectral_data_section);
file.write_all(&(sectionlenth).to_le_bytes())?; // Section length
let numberofspectral=data.spectral_data_section.len() as u16;
file.write_all(&numberofspectral.to_le_bytes())?; // Number of spectral data entries
// Write spectral data section
for spectral_data in &data.spectral_data_section {
write_spectral_data(spectral_data, &mut file)?;
}
// Write section length
// Write spectral info section
let spectral_info_flag: u32 = 0xFF00FF00;
let (spectral_info_vec, spectral_info_length) = caculate_spectral_info_length(&data.spectral_info_section);
file.write_all(&spectral_info_flag.to_le_bytes())?; // Spectral info 区块标识
file.write_all(&spectral_info_length.to_le_bytes())?; // Section length
if spectral_info_length != 0 {
file.write_all(&spectral_info_vec)?; // Write the spectral info section data
}
let other_info_flag: u32 = 0xF0F0F0F0;
let (other_info_vec, other_info_length) = cacluate_other_info_length(&data.other_info_section);
file.write_all(&other_info_flag.to_le_bytes())?; // Other info 区块标识
file.write_all(&other_info_length.to_le_bytes())?; // Section length
if other_info_length != 0 {
file.write_all(&other_info_vec)?; // Write the other info section data
}
let image_info_flag: u32 = 0x0F0F0F0F;
file.write_all(&image_info_flag.to_le_bytes())?; // Image info 区块标识
let image_info_length = caculate_image_info_length(&data.image_info_section);
file.write_all(&image_info_length.to_le_bytes())?; // Section length
if image_info_length != 0 {
let numberofimageinfo = data.image_info_section.len() as u16;
file.write_all(&numberofimageinfo.to_le_bytes())?; // Write the image info section data
// Write image info section
for image_info in &data.image_info_section {
write_image_info(image_info, &mut file)?;
}
}
Ok(())
}

View File

@ -0,0 +1,53 @@
# Iris Format Rust Porting Plan
## Project Structure
```
iris_rust/
├── Cargo.toml
└── src/
├── main.rs
├── structures.rs
├── read.rs
├── write.rs
└── examples.rs
```
## Key Components
```mermaid
graph TD
A[Create Rust Project] --> B[Project Structure]
B --> C[Define Data Structures]
C --> D[Implement Read Functions]
C --> E[Implement Write Functions]
D --> F[Serialization/Deserialization]
E --> F
F --> G[Example Implementation]
G --> H[Testing]
```
## Implementation Steps
1. **Data Structures (structures.rs)**:
- TimeStruct, SpectralData, SpectralInfo, OtherInfo, ImageInfo
- Main IrisData container
2. **Read Functions (read.rs)**:
- Implement read_time, read_spectral_data, etc.
- Use std::io::Read trait
3. **Write Functions (write.rs)**:
- Implement write_time, write_spectral_data, etc.
- Use std::io::Write trait
4. **Example Implementation (examples.rs)**:
- Create sample data
- Write/read roundtrip test
5. **Main Integration (main.rs)**:
- CLI interface
- Example execution
## Key Differences from C
- Pointers replaced with Vec types
- Automatic memory management
- Manual serialization instead of memory casting
- Comprehensive error handling with Result type