The image rendering logic in py/visdom/init.py currently uses an implicit conversion pathway that runs np.squeeze on all 1-channel images and duplicates the single channel to force it into RGB.
This introduces two key issues:
- Unsafe Spatial Squeezing: For narrow grayscale images of shape (1, 1, 100) (e.g. single pixel lines), np.squeeze collapses both the channel and the height dimension, reducing it to a 1D array (100,). This causes a ValueError: axes don't match array crash during transposition.
- Redundant Grayscale Duplication: Duplicating single-channel grayscale inputs into RGB triples the network payload size unnecessarily, as PIL and browsers natively support grayscale (L mode).
- No format validation: RGBA and unsupported channel counts (e.g. 2 channels) are handled implicitly, throwing generic NumPy errors rather than descriptive fail-fast messages.
Steps to Reproduce the Crash:
import visdom
vis = visdom.Visdom()
crash_case = np.random.rand(1, 1, 100)
vis.image(crash_case) # ValueError: axes don't match array
The image rendering logic in py/visdom/init.py currently uses an implicit conversion pathway that runs np.squeeze on all 1-channel images and duplicates the single channel to force it into RGB.
This introduces two key issues:
Steps to Reproduce the Crash: