Need help how to use preg_replace_callback - php

I have this code which returns:
float(-70.869444444444)
I can see using var_dump that it finds all coordinates, but only one is displayed.
How do I modify below code to display all coordinates transferred to degree format and also display text?
Wanted result should be:
-70.869 -6.35 test -127.49 more test second line -127.35
Code
$str60 = 'W07052 W0623 test E12727 more test second line E12725';
preg_match_all('/([EWSN])([0-9]{3})([0-9]{2})/ms', $str60, $matches);
$result60 = DMS2Decimal($degrees = (int) $matches[2][0], $minutes = (int) $matches[3][0], $seconds = 10, $direction = strtolower($matches[1][0]));
function DMS2Decimal($degrees = 0, $minutes = 0, $seconds = 0, $direction = 'n')
{
//converts DMS coordinates to decimal
//returns false on bad inputs, decimal on success
//direction must be n, s, e or w, case-insensitive
$d = strtolower($direction);
$ok = array('n', 's', 'e', 'w');
//degrees must be integer between 0 and 180
if (!is_numeric($degrees) || $degrees < 0 || $degrees > 180) {
$decimal = false;
//var_dump($decimal);
}
//minutes must be integer or float between 0 and 59
elseif (!is_numeric($minutes) || $minutes < 0 || $minutes > 59) {
$decimal = false;
//var_dump($decimal);
}
//seconds must be integer or float between 0 and 59
elseif (!is_numeric($seconds) || $seconds < 0 || $seconds > 59) {
$decimal = false;
} elseif (!in_array($d, $ok)) {
$decimal = false;
//var_dump($decimal);
} else {
//inputs clean, calculate
$decimal = $degrees + ($minutes / 60) + ($seconds / 3600);
//reverse for south or west coordinates; north is assumed
if ($d == 's' || $d == 'w') {
$decimal *= -1;
}
}
return $decimal;
}
var_dump($matches);
var_dump($result60);

Yes, preg_replace_callback is what you want. I tweaked your regular expression as I assumed you wanted to catch"W0623."
I also cleaned up your function a bit, though the only change in output was to round it to 3 decimal places. The rest was just organizing your conditions and can be ignored if you prefer.
function DMS2Decimal($degrees = 0, $minutes = 0, $seconds = 0, $direction = 'n')
{
//converts DMS coordinates to decimal
//returns false on bad inputs, decimal on success
$d = strtolower($direction);
if (
//degrees must be integer between 0 and 180
(is_numeric($degrees) && $degrees >= 0 && $degrees <= 180) &&
//minutes must be integer or float between 0 and 59
(is_numeric($minutes) && $minutes >= 0 && $minutes <= 59) &&
//seconds must be integer or float between 0 and 59
(is_numeric($seconds) && $seconds >= 0 && $seconds <= 59) &&
//direction must be n, s, e or w, case-insensitive
(in_array($d, ['n', 's', 'e', 'w']))
) {
$decimal = $degrees + ($minutes / 60) + ($seconds / 3600);
//reverse for south or west coordinates; north is assumed
if ($d == 's' || $d == 'w') {
$decimal *= -1;
}
return round($decimal, 3);
} else {
return false;
}
}
$str60 = 'W07052 W0623 test E12727 more test second line E12725';
$result60 = preg_replace_callback(
"/([EWSN])([0-9]{3})([0-9]{1,2})/ms",
function($m) {return DMS2Decimal((int)$m[2], (int)$m[3], 10, $m[1]);},
$str60
);
echo $result60;
Output:
-70.869 -62.053 test 127.453 more test second line 127.419

