Myndex / SAPC-APCA

APCA (Accessible Perceptual Contrast Algorithm) is a new method for predicting contrast for use in emerging web standards (WCAG 3) for determining readability contrast. APCA is derived form the SAPC (S-LUV Advanced Predictive Color) which is an accessibility-oriented color appearance model designed for self-illuminated displays.
https://git.apcacontrast.com/documentation/APCAeasyIntro
Other
442 stars 14 forks source link

Trouble Implementing APCA Equations and Constants in a Spreadsheet #12

Closed UXPublishing closed 2 years ago

UXPublishing commented 3 years ago

I am a UX professional with some amateur coding skills. I created an offline (MS Excel) accessible color theme tool to use on my independent projects. The tool originally calculated contrast based on the WCAG 2.1 Relative Luminance and Contrast equations. I discovered WCAG 3's draft and APCA. Now, I would like to update my Excel spreadsheet tool so that the contrast values are based on the APCA equations and constants.

I am encountering a few issues. 1) The W3 Silver Github repository references a different set of equation constants than the Myndex SAPC-APCA repository. I am not sure which version of the constants is the latest and/or most likely "approved" to use.

2) I've translated the equations several times based on the LaTeX graphic, the Pseudocode, and the Javascript functions. I've tested different versions of the constants. However, my spreadsheet is still returning Lc results that do no match the only known sources for "correct" calculated values: this repository's "Testing Your Implementation" listed test values, and the myndex.com/APCA and myndex.com/SAPC calculators.

"TESTING YOUR IMPLEMENTATION If you've implemented the code and want a quick sanity check, Here are four keystone checks with no rounding, where the first colos is TEXT and the4 second color is BACKGROUND:

888 vs #fff • 66.89346308821438

aaa vs #000 • -60.438571788907524

def vs #123 • -98.44863435731266

123 vs #234 • 1.276075977788573"

To solve my problem, I need to determine if the equations, as I have translated them into Excel formulas, are incorrect, and/or if the constants are incorrect. However, I can't seem to find any "correct" calculated values for the individual functions (e.g. fclamp, Snorm, Srev, H, C, Lc) so I can identify which part of the whole equation is wrong.

I think you wrote that you may create an OpenOffice Calc in the future. Would you be able to provide any guidance?

Thank you so much for creating these accessible tools for us!

Myndex commented 3 years ago

Hello @UXPublishing thank you for commenting, and I am sorry you are having troubled implementing the code.

Unfortunately, I was on another project for a few months, so I do apologize if I missed any loose ends here.

First, the very old code shown on the Silver repository is definitely incorrect. I have attempted to have it removed, but it still exists and I know it is causing problems.

Ooops — Test Values

From what I see, my error was not updating the "test values" and for that I am a bit embarrassed.

Here are the correct test values:

888 vs #fff • 63.056469930209424

aaa vs #000 • -56.24113336839742

def vs #123 • -93.06770049484275

123 vs #234 • 1.7512243099356113

Thank you

MORE THAN ANYTHING, thank you for bringing this to my attention. Please let me know if these test numbers sync up with you implementation.

Live Models

ALSO: the current "basic" working model is https://www.myndex.com/APCA/

But there is a more complete model at https://www.myndex.com/SAPC/ which includes a "research mode" and displays the constants being used, as well as featuring some interactive experiments that illustrate the concepts.

Please let me know if this solves the issue for you, and also if you have any further questions.

Thank you!!

Andy

UXPublishing commented 3 years ago

Hi Andy,

Thanks for helping me solve one of the issues!

Unfortunately, the Excel formulas I created are still not returning the same results as the myndex.com/APCA/ and myndex.com/SAPC/ calculators. I've triple checked everything and made sure to use the same constants as the SAPC calculator. I must have mistranslated some part of the equations, but I can't seem to find the error.

Do you still plan to post an OpenOffice Calc in the future? Would it be sometime soon?

Myndex commented 3 years ago

The most current constants are 0.98G 4g

Note the Rco, Gco, and Bco shown here are using the matrix values, instead of the rounded values. Either is acceptable.

mainTRC: 2.4,

Rco: 0.2126729, 
Gco: 0.7151522, 
Bco: 0.0721750, 

normBG: 0.56,
normTXT: 0.57,
revTXT: 0.62,
revBG: 0.65,

blkThrs: 0.022,
blkClmp: 1.414, 

scaleBoW: 1.14, 
scaleWoB: 1.14, 

loBoWthresh: 0.035991,
loBoWfactor: 27.7847239587675, 
loBoWoffset: 0.027,

loWoBthresh: 0.035991,
loWoBfactor: 27.7847239587675, 
loWoBoffset: 0.027,

loClip: 0.001,
deltaYmin: 0.0005,

Relevant Code Snippets

Assuming you have converted the BG and TXT to Y:

Soft clamps @ black:

Ytxt = (Ytxt > blkThrs) ? Ytxt : Ytxt + Math.pow(blkThrs - Ytxt, blkClmp);
Ybg = (Ybg > blkThrs) ? Ybg : Ybg + Math.pow(blkThrs - Ybg, blkClmp);

