1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
|
use std::{
io::{stdin, stdout, Read, Write},
ops::Index,
};
const WIDTH: usize = 1920;
const HEIGHT: usize = 1080;
fn main() {
let mut oframe = Frame::new();
loop {
let iframe = Frame::read(stdin());
// let diff = oframe.average_area_diff(&iframe, Area::root());
// eprintln!("{diff:?}");
oframe.apply_area_diff(Area::root(), diff);
oframe.write(stdout());
// oframe = iframe;
}
}
pub fn decode(f: &mut Frame, area: Area, tree: DiffTree) {
oframe.apply_area_diff(Area::root(), diff);
}
pub enum DiffTree {
Split([Box<DiffTree>; 2]),
Diff(PixelDiff),
}
pub fn stuff(a: &Frame, b: &Frame, area: Area) -> DiffTree {
if area.area() == 1 {
DiffTree::Diff(Frame::diff_pixel(a, b, area.x1, area.y1))
} else {
let (aa, ba) = area.split();
let (at, bt) = (stuff(a, b, aa), stuff(a, b, ba));
DiffTree::Split([Box::new(at), Box::new(bt)])
}
}
#[derive(Debug)]
pub struct Frame(Vec<u8>);
#[derive(Debug)]
pub struct PixelDiff([i8; 3]);
#[derive(Debug, Clone, Copy)]
pub struct Area {
x1: usize,
y1: usize,
x2: usize,
y2: usize,
}
impl Frame {
pub fn new() -> Self {
Self(vec![0u8; WIDTH * HEIGHT * 3])
}
pub fn read(mut r: impl Read) -> Self {
let mut f = Frame::new();
r.read_exact(&mut f.0).unwrap();
f
}
pub fn write(&self, mut w: impl Write) {
w.write_all(&self.0).unwrap()
}
pub fn diff_pixel(a: &Frame, b: &Frame, x: usize, y: usize) -> PixelDiff {
let o = (x + y * WIDTH) * 3;
PixelDiff([
(a.0[o + 0] as i16 - b.0[o + 0] as i16).clamp(i8::MIN as i16, i8::MAX as i16) as i8,
(a.0[o + 1] as i16 - b.0[o + 1] as i16).clamp(i8::MIN as i16, i8::MAX as i16) as i8,
(a.0[o + 2] as i16 - b.0[o + 2] as i16).clamp(i8::MIN as i16, i8::MAX as i16) as i8,
])
}
pub fn apply_area_diff(&mut self, Area { x1, y1, x2, y2 }: Area, p: PixelDiff) {
for x in x1..x2 {
for y in y1..y2 {
let o = (x + y * WIDTH) * 3;
self.0[o + 0] = self.0[o + 0].saturating_add_signed(p.0[0]);
self.0[o + 1] = self.0[o + 1].saturating_add_signed(p.0[1]);
self.0[o + 2] = self.0[o + 2].saturating_add_signed(p.0[2]);
}
}
}
pub fn average_area_diff(
&self,
other: &Frame,
area @ Area { x1, y1, x2, y2 }: Area,
) -> PixelDiff {
let (mut r, mut g, mut b) = (0i32, 0i32, 0i32);
for x in x1..x2 {
for y in y1..y2 {
let o = (x + y * WIDTH) * 3;
r += other.0[o + 0] as i32 - self.0[o + 0] as i32;
g += other.0[o + 1] as i32 - self.0[o + 1] as i32;
b += other.0[o + 2] as i32 - self.0[o + 2] as i32;
}
}
let a = area.area() as i32;
PixelDiff([
(r / a).clamp(i8::MIN as i32, i8::MAX as i32) as i8,
(g / a).clamp(i8::MIN as i32, i8::MAX as i32) as i8,
(b / a).clamp(i8::MIN as i32, i8::MAX as i32) as i8,
])
}
}
impl Area {
pub fn area(&self) -> usize {
self.width() as usize * self.height() as usize
}
pub fn width(&self) -> usize {
self.x2 - self.x1
}
pub fn height(&self) -> usize {
self.y2 - self.y1
}
pub fn root() -> Self {
Area {
x1: 0,
y1: 0,
x2: WIDTH,
y2: HEIGHT,
}
}
pub fn split(&self) -> (Self, Self) {
let Area { x1, y1, x2, y2 } = *self;
if self.width() > self.height() {
let xm = (self.x1 + self.x2) / 2;
(Self { x1, x2: xm, y1, y2 }, Self { x1: xm, x2, y1, y2 })
} else {
let ym = (self.y1 + self.y2) / 2;
(Self { x1, x2, y1, y2: ym }, Self { x1, x2, y1: ym, y2 })
}
}
}
|