Skip to main content

Replace colors across every frame of a GIF from the command line.

Project description

GIF Color Changer

Command line tool for replacing colors across every frame of a GIF.

Install

uv tool install gif-color-changer

From a local checkout:

uv tool install .

Usage

gifcc input.gif output.gif \
  --map "#FFFFFF=#FF0000" \
  --map "#000000=#00FF00"

Each --map is:

source_color=replacement_color

So this:

--map "#FFFFFF=#FF0000"

means:

replace white with red

You can pass as many mappings as you need. They run in order, and a pixel is only changed once.

Alpha is not part of color matching. The tool only changes RGB values and preserves each pixel's original alpha value, including fully transparent pixels.

Tolerance

GIF colors are often not exactly what they look like, especially after palette conversion or compression. Use --tolerance to match colors that are close to the source color.

gifcc input.gif output.gif \
  --map "#FFFFFF=#FF0000" \
  --tolerance 20

The default tolerance is 50.

Softness

Use --softness to blend pixels near the edge of the tolerance range instead of fully replacing every matched pixel.

gifcc input.gif output.gif \
  --map "#FFFFFF=#FF0000" \
  --tolerance 20 \
  --softness 8

With --tolerance 20 --softness 8, pixels within distance 12 of the source color are fully replaced. Pixels between 12 and 20 are blended proportionally from their original color toward the replacement color.

The default softness is 25. Use --softness 0 for hard replacement.

Palette Rewrite Mode

Palette mode rewrites every pixel by mapping its RGB value to the nearest color in a source palette, then forcing it to the color at the same position in a target palette. Alpha values are preserved unchanged.

gifcc input.gif output.gif \
  --source-palette "#000000,#808080,#FFFFFF" \
  --target-palette "#1D3557,#E63946,#F1FAEE"

Both palettes must contain the same number of colors. The source and target palettes are matched by position, so the first source color maps to the first target color, the second source color maps to the second target color, and so on.

Palette mode cannot be combined with --map, --tolerance, or --softness.

By default, palette mode uses squared RGB distance. Use --distance weighted-rgb to weight channel differences by perceptual luminance:

gifcc input.gif output.gif \
  --source-palette "#000000,#808080,#FFFFFF" \
  --target-palette "#1D3557,#E63946,#F1FAEE" \
  --distance weighted-rgb

Edge cleanup

Because each pixel is classified to its nearest palette color independently, antialiased or dithered pixels along an edge can land in a different bucket than the region around them, leaving isolated speckles of an unexpected color.

Use --cleanup to run one or more cleanup passes that reassign such pixels to the palette bucket that dominates their neighborhood:

gifcc input.gif output.gif \
  --source-palette "#000000,#808080,#FFFFFF" \
  --target-palette "#1D3557,#E63946,#F1FAEE" \
  --cleanup 2

Each pass reassigns a pixel whenever some other bucket occupies more of its 8-neighborhood than its own bucket does, snapping it to whichever neighbor color surrounds it most. This absorbs isolated speckles and the thin intermediate-color bands that form along antialiased edges, while pixels inside a solid region or on a real boundary are left intact, because their own side still dominates their neighborhood. More passes dissolve thicker bands but can also erode thin, legitimate detail.

Transparency is treated as just another region, so a pixel takes on the color and opacity of whatever surrounds it most. A stray opaque pixel sitting in transparent space becomes transparent, and a transparent hole inside a solid region fills in with that region's color. This also means a visible pixel bordering transparency is never recolored toward the hidden color of the transparent area around it.

--cleanup defaults to 0 (off) and is only valid in palette mode.

Output

The script prints how many pixels were changed for each mapping:

(255, 255, 255) -> (255, 0, 0): changed 1234 pixel(s)

In palette mode, it prints how many pixels were assigned to each source palette bucket:

(0, 0, 0) -> (29, 53, 87): assigned 1234 pixel(s)

If a mapping says it changed 0 pixels, the source color probably does not exist in the GIF at that tolerance.

Uninstall

uv tool uninstall gif-color-changer

Development

Set up the repo:

uv sync

Run tests:

uv run pytest

Run tests against a specific Python version:

uv run --python 3.11 pytest

Or use the Makefile:

make test
make test-all
make test-3.11

Run the command without installing it as a tool:

uv run gifcc input.gif output.gif \
  --map "#FFFFFF=#FF0000"

You can also run the compatibility wrapper directly:

uv run python main.py input.gif output.gif \
  --map "#FFFFFF=#FF0000"

Build

uv build

That writes the package artifacts to dist/.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

gif_color_changer-0.4.0.tar.gz (6.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

gif_color_changer-0.4.0-py3-none-any.whl (8.5 kB view details)

Uploaded Python 3

File details

Details for the file gif_color_changer-0.4.0.tar.gz.

File metadata

  • Download URL: gif_color_changer-0.4.0.tar.gz
  • Upload date:
  • Size: 6.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.7 {"installer":{"name":"uv","version":"0.11.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for gif_color_changer-0.4.0.tar.gz
Algorithm Hash digest
SHA256 6b9bd0eff48be8a6f32bd7a1e0e515072c9df63de5254dbd89617b5d7bd56cc6
MD5 e8944388fb908497877b2a20ccc8af2e
BLAKE2b-256 dfc9b124c4b39093abdef947283439da4961ef4ff7f97a66c38e1bd07947604c

See more details on using hashes here.

File details

Details for the file gif_color_changer-0.4.0-py3-none-any.whl.

File metadata

  • Download URL: gif_color_changer-0.4.0-py3-none-any.whl
  • Upload date:
  • Size: 8.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.7 {"installer":{"name":"uv","version":"0.11.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for gif_color_changer-0.4.0-py3-none-any.whl
Algorithm Hash digest
SHA256 a678ce4bf28efd52aebfd3332a1282a512a21e348d6614be5d9e61a4458fdbe3
MD5 40ada19195bb96810cd5bdae3ec7e910
BLAKE2b-256 5e84dc96262bfa4f95e5ef9504984f4f50df1e7c3fc584bd1b99c5244bce487f

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page