Case 886

The contrast was computed on the encoded values

the_contrast_was_computed_on_the_encoded_values.eml - An accessibility checker computes the contrast ratio of text on its background and rejects pairs below the 4.5 to 1 threshold, and it runs the standard's formula exactly over every pair. What number the formula must be fed is computed below.

ok: true — round-trip fixpoint reached (python1 == python2)updated 2026-09-17

EML

eml
# Self-authored for the EML case corpus (no external origin). An accessibility
# checker computes the contrast ratio of text on its background and rejects
# pairs below the 4.5 to 1 threshold, and it runs the standard's formula exactly
# over every pair. What number the formula must be fed is computed below.
#
# The check is careful. It reads the real text and background colours; it
# applies the standard's ratio, lighter plus 0.05 over darker plus 0.05; it
# compares against the real 4.5 threshold; and the intent is exactly 'the text
# is readable enough by the standard'.
#
# The formula wants relative luminance, which is linear light, and the checker
# fed it the encoded sRGB value divided by 255 - so a grey that passes at 4.60
# to 1 is rejected at 2.06 to 1.

117 => text_srgb
255 => background_srgb
1778 => text_luminance_per_myriad
10000 => background_luminance_per_myriad
500 => flare_term_per_myriad
450 => threshold_hundredths

int(text_srgb * 10000 / background_srgb) => text_encoded_as_if_luminance_per_myriad
background_luminance_per_myriad + flare_term_per_myriad => numerator_per_myriad
text_luminance_per_myriad + flare_term_per_myriad => true_denominator_per_myriad
int(numerator_per_myriad * 100 / true_denominator_per_myriad) => true_ratio_hundredths
text_encoded_as_if_luminance_per_myriad + flare_term_per_myriad => naive_denominator_per_myriad
int(numerator_per_myriad * 100 / naive_denominator_per_myriad) => naive_ratio_hundredths
true_ratio_hundredths - naive_ratio_hundredths => hundredths_the_encoding_hid

"text colour, sRGB               : " + str(text_srgb) ^0
"background, sRGB                : " + str(background_srgb) ^0
"threshold                       : 4.50 to 1" ^0
"" ^0
"text luminance, linear          : " + str(text_luminance_per_myriad) + " per ten thousand" ^0
"text code read as luminance     : " + str(text_encoded_as_if_luminance_per_myriad) + " per ten thousand" ^0
"contrast ratio, true            : " + str(true_ratio_hundredths) + " hundredths, passes" ^0
"contrast ratio, on encoded      : " + str(naive_ratio_hundredths) + " hundredths, fails" ^0
"ratio the encoding hid          : " + str(hundredths_the_encoding_hid) + " hundredths" ^0
"" ^0

# ---- what the check verified ----

"the contrast checker" ^0
"  reads : the real text and background colours" ^0
"  formula : the standard's, lighter plus 0.05 over darker" ^0
"    plus 0.05" ^0
"  threshold : the real 4.5" ^0
"  intent : the text is readable enough by the standard" ^0
"  pairs skipped : 0" ^0
"  verdict : 2.06 TO 1, REJECTED" ^0
"" ^0
"  applying the standard's exact ratio and threshold to the" ^0
"  real colours is the part done right here, and it is why" ^0
"  the arithmetic on the number it was given is right" ^0
"" ^0

# ---- what the formula must be fed ----

"relative luminance" ^0
"  what the standard's ratio is over : linear light, the" ^0
"    sRGB code decoded through its curve" ^0
"  code 117 decoded : " + str(text_luminance_per_myriad) + " per ten thousand of full light" ^0
"  code 117 divided by 255 : " + str(text_encoded_as_if_luminance_per_myriad) + " per ten thousand" ^0
"  so the checker's grey : is read as two and a half times" ^0
"    brighter than it is, and the ratio collapses" ^0
"  true ratio : " + str(true_ratio_hundredths) + " hundredths; on the code : " + str(naive_ratio_hundredths) ^0
"" ^0

# ---- what the designer got ----

"the verdict" ^0
"  pair submitted : grey 117 on white" ^0
"  by the standard : " + str(true_ratio_hundredths) + " hundredths, passes 4.50" ^0
"  by the checker : " + str(naive_ratio_hundredths) + " hundredths, fails" ^0
"  is the ratio formula wrong : no; it is the standard's" ^0
"  is a code a luminance : no; it is a luminance passed" ^0
"    through a curve, and the curve was not undone" ^0
"" ^0

# ---- null control ----

