Image Color Replacement Technique

GD and GD2 are useful libraries for creating graphics on-the-fly. Discuss your PHP GD and GD2 scripts here.

Moderators: onion2k, General Moderators

Postby phpScott » Thu Feb 02, 2006 11:00 am

I think yo have to much time on your hands onion.
And if you do can you pass some my way, please?
User avatar
phpScott
DevNet Resident
 
Posts: 1206
Joined: Wed Oct 09, 2002 6:51 pm
Location: Keele, U.K.

Postby Semi_Apocalyptic » Wed Apr 12, 2006 10:25 am

Onion2k, I was playing with the code you posted up, the one with the fuzzy colour replacing and it appears to have difficulty using both black and white, I tried replacing a green (00ff00) with white (ffffff) and the resulting image was filled with what appeared to be pure red (ff0000) where I was expecting the white to be... I'm not great with colour values in either RGB or HSV, but is this a bug that is staring you in the face when looking back at your code?
Semi_Apocalyptic
Forum Newbie
 
Posts: 2
Joined: Wed Apr 12, 2006 9:46 am

Postby onion2k » Wed Apr 12, 2006 2:11 pm

Latest version ..

Things to consider:

1. It's hue replacement, not colour replacement. Black and white are the same hue .. so expecting to replace black or white is very unlikely to work. You'll need to add code to examine the brightness as well as the hue if you want to do that.

2. Be very careful when you choose a value for $colorToChange .. a tiny difference can make a huge change to the image. Same goes for $threshold.

3. It's getting every pixel in the image, and setting every pixel that needs to change hue .. slow as hell.

