Skip to content

var-gr/gifx

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

GIFX

A backwards-compatible image container that hides modern image formats inside a valid GIF.

Quick visual example

Original source (anim.webp):

Original animated WebP example

GIFX hybrid fallback view (anim-gifx.gif):

GIFX hybrid fallback example

These are embedded from:

GIFX solves a problem almost every web developer and designer has run into: GIFs are universally supported, but they look terrible. Modern formats like animated WebP and APNG are dramatically smaller and cleaner, but plenty of platforms, email clients, legacy apps, and social pipelines still choke on them.

GIFX gives you both. The file is a real, valid GIF that works everywhere. But for apps that know what to look for, the original high-fidelity payload is right there inside.


The problem

  • GIF works in every client, browser, and chat app since the 90s. But 256 colours, no alpha blending, and bloated file sizes make it a poor choice for anything complex.
  • WebP and APNG look great and compress well, yet plenty of tools still strip, corrupt, or refuse them. Try sending an animated WebP through an older email pipeline, a CMS with strict asset rules, or a social platform that re-encodes everything.

You end up choosing between universal compatibility and acceptable quality.

The solution

GIFX embeds the original image (WebP, APNG, PNG, JPEG, or anything else Pillow can read) as a hidden payload inside a standard GIF file.

  • Old clients, viewers, and platforms see a normal GIF and display the fallback. Nothing breaks.
  • GIFX-aware websites and tools detect the hidden payload and serve the original instead. Users get the better format without you maintaining two separate asset pipelines.

The GIF fallback is auto-generated for you, and you can dial the quality up or down with --scale, --colors, and --fps-divisor. The embedded payload itself is never touched – it stays pixel-perfect.


Quick start

Install

pip install Pillow

Encode

Wrap a high-quality source image into a GIFX hybrid:

python gifx.py encode input.webp output.gif

Options:

Flag Default Description
--scale 0.5 GIF fallback resolution scale
--colors 64 GIF palette size (2–256)
--fps-divisor 2 Keep every Nth frame to shrink the GIF
--mime auto Override the embedded MIME type

Decode

Extract the hidden payload from a GIFX file:

python gifx.py decode input.gif output.webp

Inspect

Check what is inside a GIFX file without extracting:

python gifx.py inspect input.gif

Using GIFX in the browser

Drop the JavaScript files into your project and add data-gifx to any image:

<img data-gifx="/assets/animation.gif" alt="Animation">
import { mountGifxImages, loadGifx, parseGifx } from './gifx.js';

// Auto-replace all data-gifx images on page load
await mountGifxImages();

// Or load manually
const blob = await loadGifx('/assets/animation.gif');
img.src = URL.createObjectURL(blob);

The browser script automatically falls back to the GIF if:

  • the file is a plain GIF with no GIFX payload, or
  • the browser does not support animated WebP (detected at runtime).

How it works

A GIFX file is structured like this:

[GIF data ... 0x3B]   <-- standard GIF, ends with the normal trailer byte
[GIFX]                <-- 4-byte magic signature
[version]             <-- format version (1 byte)
[flags]               <-- bitfield: animated, etc. (1 byte)
[mime_len]            --
[payload_len]         --
[mime bytes]          --
[payload bytes]       <-- the original image, untouched

The GIF is fully valid and self-contained. The extra bytes after the trailer are ignored by ordinary decoders, but GIFX parsers know to look for the GIFX signature immediately after 0x3B.


File overview

File Purpose
gifx.py Command-line encoder, decoder, and inspector
gifx-core.js Low-level parser: reads a GIFX file and returns the payload
gifx-browser.js High-level helpers: loadGifx, mountGifxImages, animated-WebP feature detection
gifx.js Single import path that re-exports both core and browser APIs

A live demo is hosted on GitHub Pages: https://var-gr.github.io/gifx

The demo shows the automatic data-gifx mounting, manual loadGifx usage, and a side-by-side comparison of the original WebP versus the GIF fallback.


Why not just use <picture>?

The <picture> element is great for responsive images, but it does not help when:

  • an asset must pass through a platform that re-encodes or strips unknown formats,
  • you need one file that works as an attachment, embed, or download,
  • legacy consumers do not parse HTML at all.

GIFX keeps everything in one container. The fallback is literally inside the same file.


Licence

MIT. See LICENSE.