Convert Int into 4 Byte String in PHP - php

I need to convert an unsigned integer into a 4 byte string to send on a socket.
I have the following code and it works, but it feels... disgusting.
/**
* #param $int
* #return string
*/
function intToFourByteString( $int ) {
$four = floor($int / pow(2, 24));
$int = $int - ($four * pow(2, 24));
$three = floor($int / pow(2, 16));
$int = $int - ($three * pow(2, 16));
$two = floor($int / pow(2, 8));
$int = $int - ($two * pow(2, 8));
$one = $int;
return chr($four) . chr($three) . chr($two) . chr($one);
}
My friend who uses C says I should be able to do this with bitshifts but I don't know how and he isn't familiar enough with PHP to be helpful. Any help would be appreciated.
To do the reverse I already have the following code
/**
* #param $string
* #return int
*/
function fourByteStringToInt( $string ) {
if( strlen($string) != 4 ) {
throw new \InvalidArgumentException('String to parse must be 4 bytes exactly');
}
return (ord($string[0]) << 24) + (ord($string[1]) << 16) + (ord($string[2]) << 8) + ord($string[3]);
}

This is actually as simple as
$str = pack('N', $int);
see pack. And the reverse:
$int = unpack('N', $str)[1];
If you're curious how to do packing using bit shifts, it goes like this:
function intToFourByteString( $int ) {
return
chr($int >> 24 & 0xFF).
chr($int >> 16 & 0xFF).
chr($int >> 8 & 0xFF).
chr($int >> 0 & 0xFF);
}
Basically, shift eight bits each time and mask with 0xFF (=255) to remove high-order bits.

Related

Convert 6 array-bytes to int64 using PHP

