views:

1121

answers:

2

I hope someone can help,

I have made a script that masks images... however it is reliant on a colour to mask with ( 'green screen' style). The trouble is if the image that I am masking contains that colour it is ruined.

What I am looking to do is prior to masking the image replace any occurance of my keying colour (0,0,255) with a similar colour such as 0,0,254.

I have found a few solutions based around gif's or 256 colour PNG as they are indexed..

So my question is also will it be more efficient to convert it to a gif or 256 png then look through the index and replace the colour or search through every pixel and replace the colours.

Thanks,

+1  A: 

You need to open the input file and scan each pixel to check for your chromokey value.

Something like this:

// Open input and output image
$src = imagecreatefromJPEG('input.jpg') or die('Problem with source');
$out = ImageCreateTrueColor(imagesx($src),imagesy($src)) or die('Problem In Creating image');

// scan image pixels
for ($x = 0; $x < imagesx($src); $x++) {
    for ($y = 0; $y < imagesy($src); $y++) {
     $src_pix = imagecolorat($src,$x,$y);
     $src_pix_array = rgb_to_array($src_pix);

            // check for chromakey color
            if ($src_pix_array[0] == 0 && $src_pix_array[1] == 0 && $src_pix_array[2] == 255) {
                $src_pix_array[2] = 254;
            }


     imagesetpixel($out, $x, $y, imagecolorallocate($out, $src_pix_array[0], $src_pix_array[1], $src_pix_array[2]));
    }
}


// write $out to disc

imagejpeg($out, 'output.jpg',100) or die('Problem saving output image');
imagedestroy($out);

// split rgb to components
function rgb_to_array($rgb) {
    $a[0] = ($rgb >> 16) & 0xFF;
    $a[1] = ($rgb >> 8) & 0xFF;
    $a[2] = $rgb & 0xFF;

    return $a;
}
radio4fan
This looks fantastic... Efficiency wise how do you think it would compare to converting the image to a 256 pallet, using imagecolorexact and imagecolorset to replace any occurrence of the colour then converting it back to a true colour image?
Mark
It works perfectly, But I just tested it and it is at least 5 times less efficient as converting it to a 256 pallet image and back... but for image quality it is superior as quality is lost when converting it to 256 colours, Thank you radio4fan!
Mark
+1  A: 

Here is the replace colour solution that first converts to 256 pallet:

//Open Image
$Image = imagecreatefromJPEG('input.jpg') or die('Problem with source');

//set the image to 256 colours
imagetruecolortopalette($Image,0,256);

//Find the Chroma colour
$RemChroma = imagecolorexact( $Image,  0,0,255 );

//Replace Chroma Colour
imagecolorset($Image,$RemChroma,0,0,254);

//Use function to convert back to true colour
imagepalettetotruecolor($Image);




function imagepalettetotruecolor(&$img)
    {
        if (!imageistruecolor($img))
        {
            $w = imagesx($img);
            $h = imagesy($img);
            $img1 = imagecreatetruecolor($w,$h);
            imagecopy($img1,$img,0,0,0,0,$w,$h);
            $img = $img1;
        }
    }

I personally prefer radio4fans solution as it is lossless, but if speed is your goal this is superior.

Mark