///|
/// OpenEXR lossless byte shuffle followed by a modulo-256 predictor.
fn predict(raw : Bytes) -> Bytes {
let n = raw.length()
let half = (n + 1) / 2
let shuffled = Array::make(n, b'\x00')
for i = 0; i < n; i = i + 1 {
shuffled[if i % 2 == 0 { i / 2 } else { half + i / 2 }] = raw[i]
}
let out = Array::make(n, b'\x00')
for i = 0; i < n; i = i + 1 {
out[i] = if i == 0 {
shuffled[i]
} else {
(shuffled[i].to_int() - shuffled[i - 1].to_int() + 128).to_byte()
}
}
Bytes::from_array(out)
}
///|
fn unpredict(encoded : Bytes) -> Bytes {
let n = encoded.length()
let half = (n + 1) / 2
let unpacked = Array::make(n, b'\x00')
let mut previous = 0
for i = 0; i < n; i = i + 1 {
previous = if i == 0 {
encoded[i].to_int()
} else {
(previous + encoded[i].to_int() - 128) & 255
}
unpacked[i] = previous.to_byte()
}
Bytes::from_array(
Array::makei(n, i => unpacked[if i % 2 == 0 { i / 2 } else { half + i / 2 }]),
)
}
///|
test "EXR predictor specified odd and even byte ordering" {
assert_eq(predict(b"\x01\x02\x03\x04\x05"), b"\x01\x82\x82\x7d\x82")
for n = 0; n < 512; n = n + 1 {
let bytes = Bytes::from_array(
Array::makei(n, i => ((i * i + i * 33) & 255).to_byte()),
)
assert_eq(unpredict(predict(bytes)), bytes)
}
}