Discard very low ∆Y and return

if(Math.abs(Ybg - Ytxt) < deltaYmin){ return 0.0 }

And then the main code

//////////   SAPC CONTRAST MODULE       ////////////////////////////////////

    if ( Ybg > Ytxt ) {   // For normal polarity, black text on white

    SAPC = ( Math.pow(Ybg, normBG) - Math.pow(Ytxt, normTXT) ) * scaleBoW;

            // Low Contrast smooth rollout to prevent polarity reversal and also a low clip for very low contrasts
    outputContrast = ( SAPC < loClip ) ? 0.0 : ( SAPC < loBoWthresh ) ?  SAPC - SAPC * loBoWfactor * loBoWoffset : SAPC - loBoWoffset;

    } else {  // For reverse polarity, light text on dark -- WoB should always return negative value.

    SAPC = ( Math.pow(Ybg, revBG) - Math.pow(Ytxt, revTXT) ) * scaleWoB;

    outputContrast = ( SAPC > -loClip ) ? 0.0 :  ( SAPC > -loWoBthresh ) ?  SAPC - SAPC * loWoBfactor * loWoBoffset : SAPC + loWoBoffset;
    }

    return  outputContrast * 100

For production use, the return value can be rounded to the nearest whole number.

And again, thank you, I see I need to do some housekeeping here!

Andy

Myndex commented 3 years ago

Hi Andy, Thanks for helping me solve one of the issues!

Unfortunately, the Excel formulas I created are still not returning the same results as the myndex.com/APCA/ and myndex.com/SAPC/ calculators. I've triple checked everything and made sure to use the same constants as the SAPC calculator. I must have mistranslated some part of the equations, but I can't seem to find the error.

Do you still plan to post an OpenOffice Calc in the future? Would it be sometime soon?

And yes, I was writing the above message before I saw your reply — through March there were a lot of updates and adjustments, and there are further studies in the works, and potentially some additional adjustments. So if you take a look at the most recent post above, I indicate the most recent constants as well (G4g).

I could work on an OpenOffice version, and have been planning to.

I'll post here when available, and I'll keep this issue open — please let me know if you have other questions.

Again, sorry for any confusions, as this is a project in active research, there are occasional changes like these.

Thank you!

Andy

Myndex commented 3 years ago

Hi @UXPublishing

There is now a LibreOffice/OpenOffice spreadsheet of the 0.98g-4g version.

Link: https://github.com/Myndex/SAPC-APCA/blob/master/SAPC-0.98g-4g.ods

Please let me know of any issues or questions. I'm closing this issue for now.

Thank you

Andy

UXPublishing commented 3 years ago

Hi Andy, Thank you so much for clarifying the equations and constants. And, thank you for creating the ODS file! I was able to pin point exactly what was causing my formulas to return slightly different contrast values than the myndex.com/SAPC calculator.

I used a different set of formulas to calculate the linear RGB value for each color component. As a result, my formulas (based on WCAG 2.1) calculated a relative luminance that was slightly different than the relative luminance calculated by myndex.com/SAPC/.

My assumption is that if I want my tool to return the exact same results as the myndex.com/SAPC/ calculator, then I should use the APCA-SAPC linearization method. The question is does the linearization method matter. Is the WCAG 2.1 linearization formula more accurate? If yes, should I use it for both the WCAG 2.1 Relative Luminance calculations as well as the newer APCA Relative Luminance calculations?

Myndex commented 3 years ago

Hi Andy, Thank you so much for clarifying the equations and constants. And, thank you for creating the ODS file! I was able to pin point exactly what was causing my formulas to return slightly different contrast values than the myndex.com/SAPC calculator.

Hi @UXPublishing No problem, and thanks for asking, I think it will be helpful to others to have the ODS as a demonstrator.

My assumption is that if I want my tool to return the exact same results as the myndex.com/SAPC/ calculator, then I should use the APCA-SAPC linearization method.

It's a must do.

The SAPC linearization is tied in to the rest of the math, in particular the black soft-clamp that shapes the Y at input. It is a complete set of equations that should not be separated.

The question is does the linearization method matter. Is the WCAG 2.1 linearization formula more accurate? If yes, should I use it for both the WCAG 2.1 Relative Luminance calculations as well as the newer APCA Relative Luminance calculations?

WCAG 2.1 contrast is wrong in general, see thread #695 on the WCAG GitHub repo, the first link in this list of links to relevant posts: https://github.com/Myndex/Myndex/blob/main/IssuesIndex.md

WCAG 2.1 linearization formula is not exactly accurate, and actually references a wrong, obsolete spec, and not the official sRGB standard. But moreover, that piecewise linearization was created in the sRGB spec for math/data processing purposes to emulate an approximate 2.2 gamma curve, but prevent infinite slope at zero, and not necessarily actual monitor behavior. The IEC spec indicates in multiple places that monitors use a simple exponent TRC.

SAPC is more focused on modeling real-world display conditions, and predicting human perception of contrast for readability. The specific constants used all work together to provide accurate contrast prediction over the entire range of luminances (with a small increase in very dark color pairs).

Use only the SAPC linearization with the SAPC or APCA math.


