Translating a C++ function to PHP riddle involving log functions - php

This is a C++ to PHP riddle involving log functions.
I need to translate the following function into PHP ... It's a long story, but we are sure we have a lot of it figured out ... but I could use another pair of eyes.
I have a possible PHP implementation below ...
We have examples of data on the C++ side that produce checksums that we cannot reproduce on the PHP side ... frustrating.
============================================================
#define SYNC_CHECKSUM_MULT (0x01000193)
/**
* Calculate a reasonable checksum for floating point numbers.
*/
static void oi_AccumulateFloat64Checksum(oiInt& checksum, oiFloat64 f)
{
// j = round(f * 2^k), where j is a 12-bit number
if ( oi_IsNaN(f) || oi_IsInf(f) )
{
checksum ^= 1;
checksum *= SYNC_CHECKSUM_MULT;
return;
}
oiInt exponent = (oiInt)logb(f);
oiInt k = 12 - exponent;
oiFloat64 jUnrounded = scalb(f, k);
oiFloat64 jRounded = floor(jUnrounded + 0.5);
oiInt kChange = (oiInt)logb(jRounded) - 12;
k += kChange;
oiFloat64 jFloat = scalb(jRounded, kChange);
oiInt j = (oiInt)jFloat;
checksum ^= j;
checksum *= SYNC_CHECKSUM_MULT;
checksum ^= k;
checksum *= SYNC_CHECKSUM_MULT;
}
============= PHP Implementation =========================
This is executed before we call this function.. $intChecksum = 0;
public function AccumulateFloatChecksum(&$intChecksum, $floatValue) {
// j = round(f * 2^k), where j is a 12-bit number
$TRIVIAL_CHECKSUM_MULT = 0x01000193;
if ( !is_numeric($floatValue) || $floatValue == 0 || is_nan($floatValue) || is_infinite($floatValue) )
{
$intChecksum ^= 1;
$intChecksum *= $TRIVIAL_CHECKSUM_MULT;
$intChecksum &= 0xFFFFFFFF;
return;
}
//var_dump('$floatValue: '.$floatValue);
// oiInt exponent = (oiInt)logb(f);
$exponent = intval(log($floatValue, 2));
//var_dump('$exponent: '.$exponent);
// oiInt k = 12 - exponent;
$k = 12 - $exponent;
//var_dump('$k 1: '.$k);
// oiFloat64 jUnrounded = scalb(f, k);
$jUnrounded = $floatValue * pow(2, $k);
//var_dump('$jUnrounded: '.$jUnrounded);
// oiFloat64 jRounded = floor(jUnrounded + 0.5);
$jRounded = floor($jUnrounded + 0.5);
//var_dump('$jRounded: '.$jRounded);
// oiInt kChange = (oiInt)logb(jRounded) - 12;
$kChange = intval(log($jRounded, 2)) - 12;
//var_dump('$kChange: '.$kChange);
// k += kChange;
$k += $kChange;
//var_dump('$k 2: '.$k);
// oiFloat64 jFloat = scalb(jRounded, kChange);
$jFloat = $jRounded * pow(2, $kChange);
//var_dump('$jFloat: '.$jFloat);
$j = intval($jFloat);
//var_dump('$j: '.$j);
//var_dump('===============================');
$intChecksum ^= $j;
$intChecksum *= $TRIVIAL_CHECKSUM_MULT;
$intChecksum &= 0xFFFFFFFF;
$intChecksum ^= $k;
$intChecksum *= $TRIVIAL_CHECKSUM_MULT;
$intChecksum &= 0xFFFFFFFF;
}

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;
}

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%)'

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'];

NSString en/decode base64

