// Copyright 2026 International Digital Economy Academy
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
///|
fn paeth_predictor(a : Int, b : Int, c : Int) -> Int {
let p = a + b - c
let pa = if p > a { p - a } else { a - p }
let pb = if p > b { p - b } else { b - p }
let pc = if p > c { p - c } else { c - p }
if pa <= pb && pa <= pc {
a
} else if pb <= pc {
b
} else {
c
}
}
///|
/// Reconstruct a filtered scanline (decode side).
/// `filter_type`: 0=None, 1=Sub, 2=Up, 3=Average, 4=Paeth
fn reconstruct_row(
filter_type : Int,
row : Bytes,
prev : Bytes,
bpp : Int,
) -> Bytes raise DecodeError {
let len = row.length()
let buf = FixedArray::make(len, b'\x00')
match filter_type {
0 => buf.blit_from_bytes(0, row, 0, len)
1 =>
for i in 0..= bpp { buf[i - bpp].to_int() } else { 0 }
buf[i] = ((row[i].to_int() + a) % 256).to_byte()
}
2 =>
for i in 0..
for i in 0..= bpp { buf[i - bpp].to_int() } else { 0 }
let b = prev[i].to_int()
buf[i] = ((row[i].to_int() + (a + b) / 2) % 256).to_byte()
}
4 =>
for i in 0..= bpp { buf[i - bpp].to_int() } else { 0 }
let b = prev[i].to_int()
let c = if i >= bpp { prev[i - bpp].to_int() } else { 0 }
buf[i] = ((row[i].to_int() + paeth_predictor(a, b, c)) % 256).to_byte()
}
_ => raise CorruptData("unknown filter type: " + filter_type.to_string())
}
Bytes::from_array(buf)
}