I'm reverse engineering a javascript script to PHP and there are many functions that convert:
6 array bytes of [224, 221, 199, 147, 195, 47]
and output that to 1632933900000 (which is timestamp, Int64)
Can you help me how to pack/unpack those bytes as above to the final integer using PHP ?
Samples:
[224, 221, 199, 147, 195, 47] gets to 1632933900000
[224, 143, 228, 137, 198, 47]
gets to 1633718700000
ADDITIONAL INFO:
The javascript code is very long (it was obfuscated). I just know for certain that it is placed within 6 bytes.
NEXT UPDATE...
It goes to this function (this.buf is array-bytes):
function u() {
var e = new a(0, 0),
t = 0;
if (!(this.len - this.pos > 4)) {
for (; t < 3; ++t) {
if (this.pos >= this.len) throw s(this);
if (e.lo = (e.lo | (127 & this.buf[this.pos]) << 7 * t) >>> 0, this.buf[this.pos++] < 128) return e
}
return e.lo = (e.lo | (127 & this.buf[this.pos++]) << 7 * t) >>> 0, e
}
for (; t < 4; ++t)
if (e.lo = (e.lo | (127 & this.buf[this.pos]) << 7 * t) >>> 0, this.buf[this.pos++] < 128) return e;
if (e.lo = (e.lo | (127 & this.buf[this.pos]) << 28) >>> 0, e.hi = (e.hi | (127 & this.buf[this.pos]) >> 4) >>> 0, this.buf[this.pos++] < 128) return e;
if (t = 0, this.len - this.pos > 4) {
for (; t < 5; ++t)
if (e.hi = (e.hi | (127 & this.buf[this.pos]) << 7 * t + 3) >>> 0, this.buf[this.pos++] < 128) return e
} else
for (; t < 5; ++t) {
if (this.pos >= this.len) throw s(this);
if (e.hi = (e.hi | (127 & this.buf[this.pos]) << 7 * t + 3) >>> 0, this.buf[this.pos++] < 128) return e
}
throw Error("invalid varint encoding")
}
And then it has [hi and low] numbers and this gets the timestamp:
o.prototype.toNumber = function(e) {
if (!e && this.hi >>> 31) {
var t = 1 + ~this.lo >>> 0,
n = ~this.hi >>> 0;
return t || (n = n + 1 >>> 0), -(t + 4294967296 * n)
}
return this.lo + 4294967296 * this.hi
}
224 221 199 147 195 47 is the decimal representation of E0 DD C7 93 C3 2F ... which is 247243140743983 in decimal. Maybe not the whole dword is the timestamp ...for comparision: 01 7C 32 71 EE E0 or 61 54 98 0C. One can already notice by the first digit, how far off this approach is.
That number in JS might be of type BigInt:
BigInt("0x017C3271EEE0")
But BigInt("0xE0DDC793C32F") still gives 247243140743983.
Just to complete this answer I used following stuff, but I have absolutely no clue what it does :D
<?php
function int64_helper($obj)
{
$e = (object) ['lo' => 0, 'hi' => 0];
if (!($obj->len - $obj->pos > 4)) {
for ($i = 0; $i < 3; $i++) {
if ($obj->pos >= $obj->len) throw new Exception('ERROR RANGE');
$e->lo = rrr($e->lo | ((127 & $obj->buf[$obj->pos]) << (7 * $i)), 0);
if ($obj->buf[$obj->pos++] < 128) return $e;
}
$e->lo = rrr($e->lo | ((127 & $obj->buf[$obj->pos++]) << (7 * $i)), 0);
return $e;
}
for ($i = 0; $i < 4; $i++) {
$e->lo = rrr($e->lo | ((127 & $obj->buf[$obj->pos]) << (7 * $i)), 0);
if ($obj->buf[$obj->pos++] < 128) return $e;
}
$e->lo = rrr(($e->lo | ((127 & $obj->buf[$obj->pos]) << 28)), 0);
$e->hi = rrr(($e->hi | rr((127 & $obj->buf[$obj->pos]), 4)), 0);
if ($obj->buf[$obj->pos++] < 128) {
return $e;
}
if ($obj->len - $obj->pos > 4) {
for ($i = 0; $i < 5; $i++) {
$e->hi = rrr($e->hi | ((127 & $obj->buf[$obj->pos]) << (7 * $i) + 3), 0);
if ($obj->buf[$obj->pos++] < 128) return $e;
}
}
else {
for ($i = 0; $i < 5; $i++) {
if ($obj->pos >= $obj->len) throw new Exception('ERROR RANGE');
$e->hi = rrr($e->hi | ((127 & $obj->buf[$obj->pos]) << (7 * $i) + 3), 0);
if ($obj->buf[$obj->pos++] < 128) return $e;
}
}
throw new Exception("invalid timestamp encoding");
}
/**
* Date time
*/
function int64($obj)
{
$e = int64_helper($obj);
$mst = $e->lo + 4294967296 * $e->hi;
$t = substr($mst, 0, -3); // poslední 3 nuly dávám pryč
$s = date("Y-m-d H:i:s", $t); // prague timezone
return $s;
}
/**
* The >>> javascript operator in php x86_64
* Usage: -1149025787 >>> 0 ---> rrr(-1149025787, 0) === 3145941509
* #return int
*/
function rrr($v, $n)
{
return ($v & 0xFFFFFFFF) >> ($n & 0x1F);
}
/**
* The >> javascript operator in php x86_64
* #return int
*/
function rr($v, $n)
{
return ($v & 0x80000000 ? $v | 0xFFFFFFFF00000000 : $v & 0xFFFFFFFF) >> ($n & 0x1F);
}
/**
* The << javascript operator in php x86_64
* #return int
*/
function ll($v, $n)
{
return ($t = ($v & 0xFFFFFFFF) << ($n & 0x1F)) & 0x80000000 ? $t | 0xFFFFFFFF00000000 : $t & 0xFFFFFFFF;
}

Convert binary or hexadecimal string using php into 32-bit float value. Big endian \ Little endian

