///|
/// LZW diagnostics for compression tuning and test fixtures.
pub(all) struct LzwRoundtripReport {
input_bytes : Int
compressed_bytes : Int
decoded_bytes : Int
minimum_code_size : Int
exact : Bool
saving_per_mille : Int
} derive(Debug)
///|
pub fn LzwRoundtripReport::input_bytes(self : LzwRoundtripReport) -> Int {
self.input_bytes
}
///|
pub fn LzwRoundtripReport::compressed_bytes(self : LzwRoundtripReport) -> Int {
self.compressed_bytes
}
///|
pub fn LzwRoundtripReport::decoded_bytes(self : LzwRoundtripReport) -> Int {
self.decoded_bytes
}
///|
pub fn LzwRoundtripReport::minimum_code_size(self : LzwRoundtripReport) -> Int {
self.minimum_code_size
}
///|
pub fn LzwRoundtripReport::exact(self : LzwRoundtripReport) -> Bool {
self.exact
}
///|
pub fn LzwRoundtripReport::saving_per_mille(self : LzwRoundtripReport) -> Int {
self.saving_per_mille
}
///|
/// Encode and decode an index stream, reporting exactness and size.
pub fn lzw_roundtrip(
indices : ArrayView[Byte],
minimum_code_size : Int,
) -> LzwRoundtripReport raise GifError {
let encoded = lzw_encode(indices, minimum_code_size)
let decoded = lzw_decode(encoded, minimum_code_size, indices.length())
let mut exact = decoded.length() == indices.length()
if exact {
for i in 0.. Int {
let safe = if colors < 2 { 2 } else if colors > 256 { 256 } else { colors }
let mut bits = 1
let mut size = 2
while size < safe {
size *= 2
bits += 1
}
if bits < 2 {
2
} else {
bits
}
}
///|
/// Split indices into bounded slices for streaming quantization work.
pub fn split_indices(
indices : ArrayView[Byte],
chunk_size : Int,
) -> Array[Array[Byte]] {
let safe = if chunk_size < 1 { 1 } else { chunk_size }
let result : Array[Array[Byte]] = []
let mut offset = 0
while offset < indices.length() {
let part : Array[Byte] = []
let remaining = indices.length() - offset
let length = if remaining > safe { safe } else { remaining }
for i in 0.. Array[Byte] {
let result : Array[Byte] = []
for part in parts {
for byte in part {
result.push(byte)
}
}
result
}
///|
/// Return the number of runs in a palette index stream.
pub fn lzw_run_count(indices : ArrayView[Byte]) -> Int {
if indices.length() == 0 {
0
} else {
let mut count = 1
for i in 1.. Array[Byte] {
let safe_length = if length < 0 { 0 } else { length }
let safe_colors = if colors < 1 {
1
} else if colors > 256 {
256
} else {
colors
}
let result : Array[Byte] = []
for i in 0..