Recent

Author Topic: [Solved] How to obtain the complementary color of a TColor ?  (Read 1547 times)

circular

  • Hero Member
  • *****
  • Posts: 3045
    • Personal webpage
Re: [Solved] How to obtain the complementary color of a TColor ?
« Reply #15 on: July 19, 2019, 08:05:14 am »
You can probably use a cast a mask and the not operator? Should be faster than subtraction. It does a bit-wise negation.
I was worried by that in the past but in practice it made no difference. Subtracting is not so complicated, for example if you compare that to multiplication.

The main thing, is that I didn't understand that ( déjà vu ):
To call or not to call SwapRedBlue depends from my material context, and the purpose of this call:
- depending on the CPU processor type (Motorola versus Intel), I will write - in a file - AColor's RGB in that order ie RGB; or inversed ie BGR (cross-compilation problems are not yet fully in my head).
- depending on the logic of use: let's say I found a pretty #aabbcc color on a website, i.e. a hexdecimal representation in @string format ==> it means that Red='#aa', Green='#bb', and Blue='#cc'. If you want to assign this same compiled color, then $aabbcc to a Canvas property, it will not work: indeed, the binary bits are read from right to left (as @circular pointed out). So, the compiled equivalent will have to be: Red=$cc, Green=$bb Blue=$cc (lately, I've been developing with interpreted Javascript code).
Yep.

Note that when writing a file, if you write each byte individually, then you can just follow the specification of the file format. Otherwise, well TColor contains 4 bytes, so what we're saying here about swaping red and blue will be incomplete.

Quote
PS: another simple manipulation of the bytes, to obtain 3 differents colors - which contrast with each other at most - is the "triadic color scheme": if color_base=aabbcc ==> triad_1=bbccaa, triad_2=ccaabb.
Indeed.
Conscience is the debugger of the mind

Thaddy

  • Hero Member
  • *****
  • Posts: 9274
Re: [Solved] How to obtain the complementary color of a TColor ?
« Reply #16 on: July 19, 2019, 09:28:43 am »
You can probably use a cast a mask and the not operator? Should be faster than subtraction. It does a bit-wise negation.
I was worried by that in the past but in practice it made no difference. Subtracting is not so complicated, for example if you compare that to multiplication.
Well, not or negation operates on only one register, subtraction on two.... On arm it makes a difference. That was my ratio.
But I never applied this on graphics, only on audio.
also related to equus asinus.

wp

  • Hero Member
  • *****
  • Posts: 6447
Re: [Solved] How to obtain the complementary color of a TColor ?
« Reply #17 on: July 19, 2019, 09:35:38 am »
PS: another simple manipulation of the bytes, to obtain 3 differents colors - which contrast with each other at most - is the "triadic color scheme": if color_base=aabbcc ==> triad_1=bbccaa, triad_2=ccaabb.
In this algorithm, the original and modified colors will have no or little contrast when aa, bb and cc are equal or almost equal.
Lazarus trunk / fpc 3.0.4 / all 32-bit on Win-10

devEric69

  • Full Member
  • ***
  • Posts: 156
Re: [Solved] How to obtain the complementary color of a TColor ?
« Reply #18 on: July 19, 2019, 10:14:44 am »
Indeed.
But the complementary and trid colors are the only 2 algorithms, to obtain colors by simple manipulations of R, G and B. Afterwards, the algorithms become more complicated (need to use the chromatic circle and to use [radians] angles, shadow degrees i.e. gray percentage, highlighting...).
I saw that there was an impressive library of objects \ methods to manage these concepts, once they were understood (which is not yet my case): https://wiki.lazarus.freepascal.org/mbColorLib .

In fact I use the complementary color sparingly (contrast is what tires the eyes the most): it's just to "massively" affect the color of the fonts in opposition to the color of the Canvas of their parent component, with recursive RTTI (I happily tested my Delphi RTTI routines: they work very well with Lazarus).
use: Ubuntu 18.04 + Laz. 1.8.5 + FPC 3.0.5 (64 bits).

wp

  • Hero Member
  • *****
  • Posts: 6447
