aboutsummaryrefslogtreecommitdiff
path: root/evc/src/block.rs
diff options
context:
space:
mode:
Diffstat (limited to 'evc/src/block.rs')
-rw-r--r--evc/src/block.rs57
1 files changed, 37 insertions, 20 deletions
diff --git a/evc/src/block.rs b/evc/src/block.rs
index 24691e8..04ee3d2 100644
--- a/evc/src/block.rs
+++ b/evc/src/block.rs
@@ -1,10 +1,9 @@
-use anyhow::bail;
-
use crate::{
- format::ser::{Ser, Sink, Small, Source},
+ format::ser::{ConstSizeSerExt, Sink, Small, Source},
helpers::vector::Vec2,
helpers::{matrix::Mat2, pixel::Pixel},
};
+use anyhow::bail;
#[derive(Clone, Debug)]
pub enum Block {
@@ -22,16 +21,21 @@ pub struct AdvancedReference {
}
impl Block {
- pub fn write(&self, sink: &mut impl std::io::Write) -> anyhow::Result<()> {
+ pub const REFZERO: Block = Block::Reference {
+ translation: Vec2::<isize>::ZERO,
+ };
+
+ pub fn write(&self, sink: &mut impl std::io::Write, size: Vec2<isize>) -> anyhow::Result<()> {
match &self {
Block::Literal(pixels) => {
sink.put(0u8)?;
- pixels.write(sink)?;
+ pixels.write_const_size(sink, size.area() as usize)?;
}
Block::Split(box [a, b]) => {
sink.put(1u8)?;
- a.write(sink)?;
- b.write(sink)?;
+ let [asize, bsize] = split_size(size);
+ a.write(sink, asize)?;
+ b.write(sink, bsize)?;
}
Block::Reference { translation } => {
sink.put(2u8)?;
@@ -51,20 +55,9 @@ impl Block {
pub fn read(source: &mut impl std::io::Read, size: Vec2<isize>) -> anyhow::Result<Self> {
Ok(match source.get::<u8>()? {
- 0 => Block::Literal(source.get()?),
+ 0 => Block::Literal(Vec::read_const_size(source, size.area() as usize)?),
1 => Block::Split(Box::new({
- let vert = size.x > size.y;
- let asize = if vert {
- (size.x / 2, size.y).into()
- } else {
- (size.x, size.y / 2).into()
- };
- let bsize = if vert {
- (size.x - size.x / 2, size.y).into()
- } else {
- (size.x, size.y - size.y / 2).into()
- };
-
+ let [asize, bsize] = split_size(size);
let a = Block::read(source, asize)?;
let b = Block::read(source, bsize)?;
[a, b]
@@ -82,10 +75,34 @@ impl Block {
}
}
+pub fn split_size(size: Vec2<isize>) -> [Vec2<isize>; 2] {
+ let vert = size.x > size.y;
+ [
+ if vert {
+ (size.x / 2, size.y).into()
+ } else {
+ (size.x, size.y / 2).into()
+ },
+ if vert {
+ (size.x - size.x / 2, size.y).into()
+ } else {
+ (size.x, size.y - size.y / 2).into()
+ },
+ ]
+}
+
impl Block {
pub fn is_literal(&self) -> bool {
matches!(self, Block::Literal(..))
}
+ pub fn is_ref_without_translation(&self) -> bool {
+ matches!(
+ self,
+ Block::Reference {
+ translation: Vec2::<isize>::ZERO
+ }
+ )
+ }
}
impl Default for AdvancedReference {