How to invert hexadecimal RGB values ​​unlike PHP

So far I have the code below:

function hexrgb_invert($hex) { $arr = str_split($hex, 2); foreach ($arr as &$value) { $c = base_convert($value, 16, 10); $value = str_pad(base_convert(255 - $c, 10, 16), 2, '0', STR_PAD_LEFT); } return implode('', $arr); } 

Problem: I need to invert colors based on contrast. The above function works for some things, but not for others.

Example: If the input signal is 9d702f , the output will be 9d702f . (2 colors with low contrast)

I did not find any luck elsewhere in StackOverflow, since most of the answers seem to use the same algorithm that I already use.


Other examples:

Say I'm trying to find the opposite of #FFFFFF (white). This is very straightforward because white is the primary color, so it can be easily calculated. (Which above will work fine for.) The opposite is #FFFFFF , of course, #000000 (black), and when you compare 2 colors, you get a 21: 1 contrast ratio .

However, if we try to use the same function above with the color #808080 , it will give us the color #7F7F7F . These 2 colors are almost identical and have a contrast ratio of just 1.01: 1 . This is because the closer you get the hex value of 80 (decimal 128 ), the less contrast the function can provide.

In the specific case of #808080 color of #000000 will provide the greatest constrast at 5.32: 1 .


Decision:

 function rgb_best_contrast($r, $g, $b) { return array( 'r' => ($r < 128) ? 255 : 0, 'g' => ($g < 128) ? 255 : 0, 'b' => ($b < 128) ? 255 : 0 ); } 
+5
source share
3 answers

Having tried several dozen different methods to try to calculate the best contrast color of the opposite color for any given color, I finally broke down and started manually testing individual color contrasts.

I used this script to search the entire RGB color space for the best match for any given color:

 $test_a = ['r' => 128, 'g' => 128, 'b' => 128]; $best = [ 'color' => ['r' => 128, 'g' => 128, 'b' => 128], 'diff' => 0.0 ]; foreach (range(0, 255) as $r) { foreach (range(0, 255) as $g) { foreach (range(0, 255) as $b) { $test_b = ['r' => $r, 'g' => $g, 'b' => $b]; // YQI sensitive contrast check $diff = check::rgb_contrast($test_a, $test_b); if ($diff > $best['diff']) { $best = [ 'color' => $test_b, 'diff' => $diff ]; } } } } var_dump($best); 

In short, a very obvious template appeared with all my results. This function works with this template:

 function rgb_best_contrast($r, $g, $b) { return array( 'r' => ($r < 128) ? 255 : 0, 'g' => ($g < 128) ? 255 : 0, 'b' => ($b < 128) ? 255 : 0 ); } 

It works exactly as expected. Always gives the best contrasting color.

0
source

str_pad adds characters to the right by default - its optional argument $pad_type defaults to STR_PAD_RIGHT .

You need to make it add zeros to the left :

 str_pad(base_convert(255 - $c, 10, 16), 2, '0', STR_PAD_LEFT) 

Your example in detail:

  • Input: 6ff060 , considering only the value of G : $c = 0xf0 (decimal: 240).
  • 255 - 240 = 15 (hex: f)
  • base_convert(255 - $c, 10, 16) produces: 'f' (like a string!)
  • str_pad(base_convert(255 - $c, 10, 16), 2, '0') adds one zero to the right , creating 'f0' .
  • Setting $pad_type = STR_PAD_LEFT fixes the problem.
+2
source

This will make your work a lot easier and very easy to use https://github.com/villfa/php-invert-color

0
source

All Articles