Re: [Solved] How to obtain the complementary color of a TColor ?
« Reply #19 on: July 19, 2019, 04:29:41 pm »
But the complementary and trid colors are the only 2 algorithms, to obtain colors by simple manipulations of R, G and B.
Be careful with absolute statements ("the only 2 algorithms"). I know a third one, the result is less distracting than the multicolored ComplemantaryColor:
Code: Pascal  [Select]
  1. function HighContrastColor(AColor: TColor): TColor;
  2. var
  3.   sum: Integer;
  4. begin
  5.   sum := Red(AColor) + Green(AColor + Blue(AColor);
  6.   if sum < 3*128 then     // AColor is rather "dark" ---> return white
  7.     Result := clWhite
  8.   else                    // AColor is rather "bright" --> return black
  9.     Result := clBlack;
  10. end;

I am attaching a demo showing the high-contrast, complementary color and two byte-swapping functions.
« Last Edit: July 19, 2019, 05:20:57 pm by wp »
Lazarus trunk / fpc 3.0.4 / all 32-bit on Win-10

devEric69

  • Full Member
  • ***
  • Posts: 156
Re: [Solved] How to obtain the complementary color of a TColor ?
« Reply #20 on: July 19, 2019, 05:20:06 pm »
Yeah: it's true that the "complementary" is rather ineffective in the middle of a grey environment :D .
Thank you for sharing.
« Last Edit: July 19, 2019, 05:23:13 pm by devEric69 »
use: Ubuntu 18.04 + Laz. 1.8.5 + FPC 3.0.5 (64 bits).

circular

  • Hero Member
  • *****
  • Posts: 3045
    • Personal webpage
Re: [Solved] How to obtain the complementary color of a TColor ?
« Reply #21 on: July 19, 2019, 07:13:29 pm »
Well, not or negation operates on only one register, subtraction on two.... On arm it makes a difference. That was my ratio.
But I never applied this on graphics, only on audio.
Not sure how you could use only one register here as the not is applied to 3 bytes, not the highest byte.
Conscience is the debugger of the mind

lucamar

  • Hero Member
  • *****
  • Posts: 2120
Re: [Solved] How to obtain the complementary color of a TColor ?
« Reply #22 on: July 19, 2019, 07:34:37 pm »
Not sure how you could use only one register here as the not is applied to 3 bytes, not the highest byte.

Processor registers are four (or eight) bytes long, so no problem, is there? I mean, the highest pixel format is 32 bit: it just fits in a 386 register.
Turbo Pascal 3 CP/M - Amstrad PCW 8256 (512 KB !!!) :P
Lazarus 2.0.2/2.0.4  - FPC 3.0.4 on:
(K|L)Ubuntu 12..16, Windows XP SP3, various DOSes.

circular

  • Hero Member
  • *****
  • Posts: 3045
    • Personal webpage
Re: [Solved] How to obtain the complementary color of a TColor ?
« Reply #23 on: July 20, 2019, 05:18:35 pm »
Processor registers are four (or eight) bytes long, so no problem, is there? I mean, the highest pixel format is 32 bit: it just fits in a 386 register.
Sure but the not instruction cannot be applied on 3 bytes. To invert only part of the value, one could do a xor with a mask, but where does the mask come from? Either a register or an immediate value.
Conscience is the debugger of the mind

Thaddy

  • Hero Member
  • *****
  • Posts: 9274
Re: [Solved] How to obtain the complementary color of a TColor ?
« Reply #24 on: July 20, 2019, 09:48:05 pm »
Sure but the not instruction cannot be applied on 3 bytes. To invert only part of the value, one could do a xor with a mask, but where does the mask come from? Either a register or an immediate value.
Hence the mask on a 32 bit  values, masking out the least significant byte.. You can also not the individual  bytes of course, but that would be slower.
also related to equus asinus.

circular

  • Hero Member
  • *****
  • Posts: 3045
    • Personal webpage
Re: [Solved] How to obtain the complementary color of a TColor ?
« Reply #25 on: July 22, 2019, 12:18:21 pm »
Yes
Conscience is the debugger of the mind

Bazzao

  • Full Member
  • ***
  • Posts: 145
  • Pies are squared.
Re: [Solved] How to obtain the complementary color of a TColor ?
« Reply #26 on: July 24, 2019, 11:41:08 pm »
Hi,

I was using the Jedi's method JvgUtils.ComplementaryColor(AColor: TColor): TColor; , under Delphi.
Is there an equivalent in FPC or LCL packages?

I found this years ago and it works quite well.

Code: Pascal  [Select]
  1. var I,R,G,B:integer;  
  2.   R:=Red(Memo1.Color);
  3.   G:=Green(Memo1.Color);
  4.   B:=Blue(Memo1.Color);
  5.   I:=Round(Sqrt(R*R*0.241+G*G*0.691+B*B*0.068));
  6.   if I>128 then
  7.     Memo1.Font.Color:=clBlack
  8.   else
  9.     Memo1.Font.Color:=clWhite;
  10.  

The result colour is only black or white.

B
Bazza

Lazarus 1.6.4 r54278 FPC 3.0.2 x86_64-win64-win32/win64
Windows 10.