第一次提交
This commit is contained in:
10
.gitignore
vendored
Normal file
10
.gitignore
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
/cmake-build-debug-visual-studio/
|
||||
/build/
|
||||
/.vscode/
|
||||
/doc/高光谱数据文件格式规范文档.pdf
|
||||
/rust/iris_rust/target/
|
||||
/rust/iris_rust/iris_data_example.iris
|
||||
/rust/iris_rust/output_iris_data.iris
|
||||
/rust/iris_rust/output_iris_data1.iris
|
||||
/rust/iris_rust/test.iris
|
||||
/rust/iris_rust/Cargo.lock
|
28
CMakeLists.txt
Normal file
28
CMakeLists.txt
Normal file
@ -0,0 +1,28 @@
|
||||
cmake_minimum_required(VERSION 3.10)
|
||||
project(SpectralFormat)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 11)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED True)
|
||||
|
||||
# Include nlohmann/json
|
||||
include_directories(source)
|
||||
include_directories(source/iris_format)
|
||||
include_directories(source/json)
|
||||
# Add the main library
|
||||
add_library(IrisFormat SHARED
|
||||
source/iris_format/iris_deffine.cpp
|
||||
source/iris_format/forwin.cpp
|
||||
)
|
||||
|
||||
# Add the test executable
|
||||
add_executable(test_iris_format tests/test_iris_format.cpp)
|
||||
|
||||
# Link the library and json header to the test executable
|
||||
target_link_libraries(test_iris_format IrisFormat)
|
||||
|
||||
# Add a test case
|
||||
add_test(NAME IrisReadWriteTest COMMAND test_iris_format)
|
||||
|
||||
# Optional: Install the library
|
||||
# install(TARGETS IrisFormat DESTINATION lib)
|
||||
# install(FILES source/IrisFormat.hpp DESTINATION include)
|
131
doc/高光谱数据文件格式规范文档.md
Normal file
131
doc/高光谱数据文件格式规范文档.md
Normal file
@ -0,0 +1,131 @@
|
||||
# 高光谱数据文件格式规范文档(.iris)
|
||||
|
||||
## 1. 文件概述
|
||||
|
||||
本规范定义了一种用于存储高光谱数据及相关信息的二进制文件格式。该格式采用模块化设计,支持灵活扩展,能够高效存储高光谱数据、元数据、预览图像等多种信息。
|
||||
|
||||
通用定义
|
||||
|
||||
```c++
|
||||
struct IRIS_Time_Struct
|
||||
{
|
||||
int8_t timezone; // 时区
|
||||
uint16_t year; // 年
|
||||
uint8_t month; // 月
|
||||
uint8_t day; // 日
|
||||
uint8_t hour; // 时
|
||||
uint8_t minute; // 分
|
||||
uint8_t second; // 秒
|
||||
uint16_t millisecond; // 毫秒
|
||||
};
|
||||
```
|
||||
|
||||
|
||||
|
||||
## 2.根文件结构
|
||||
|
||||
数去分为4个区域分别是 高光谱数据(SpectralData)、高光谱元数据(SpectralInfo)、其他信息(Other)、图片信息(Image)
|
||||
|
||||
| 高光谱数据 | 高光谱元数据 | 其他信息 | 图片信息 |
|
||||
| ---------- | ------------ | -------- | -------- |
|
||||
|
||||
每块区域的存储结构如下:
|
||||
|
||||
|
||||
|
||||
| 数据区标识(4字节) | 数据区长度(8字节) | 数据内容(N字节) |
|
||||
| ---------- | ---------- | --------- |
|
||||
|
||||
其中四块数据区域标识如下
|
||||
|
||||
| SpectralData | 0x 00 ff 00 ff |
|
||||
| ------------ | -------------- |
|
||||
| SpectralInfo | 0x ff 00 ff 00 |
|
||||
| Other | 0x f0 f0 f0 f0 |
|
||||
| Image | 0x0f 0f 0f 0f |
|
||||
|
||||
当某个区域没有数据时标识不能少 此时数据内容长度为0
|
||||
|
||||
## 2.1 高光谱元数据(SpectralInfo)
|
||||
|
||||
info数据采取如下格式进行存储
|
||||
|
||||
| info数量(2字节)n | info1数据长度(2字节) | info1类型(1字节 ) | info1数据(nn字节) | .... | ... | infon数据长度 | infon类型 | infon数据 |
|
||||
| ------------------ | -------------------- | ----------------- | ------------------- | ---- | ---- | ------------- | --------- | --------- |
|
||||
|
||||
其中info数据类型有如下
|
||||
|
||||
| 值 | 类型 | 说明 |
|
||||
| ---- | --------- | ------------------------------------------ |
|
||||
| 0x00 | json | info数据为json字符串二进制存储 |
|
||||
| 0x01 | string | info数据为字符串二进制存储 字符串以逗号分隔key,value |
|
||||
| 0x02 | key:value | 其中info第一个是key的字节数 然后以该字节读取key 以剩余字节读取value |
|
||||
| 0x03 | 波长数组 | 前20个字节是sensor_id 其他字节是float数组 波长数组 |
|
||||
| 其他待定 | | |
|
||||
|
||||
元数据必须包含如下信息
|
||||
|
||||
1、元信息必须包含后续所有光谱数据对应的光谱设备 以sensor_id标识
|
||||
|
||||
3、 波长信息 如果提供的是波长系数 则用json保存 存储结构是 sensor_id--wevainfo--a[0],a[1],a[2],a[3] 如果是波长数组 则用0x03保存 json中可以用IS_Weave_ARR来标识波长信息在0x03中
|
||||
|
||||
4、元数据还应包含环境数据 Environment 信息 至少包含日期(Date)和Time 信息
|
||||
|
||||
##2.2 高光谱数据
|
||||
|
||||
| 光谱数据数量(2字节) | 光谱数据1 | 光谱数据2 | 光谱数据3 | .... | .... | .... | 光谱数据n |
|
||||
| --------------------- | --------- | --------- | --------- | ---- | ---- | ---- | --------- |
|
||||
|
||||
{HH3: 地物DN 白板DN DARK_DN,flat_ref,califile}
|
||||
|
||||
{HH3califlie: califile,DN,lampvalue}
|
||||
|
||||
光谱数据格式如下
|
||||
|
||||
| 项目 | 字节 | 类型 | 说明 |
|
||||
| ------------------ | -------------------------- | ---------------- | ------------------------------------------------------------ |
|
||||
| name | 100 | string | basename_number_type字符串 \0结尾 |
|
||||
| Sensor_id | 50 | string | 字符串 \0结尾 |
|
||||
| 光纤_id | 1 | uint8 | |
|
||||
| Date | sizeof(IRIS_Time_Struct) | IRIS_Time_Struct | 采集日期 |
|
||||
| 曝光时间 (shutter) | 8 | double | 毫秒 |
|
||||
| gain | 4 | float | db |
|
||||
| 数据类型 | 1 | uint8 | 数据类型 见下一个表 |
|
||||
| 数据长度 | 1 | uint8 | 每一个像素数据长度 N |
|
||||
| 地物类型 | 1 | uint8 | 0 dn 1 rad 2 ref 3 irad 4 califile 5 flat_ref 6 dark_dn 6 flat_dn |
|
||||
| 波段数量 | 2 | uint16 | 波段数 Bandnum |
|
||||
| 数据有效标识 | 1 | uint8 | 0 数据有效 |
|
||||
| 光谱数据 | N*Bandnum | 数据类型决定 | |
|
||||
|
||||
数据类型如下
|
||||
|
||||
| 编码值 | 数据类型 | 描述 |
|
||||
| ---- | ------- | ------------------------- |
|
||||
| 0x10 | uint8 | 无符号8位整型 (0-255) |
|
||||
| 0x11 | int16 | 有符号16位整型 (-32,768~32,767) |
|
||||
| 0x12 | uint16 | 无符号16位整型 (0-65,535) |
|
||||
| 0x13 | int32 | 有符号32位整型 |
|
||||
| 0x14 | uint32 | 无符号32位整型 |
|
||||
| 0x20 | float32 | IEEE 754单精度浮点 |
|
||||
| 0x21 | float64 | IEEE 754双精度浮点 |
|
||||
|
||||
## 2.3 Other
|
||||
|
||||
该部分数据与2.1结构一致
|
||||
|
||||
## 2.4 图像信息
|
||||
|
||||
图像部分数据如下
|
||||
|
||||
| 图像个数(2 字节)n | 图像数据1 | 图像数据2 | ... | 图像数据n |
|
||||
| ----------------- | --------- | --------- | ---- | --------- |
|
||||
|
||||
每个图像数据
|
||||
|
||||
| 项目 | 字节 | 类型 | 说明 |
|
||||
| --------- | ------------------------ | ---------------- | ------------------------------- |
|
||||
| 数据长度 | 8 | uint64 | 除了改项以外其他部分的长度 |
|
||||
| name | 100 | string | 字符串 \0结尾 |
|
||||
| Time | sizeof(IRIS_Time_Struct) | IRIS_Time_Struct | 采集时间 |
|
||||
| type | 1 | uint8 | 0 jpg 1 png 2 tiff 3 data。。。 |
|
||||
| imagedata | 数据长度 | | 图像数据 |
|
7
rust/iris_rust/Cargo.toml
Normal file
7
rust/iris_rust/Cargo.toml
Normal file
@ -0,0 +1,7 @@
|
||||
[package]
|
||||
name = "iris_rust"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
serde_json = "1.0.140"
|
160
rust/iris_rust/src/examples.rs
Normal file
160
rust/iris_rust/src/examples.rs
Normal 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();
|
||||
}
|
9
rust/iris_rust/src/lib.rs
Normal file
9
rust/iris_rust/src/lib.rs
Normal 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};
|
28
rust/iris_rust/src/main.rs
Normal file
28
rust/iris_rust/src/main.rs
Normal 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
264
rust/iris_rust/src/read.rs
Normal 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)
|
||||
}
|
408
rust/iris_rust/src/structures.rs
Normal file
408
rust/iris_rust/src/structures.rs
Normal 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
254
rust/iris_rust/src/write.rs
Normal 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(())
|
||||
}
|
53
rust/iris_rust_port_plan.md
Normal file
53
rust/iris_rust_port_plan.md
Normal 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
|
141
source/iris_format/forwin.cpp
Normal file
141
source/iris_format/forwin.cpp
Normal file
@ -0,0 +1,141 @@
|
||||
#include"iris_deffine.h"
|
||||
#include"json/json.hpp"
|
||||
#include<string>
|
||||
#include<vector>
|
||||
using json = nlohmann::json;
|
||||
uint64_t get_Sepctral_Info_to_Byte(Sepctral_Info_Section_Data_Struct *sepctralinfo,uint8_t **retbuffer)
|
||||
{
|
||||
uint8_t *buffer = *retbuffer; // 使用提供的缓冲区指针
|
||||
if(buffer != nullptr)
|
||||
{
|
||||
delete[] buffer; // 释放之前的内存
|
||||
buffer = nullptr; // 将指针置为nullptr
|
||||
}
|
||||
std::vector<uint8_t> buffer_vector; // 使用vector来管理内存
|
||||
|
||||
int number_of_spectral_info = sepctralinfo->SepctralInfoNumber;
|
||||
if (number_of_spectral_info <= 0)
|
||||
{
|
||||
buffer = nullptr; // 如果没有光谱信息,设置buffer为nullptr
|
||||
return 0; // 返回0表示没有光谱信息
|
||||
}
|
||||
for (size_t i = 0; i < number_of_spectral_info; i++)
|
||||
{
|
||||
json j;
|
||||
std::string SensorId=sepctralinfo->SepctralInfoAddressList[i].SensorId;
|
||||
j["SensorId"] =SensorId;
|
||||
j["WaveCoeff"]["a1"] = sepctralinfo->SepctralInfoAddressList[i].WaveCoeff[0];
|
||||
j["WaveCoeff"]["a2"] =sepctralinfo->SepctralInfoAddressList[i].WaveCoeff[1];
|
||||
j["WaveCoeff"]["a3"] = sepctralinfo->SepctralInfoAddressList[i].WaveCoeff[2];
|
||||
j["WaveCoeff"]["a4"] = sepctralinfo->SepctralInfoAddressList[i].WaveCoeff[3];
|
||||
std::string json_str = j.dump();
|
||||
|
||||
uint16_t json_length = strlen(json_str.c_str())+1;
|
||||
|
||||
if (json_length > 0xFFFF)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
uint8_t *tempbuff= new uint8_t[json_length + 3];
|
||||
tempbuff[1] = (json_length >> 8) & 0xFF; // 高字节
|
||||
tempbuff[0] = json_length & 0xFF; // 低字节
|
||||
tempbuff[2] = 0x00; //表示为json
|
||||
// 将json字符串复制到tempbuff中
|
||||
strcpy((char*)tempbuff + 3, json_str.c_str()); // +1 for the type byte
|
||||
// 将tempbuff中的数据添加到buffer_vector中
|
||||
buffer_vector.insert(buffer_vector.end(), tempbuff, tempbuff + json_length + 3);
|
||||
delete[] tempbuff; // 释放临时缓冲区
|
||||
|
||||
/* code */
|
||||
}
|
||||
// 将vector中的数据复制到buffer中
|
||||
uint16_t total_length = buffer_vector.size()+2;
|
||||
|
||||
buffer = new uint8_t[total_length];
|
||||
if (buffer == nullptr)
|
||||
{
|
||||
return 0; // 返回0表示内存分配失败
|
||||
}
|
||||
int16_t spectralnumber =sepctralinfo->SepctralInfoNumber;
|
||||
buffer[1] = (spectralnumber >> 8) & 0xFF; // 高字节
|
||||
buffer[0] = spectralnumber & 0xFF; // 低字节
|
||||
memcpy(buffer + 2, buffer_vector.data(), buffer_vector.size()); // 将vector中的数据复制到buffer中
|
||||
*retbuffer = buffer; // 设置输出缓冲区指针为新分配的缓冲区
|
||||
return total_length; // 返回总长度
|
||||
|
||||
}
|
||||
|
||||
uint64_t get_Other_Info_to_Byte(Other_Info_Section_Data_Struct *otherdata,uint8_t **retbuffer)
|
||||
{
|
||||
uint8_t *buffer = *retbuffer; // 使用提供的缓冲区指针
|
||||
if(buffer != nullptr)
|
||||
{
|
||||
delete[] buffer; // 释放之前的内存
|
||||
buffer = nullptr; // 将指针置为nullptr
|
||||
}
|
||||
std::vector<uint8_t> buffer_vector; // 使用vector来管理内存
|
||||
|
||||
int number_of_spectral_info = otherdata->OtherInfoNumber;
|
||||
if (number_of_spectral_info <= 0)
|
||||
{
|
||||
buffer = nullptr; // 如果没有光谱信息,设置buffer为nullptr
|
||||
return 0; // 返回0表示没有光谱信息
|
||||
}
|
||||
for (size_t i = 0; i < number_of_spectral_info; i++)
|
||||
{
|
||||
json j;
|
||||
uint8_t Type=otherdata->OtherInfoAddressList[i].Type;
|
||||
j["Type"] =Type;
|
||||
// j["WaveCoeff"]["a1"] = otherdata->SepctralInfoAddressList[i].WaveCoeff[0];
|
||||
// j["WaveCoeff"]["a2"] =otherdata->SepctralInfoAddressList[i].WaveCoeff[1];
|
||||
// j["WaveCoeff"]["a3"] = otherdata->SepctralInfoAddressList[i].WaveCoeff[2];
|
||||
// j["WaveCoeff"]["a4"] = otherdata->SepctralInfoAddressList[i].WaveCoeff[3];
|
||||
std::string json_str = j.dump();
|
||||
uint16_t json_length = json_str.length()+1;
|
||||
|
||||
if (json_length > 0xFFFF)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
uint8_t *tempbuff= new uint8_t[json_length + 3];
|
||||
tempbuff[1] = (json_length >> 8) & 0xFF; // 高字节
|
||||
tempbuff[0] = json_length & 0xFF; // 低字节
|
||||
tempbuff[2] = 0x00; //表示为json
|
||||
// 将json字符串复制到tempbuff中
|
||||
strcpy((char*)tempbuff + 3, json_str.c_str()); // +1 for the type byte
|
||||
// 将tempbuff中的数据添加到buffer_vector中
|
||||
buffer_vector.insert(buffer_vector.end(), tempbuff, tempbuff + json_length + 3);
|
||||
delete[] tempbuff; // 释放临时缓冲区
|
||||
|
||||
/* code */
|
||||
}
|
||||
// 将vector中的数据复制到buffer中
|
||||
uint16_t total_length = buffer_vector.size()+2;
|
||||
|
||||
buffer = new uint8_t[total_length];
|
||||
if (buffer == nullptr)
|
||||
{
|
||||
return 0; // 返回0表示内存分配失败
|
||||
}
|
||||
int16_t spectralnumber =otherdata->OtherInfoNumber;
|
||||
buffer[1] = (spectralnumber >> 8) & 0xFF; // 高字节
|
||||
buffer[0] = spectralnumber & 0xFF; // 低字节
|
||||
memcpy(buffer + 2, buffer_vector.data(), buffer_vector.size()); // 将vector中的数据复制到buffer中
|
||||
*retbuffer = buffer; // 设置输出缓冲区指针为新分配的缓冲区
|
||||
return total_length; // 返回总长度
|
||||
|
||||
}
|
||||
|
||||
One_Spectral_Info_Struct Get_spectral_info_from_byte(uint8_t *buffer, size_t length) {
|
||||
One_Spectral_Info_Struct retstruct;
|
||||
std::string json_str(reinterpret_cast<char*>(buffer), length-1);
|
||||
json j = json::parse(json_str, nullptr, false);
|
||||
std::string sensor_id = j["SensorId"].get<std::string>();
|
||||
strcpy(retstruct.SensorId,sensor_id.c_str() );
|
||||
retstruct.WaveCoeff[0] = j["WaveCoeff"]["a1"].get<double>();
|
||||
retstruct.WaveCoeff[1] = j["WaveCoeff"]["a2"].get<double>();
|
||||
retstruct.WaveCoeff[2] = j["WaveCoeff"]["a3"].get<double>();
|
||||
retstruct.WaveCoeff[3] = j["WaveCoeff"]["a4"].get<double>();
|
||||
return retstruct;
|
||||
|
||||
}
|
604
source/iris_format/iris_deffine.cpp
Normal file
604
source/iris_format/iris_deffine.cpp
Normal file
@ -0,0 +1,604 @@
|
||||
#include "iris_deffine.h"
|
||||
#include<string>
|
||||
#ifndef nullptr
|
||||
#define nullptr NULL
|
||||
#endif
|
||||
MyfileControl_Struct *File_control_ptr = nullptr;
|
||||
|
||||
void IRIS_DATA_example() {
|
||||
One_IRIS_DATA_Struct mydata = Create_IRIS_DATA_Struct();
|
||||
//
|
||||
// double plot1[2000]={0.0}; // HH3_IRIS 产生的数据
|
||||
// float plot2[500]={0.0}; // IS3_IRIS 产生的数据
|
||||
// uint16_t plot3[1000]={0};// HH3_IRIS 产生的数据
|
||||
// float plot4[500]={0.0}; // IS2_IRIS 产生的数据
|
||||
//最好不要让指针指向数组 影响destroy函数
|
||||
double *plot1= new double[2000]; // HH3_IRIS 产生的数据
|
||||
float *plot2= new float[500]; // IS3_IRIS 产生的数据
|
||||
uint16_t *plot3= new uint16_t[1000]; // HH3_IRIS 产生的数据
|
||||
float *plot4= new float[500]; // IS2_IRIS 产生的数据
|
||||
//随机产生plot1数据
|
||||
for (int i = 0; i < 2000; i++) {
|
||||
plot1[i] = static_cast<double>(rand() % 1000) / 10.0; // 生成0.0到100.0之间的随机数
|
||||
}
|
||||
//随机产生plot2数据
|
||||
for (int i = 0; i < 500; i++) {
|
||||
plot2[i] = static_cast<float>(rand() % 1000) / 10.0; // 生成0.0到100.0之间的随机数
|
||||
}
|
||||
//随机产生plot3数据
|
||||
for (int i = 0; i < 1000; i++) {
|
||||
plot3[i] = static_cast<uint16_t>(rand() % 1000); // 生成0到999之间的随机数
|
||||
}
|
||||
//随机产生plot4数据
|
||||
for (int i = 0; i < 500; i++) {
|
||||
plot4[i] = static_cast<float>(rand() % 1000) / 10.0; // 生成0.0到100.0之间的随机数
|
||||
}
|
||||
//时间结构体构建
|
||||
|
||||
IRIS_Time_Struct time;
|
||||
time.Year = 2023;
|
||||
time.Month = 10;
|
||||
time.Day = 1;
|
||||
time.Hour = 12;
|
||||
time.Minute = 30;
|
||||
time.Second = 0;
|
||||
|
||||
//光谱数据区域构建
|
||||
mydata.SepctralDataSection.SectionContent.SepctralDataNumber=4;
|
||||
mydata.SepctralDataSection.SectionContent.SepctralDataAddressList = new One_Spectral_Data_Struct[4];
|
||||
///赋值第一个光谱数据
|
||||
One_Spectral_Data_Struct &tempspectradata= mydata.SepctralDataSection.SectionContent.SepctralDataAddressList[0];
|
||||
tempspectradata.CollectionTime= time; // 采集时间
|
||||
tempspectradata.DataType = DATA_TYPE_FLOAT64; // 假设数据类型为0
|
||||
tempspectradata.PixelSize = sizeof(double);
|
||||
tempspectradata.Bands = 2000;
|
||||
tempspectradata.FiberID=1;
|
||||
tempspectradata.SpectralDataAddress = (uint8_t *)plot1;
|
||||
std::string temp="HH3_IRIS";
|
||||
strcpy(tempspectradata.SensorId, temp.c_str());
|
||||
///赋值第二个光谱数据
|
||||
One_Spectral_Data_Struct &tempspectradata1= mydata.SepctralDataSection.SectionContent.SepctralDataAddressList[1];
|
||||
tempspectradata1.CollectionTime= time; // 采集时间
|
||||
tempspectradata1.DataType = DATA_TYPE_FLOAT32; // 假设数据类型为0
|
||||
tempspectradata1.PixelSize = sizeof(float); // 假设像素大小为1000
|
||||
tempspectradata1.Bands = 500; // 假设波段数为1000
|
||||
tempspectradata1.FiberID=1;
|
||||
|
||||
tempspectradata1.SpectralDataAddress = (uint8_t *)plot2;
|
||||
std::string temp1="IS3_IRIS";
|
||||
strcpy(tempspectradata1.SensorId, temp1.c_str());
|
||||
///赋值第三个光谱数据
|
||||
One_Spectral_Data_Struct &tempspectradata2= mydata.SepctralDataSection.SectionContent.SepctralDataAddressList[2];
|
||||
tempspectradata2.CollectionTime= time; // 采集时间
|
||||
tempspectradata2.DataType = DATA_TYPE_INT16; // 假设数据类型为0
|
||||
tempspectradata2.PixelSize = sizeof(uint16_t); // 假设像素大小为1000
|
||||
tempspectradata2.Bands = 500; // 假设波段数为1000
|
||||
tempspectradata2.FiberID=2;
|
||||
tempspectradata2.SpectralDataAddress = (uint8_t *)plot3;
|
||||
std::string temp2="IS2_IRIS";
|
||||
strcpy(tempspectradata2.SensorId, temp2.c_str());
|
||||
///赋值第二个光谱数据
|
||||
One_Spectral_Data_Struct &tempspectradata3= mydata.SepctralDataSection.SectionContent.SepctralDataAddressList[3];
|
||||
tempspectradata3.CollectionTime= time; // 采集时间
|
||||
tempspectradata3.DataType = DATA_TYPE_FLOAT32; // 假设数据类型为0
|
||||
tempspectradata3.PixelSize = sizeof(float); // 假设像素大小为1000
|
||||
tempspectradata3.Bands = 500; // 假设波段数为1000
|
||||
tempspectradata3.FiberID=3;
|
||||
tempspectradata3.SpectralDataAddress = (uint8_t *)plot4;
|
||||
|
||||
strcpy(tempspectradata3.SensorId, temp1.c_str());
|
||||
|
||||
///光谱信息区域构造
|
||||
mydata.SepctralInfoSection.SectionContent.SepctralInfoNumber = 3;
|
||||
mydata.SepctralInfoSection.SectionContent.SepctralInfoAddressList = new One_Spectral_Info_Struct[3];
|
||||
//第一个光谱仪的信息
|
||||
One_Spectral_Info_Struct &tempspectralinfo=mydata.SepctralInfoSection.SectionContent.SepctralInfoAddressList[0];
|
||||
strcpy(tempspectralinfo.SensorId, "HH3_IRIS");
|
||||
tempspectralinfo.WaveCoeff[0] = 0.1;
|
||||
tempspectralinfo.WaveCoeff[1] = 0.2;
|
||||
tempspectralinfo.WaveCoeff[2] = 0.3;
|
||||
tempspectralinfo.WaveCoeff[3] = 0.4;
|
||||
//第二个光谱仪的信息
|
||||
One_Spectral_Info_Struct &tempspectralinfo1=mydata.SepctralInfoSection.SectionContent.SepctralInfoAddressList[1];
|
||||
strcpy(tempspectralinfo1.SensorId, "IS3_IRIS");
|
||||
tempspectralinfo1.WaveCoeff[0] = 0.5;
|
||||
tempspectralinfo1.WaveCoeff[1] = 0.6;
|
||||
tempspectralinfo1.WaveCoeff[2] = 0.7;
|
||||
tempspectralinfo1.WaveCoeff[3] = 0.8;
|
||||
//第三个光谱仪的信息
|
||||
One_Spectral_Info_Struct &tempspectralinfo2=mydata.SepctralInfoSection.SectionContent.SepctralInfoAddressList[2];
|
||||
strcpy(tempspectralinfo2.SensorId, "IS2_IRIS");
|
||||
tempspectralinfo2.WaveCoeff[0] = 0.9;
|
||||
tempspectralinfo2.WaveCoeff[1] = 1.0;
|
||||
tempspectralinfo2.WaveCoeff[2] = 1.1;
|
||||
tempspectralinfo2.WaveCoeff[3] = 1.2;
|
||||
|
||||
|
||||
///其他信息区域构造
|
||||
mydata.OtherInfoSection.SectionContent.OtherInfoNumber = 0;
|
||||
mydata.OtherInfoSection.SectionContent.OtherInfoAddressList = nullptr; // 假设没有其他信息
|
||||
///图像信息区域构造
|
||||
mydata.ImageInfoSection.SectionContent.ImageInfoNumber = 1;
|
||||
// int8_t image[10000]; 用数组会影响destroy 最好动态分配
|
||||
int8_t *image = new int8_t[10000]; // 假设图像数据为10000字节
|
||||
mydata.ImageInfoSection.SectionContent.ImageInfoAddressList = new One_Image_Info_Struct[1];
|
||||
One_Image_Info_Struct &tempimageinfo=mydata.ImageInfoSection.SectionContent.ImageInfoAddressList[0];
|
||||
tempimageinfo.DataLength = 10000+100+sizeof(IRIS_Time_Struct)+1; // 假设图像数据长度为10000
|
||||
strcpy(tempimageinfo.Name, "SampleImage");
|
||||
tempimageinfo.CollectionTime = time;
|
||||
tempimageinfo.Type = 3; // 假设图像类型为1
|
||||
tempimageinfo.ImageDataAddress = (uint8_t *)image; // 假设图像数据地址为image
|
||||
|
||||
if (File_control_ptr!= nullptr) {
|
||||
// 调用写入函数
|
||||
write_IRIS_DATA_Struct_EMB(&mydata, "iris_data_example.iris", *File_control_ptr);
|
||||
One_IRIS_DATA_Struct mydata2= Get_One_IRIS_DATA_From_File("iris_data_example.iris", *File_control_ptr);
|
||||
Destroy_IRIS_DATA_Struct(mydata2);
|
||||
|
||||
Destroy_IRIS_DATA_Struct(mydata);
|
||||
//mydata2.ImageInfoSection.SectionContent.ImageInfoNumber=1;
|
||||
|
||||
} else {
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
void Set_File_Functions( MyfileControl_Struct *File_control)
|
||||
{
|
||||
File_control_ptr = File_control;
|
||||
}
|
||||
void Write_IRIS_DATA_Struct_EMB_NoFUNC( One_IRIS_DATA_Struct *iris_data,std::string Filepath)
|
||||
{
|
||||
if (File_control_ptr == nullptr) {
|
||||
return; // Ensure File_control_ptr is set before proceeding
|
||||
}
|
||||
write_IRIS_DATA_Struct_EMB(iris_data,Filepath,*File_control_ptr);
|
||||
}
|
||||
One_IRIS_DATA_Struct Create_IRIS_DATA_Struct()
|
||||
{
|
||||
One_IRIS_DATA_Struct iris_data;
|
||||
iris_data.SepctralDataSection.SectionFlag = SPECTRAL_DATA_SECTION;
|
||||
iris_data.SepctralDataSection.SectionLength = 0;
|
||||
iris_data.SepctralInfoSection.SectionFlag = SPECTRAL_INFO_SECTION;
|
||||
iris_data.SepctralInfoSection.SectionLength = 0;
|
||||
iris_data.OtherInfoSection.SectionFlag = OTHER_SECTION;
|
||||
iris_data.OtherInfoSection.SectionLength = 0;
|
||||
iris_data.ImageInfoSection.SectionFlag = IMAGE_SECTION;
|
||||
iris_data.ImageInfoSection.SectionLength = 0;
|
||||
iris_data.SepctralDataSection.SectionContent.SepctralDataAddressList = nullptr;
|
||||
iris_data.SepctralInfoSection.SectionContent.SepctralInfoAddressList = nullptr;
|
||||
iris_data.OtherInfoSection.SectionContent.OtherInfoAddressList = nullptr;
|
||||
iris_data.ImageInfoSection.SectionContent.ImageInfoAddressList = nullptr;
|
||||
|
||||
return iris_data;
|
||||
}
|
||||
|
||||
// Helper function to write a section
|
||||
void write_section_emb(SECTIONFLAG flag, uint64_t length, const uint8_t *data, WriteDataFunc write_callback) {
|
||||
write_callback((uint8_t *)(&flag), sizeof(SECTIONFLAG));
|
||||
write_callback((uint8_t *)(&length), sizeof(uint64_t));
|
||||
if (length > 0 && data != nullptr) {
|
||||
write_callback(data, length);
|
||||
}
|
||||
}
|
||||
uint64_t get_Sepctral_Data_to_Byte(Sepctral_Data_Section_Data_Struct *data_section, uint8_t **retbuff) {
|
||||
uint8_t *buff = *retbuff; // Use the provided buffer pointer
|
||||
|
||||
if(buff!= nullptr) {
|
||||
delete[] buff; // Free the buffer if it was allocated
|
||||
buff = nullptr;
|
||||
}
|
||||
|
||||
|
||||
if (data_section == nullptr || data_section->SepctralDataAddressList == nullptr) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint64_t total_length = sizeof(uint16_t); // For SepctralDataNumber
|
||||
|
||||
for (uint16_t i = 0; i < data_section->SepctralDataNumber; ++i) {
|
||||
const One_Spectral_Data_Struct *item = &data_section->SepctralDataAddressList[i];
|
||||
total_length += 100; // Name
|
||||
total_length += 50; // SensorId
|
||||
total_length +=1; // FiberID
|
||||
total_length += sizeof(IRIS_Time_Struct); // CollectionTime
|
||||
total_length += sizeof(double); // Exposure
|
||||
total_length += sizeof(float); // Gain
|
||||
total_length += sizeof(uint8_t); // DataType
|
||||
total_length += sizeof(uint8_t); // PixelSize
|
||||
total_length += sizeof(uint8_t); // GroundType
|
||||
total_length += sizeof(uint16_t); // Bands
|
||||
total_length += sizeof(uint8_t); // ValidFlag
|
||||
total_length += (uint64_t)item->PixelSize * item->Bands; // SpectralData
|
||||
}
|
||||
buff = new uint8_t[total_length];
|
||||
uint16_t spectral_data_number = data_section->SepctralDataNumber;
|
||||
memcpy(buff, &spectral_data_number, sizeof(uint16_t)); // Copy SepctralDataNumber to the buffer
|
||||
uint64_t now_offset = sizeof(uint16_t); // Start after SepctralDataNumber
|
||||
for (uint16_t i = 0; i < data_section->SepctralDataNumber; ++i) {
|
||||
const One_Spectral_Data_Struct *item = &data_section->SepctralDataAddressList[i];
|
||||
memcpy(buff + now_offset, item->Name, 100); // Copy Name
|
||||
now_offset += 100;
|
||||
memcpy(buff + now_offset, item->SensorId, 50); // Copy SensorId
|
||||
now_offset += 50;
|
||||
memcpy(buff + now_offset, &item->FiberID, sizeof(uint8_t)); // Copy FiberID
|
||||
now_offset += sizeof(uint8_t);
|
||||
memcpy(buff + now_offset, &item->CollectionTime, sizeof(IRIS_Time_Struct)); // Copy CollectionTime
|
||||
now_offset += sizeof(IRIS_Time_Struct);
|
||||
memcpy(buff + now_offset, &item->Exposure, sizeof(double)); // Copy Exposure
|
||||
now_offset += sizeof(double);
|
||||
memcpy(buff + now_offset, &item->Gain, sizeof(float)); // Copy Gain
|
||||
now_offset += sizeof(float);
|
||||
memcpy(buff + now_offset, &item->DataType, sizeof(uint8_t)); // Copy DataType
|
||||
now_offset += sizeof(uint8_t);
|
||||
memcpy(buff + now_offset, &item->PixelSize, sizeof(uint8_t)); // Copy PixelSize
|
||||
now_offset += sizeof(uint8_t);
|
||||
memcpy(buff + now_offset, &item->GroundType, sizeof(uint8_t)); // Copy GroundType
|
||||
now_offset += sizeof(uint8_t);
|
||||
memcpy(buff + now_offset, &item->Bands, sizeof(uint16_t)); // Copy Bands
|
||||
now_offset += sizeof(uint16_t);
|
||||
memcpy(buff + now_offset, &item->ValidFlag, sizeof(uint8_t)); // Copy ValidFlag
|
||||
now_offset += sizeof(uint8_t);
|
||||
memcpy(buff + now_offset, item->SpectralDataAddress, (uint64_t)item->PixelSize * item->Bands); // Copy SpectralData
|
||||
now_offset += (uint64_t)item->PixelSize * item->Bands;
|
||||
}
|
||||
if (now_offset != total_length) {
|
||||
// Handle error: not all data was copied
|
||||
delete[] buff; // Free the buffer if it was allocated
|
||||
buff = nullptr;
|
||||
return -2; // Error: Data length mismatch
|
||||
}
|
||||
*retbuff = buff; // Set the output buffer pointer to the allocated buffer
|
||||
return total_length; // Return the total length of the data written to the buffer
|
||||
|
||||
}
|
||||
|
||||
uint64_t Get_Image_Data_to_Byte(const Image_Info_Section_Data_Struct *image_section, uint8_t **retbuff) {
|
||||
|
||||
if (image_section == nullptr || image_section->ImageInfoAddressList == nullptr,image_section->ImageInfoNumber == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint64_t total_length = sizeof(uint16_t); // For ImageInfoNumber
|
||||
|
||||
for (uint16_t i = 0; i < image_section->ImageInfoNumber; ++i) {
|
||||
const One_Image_Info_Struct *item = &image_section->ImageInfoAddressList[i];
|
||||
total_length += sizeof(uint64_t); // DataLength
|
||||
total_length += 100; // Name
|
||||
total_length += sizeof(IRIS_Time_Struct); // CollectionTime
|
||||
total_length += sizeof(uint8_t); // Type
|
||||
total_length += item->DataLength - (100 + sizeof(IRIS_Time_Struct) + sizeof(uint8_t)); // ImageData (DataLength includes Name, Time, Type)
|
||||
}
|
||||
|
||||
uint8_t *buff = new uint8_t[total_length];
|
||||
uint16_t image_info_number = image_section->ImageInfoNumber;
|
||||
memcpy(buff, &image_info_number, sizeof(uint16_t)); // Copy ImageInfoNumber to the buffer
|
||||
uint64_t now_offset = sizeof(uint16_t); // Start after ImageInfoNumber
|
||||
for (uint16_t i = 0; i < image_section->ImageInfoNumber; ++i) {
|
||||
const One_Image_Info_Struct *item = &image_section->ImageInfoAddressList[i];
|
||||
memcpy(buff + now_offset, &item->DataLength, sizeof(uint64_t)); // Copy DataLength
|
||||
now_offset += sizeof(uint64_t);
|
||||
memcpy(buff + now_offset, item->Name, 100); // Copy Name
|
||||
now_offset += 100;
|
||||
memcpy(buff + now_offset, &item->CollectionTime, sizeof(IRIS_Time_Struct)); // Copy CollectionTime
|
||||
now_offset += sizeof(IRIS_Time_Struct);
|
||||
memcpy(buff + now_offset, &item->Type, sizeof(uint8_t)); // Copy Type
|
||||
now_offset += sizeof(uint8_t);
|
||||
memcpy(buff + now_offset, item->ImageDataAddress, item->DataLength - (100 + sizeof(IRIS_Time_Struct) + sizeof(uint8_t))); // Copy ImageData
|
||||
now_offset += item->DataLength - (100 + sizeof(IRIS_Time_Struct) + sizeof(uint8_t));
|
||||
}
|
||||
*retbuff= buff; // Set the output buffer pointer to the allocated buffer
|
||||
return total_length; // Return the total length of the data written to the buffer
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void write_IRIS_DATA_Struct_EMB(One_IRIS_DATA_Struct *iris_data,std::string Filepath, MyfileControl_Struct File_control) {
|
||||
|
||||
if (iris_data == nullptr || File_control.Write_data == nullptr||File_control.open_file == nullptr||File_control.close_file == nullptr) {
|
||||
return; // Handle error: invalid input
|
||||
}
|
||||
File_control.open_file(Filepath, "wb"); // Open the file for writing in binary mode
|
||||
|
||||
|
||||
// Write SpectralData section
|
||||
uint8_t *tempbuff= nullptr;
|
||||
iris_data->SepctralDataSection.SectionLength = get_Sepctral_Data_to_Byte(&iris_data->SepctralDataSection.SectionContent, &tempbuff);
|
||||
write_section_emb(
|
||||
iris_data->SepctralDataSection.SectionFlag,
|
||||
iris_data->SepctralDataSection.SectionLength, // Using SectionLength from the struct
|
||||
tempbuff, // Assuming AddressList points to raw data
|
||||
File_control.Write_data
|
||||
);
|
||||
if (tempbuff != nullptr) {
|
||||
delete[] tempbuff; // Free the temporary buffer if it was allocated
|
||||
tempbuff = nullptr;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Write SpectralInfo section
|
||||
// Based on the ambiguity, assuming SectionLength in the struct is the correct length of the raw data.
|
||||
iris_data->SepctralInfoSection.SectionLength= get_Sepctral_Info_to_Byte(&iris_data->SepctralInfoSection.SectionContent,&tempbuff);
|
||||
write_section_emb(
|
||||
iris_data->SepctralInfoSection.SectionFlag,
|
||||
iris_data->SepctralInfoSection.SectionLength, // Using SectionLength from the struct
|
||||
// Assuming AddressList points to raw data
|
||||
tempbuff,
|
||||
File_control.Write_data
|
||||
);
|
||||
if (tempbuff != nullptr) {
|
||||
delete[] tempbuff; // Free the temporary buffer if it was allocated
|
||||
tempbuff = nullptr;
|
||||
}
|
||||
// Write Other section
|
||||
// Based on the ambiguity, assuming SectionLength in the struct is the correct length of the raw data.
|
||||
iris_data->OtherInfoSection.SectionLength = get_Other_Info_to_Byte(&iris_data->OtherInfoSection.SectionContent, &tempbuff);
|
||||
write_section_emb(
|
||||
iris_data->OtherInfoSection.SectionFlag,
|
||||
iris_data->OtherInfoSection.SectionLength, // Using SectionLength from the struct
|
||||
tempbuff, // Assuming AddressList points to raw data
|
||||
File_control.Write_data
|
||||
);
|
||||
if (tempbuff != nullptr) {
|
||||
delete[] tempbuff; // Free the temporary buffer if it was allocated
|
||||
tempbuff = nullptr;
|
||||
}
|
||||
iris_data->ImageInfoSection.SectionLength =Get_Image_Data_to_Byte(&iris_data->ImageInfoSection.SectionContent, &tempbuff);
|
||||
write_section_emb(
|
||||
iris_data->ImageInfoSection.SectionFlag,
|
||||
iris_data->ImageInfoSection.SectionLength, // Using SectionLength from the struct
|
||||
tempbuff, // Assuming AddressList points to raw data
|
||||
File_control.Write_data
|
||||
);
|
||||
if (tempbuff != nullptr) {
|
||||
delete[] tempbuff; // Free the temporary buffer if it was allocated
|
||||
tempbuff = nullptr;
|
||||
}
|
||||
File_control.close_file(); // Close the file after writing all sections
|
||||
|
||||
|
||||
}
|
||||
|
||||
One_IRIS_DATA_Struct Get_One_IRIS_DATA_From_File(std::string Filepath, MyfileControl_Struct File_control) {
|
||||
// if (File_control== nullptr) {
|
||||
// return Create_IRIS_DATA_Struct(); // Return an empty struct if File_control_ptr is not set
|
||||
// }
|
||||
One_IRIS_DATA_Struct Retrun_Data;
|
||||
File_control.open_file(Filepath, "rb"); // Open the file for reading in binary mode
|
||||
uint64_t ReadLength = 0;
|
||||
uint8_t *readbuffer = nullptr;
|
||||
while (1) {
|
||||
ReadLength= File_control.Read_data(&readbuffer, 12); // Get the file size
|
||||
if (ReadLength != 12) {
|
||||
break; // Break if no more data to read
|
||||
}
|
||||
uint32_t SecTionFlag = 0;
|
||||
uint64_t SectionLength = 0;
|
||||
memcpy(&SecTionFlag, readbuffer, 4); // Read the section flag
|
||||
memcpy(&SectionLength, readbuffer + 4, 8); // Read the section length
|
||||
delete [] readbuffer; // Free the read buffer
|
||||
readbuffer = nullptr; // Reset the pointer to nullptr
|
||||
switch (SecTionFlag) {
|
||||
case SPECTRAL_DATA_SECTION: {
|
||||
Sepctral_Data_Section_Struct &spectral_data_section = Retrun_Data.SepctralDataSection;
|
||||
spectral_data_section.SectionLength= SectionLength; // 区域长度
|
||||
Sepctral_Data_Section_Data_Struct &spectral_data_content = spectral_data_section.SectionContent;
|
||||
uint64_t lenthinsection=0;
|
||||
lenthinsection+= File_control.Read_data(&readbuffer, 2); // Read the spectral data section
|
||||
uint16_t number_of_spectral_data = 0;
|
||||
memcpy(&number_of_spectral_data, readbuffer, 2); // 读取光谱数据数量
|
||||
spectral_data_content.SepctralDataNumber= number_of_spectral_data; // 设置光谱数据数量
|
||||
spectral_data_content.SepctralDataAddressList= new One_Spectral_Data_Struct[number_of_spectral_data]; // 创建光谱数据数组
|
||||
for (int32_t j=0;j<number_of_spectral_data;j++) {
|
||||
One_Spectral_Data_Struct &one_spectral_data = spectral_data_content.SepctralDataAddressList[j];
|
||||
lenthinsection+= File_control.Read_data( &readbuffer, sizeof(One_Spectral_Data_Struct)-sizeof(uint8_t *)); // Read the Name
|
||||
memcpy(&one_spectral_data,readbuffer,sizeof(One_Spectral_Data_Struct)-sizeof(uint8_t *));
|
||||
int32_t spectral_data_length = one_spectral_data.PixelSize* one_spectral_data.Bands; // 计算光谱数据长度
|
||||
one_spectral_data.SpectralDataAddress=nullptr;
|
||||
// one_spectral_data.SpectralDataAddress = new uint8_t[spectral_data_length]; // 分配光谱数据地址
|
||||
lenthinsection+= File_control.Read_data(&one_spectral_data.SpectralDataAddress, spectral_data_length); // 读取光谱数据
|
||||
delete [] readbuffer; // 释放之前的读取缓冲区
|
||||
readbuffer = nullptr; // 释放后将指针设置为nullptr
|
||||
}
|
||||
if (lenthinsection!= SectionLength) {
|
||||
// Handle error: not all data was read
|
||||
delete[] spectral_data_content.SepctralDataAddressList; // Free the allocated array
|
||||
spectral_data_content.SepctralDataAddressList = nullptr; // Reset the pointer to nullptr
|
||||
return Create_IRIS_DATA_Struct(); // Return an empty struct
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ReadLength= File_control.Read_data(&readbuffer, SectionLength); // Read the spectral data section
|
||||
|
||||
break;
|
||||
}
|
||||
case SPECTRAL_INFO_SECTION: {
|
||||
//ReadLength= File_control.Read_data(&readbuffer, SectionLength); // Read the spectral info section
|
||||
uint16_t lenth_in_section=0;
|
||||
Sepctral_Info_Section_Struct &spectral_info_section = Retrun_Data.SepctralInfoSection;
|
||||
spectral_info_section.SectionLength= SectionLength; // 区域长度
|
||||
Sepctral_Info_Section_Data_Struct &spectral_info_content = spectral_info_section.SectionContent;
|
||||
lenth_in_section+= File_control.Read_data(&readbuffer, 2); // Read the spectral info section
|
||||
uint16_t number_of_spectral_info = 0;
|
||||
memcpy(&number_of_spectral_info, readbuffer, 2); // 读取光谱信息数量
|
||||
spectral_info_content.SepctralInfoNumber= number_of_spectral_info; // 设置光谱信息数量
|
||||
spectral_info_content.SepctralInfoAddressList= new One_Spectral_Info_Struct[number_of_spectral_info]; // 创建光谱信息数组
|
||||
for (int32_t j=0;j<number_of_spectral_info;j++) {
|
||||
One_Spectral_Info_Struct &one_spectral_info = spectral_info_content.SepctralInfoAddressList[j];
|
||||
uint16_t lenth_of_this_spectral_info=0;
|
||||
uint8_t type_of_spectral_info=0;
|
||||
lenth_in_section+= File_control.Read_data(&readbuffer, 3); // Read the spectral info section
|
||||
memcpy(&lenth_of_this_spectral_info, readbuffer, 2); // 读取光谱信息长度
|
||||
type_of_spectral_info = readbuffer[2]; // 读取光谱信息类型
|
||||
lenth_in_section+=File_control.Read_data(&readbuffer, lenth_of_this_spectral_info); // Read the spectral info section
|
||||
if (type_of_spectral_info == 0x00) {
|
||||
one_spectral_info= Get_spectral_info_from_byte(readbuffer,lenth_of_this_spectral_info);
|
||||
}
|
||||
delete [] readbuffer; // 释放之前的读取缓冲区
|
||||
readbuffer = nullptr; // 释放后将指针设置为nullptr
|
||||
|
||||
|
||||
}
|
||||
if (lenth_in_section!= SectionLength) {
|
||||
// Handle error: not all data was read
|
||||
delete[] spectral_info_content.SepctralInfoAddressList; // Free the allocated array
|
||||
spectral_info_content.SepctralInfoAddressList = nullptr; // Reset the pointer to nullptr
|
||||
return Create_IRIS_DATA_Struct(); // Return an empty struct
|
||||
}
|
||||
break;
|
||||
}
|
||||
case OTHER_SECTION: {
|
||||
if (SectionLength==0) {
|
||||
Retrun_Data.OtherInfoSection.SectionLength=0;
|
||||
Retrun_Data.OtherInfoSection.SectionContent.OtherInfoNumber=0;
|
||||
break;
|
||||
}
|
||||
//ReadLength= File_control.Read_data(&readbuffer, SectionLength); // Read the other section
|
||||
uint16_t lenth_in_section=0;
|
||||
Other_Info_Section_Struct &other_info_section = Retrun_Data.OtherInfoSection;
|
||||
other_info_section.SectionLength= SectionLength; // 区域长度
|
||||
Other_Info_Section_Data_Struct &other_info_content = other_info_section.SectionContent;
|
||||
lenth_in_section+= File_control.Read_data(&readbuffer, 2); // Read the other info section
|
||||
uint16_t number_of_other_info = 0;
|
||||
memcpy(&number_of_other_info, readbuffer, 2); // 读取其他信息数量
|
||||
other_info_content.OtherInfoNumber= number_of_other_info; // 设置其他信息数量
|
||||
other_info_content.OtherInfoAddressList= new One_Other_Info_Struct[number_of_other_info]; // 创建其他信息数组
|
||||
|
||||
|
||||
break;
|
||||
}
|
||||
case IMAGE_SECTION: {
|
||||
if (SectionLength==0) {
|
||||
Retrun_Data.ImageInfoSection.SectionLength=0;
|
||||
Retrun_Data.ImageInfoSection.SectionContent.ImageInfoNumber=0;
|
||||
break;
|
||||
}
|
||||
//ReadLength= File_control.Read_data(&readbuffer, SectionLength); // Read the image section
|
||||
uint16_t lenth_in_section=0;
|
||||
Image_Info_Section_Struct &image_info_section = Retrun_Data.ImageInfoSection;
|
||||
image_info_section.SectionLength= SectionLength; // 区域长度
|
||||
Image_Info_Section_Data_Struct &image_info_content = image_info_section.SectionContent;
|
||||
lenth_in_section+= File_control.Read_data(&readbuffer, 2); // Read the image info section
|
||||
uint16_t number_of_image_info = 0;
|
||||
memcpy(&number_of_image_info, readbuffer, 2); // 读取图像信息数量
|
||||
image_info_content.ImageInfoNumber= number_of_image_info; // 设置图像信息数量
|
||||
image_info_content.ImageInfoAddressList= new One_Image_Info_Struct[number_of_image_info]; // 创建图像信息数组
|
||||
for (int32_t j=0;j<number_of_image_info;j++) {
|
||||
|
||||
One_Image_Info_Struct &one_image_info = image_info_content.ImageInfoAddressList[j];
|
||||
uint64_t image_data_length = 0;
|
||||
lenth_in_section+= File_control.Read_data(&readbuffer, 8); // Read the image data length
|
||||
memcpy(&image_data_length, readbuffer, 8); // 读取图像数据长度
|
||||
one_image_info.DataLength = image_data_length; // 设置图像数据长度
|
||||
lenth_in_section+= File_control.Read_data(&readbuffer, 100); // Read the image name
|
||||
memcpy(one_image_info.Name, readbuffer, 100); // 读取图像名称
|
||||
lenth_in_section+= File_control.Read_data(&readbuffer, sizeof(IRIS_Time_Struct)); // Read the image collection time
|
||||
memcpy(&one_image_info.CollectionTime, readbuffer, sizeof(IRIS_Time_Struct)); // 读取图像采集时间
|
||||
lenth_in_section+= File_control.Read_data(&readbuffer, 1); // Read the image type
|
||||
memcpy(&one_image_info.Type, readbuffer, 1); // 读取图像类型
|
||||
one_image_info.ImageDataAddress = nullptr; // 初始化图像数据地址为nullptr
|
||||
int64_t image_total_data_length = image_data_length - (100 + sizeof(IRIS_Time_Struct) + sizeof(uint8_t)); // 计算图像数据长度
|
||||
lenth_in_section+= File_control.Read_data(&one_image_info.ImageDataAddress, image_total_data_length); // 读取图像数据
|
||||
delete [] readbuffer; // 释放之前的读取缓冲区
|
||||
readbuffer = nullptr; // 释放后将指针设置为nullptr
|
||||
|
||||
}
|
||||
if (lenth_in_section!= SectionLength) {
|
||||
// Handle error: not all data was read
|
||||
delete[] image_info_content.ImageInfoAddressList; // Free the allocated array
|
||||
image_info_content.ImageInfoAddressList = nullptr; // Reset the pointer to nullptr
|
||||
return Create_IRIS_DATA_Struct(); // Return an empty struct
|
||||
}
|
||||
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (readbuffer!=nullptr) {
|
||||
delete [] readbuffer; // Free the read buffer after processing
|
||||
readbuffer = nullptr; // Reset the pointer to nullptr
|
||||
}
|
||||
}
|
||||
File_control.close_file(); // Close the file after reading all sections
|
||||
|
||||
|
||||
return Retrun_Data; // Return the populated One_IRIS_DATA_Struct
|
||||
|
||||
}
|
||||
void Destroy_IRIS_DATA_Struct(One_IRIS_DATA_Struct &iris_data) {
|
||||
//清除光谱区域
|
||||
if (iris_data.SepctralDataSection.SectionContent.SepctralDataNumber !=0) {
|
||||
int16_t numberforclear = iris_data.SepctralDataSection.SectionContent.SepctralDataNumber;
|
||||
for (int16_t i=0;i<numberforclear;i++) {
|
||||
if (iris_data.SepctralDataSection.SectionContent.SepctralDataAddressList[i].SpectralDataAddress!= nullptr) {
|
||||
delete[] iris_data.SepctralDataSection.SectionContent.SepctralDataAddressList[i].SpectralDataAddress; // Free the spectral data address
|
||||
iris_data.SepctralDataSection.SectionContent.SepctralDataAddressList[i].SpectralDataAddress = nullptr; // Reset the pointer to nullptr
|
||||
}
|
||||
}
|
||||
if (iris_data.SepctralDataSection.SectionContent.SepctralDataAddressList!=nullptr)
|
||||
delete[] iris_data.SepctralDataSection.SectionContent.SepctralDataAddressList; // Free the spectral data address list
|
||||
iris_data.SepctralDataSection.SectionContent.SepctralDataAddressList = nullptr; // Reset the pointer to nullptr
|
||||
iris_data.SepctralDataSection.SectionContent.SepctralDataNumber=0;
|
||||
iris_data.SepctralDataSection.SectionLength=0;
|
||||
}
|
||||
//清除光谱信息区域
|
||||
if (iris_data.SepctralInfoSection.SectionContent.SepctralInfoNumber !=0) {
|
||||
int16_t numberforclear = iris_data.SepctralInfoSection.SectionContent.SepctralInfoNumber;
|
||||
for (int16_t i=0;i<numberforclear;i++) {
|
||||
// No dynamic memory allocation in One_Spectral_Info_Struct, so no need to free anything
|
||||
}
|
||||
if (iris_data.SepctralInfoSection.SectionContent.SepctralInfoAddressList!=nullptr)
|
||||
delete[] iris_data.SepctralInfoSection.SectionContent.SepctralInfoAddressList; // Free the spectral info address list
|
||||
iris_data.SepctralInfoSection.SectionContent.SepctralInfoAddressList = nullptr; // Reset the pointer to nullptr
|
||||
iris_data.SepctralInfoSection.SectionContent.SepctralInfoNumber=0;
|
||||
iris_data.SepctralInfoSection.SectionLength=0;
|
||||
}
|
||||
//清除其他信息区域
|
||||
if (iris_data.OtherInfoSection.SectionContent.OtherInfoNumber !=0) {
|
||||
int16_t numberforclear = iris_data.OtherInfoSection.SectionContent.OtherInfoNumber;
|
||||
for (int16_t i=0;i<numberforclear;i++) {
|
||||
// No dynamic memory allocation in One_Other_Info_Struct, so no need to free anything
|
||||
}
|
||||
if (iris_data.OtherInfoSection.SectionContent.OtherInfoAddressList!=nullptr)
|
||||
delete[] iris_data.OtherInfoSection.SectionContent.OtherInfoAddressList; // Free the other info address list
|
||||
iris_data.OtherInfoSection.SectionContent.OtherInfoAddressList = nullptr; // Reset the pointer to nullptr
|
||||
iris_data.OtherInfoSection.SectionContent.OtherInfoNumber=0;
|
||||
iris_data.OtherInfoSection.SectionLength=0;
|
||||
}
|
||||
//清除图像信息区域
|
||||
if (iris_data.ImageInfoSection.SectionContent.ImageInfoNumber !=0) {
|
||||
int16_t numberforclear = iris_data.ImageInfoSection.SectionContent.ImageInfoNumber;
|
||||
for (int16_t i=0;i<numberforclear;i++) {
|
||||
if (iris_data.ImageInfoSection.SectionContent.ImageInfoAddressList[i].ImageDataAddress!= nullptr) {
|
||||
delete[] iris_data.ImageInfoSection.SectionContent.ImageInfoAddressList[i].ImageDataAddress; // Free the image data address
|
||||
iris_data.ImageInfoSection.SectionContent.ImageInfoAddressList[i].ImageDataAddress = nullptr; // Reset the pointer to nullptr
|
||||
}
|
||||
}
|
||||
if (iris_data.ImageInfoSection.SectionContent.ImageInfoAddressList!=nullptr)
|
||||
delete[] iris_data.ImageInfoSection.SectionContent.ImageInfoAddressList; // Free the image info address list
|
||||
iris_data.ImageInfoSection.SectionContent.ImageInfoAddressList = nullptr; // Reset the pointer to nullptr
|
||||
iris_data.ImageInfoSection.SectionContent.ImageInfoNumber=0;
|
||||
iris_data.ImageInfoSection.SectionLength=0;
|
||||
}
|
||||
//清除整个结构体
|
||||
iris_data.SepctralDataSection.SectionFlag = SPECTRAL_DATA_SECTION;
|
||||
iris_data.SepctralDataSection.SectionLength = 0;
|
||||
iris_data.SepctralInfoSection.SectionFlag = SPECTRAL_INFO_SECTION;
|
||||
iris_data.SepctralInfoSection.SectionLength = 0;
|
||||
iris_data.OtherInfoSection.SectionFlag = OTHER_SECTION;
|
||||
iris_data.OtherInfoSection.SectionLength = 0;
|
||||
iris_data.ImageInfoSection.SectionFlag = IMAGE_SECTION;
|
||||
iris_data.ImageInfoSection.SectionLength = 0;
|
||||
}
|
220
source/iris_format/iris_deffine.h
Normal file
220
source/iris_format/iris_deffine.h
Normal file
@ -0,0 +1,220 @@
|
||||
#ifndef IRIS_DEFFINE_H
|
||||
#define IRIS_DEFFINE_H
|
||||
|
||||
#include <cstdint> // For uint8_t, uint16_t, uint32_t, uint64_t, int8_t
|
||||
#include <stddef.h> // For size_t
|
||||
#include <string> // For std::string
|
||||
|
||||
//结构体内存1字节对齐
|
||||
#pragma pack(1)
|
||||
|
||||
#define SPECTRAL_DATA_SECTION 0x00ff00ff
|
||||
#define SPECTRAL_INFO_SECTION 0xff00ff00
|
||||
#define OTHER_SECTION 0xf0f0f0f0
|
||||
#define IMAGE_SECTION 0x0f0f0f0f
|
||||
/*| 编码值 | 数据类型 | 描述 |
|
||||
| ------ | -------- | ------------------------------- |
|
||||
| 0x10 | uint8 | 无符号8位整型 (0-255) |
|
||||
| 0x11 | int16 | 有符号16位整型 (-32,768~32,767) |
|
||||
| 0x12 | uint16 | 无符号16位整型 (0-65,535) |
|
||||
| 0x13 | int32 | 有符号32位整型 |
|
||||
| 0x14 | uint32 | 无符号32位整型 |
|
||||
| 0x20 | float32 | IEEE 754单精度浮点 |
|
||||
| 0x21 | float64 | IEEE 754双精度浮点 |
|
||||
*/
|
||||
#define DATA_TYPE_UINT8 0x10
|
||||
#define DATA_TYPE_INT16 0x11
|
||||
#define DATA_TYPE_UINT16 0x12
|
||||
#define DATA_TYPE_INT32 0x13
|
||||
#define DATA_TYPE_UINT32 0x14
|
||||
#define DATA_TYPE_FLOAT32 0x20
|
||||
#define DATA_TYPE_FLOAT64 0x21
|
||||
|
||||
|
||||
|
||||
|
||||
typedef uint32_t SECTIONFLAG;
|
||||
|
||||
// Function pointer type for saving data (C compatible)
|
||||
typedef void (*WriteDataFunc)(const uint8_t *data, size_t size);
|
||||
typedef void (*OpenFileFunc)(std::string Filepath,const char *mode);
|
||||
typedef void (*CloseFileFunc)(void);
|
||||
typedef int64_t (*ReadFileFunc)(uint8_t **buffer, size_t size);
|
||||
|
||||
|
||||
// Forward declarations of structs for C compatibility
|
||||
// This is good practice if structs reference each other
|
||||
typedef struct IRIS_Time_Struct IRIS_Time_Struct;
|
||||
typedef struct Section_Data_Struct Section_Data_Struct;
|
||||
typedef struct One_Spectral_Data_Struct One_Spectral_Data_Struct;
|
||||
typedef struct Sepctral_Data_Section_Data_Struct Sepctral_Data_Section_Data_Struct;
|
||||
typedef struct Sepctral_Data_Section_Struct Sepctral_Data_Section_Struct;
|
||||
typedef struct One_Spectral_Info_Struct One_Spectral_Info_Struct;
|
||||
typedef struct Sepctral_Info_Section_Data_Struct Sepctral_Info_Section_Data_Struct;
|
||||
typedef struct Sepctral_Info_Section_Struct Sepctral_Info_Section_Struct;
|
||||
typedef struct One_Other_Info_Struct One_Other_Info_Struct;
|
||||
typedef struct Other_Info_Section_Data_Struct Other_Info_Section_Data_Struct;
|
||||
typedef struct Other_Info_Section_Struct Other_Info_Section_Struct;
|
||||
typedef struct One_Image_Info_Struct One_Image_Info_Struct;
|
||||
typedef struct Image_Info_Section_Data_Struct Image_Info_Section_Data_Struct;
|
||||
typedef struct Image_Info_Section_Struct Image_Info_Section_Struct;
|
||||
typedef struct One_IRIS_DATA_Struct One_IRIS_DATA_Struct;
|
||||
typedef struct MyfileControl_Struct MyfileControl_Struct;
|
||||
|
||||
typedef struct MyfileControl_Struct
|
||||
{
|
||||
OpenFileFunc open_file; // 打开文件函数
|
||||
CloseFileFunc close_file; // 关闭文件函数
|
||||
WriteDataFunc Write_data; // 保存数据函数
|
||||
ReadFileFunc Read_data; // 读取数据函数
|
||||
} MyfileControl_Struct;
|
||||
|
||||
// Define structs with typedef for C compatibility
|
||||
typedef struct IRIS_Time_Struct
|
||||
{
|
||||
int8_t TimeZone; // 时区
|
||||
uint16_t Year; // 年
|
||||
uint8_t Month; // 月
|
||||
uint8_t Day; // 日
|
||||
uint8_t Hour; // 时
|
||||
uint8_t Minute; // 分
|
||||
uint8_t Second; // 秒
|
||||
uint16_t Millisecond; // 毫秒
|
||||
} IRIS_Time_Struct;
|
||||
|
||||
|
||||
typedef struct Section_Data_Struct
|
||||
{
|
||||
SECTIONFLAG SectionFlag; // 区域标志
|
||||
uint64_t SectionLength; // 区域长度
|
||||
uint8_t *SectionDataAddress; // 区域类型 (pointer to data)
|
||||
} Section_Data_Struct;
|
||||
|
||||
///////////////////////////////// 光谱数据结构体 /////////////////////////////////
|
||||
|
||||
typedef struct One_Spectral_Data_Struct{
|
||||
char Name[100]; // 光谱数据名称
|
||||
char SensorId[50]; // 传感器ID
|
||||
uint8_t FiberID; // 光纤ID
|
||||
IRIS_Time_Struct CollectionTime; // 采集时间
|
||||
double Exposure; // 曝光时间
|
||||
float Gain; // 增益
|
||||
uint8_t DataType; // 数据类型
|
||||
uint8_t PixelSize; // 像素大小
|
||||
uint8_t GroundType; // 地面类型
|
||||
uint16_t Bands; // 波段数
|
||||
uint8_t ValidFlag; // 有效标志
|
||||
uint8_t *SpectralDataAddress; // 光谱数据地址 (pointer to data)
|
||||
} One_Spectral_Data_Struct;
|
||||
|
||||
|
||||
typedef struct Sepctral_Data_Section_Data_Struct
|
||||
{
|
||||
uint16_t SepctralDataNumber;
|
||||
One_Spectral_Data_Struct *SepctralDataAddressList; // 光谱数据地址 (pointer to array of structs)
|
||||
|
||||
} Sepctral_Data_Section_Data_Struct;
|
||||
|
||||
typedef struct Sepctral_Data_Section_Struct
|
||||
{
|
||||
SECTIONFLAG SectionFlag; // 区域标志
|
||||
uint64_t SectionLength; // 区域长度
|
||||
Sepctral_Data_Section_Data_Struct SectionContent; // 光谱数据区域
|
||||
} Sepctral_Data_Section_Struct;
|
||||
|
||||
|
||||
///////////////////////////////// 光谱信息结构相关定义 /////////////////////////////////
|
||||
|
||||
// 下面结构体应通过转换成json在进行存储 读取时亦然
|
||||
typedef struct One_Spectral_Info_Struct{
|
||||
char SensorId[50]; // 传感器ID
|
||||
double WaveCoeff[4]; // 波长系数
|
||||
} One_Spectral_Info_Struct;
|
||||
|
||||
typedef struct Sepctral_Info_Section_Data_Struct
|
||||
{
|
||||
uint16_t SepctralInfoNumber; // 光谱信息数量
|
||||
One_Spectral_Info_Struct *SepctralInfoAddressList; // 光谱信息地址 (pointer to array of structs)
|
||||
} Sepctral_Info_Section_Data_Struct;
|
||||
|
||||
typedef struct Sepctral_Info_Section_Struct
|
||||
{
|
||||
SECTIONFLAG SectionFlag; // 区域标志
|
||||
uint64_t SectionLength; // 区域长度
|
||||
Sepctral_Info_Section_Data_Struct SectionContent; // 光谱信息区域
|
||||
} Sepctral_Info_Section_Struct;
|
||||
|
||||
///////////////////////////////// 其他信息结构相关定义 /////////////////////////////////
|
||||
typedef struct One_Other_Info_Struct{
|
||||
uint8_t Type; // 信息类型; // 数据地址 (pointer to data)
|
||||
} One_Other_Info_Struct;
|
||||
|
||||
typedef struct Other_Info_Section_Data_Struct
|
||||
{
|
||||
uint16_t OtherInfoNumber; // 其他信息数量
|
||||
One_Other_Info_Struct *OtherInfoAddressList; // 其他信息地址 (pointer to array of structs)
|
||||
} Other_Info_Section_Data_Struct;
|
||||
|
||||
typedef struct Other_Info_Section_Struct
|
||||
{
|
||||
SECTIONFLAG SectionFlag; // 区域标志
|
||||
uint64_t SectionLength; // 区域长度
|
||||
Other_Info_Section_Data_Struct SectionContent; // 其他信息区域
|
||||
} Other_Info_Section_Struct;
|
||||
|
||||
///////////////////////////////// 图像信息结构相关定义 /////////////////////////////////
|
||||
typedef struct One_Image_Info_Struct{
|
||||
uint64_t DataLength; // 图像数据长度
|
||||
char Name[100]; // 图像名称
|
||||
IRIS_Time_Struct CollectionTime; // 采集时间
|
||||
uint8_t Type; // 图像类型
|
||||
uint8_t *ImageDataAddress; // 图像数据地址 (pointer to data)
|
||||
} One_Image_Info_Struct;
|
||||
|
||||
typedef struct Image_Info_Section_Data_Struct
|
||||
{
|
||||
uint16_t ImageInfoNumber; // 图像信息数量
|
||||
One_Image_Info_Struct *ImageInfoAddressList; // 图像信息地址 (pointer to array of structs)
|
||||
} Image_Info_Section_Data_Struct;
|
||||
|
||||
typedef struct Image_Info_Section_Struct
|
||||
{
|
||||
SECTIONFLAG SectionFlag; // 区域标志
|
||||
uint64_t SectionLength; // 区域长度
|
||||
Image_Info_Section_Data_Struct SectionContent; // 图像信息区域
|
||||
} Image_Info_Section_Struct;
|
||||
|
||||
|
||||
typedef struct One_IRIS_DATA_Struct
|
||||
{
|
||||
Sepctral_Data_Section_Struct SepctralDataSection; // 光谱数据区域
|
||||
Sepctral_Info_Section_Struct SepctralInfoSection; // 光谱信息区域
|
||||
Other_Info_Section_Struct OtherInfoSection; // 其他信息区域
|
||||
Image_Info_Section_Struct ImageInfoSection; // 图像信息区域
|
||||
} One_IRIS_DATA_Struct;
|
||||
|
||||
//恢复默认字节对齐
|
||||
#pragma pack()
|
||||
#ifdef WIN32
|
||||
#define VSDLL_EXPORTS __declspec(dllexport)
|
||||
#else
|
||||
|
||||
#define VSDLL_EXPORTS
|
||||
#endif
|
||||
|
||||
// Function prototypes (C style)
|
||||
VSDLL_EXPORTS One_IRIS_DATA_Struct Create_IRIS_DATA_Struct(void);
|
||||
// 通过全局设置读写函数 在写入时就不用传递函数指针了
|
||||
VSDLL_EXPORTS void Set_File_Functions( MyfileControl_Struct *File_control);
|
||||
VSDLL_EXPORTS void Write_IRIS_DATA_Struct_EMB_NoFUNC( One_IRIS_DATA_Struct *iris_data,std::string Filepath);
|
||||
|
||||
//改变为指定读写函数的写入
|
||||
VSDLL_EXPORTS void write_IRIS_DATA_Struct_EMB( One_IRIS_DATA_Struct *iris_data,std::string Filepath, MyfileControl_Struct File_control);
|
||||
//下面函数需要根据平台自行实现
|
||||
uint64_t get_Sepctral_Info_to_Byte(Sepctral_Info_Section_Data_Struct *sepctralinfo,uint8_t **retbuffer);
|
||||
uint64_t get_Other_Info_to_Byte(Other_Info_Section_Data_Struct *otherdata,uint8_t **retbuffer);
|
||||
One_IRIS_DATA_Struct Get_One_IRIS_DATA_From_File(std::string Filepath, MyfileControl_Struct File_control);
|
||||
VSDLL_EXPORTS void IRIS_DATA_example();
|
||||
One_Spectral_Info_Struct Get_spectral_info_from_byte(uint8_t *buffer, size_t length);
|
||||
void Destroy_IRIS_DATA_Struct(One_IRIS_DATA_Struct &iris_data);
|
||||
#endif // IRIS_DEFFINE_H
|
25526
source/json/json.hpp
Normal file
25526
source/json/json.hpp
Normal file
File diff suppressed because it is too large
Load Diff
43
tests/test_iris_format.cpp
Normal file
43
tests/test_iris_format.cpp
Normal file
@ -0,0 +1,43 @@
|
||||
|
||||
#include <cassert>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <iris_format/iris_deffine.h>
|
||||
FILE *fp = nullptr;
|
||||
void openfile(std::string Filepath,const char *mode) {
|
||||
fp= fopen(Filepath.c_str(), mode);
|
||||
}
|
||||
void write_data(const uint8_t *data, size_t length) {
|
||||
if (fp != nullptr) {
|
||||
fwrite(data, 1, length, fp);
|
||||
}
|
||||
}
|
||||
void closefile() {
|
||||
if (fp != nullptr) {
|
||||
fclose(fp);
|
||||
fp = nullptr;
|
||||
}
|
||||
}
|
||||
int64_t read_data(uint8_t **buffer, size_t size) {
|
||||
if (fp == nullptr) {
|
||||
return -1; // File not open
|
||||
}
|
||||
if (*buffer != nullptr) {
|
||||
delete[] *buffer; // Free previously allocated buffer
|
||||
}
|
||||
*buffer = new uint8_t[size];
|
||||
return fread(*buffer, 1, size, fp);
|
||||
}
|
||||
|
||||
int main() {
|
||||
MyfileControl_Struct *file_control = new MyfileControl_Struct;
|
||||
file_control->open_file = openfile;
|
||||
file_control->Write_data = write_data;
|
||||
file_control->close_file = closefile;
|
||||
file_control->Read_data = read_data;
|
||||
Set_File_Functions(file_control);
|
||||
IRIS_DATA_example();
|
||||
return 0;
|
||||
}
|
Reference in New Issue
Block a user