Last active
May 18, 2023 23:39
-
-
Save strainer/ca20642e9a091634f685915bd6b90e51 to your computer and use it in GitHub Desktop.
theme inversion for scite
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
constexpr Scintilla::Colour InvertLight(Scintilla::Colour c) noexcept { | |
// Integer calcs done at x16 (0..4080 + 8) 0 => 0..15 255 => 4080..4095 | |
int R = 8 + 16 * ( c & 0xffU ); | |
int G = 8 + 16 * ( (c >>8) & 0xffU ); | |
int B = 8 + 16 * ( (c >>16) & 0xffU ); | |
const int rw = 18, gw = 35, bw = 11; // Brightness factors (compromised) | |
const int lumTrast = -64; | |
// `lumTrast` is like the contrast control of televisions, | |
// except it can go into negative to produce luminosity inversion. | |
// Value of 64 = 100% contrast, -64 = -100% contrast | |
const int addBright = 0; // Adjusts output brightness -1000 > 1000 | |
const int sign = lumTrast<0 ? -1 : 1; | |
const int inLum = ( R*rw + G*gw + B*bw )/64 + 4 ; // lum of input. 8 to 4088 | |
// Calculate target luminosity of rgb | |
long lumCalc = 2044 + ( (long)(inLum-2044)*lumTrast )/64; | |
// Skew very low or high targets to be less low or high | |
if (lumCalc>15 && lumCalc<4080) { | |
long apin = 50, bpin = 550; // drags 1% bright to 12% | |
if (lumCalc<apin) { | |
lumCalc = (bpin*lumCalc/apin); | |
} else lumCalc = bpin + (lumCalc-apin)*(4096-bpin)/(4096-apin); | |
apin = 4088-50, bpin = 4088-350; // drags 99% bright to 92% | |
if (lumCalc<apin) { | |
lumCalc = (bpin*lumCalc/apin); | |
} else lumCalc = bpin + (lumCalc-apin)*(4096-bpin)/(4096-apin); | |
} | |
lumCalc += (addBright*4088)/1000; | |
int outLum = (int)( lumCalc<8? 8 : lumCalc>4088? 4088 : lumCalc ); | |
int mxc = R>G? R : G>B? G: B; // find max channel value | |
if(sign==-1 && mxc>3700 ) { // if max is near full | |
int avex = (R+G+B)*(mxc-3700)/(3000); // calculate saturation boost | |
R=R-avex ; G=G-avex ; B=B-avex; | |
int curLum = ( R*rw + G*gw + B*bw )/64; // re-estimate luminosity | |
R = (R*inLum)/curLum; // restore to inLum | |
G = (G*inLum)/curLum; | |
B = (B*inLum)/curLum; | |
} | |
int addmov = 0; | |
if (outLum > inLum) { // addmov descreases color when brightening | |
addmov = (outLum - inLum)*12/12; // move full way seems best | |
} else { // overshoot when darkening too boost color | |
addmov = outLum*2/3 - inLum; | |
} | |
R+=addmov; G+=addmov; B+=addmov; | |
if (outLum < inLum) { | |
int curLum = ( R*rw + G*gw + B*bw )/64 + 1; | |
R = (R*outLum)/curLum; // move rest of way by scaling R,G,B | |
G = (G*outLum)/curLum; | |
B = (B*outLum)/curLum; | |
} | |
// After gross Lum adjustments R,G,B values may be negative or overflow | |
const int un = 8 , ov = 4088; // Under and over flow limits | |
int rc = R<un ? R-un : R>ov ? R-ov : 0; // discern under-overflows | |
int gc = G<un ? G-un : G>ov ? G-ov : 0; | |
int bc = B<un ? B-un : B>ov ? B-ov : 0; | |
R-=rc; G-=gc; B-=bc; // remove them | |
rc = (rc*rw)/(gw+bw); // adjust carries by relative luminosity | |
gc = (gc*gw)/(rw+bw); | |
bc = (bc*bw)/(gw+rw); | |
R+=gc+bc; G+=rc+bc; B+=rc+gc; // redistribute carries | |
R-= R<un ? R-un : R>ov ? R-ov : 0; // remove any following excesses | |
G-= G<un ? G-un : G>ov ? G-ov : 0; | |
B-= B<un ? B-un : B>ov ? B-ov : 0; | |
return ColourRGB( R>>4, G>>4, B>>4 ); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment