2015-09-22 5 views
0

Да, я знаю, что есть вопросы, связанные с stackoverflow, но они не очень хорошо работают по моей потребности. Я пытаюсь заменить цвет изображения другим цветом. В нижеприведенном коде я заменяю (255,0,255) на (0,192,239). Ниже код работает, но не полностью заменяет новый цвет над розовым (255,0,255) цвет, некоторые мелкие точки или рамка розового цвета остаются, как вы можете видеть на выходном изображении.Заменить цвет другим цветом в изображении с помощью PHP

Как я могу получить его идеальное решение?

<?php 
$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 == 255 && $green == 0 && $blue == 255) { 
      $red = 0; 
      $green=192; 
      $blue =239; 
     } 

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

Original image output image

+0

Это потому, что эти строки не '(255.0.255)' точно. Для этого вам необходимо реализовать цветовой диапазон. – FrogTheFrog

+0

@Helix Да, я пробовал это, держа диапазон ($ red <= 255 && $ red> = 245) && ($ green> = 0 && $ green <= 10) && ($ blue <= 255 && $ blue> = 245), но выход по-прежнему остается таким же. Я прав? –

+0

Дайте мне секунду, и я постараюсь отправить ответ. Возникли проблемы с базовой математикой. – FrogTheFrog

ответ

2

EDIT 2: Вы, возможно, потребуется оптимизировать что-то и изменить hueAbsoluteError, чтобы удовлетворить ваши потребности, но оттенок путь к просветлению и резче качество изображения (функции взято с https://gist.github.com/brandonheyer/5254516):

<?php 
function RGBtoHSL($r, $g, $b) { 
    $r /= 255; 
    $g /= 255; 
    $b /= 255; 
    $max = max($r, $g, $b); 
    $min = min($r, $g, $b); 
    $l = ($max + $min)/2; 
    $d = $max - $min; 
    if($d == 0){ 
     $h = $s = 0; 
    } else { 
     $s = $d/(1 - abs(2 * $l - 1)); 
     switch($max){ 
      case $r: 
       $h = 60 * fmod((($g - $b)/$d), 6); 
       if ($b > $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); 

enter image description here

EDIT: Лучше решение - определить, если цвет нуждается в замене (с помощью этого метода). Определите оттенок оттенка (я понятия не имею, правильный ли это термин, что я имею в виду - легкость и темнота). Примените его к цвету замены, чтобы придать ему оттенок или ощущение АА.


Итак, как я уже сказал в своем комментарии, вы должны определить, если этот цвет действительно пинг (темный, свет и т.д.). Самое простое решение - применить метод абсолютной ошибки для определенных цветовых каналов. Там может быть (определенно есть) лучше универсальный метод, но я надеюсь, что это будет делать:

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

enter image description here

+0

Я сначала пробежал код, он потерял качество выходного изображения, когда меняю файл (изображение), он принимает синий фон и полностью уничтожает выходное изображение. –

+0

Я попробую другое решение с цветовым пространством HSL. – FrogTheFrog

Смежные вопросы