ImageWidget::LoadImageFile creates UI textures without the sRGB flag 0x10000.
The UI, however, is drawn into an sRGB swap chain whose widget shaders expect sRGB textures.
clunky workaround is to wrap everything in .imageset, so i figured out how it works
Imagesets pass the sRGB flag; nothing else differs. Both paths use the same texture loader, the same texture creation, the same file and the same shader.
To fix this issue, simply
Pass the sRGB flag from ImageWidget::LoadImageFile: (noCache << 9) | 0x18080 instead of (noCache << 9) | 0x8080, the value LoadImageSet already uses.