vty
vty copied to clipboard
rgbColor: Non-monotonicity, beyond-white brightness, and some documentation that confused me
The documentation for the rgbColor function in Vty-Attributes implies that each number in an RGB triple can take 16 values. After experimenting, I discovered each value can be anywhere between 0 and 255. I suspect that documentation should read "256^3" where it currently read "16^3". (Or it could be even more explicit by using a type synonym for Int, documented with its intended range.)
I also discovered that 255 yields a value brighter than Vty's built-in white. This is great for me! I imagine its intentional on your part, as Vty's "white" is (to my eyes) equal to the one used by the console generally, outside of Brick. But I wonder whether the extra headroom deserves documentation too?
Last it seems noteworthy that brighteness appears not to be monotonic. The code below, for instance, illustrates that gray 18 and gray 58 (where gray k = rgbColor k k k) are much darker than neighboring values.
I've tried this on Konsole and Terminator, and the results are almost the same. Both have roughly monotonic scaling of color from 0 to 255, with (at least) values 18 and 58 being abnormally dark. On Konsole, gray 160 looks indistinguishable to Vty's white, while on Terminator gray 160 looks too dark and gray 200 looks about equal.
Do you get the same thing, or is my system weird? (I use version 18.04 of Kubuntu (that's KDE + Ubuntu) on a Dell Inspiron laptop.)
module Hode.UI.Main where
import Brick.Util (on)
import Brick.Widgets.Core
import qualified Brick.AttrMap as B
import qualified Brick.Main as B
import qualified Brick.Types as B
import qualified Graphics.Vty as B
main :: IO ()
main = B.defaultMain app ()
app :: B.App () e ()
app = B.App
{ B.appDraw = appDraw
, B.appChooseCursor = \_ _ -> Nothing
, B.appHandleEvent = \_ _ -> B.halt ()
, B.appStartEvent = return
, B.appAttrMap = const appAttrMap
}
appDraw :: () -> [B.Widget ()]
appDraw _ =
[vBox [ withAttr (B.attrName i) $ str i
| i <- map fst someGrays ]]
appAttrMap :: B.AttrMap
appAttrMap = B.attrMap B.defAttr $
map (\(x,y) -> (B.attrName x, y)) someGrays
-- | A logarithmic sampling of the color space.
-- Maybe I should be sampling linearly.
someGrays :: [ (String, B.Attr) ]
someGrays =
let gray :: Int -> B.Color
gray k = B.rgbColor k k k
in
-- Vty's white seems to be around gray 160.
[ ( "#### This is gray 160.", gray 160 `on` B.black )
, ( "#### This is Vty's white.", B.white `on` B.black )
, ( "#### This is gray 200.", gray 200 `on` B.black ) ]
++
-- A roughly linear sampling of the color space,
-- shifted by 6 to show that values 18 and 58 are weird.
[ ("#### This is gray " ++ show i, gray i `on` gray 0)
| j <- [1..32]
, let i = max 0 $ j*8-6 ]
I just noticed that in Terminator, Vty's black is not as dark as gray 0. (In Konsole they look identical.)
I've updated/added plans to update the documentation to include these suggestions.
The non-monotonic grays occur in gnome-terminal, xfce's terminal, and vscode. they also occur if i set TERM=screen-256color; It definitely looks to be a vty issue.
Thanks, @cjenn. @JeffreyBenjaminBrown As for the other built-in colors such as white, it comes down to the terminal emulator's choice of colors. The palette used for the 16 base colors is up to the terminal so it's not at all surprising that white in your case is less "white" than 0xFFFFFF.
With the change I just pushed (linked above), I think I've done all I can do on this ticket. Please re-open tickets on more specific issues if they arise. (The non-monotonicity change is a consequence of the color conversion algorithm we use but did not design. If someone wants to recommend an alternative, I'm open to considering it.) Thanks!