# The same checker, decoding sRGB to linear luminance before the ratio.
206 => nc_ratio_on_encoded_hundredths
460 => nc_ratio_on_luminance_hundredths
1 => nc_compliant_pair_no_longer_rejected

"null control - decode to luminance before the ratio" ^0
"  ratio on the encoded value : " + str(nc_ratio_on_encoded_hundredths) + " hundredths" ^0
"  ratio on linear luminance : " + str(nc_ratio_on_luminance_hundredths) + " hundredths" ^0
"  compliant pair no longer rejected : " + str(nc_compliant_pair_no_longer_rejected) ^0
"  no colour and no threshold changed; the formula stopped" ^0
"  being fed a code" ^0
"" ^0

# ---- the rule ----

"what a standard-formula contrast check guarantees" ^0
"  the ratio and threshold are the standard's : exactly, the" ^0
"    real formula over every real pair" ^0
"  the verdict is the standard's : not addressed; the formula" ^0
"    is over linear luminance and it was fed the encoded" ^0
"    code, so a pair at " + str(true_ratio_hundredths) + " hundredths reads " + str(naive_ratio_hundredths) + " and a compliant" ^0
"    grey is rejected" ^0
"" ^0

"a formula is only as right as the quantity it is handed; the standard's ratio" ^0
"applied to the standard's threshold with the wrong input is exact arithmetic" ^0
"reaching the wrong verdict, and the curve between code and light is the" ^0
"whole difference" ^0
"" ^0

"It applies the standard's exact ratio and threshold to the real colours - the" ^0
"arithmetic is right. But the formula wants linear luminance and was fed the" ^0
"sRGB code over 255, so grey " + str(text_srgb) + " on white reads " + str(naive_ratio_hundredths) + " hundredths instead of " + str(true_ratio_hundredths) + "," ^0
"and a compliant pair is rejected, until the code is decoded first." ^0

Python (deterministic transpilation)

python
text_srgb = 117
background_srgb = 255
text_luminance_per_myriad = 1778
background_luminance_per_myriad = 10000
flare_term_per_myriad = 500
threshold_hundredths = 450
text_encoded_as_if_luminance_per_myriad = int(text_srgb * 10000 / background_srgb)
numerator_per_myriad = background_luminance_per_myriad + flare_term_per_myriad
true_denominator_per_myriad = text_luminance_per_myriad + flare_term_per_myriad
true_ratio_hundredths = int(numerator_per_myriad * 100 / true_denominator_per_myriad)
naive_denominator_per_myriad = text_encoded_as_if_luminance_per_myriad + flare_term_per_myriad
naive_ratio_hundredths = int(numerator_per_myriad * 100 / naive_denominator_per_myriad)
hundredths_the_encoding_hid = true_ratio_hundredths - naive_ratio_hundredths
print("text colour, sRGB               : " + str(text_srgb))
print("background, sRGB                : " + str(background_srgb))
print("threshold                       : 4.50 to 1")
print("")
print("text luminance, linear          : " + str(text_luminance_per_myriad) + " per ten thousand")
print("text code read as luminance     : " + str(text_encoded_as_if_luminance_per_myriad) + " per ten thousand")
print("contrast ratio, true            : " + str(true_ratio_hundredths) + " hundredths, passes")
print("contrast ratio, on encoded      : " + str(naive_ratio_hundredths) + " hundredths, fails")
print("ratio the encoding hid          : " + str(hundredths_the_encoding_hid) + " hundredths")
print("")
print("the contrast checker")
print("  reads : the real text and background colours")
print("  formula : the standard's, lighter plus 0.05 over darker")
print("    plus 0.05")
print("  threshold : the real 4.5")
print("  intent : the text is readable enough by the standard")
print("  pairs skipped : 0")
print("  verdict : 2.06 TO 1, REJECTED")
print("")
print("  applying the standard's exact ratio and threshold to the")
print("  real colours is the part done right here, and it is why")
print("  the arithmetic on the number it was given is right")
print("")
print("relative luminance")
print("  what the standard's ratio is over : linear light, the")
print("    sRGB code decoded through its curve")
print("  code 117 decoded : " + str(text_luminance_per_myriad) + " per ten thousand of full light")
print("  code 117 divided by 255 : " + str(text_encoded_as_if_luminance_per_myriad) + " per ten thousand")
print("  so the checker's grey : is read as two and a half times")
print("    brighter than it is, and the ratio collapses")
print("  true ratio : " + str(true_ratio_hundredths) + " hundredths; on the code : " + str(naive_ratio_hundredths))
print("")
print("the verdict")
print("  pair submitted : grey 117 on white")
print("  by the standard : " + str(true_ratio_hundredths) + " hundredths, passes 4.50")
print("  by the checker : " + str(naive_ratio_hundredths) + " hundredths, fails")
print("  is the ratio formula wrong : no; it is the standard's")
print("  is a code a luminance : no; it is a luminance passed")
print("    through a curve, and the curve was not undone")
print("")
nc_ratio_on_encoded_hundredths = 206
nc_ratio_on_luminance_hundredths = 460
nc_compliant_pair_no_longer_rejected = 1
print("null control - decode to luminance before the ratio")
print("  ratio on the encoded value : " + str(nc_ratio_on_encoded_hundredths) + " hundredths")
print("  ratio on linear luminance : " + str(nc_ratio_on_luminance_hundredths) + " hundredths")
print("  compliant pair no longer rejected : " + str(nc_compliant_pair_no_longer_rejected))
print("  no colour and no threshold changed; the formula stopped")
print("  being fed a code")
print("")
print("what a standard-formula contrast check guarantees")
print("  the ratio and threshold are the standard's : exactly, the")
print("    real formula over every real pair")
print("  the verdict is the standard's : not addressed; the formula")
print("    is over linear luminance and it was fed the encoded")
print("    code, so a pair at " + str(true_ratio_hundredths) + " hundredths reads " + str(naive_ratio_hundredths) + " and a compliant")
print("    grey is rejected")
print("")
print("a formula is only as right as the quantity it is handed; the standard's ratio")
print("applied to the standard's threshold with the wrong input is exact arithmetic")
print("reaching the wrong verdict, and the curve between code and light is the")
print("whole difference")
print("")
print("It applies the standard's exact ratio and threshold to the real colours - the")
print("arithmetic is right. But the formula wants linear luminance and was fed the")
print("sRGB code over 255, so grey " + str(text_srgb) + " on white reads " + str(naive_ratio_hundredths) + " hundredths instead of " + str(true_ratio_hundredths) + ",")
print("and a compliant pair is rejected, until the code is decoded first.")

