let from_sRGB sRGB = if sRGB <= 0.03928 then sRGB /. 12.92 else ((sRGB +. 0.055) /. 1.055) ** 2.4 type rgb = { r: float ; g: float ; b: float } (* https://www.w3.org/TR/2008/REC-WCAG20-20081211/#relativeluminancedef *) let relativeLuminance (c: rgb) = 0.2126 *. from_sRGB (c.r /. 255.) +. 0.7152 *. from_sRGB (c.g /. 255.) +. 0.0722 *. from_sRGB (c.b /. 255.) (* https://www.w3.org/TR/2008/REC-WCAG20-20081211/#contrastratio *) let contrast_ratio (c1: rgb) (c2: rgb) = let rl1 = relativeLuminance c1 in let rl2 = relativeLuminance c2 in if (rl1 > rl2) then (rl1 +. 0.05) /. (rl2 +. 0.05) else (rl2 +. 0.05) /. (rl1 +. 0.05) let from_raw color = let get_opt = function | Some x -> x | None -> raise (Invalid_argument "Option.get") in let div = H.div [| HA.style ("color: " ^ color) |] [| |] in let body = Document.query_selector_unsafe "body" in let () = Element.append_child body div in let rgb = [%raw {| window.getComputedStyle(div).color |}] in let () = Element.remove_child body div in let xs = Js.String.split ", " (get_opt (Js.String.splitByRe [%re "/[()]/"] rgb).(1)) in { r = Js.Float.fromString xs.(0) ; g = Js.Float.fromString xs.(1) ; b = Js.Float.fromString xs.(2) }