figif-core 0.1.0

GIF frame analysis and manipulation library with plugin architecture
Documentation

figif-core

A Rust library for GIF frame analysis and manipulation with a plugin architecture.

figif-core provides tools for:

  • Duplicate Detection: Identify similar/duplicate frames using perceptual hashing
  • Segment Analysis: Group consecutive similar frames into logical segments
  • Timing Control: Modify frame delays to speed up, slow down, or collapse segments
  • Export: Re-encode GIFs with applied modifications

Quick Start

use figif_core::prelude::*;

// Create analyzer with default settings (uses dHash)
let figif = Figif::new();

// Analyze a GIF file
let analysis = figif.analyze_file("demo.gif")?;

// Inspect detected segments
for segment in &analysis.segments {
    println!(
        "Segment {}: {} frames, {}ms, static={}",
        segment.id,
        segment.frame_count(),
        segment.duration_ms(),
        segment.is_static
    );
}

// Cap all pause segments to max 300ms
let ops = analysis.pauses().cap(300);

// Export with a lossless encoder
let encoder = StandardEncoder::new();
analysis.export_to_file(&encoder, &ops, "output.gif", &EncodeConfig::default())?;
# Ok::<(), Box<dyn std::error::Error>>(())

Fluent Selector API

The selector API provides chainable, ergonomic control over segment operations:

use figif_core::prelude::*;

let analysis = Figif::new().analyze_file("demo.gif")?;

// Cap all pauses to 300ms
let ops = analysis.pauses().cap(300);

// Collapse only long pauses (> 500ms) to 200ms
let ops = analysis.pauses().longer_than(500).collapse(200);

// Remove pauses longer than 1 second
let ops = analysis.pauses().longer_than(1000).remove();

// Speed up motion segments by 1.5x
let ops = analysis.motion().speed_up(1.5);

// Combine operations: cap long pauses AND speed up motion
let ops = analysis.pauses().longer_than(500).cap(300)
    .merge(&analysis.motion().speed_up(1.2));

// Get statistics
println!("Pause count: {}", analysis.pauses().count());
println!("Pause duration: {}ms", analysis.pauses().total_duration_ms());
# Ok::<(), Box<dyn std::error::Error>>(())

Using Different Hashers

use figif_core::{Figif, hashers::{PHasher, BlockHasher}};

// Use pHash for more robust matching
let figif = Figif::new()
    .with_hasher(PHasher::new())
    .similarity_threshold(8);

// Or use BlockHash
let figif = Figif::new()
    .with_hasher(BlockHasher::with_size(16, 16));

Lossy Encoding (requires lossy feature)

#[cfg(feature = "lossy")]
{
    use figif_core::encoders::GifskiEncoder;
    use figif_core::EncodeConfig;

    let encoder = GifskiEncoder::with_quality(85);
    let config = EncodeConfig::new()
        .with_width(480)
        .with_lossy_quality(80);

    let bytes = analysis.export(&encoder, &ops, &config)?;
}

Feature Flags

  • parallel (default): Enable parallel frame hashing using rayon
  • lossy: Enable GifskiEncoder for high-quality lossy compression

Plugin Architecture

figif-core is designed to be extensible. You can implement custom:

  • Hashers: Implement [traits::FrameHasher] for custom duplicate detection
  • Decoders: Implement [traits::GifDecoder] for custom loading
  • Encoders: Implement [traits::GifEncoder] for custom output formats
  • Similarity Metrics: Implement [traits::SimilarityMetric] for custom comparison