use std::io::{BufRead, Write};
use super::filter_non_finite;
use crate::lut::Lut1D;
pub fn write<W: Write>(
mut writer: W,
range_min: f32,
range_max: f32,
tables: &[&[f32]],
) -> std::io::Result<()> {
assert!(tables.len() > 0 && tables.len() <= 3);
assert!(tables.iter().all(|t| t.len() == tables[0].len()));
writer.write_all(b"Version 1\n")?;
writer.write_all(
format!(
"From {} {}\n",
filter_non_finite(range_min),
filter_non_finite(range_max)
)
.as_bytes(),
)?;
writer.write_all(format!("Length {}\n", tables[0].len()).as_bytes())?;
writer.write_all(format!("Components {}\n", tables.len()).as_bytes())?;
writer.write_all(b"{\n")?;
for i in 0..tables[0].len() {
writer.write_all(b" ")?;
for t in tables.iter() {
writer.write_all(format!(" {}", filter_non_finite(t[i])).as_bytes())?;
}
writer.write_all(b"\n")?;
}
writer.write_all(b"}\n")?;
Ok(())
}
pub fn read<R: BufRead>(reader: R) -> Result<Lut1D, super::ReadError> {
let mut range_min = 0.0;
let mut range_max = 1.0;
let mut length = 0;
let mut components = 0;
let mut tables = Vec::new();
let mut reading_table = false;
for line in reader.lines() {
let line = line?;
let parts: Vec<_> = line.split_whitespace().collect();
if parts.is_empty() {
continue;
}
if !reading_table {
if parts[0] == "Version" && parts.len() == 2 {
if parts[1].parse::<usize>()? != 1 {
return Err(super::ReadError::FormatErr);
}
continue;
} else if parts[0] == "From" && parts.len() == 3 {
range_min = parts[1].parse::<f32>()?;
range_max = parts[2].parse::<f32>()?;
continue;
} else if parts[0] == "Components" && parts.len() == 2 {
components = parts[1].parse::<usize>()?;
continue;
} else if parts[0] == "Length" && parts.len() == 2 {
length = parts[1].parse::<usize>()?;
continue;
} else if parts[0] == "{" && parts.len() == 1 {
if length == 0 || components < 1 || components > 3 {
return Err(super::ReadError::FormatErr);
}
for _ in 0..components {
tables.push(Vec::new());
}
reading_table = true;
continue;
} else {
return Err(super::ReadError::FormatErr);
}
} else if reading_table {
if parts[0] == "}" {
break;
} else if parts.len() == components {
for i in 0..components {
tables[i].push(parts[i].parse::<f32>()?);
}
continue;
} else {
return Err(super::ReadError::FormatErr);
}
}
}
if !tables.iter().flatten().all(|n| n.is_finite())
|| !range_min.is_finite()
|| !range_max.is_finite()
{
return Err(super::ReadError::FormatErr);
}
if length == tables[0].len() {
Ok(Lut1D {
ranges: vec![(range_min, range_max)],
tables: tables,
})
} else {
Err(super::ReadError::FormatErr)
}
}