use Encoder;
use byteorder::{ByteOrder, NetworkEndian, WriteBytesExt};
use flate2::Crc;
use std::io::{self, Write};
pub fn palette<W: Write, F>(enc: &mut Encoder<W, F>, rgb: &[u8])
-> io::Result<()>
{
assert!(rgb.len() % 3 == 0);
assert!(rgb.len() / 3 <= 256);
enc.chunk(b"PLTE", rgb)?;
Ok(())
}
pub fn palette_alpha<W: Write, F>(enc: &mut Encoder<W, F>, rgba: &[u8])
-> io::Result<()>
{
assert!(rgba.len() % 4 == 0);
assert!(rgba.len() / 4 <= 256);
let len = rgba.len() / 4;
let mut plte = [0; 256 * 3];
let mut trns = [0; 256];
for i in 0..len {
plte[3*i + 0] = rgba[4*i + 0];
plte[3*i + 1] = rgba[4*i + 1];
plte[3*i + 2] = rgba[4*i + 2];
trns[i] = rgba[4*i + 3];
}
enc.chunk(b"PLTE", &plte[..len * 3])?;
enc.chunk(b"tRNS", &trns[..len])?;
Ok(())
}
pub fn aspect_ratio<W: Write, F>(enc: &mut Encoder<W, F>, x: u32, y: u32)
-> io::Result<()>
{
let mut phys = [0; 9];
NetworkEndian::write_u32(&mut phys[0..4], x);
NetworkEndian::write_u32(&mut phys[4..8], y);
enc.chunk(b"pHYs", &phys)?;
Ok(())
}
pub fn text<W: Write, F>(enc: &mut Encoder<W, F>, keyword: Keyword, text: &str)
-> io::Result<()>
{
assert!(keyword.valid());
assert!(text.find('\0').is_none());
let kind = b"iTXt";
let sink = enc.writer();
let data = &[
keyword.as_str().as_bytes(),
&[0, 0, 0, 0, 0],
text.as_bytes(),
];
let mut crc = Crc::new();
crc.update(kind);
for sec in data {
crc.update(sec);
}
sink.write_u32::<NetworkEndian>(crc.amount() - 4)?;
sink.write_all(kind)?;
for sec in data {
sink.write_all(sec)?;
}
sink.write_u32::<NetworkEndian>(crc.sum())?;
Ok(())
}
pub enum Keyword<'a> {
Title,
Author,
Description,
Copyright,
CreationTime,
Software,
Disclaimer,
Warning,
Source,
Comment,
Other(&'a str),
}
impl<'a> Keyword<'a> {
pub fn valid(&self) -> bool {
match *self {
Keyword::Other(s) =>
1 <= s.len() &&
s.len() <= 79 &&
s.bytes().all(|b| 32 <= b && b <= 126) &&
!(s.starts_with(' ') || s.ends_with(' ')) &&
s.find(" ").is_none(),
_ => true
}
}
pub fn as_str(&self) -> &str {
match *self {
Keyword::Title => "Title",
Keyword::Author => "Author",
Keyword::Description => "Description",
Keyword::Copyright => "Copyright",
Keyword::CreationTime => "Creation Time",
Keyword::Software => "Software",
Keyword::Disclaimer => "Disclaimer",
Keyword::Warning => "Warning",
Keyword::Source => "Source",
Keyword::Comment => "Comment",
Keyword::Other(s) => s,
}
}
}