Change “HUE” of an image with PHP GD Library?

前端 未结 2 1122
臣服心动
臣服心动 2020-12-09 04:36

I\'d like to change the \"hue\" of an image using the PHP image processing functions. Which is the correct filter to apply?

Note: I\'m from a photoshop background, s

相关标签:
2条回答
  • 2020-12-09 05:21

    You'd normally convert from RGB to HSL color space, at which point you can manipulate the hue directly. Once you've done what you want, you convert back to RGB.

    0 讨论(0)
  • 2020-12-09 05:35

    I'm pretty sure there are no functions in PHP that can handle the change of hue. But you can write your own function to do this, here are the steps to change the image's hue:

    1. Traverse the image pixel by pixel
    2. Get the RGB color at pixel using imagecolorat()
    3. Transform the RGB value into a HSL value
    4. Change the hue value, leave saturation and lightness alone (Hue is a value from 0 to 360)
    5. Transform the new HSL value back to RGB
    6. Change the color at current pixel

    Actually this seems quite an interesting thing to try out, so I might just do this myself and post it here if you don't find any other solution.

    EDIT

    Wrote the function. To change hue in PHP, you'll need functions to transform between RGB and HSL color spaces and a function that does the traversing of the image. This might be a bit ugly but it works nicely. Quite slow on larger images.

    function imagehue(&$image, $angle) {
        if($angle % 360 == 0) return;
        $width = imagesx($image);
        $height = imagesy($image);
    
        for($x = 0; $x < $width; $x++) {
            for($y = 0; $y < $height; $y++) {
                $rgb = imagecolorat($image, $x, $y);
                $r = ($rgb >> 16) & 0xFF;
                $g = ($rgb >> 8) & 0xFF;
                $b = $rgb & 0xFF;            
                $alpha = ($rgb & 0x7F000000) >> 24;
                list($h, $s, $l) = rgb2hsl($r, $g, $b);
                $h += $angle / 360;
                if($h > 1) $h--;
                list($r, $g, $b) = hsl2rgb($h, $s, $l);            
                imagesetpixel($image, $x, $y, imagecolorallocatealpha($image, $r, $g, $b, $alpha));
            }
        }
    }
    

    Here's the required helper functions for converting color space, shamelessly copied from http://www.actionscript.org/forums/showthread.php3?t=50746 with minor alterations:

    function rgb2hsl($r, $g, $b) {
       $var_R = ($r / 255);
       $var_G = ($g / 255);
       $var_B = ($b / 255);
    
       $var_Min = min($var_R, $var_G, $var_B);
       $var_Max = max($var_R, $var_G, $var_B);
       $del_Max = $var_Max - $var_Min;
    
       $v = $var_Max;
    
       if ($del_Max == 0) {
          $h = 0;
          $s = 0;
       } else {
          $s = $del_Max / $var_Max;
    
          $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++;
          if ($h > 1) $h--;
       }
    
       return array($h, $s, $v);
    }
    
    function hsl2rgb($h, $s, $v) {
        if($s == 0) {
            $r = $g = $B = $v * 255;
        } else {
            $var_H = $h * 6;
            $var_i = floor( $var_H );
            $var_1 = $v * ( 1 - $s );
            $var_2 = $v * ( 1 - $s * ( $var_H - $var_i ) );
            $var_3 = $v * ( 1 - $s * (1 - ( $var_H - $var_i ) ) );
    
            if       ($var_i == 0) { $var_R = $v     ; $var_G = $var_3  ; $var_B = $var_1 ; }
            else if  ($var_i == 1) { $var_R = $var_2 ; $var_G = $v      ; $var_B = $var_1 ; }
            else if  ($var_i == 2) { $var_R = $var_1 ; $var_G = $v      ; $var_B = $var_3 ; }
            else if  ($var_i == 3) { $var_R = $var_1 ; $var_G = $var_2  ; $var_B = $v     ; }
            else if  ($var_i == 4) { $var_R = $var_3 ; $var_G = $var_1  ; $var_B = $v     ; }
            else                   { $var_R = $v     ; $var_G = $var_1  ; $var_B = $var_2 ; }
    
            $r = $var_R * 255;
            $g = $var_G * 255;
            $B = $var_B * 255;
        }    
        return array($r, $g, $B);
    }
    

    And finally, an usage example. This example opens an image, shifts its hue by 180° and outputs to the browser:

    header('Content-type: image/png');
    $image = imagecreatefrompng('image.png');
    imagehue($image, 180);
    imagepng($image);
    

    As the angle of hue is set in degrees, giving 0, 360, 720 or any multiple of 360 will result in no change to the image.

    0 讨论(0)
提交回复
热议问题