/**
 * Shift a given color, using a reference pair and a target blend color.
 *
 * Note: this function is significantly different from the JS version, as it
 * is written to match the blended images perfectly.
 *
 * Constraint: if (ref2 == target + (ref1 - target) * delta) for some fraction delta
 *              then (return == target + (given - target) * delta)
 *
 * Loose constraint: Preserve relative positions in saturation and luminance
 *                   space.
 */
function _color_shift($given, $ref1, $ref2, $target)
{
    // We assume that ref2 is a blend of ref1 and target and find
    // delta based on the length of the difference vectors:
    // delta = 1 - |ref2 - ref1| / |white - ref1|
    $target = _color_unpack($target, true);
    $ref1 = _color_unpack($ref1, true);
    $ref2 = _color_unpack($ref2, true);
    for ($i = 0; $i < 3; ++$i) {
        $numerator += ($ref2[$i] - $ref1[$i]) * ($ref2[$i] - $ref1[$i]);
        $denominator += ($target[$i] - $ref1[$i]) * ($target[$i] - $ref1[$i]);
    }
    $delta = $denominator > 0 ? 1 - sqrt($numerator / $denominator) : 0;
    // Calculate the color that ref2 would be if the assumption was true.
    for ($i = 0; $i < 3; ++$i) {
        $ref3[$i] = $target[$i] + ($ref1[$i] - $target[$i]) * $delta;
    }
    // If the assumption is not true, there is a difference between ref2 and ref3.
    // We measure this in HSL space. Notation: x' = hsl(x).
    $ref2 = _color_rgb2hsl($ref2);
    $ref3 = _color_rgb2hsl($ref3);
    for ($i = 0; $i < 3; ++$i) {
        $shift[$i] = $ref2[$i] - $ref3[$i];
    }
    // Take the given color, and blend it towards the target.
    $given = _color_unpack($given, true);
    for ($i = 0; $i < 3; ++$i) {
        $result[$i] = $target[$i] + ($given[$i] - $target[$i]) * $delta;
    }
    // Finally, we apply the extra shift in HSL space.
    // Note: if ref2 is a pure blend of ref1 and target, then |shift| = 0.
    $result = _color_rgb2hsl($result);
    for ($i = 0; $i < 3; ++$i) {
        $result[$i] = min(1, max(0, $result[$i] + $shift[$i]));
    }
    $result = _color_hsl2rgb($result);
    // Return hex color.
    return _color_pack($result, true);
}
Example #2
0
/**
 * Preprocessor for theme_spaces_design().
 */
function ginkgo_preprocess_spaces_design(&$vars)
{
    if (module_exists('color') && !empty($vars['color'])) {
        if ($rgb = _color_unpack($vars['color'], TRUE)) {
            $classes = context_get('theme', 'body_classes');
            $classes .= ' color';
            context_set('theme', 'body_classes', $classes);
            $hsl = _color_rgb2hsl($rgb);
            if ($hsl[2] > 0.8) {
                $hsl[2] = 0.7;
                $rgb = _color_hsl2rgb($hsl);
            }
            // This code generates color values that are blended against
            // Black/White -- IT DOES NOT PRESERVE SATURATION.
            $modifiers = array('upshift' => $hsl[2] < 0.25 ? array('+', 0.1) : array('+', 0.25), 'downshift' => array('-', 0.38));
            foreach ($modifiers as $id => $modifier) {
                $color = $rgb;
                foreach ($rgb as $k => $v) {
                    switch ($modifier[0]) {
                        case '-':
                            $color[$k] = $color[$k] * (1 - $modifier[1]);
                            break;
                        default:
                            $color[$k] = $color[$k] + (1 - $color[$k]) * $modifier[1];
                            break;
                    }
                }
                $vars[$id] = _color_pack($color, TRUE);
            }
            $vars['color'] = _color_pack($rgb, TRUE);
        }
    }
}
Example #3
0
/**
* Autohift colors in HSL color space
* @param color
* CSS hex color to be shifted (e.g. #000000 )
* @param $X_min
* Hue/Saturation/Lightness minimum value, normalized to a fraction of 1
* @param $X_max
* Hue/Saturation/Lightness maximum value, normalized to a fraction of 1
* @return a string containing a CSS hexcolor (e.g. #000000 )
*/
function color_autoshift($color, $min_h, $max_h, $min_s, $max_s, $min_l, $max_l)
{
    $newcolor = _color_unpack($color, TRUE);
    // hex to RGB
    $newcolor = _color_rgb2hsl($newcolor);
    // RGB to HSL
    if ($min_h) {
        if ($newcolor[0] < $min_h) {
            $newcolor[0] = $min_h;
        }
    }
    if ($max_h) {
        if ($newcolor[0] > $max_h) {
            $newcolor[0] = $max_h;
        }
    }
    if ($min_s) {
        if ($newcolor[1] < $min_s) {
            $newcolor[1] = $min_s;
        }
    }
    if ($max_s) {
        if ($newcolor[1] > $max_s) {
            $newcolor[1] = $max_s;
        }
    }
    if ($min_l) {
        if ($newcolor[2] < $min_l) {
            $newcolor[2] = $min_l;
        }
    }
    if ($max_l) {
        if ($newcolor[2] > $max_l) {
            $newcolor[2] = $max_l;
        }
    }
    $newcolor = _color_hsl2rgb($newcolor);
    // Back to RGB
    $newcolor = _color_pack($newcolor, TRUE);
    // RGB back to hex
    return $newcolor;
}