I am trying to make a equilvant of these php functions to encrype/decrypt in objective c but with no luck so far.
I counld't find any base64_en/decode methods in obj-c, is there any?
function encrypt($string, $key) {
$result = '';
 for($i = 0; $i < strlen($string); $i++) {
$char = substr($string, $i, 1);
$keychar = substr($key, ($i % strlen($key))-1, 1);
$char = chr(ord($char) + ord($keychar));
$result .= $char;
 }

return base64_encode($result);
}
function decrypt($string, $key) {
$result = '';
$string = base64_decode($string);
for($i = 0; $i < strlen($string); $i++) {
$char = substr($string, $i, 1);
$keychar = substr($key, ($i % strlen($key))-1, 1);
$char = chr(ord($char) - ord($keychar));
$result.=$char;
}
return $result;
}
Ty already!
Check out this category I use for this very task, it's an NSString category for converting strings to md5, base64 etc...
https://gist.github.com/3907443
From NSString to NSData:
+ (NSString *)encodeBase64WithString:(NSString *)strData {
return [NSString encodeBase64WithData:[strData dataUsingEncoding:NSUTF8StringEncoding]];
}
Encode from NSData:
+ (NSString *)encodeBase64WithData:(NSData *)objData {
const unsigned char * objRawData = [objData bytes];
char * objPointer;
char * strResult;
// Get the Raw Data length and ensure we actually have data
int intLength = [objData length];
if (intLength == 0) return nil;
// Setup the String-based Result placeholder and pointer within that placeholder
strResult = (char *)calloc(((intLength + 2) / 3) * 4, sizeof(char));
objPointer = strResult;
// Iterate through everything
while (intLength > 2) { // keep going until we have less than 24 bits
*objPointer++ = _base64EncodingTable[objRawData[0] >> 2];
*objPointer++ = _base64EncodingTable[((objRawData[0] & 0x03) << 4) + (objRawData[1] >> 4)];
*objPointer++ = _base64EncodingTable[((objRawData[1] & 0x0f) << 2) + (objRawData[2] >> 6)];
*objPointer++ = _base64EncodingTable[objRawData[2] & 0x3f];
// we just handled 3 octets (24 bits) of data
objRawData += 3;
intLength -= 3;
}
// now deal with the tail end of things
if (intLength != 0) {
*objPointer++ = _base64EncodingTable[objRawData[0] >> 2];
if (intLength > 1) {
*objPointer++ = _base64EncodingTable[((objRawData[0] & 0x03) << 4) + (objRawData[1] >> 4)];
*objPointer++ = _base64EncodingTable[(objRawData[1] & 0x0f) << 2];
*objPointer++ = '=';
} else {
*objPointer++ = _base64EncodingTable[(objRawData[0] & 0x03) << 4];
*objPointer++ = '=';
*objPointer++ = '=';
}
}
// Terminate the string-based result
*objPointer = '\0';
// Return the results as an NSString object
return [NSString stringWithCString:strResult encoding:NSASCIIStringEncoding];
}
Decode:
+ (NSData *)decodeBase64WithString:(NSString *)strBase64 {
const char * objPointer = [strBase64 cStringUsingEncoding:NSASCIIStringEncoding];
int intLength = strlen(objPointer);
int intCurrent;
int i = 0, j = 0, k;
unsigned char * objResult;
objResult = calloc(intLength, sizeof(char));
// Run through the whole string, converting as we go
while ( ((intCurrent = *objPointer++) != '\0') && (intLength-- > 0) ) {
if (intCurrent == '=') {
if (*objPointer != '=' && ((i % 4) == 1)) {// || (intLength > 0)) {
// the padding character is invalid at this point -- so this entire string is invalid
free(objResult);
return nil;
}
continue;
}
intCurrent = _base64DecodingTable[intCurrent];
if (intCurrent == -1) {
// we're at a whitespace -- simply skip over
continue;
} else if (intCurrent == -2) {
// we're at an invalid character
free(objResult);
return nil;
}
switch (i % 4) {
case 0:
objResult[j] = intCurrent << 2;
break;
case 1:
objResult[j++] |= intCurrent >> 4;
objResult[j] = (intCurrent & 0x0f) << 4;
break;
case 2:
objResult[j++] |= intCurrent >>2;
objResult[j] = (intCurrent & 0x03) << 6;
break;
case 3:
objResult[j++] |= intCurrent;
break;
}
i++;
}
// mop things up if we ended on a boundary
k = j;
if (intCurrent == '=') {
switch (i % 4) {
case 1:
// Invalid state
free(objResult);
return nil;
case 2:
k++;
// flow through
case 3:
objResult[k] = 0;
}
}
// Cleanup and setup the return NSData
NSData * objData = [[[NSData alloc] initWithBytes:objResult length:j] autorelease];
free(objResult);
return objData;
}

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);
}

Categories