aboutsummaryrefslogtreecommitdiff
path: root/bv1/codec/src/serialize.rs
diff options
context:
space:
mode:
authormetamuffin <metamuffin@disroot.org>2023-03-09 22:48:33 +0100
committermetamuffin <metamuffin@disroot.org>2023-03-09 22:48:33 +0100
commit680b08e6b9d64284b7992fb52a23e5f891291406 (patch)
treeabe30a9f18be09ef931b4b6357d216f6ba982095 /bv1/codec/src/serialize.rs
parentc45f80a14ecd00914eb1d4e8f628b74a713667ba (diff)
downloadvideo-codec-experiments-680b08e6b9d64284b7992fb52a23e5f891291406.tar
video-codec-experiments-680b08e6b9d64284b7992fb52a23e5f891291406.tar.bz2
video-codec-experiments-680b08e6b9d64284b7992fb52a23e5f891291406.tar.zst
rename + readme
Diffstat (limited to 'bv1/codec/src/serialize.rs')
-rw-r--r--bv1/codec/src/serialize.rs116
1 files changed, 116 insertions, 0 deletions
diff --git a/bv1/codec/src/serialize.rs b/bv1/codec/src/serialize.rs
new file mode 100644
index 0000000..960aa1b
--- /dev/null
+++ b/bv1/codec/src/serialize.rs
@@ -0,0 +1,116 @@
+use crate::{split::split, Block, Pixel, Ref, View, P2};
+use std::io::{Read, Result, Write};
+
+impl Pixel {
+ #[inline]
+ pub fn write(&self, w: &mut impl Write) -> Result<()> {
+ w.write_all(&[
+ self.r.clamp(0, 255) as u8,
+ self.g.clamp(0, 255) as u8,
+ self.b.clamp(0, 255) as u8,
+ ])
+ }
+ #[inline]
+ pub fn read(r: &mut impl Read) -> Result<Pixel> {
+ Ok(Self {
+ r: read_byte(r)? as i16,
+ g: read_byte(r)? as i16,
+ b: read_byte(r)? as i16,
+ })
+ }
+}
+impl Pixel {
+ #[inline]
+ pub fn write_full(&self, w: &mut impl Write) -> Result<()> {
+ write_word(w, self.r)?;
+ write_word(w, self.g)?;
+ write_word(w, self.b)?;
+ Ok(())
+ }
+ #[inline]
+ pub fn read_full(r: &mut impl Read) -> Result<Pixel> {
+ Ok(Self {
+ r: read_word(r)?,
+ g: read_word(r)?,
+ b: read_word(r)?,
+ })
+ }
+}
+impl P2 {
+ #[inline]
+ pub fn write(&self, w: &mut impl Write) -> Result<()> {
+ write_word(w, self.x as i16)?;
+ write_word(w, self.y as i16)?;
+ Ok(())
+ }
+
+ #[inline]
+ pub fn read(r: &mut impl Read) -> Result<P2> {
+ Ok(Self {
+ x: read_word(r)? as i32,
+ y: read_word(r)? as i32,
+ })
+ }
+}
+
+impl Block {
+ pub fn write(&self, w: &mut impl Write) -> Result<()> {
+ match self {
+ Block::Split(a, b) => {
+ w.write_all(&[0])?;
+ a.write(w)?;
+ b.write(w)?;
+ }
+ Block::Lit(pixels) => {
+ w.write_all(&[1])?;
+ for p in pixels {
+ p.write(w)?;
+ }
+ }
+ Block::Ref(k) => {
+ w.write_all(&[2])?;
+ k.pos_off.write(w)?;
+ k.color_off.write_full(w)?;
+ }
+ }
+ Ok(())
+ }
+ pub fn read(r: &mut impl Read, view: View) -> Result<Block> {
+ match read_byte(r)? {
+ 0 => {
+ let [av, bv] = split(view);
+ Ok(Block::Split(
+ box Block::read(r, av)?,
+ box Block::read(r, bv)?,
+ ))
+ }
+ 1 => {
+ let mut px = vec![];
+ for _ in 0..view.size().area() {
+ px.push(Pixel::read(r)?)
+ }
+ Ok(Block::Lit(px))
+ }
+ 2 => Ok(Block::Ref(Ref {
+ pos_off: P2::read(r)?,
+ color_off: Pixel::read_full(r)?,
+ })),
+ _ => Err(std::io::Error::other("unknown block variant")),
+ }
+ }
+}
+
+#[inline]
+fn read_byte(r: &mut impl Read) -> Result<u8> {
+ let mut buf = [0u8];
+ r.read_exact(&mut buf)?;
+ Ok(buf[0])
+}
+#[inline]
+fn write_word(w: &mut impl Write, v: i16) -> Result<()> {
+ w.write_all(&[(v & 0xff) as u8, (v >> 8) as u8])
+}
+#[inline]
+fn read_word(r: &mut impl Read) -> Result<i16> {
+ Ok((read_byte(r)? as u16 | ((read_byte(r)? as u16) << 8)) as i16)
+}