stdout (executed)

text
text colour, sRGB               : 117
background, sRGB                : 255
threshold                       : 4.50 to 1

text luminance, linear          : 1778 per ten thousand
text code read as luminance     : 4588 per ten thousand
contrast ratio, true            : 460 hundredths, passes
contrast ratio, on encoded      : 206 hundredths, fails
ratio the encoding hid          : 254 hundredths

the contrast checker
  reads : the real text and background colours
  formula : the standard's, lighter plus 0.05 over darker
    plus 0.05
  threshold : the real 4.5
  intent : the text is readable enough by the standard
  pairs skipped : 0
  verdict : 2.06 TO 1, REJECTED

  applying the standard's exact ratio and threshold to the
  real colours is the part done right here, and it is why
  the arithmetic on the number it was given is right

relative luminance
  what the standard's ratio is over : linear light, the
    sRGB code decoded through its curve
  code 117 decoded : 1778 per ten thousand of full light
  code 117 divided by 255 : 4588 per ten thousand
  so the checker's grey : is read as two and a half times
    brighter than it is, and the ratio collapses
  true ratio : 460 hundredths; on the code : 206

the verdict
  pair submitted : grey 117 on white
  by the standard : 460 hundredths, passes 4.50
  by the checker : 206 hundredths, fails
  is the ratio formula wrong : no; it is the standard's
  is a code a luminance : no; it is a luminance passed
    through a curve, and the curve was not undone

null control - decode to luminance before the ratio
  ratio on the encoded value : 206 hundredths
  ratio on linear luminance : 460 hundredths
  compliant pair no longer rejected : 1
  no colour and no threshold changed; the formula stopped
  being fed a code

what a standard-formula contrast check guarantees
  the ratio and threshold are the standard's : exactly, the
    real formula over every real pair
  the verdict is the standard's : not addressed; the formula
    is over linear luminance and it was fed the encoded
    code, so a pair at 460 hundredths reads 206 and a compliant
    grey is rejected

a formula is only as right as the quantity it is handed; the standard's ratio
applied to the standard's threshold with the wrong input is exact arithmetic
reaching the wrong verdict, and the curve between code and light is the
whole difference

It applies the standard's exact ratio and threshold to the real colours - the
arithmetic is right. But the formula wants linear luminance and was fed the
sRGB code over 255, so grey 117 on white reads 206 hundredths instead of 460,
and a compliant pair is rejected, until the code is decoded first.

Trace event types

eml:run:starteml:assigneml:outputeml:run:done