Syntax: [ Download ] [ Hide ]
<?php



        $file = "dress.png";

        $colorToChange = "AB0A10";

        $newColor = "FF00FF";

        $threshold = 10;



        $image = imagecreatefrompng($file);

        $width = imagesx($image);

        $height = imagesy($image);



        $c1 = sscanf($colorToChange,"%2x%2x%2x");

        list($h,$s,$v) = rgbtohsv($c1[0],$c1[1],$c1[2]);

        $hueToReplace = $h;

        $c2 = sscanf($newColor,"%2x%2x%2x");

        list($h,$s,$v) = rgbtohsv($c2[0],$c2[1],$c2[2]);

        $newHue = $h;

        $newSat = $s;



        for ($y=0;$y<$height;$y++) {

                for ($x=0;$x<$width;$x++) {

                        $rgb = imagecolorat($image,$x,$y);

                        $a = ($rgb >> 24) & 0xFF;

                        $r = ($rgb >> 16) & 0xFF;

                        $g = ($rgb >>  & 0xFF;

                        $b = $rgb & 0xFF;

                        list($h,$s,$v) = rgbtohsv($r,$g,$b);

                        if ($h >= $hueToReplace) {

                                $angle = 360-($h-$hueToReplace);

                        } else {

                                $angle = 360-($hueToReplace-$h);

                        }

                        if ($angle > 180) { $angle = 360-$angle; }

                        if ($angle <= $threshold) {

                                $h = $newHue+($h-$hueToReplace);

                                if ($h<0) { $h+=360; }

                                if ($h>360) { $h-=360; }

                                list($r,$g,$b) = hsvtorgb($h,$s,$v);

                                $color = imagecolorallocatealpha($image,$r,$g,$b,$a);

                                imagesetpixel($image,$x,$y,$color);

                        }

                }

        }



        header("Content-Type: image/png");

        imagepng($image);



        //These are PEAR functions from Image_color2 tweaked to suit my coding style.



        function rgbtohsv($r,$g,$b) {

       

        $r=$r/255; $g=$g/255; $b=$b/255;



        $min = min($r, $g, $b);

        $max = max($r, $g, $b);



        switch ($max) {

                        case 0:

                                $h = $s = $v = 0;

                                break;

                        case $min:

                                $h = $s = 0;

                                $v = $max;

                                break;

                        default:

                                $delta = $max - $min;



                                if( $r == $max ) {

                                        $h = 0 + ( $g - $b ) / $delta;

                                } else if( $g == $max ) {

                                        $h = 2 + ( $b - $r ) / $delta;

                                } else {

                                        $h = 4 + ( $r - $g ) / $delta;

                                }

                                $h *= 60;

                                if($h < 0 ) {

                                        $h += 360;

                                }

                                $s = $delta / $max;

                                $v = $max;

        }

        return array($h, $s, $v);

        }



        function hsvtorgb( $h,$s,$v ) {

       

        if ($s == 0) {

            $r = $g = $b = $v;

        } else {

            $h = $h / 60.0;

            $s = $s;

            $v = $v;



            $hi = floor($h);

            $f = $h - $hi;

            $p = ($v * (1.0 - $s));

            $q = ($v * (1.0 - ($f * $s)));

            $t = ($v * (1.0 - ((1.0 - $f) * $s)));



                        switch( $hi ) {

                                case 0: $r = $v; $g = $t; $b = $p; break;

                                case 1: $r = $q; $g = $v; $b = $p; break;

                                case 2: $r = $p; $g = $v; $b = $t; break;

                                case 3: $r = $p; $g = $q; $b = $v; break;

                                case 4: $r = $t; $g = $p; $b = $v; break;

                                default: $r = $v; $g = $p; $b = $q; break;

                        }

        }

       

        return array(

            (integer) ($r * 255 + 0.5),

            (integer) ($g * 255 + 0.5),

            (integer) ($b * 255 + 0.5)

        );

       

        }



?>
User avatar
onion2k
Jedi Mod
 
Posts: 5263
Joined: Tue Dec 21, 2004 6:03 pm
Location: usrlab.com

Postby Semi_Apocalyptic » Thu Apr 13, 2006 7:27 am

feyd | Please use
Syntax: [ Download ] [ Hide ]
,
[syntax=php]and
Syntax: [ Download ] [ Hide ]
  1. tags where appropriate when posting code. Your post has been edited to reflect how we'd like it posted. Please read: Posting Code in the Forums to learn how to do it too. 
  2.  
  3.  
  4.  
  5.  
  6.  
  7. Ok, I've been doing some reading up on colours and I pretty much fully understand how RGB/HSV/Hexadecimal colours work now, and how to convert between them. I don't understand the formulas for the HSV to RGB (and visa-vera), but I can convert the formula to be used with PHP so its all good - so I fully understand how your script works now. 
  8.  
  9.  
  10.  
  11. One thing I didn't 100% get though, is a part of your rgbtohsv() function: 
Syntax: [ Download ] [ Hide ]
if( $r == $max ) {

    $h = 0 + ( $g - $b ) / $delta;

} else if( $g == $max ) {

    $h = 2 + ( $b - $r ) / $delta;

} else {

    $h = 4 + ( $r - $g ) / $delta;

}

Whats the reasoning behind the addition of 0, 2 or 4? In the formula I have, additions of 0, 120 and 240... I used the formula at Wikipedia.

I think I'm going to play with your script a little more to get it to work with blacks and whites, now that I understand how the HSV model works and try and turn it more into a colour replacement than a hue replacement. With the hue colour wheel working how it does, I think its best to stick to RGB to HSV to RGB for use with colour replacement too as its easier to find similar colours that way.

The speed it a bit of a concern though, for the task I'd like to use this for anyway. I have tried converting the image to an 8-bit gif and altering the palette instead but results were poor, even though the images I'm using are coloured in line drawings. ImageMagicks -draw functionality doesnt support anti-aliasing either so that didn't produce great results. In theory, your method would produce the best results out of what I have tried, but its just the speed. I might work on a script with a mixture of yours and some ImageMagick stuff - Get the range of colours with the HEX to RGB to HSV to RGB to HEX and then use the returned colours with ImageMagicks -opaque function possibly, not sure how it would effect speed though...

Anyways, enough of my rambling. Thanks onion2k for the updated script.


feyd | Please use
Syntax: [ Download ] [ Hide ]
,
[syntax=php]and
Syntax: [ Download ] [ Hide ]
  1. tags where appropriate when posting code. Your post has been edited to reflect how we'd like it posted. Please read: Posting Code in the Forums to learn how to do it too. 
  2.  
  3. SA: I did use the 
Syntax: [ Download ] [ Hide ]
tags...</span>
Semi_Apocalyptic
Forum Newbie
 
Posts: 2
Joined: Wed Apr 12, 2006 9:46 am

Postby onion2k » Thu Apr 13, 2006 10:59 am

Semi_Apocalyptic wrote:Whats the reasoning behind the addition of 0, 2 or 4? In the formula I have, additions of 0, 120 and 240... I used the formula at Wikipedia.

If you examine the line immediately following.. $h *= 60; ..you'll see that it does approximately the same thing. I didn't write that code, I nicked it from PEAR .. it might be wrong. Works well enough for my purposes though.
User avatar
onion2k
Jedi Mod
 
Posts: 5263
Joined: Tue Dec 21, 2004 6:03 pm
Location: usrlab.com

Re: Image Color Replacement Technique

Postby anandafit » Tue Feb 23, 2010 5:35 am

I wrote a coding for replacing color of PNG image according to the given color. Now it is work fine. But problem is it will getting annoying when I use transparent background PNG image. it means that when I apply a color that color will apply for my whole image. not for selected colored object. But it worked fine when I used normal PNG image.

My code:

<?php
$im = imagecreatefrompng("lifestyle_noTrance.png");
$size = getimagesize("lifestyle_noTrance.png");
$L=$size[0];
$H=$size[1];

for($j=0;$j<$H;$j++){
for($i=0;$i<$L;$i++){

$rgb = imagecolorat($im, $i, $j);
$r = ($rgb >> 16) & 0xFF;
$g = ($rgb >> 8) & 0xFF;
$b = $rgb & 0xFF;

//Turn off transparency blending



//Create a new transparent color for image

if($r=='0' && $g=='0' && $b=='0'){

$color = imagecolorallocatealpha($im, 255, 0, 0, 127);
}

else{
$color = imagecolorallocatealpha($im, $r, $g, $b, 127);
}


imagesetpixel($im, $i, $j, $color);

//Restore transparency blending
imagesavealpha($im, true);

}
}
header('content-type: image/png');
imagepng($im);
?>

Please help me, What may be the problem of my codding ? :cry: :cry:
anandafit
Forum Newbie
 
Posts: 2
Joined: Tue Feb 23, 2010 12:34 am

Previous

Return to PHPGD.com

Who is online

Users browsing this forum: Bing [Bot] and 1 guest