///|
/// Batch operations for applying a common export policy to many animations.
pub(all) struct BatchItem {
name : String
animation : Animation
} derive(Debug)
///|
pub fn BatchItem::new(name : String, animation : Animation) -> BatchItem {
{ name, animation }
}
///|
pub fn BatchItem::name(self : BatchItem) -> String {
self.name
}
///|
pub fn BatchItem::animation(self : BatchItem) -> Animation {
self.animation
}
///|
pub(all) struct BatchReport {
processed : Int
encoded : Int
failed : Int
total_input_bytes : Int
total_output_bytes : Int
names : Array[String]
} derive(Debug)
///|
pub fn BatchReport::processed(self : BatchReport) -> Int {
self.processed
}
///|
pub fn BatchReport::encoded(self : BatchReport) -> Int {
self.encoded
}
///|
pub fn BatchReport::failed(self : BatchReport) -> Int {
self.failed
}
///|
pub fn BatchReport::total_input_bytes(self : BatchReport) -> Int {
self.total_input_bytes
}
///|
pub fn BatchReport::total_output_bytes(self : BatchReport) -> Int {
self.total_output_bytes
}
///|
pub fn BatchReport::names(self : BatchReport) -> ArrayView[String] {
self.names[:]
}
///|
/// Encode a batch, retaining successful output and continuing after failures.
pub fn encode_batch(
items : ArrayView[BatchItem],
profile : ExportProfile,
) -> (Array[(String, Bytes)], BatchReport) {
let outputs : Array[(String, Bytes)] = []
let names : Array[String] = []
let mut encoded = 0
let mut failed = 0
let mut input_bytes = 0
let mut output_bytes = 0
for item in items {
names.push(item.name())
let result : Bytes? = try {
let plan = item.animation().plan_export(profile)
let bytes = item.animation().export_with_plan(plan)
Some(bytes)
} catch {
_ => None
} noraise {
_ => None
}
match result {
None => failed += 1
Some(bytes) => {
encoded += 1
output_bytes += bytes.length()
input_bytes += item.animation().width *
item.animation().height *
item.animation().frame_count()
outputs.push((item.name(), bytes))
}
}
}
(
outputs,
BatchReport::{
processed: items.length(),
encoded,
failed,
total_input_bytes: input_bytes,
total_output_bytes: output_bytes,
names,
},
)
}
///|
/// Apply a pipeline to all batch items while preserving their names.
pub fn transform_batch(
items : ArrayView[BatchItem],
pipeline : CanvasPipeline,
) -> Array[BatchItem] {
let result : Array[BatchItem] = []
for item in items {
result.push(
BatchItem::new(item.name(), pipeline.apply_animation(item.animation())),
)
}
result
}
///|
/// Return output compression in per mille, based on measured byte totals.
pub fn BatchReport::saving_per_mille(self : BatchReport) -> Int {
if self.total_input_bytes <= 0 {
0
} else {
(self.total_input_bytes - self.total_output_bytes) *
1000 /
self.total_input_bytes
}
}