I want to know how to build a function that give the code of an color and
display a gradient of this color. For example:
function generate_color(int colorindex)
{ .......
.......
Generate 10 pale colors of this color.
}
Please help me
The code Michael references is rather scary. But the solution is straightforward. It may be clearer if you consider simply a grey scale image:
function create_pallette($start, $end, $entries=10)
{
$inc=($start - $end)/($entries-1);
$out=array(0=>$start);
for ($x=1; $x<$entries;$x++) {
$out[$x]=$start+$inc * $x;
}
return $out;
}
Only using a 3D vector (RGB) instead of a 1D vector.
C.
In the answer to this question lies your solution, only in Javascript...
Generate lighter/darker color in css using javascript
I'm not going to write it out, but a simple Google search for 'lighten hex colour php' yields:
function colourBrightness($hex, $percent) {
// Work out if hash given
$hash = '';
if (stristr($hex,'#')) {
$hex = str_replace('#','',$hex);
$hash = '#';
}
/// HEX TO RGB
$rgb = array(hexdec(substr($hex,0,2)), hexdec(substr($hex,2,2)), hexdec(substr($hex,4,2)));
//// CALCULATE
for ($i=0; $i<3; $i++) {
// See if brighter or darker
if ($percent > 0) {
// Lighter
$rgb[$i] = round($rgb[$i] * $percent) + round(255 * (1-$percent));
} else {
// Darker
$positivePercent = $percent - ($percent*2);
$rgb[$i] = round($rgb[$i] * $positivePercent) + round(0 * (1-$positivePercent));
}
// In case rounding up causes us to go to 256
if ($rgb[$i] > 255) {
$rgb[$i] = 255;
}
}
//// RBG to Hex
$hex = '';
for($i=0; $i < 3; $i++) {
// Convert the decimal digit to hex
$hexDigit = dechex($rgb[$i]);
// Add a leading zero if necessary
if(strlen($hexDigit) == 1) {
$hexDigit = "0" . $hexDigit;
}
// Append to the hex string
$hex .= $hexDigit;
}
return $hash.$hex;
}
http://lab.pxwebdesign.com.au/?p=14
Your Google is just as good as mine!
Related
I'm in php.
I've got a RYB color with that value :
$rybColor = array("r"=>0,"y"=255",b="255")
I would like to convert it in RGB in order to get
$rgbColor = array("r"=>0,"g"=>255,"b"=>0)
is that something possible ?
I found a script there in javascript
link
but it's a bit complicated for me. I stuck on the normalisation of the values..
Absolutely.
Here's a quick PHP version of the JavaScript version of the Python version you linked:
// RYB color to RGB color
function RYB2RGB($iRed, $iYellow, $iBlue){
// Remove the whiteness from the color.
$iWhite = min($iRed, $iYellow, $iBlue);
$iRed -= $iWhite;
$iYellow -= $iWhite;
$iBlue -= $iWhite;
$iMaxYellow = max($iRed, $iYellow, $iBlue);
// Get the green out of the yellow and blue
$iGreen = min($iYellow, $iBlue);
$iYellow -= $iGreen;
$iBlue -= $iGreen;
if ($iBlue > 0 && $iGreen > 0)
{
$iBlue *= 2.0;
$iGreen *= 2.0;
}
// Redistribute the remaining yellow.
$iRed += $iYellow;
$iGreen += $iYellow;
// Normalize to values.
$iMaxGreen = max($iRed, $iGreen, $iBlue);
if ($iMaxGreen > 0)
{
$iN = $iMaxYellow / $iMaxGreen;
$iRed *= $iN;
$iGreen *= $iN;
$iBlue *= $iN;
}
// Add the white back $in.
$iRed += $iWhite;
$iGreen += $iWhite;
$iBlue += $iWhite;
// Save the RGB
$RGB = [floor($iRed), floor($iGreen), floor($iBlue)];
return $RGB
}
$R = 98;
$y = 152;
$b = 223;
var_dump( RYB2RGB( $R, $y, $b ) ); //
// array(3) {
// [0]=>
// float(98)
// [1]=>
// float(193)
// [2]=>
// float(223)
// }
I have some code that I got from here: Color coding based on number
function GreenYellowRed($number) {
$number--; // working with 0-99 will be easier
if ($number < 50) {
// green to yellow
$r = floor(255 * ($number / 50));
$g = 255;
} else {
// yellow to red
$r = 255;
$g = floor(255 * ((50-$number%50) / 50));
}
$b = 0;
return "$r,$g,$b";
}
I am then calling it on a percentage output... like this:
"<span style='background-color: rgb(" . GreenYellowRed($percentage) . ")'>" . $percentage . "%</span>"
It works as expected, but it makes lower numbers green and higher numbers red. In my case, low percentage is bad and high percentage is good, but I can't work out what to change to make it work in reverse so that hight numbers go green and low numbers go red.
I've tried a few things but it never seems to do what I want... can anyone help?
Chnge this:
return "$r,$g,$b";
to this:
return "$g,$r,$b";
Soooo easy when I thought about it!!
All I had to do was to swap $r and $g on each side of the if statement, like this:
function GreenYellowRed($number)
{
$number--; // working with 0-99 will be easier
if ($number < 50) {
// green to yellow
$g = floor(255 * ($number / 50));
$r = 255;
} else {
// yellow to red
$g = 255;
$r = floor(255 * ((50-$number%50) / 50));
}
$b = 0;
return "$r,$g,$b";
}
All sorted :)
I am working with the jpgraph and creating radar chart.
Facing the issue with fill custom shape polygon with gradient colour.
I have function to fill a gradient colour polygon with a flat bottom and i want to fill the gradient colour in my custom shape polygon.
Can anyone help me? How can i do this?
Current Output:
Desired Output:
You can find the gradient class at here.
http://code.google.com/r/linksoftafrica-maison-george/source/browse/libs/jpgraph/jpgraph_gradient.php
// Fill a special case of a polygon with a flat bottom
// with a gradient. Can be used for filled line plots.
// Please note that this is NOT a generic gradient polygon fill
// routine. It assumes that the bottom is flat (like a drawing
// of a mountain)
function FilledFlatPolygon($pts,$from_color,$to_color) {
if( count($pts) == 0 ) return;
$maxy=$pts[1];
$miny=$pts[1];
$n = count($pts) ;
for( $i=0, $idx=0; $i < $n; $i += 2) {
$x = round($pts[$i]);
$y = round($pts[$i+1]);
$miny = min($miny,$y);
$maxy = max($maxy,$y);
}
$colors = array();
$this->GetColArray($from_color,$to_color,abs($maxy-$miny)+1,$colors,$this->numcolors);
for($i=$miny, $idx=0; $i <= $maxy; ++$i ) {
$colmap[$i] = $colors[$idx++];
}
$n = count($pts)/2 ;
$idx = 0 ;
while( $idx < $n-1 ) {
$p1 = array(round($pts[$idx*2]),round($pts[$idx*2+1]));
$p2 = array(round($pts[++$idx*2]),round($pts[$idx*2+1]));
// Find the largest rectangle we can fill
$y = max($p1[1],$p2[1]) ;
for($yy=$maxy; $yy > $y; --$yy) {
$this->img->current_color = $colmap[$yy];
$this->img->Line($p1[0],$yy,$p2[0]-1,$yy);
}
if( $p1[1] == $p2[1] ) continue;
// Fill the rest using lines (slow...)
$slope = ($p2[0]-$p1[0])/($p1[1]-$p2[1]);
$x1 = $p1[0];
$x2 = $p2[0]-1;
$start = $y;
if( $p1[1] > $p2[1] ) {
while( $y >= $p2[1] ) {
$x1=$slope*($start-$y)+$p1[0];
$this->img->current_color = $colmap[$y];
$this->img->Line($x1,$y,$x2,$y);
--$y;
}
}
else {
while( $y >= $p1[1] ) {
$x2=$p2[0]+$slope*($start-$y);
$this->img->current_color = $colmap[$y];
$this->img->Line($x1,$y,$x2,$y);
--$y;
}
}
}
}
It looks to me that your current code is not suitable for this task. You need code for Gouraud shaded triangles (3-sided polygons).
When you have code for that, you simply draw three triangles where on point of the triangle is in the center of the graph and two points are on the radar axles.
Unfortunately, I didn't find ready-made code for jpgraph.
The string of the hexadecimal number is like: 0X1.05P+10
The real value of this hexadecimal number is:1044.0
I can convert it using C language with method strtod.
But I can't find the way to convert it in PHP. Can somebody show me how to do it?
value string list:
1. "0X1.FAP+9"
2. "0X1.C4P+9"
3. "0X1.F3P+9"
4. "0X1.05P+10"
I think you'll have to make a custom function for this. So because I'm feeling nice today I custom-made one for you:
function strtod($hex) {
preg_match('#([\da-f]+)\.?([\da-f]*)p#i', $hex, $parts);
$i = 0;
$fractional_part = array_reduce(str_split($parts[2]), function($sum, $part) use (&$i) {
$sum += hexdec($part) * pow(16, --$i);
return $sum;
});
$decimal = (hexdec($parts[1]) + $fractional_part) * pow(2, array_pop(explode('+', $hex)));
return $decimal;
}
foreach(array('0X1.FAP+9', '0X1.C4P+9', '0X1.F3P+9', '0X1.05P+10', '0X1P+0') as $hex) {
var_dump(strtod($hex));
};
For versions below PHP 5.3:
function strtod($hex) {
preg_match('#([\da-f]+)\.?([\da-f]*)p#i', $hex, $parts);
$fractional_part = 0;
foreach(str_split($parts[2]) as $index => $part) {
$fractional_part += hexdec($part) * pow(16, ($index + 1) * -1);
}
$decimal = (hexdec($parts[1]) + $fractional_part) * pow(2, array_pop(explode('+', $hex)));
return $decimal;
}
foreach(array('0X1.FAP+9', '0X1.C4P+9', '0X1.F3P+9', '0X1.05P+10', '0X1P+0') as $hex) {
var_dump(strtod($hex));
};
hexdec(0X1.05P+10)
OK so that looks wrong to me as that doesn't look like a proper hex number but its the hexdec() function you want in php http://php.net/manual/en/function.hexdec.php
echo hexdec("0X1FAP")+9
echo hexdec("0X1C4P")+9
echo hexdec("0X1F3P")+9
echo hexdec("0X105P")+10
decimal = hex
(1044.0)10 = (414)16
I found Marcel Jackwerth's response to How to code a URL shortener? to be a good answer for the problem, however my question is how it'll look in PHP? Here's Marcel's answer:
You need a Bijective Function f (there must be no x1 != x2, that will make f(x1) = f(x2); and for every y you will find a x so that f(x)=y). This is necessary so that you can find a inverse function g('abc') = 123 for your f(123)='abc' function.
I would continue your "convert number to string" approach (however you will realize that your proposed algorithm fails if your id is a prime and greater than 52).
How to convert the id to a shortened url:
Think of an alphabet you want to use. In your case that's [a-zA-Z0-9]. It contains 62 letters.
Take the auto-generated unique numerical key (auto-incremented id): for example 125 (a decimal number)
Now you have to convert the 125 (base 10) to X (base 62). This will then be {2}{1} (2×62+1=125).
Now map the symbols {2} and {1} to your alphabet. Say {0} = 'a', {25} = 'z' and so on. We will have {2} = 'c' and {1} = 'b'. So '/cb' will be your shortened url.
How to resolve a shortened url abc to the initial id:
If you want to do this in reverse, it's not quite diffcult. 'e9a' will be resolved to "4th,61st,0th letter in alphabet" = {4}{61}{0}, which is 4×62×62 + 61×62 + 0 = 19158. You will then just have to find your database-record with id 19158.
function convert($src, $srcAlphabet, $dstAlphabet) {
$srcBase = strlen($srcAlphabet);
$dstBase = strlen($dstAlphabet);
$wet = $src;
$val = 0;
$mlt = 1;
while ($l = strlen($wet)) {
$digit = $wet[$l - 1];
$val += $mlt * strpos($srcAlphabet, $digit);
$wet = substr($wet, 0, $l - 1);
$mlt *= $srcBase;
}
$wet = $val;
$dst = '';
while ($wet >= $dstBase) {
$digitVal = $wet % $dstBase;
$digit = $dstAlphabet[$digitVal];
$dst = $digit . $dst;
$wet /= $dstBase;
}
$digit = $dstAlphabet[$wet];
$dst = $digit . $dst;
return $dst;
}
// prints cb
print convert('125', '0123456789', 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789');
// prints 19158
print convert('e9a', 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', '0123456789');
I like this PHP function which allows you to customise the alphabet (and remove confusing 0/O's etc.)
// From http://snipplr.com/view/22246/base62-encode--decode/
private function base_encode($val, $base=62, $chars='0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ') {
$str = '';
do {
$i = fmod($val, $base);
$str = $chars[$i] . $str;
$val = ($val - $i) / $base;
} while($val > 0);
return $str;
}
Follow the URL to find the reverse 'decode' function too.
The main problem with Marcel's solution is that it uses a zero digit as a placeholder. By converting between bases, inevitably the numeral chosen to represent 0 can't appear at the front of the converted number.
For example, if you convert base 10 integers to base 4 using "ABCD" using the provided mechanism, there is no way to obtain output that starts with the letter "A", since that represents a zero in the new base and won't prefix the number. You might expect 5 to be "AA", but instead, it is "BA". There is no way to coerce that algorithm into producing "AA", because it would be like writing "00" in decimal, which has the same value as "0".
Here's an alternate solution in PHP that uses the entire gamut:
function encode($n, $alphabet = 'ABCD') {
$output = '';
if($n == 0) {
$output = $alphabet[0];
}
else {
$digits = floor(log($n, strlen($alphabet))) + 1;
for($z = 0; $z < $digits; $z++) {
$digit = $n % 4;
$output = $alphabet[$digit] . $output;
$n = floor($n / 4) - 1;
}
}
return $output;
}
function decode($code, $alphabet = 'ABCD') {
$n = 0;
$code = str_split($code);
$unit = 1;
while($letter = array_pop($code)) {
$n += (strpos($alphabet, $letter) + 1) * $unit;
$unit = $unit * strlen($alphabet);
}
return $n - 1;
}
echo encode(25); // should output "ABB"
echo decode('ABB'); // should output 25
Change/pass the second parameter to a list of characters to use instead of the short 4-character dictionary of "ABCD".
all you need to do is convert between different base systems base 10 to base 62
https://github.com/infinitas/infinitas/blob/dev/core/short_urls/models/short_url.php