A few days ago I got a help request from a user: “How do you change pixel color during the iteration with ImagickPixelIterator”. My initial response was that ImagickPixelIterator is read-only.
Well, I have to admit I was wrong. After searching trough ImageMagick docs I stumbled across an example and noticed that PixelIterator (and therefor ImagickPixelIterator) is not read-only after all. I have tried the code like in this example before; without the syncIterator call after each row. After adding the Imagick::syncIterator call everything worked as expected.
This example will work with Imagick 2.1.0 (the RC1 was released yesterday) but with a little tweaking it should work with 2.0.x too.
- <?php
- /* Create new object with the image */
- $im = new Imagick( "strawberry.png" );
- /* Get iterator */
- $it = $im->getPixelIterator();
- /* Loop trough pixel rows */
- foreach( $it as $row => $pixels )
- {
- /* For every second row */
- if ( $row % 2 )
- {
- /* Loop trough the pixels in the row (columns) */
- foreach ( $pixels as $column => $pixel )
- {
- /* Paint every second pixel black*/
- if ( $column % 2 )
- {
- $pixel->setColor( "black" );
- }
- }
- }
- /* Sync the iterator, this is important
- to do on each iteration */
- $it->syncIterator();
- }
- /* Display the image */
- header( "Content-Type: image/png" );
- echo $im;
- ?>
The source image:
The result image:
Trackback: PHPDeveloper.org
Pingback: developercast.com » Mikko Koppanen’s Blog: ImagickPixelIterator is not read-only after all…
#1 by kakapo on November 16, 2007 - 8:40 am
Quote
Mikko, how to set one color of a image to transparent? My program is below,but it not works.
/* Create new object with the image */
$im = new Imagick( “logo.gif” );
$blue = new ImagickPixel(‘#025AA4′);
$it = $im->getPixelIterator();
foreach( $it as $row => $pixels )
{
foreach ( $pixels as $column => $pixel )
{
$color = $pixel->getColorValue (imagick::COLOR_ALPHA );
if($pixel->isSimilar($blue,1)){
$pixel->setColor( “transparent” );
//$pixel->setColorValue(imagick::COLOR_ALPHA ,0);
}
}
$it->syncIterator();
}
/* Display the image */
header( “Content-Type: image/gif” );
echo $im;
#2 by Mikko Koppanen on November 16, 2007 - 9:19 am
Quote
Hello again kakapo,
Try calling $im->setImageMatte( true ); right after you clear the object!
#3 by kakapo on November 16, 2007 - 10:32 am
Quote
Oh! Thanks! i works! here is my code:
getImageWidth();
$logo_height = $logo->getImageHeight();
$im = new Imagick(“glitter_blue.gif”);
$new_im = new Imagick();
$new_im->setFormat(“gif”);
foreach ($im as $image){
repeatPic($new_im,$image,$logo_width,$logo_height);
$new_im->compositeImage($logo,Imagick::COMPOSITE_OVER,0,0);
}
header( “Content-Type: image/gif” );
echo $new_im->getImagesBlob();
die;
/**
* replace one color to another color or transparent
* @param imagick $im
* @param string $color
* @param string $replacecolor
* @return void
*/
function replaceOneColorOfImage(& $im,$color=’white’,$replacecolor=’black’){
$im ->setImageMatte( true );
$color_pix = new ImagickPixel($color);
$it = $im->getPixelIterator();
foreach( $it as $row => $pixels )
{
foreach ( $pixels as $column => $pixel )
{
$color = $pixel->getColorValue (imagick::COLOR_ALPHA );
if($pixel->isSimilar($color_pix,1.732)){
$pixel->setColor( $replacecolor );
//$pixel->setColorValue(imagick::COLOR_OPACITY ,0.3);
}
}
$it->syncIterator();
}
}
/**
* repeat a pic to a big size
* @param imagick $new_im
* @param imagick $image
* @param integer $width
* @param integer $height
* @return void
*/
function repeatPic(&$new_image,$image,$width,$height){
$new_image->newImage($width,$height,new ImagickPixel(“transparent”));
$org_width = $image->getImageWidth();
$org_height = $image->getImageHeight();
for ($i=0,$c=ceil($width%$org_width);$icompositeImage($image,Imagick::COMPOSITE_OVER,$org_width*$i,$org_height*$j);
}
}
}
?>
original pic:
http://www.kakapo.cn/imagick/glitter_blue.gif
http://www.kakapo.cn/imagick/logo.gif
example result pic:
http://www.kakapo.cn/imagick/animate.gif
#4 by kakapo on November 16, 2007 - 10:42 am
Quote
what’s wrong, my code are stripped? the whole below:
———————————–
$logo = new Imagick(“logo.gif”);
replaceOneColorOfImage($logo,”#025AA4″,’transparent’);
$logo_width = $logo->getImageWidth();
$logo_height = $logo->getImageHeight();
$im = new Imagick(“glitter_blue.gif”);
$new_im = new Imagick();
$new_im->setFormat(“gif”);
foreach ($im as $image){
repeatPic($new_im,$image,$logo_width,$logo_height);
$new_im->compositeImage($logo,Imagick::COMPOSITE_OVER,0,0);
}
header( “Content-Type: image/gif” );
echo $new_im->getImagesBlob();
die;
/**
* replace one color to another color or transparent
* @param imagick $im
* @param string $color
* @param string $replacecolor
* @return void
*/
function replaceOneColorOfImage(& $im,$color=’white’,$replacecolor=’black’){
$im ->setImageMatte( true );
$color_pix = new ImagickPixel($color);
$it = $im->getPixelIterator();
foreach( $it as $row => $pixels )
{
foreach ( $pixels as $column => $pixel )
{
$color = $pixel->getColorValue (imagick::COLOR_ALPHA );
if($pixel->isSimilar($color_pix,1.732)){
$pixel->setColor( $replacecolor );
//$pixel->setColorValue(imagick::COLOR_OPACITY ,0.3);
}
}
$it->syncIterator();
}
}
/**
* repeat a pic to a big size
* @param imagick $new_im
* @param imagick $image
* @param integer $width
* @param integer $height
* @return void
*/
function repeatPic(&$new_image,$image,$width,$height){
$new_image->newImage($width,$height,new ImagickPixel(“transparent”));
$org_width = $image->getImageWidth();
$org_height = $image->getImageHeight();
for ($i=0,$c=ceil($width%$org_width);$icompositeImage($image,Imagick::COMPOSITE_OVER,$org_width*$i,$org_height*$j);
}
}
}
#5 by Mikko Koppanen on November 16, 2007 - 10:45 am
Quote
kakapo,
You should put a link to the source code. If you paste it here it loses most of the formatting (tabs especially).
#6 by kakapo on November 16, 2007 - 10:48 am
Quote
God! It can’t be read! The codes of function are wrong after postting.
#7 by Mikko Koppanen on November 16, 2007 - 10:53 am
Quote
kakapo,
Can you send me the code via email to mkoppanen@php.net? I can write a small post about it here. Please include an url where you want me to link the credits.
#8 by kakapo on November 16, 2007 - 10:58 am
Quote
ok, I’m sorry!the example is here.http://www.kakapo.cn/blog/read.php?127
#9 by kakapo on November 19, 2007 - 11:32 am
Quote
Mikko, how to draw a image like this? http://www.kakapo.cn/imagick/mirror.png
#10 by open source cms on November 26, 2007 - 11:24 am
Quote
Looks great ;]
#11 by childporn on May 21, 2008 - 10:31 pm
Quote
http://childporn.all-nintendo-wii.info/index.html childporn
#12 by John.G. Sujith Kumar on July 16, 2009 - 3:25 pm
Quote
Hi Mikko,
thanks a lot for your wonderful code ,I did a code for Red eye filter based on your code,just change the syntax,it can be use for regional pixel iterations.
————————————————————————————-
function redI(){
/* Create new object with the image */
$im = new Imagick( “kingfisher.jpg” );
/* Get iterator */
$it = $im->getPixelRegionIterator(50,50,50,50);
/* Loop trough pixel rows */
foreach( $it as $row => $pixels ){
/* For every second row */
if ( $row % 2 ){
/* Loop trough the pixels in the row (columns) */
foreach ($pixels as $column => $pixel ){
/* Paint every second pixel black*/
if ($column % 2 ){
$pixel->setColor( “black” );
}
}
}
/* Sync the iterator, this is important to do on each iteration */
$it->syncIterator();
}
header( “Content-Type: image/png” );
echo $im;
}
#13 by Kaveh on November 23, 2009 - 5:59 pm
Quote
Hi;
I tried to test this codes to see that mu server work for Imagemagick but doesn’t work so i thought that maybe my address to .png is wrong ,thanks for your advice:
i put the codes in test.php
strawberry.png and test.php in same folder
and the first code as is:
$im = new Imagick( “strawberry.png” );
is this right?
thanks
Pingback: Imagick blog » Blog Archive » ImagickPixelIterator is not read-only after all..
#14 by Japan 2 Day Diet Lingzhi on May 6, 2010 - 6:09 am
Quote
Good post, but i try to run this code and it makes an error,,.,,.,,,
/**
* replace one color to another color or transparent
* @param imagick $im
* @param string $color
* @param string $replacecolor
* @return void
*/
whats the meaning of it?
#15 by Alejandro on July 29, 2010 - 5:30 pm
Quote
Hi. I’ve been reading and searching but I can’t find anything and either figure out how to create a text image with transparente background. Could someone please help me on this?…
Here’s my code.
newImage (500, 500, $pixel);
$image->setImageMatte (true);
// Black text
$pixel->setColor (‘white’);
// Font properties
$draw->setFont (‘Bookman-DemiItalic’);
$draw->setFontSize ( 30 );
$draw->setGravity (Imagick::GRAVITY_WEST);
$draw->setFillColor ($pixel);
$texto = ‘muerto, muerto…’.”\n”.’muertooooooooooooooo’;
// Create text
$image->annotateImage ($draw, 50, 0, 0, $texto);
// Give image a format
$image->setImageFormat (‘png24′);
$image->writeImage (‘composite.png’);
// Output the image with headers
header (‘Content-type: image/png’);
?>
#16 by radu on November 14, 2010 - 7:29 pm
Quote
Hi.
How can i check if a pixel is transparent ?
#17 by makaron on April 21, 2011 - 12:22 pm
Quote
Hi! I have faced a little trouble while trying to change some pixels opacity, not the whole color…
Here is my code:
foreach( $it as $row => $pixels )
{
$pixel_x = 0;
/* Loop trough the pixels in the row (columns) */
$fill = false;
$opacity = 1;
$opacityMinus = 0.05;
foreach ( $pixels as $column => $pixel )
{
$pColor = $pixel->getColor();
if(isset($maskMatrix[$pixel_x]) && isset($maskMatrix[$pixel_x][$pixel_y])){
$fill = true;
}
$color = $pixel->getColorValue (imagick::COLOR_ALPHA );
//print_pre($pixel->getColor());die;
if($fill){
$pixel->setColorValue(imagick::COLOR_OPACITY ,0.3);
}
$opacity -= $opacityMinus;
$pixel_x++;
}
$pixel_y++;
/* Sync the iterator, this is important to do on each iteration */
$it->syncIterator();
}
$this->showImg($image);
as a result i’m receiving the grey fill, instead of transparent
Could someone please help me? Maybe there is some method to enable opacity in image?
#18 by Mikko Koppanen on April 21, 2011 - 12:50 pm
Quote
makaron,
your issue is that you are not reducing opacity. You are actually saying “set opacity of this pixel to 0.3″, which means that already opaque pixels will turn gray. Take a look at this code for inspiration: http://valokuva.org/~mikko/opacity/
#19 by makaron on April 21, 2011 - 4:59 pm
Quote
Thanks!
And i have met another one problem -> on local server this line:
$gradient->newPseudoImage(400, 210, ‘gradient:white-transparent’);
works fine… but when i pushed it to production – it is totatally black
i am using this gradient to fill annotation…
thank you!
#20 by Peg Rhodes on April 26, 2011 - 6:24 pm
Quote
It seems like there should be an easier way to compass changing the color of pixels
#21 by Slide Share on August 5, 2011 - 12:11 pm
Quote
does the code really works??
i tried but its not working anybody else tried it
plz update