How can I convert 32-bit binary string like 00111001101010000101110000100010 or hexadecimal string like 39a85c22 into float value?
For use in zend framework.
I use the following class. Usage which output 0.00032112101325765 3 times:
$x = new Application_Model_Binary("39a85c22");
echo "\n".$x->getFloatFromBits(0, Application_Model_Binary::ENDIAN_BIG);
$x = new Application_Model_Binary("00111001101010000101110000100010", false);
echo "\n".$x->getFloatFromBits(0, Application_Model_Binary::ENDIAN_BIG);
$x = new Application_Model_Binary("225ca839");
echo "\n".$x->getFloatFromBits(0, Application_Model_Binary::ENDIAN_LITTLE);
and the class
class Application_Model_Binary
{
const ENDIAN_BIG = 0;
const ENDIAN_LITTLE = 1;
private $bin;
public function __construct($string, $as_hex = true) {
if($as_hex){
$this->bin = $this->hex2bin($string);
}else{
$this->bin = $string;
}
}
/**
* convert hex-string into bin-string
* #param string $data
* #return string
*/
private function hex2bin($data){
$encoded = '';
$data_arr = str_split($data, 2);
foreach($data_arr as $val){
$binary = base_convert($val, 16, 2);
$encoded .= str_pad($binary, 8, '0', STR_PAD_LEFT);
}
return $encoded;
}
/**
* get integer value out of current binary
* #param integer $start offset
* #param integer $length length
* #return integer
*/
public function getValueFromBits($start, $length = null){
return base_convert($this->getBinarySlice($start, $length), 2, 10);
}
/**
* get particular piece of current binary
* #param integer $start
* #param integer $length
* #return string
*/
public function getBinarySlice($start, $length = null){
if($length){
return substr($this->bin, $start, $length);
}else{
return substr($this->bin, $start);
}
}
/**
* bits count
* #return type
*/
public function bits(){
return strlen($this->bin);
}
/**
* get 32-bit float value at particular offset at specific endian type
* #param integer $offset offset
* #return float
*/
public function getFloatFromBits($offset, $mode = self::ENDIAN_BIG){
if($mode === self::ENDIAN_BIG){
$sign = $this->getBinarySlice($offset, 1);
$exp = $this->getBinarySlice($offset + 1, 8);
$mantissa = "1" . $this->getBinarySlice($offset + 9, 23);
}else{
$sign = $this->getBinarySlice($offset + 24, 1);
$exp = $this->getBinarySlice($offset + 25, 7).$this->getBinarySlice($offset + 16, 1);
$mantissa = "1" . $this->getBinarySlice($offset + 17, 7) . $this->getBinarySlice($offset + 8, 8) . $this->getBinarySlice($offset, 8);
}
$mantissa = str_split($mantissa);
$exp = bindec($exp) - 127;
$base = 0;
for ($i = 0; $i < 24; $i++) {
$base += (1 / pow(2, $i))*$mantissa[$i];
}
return $base * pow(2, $exp) * ($sign*-2+1);
}
}

PHP function to convert HSL to RGB or Hex