The script below might return your desired result. I'm not sure if I have given correct input values to the function, it is based on this, where NWSE are the direction, the next {2}digits might be Degree, {2} digits after that might be the Minute and the remaining digits might be the Second, which may or may not be a float number.
$str60 = 'N404536 W73592.4 test E73592.4 more test second line S73592.4';
$split_strings = preg_split('/\s/s', $str60);
foreach ($split_strings as $value) {
if (preg_match('/([EWSN][0-9\.]{4,})/ms', $value)) {
$result60 .= DMS2Decimal(
$degrees = (int) substr($value, 1, 2), // Not sure, this might return degrees - e.g., W{73}592.4
$minutes = (int) substr($value, 3, 2), // Not sure, this might return minutes - e.g., W735{92}.4
$seconds = substr($value, 5) != null ? (int) substr($value, 5) : 0, // Not sure, this checks if second is available or place zero - e.g., W7359{2.4}
$direction = substr($value, 0, 1) // This is direction East West North South - e.g., {W}73592.4
) . " ";
} else {
$result60 .= $value . " ";
}
}
var_dump($result60);
function DMS2Decimal($degrees = 0, $minutes = 0, $seconds = 0, $direction = 'n')
{
//converts DMS coordinates to decimal
//returns false on bad inputs, decimal on success
//direction must be n, s, e or w, case-insensitive
$d = strtolower($direction);
$ok = array('n', 's', 'e', 'w');
//degrees must be integer between 0 and 180
if (!is_numeric($degrees) || $degrees < 0 || $degrees > 180) {
$decimal = false;
//var_dump($decimal);
}
//minutes must be integer or float between 0 and 59
elseif (!is_numeric($minutes) || $minutes < 0 || $minutes > 59) {
$decimal = false;
//var_dump($decimal);
}
//seconds must be integer or float between 0 and 59
elseif (!is_numeric($seconds) || $seconds < 0 || $seconds > 59) {
$decimal = false;
} elseif (!in_array($d, $ok)) {
$decimal = false;
//var_dump($decimal);
} else {
//inputs clean, calculate
$decimal = $degrees + ($minutes / 60) + ($seconds / 3600);
//reverse for south or west coordinates; north is assumed
if ($d == 's' || $d == 'w') {
$decimal *= -1;
}
}
return $decimal;
}
Output
string(56) "40.76 -73.984 test 73.984 more test second line -73.984 "

Related

PHP function to convert Hex to HSL (Not HSL to Hex)

