I also tried to do this, and the best I came up with was to use an overlap filter. Here is my code in php:
$overlay_color = array('r'=>180,'g'=>22,'b'=>1); function overlay ($top, $bottom) { return $bottom < 128 ? ( 2 * $bottom * $top ) / 255 : 255 - ( 2 * ( 255 - $bottom ) * ( 255 - $top ) / 255 ); } $original = new Imagick('img/girl.jpg'); $img = new Imagick(); //unmodified version $img->addImage($original); $it = $original->getPixelIterator(); foreach( $it as $row => $pixels ) { foreach ( $pixels as $column => $pixel ) { $rgba = $pixel->getColor(); $pixel->setColor('rgb('.overlay($overlay_color['r'], $rgba['r']).','.overlay($overlay_color['g'], $rgba['g']).','.overlay($overlay_color['b'], $rgba['b']).')'); } $it->syncIterator(); } //add modified version $img->addImage($original); $img->resetIterator(); $combined = $img->appendImages(true); //stack images header('content-type: image/jpeg'); $combined->setImageFormat("jpeg"); echo $combined;
I can not find the formula for the "color" mode of Photoshop. If I could find it would be pretty straight forward.
Update: I found this site that very well explains the Photoshop formula: http://www.beneaththewaves.net/Photography/Secrets_of_Photoshops_Colour_Blend_Mode_Revealed_Sort_Of.html , and I managed to get it working in PHP. Here are the functions:
function Lum($colour) { return ($colour['r'] * 0.3) + ($colour['g'] * 0.59) + ($colour['b'] * 0.11); } function ClipColour($colour) { $result = $colour; $luminance = Lum($colour); $cMin = min($colour['r'], $colour['g'], $colour['b']); $cMax = max($colour['r'], $colour['g'], $colour['b']); if ($cMin < 0.0) { $result['r'] = $luminance + ((($colour['r'] - $luminance) * $luminance) / ($luminance - $cMin)); $result['g'] = $luminance + ((($colour['g'] - $luminance) * $luminance) / ($luminance - $cMin)); $result['b'] = $luminance + ((($colour['b'] - $luminance) * $luminance) / ($luminance - $cMin)); } if ($cMax > 255) { $result['r'] = $luminance + ((($colour['r'] - $luminance) * (255 - $luminance)) / ($cMax - $luminance)); $result['g'] = $luminance + ((($colour['g'] - $luminance) * (255 - $luminance)) / ($cMax - $luminance)); $result['b'] = $luminance + ((($colour['b'] - $luminance) * (255 - $luminance)) / ($cMax - $luminance)); } return $result; } function SetLum($colour, $luminance) { $result = array(); $diff = $luminance - Lum($colour); $result['r'] = $colour['r'] + $diff; $result['g'] = $colour['g'] + $diff; $result['b'] = $colour['b'] + $diff; return ClipColour($result); }
and here is the updated pixel conversion code:
$rgb = $pixel->getColor(); $rgb = SetLum($overlay_color,Lum($rgb)); $pixel->setColor('rgb('.round($rgb['r']).','. round($rgb['g']).','.round($rgb['b']).')');
Castles
source share