Replace a color with another color in an image with PHP

前端 未结 1 1127
攒了一身酷
攒了一身酷 2021-01-07 10:22

Yes I know there are related questions available on stackoverflow but they are not perfectly work as per my need. I am trying to replace a color of an image with another col

1条回答
  •  粉色の甜心
    2021-01-07 11:03

    EDIT 2 : You might need to optimize something and change hueAbsoluteError to suit your needs, but hue is the way to enlightenment and sharper picture quality (functions taken from https://gist.github.com/brandonheyer/5254516):

     $g) {
                        $h += 360;
                    }
                    break;
                case $g:
                    $h = 60 * ( ( $b - $r ) / $d + 2 );
                    break;
                case $b:
                    $h = 60 * ( ( $r - $g ) / $d + 4 );
                    break;
            }
        }
        return array( round( $h, 2 ), round( $s, 2 ), round( $l, 2 ) );
    }
    
    function HSLtoRGB( $h, $s, $l ){
        $c = ( 1 - abs( 2 * $l - 1 ) ) * $s;
        $x = $c * ( 1 - abs( fmod( ( $h / 60 ), 2 ) - 1 ) );
        $m = $l - ( $c / 2 );
        if ( $h < 60 ) {
            $r = $c;
            $g = $x;
            $b = 0;
        } else if ( $h < 120 ) {
            $r = $x;
            $g = $c;
            $b = 0;
        } else if ( $h < 180 ) {
            $r = 0;
            $g = $c;
            $b = $x;
        } else if ( $h < 240 ) {
            $r = 0;
            $g = $x;
            $b = $c;
        } else if ( $h < 300 ) {
            $r = $x;
            $g = 0;
            $b = $c;
        } else {
            $r = $c;
            $g = 0;
            $b = $x;
        }
        $r = ( $r + $m ) * 255;
        $g = ( $g + $m ) * 255;
        $b = ( $b + $m  ) * 255;
        return array( floor( $r ), floor( $g ), floor( $b ) );
    }
    
    /* ---------------CHANGE THESE------------------- */
    $colorToReplace = RGBtoHSL(255, 0, 255);
    $hueAbsoluteError = 0.4;
    $replacementColor = RGBtoHSL(0, 192, 239);
    /* ---------------------------------------------- */
    
    $filename = 'img/Mascots_Aviators_General-copy.png';
    $im = imagecreatefrompng($filename);
    $out = imagecreatetruecolor(imagesx($im), imagesy($im));
    $transColor = imagecolorallocatealpha($out, 254, 254, 254, 127);
    imagefill($out, 0, 0, $transColor);
    
    for ($x = 0; $x < imagesx($im); $x++) {
        for ($y = 0; $y < imagesy($im); $y++) {
            $pixel = imagecolorat($im, $x, $y);
    
            $red = ($pixel >> 16) & 0xFF;
            $green = ($pixel >> 8) & 0xFF;
            $blue = $pixel & 0xFF;
            $alpha = ($pixel & 0x7F000000) >> 24;
    
            $colorHSL = RGBtoHSL($red, $green, $blue);
    
            if ((($colorHSL[0]  >= $colorToReplace[0] - $hueAbsoluteError) && ($colorToReplace[0] + $hueAbsoluteError) >= $colorHSL[0])){
                $color = HSLtoRGB($replacementColor[0], $replacementColor[1], $colorHSL[2]);
                $red = $color[0];
                $green= $color[1];
                $blue = $color[2];
            }
    
            if ($alpha == 127) {
                imagesetpixel($out, $x, $y, $transColor);
            }
            else {
                imagesetpixel($out, $x, $y, imagecolorallocatealpha($out, $red, $green, $blue, $alpha));
            }
        }
    }
    imagecolortransparent($out, $transColor);
    imagesavealpha($out, TRUE);
    header('Content-type: image/png');
    imagepng($out);
    

    EDIT : Better solution - determine if color needs replacement (using this method). Determine replaced color's hue (I have no idea if it's correct term, what I mean is lightness and darkness). Apply it to replacement color to give it a shade or AA feeling.


    So, as I have said in my comment, you need to determine if this color is really ping (dark, light, etc.). Easiest solution is to apply absolute error method for specific color channels. There may be (there definitely is) better universal method, but I hope this will do:

    $color = [255, 0, 255];
    $colorAbsoluteError = [150, 0, 150];
    $replacementColor = [0, 192, 239];
    $filename = 'img/Mascots_Aviators_General-copy.png';
    $im = imagecreatefrompng($filename);
    $out = imagecreatetruecolor(imagesx($im), imagesy($im));
    $transColor = imagecolorallocatealpha($out, 254, 254, 254, 127);
    imagefill($out, 0, 0, $transColor);
    
    for ($x = 0; $x < imagesx($im); $x++) {
        for ($y = 0; $y < imagesy($im); $y++) {
            $pixel = imagecolorat($im, $x, $y);
    
            $red = ($pixel >> 16) & 0xFF;
            $green = ($pixel >> 8) & 0xFF;
            $blue = $pixel & 0xFF;
            $alpha = ($pixel & 0x7F000000) >> 24;
    
            if ((($red  >= $color[0] - $colorAbsoluteError[0]) && ($color[0] + $colorAbsoluteError[0]) >= $red) &&
                (($green  >= $color[1] - $colorAbsoluteError[1]) && ($color[1] + $colorAbsoluteError[1]) >= $green) &&
                (($blue  >= $color[2] - $colorAbsoluteError[2]) && ($color[2] + $colorAbsoluteError[2]) >= $blue)){
                $red = $replacementColor[0];
                $green= $replacementColor[1];
                $blue = $replacementColor[2];
            }
    
            if ($alpha == 127) {
                imagesetpixel($out, $x, $y, $transColor);
            }
            else {
                imagesetpixel($out, $x, $y, imagecolorallocatealpha($out, $red, $green, $blue, $alpha));
            }
        }
    }
    imagecolortransparent($out, $transColor);
    imagesavealpha($out, TRUE);
    header('Content-type: image/png');
    imagepng($out);
    

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