How do I convert longhand hex to RGB(A)?
For example, I have the following code to convert all formats of hex, colorname, etc.. to RGBA for background opacity, but for some reason longhand hex does not work, but instead takes the shorthand from the longhand (eg. background-color: #0000ff; becomes background-color: #000;).
Alot of the code below is based off of Convert hex color to RGB values in PHP but that question and similar questions are not able to resolve my issue. I spent 2 weeks looking for an answer to this, and have yet to find one, so I come here.
Color name to hex function:
function color_name_to_hex($color_name) {
$colors = array(
'aliceblue'=>'F0F8FF',
'antiquewhite'=>'FAEBD7',
'aqua'=>'00FFFF',
'aquamarine'=>'7FFFD4',
'azure'=>'F0FFFF',
'beige'=>'F5F5DC',
'bisque'=>'FFE4C4',
'black'=>'000000',
'blanchedalmond '=>'FFEBCD',
'blue'=>'0000FF',
'blueviolet'=>'8A2BE2',
'brown'=>'A52A2A',
'burlywood'=>'DEB887',
'cadetblue'=>'5F9EA0',
'chartreuse'=>'7FFF00',
'chocolate'=>'D2691E',
'coral'=>'FF7F50',
'cornflowerblue'=>'6495ED',
'cornsilk'=>'FFF8DC',
'crimson'=>'DC143C',
'cyan'=>'00FFFF',
'darkblue'=>'00008B',
'darkcyan'=>'008B8B',
'darkgoldenrod'=>'B8860B',
'darkgray'=>'A9A9A9',
'darkgreen'=>'006400',
'darkgrey'=>'A9A9A9',
'darkkhaki'=>'BDB76B',
'darkmagenta'=>'8B008B',
'darkolivegreen'=>'556B2F',
'darkorange'=>'FF8C00',
'darkorchid'=>'9932CC',
'darkred'=>'8B0000',
'darksalmon'=>'E9967A',
'darkseagreen'=>'8FBC8F',
'darkslateblue'=>'483D8B',
'darkslategray'=>'2F4F4F',
'darkslategrey'=>'2F4F4F',
'darkturquoise'=>'00CED1',
'darkviolet'=>'9400D3',
'deeppink'=>'FF1493',
'deepskyblue'=>'00BFFF',
'dimgray'=>'696969',
'dimgrey'=>'696969',
'dodgerblue'=>'1E90FF',
'firebrick'=>'B22222',
'floralwhite'=>'FFFAF0',
'forestgreen'=>'228B22',
'fuchsia'=>'FF00FF',
'gainsboro'=>'DCDCDC',
'ghostwhite'=>'F8F8FF',
'gold'=>'FFD700',
'goldenrod'=>'DAA520',
'gray'=>'808080',
'green'=>'008000',
'greenyellow'=>'ADFF2F',
'grey'=>'808080',
'honeydew'=>'F0FFF0',
'hotpink'=>'FF69B4',
'indianred'=>'CD5C5C',
'indigo'=>'4B0082',
'ivory'=>'FFFFF0',
'khaki'=>'F0E68C',
'lavender'=>'E6E6FA',
'lavenderblush'=>'FFF0F5',
'lawngreen'=>'7CFC00',
'lemonchiffon'=>'FFFACD',
'lightblue'=>'ADD8E6',
'lightcoral'=>'F08080',
'lightcyan'=>'E0FFFF',
'lightgoldenrodyellow'=>'FAFAD2',
'lightgray'=>'D3D3D3',
'lightgreen'=>'90EE90',
'lightgrey'=>'D3D3D3',
'lightpink'=>'FFB6C1',
'lightsalmon'=>'FFA07A',
'lightseagreen'=>'20B2AA',
'lightskyblue'=>'87CEFA',
'lightslategray'=>'778899',
'lightslategrey'=>'778899',
'lightsteelblue'=>'B0C4DE',
'lightyellow'=>'FFFFE0',
'lime'=>'00FF00',
'limegreen'=>'32CD32',
'linen'=>'FAF0E6',
'magenta'=>'FF00FF',
'maroon'=>'800000',
'mediumaquamarine'=>'66CDAA',
'mediumblue'=>'0000CD',
'mediumorchid'=>'BA55D3',
'mediumpurple'=>'9370D0',
'mediumseagreen'=>'3CB371',
'mediumslateblue'=>'7B68EE',
'mediumspringgreen'=>'00FA9A',
'mediumturquoise'=>'48D1CC',
'mediumvioletred'=>'C71585',
'midnightblue'=>'191970',
'mintcream'=>'F5FFFA',
'mistyrose'=>'FFE4E1',
'moccasin'=>'FFE4B5',
'navajowhite'=>'FFDEAD',
'navy'=>'000080',
'oldlace'=>'FDF5E6',
'olive'=>'808000',
'olivedrab'=>'6B8E23',
'orange'=>'FFA500',
'orangered'=>'FF4500',
'orchid'=>'DA70D6',
'palegoldenrod'=>'EEE8AA',
'palegreen'=>'98FB98',
'paleturquoise'=>'AFEEEE',
'palevioletred'=>'DB7093',
'papayawhip'=>'FFEFD5',
'peachpuff'=>'FFDAB9',
'peru'=>'CD853F',
'pink'=>'FFC0CB',
'plum'=>'DDA0DD',
'powderblue'=>'B0E0E6',
'purple'=>'800080',
'red'=>'FF0000',
'rosybrown'=>'BC8F8F',
'royalblue'=>'4169E1',
'saddlebrown'=>'8B4513',
'salmon'=>'FA8072',
'sandybrown'=>'F4A460',
'seagreen'=>'2E8B57',
'seashell'=>'FFF5EE',
'sienna'=>'A0522D',
'silver'=>'C0C0C0',
'skyblue'=>'87CEEB',
'slateblue'=>'6A5ACD',
'slategray'=>'708090',
'slategrey'=>'708090',
'snow'=>'FFFAFA',
'springgreen'=>'00FF7F',
'steelblue'=>'4682B4',
'tan'=>'D2B48C',
'teal'=>'008080',
'thistle'=>'D8BFD8',
'tomato'=>'FF6347',
'turquoise'=>'40E0D0',
'violet'=>'EE82EE',
'wheat'=>'F5DEB3',
'white'=>'FFFFFF',
'whitesmoke'=>'F5F5F5',
'yellow'=>'FFFF00',
'yellowgreen'=>'9ACD32');
$color_name = strtolower($color_name);
if (isset($colors[$color_name]))
{
return ('#' . $colors[$color_name]);
}
else
{
return ($color_name);
}
}
Get that function and don't do if already RGB:
$content__background_color = '#0000FF';
if(strpos($content__background_color, 'rgb') !== false){
$rgbarr = explode(",",$content__background_color,3);
$colorname = sprintf("#%02x%02x%02x", $rgbarr[0], $rgbarr[1], $rgbarr[2]);
} else {
$colorname = self::color_name_to_hex($content__background_color);
}
Convert to RGBA:
list($r, $g, $b) = array_map(function($c){return hexdec(str_pad($c, 2, $c));}, str_split(ltrim($colorname, '#'), strlen($colorname > 4 ? 2 : 1)));
$send_to_less_example[ 'content-opacity-level' ] = "rgba($r, $g, $b, " . '75' / 100.00 . ')';
return $send_to_less_example;
Any ideas would be greatly appreciated.
The algorithm is fine, you just have a wrong closing parenthesis at strlen($colorname > 4 ? 2 : 1) it should be strlen($colorname) > 4 ? 2 : 1 so change it to be like this and you'll have it working:
list($r, $g, $b) = array_map(
function($c) {
return hexdec(str_pad($c, 2, $c));
},
str_split(ltrim($colorname, '#'), strlen($colorname) > 4 ? 2 : 1)
);
You can see it working at sandbox.onlinephpfunctions.com.
Related
I am having a code written in python
from base64 import b32encode, b32decode
somename = 'Karthik Bhat K'
b32encoded = b32encode(somename)
b32decoded = b32decode(b32encoded)
I want to write the b32encode and b32decode code in php because the key generated by python is used by app written in php.
Php does have base64_encode but for base32_encode I didn't find any builtins
I am currently using custom written function
// Note this functions can be improved!
function base32_encode($d): string{
// position mapping of characters
list($t, $b, $r) = array("ABCDEFGHIJKLMNOPQRSTUVWXYZ234567", "", "");
foreach(str_split($d) as $c) {
// Get 8 bits for each character
$b = $b . sprintf("%08b", ord($c));
}
// Since there are only 32 element in b32encode i.e A-Z and 2-7
// split the binary with 5 bits in each chunk
// since 2 ^ 5 is 32, gives items between 0 and 31
foreach(str_split($b, 5) as $c) {
// If any group has less than 5 bits fill it with 0 from the right
if (strlen($c) < 5)
$c = str_pad($c, 5, "0", STR_PAD_RIGHT);
// bindec converts binary to decimal
// The decimal is index in the array $t
// Get the value from the index of array $t
$r = $r . $t[bindec($c)];
}
return($r);
}
function base32_decode($d): string{
list($t, $b, $r) = array("ABCDEFGHIJKLMNOPQRSTUVWXYZ234567", "", "");
// Encode just split bit string into set of 5 character each
// This is the reverse of it. Find index in $t and convert it into
// 5 bit string and join each of them
foreach(str_split($d) as $c)
$b = $b . sprintf("%05b", strpos($t, $c));
// Each 8 bit of the string $b will give you the decoded string
foreach(str_split($b, 8) as $c) {
if (bindec($c)) { // Ignores the padding given in base32_encode
$r = $r . chr(bindec($c));
}
}
return($r);
}
The function below finds the number, rounds it off and puts a K or M on the end of it
IE: 25000 becomes 25K
function abbr_no($number) {
$number = preg_replace('/[^0-9]/', '', $number);
$numbers = array('', 'K', 'M');
if ($number == 0) {
return('n/a');
} else {
return (round($number/pow(10000, ($i = floor(log($number, 10000)))), 0) . $numbers[$i]);
}
}
and so it basically does what I want, but as is for a number like 389345 it rounds it off and spits out 39K (as it should) however I would like the result to be 398K (3 digit number)
Now in the last return line:
0) . $numbers[$i]);
if I change the 0 to a 1 the result becomes 39.8K but again I don't want the decimal point so I am currently stuck and have hit a brickwall
As always all help is appreciated and thank you in advance.
This allows you to convert on all sorts of scales,
function humanize($val, $postfix)
{
foreach ($postfix as $p=>$div) {
$t=round($val/$div) . $p;
if (strlen($t)<(3+strlen($p))) {
break;
}
}
return trim($t);
}
e.g.
$postfix=array(''=>1, 'K'=>1000,'M'=>1000000,'B'=>1000000000);
To answer the original question,
$postfix=array('walnut' => 0.16, 'chicken egg'=>0.35,
'grapefruit' => 1, 'bulgarian airbag' => 1.1,
'bulgarian funbag'=>3.27, 'football' => 11.07,
'olympic swim pool' => 4780114, 'known universe'=>1.17456E4933);
for the Vulture Central Weights and Measures Soviet volume standard.
without editing much of your code you can add additional if statement
test if the modular division by 1
yournumber%1
($i = floor(log($number, 10000)))), 0) % 1
gives you 0
if it doesnt then
multiply your number by 10 (you can make it a while statement so it multiplies it by 10 until there are no spaces after decimal point)
then return that number
so if you use your_number like 39.8 as an example it would look like this
while(your_number%1 != 0){
your_number*=10;
}
return your_number;
This a quick fix but its definitely not the best way to code this
I'd like to know if exists some function to automatically format a number by it's decimal, so if I have:
<?php
// $sql_result["col_number"] == 1,455.75
number_format ($sql_result["col_number"], 2, ".", "");
// will return 1455.75
// $sql_result["col_number"] == 1,455.00
number_format ($sql_result["col_number"], 2, ".", "");
// could I get 1455 instead of 1455.00?
?>
so my answer is if does exist some way to remove the decimals if I have DECIMAL data forma in my DB only when it's round?
Or shoud I do something like that?
<?php
// $sql_result["col_number"] == 1,455.00
str_replace(".00", "", (string)number_format ($sql_result["col_number"], 2, ".", ""));
// will return 1455
?>
floatval or simply casting to float
php > echo floatval(7.00);
7
php > echo floatval(2.30);
2.3
php > echo floatval(1.25);
1.25
php > echo floatval(1.125);
1.125
php > echo (float) 7.00;
7
php > echo (float) 2.30;
2.3
php > echo (float) 1.25;
1.25
php > echo (float) 1.125;
1.125
I actually think that your workaround is as good as any. It's simple and clear, and there's really no point talking about performance here, so just go for it.
As Emil says yours are good. But if you want to remove 0 from e.g. 7.50 too, I've got a suggestion, rtrim():
<?php
// if $sql_result["col_number"] == 1,455.50
rtrim(rtrim(number_format($sql_result["col_number"], 2, ".", ""), '0'), '.');
// will return 1455.5
?>
You could also use rtrim(), which would remove excess 0s, in the case where you might want to keep one decimal place but not the excess zeros. (For example, 4.50 becomes 4.5.) Also allows you to change the number of decimal places from 2 to any other number.
rtrim(rtrim((string)number_format($value, 2, ".", ""),"0"),".");
// 4.00 -> 4
// 4.50 -> 4.5
// 4.54000000 -> 4.54 (if you're doing more decimal places)
Actually I think the cleanest way I can think of to do this for someone that just did a search looking for this sort of thing is to do this:
( number_format ($sql_result["col_number"], 2) * 100 ) / 100;
I've been accused of doing something like this:
floatval($foo) == intval($foo) ? number_format($foo) : number_format($foo,2);
If you are targeting US currency I like to use this method:
function moneyform($number, $symbol = true) {
return str_replace(".00", "", money_format(($symbol? '%.2n' : "%!n"), $number));
}
moneyform(1300999);
-->$1,300,999
moneyform(2500.99);
-->$2,500.99
moneyform(2500.99, false);
-->2,500.99
Mine since most quantity or pieces do not require decimal, this function will only show decimal when needed.
str_replace(".00", "", number_format($this->pieces, 2));
Warren.S answer helped me out. I didn't need the number_format function, so I just did this
$value=$value-0;
But in the OP's case, he needs number_format to remove the commas. So this would work for him
$value=number_format ($sql_result["col_number"], 2, ".", "")-0;
Since I could not find a flexible solution I wrote a simple function to get the best result:
function getValueFormattedWithMinimalDecimals($value, $max_decimals = 2, $dec_point = ',', $thousands_sep = '') {
$bestNumberOfDecimals = -1;
$decimal = 0;
while ($decimal <= $max_decimals) {
$bestNumberOfDecimals = $decimal;
$valueDecimals = number_format($value, $decimal);
if (floatval($value) == $valueDecimals) {
break;
}
$decimal++;
}
if($bestNumberOfDecimals > 0 && number_format($value, $bestNumberOfDecimals) == number_format($value, 0)) {
$bestNumberOfDecimals = 0;
}
return number_format($value, $bestNumberOfDecimals, $dec_point, $thousands_sep);
}
What about
number_format($value,2) - 0;
I want users on my website to be able to pick a hex colour, and I just want to display white text for dark colours and black text for light colours. Can you work out the brightness from a hex code (preferably PHP)?
$hex = "78ff2f"; //Bg color in hex, without any prefixing #!
//break up the color in its RGB components
$r = hexdec(substr($hex,0,2));
$g = hexdec(substr($hex,2,2));
$b = hexdec(substr($hex,4,2));
//do simple weighted avarage
//
//(This might be overly simplistic as different colors are perceived
// differently. That is a green of 128 might be brighter than a red of 128.
// But as long as it's just about picking a white or black text color...)
if($r + $g + $b > 382){
//bright color, use dark font
}else{
//dark color, use bright font
}
I made one similar - but based on weightings of each colour (based on the C# version of this thread)
function readableColour($bg){
$r = hexdec(substr($bg,0,2));
$g = hexdec(substr($bg,2,2));
$b = hexdec(substr($bg,4,2));
$contrast = sqrt(
$r * $r * .241 +
$g * $g * .691 +
$b * $b * .068
);
if($contrast > 130){
return '000000';
}else{
return 'FFFFFF';
}
}
echo readableColour('000000'); // Output - FFFFFF
EDIT:
Small optimisation:
Sqrt is known as an expensive math operation, which is probably neglectable in most scenarios, but anyway, it could be avoided by doing something like this.
function readableColour($bg){
$r = hexdec(substr($bg,0,2));
$g = hexdec(substr($bg,2,2));
$b = hexdec(substr($bg,4,2));
$squared_contrast = (
$r * $r * .299 +
$g * $g * .587 +
$b * $b * .114
);
if($squared_contrast > pow(130, 2)){
return '000000';
}else{
return 'FFFFFF';
}
}
echo readableColour('000000'); // Output - FFFFFF
It simply doesn't apply the sqrt, instead it powers the desired cut off contrast by two, which is a much cheaper calculation
I know this is a very old topic, but for users who came from "Google Search", this link may be what they are looking for. I've searched for something like this and I think it's a good idea to post it here:
https://github.com/mexitek/phpColors
use Mexitek\PHPColors\Color;
// Initialize my color
$myBlue = new Color("#336699");
echo $myBlue->isLight(); // false
echo $myBlue->isDark(); // true
That's it.
You need to convert the RGB values to HLS/HSL (Hue Lightness and Saturation) you can then use the Lightness to determine whether you need light text or dark text.
This page has some details on how to the conversion in PHP as well as selecting complementary colour from this.
I've only just spotted that the site is an astrology site - so apologies if anyone's offended.
If you have imagemagick extension activated, you can simply create an ImagickPixel object, call setColor with your hex value, and then call getHSL() (and get the last item of the obtained array I suppose)...
I tried a different approach to this, I used HSL (hue, saturation & lightness) lightness percentage to check if the color is dark or light. (like #chrisf said in his answer)
function:
function colorislight($hex) {
$hex = str_replace('#', '', $hex);
$r = (hexdec(substr($hex, 0, 2)) / 255);
$g = (hexdec(substr($hex, 2, 2)) / 255);
$b = (hexdec(substr($hex, 4, 2)) / 255);
$lightness = round((((max($r, $g, $b) + min($r, $g, $b)) / 2) * 100));
return ($lightness >= 50 ? true : false);
}
On the return line it checks if the lightness percentage is higher than 50% and returns true otherwise false is returned. You can easily change it to return true if the color has 30% lightness and so on. The $lightness variable can return from 0 to 100 0 being the darkest and 100 being the lightest.
how to use the function:
$color = '#111111';
if ( colorislight($color) ) {
echo 'this color is light';
}
else {
echo 'this color is dark';
}
lets say i have the following RGB values:
R:129
G:98
B:87
Photoshop says the saturation of that colour is 33%
How would i work out that percentage using PHP and the RGB values?
See RGB to HSV in PHP
Taking only the saturation bits from that code, and converting into a percentage:
function saturation($R, $G, $B) { // 0-255
$Min = min($R, $G, $B);
$Max = max($R, $G, $B);
return $Max == 0 ? 0 : (($Max - $Min) / $Max) * 100;
}
Alternately you could use the original code in the link above - the HSV values it returns are between 0.0 and 1.0, so you just need to multiply the saturation value by 100 to get your percentage.
PEAR (PHP Extensions And Application Repository) has a nice package called Image_Color2 which allows you do to quick conversions between different color models:
include "Image/Color2.php";
$color = new Image_Color2(array(129,98,87));
$hsv = $color->convertTo('hsv');
$hsvArray = $hsv->getArray();
echo "Hue is " . $hsvArray[0] . "\n";
echo "Saturation is: " . $hsvArray[1] . "\n";
echo "Brightness is: " . $hsvArray[2];