Files
avatar/README.md
T

7.3 KiB
Raw Blame History

Matrix avatar

cmatrix_avatar.py generates a square avatar directly, with the original green character rain, yellow G/W/B highlights, and blue block-letter GWB. It writes both an outlined SVG and a PNG; terminal screenshots are no longer needed.

Run

Create the environment in this directory with uv:

uv venv
uv sync
uv run python cmatrix_avatar.py

The default outputs are avatar.svg and avatar.png (2048 × 2048). The default background grid is 43 rows × 77 columns. The original six-line GWB is rendered as a separate vector layer, uniformly scaled to 72% of the image width (roughly 2.1 times the background cell size) and centered. The complete background grid fits inside the square with a safety margin. Whole background cells intersecting the central logo area are left empty; all remaining cells are preserved without cropping. The reserved area includes a quarter-cell gap, and actual glyph bounds are checked to avoid sliced letters. Colors are fixed, independent of terminal themes. Rain brightness uses 32 nonlinear levels, from 0.5% to 100% of its peak. Green and yellow characters share the logo's peak luminance. The SDR logo stays exactly its original blue (#3b73fa); rain peaks are reduced to its luminance. HDR scales linear RGB without adding white, preserving the original chromaticity. The stronger gradient remains; this is not a pixel-identical restoration of the older rain palette. Shape, size, and placement are unchanged.

# Reproduce a background and also generate small previews.
uv run python cmatrix_avatar.py --seed 42 --previews

# Also write a true 16-bit HDR PNG with a shared 400-nit luminance peak.
uv run python cmatrix_avatar.py --seed 42 --hdr --peak-nits 400

# Customize the output, resolution, and complete grid dimensions.
uv run python cmatrix_avatar.py --output portraits/gwb.png --size 2048 --rows 43 --columns 77 --logo-width 0.72

# Use the original grid dimensions while retaining the independently sized logo.
uv run python cmatrix_avatar.py --rows 28 --columns 67

# Select a different monospace font.
uv run python cmatrix_avatar.py --font C:/Windows/Fonts/consola.ttf

Each run prints its random seed. Use that seed and the same font to reproduce the image with the same row/column settings. Without --seed, each run generates a new background. Existing outputs at the selected path are replaced. --output accepts a basename, a .png path, or a .svg path; both formats are always generated.

--previews adds avatar-128.png and avatar-64.png (using the chosen output basename). Use the full-size PNG for a WeChat avatar and keep the SVG as the scalable original.

HDR output

--hdr adds avatar-hdr.png, a 16-bit RGB PNG encoded with BT.2020 primaries and the ST 2084 (PQ) transfer function. PNG cICP identifies that encoding; cLLI records the measured maximum and average luminance of the encoded image. Rendering and antialiasing are composited in linear light before PQ encoding. This is an HDR signal, rather than an SDR image with a brightness filter. See the PNG specification.

--peak-nits accepts 100–2000 (default 400). This is the target luminance Y of fully covered peak characters and GWB, not the maximum individual RGB channel value. At the default setting, rain levels span 2–400 nits, with a 0.02-nit background. Quantization can introduce very small differences.

Actual HDR appearance requires an HDR display, enabled HDR output, and a viewer that understands PQ PNG metadata. An ordinary chat preview cannot demonstrate the encoded peak brightness. The regular PNG and SVG remain SDR alternatives; use the regular PNG for a WeChat avatar rather than relying on HDR preservation. The PQ PNG does not contain an SDR fallback: do not upload it expecting an unsupported viewer to reproduce the regular PNG. Display tone mapping and color volume limits can also alter the HDR appearance despite preserved encoded chromaticity.

WeChat compatibility research (2026-10-18)

No explicit official guarantee for HDR preservation in personal profile pictures was found. Tencent Cloud's HDR processing documentation describes a separate cloud service, not a guarantee for WeChat avatars. Ultra HDR JPEG can carry an SDR base and an HDR gain map, enabling SDR fallback in legacy viewers. That would be preferable to PQ-only PNG for a single adaptive file, but WeChat's upload/crop/re-encode pipeline still needs device testing to verify gain-map preservation. Use avatar.png for dependable SDR source colors; no promise is made about pixel-identical output after WeChat processing.

To package the current matching PNG/SVG pair as an adaptive Ultra HDR JPEG:

uv run python avatar_ultrahdr.py

This writes avatar-ultrahdr.jpg using pyultrahdr: a quality-100, 4:4:4 SDR JPEG base plus a full-resolution grayscale gain map and XMP/MPF metadata. The base comes directly from avatar.png, with no tone mapping or palette change. JPEG compression introduces small pixel differences. The map targets 400-nit character/logo peaks while preserving the base chromaticity; shadows never become darker than the SDR base. This differs intentionally from the PQ PNG's black level. The script reports ordinary-decoding error and checks both images are present. Actual HDR display and WeChat gain-map survival require device testing.

Rendering

OCR A Extended (C:/Windows/Fonts/OCRAEXT.TTF) is preferred on Windows: its distinctive diamond-shaped O, D, S, and W match the reference screenshot. The screenshot's historical terminal settings are unavailable; this identification is based on comparing glyph shapes, not the current Windows Terminal setting. See Microsoft's font entry.

OCR A Extended has no block/box glyphs, so GWB uses Consolas as a fallback, with the original character proportions. This preserves the logo design; the screenshot alone does not establish its original fallback font. --logo-font can override it. No proprietary font files are copied into the project.

If OCR A Extended is unavailable, the defaults fall back to Consolas, Cascadia Mono, DejaVu Sans Mono (Linux), or Menlo (macOS). --font selects the background font explicitly. A font that includes the logo glyphs is also used for GWB unless --logo-font overrides it. Cells use a height/width ratio of 1.8 to match the reference terminal; each font's outlines are first fitted to that cell aspect ratio. The assembled GWB is then scaled uniformly using --logo-width (0.4 to 0.85, default 0.72), independently of the number of background rows and columns.

FontTools converts glyphs to vector paths, and resvg renders that same SVG to PNG. The SVG embeds no raster images and requires no installed fonts to view. Pillow creates optional thumbnail previews. Dependencies are recorded in pyproject.toml and pinned in uv.lock.

Verify

uv run python -m unittest discover -s tests

Checks cover reproducible SVG paths, matching PNG rendering, logo placement, thumbnail dimensions, custom output paths, and invalid command-line options. HDR checks also cover PQ reference values, equal luminance peaks, gradients, 16-bit PNG data, color metadata, and decoded luminance measurements.