Encode images into WEFAX (Weather Facsimile) HF radiofax audio WAV files and decode WEFAX recordings back into images. Supports IOC 576/288 at 120/60 RPM per WMO standards. Use this skill whenever the user mentions WEFAX, weather fax, radiofax, HF fax, weather map transmission, marine weather charts, NOAA radiofax, JMH, or wants to convert images to/from the FM audio format used for HF weather chart broadcasts. Also trigger when the user has a WAV file recorded from a shortwave weather fax broadcast and wants to extract the weather map image. Distinct from the fax-codec skill which handles telephone Group 3 fax — WEFAX uses FM modulation on HF radio, not DPSK on telephone lines. Covers encoding (image to WAV) and decoding (WAV to image).
What is WEFAX? HF Weather Facsimile (radiofax) is an international standard for broadcasting weather maps and charts over shortwave radio. Used by NOAA, Japan Meteorological Agency (JMH), Deutscher Wetterdienst (DWD), and many others. Images are transmitted as FM-modulated audio signals.
Key specs:
Encode: Image → WEFAX WAV
python3 wefax_encode.py weather_map.png output.wav [--ioc 576] [--rpm 120]
Decode: WEFAX WAV → Image
python3 wefax_decode.py recording.wav weather_map.png [--ioc 576] [--rpm 120]
A complete WEFAX transmission has five parts:
Start tone (300 Hz, 5 seconds)
Phasing signal (30 seconds)
Image data (variable duration)
Stop tone (450 Hz, 5 seconds)
Guard band (optional)
Signal diagram:
Time →
[300Hz] [Black/White] [FM Image Data] [450Hz]
5s 30 sec variable 5s
FM Modulation:
Basic usage:
python3 wefax_encode.py weather_map.png output.wav -v
Common options:
# Standard resolution, standard speed (IOC 576, 120 RPM)
python3 wefax_encode.py map.jpg output.wav
# Lower resolution (IOC 288)
python3 wefax_encode.py map.jpg output.wav --ioc 288
# Slow speed (60 RPM — twice as long)
python3 wefax_encode.py map.jpg output.wav --rpm 60
# Just the image, no start/stop tones
python3 wefax_encode.py map.jpg output.wav --no-start-stop
# Verbose output
python3 wefax_encode.py map.jpg output.wav -v
Image requirements:
Basic usage:
python3 wefax_decode.py recording.wav weather_map.png -v
Common options:
# Standard settings (IOC 576, 120 RPM)
python3 wefax_decode.py recording.wav output.png
# Lower resolution (match encoding)
python3 wefax_decode.py recording.wav output.png --ioc 288
# Slow speed (match encoding)
python3 wefax_decode.py recording.wav output.png --rpm 60
# Disable auto-detection (use all audio)
python3 wefax_decode.py recording.wav output.png --no-auto-detect
# Verbose output
python3 wefax_decode.py recording.wav output.png -v
Detection features:
--no-auto-detectEach pixel value is mapped to a frequency:
Frequency = 1500 Hz + (pixel_value / 255) × 800 Hz
pixel 0 (black) → 1500 Hz
pixel 127 (gray) → 1900 Hz (center)
pixel 255 (white) → 2300 Hz
The FM signal maintains continuous phase (no phase discontinuities) as the frequency changes, simulating the smooth waveform of analog radio transmission.
pixel = (freq - 1500) / 800 × 255pixel = (freq - 1500) / 800 × 255# Get a weather map image (e.g., from a weather service)
# crop it to roughly square, save as PNG
# Encode at standard resolution
python3 wefax_encode.py weather_map.png output.wav -v
# Result: 2-3 minute WAV file (depending on image height)
# Can be:
# - Played over SSB radio transmitter for broadcast
# - Uploaded as a podcast or audio file
# - Analyzed to study WEFAX signal characteristics
# Record a weather fax transmission from a shortwave receiver
# (e.g., using an SDR like RTL-SDR)
# Decode with auto-detection
python3 wefax_decode.py recording.wav weather_map.png -v
# Result: PNG image of the weather map
# Auto-detection skips start/stop tones and phasing
# If auto-detection fails (non-standard format), try:
python3 wefax_decode.py recording.wav weather_map.png --no-auto-detect
# Encode multiple weather maps
for img in weather_maps/*.png; do
python3 wefax_encode.py "$img" "${img%.png}.wav"
done
# Decode multiple recordings
for wav in recordings/*.wav; do
python3 wefax_decode.py "$wav" "${wav%.wav}.png" -v
done
# Encode a high-detail chart at low resolution (faster, smaller)
python3 wefax_encode.py detailed_chart.png output.wav --ioc 288
# Encode at slow speed for weak-signal reception
python3 wefax_encode.py map.png output_slow.wav --rpm 60
# Decode both
python3 wefax_decode.py output.wav decoded_standard.png
python3 wefax_decode.py output_slow.wav decoded_slow.png --rpm 60
Python packages:
numpy — Numeric computation, signal processingscipy — Scientific computing (Hilbert transform for FM demodulation)Pillow (PIL) — Image loading/savingwave — Standard library WAV I/OInstall:
pip install numpy scipy Pillow
System requirements:
IOC defines the horizontal resolution (pixels per line):
IOC × Line Period = Pixels Per Line × π
IOC 576 @ 120 RPM (0.5s line): 1809 pixels/line
IOC 288 @ 120 RPM (0.5s line): 904 pixels/line
IOC 576 @ 60 RPM (1.0s line): 3618 pixels/line
Higher IOC = more pixels per line = finer detail, but longer transmission time.
Line Period = 60 / RPM seconds
120 RPM: 0.5 seconds per line
60 RPM: 1.0 second per line
Line period determines how long each scan line takes to transmit.
WEFAX uses linear frequency mapping:
Frequency = 1500 + (Pixel / 255) × 800
or, inverted:
Pixel = (Frequency - 1500) / 800 × 255
This simplicity (vs. complex modulation schemes) makes WEFAX robust to noise and frequency drift.
WEFAX is defined by the World Meteorological Organization (WMO):
The standard includes timing, synchronization, and frequency specifications to ensure international interoperability.
Problem: Decoded image is blank or all noise
--no-auto-detect if tone detection is failingProblem: Image is stretched or wrong aspect ratio
Problem: Decoding takes a long time
Problem: Audio quality is poor on playback
MIT License — Use freely, modify, and distribute.