Does anyone know how to convert a Hex color to HSL in PHP? I've searched but the functions that I’ve found don’t convert precisely the color.
I think the mistake in the second answer is using integer division rather than fmod() when calculating the hue when red is the maximum colour value $hue = (($green - $blue) / $delta) % 6;
I think the mistake in the first answer is in the saturation calculation -
for me $s = $l > 0.5 ? $diff / (2 - $max - $min) : $diff / ($max + $min); is a bit confusing to unpick
Since usually when I want to convert RGB to HSL I want to adjust the lightness value to make a lighter or darker version of the same colour, I have built that into the function below by adding an optional $ladj percent value.
The $hex parameter can be either a hex string (with or without the '#') or an array of RGB values (between 0 and 255)
The return value is an HSL string ready to drop straight in to a CSS colour. ie the values are from 0 to 359 for hue and 0 to 100% for saturation and lightness.
I think this works correctly (based on https://gist.github.com/brandonheyer/5254516)
function hex2hsl($RGB, $ladj = 0) {
//have we got an RGB array or a string of hex RGB values (assume it is valid!)
if (!is_array($RGB)) {
$hexstr = ltrim($RGB, '#');
if (strlen($hexstr) == 3) {
$hexstr = $hexstr[0] . $hexstr[0] . $hexstr[1] . $hexstr[1] . $hexstr[2] . $hexstr[2];
}
$R = hexdec($hexstr[0] . $hexstr[1]);
$G = hexdec($hexstr[2] . $hexstr[3]);
$B = hexdec($hexstr[4] . $hexstr[5]);
$RGB = array($R,$G,$B);
}
// scale the RGB values to 0 to 1 (percentages)
$r = $RGB[0]/255;
$g = $RGB[1]/255;
$b = $RGB[2]/255;
$max = max( $r, $g, $b );
$min = min( $r, $g, $b );
// lightness calculation. 0 to 1 value, scale to 0 to 100% at end
$l = ( $max + $min ) / 2;
// saturation calculation. Also 0 to 1, scale to percent at end.
$d = $max - $min;
if( $d == 0 ){
// achromatic (grey) so hue and saturation both zero
$h = $s = 0;
} else {
$s = $d / ( 1 - abs( (2 * $l) - 1 ) );
// hue (if not grey) This is being calculated directly in degrees (0 to 360)
switch( $max ){
case $r:
$h = 60 * fmod( ( ( $g - $b ) / $d ), 6 );
if ($b > $g) { //will have given a negative value for $h
$h += 360;
}
break;
case $g:
$h = 60 * ( ( $b - $r ) / $d + 2 );
break;
case $b:
$h = 60 * ( ( $r - $g ) / $d + 4 );
break;
} //end switch
} //end else
// make any lightness adjustment required
if ($ladj > 0) {
$l += (1 - $l) * $ladj/100;
} elseif ($ladj < 0) {
$l += $l * $ladj/100;
}
//put the values in an array and scale the saturation and lightness to be percentages
$hsl = array( round( $h), round( $s*100), round( $l*100) );
//we could return that, but lets build a CSS compatible string and return that instead
$hslstr = 'hsl('.$hsl[0].','.$hsl[1].'%,'.$hsl[2].'%)';
return $hslstr;
}
In real life I would break out the hex string to RGB array conversion and the percentage adjustment into separate functions, but have included them here for completeness.
You could also use the percent adjustment to shift the hue or saturation once you've got the colour in HSL format.
function hexToHsl($hex) {
$hex = array($hex[0].$hex[1], $hex[2].$hex[3], $hex[4].$hex[5]);
$rgb = array_map(function($part) {
return hexdec($part) / 255;
}, $hex);
$max = max($rgb);
$min = min($rgb);
$l = ($max + $min) / 2;
if ($max == $min) {
$h = $s = 0;
} else {
$diff = $max - $min;
$s = $l > 0.5 ? $diff / (2 - $max - $min) : $diff / ($max + $min);
switch($max) {
case $rgb[0]:
$h = ($rgb[1] - $rgb[2]) / $diff + ($rgb[1] < $rgb[2] ? 6 : 0);
break;
case $rgb[1]:
$h = ($rgb[2] - $rgb[0]) / $diff + 2;
break;
case $rgb[2]:
$h = ($rgb[0] - $rgb[1]) / $diff + 4;
break;
}
$h /= 6;
}
return array($h, $s, $l);
}
Rewritten (and adjusted a bit) from javascript from https://css-tricks.com/converting-color-spaces-in-javascript/
<?php
function hexToHsl($hex)
{
$red = hexdec(substr($hex, 0, 2)) / 255;
$green = hexdec(substr($hex, 2, 2)) / 255;
$blue = hexdec(substr($hex, 4, 2)) / 255;
$cmin = min($red, $green, $blue);
$cmax = max($red, $green, $blue);
$delta = $cmax - $cmin;
if ($delta === 0) {
$hue = 0;
} elseif ($cmax === $red) {
$hue = (($green - $blue) / $delta) % 6;
} elseif ($cmax === $green) {
$hue = ($blue - $red) / $delta + 2;
} else {
$hue = ($red - $green) / $delta + 4;
}
$hue = round($hue * 60);
if ($hue < 0) {
$hue += 360;
}
$lightness = (($cmax + $cmin) / 2) * 100;
$saturation = $delta === 0 ? 0 : ($delta / (1 - abs(2 * $lightness - 1))) * 100;
if ($saturation < 0) {
$saturation += 100;
}
$lightness = round($lightness);
$saturation = round($saturation);
return "hsl(${hue}, ${saturation}%, ${lightness}%)";
}
Example:
<?php
echo hexToHsl('fbffe0'); // outputs 'hsl(68, 100%, 94%)'

How to calculate a certain color based on another color?

For example I have a blue color:
#049cd9 or rgba(4, 156, 218)
How can I calculate the correspondent color, which in this case it would be a dark blue color:
#004ea0 or rgba(0, 78, 160)
?
Normally I don't know the 2nd color (that I want to find out), so I want to find a way to get the darker color based on the first color.
Is there a formula or something that I can generate by substracting the two colors somehow?
So I've found HEX to HSL and HSL to HEX functions:
function hex_to_hue($hexcode)
{
$redhex = substr($hexcode,0,2);
$greenhex = substr($hexcode,2,2);
$bluehex = substr($hexcode,4,2);
// $var_r, $var_g and $var_b are the three decimal fractions to be input to our RGB-to-HSL conversion routine
$var_r = (hexdec($redhex)) / 255;
$var_g = (hexdec($greenhex)) / 255;
$var_b = (hexdec($bluehex)) / 255;
// Input is $var_r, $var_g and $var_b from above
// Output is HSL equivalent as $h, $s and $l — these are again expressed as fractions of 1, like the input values
$var_min = min($var_r,$var_g,$var_b);
$var_max = max($var_r,$var_g,$var_b);
$del_max = $var_max - $var_min;
$l = ($var_max + $var_min) / 2;
if ($del_max == 0) {
$h = 0;
$s = 0;
} else {
if ($l < 0.5) {
$s = $del_max / ($var_max + $var_min);
} else {
$s = $del_max / (2 - $var_max - $var_min);
}
;
$del_r = ((($var_max - $var_r) / 6) + ($del_max / 2)) / $del_max;
$del_g = ((($var_max - $var_g) / 6) + ($del_max / 2)) / $del_max;
$del_b = ((($var_max - $var_b) / 6) + ($del_max / 2)) / $del_max;
if ($var_r == $var_max) {
$h = $del_b - $del_g;
} else if ($var_g == $var_max) {
$h = (1 / 3) + $del_r - $del_b;
} else if ($var_b == $var_max) {
$h = (2 / 3) + $del_g - $del_r;
}
;
if ($h < 0) {
$h += 1;
}
;
if ($h > 1) {
$h -= 1;
}
;
}
;
return array($h, $s, $l);
/*
// Calculate the opposite hue, $h2
$h2 = $h + 0.5;
if ($h2 > 1)
{
$h2 -= 1;
};
return array($h2, $s, $l);
*/
}
function hue_to_hex($hue = array())
{
function hue_2_rgb($v1,$v2,$vh)
{
if ($vh < 0) {
$vh += 1;
}
;
if ($vh > 1) {
$vh -= 1;
}
;
if ((6 * $vh) < 1) {
return($v1 + ($v2 - $v1) * 6 * $vh);
}
;
if ((2 * $vh) < 1) {
return($v2);
}
;
if ((3 * $vh) < 2) {
return($v1 + ($v2 - $v1) * ((2 / 3 - $vh) * 6));
}
;
return($v1);
}
;
list($h2, $s, $l) = $hue;
// Input is HSL value of complementary colour, held in $h2, $s, $l as fractions of 1
// Output is RGB in normal 255 255 255 format, held in $r, $g, $b
// Hue is converted using function hue_2_rgb, shown at the end of this code
if ($s == 0) {
$r = $l * 255;
$g = $l * 255;
$b = $l * 255;
} else {
if ($l < 0.5) {
$var_2 = $l * (1 + $s);
} else {
$var_2 = ($l + $s) - ($s * $l);
}
;
$var_1 = 2 * $l - $var_2;
$r = 255 * hue_2_rgb($var_1,$var_2,$h2 + (1 / 3));
$g = 255 * hue_2_rgb($var_1,$var_2,$h2);
$b = 255 * hue_2_rgb($var_1,$var_2,$h2 - (1 / 3));
}
;
$rhex = sprintf("%02X",round($r));
$ghex = sprintf("%02X",round($g));
$bhex = sprintf("%02X",round($b));
return $rhex.$ghex.$bhex;
}
They work because I tested them by converting a color back and forth.
But I don't know how can I change the Hue and Luminosity properties just like in Photoshop?
The dark color would be H +13 and L -28.
And the hex_to_hsl function above returns float values between 0 and 1...
There are formulas that convert an RGB color to HSV (Hue, Saturation and Value). From the HSV you can change any of the HSV components and then convert back to RGB. I've found stuff online and done this before. Let me know if you want more details on the algorithms, I can dig them up for you if you want.
#XXXXXX represent hexa decimal number in colors for RED, GREEN and BLUE, each two characters from left to right if you increase the number it will get light, if decrease the number, it will be darker.
You need to convert the RGB value to HSL or HSV and then you can decrease the L (luma) or V (value) component as you wish and then convert back to RGB.
see this answer for example code:
RGB to HSV in PHP
The easiest way to tinker with how colours are perceived (ie, lighter, darker, brighter, duller, etc) is to convert it to HSL. There are plenty of resources online for converting RGB to HSL and back again in PHP and JavaScript. Google will find you as many implementations as you want. Then to decrease the lightness, reduce the L value (multiply by 0.75 or similar) and convert back to RGB.
function hex_to_hue($hexcode, $percent) {
$redhex = substr($hexcode, 0, 2);
$greenhex = substr($hexcode, 2, 2);
$bluehex = substr($hexcode, 4, 2);
// $var_r, $var_g and $var_b are the three decimal fractions to be input to our RGB-to-HSL conversion routine
$var_r = (hexdec($redhex)) / 255;
$var_g = (hexdec($greenhex)) / 255;
$var_b = (hexdec($bluehex)) / 255;
// Input is $var_r, $var_g and $var_b from above
// Output is HSL equivalent as $h, $s and $l — these are again expressed as fractions of 1, like the input values
$var_min = min($var_r, $var_g, $var_b);
$var_max = max($var_r, $var_g, $var_b);
$del_max = $var_max - $var_min;
$l = ($var_max + $var_min) / 2;
if ($del_max == 0) {
$h = 0;
$s = 0;
} else {
if ($l < 0.5) {
$s = $del_max / ($var_max + $var_min);
} else {
$s = $del_max / (2 - $var_max - $var_min);
}
;
$del_r = ((($var_max - $var_r) / 6) + ($del_max / 2)) / $del_max;
$del_g = ((($var_max - $var_g) / 6) + ($del_max / 2)) / $del_max;
$del_b = ((($var_max - $var_b) / 6) + ($del_max / 2)) / $del_max;
if ($var_r == $var_max) {
$h = $del_b - $del_g;
} else if ($var_g == $var_max) {
$h = (1 / 3) + $del_r - $del_b;
} else if ($var_b == $var_max) {
$h = (2 / 3) + $del_g - $del_r;
}
;
if ($h < 0) {
$h += 1;
}
;
if ($h > 1) {
$h -= 1;
}
;
}
;
//return array($h, $s, $l);
// Calculate the opposite hue, $h2
$h2 = $h + $percent;
if ($h2 > 1) {
$h2 -= 1;
}
// Calculate the opposite hue, $s2
$s2 = $s + $percent;
if ($s2 > 1) {
$s2 -= 1;
}
// Calculate the opposite hue, $s2
$l2 = $l + $percent;
if ($l2 > 1) {
$l2 -= 1;
}
return array($h2, $s2, $l2);
}

How to format numbers in php 1,000 to 1k

Im trying to format the output of numbers in php. I have an amount of posts that show up, and next to each user is the total of posts. But it shows that actual amount, i want it to show it in a shorter format, actually, just like they do here at SO with reputation
any ideas?
<?
$numbers = array(100,1000,15141,3421);
function format_number($number) {
if($number >= 1000) {
return $number/1000 . "k"; // NB: you will want to round this
}
else {
return $number;
}
}
foreach($numbers as $number) {
echo $number . " : " . format_number($number);
echo "\n";
}
function count_format($n, $point='.', $sep=',') {
if ($n < 0) {
return 0;
}
if ($n < 10000) {
return number_format($n, 0, $point, $sep);
}
$d = $n < 1000000 ? 1000 : 1000000;
$f = round($n / $d, 1);
return number_format($f, $f - intval($f) ? 1 : 0, $point, $sep) . ($d == 1000 ? 'k' : 'M');
}
Use This
Shorten long numbers to K/M/B?
function number_format_short( $n, $precision = 1 ) {
if ($n < 900) {
// 0 - 900
$n_format = number_format($n, $precision);
$suffix = '';
} else if ($n < 900000) {
// 0.9k-850k
$n_format = number_format($n / 1000, $precision);
$suffix = 'K';
} else if ($n < 900000000) {
// 0.9m-850m
$n_format = number_format($n / 1000000, $precision);
$suffix = 'M';
} else if ($n < 900000000000) {
// 0.9b-850b
$n_format = number_format($n / 1000000000, $precision);
$suffix = 'B';
} else {
// 0.9t+
$n_format = number_format($n / 1000000000000, $precision);
$suffix = 'T';
}

PHP allocate color without image resource

Can you allocate a color in PHP GD without an image resource? It should be possible because really an allocated color is a number, right?
$im = imagecreatetruecolor(100, 100);
$col = imagecolorallocate($im, 255, 0, 0);
print $col."<br/>";
$col2 = imagecolorallocate($im, 255, 0, 0);
print $col2."<br/>";
$im2 = imagecreatetruecolor(600, 100);
$col3 = imagecolorallocate($im, 255, 0, 0);
print $col3;
This prints out:
16711680
16711680
16711680
I guess what the real question is how 255, 0, and 0 are made into 16711680.
16711680 (decimal) is 0x00FF0000 (hexadecimal)
00 - Alpha value (0 dec)
FF - Red (255 dec)
00 - Green (0 dec)
00 - Blue (0 dec)
See http://www.php.net/manual/en/function.imagecolorallocatealpha.php to set the alpha byte
Edit:
Also, to answer your first question -- yes, you can create a color without an image resource (and, consequently without a call to imagecolorallocate):
$col1 = 0x00FF0000; // Red
$col2 = 0x0000FF00; // Green
// etc...
It should be possible because really an allocated color is a number, right?
No, it's not. GD may also have to register that color in the palette of the image (think non true color images).
So you need an image resource.
The color index, or color id can be determined several ways. This should help on the road to discovery.
Update ***
I'm not sure why, but after seeing this question I wrote the following function to convert <many> types of color values to <many> types of color expressions. Hope it works for someone. *Added CMYK just because. ...
Options -->
'int',
'rgba', 'rgb', 'cmyk',
'hex', 'rgbaCSS', 'rgbCSS', 'hexCSS', 'hexCSS4'
If someone wanted to get really serious, they could write optional arguments for converting the format to any; using sprintf.
<?php
function convertColorValue($colorValue, $toType = 'hex', $recurse = 0) {
if ($recurse > 2) { return $colorValue; }
if (!is_array($colorValue)) {
// OUT --> {Mixed} :: Options --> rgba || rgb || cmyk
// If not an array then we have some form of Number - Valid values int || hex<string>
// Please note that hex numbers such as 0x000000 that are not strings '0x000000' are interpreted by php as their number representation.
// Shortcode hex values.
if (is_string($colorValue) && $colorValue{0} === '#') {
$start = 0;
if (strlen($colorValue) === 4) {
$rgb['alpha'] = hexdec(str_repeat(substr($colorValue, $start++, 1), 2));
} else {
$rgb['alpha'] = 0;
}
$rgb['r'] = hexdec(str_repeat(substr($colorValue, $start++, 1), 2));
$rgb['g'] = hexdec(str_repeat(substr($colorValue, $start++, 1), 2));
$rgb['b'] = hexdec(str_repeat(substr($colorValue, $start, 1), 2));
// We need to make sure this follows some rules before we send it back even if it is the type we are being asked for.
return convertColorValue($rgb, $toType);
}
// Make sure we have a clean sensible string for conversion.
if (preg_match("/[^0-9a-f]/i", $colorValue) !== false) {
if (($colorValue{0} === 0 && $colorValue{1} !== 'x'))
$colorValue = '0x' . $colorValue;
}
$colorValue = preg_replace("/[^0-9a-fx]/i", '', $colorValue); // 4294967295 === 0xFFFFFFFF, the maximum color value.
$colorValue = strlen((string) $colorValue) >= 10 ? (intval(substr($colorValue, 0, 10), 0) > 4294967295 ? 0 : substr($colorValue, 0, 10)) : $colorValue;
// CONVERT our number to base 10 from whatever base it is in.
// **** TODO: Hopefully int or hex, not sure what happens in other bases. ¯\_(ツ)_/¯
// Hex strings should always be prepended with 0x, otherwise confusion happens 11110000 !=? 0x11110000
// If not prepended here with 0x, I can't fix/predict which you are trying to represent int or hex. Int is naturally assumed.
$color = [];
$colorValue = intval(intval($colorValue, 0), 10);
$color['r'] = ($colorValue >> 16) & 0xFF;
$color['g'] = ($colorValue >> 8) & 0xFF;
$color['b'] = $colorValue & 0xFF;
$color['alpha'] = ($colorValue >> 24) & 0x7F;
if ($toType === 'cmyk') {
$c = (255 - $color['r']) / 255.0 * 100;
$m = (255 - $color['g']) / 255.0 * 100;
$y = (255 - $color['b']) / 255.0 * 100;
$b = min([$c,$m,$y]);
$c = $c - $b; $m = $m - $b; $y = $y - $b;
return ['c' => $c, 'm' => $m, 'y' => $y, 'k' => $b, 'alpha' => $color['alpha']];
}
if ($toType === 'rgba' || $toType === 'rgb') {
return $color;
}
return convertColorValue($color, $toType, ++$recurse);
}
// OUT --> {Mixed} :: Options --> int || hex || hexCSS || rgbCSS || rgbaCSS || hexCSS4
// If they've thrown us a c, we are going to assume they gave us CMYK.
if (isset($colorValue['c'])) {
$colorValue['c'] = empty($colorValue['c']) ? 0 : $colorValue['c'] / 100;
$colorValue['m'] = empty($colorValue['m']) ? 0 : $colorValue['m'] / 100;
$colorValue['y'] = empty($colorValue['y']) ? 0 : $colorValue['y'] / 100;
$colorValue['k'] = empty($colorValue['k']) ? 0 : $colorValue['k'] / 100;
$colorValue['r'] = round((1 - ($colorValue['c'] * (1 - $colorValue['k'])) - $colorValue['k']) * 255);
$colorValue['g'] = round((1 - ($colorValue['m'] * (1 - $colorValue['k'])) - $colorValue['k']) * 255);
$colorValue['b'] = round((1 - ($colorValue['y'] * (1 - $colorValue['k'])) - $colorValue['k']) * 255);
} else {
$colorValue['r'] = empty($colorValue['r']) ? 0 : $colorValue['r'];
$colorValue['g'] = empty($colorValue['g']) ? 0 : $colorValue['g'];
$colorValue['b'] = empty($colorValue['b']) ? 0 : $colorValue['b'];
}
$colorValue['alpha'] = (empty($colorValue['alpha']) || $colorValue['alpha'] > 0x7f) ? 0 : $colorValue['alpha'];
if ($toType === 'rgbaCSS') {
$color['alpha'] = empty($color['alpha']) ? 1 :
(round(1 * $color['alpha'] / 127, 3, PHP_ROUND_HALF_DOWN));
return "rgba({$colorValue['r']}, {$colorValue['g']}, {$colorValue['b']}, {$colorValue['alpha']})";
}
if ($toType === 'rgbCSS') {
return "rgb({$colorValue['r']}, {$colorValue['g']}, {$colorValue['b']})";
}
// Just return the rgb value if opaque since '==' color-values.
if (empty($colorValue['alpha'])) {
$hex = sprintf("%02x%02x%02x", $colorValue['r'], $colorValue['g'], $colorValue['b']);
} else {
$hex = sprintf("%02x%02x%02x%02x", $colorValue['alpha'], $colorValue['r'], $colorValue['g'], $colorValue['b']);
}
$isCSS = ($toType === 'hexCSS4' || $toType === 'hexCSS');
if ($toType === 'hex' || $isCSS) {
return $isCSS ? ("#".$hex) : ("0x".$hex);
}
$hex = "0x".$hex;
if ($toType === 'int') { return hexdec($hex); }
// Is now a hex string. Going back UP^
return convertColorValue($hex, $toType, ++$recurse);
}
Use this function
function img_color($r, $g, $b, $a=0) {
// prepare red color
if (is_string($r)) {
if (!preg_match('/^[a-f0-9]{1,2}$/i', $r)) return false;
$r = hexdec($r);
}
elseif (is_int($r)) {if ($r<0 or $r>255) return false;}
else return false;
// prepare green color
if (is_string($g)) {
if (!preg_match('/^[a-f0-9]{1,2}$/i', $g)) return false;
$g = hexdec($g);
}
elseif (is_int($g)) {if ($g<0 or $g>255) return false;}
else return false;
// prepare blue color
if (is_string($b)) {
if (!preg_match('/^[a-f0-9]{1,2}$/i', $b)) return false;
$b = hexdec($b);
}
elseif (is_int($b)) {if ($b<0 or $b>255) return false;}
else return false;
// prepare alpha channel
if (is_string($a)) {
if (!preg_match('/^[a-f0-9]{1,2}$/i', $a)) return false;
$a = hexdec($a);
}
elseif (!is_int($a)) return false;
if ($a<0 or $a>127) return false;
$result = unpack('I', chr($b) . chr($g) . chr($r) . chr($a));
return $result[1];
}

Rounding to the Nearest Ending Digits

I have the following function that rounds a number to the nearest number ending with the digits of $nearest, and I was wondering if there is a more elegant way of doing the same.
/**
* Rounds the number to the nearest digit(s).
*
* #param int $number
* #param int $nearest
* #return int
*/
function roundNearest($number, $nearest, $type = null)
{
$result = abs(intval($number));
$nearest = abs(intval($nearest));
if ($result <= $nearest)
{
$result = $nearest;
}
else
{
$ceil = $nearest - substr($result, strlen($result) - strlen($nearest));
$floor = $nearest - substr($result, strlen($result) - strlen($nearest)) - pow(10, strlen($nearest));
switch ($type)
{
case 'ceil':
$result += $ceil;
break;
case 'floor':
$result += $floor;
break;
default:
$result += (abs($ceil) <= abs($floor)) ? $ceil : $floor;
break;
}
}
if ($number < 0)
{
$result *= -1;
}
return $result;
}
Some examples:
roundNearest(86, 9); // 89
roundNearest(97, 9); // 99
roundNearest(97, 9, 'floor'); // 89
Thanks in advance!
PS: This question is not about rounding to the nearest multiple.
This works for me:
function roundToDigits($num, $suffix, $type = 'round') {
$pow = pow(10, floor(log($suffix, 10) + 1));
return $type(($num - $suffix) / $pow) * $pow + $suffix;
};
$type should be either "ceil", "floor", or "round"
I think this should work, and it's more elegant to me, at least:
function roundNearest($number, $nearest, $type = null)
{
if($number < 0)
return -roundNearest(-$number, $nearest, $type);
$nearest = abs($nearest);
if($number < $nearest)
return $nearest;
$len = strlen($nearest);
$pow = pow(10, $len);
$diff = $pow - $nearest;
if($type == 'ciel')
$adj = 0.5;
else if($type == 'floor')
$adj = -0.5;
else
$adj = 0;
return round(($number + $diff)/$pow + $adj)*$pow - $diff;
}
Edit: Added what I think you want from negative inputs.

Categories