///|
/// A single report object for CLI diagnostics and benchmark artifacts.
pub(all) struct GifDocumentReport {
bytes : Int
width : Int
height : Int
frames : Int
duration_cs : Int
encoded_pixels : Int
unique_colors : Int
entropy_milli : Int
estimated_bytes : Int
validation_errors : Int
validation_warnings : Int
complete_index : Bool
} derive(Debug)
///|
pub fn GifDocumentReport::bytes(self : GifDocumentReport) -> Int {
self.bytes
}
///|
pub fn GifDocumentReport::width(self : GifDocumentReport) -> Int {
self.width
}
///|
pub fn GifDocumentReport::height(self : GifDocumentReport) -> Int {
self.height
}
///|
pub fn GifDocumentReport::frames(self : GifDocumentReport) -> Int {
self.frames
}
///|
pub fn GifDocumentReport::duration_cs(self : GifDocumentReport) -> Int {
self.duration_cs
}
///|
pub fn GifDocumentReport::encoded_pixels(self : GifDocumentReport) -> Int {
self.encoded_pixels
}
///|
pub fn GifDocumentReport::unique_colors(self : GifDocumentReport) -> Int {
self.unique_colors
}
///|
pub fn GifDocumentReport::entropy_milli(self : GifDocumentReport) -> Int {
self.entropy_milli
}
///|
pub fn GifDocumentReport::estimated_bytes(self : GifDocumentReport) -> Int {
self.estimated_bytes
}
///|
pub fn GifDocumentReport::validation_errors(self : GifDocumentReport) -> Int {
self.validation_errors
}
///|
pub fn GifDocumentReport::validation_warnings(self : GifDocumentReport) -> Int {
self.validation_warnings
}
///|
pub fn GifDocumentReport::complete_index(self : GifDocumentReport) -> Bool {
self.complete_index
}
///|
/// Analyze an encoded GIF without altering the input buffer.
pub fn report_gif(data : Bytes) -> GifDocumentReport raise GifError {
let info = inspect(data)
let validation = validate_gif_bytes(data)
let index = index_gif(data)
GifDocumentReport::{
bytes: data.length(),
width: info.width(),
height: info.height(),
frames: info.frame_count(),
duration_cs: 0,
encoded_pixels: info.width() * info.height() * info.frame_count(),
unique_colors: 0,
entropy_milli: 0,
estimated_bytes: data.length(),
validation_errors: validation.errors(),
validation_warnings: validation.warnings(),
complete_index: index.is_complete(),
}
}
///|
/// Analyze source animation quality and predicted export cost.
pub fn report_animation(
animation : Animation,
options : OptimizationOptions,
) -> GifDocumentReport raise GifError {
let validation = validate_animation(animation)
let complexity = animation.complexity()
let optimization = animation.optimization_report(options)
GifDocumentReport::{
bytes: 0,
width: animation.width,
height: animation.height,
frames: animation.frame_count(),
duration_cs: animation.duration_cs(),
encoded_pixels: optimization.output_pixels(),
unique_colors: complexity.mean_unique_colors(),
entropy_milli: complexity.peak_entropy(),
estimated_bytes: optimization.estimated_bytes(),
validation_errors: validation.errors(),
validation_warnings: validation.warnings(),
complete_index: false,
}
}
///|
/// Produce stable key/value text suitable for a benchmark log.
pub fn GifDocumentReport::summary(self : GifDocumentReport) -> String {
"bytes=\{self.bytes} size=\{self.width}x\{self.height} frames=\{self.frames} " +
"duration_cs=\{self.duration_cs} encoded_pixels=\{self.encoded_pixels} " +
"estimated_bytes=\{self.estimated_bytes} errors=\{self.validation_errors} " +
"warnings=\{self.validation_warnings} index=\{self.complete_index}"
}
///|
/// Compare two reports and return byte, pixel, and quality deltas.
pub fn report_delta(
before : GifDocumentReport,
after : GifDocumentReport,
) -> (Int, Int, Int) {
(
after.estimated_bytes - before.estimated_bytes,
after.encoded_pixels - before.encoded_pixels,
after.entropy_milli - before.entropy_milli,
)
}
///|
/// Report whether an export meets basic acceptance invariants.
pub fn GifDocumentReport::meets_invariants(self : GifDocumentReport) -> Bool {
self.width > 0 &&
self.height > 0 &&
self.frames > 0 &&
self.validation_errors == 0 &&
self.complete_index
}