Snibgo was indeed pointing me in the right direction! It was not the function that was doing strange things, it was me (ofcourse) who did not supply the right input
I had tried that function, but it gave really weird results. Turned out you had to input a black/grey/white (alpha map) image, and not just the uploaded image itself..
After some tweaks, converting the image to black/white, and using that as input > I did get a good result. But with a background, and no longer transparent - so I wrote another piece of script that removed the background. And after that, the result is very nice! Thanks for all the help
For future reference, I'll post the entire function that does what I need in PHP:
Code: Select all
public function createEmbossedLogo($imagePath, $embossedFilePath) {
// initialize Imagick and load the image
$imagick = new \Imagick(realpath($imagePath));
// make sure we are using PNG, so we can use the alpha channel
$imagick->setImageFormat('png');
// resize the logo, so we do not have to process too many pixels
$imagick->resizeImage(200, null,\Imagick::FILTER_CATROM,1);
// if the image does not have any margin around the content,
// the shade would be cut off at the sides,
// so we add an invisible border of 5 pixels, to add some margin
$imagick->borderImage('rgba(255,0,0,0)',5, 5);
// now we have to convert the image to a black/white image, using only the alpha channel
// and use the alpha channel value as the R/G/B channel values
// load the pixels of the image
$imageIterator = $imagick->getPixelIterator();
foreach ($imageIterator as $row => $pixels) { /* Loop through pixel rows */
foreach ($pixels as $column => $pixel) { /* Loop through the pixels in the row (columns) */
/** @var $pixel \ImagickPixel */
$nor_color = $pixel->getColor(true); //normalized color
// the alpha channel will be 0 if it is completely invisible and 1 if visibile
// but can be any value in between 0-1
// by using the alpha channel as the white/grey/black value, we create an alpha map
$alpha = $nor_color['a'];
$rgbValue = $alpha*255;
$pixel->setColor('rgba('.$rgbValue.','.$rgbValue.','.$rgbValue.',1');
}
$imageIterator->syncIterator(); /* Sync the iterator, this is important to do on each iteration */
}
// add the shading, the first parameter makes sure that all the 'to be removed' pixels
// are the same color, so we can find them in the next loop through all pixels
// they would otherwise be black, one of the colors we do need to keep in the result
$imagick->shadeImage(true,270,45);
// the shadeImage function will make all the pixels grey that should be transparent
// so we loop over all the pixels in the image once again to remove them
$imageIterator = $imagick->getPixelIterator();
$colorFound = false;
$colorRange = 10;
foreach ($imageIterator as $row => $pixels) { /* Loop through pixel rows */
foreach ($pixels as $column => $pixel) { /* Loop through the pixels in the row (columns) */
/** @var $pixel \ImagickPixel */
$color = $pixel->getColor(); //normalized color
if (!$colorFound) {
// since added some margin around the image, we can take the first pixel
// of the top left corner, and use it as the color to make transparent
// and since the image is in black/white, we only need one 'color' channel
$colorFound = array();
$colorFound['r'] = $color['r'];
}
// the default alpha for pixels to keep is 1
$alpha = 1;
// see if the color of this pixel is close to that of the 'color to be deleted'
// if so, we will not totally delete it, but change the alpha channel accordingly
$diff = abs($color['r']-$colorFound['r']);
if ($diff<=$colorRange) {
// set alpha value for this pixel, based on the difference from the removed color
$alpha = $diff / $colorRange;
}
// the entire opacity of the image has to brought down, to make the image a bit 'softer'
$alpha *= 0.35;
// this pixel matches the 'to be removed' color, so we set it to a new value with alpha 0
$pixel->setColor('rgba('.$color['r'].','.$color['g'].','.$color['b'].','.$alpha.')');
}
$imageIterator->syncIterator(); /* Sync the iterator, this is important to do on each iteration */
}
// remove any excess margins that are not needed
$imagick->trimImage(0);
// store the image
$imagick->writeImage($embossedFilePath);
}