Does anyone know a PHP function (for >5.3) which can convert an HSL color to either RGB or Hex? I've tried a dozen Google searches and none of the functions I have found work as expected.
It doesn't matter whether the function converts to RGB or hex because converting between those two is trivial. The inputs are HSL values for CSS (Hue: 0–360, Saturation: 0–100, Lightness: 0–100).
Edit: Specifying the input and output format would be a bonus :)
Taking the code from one of the answers in the link of Jim's comment (PHP HSV to RGB formula comprehension), we can compute it as follows:
<?php
$hue = 209;
$sat = 75;
$lum = 60;
$hue /= 360;
$sat /= 100;
$lum /= 100;
$result = ColorHSLToRGB($hue, $sat, $lum);
var_dump($result); echo '<br>';
printf("rgb = %d,%d,%d<br>", $result['r'], $result['g'], $result['b']);
function ColorHSLToRGB($h, $s, $l){
$r = $l;
$g = $l;
$b = $l;
$v = ($l <= 0.5) ? ($l * (1.0 + $s)) : ($l + $s - $l * $s);
if ($v > 0){
$m;
$sv;
$sextant;
$fract;
$vsf;
$mid1;
$mid2;
$m = $l + $l - $v;
$sv = ($v - $m ) / $v;
$h *= 6.0;
$sextant = floor($h);
$fract = $h - $sextant;
$vsf = $v * $sv * $fract;
$mid1 = $m + $vsf;
$mid2 = $v - $vsf;
switch ($sextant)
{
case 0:
$r = $v;
$g = $mid1;
$b = $m;
break;
case 1:
$r = $mid2;
$g = $v;
$b = $m;
break;
case 2:
$r = $m;
$g = $v;
$b = $mid1;
break;
case 3:
$r = $m;
$g = $mid2;
$b = $v;
break;
case 4:
$r = $mid1;
$g = $m;
$b = $v;
break;
case 5:
$r = $v;
$g = $m;
$b = $mid2;
break;
}
}
return array('r' => $r * 255.0, 'g' => $g * 255.0, 'b' => $b * 255.0);
}
?>
Output:
array(3) { ["r"]=> float(76.5) ["g"]=> float(155.55) ["b"]=> float(229.5) }
rgb = 76,155,229
Putting this together (which helped me produce this chart)
/**
* convert a HSL colorscheme to either Hexadecimal (default) or RGB.
*
* We want a method where we can programmatically generate a series of colors
* between two values (eg. red to green) which is easy to do with HSL because
* you just change the hue. (0 = red, 120 = green). You can use this function
* to convert those hsl color values to either the rgb or hexadecimal color scheme.
* e.g. You have
* hsl(50, 100%, 50%)
* To convert,
* $hex = convertHSL(50,100,50); // returns #ffd500
* or
* $rgb = convertHSL(50,100,50, false); // returns rgb(255, 213, 0)
*
* see https://coderwall.com/p/dvsxwg/smoothly-transition-from-green-to-red
* #param int $h the hue
* #param int $s the saturation
* #param int $l the luminance
* #param bool $toHex whether you want hexadecimal equivalent or rgb equivalent
* #return string usable in HTML or CSS
*/
function convertHSL($h, $s, $l, $toHex=true){
$h /= 360;
$s /=100;
$l /=100;
$r = $l;
$g = $l;
$b = $l;
$v = ($l <= 0.5) ? ($l * (1.0 + $s)) : ($l + $s - $l * $s);
if ($v > 0){
$m;
$sv;
$sextant;
$fract;
$vsf;
$mid1;
$mid2;
$m = $l + $l - $v;
$sv = ($v - $m ) / $v;
$h *= 6.0;
$sextant = floor($h);
$fract = $h - $sextant;
$vsf = $v * $sv * $fract;
$mid1 = $m + $vsf;
$mid2 = $v - $vsf;
switch ($sextant)
{
case 0:
$r = $v;
$g = $mid1;
$b = $m;
break;
case 1:
$r = $mid2;
$g = $v;
$b = $m;
break;
case 2:
$r = $m;
$g = $v;
$b = $mid1;
break;
case 3:
$r = $m;
$g = $mid2;
$b = $v;
break;
case 4:
$r = $mid1;
$g = $m;
$b = $v;
break;
case 5:
$r = $v;
$g = $m;
$b = $mid2;
break;
}
}
$r = round($r * 255, 0);
$g = round($g * 255, 0);
$b = round($b * 255, 0);
if ($toHex) {
$r = ($r < 15)? '0' . dechex($r) : dechex($r);
$g = ($g < 15)? '0' . dechex($g) : dechex($g);
$b = ($b < 15)? '0' . dechex($b) : dechex($b);
return "#$r$g$b";
} else {
return "rgb($r, $g, $b)";
}
My tests of all other implementations showed only weird and possibly unplausible results. Here is a PHP implementation of #Mohsen's code from https://stackoverflow.com/a/9493060/1598477. Plus a test to show the full beauty...
Sorry to cross-post this. But I really haven't seen any other implementation that gives the quality I needed.
/**
* Converts an HSL color value to RGB. Conversion formula
* adapted from http://en.wikipedia.org/wiki/HSL_color_space.
* Assumes h, s, and l are contained in the set [0, 1] and
* returns r, g, and b in the set [0, 255].
*
* #param {number} h The hue
* #param {number} s The saturation
* #param {number} l The lightness
* #return {Array} The RGB representation
*/
function hue2rgb($p, $q, $t){
if($t < 0) $t += 1;
if($t > 1) $t -= 1;
if($t < 1/6) return $p + ($q - $p) * 6 * $t;
if($t < 1/2) return $q;
if($t < 2/3) return $p + ($q - $p) * (2/3 - $t) * 6;
return $p;
}
function hslToRgb($h, $s, $l){
if($s == 0){
$r = $l;
$g = $l;
$b = $l; // achromatic
}else{
$q = $l < 0.5 ? $l * (1 + $s) : $l + $s - $l * $s;
$p = 2 * $l - $q;
$r = hue2rgb($p, $q, $h + 1/3);
$g = hue2rgb($p, $q, $h);
$b = hue2rgb($p, $q, $h - 1/3);
}
return array(round($r * 255), round($g * 255), round($b * 255));
}
/* Uncomment to test * /
for ($i=0;$i<360;$i++) {
$rgb=hslToRgb($i/360, 1, .9);
echo '<div style="background-color:rgb(' .$rgb[0] . ', ' . $rgb[1] . ', ' . $rgb[2] . ');padding:2px;"></div>';
}
/* End Test */
The PEAR package Image_Color2 has methods to transform between color models - see convertTo.
Here is my solution
HSV value restrictions: $H [0-359], $S [0-100], $V [0-100]
function hsv_to_rgb($iH, $iS, $iV) {
if($iH < 0) $iH = 0;
if($iH > 360) $iH = 360;
if($iS < 0) $iS = 0;
if($iS > 100) $iS = 100;
if($iV < 0) $iV = 0;
if($iV > 100) $iV = 100;
$dS = $iS/100.0;
$dV = $iV/100.0;
$dC = $dV*$dS;
$dH = $iH/60.0;
$dT = $dH;
while($dT >= 2.0) $dT -= 2.0; // php modulus does not work with float
$dX = $dC*(1-abs($dT-1)); // as used in the Wikipedia link
switch($dH) {
case($dH >= 0.0 && $dH < 1.0):
$dR = $dC; $dG = $dX; $dB = 0.0; break;
case($dH >= 1.0 && $dH < 2.0):
$dR = $dX; $dG = $dC; $dB = 0.0; break;
case($dH >= 2.0 && $dH < 3.0):
$dR = 0.0; $dG = $dC; $dB = $dX; break;
case($dH >= 3.0 && $dH < 4.0):
$dR = 0.0; $dG = $dX; $dB = $dC; break;
case($dH >= 4.0 && $dH < 5.0):
$dR = $dX; $dG = 0.0; $dB = $dC; break;
case($dH >= 5.0 && $dH < 6.0):
$dR = $dC; $dG = 0.0; $dB = $dX; break;
default:
$dR = 0.0; $dG = 0.0; $dB = 0.0; break;
}
$dM = $dV - $dC;
$dR += $dM; $dG += $dM; $dB += $dM;
$dR *= 255; $dG *= 255; $dB *= 255;
return array(round($dR), round($dG), round($dB));
}
Copied from this SO Answer by Cullub.
This code worked perfectly to convert a user email to user avatar colour. After long hours of searching, I got the correct hex value similar to the one generated using javascript on the front end.
TL;DR: The full code can be found here on Pastebin.
/**
* convert user email to hsl for user avatar
* #param string $string
* #return string HEX color code
*/
function stringToColor($string)
{
$hash = 0;
$l = 70;
$s = 60;
for ($i = 0; $i < strlen($string); $i++) {
$hash = ord($string[$i]) + (($hash << 5) - $hash);
}
$h = fmod($hash, 360);
return $this->hslToHex($h, $s, $l, true);
}
/**
* Converts HSL to Hex by converting it to
* RGB, then converting that to hex.
*
* string hslToHex($h, $s, $l[, $prependPound = true]
*
* $h is the Degrees value of the Hue
* $s is the Percentage value of the Saturation
* $l is the Percentage value of the Lightness
* $prependPound is a bool, whether you want a pound
* sign prepended. (optional - default=true)
*
* Calls:
* hslToRgb
*
* Output: Hex in the format: #00ff88 (with
* pound sign). Rounded to the nearest whole
* number.
*/
function hslToHex($h, $s, $l, $prependPound = true)
{
//convert hsl to rgb
$rgb = $this->hslToRgb($h, $s, $l);
//convert rgb to hex
$hexR = $rgb['r'];
$hexG = $rgb['g'];
$hexB = $rgb['b'];
//round to the nearest whole number
$hexR = round($hexR);
$hexG = round($hexG);
$hexB = round($hexB);
//convert to hex
$hexR = dechex($hexR);
$hexG = dechex($hexG);
$hexB = dechex($hexB);
//check for a non-two string length
//if it's 1, we can just prepend a
//0, but if it is anything else non-2,
//it must return false, as we don't
//know what format it is in.
if (strlen($hexR) != 2) {
if (strlen($hexR) == 1) {
//probably in format #0f4, etc.
$hexR = "0" . $hexR;
} else {
//unknown format
return false;
}
}
if (strlen($hexG) != 2) {
if (strlen($hexG) == 1) {
$hexG = "0" . $hexG;
} else {
return false;
}
}
if (strlen($hexB) != 2) {
if (strlen($hexB) == 1) {
$hexB = "0" . $hexB;
} else {
return false;
}
}
//if prependPound is set, will prepend a
//# sign to the beginning of the hex code.
//(default = true)
$hex = "";
if ($prependPound) {
$hex = "#";
}
$hex = $hex . $hexR . $hexG . $hexB;
return $hex;
}
/**
* Converts an HSL color value to RGB. Conversion formula
* adapted from http://www.niwa.nu/2013/05/math-behind-colorspace-conversions-rgb-hsl/.
* Assumes h, s, and l are in the format Degrees,
* Percent, Percent, and returns r, g, and b in
* the range [0 - 255].
*
* Called by hslToHex by default.
*
* Calls:
* degPercPercToHsl
* hueToRgb
*
* #param Number h The hue value
* #param Number s The saturation level
* #param Number l The luminence
* #return Array The RGB representation
*/
function hslToRgb($h, $s, $l)
{
//convert the hue's 360 degrees in a circle to 1
$h /= 360;
//convert the saturation and lightness to the 0-1
//range by multiplying by 100
$s /= 100;
$l /= 100;
//If there's no saturation, the color is a greyscale,
//so all three RGB values can be set to the lightness.
//(Hue doesn't matter, because it's grey, not color)
if ($s == 0) {
$r = $l * 255;
$g = $l * 255;
$b = $l * 255;
} else {
//calculate some temperary variables to make the
//calculation eaisier.
if ($l < 0.5) {
$temp2 = $l * (1 + $s);
} else {
$temp2 = ($l + $s) - ($s * $l);
}
$temp1 = 2 * $l - $temp2;
//run the calculated vars through hueToRgb to
//calculate the RGB value. Note that for the Red
//value, we add a third (120 degrees), to adjust
//the hue to the correct section of the circle for
//red. Simalarly, for blue, we subtract 1/3.
$r = 255 * $this->hueToRgb($temp1, $temp2, $h + (1 / 3));
$g = 255 * $this->hueToRgb($temp1, $temp2, $h);
$b = 255 * $this->hueToRgb($temp1, $temp2, $h - (1 / 3));
}
$rgb['r'] = $r;
$rgb['g'] = $g;
$rgb['b'] = $b;
return $rgb;
// return "rgb($r, $g, $b)";
}
/**
* Converts an HSL hue to it's RGB value.
*
* Input: $temp1 and $temp2 - temperary vars based on
* whether the lumanence is less than 0.5, and
* calculated using the saturation and luminence
* values.
* $hue - the hue (to be converted to an RGB
* value) For red, add 1/3 to the hue, green
* leave it alone, and blue you subtract 1/3
* from the hue.
*
* Output: One RGB value.
*
* Thanks to Easy RGB for this function (Hue_2_RGB).
* http://www.easyrgb.com/index.php?X=MATH&$h=19#text19
*
*/
function hueToRgb($temp1, $temp2, $hue)
{
if ($hue < 0) {
$hue += 1;
}
if ($hue > 1) {
$hue -= 1;
}
if ((6 * $hue) < 1) {
return ($temp1 + ($temp2 - $temp1) * 6 * $hue);
} elseif ((2 * $hue) < 1) {
return $temp2;
} elseif ((3 * $hue) < 2) {
return ($temp1 + ($temp2 - $temp1) * ((2 / 3) - $hue) * 6);
}
return $temp1;
}
If you have decimal RGB values (enhzflep showed how to get them), you can easily get the #ab01cd hex web string:
$rgb['r'] = ($t = round($rgb['r'] * 255, 0)) < 15 ? '0'.dechex($t) : dechex($t);
$rgb['g'] = ($t = round($rgb['g'] * 255, 0)) < 15 ? '0'.dechex($t) : dechex($t);
$rgb['b'] = ($t = round($rgb['b'] * 255, 0)) < 15 ? '0'.dechex($t) : dechex($t);
$hexweb = "#".$rgb['r'].$rgb['g'].$rgb['b'];

How do I make a lighter version of a colour using PHP?

Hello fellow earthlings. A quesion about RGB color and its usefulness in a simple tiny php code:
Imagine I have variable $colorA containning a valid six char color. say B1B100, a greenish natural color. Now If I would like to make a new color from that, which is, say, ten steps lighter thatn that original color, roughly.
$colorA = B1B100 // original color
php code with little color engine lightening stuff up goes here
$colorB = ?????? // original color lightened up
Is there a php ready function that KNOWS rgb colors something like
php function RGB ( input color, what to do, output color)
Where what to do could be +/- 255 values of brightness etc etc.
Is something like this already possible or am I day dreaming?
rgb-hsl($colorA, +10, $colorB);
If this does not exist, what would be the shortest code for doing this? Suggestions, code or ideas are all answers to me. Thanks.
This SO question has a full-blown PHP script that can convert a RGB to a HSL colour, and increase its H component of a HSL colour - it should be trivial to change to increase L instead.
In general if you want a lighter shade of a particular colour, the most accurate process is to convert from RGB to HSL (or HSV), change the 'L' (or 'V') value which represents lightness, and then convert back to RGB.
This will preserve the "hue", which represents where the colour sits on the spectrum, but change the "tint" (if lightening) or "shade" (if darkening) of that colour.
See http://en.wikipedia.org/wiki/HSL_and_HSV for more information.
On this website: http://www.sitepoint.com/forums/showthread.php?t=586223 they are talking about this code which is originally made by opensource Drupal. Seems to work fine in PHP!?
Now, how do I now indermingle myself with this code and change the lightness of an HSL value, before its outputted as RGB again?
<?php
### RGB >> HSL
function _color_rgb2hsl($rgb) {
$r = $rgb[0]; $g = $rgb[1]; $b = $rgb[2];
$min = min($r, min($g, $b)); $max = max($r, max($g, $b));
$delta = $max - $min; $l = ($min + $max) / 2; $s = 0;
if ($l > 0 && $l < 1) {
$s = $delta / ($l < 0.5 ? (2 * $l) : (2 - 2 * $l));
}
$h = 0;
if ($delta > 0) {
if ($max == $r && $max != $g) $h += ($g - $b) / $delta;
if ($max == $g && $max != $b) $h += (2 + ($b - $r) / $delta);
if ($max == $b && $max != $r) $h += (4 + ($r - $g) / $delta);
$h /= 6;
} return array($h, $s, $l);
}
### HSL >> RGB
function _color_hsl2rgb($hsl) {
$h = $hsl[0]; $s = $hsl[1]; $l = $hsl[2];
$m2 = ($l <= 0.5) ? $l * ($s + 1) : $l + $s - $l*$s;
$m1 = $l * 2 - $m2;
return array(_color_hue2rgb($m1, $m2, $h + 0.33333),
_color_hue2rgb($m1, $m2, $h),
_color_hue2rgb($m1, $m2, $h - 0.33333));
}
### Helper function for _color_hsl2rgb().
function _color_hue2rgb($m1, $m2, $h) {
$h = ($h < 0) ? $h + 1 : (($h > 1) ? $h - 1 : $h);
if ($h * 6 < 1) return $m1 + ($m2 - $m1) * $h * 6;
if ($h * 2 < 1) return $m2;
if ($h * 3 < 2) return $m1 + ($m2 - $m1) * (0.66666 - $h) * 6;
return $m1;
}
### Convert a hex color into an RGB triplet.
function _color_unpack($hex, $normalize = false) {
if (strlen($hex) == 4) {
$hex = $hex[1] . $hex[1] . $hex[2] . $hex[2] . $hex[3] . $hex[3];
} $c = hexdec($hex);
for ($i = 16; $i >= 0; $i -= 8) {
$out[] = (($c >> $i) & 0xFF) / ($normalize ? 255 : 1);
} return $out;
}
### Convert an RGB triplet to a hex color.
function _color_pack($rgb, $normalize = false) {
foreach ($rgb as $k => $v) {
$out |= (($v * ($normalize ? 255 : 1)) << (16 - $k * 8));
}return '#'. str_pad(dechex($out), 6, 0, STR_PAD_LEFT);
}
/* $testrgb = array(0.2,0.75,0.4); //RGB to start with
print_r($testrgb); */
print "Hex: ";
$testhex = "#b7b700";
print $testhex;
$testhex2rgb = _color_unpack($testhex,true);
print "<br />RGB: ";
var_dump($testhex2rgb);
print "<br />HSL color module: ";
$testrgb2hsl = _color_rgb2hsl($testhex2rgb); //Converteren naar HSL
var_dump($testrgb2hsl);
print "<br />RGB: ";
$testhsl2rgb = _color_hsl2rgb($testrgb2hsl); // En weer terug naar RGB
var_dump($testhsl2rgb);
print "<br />Hex: ";
$testrgb2hex = _color_pack($testhsl2rgb,true);
var_dump($testrgb2hex);
?>
PHP does have a couple image manipulation libraries. Either GD or Imagemagick
EDIT: I jumped the gun, these libraries do not have direct PHP color manipulation functions - I honestly assumed they did of a sort after seeing a lot of the things they can do with images via PHP. They do accomplish a lot of cool things. Here's one guy's example.

How to decode numeric HTML entities in PHP

I'm trying to decode encoded long dash from numeric entity to string, but it seems that I can't find a function which can do this properly.
The best that I found is mb_decode_numericentity(), however, for some reason it fails to decode long dash and some other special characters.
$str = '–';
$str = mb_decode_numericentity($str, array(0xFF, 0x2FFFF, 0, 0xFFFF), 'ISO-8859-1');
This will return "?".
Anyone knows how to solve this problem?
The following code snippet (mostly stolen from here and improved) will work for literal, numeric decimal, and numeric hexa-decimal entities:
header("content-type: text/html; charset=utf-8");
/**
* Decodes all HTML entities, including numeric and hexadecimal ones.
*
* #param mixed $string
* #return string decoded HTML
*/
function html_entity_decode_numeric($string, $quote_style = ENT_COMPAT, $charset = "utf-8")
{
$string = html_entity_decode($string, $quote_style, $charset);
$string = preg_replace_callback('~&#x([0-9a-fA-F]+);~i', "chr_utf8_callback", $string);
$string = preg_replace('~&#([0-9]+);~e', 'chr_utf8("\\1")', $string);
return $string;
}
/**
* Callback helper
*/
function chr_utf8_callback($matches)
{
return chr_utf8(hexdec($matches[1]));
}
/**
* Multi-byte chr(): Will turn a numeric argument into a UTF-8 string.
*
* #param mixed $num
* #return string
*/
function chr_utf8($num)
{
if ($num < 128) return chr($num);
if ($num < 2048) return chr(($num >> 6) + 192) . chr(($num & 63) + 128);
if ($num < 65536) return chr(($num >> 12) + 224) . chr((($num >> 6) & 63) + 128) . chr(($num & 63) + 128);
if ($num < 2097152) return chr(($num >> 18) + 240) . chr((($num >> 12) & 63) + 128) . chr((($num >> 6) & 63) + 128) . chr(($num & 63) + 128);
return '';
}
$string ="”";
echo html_entity_decode_numeric($string);
Improvement suggestions are welcome.
mb_decode_numericentity does not handle hexadecimal, only decimal. Do you get the expected result with:
$str = '–';
$str = mb_decode_numericentity ( $str , Array(255, 3145727, 0, 65535) , 'ISO-8859-1');
You can use hexdec to convert your hexadecimal to decimal.
Also, out of curiosity, does the following work:
$str = '–';
$str = html_entity_decode($str);

Categories