Skip to content

Latest commit

 

History

5 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Wezen

Dependency-free Ruby encoders for deterministic APNG, GIF, PNG, and asciinema demo media.

Gem version CI status Ruby 3.1 or newer MIT license

Features · Installation · Quick start · Output formats · Development


Wezen turns RGBA frames and terminal events into portable, reproducible demo assets. It is built for documentation, fixtures, and recording pipelines where the same input should produce the same bytes.

The name comes from δ Canis Majoris: its IAU name derives from the Arabic al-wazn, meaning “the weight.”

Features

  • Lossless APNG with optional changed-frame rectangles, plus PNG stills
  • GIF89a encoding with deterministic median-cut palettes and dithering
  • Frame coalescing, scaling, cropping, sampling, blending, and change bounds
  • Asciinema v2 JSON Lines output for terminal recordings
  • Byte-stable output for identical inputs
  • No runtime dependencies beyond Ruby's zlib and json standard libraries

Installation

Add Wezen to your Gemfile:

gem "wezen"

Then install dependencies:

bundle install

Or install the gem directly:

gem install wezen

Wezen requires Ruby 3.1 or newer.

Quick start

Create a two-frame animation and write lossless APNG and compatible GIF versions:

require "wezen"

animation = Wezen::Animation.new(width: 2, height: 1)
animation.add([255, 0, 0, 255, 0, 0, 255, 255].pack("C*"), delay_ms: 100)
animation.add([255, 0, 0, 255, 0, 255, 0, 255].pack("C*"), delay_ms: 100)

Wezen::APNG.write("demo.apng", animation)
Wezen::GIF.write("demo.gif", animation, dither: :bayer)

Frames are packed RGBA strings in row-major order. Animation#add merges identical consecutive frames and adds their delays automatically.

Output formats

Format Use case Behavior
APNG Lossless animation Preserves RGBA pixels and stores changed rectangles when possible
GIF89a Broad compatibility Uses a deterministic global palette with optional dithering
PNG Still frames Writes a single lossless RGBA image
Asciinema v2 Terminal sessions Writes chronological output, input, and resize events as JSON Lines

APNG

APNG is the preferred animation format when color and alpha fidelity matter:

bytes = Wezen::APNG.encode(animation, compression: 9, diff: true)
File.binwrite("demo.apng", bytes)

GIF

Control palette size, palette strategy, dithering, and frame differences:

Wezen::GIF.write(
  "demo.gif",
  animation,
  colors: 128,
  palette: :global,
  dither: :floyd_steinberg,
  diff: true
)

Provide a Wezen::Palette when the recording needs a fixed application palette. Supported dithering modes are :floyd_steinberg, :bayer, and :none.

PNG

Write a single packed RGBA frame:

frame = animation.each.first
Wezen::PNG.write("frame.png", animation.width, animation.height, frame.rgba)

Asciinema casts

Create an asciinema v2 recording from chronological terminal events:

events = [
  Wezen::Cast::Event.new(0.0, :output, "$ bundle exec rake\r\n"),
  Wezen::Cast::Event.new(0.4, :output, "12 examples, 0 failures\r\n")
]

Wezen::Cast.write(
  "demo.cast",
  width: 80,
  height: 24,
  title: "Test run",
  events: events
)

Event kinds are :output, :input, and :resize.

Transform animations

Every transformation returns a new Wezen::Animation:

animation = animation.coalesce(tolerance: 2)
animation = animation.scale(to_width: 640, to_height: 360)
animation = animation.crop([0, 0, 320, 180])
animation = animation.drop_to(fps: 12)

Use Wezen::Image directly for lower-level scaling, cropping, alpha blending, and changed-pixel bounds.

Design decisions

Wezen deliberately ships encoders without runtime decoders. This keeps the gem small, portable, and focused while round-trip tests validate generated media.

The architecture records explain the durable format choices:

Development

bundle install
bundle exec rake
bundle exec rake bench
bundle exec rbs -I sig validate
gem build --strict wezen.gemspec

Contributing

Bug reports and pull requests are welcome in the GitHub repository.

License

Wezen is available under the MIT License.

About

Dependency-free Ruby encoders for deterministic APNG, GIF, PNG, and asciinema demo media

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages