use std::fs;
use std::io;
use std::path::Path;
use crate::ifd::{AllocatedIfdChain, IfdChain};
use crate::write::{Cursor, EndianFile, Endianness};
pub struct TiffFile {
header: TiffHeader,
ifds: IfdChain,
}
impl TiffFile {
pub fn new(ifds: IfdChain) -> TiffFile {
TiffFile {
header: TiffHeader {
byte_order: Endianness::II,
magic_number: 42,
},
ifds: ifds,
}
}
pub fn with_endianness(mut self, endian: Endianness) -> Self {
self.header.byte_order = endian;
self
}
pub fn write_to<P: AsRef<Path>>(self, file_path: P) -> io::Result<fs::File> {
if let Some(dir) = file_path.as_ref().parent() {
fs::create_dir_all(dir)?;
}
let file = fs::File::create(file_path)?;
self.allocate(file).write()
}
fn allocate(self, file: fs::File) -> AllocatedTiffFile {
let mut c = Cursor::new();
let header = self.header.allocate(&mut c);
let ifds = self.ifds.allocate(&mut c);
let file = EndianFile::new(file, header.byte_order);
AllocatedTiffFile { header, ifds, file }
}
}
struct AllocatedTiffFile {
header: AllocatedTiffHeader,
ifds: AllocatedIfdChain,
file: EndianFile,
}
impl AllocatedTiffFile {
fn write(mut self) -> io::Result<fs::File> {
self.header.write_to(&mut self.file)?;
self.ifds.write_to(&mut self.file)?;
Ok(self.file.into())
}
}
struct TiffHeader {
byte_order: Endianness,
magic_number: u16,
}
impl TiffHeader {
fn allocate(self, c: &mut Cursor) -> AllocatedTiffHeader {
c.allocate(8);
AllocatedTiffHeader {
byte_order: self.byte_order,
magic_number: self.magic_number,
offset_to_ifd0: c.allocated_bytes(),
}
}
}
struct AllocatedTiffHeader {
byte_order: Endianness,
magic_number: u16,
offset_to_ifd0: u32,
}
impl AllocatedTiffHeader {
fn write_to(self, file: &mut EndianFile) -> io::Result<()> {
file.write_u16(self.byte_order.id())?;
file.write_u16(self.magic_number)?;
file.write_u32(self.offset_to_ifd0)?;
Ok(())
}
}