Side Bar: Why Y is not Eye

But as far as the linearization methods, the piecewise is not a "more accurate" method to find perceived luminance — human perception is not nearly so simple. Blue for instance does not necessarily add to luminance, blue can have a subtractive effect on perceived luminance. Neither the piecewise nor the simple exponent version of linearization considers this. Really a 3D LUT is needed to get this level of accuracy.

Human perception is not linear. Light is linear, but we are not. Luminance Y or L does not follow perception, other than it is spectrally weighted. Y is not lightness/darkness/brightness weighted — those are human perceptions.

Displays are engineered so that R=G=B=White (or gray), but "everything gets whacky" when we move away from that 0 chroma point. Display primaries are chosen not for peak cone responses, but instead to affect the target cone more than the other cones. In the newer UHD displays (Rec2020/2100) the red primary is on the locus and affects the L cone with minimal interaction to the M cone.

But at in the middle of the spectrum, the L and M cone responses overlap so much that the green primary affects them both substantially. Blue, at the short end of the spectrum affects "mainly" the S cone... but there are no S cones in the fovea, and in fact only a very few S cones scattered in the periphery (among the reasons that blue cannot display small details).

Here's an example: the in each rectangle, the yellow patch and the white patch are identical except for the blue channel. In the yellow, the blue is zero, but the red and green values are the same as in the white patch. Depending on the surround, does the yellow seem lighter or darker than the white?

Screen Shot 2021-07-18 at 3 43 03 PM
From the top:
BG    Yellow  White
#000   #bb0   #bbb
#777   #cc0   #ccc
#ccc   #dd0   #ddd
#fff   #ee0   #eee

In the sRGB linearization, the coefficient is specified as 7% blue added to luminance... but depending on other factors, it's not necessarily 7%, and can even be considered nil or negative, depending.

Since APCA is all about readability contrast, some of these subtle differences can be sidelined. Nevertheless there are some un-released modules that take some of these chroma-specific variations into account.

Thank you for your comments, let me know if you have other questions!

Andy

UXPublishing commented 3 years ago

Andy,

Thank you so much for clarifying. You have been a tremendous help.

Since it may take a few years to define and approve the WCAG 3 APCA method, I was planning to use both WCAG 2.1 Contrast and APCA Contrast. I will use the WCAG 2.1 Contrast method as it is defined (incl. the alternate linearization method), and then I will use the APCA contrast method as it is defined.

I am trying to determine how WCAG 3 and APCA applies to user interface components and graphical objects that currently fall into the WCAG 2.1 1.4.11 Non-text Contrast bucket. Specifically, if/how APCA applies to adjacent colors. The Lc Font Size and Weight Lookup Table seems to state that all text (incl. text parts of user interface components and graphics) should follow the APCA minimum contrast guidelines. I am just not sure what minimum contrast levels to use with the graphical objects such as icons, progress bars, chart lines, or chart axis lines. Would I just compare the height of the graphical object or line (in px) to the Lc Font Size (in px)?

Myndex commented 3 years ago

Hi @UXPublishing

Thank you so much for clarifying. You have been a tremendous help.

No problem.

Since it may take a few years to define and approve the WCAG 3 APCA method, I was planning to use both WCAG 2.1 Contrast and APCA Contrast. I will use the WCAG 2.1 Contrast method as it is defined ....SNIP... the APCA contrast method as it is defined.

Yes they are two different and incompatible methodologies. Nevertheless, we are working on a WCAG 2.x version of APCA as an interim step.

I am trying to determine how WCAG 3 and APCA applies to user interface components and graphical objects that currently fall into the WCAG 2.1 1.4.11 Non-text Contrast bucket. SNIP... I am just not sure what minimum contrast levels to use with the graphical objects such as icons, progress bars, chart lines, or chart axis lines. Would I just compare the height of the graphical object or line (in px) to the Lc Font Size (in px)?

Think in terms of stroke width. If the letter T of a font for a given contrast has a stroke width of 4px (not counting anti-aliasing), then 4px is the stroke width you'd want as a minimum for a non-text element at that same contrast...

EXCEPT: keep in mind that the APCA values are targeted at readability, which is a higher contrast than legibility. There are some more clear guidelines in the works, but suffice to say it is not relative to font body height, it is relative to glyph weight, i.e. the major stroke width of a glyph. This is because contrast perception is dependent on spatial frequency.

Still, non-text objects are a little different as they are processed by different areas of the brain. For body text, the critical contrast needs to be high enough that the text is filtered through the Visual Word Form Area (VWFA) so that whole words and letter pairs are recognized. But objects and object recognition is a little different.

Nevertheless, line thickness is key, and is part of the luminance contrast filtering at the entry stage of the visual cortex, V1. Thinner lines need a higher contrast color pair to be perceived.

This is getting into basic theory. You might want to look over my notes on the Visual Contrast Wiki:

https://www.w3.org/WAI/GL/task-forces/silver/wiki/Visual_Contrast_of_Text_Subgroup

Thank you,

Andy

UXPublishing commented 3 years ago

Hi Andy,

Thank you for clarifying. I'll definitely follow your guidance until the specifications are published.