Imagemagick convert -fill does not change edges from a particular palette area - php

When I am trying to remove Green (#09f80c) color from this image using below command
magick convert images/img001.png - fill transparent -opaque #09f80c images/tp.png
I am getting below image:
This image I get as an output for above command. This image still has some green dots at the edges. How to remove them completely?
I want converted image not to have those extra pixels.
Your help would be highly appreciated.

In Imagemagick, you can use -fuzz as Andy suggested. But you can only increase the fuzz value so far before it starts changing other regions as well as the green.
Start by measuring the color as close as possible. I get #2FF81D
Here is about a large a fuzz value as possible for this image. But it still has some green on the outside. (Unix syntax)
convert green.jpg -fuzz 35% -transparent "#2FF81D" green_trans1.png
To further reduce the effect, you can antialias the border of the transparent area by blurring it a little and tapering (via -level).
convert green.jpg -fuzz 35% -transparent "#2FF81D" -channel a -blur 0x3 -level 50x100% +channel green_trans2.png

Maybe you should try -fuzz argument e.g -fuzz 40%.
I found this in the documentation here:
http://www.imagemagick.org/Usage/color_basics/#replace

Related

Set image color to match background color php

I am using Imagemagick to work with images in php. I am no-wise in ImageMagick so could not do it. I have 2 Pictures, 1 is background and other one is above it. The one which is on top is of gray color png. While the background image can be any image. I want to set my top image's color to match the most color of background image.
For Example, this is a random background image which has beige/pink as its main color
and this is my top image
I want my above top image to change its color to match the most color of background image, as in the above image, it should be something like
Is it possible?
I don't feel like writing and debugging a load of PHP today, but can show you some techniques on the command line that you should be able to translate into PHP.
You can get the mean of the background image by resizing it to a single 1x1 pixel and then printing its value in RGB terms:
convert background.jpg -scale 1x1 -format "%[pixel:p{0,0}]" info:
srgb(219,199,164)
If I take that value and make a solid square out of it, you can see it is a beige colour like you suggest:
convert -size 100x100 xc:"srgb(219,199,164)" mean.png
You can probably use getImageChannelStatistics()
in PHP for that.
If I now take that colour, and make it the fill colour for tinting and apply a tint, I get this:
convert top.png -fill "srgb(219,199,164)" -tint 100% result.png
In PHP, you'd be looking at tintImage().
Something horrible has happened down the right side - I don't understand that, but if I extract the opacity from your top image and re-apply it to the result image, it goes away:
convert top.png -alpha extract alpha.pgm
convert top.png -fill "srgb(219,199,164)" -tint 100% alpha.pgm -compose copyopacity -composite result.png
I have solved it myself through these 2 lines of codes
exec("convert fabric.jpg -scale 1x1\! -format '%[pixel:u]' info:-", $a);
exec('convert arm-shadow.png -fuzz 10% -fill "'.$a[0].'" +opaque black -fill "'.$a[0].'" -opaque black foo.png');

Can I Composite from right side with imagemagick?

In this normal case, when we need to composite a image on another image, we use :
exec("convert 1.jpg 2.jpg -geometry +0+0 -compose DstOver -composite result.jpg);
and 0,0 points are the start line in left site of picture.
I need to use my points from right side for example i have a jpg file with 500px height and 500px width and i need to composite image2 from 500,0 . its not good because if your image2 file has 100px in 100px height and width, your result hasn't any change in view.
my goal is compose from right side of image because my image2 has different width and height every time.
i mean i need compose from 3 and 4 point like picture.
I try Imagemagick place image in bottom right corner but this solution compose with SouthEast , SouthWest and ...
I need use my geometry size and points..
With image with fixed size i do not have any problem but i create text with imagemagick and it may with 1 charachter or more and in in this case my width of png text has different size.
Edit :
In fact i get text from input and with different length then compose with background picture like:
ok, i need compose with right corner of "Sample Text 2" like picture, not left like "Text1"
when i create text png file it may be created by different width and height .
(sorry i can't explain better and sorry for my bad english)
Edited
Ok, I am getting closer to understanding what you want, First observation is that if you specify -gravity then the offset in the geometry is relative to the gravity - it moves the overlaid image INWARDS from the gravity corner by the amount you specify in the geometry offset. So let's start by setting the gravity to NorthEast to put the overlay in the top-right corner:
convert background.jpg overlay.jpg -gravity northeast -composite out.jpg
Now let's get the width of the overlay and use it to calculate the geometry you require, assuming you want the overlaid image to have its right edge 50 pixels in from the background's right edge:
geom=$(convert overlay.jpg -print "+%[fx:w+50]+0" null:)
echo $geom # this is just to show what is happening - you don't need it
+150+0
convert background.jpg overlay.jpg -gravity northeast -geometry $geom -composite out.jpg
Of course you can do that in a single command like this:
convert background.jpg overlay.jpg -gravity northeast -geometry $(convert overlay.jpg -print "+%[fx:w+50]+0" null:) -composite out.jpg
Original Answer
I am sorry, but I still don't understand exactly what you are asking, so I will answer what I think you mean and maybe you can explain what is wrong with my understanding.
convert -size 500x500! xc:red background.jpg # make a big red background
convert -size 100x100! xc:blue overlay.jpg # make a smaller blue overlay
# place overlay on image at desired position
convert background.jpg overlay.jpg -geometry +360+40 -composite out.jpg

Trim image background but leave padding in Graphicsmagick

I assemble Graphicsmagick commands in php and then call them using exec(). I need to trim images but retain a padding of 20 pixels. So I want to do the following:
exec('gm convert input.jpg -trim -bordercolor white -border 20x20 output.jpg');
but use the color which was trimmed instead of white. How this can be achieved?
This works for me.
gm convert input.jpg -crop 1x1+0+0 corner.txt
color=`sed -e "s/.* #/#/" corner.txt`
gm convert input.jpg -trim -bordercolor $color -border 20x20 output.jpg
The txt format in GraphicsMagick has no header (unlike ImageMagick) so the (0,0) pixel is in the first line (actually the only line of a 1x1 image).
The corner.txt file for the 1x1 cropped image is simply this:
0,0: (255,255,255) #FFFFFF
It happened to be white in my test image, but it will be whatever the color of the (0,0) pixel.
It seems that this is currently not possible with GraphicsMagick (at the time of this writing: GM v1.4 beta).
In ImageMagick it can be done because IM provides an fx command to sample the color value of a given pixel:
convert myimage.png -format '%[fx:p{10,20}]' info:
This will return the color value of the pixel at position x=10, y=20. The output can then be used in subsequent IM commands to add a border of that color.

Get top left of pixel in image having alpha set 1 using imagick

I need to find the x coordinate of first pixel along with y coordinate having alpha set 1. I have a transparent image on which i have a black border rectangle. Now i need to find the rectangle's top and left.
For example, check image:
So i thought of, if somehow i can get first non transparent point in image i can get its coordinates and know about it.
Can it be done using Imagick in php. I read about pixelIterator, but how do i use it to do this? any suggestions or thoughts?
You could loopt trough all the pixels and use the Imagick::getImagePixelColor(x,y) function to read the color.
Three years later, and just for kicks, here are some thoughts on a way of approaching this with ImageMagick from the command line...
First, you can extract the transparency channel, using -alpha extract <filename>, but I don't really want the file so I can pipe it out to another convert command to threshold out anything where the alpha is not 1 (I assume a 16-bit quantisation, i.e. 65535=1) and then ask ImageMagick how it would trim that image to the smallest bounding box by using -format %# -write info:
convert rectangle.png -alpha extract png:- | convert - -threshold 65534 -format %# -write info: alpha.png
Output
91x118+80+81
That tells me the that the bounding box for the thresholded transparency is 91px wide by 118 pixels tall and it starts 80px across from the top left corner and most importantly that it starts 81 pixels down from the top - I now know the y coordinate is 81.
Whilst we don't actually need it to find the pixel you seek, it helps show what I am doing, so let me just draw that box so you can see it:
convert rectangle.png -stroke red -fill none -draw "rectangle 80,81 170,198" fyi.png
Now I can crop just the 81st line out of the image and look for the first white pixel with grep and exit as soon as I have found it.
convert alpha.png -crop x1+0+81 txt: | grep -m1 "#FFFFFF"
Output
147,0: (65535,65535,65535) #FFFFFF gray(255)
So, that tells me that the first white pixel is 147 across, so I know the x coordinate too. Therefore the pixel you seek is at 147,81.

Imagick. Changing a color to be transparent

I would like to change the black border of this image :
http://dev.loungeup.net/im/
to transparent with Imagick in PHP.
The result image should have the gray border visible, the image inside the gray border visible, and everything outside the gray border (today in black) should be transparent and let the underlying content (in HTML page for example) visible.
I have been through the documentation several times and tried several solutions but did not figure out how to achieve it.
Any help is appreciated.
Thanks
Here's one method you could use which is similar to Photoshop's magic wand tool:
convert original.jpg -alpha set -channel alpha -fuzz 18% \
-fill none -floodfill +0+0 black transparent-border.png
Here are the commands broken down:
convert original.jpg: start Imagemagick with the original image
-alpha set: activate the alpha channel
-channel alpha: have subsequent operators act on alpha channel
-fuzz 18%: see -floodfill...
-fill none: see -floodfill...
-floodfill +0+0 black: start from the upper left corner (+0+0) and find neighboring pixels within -fuzz color distance of black and replace it will -fill
transparent-border.png: the output image
Here's the result:
Unfortunately, as you can see, this method still leaves some dark pixels with the image you provided because the border is not pure black and blends a bit with the inner gray border, and the image itself is quite small.
You will get much better results if you have a better-quality source image, or a larger one which you could then reduce in size after modifying.
If you're stuck with these small images (or if you just want to use another method), I would recommend going a different route where you create your own mask shape that is just smaller than the shape of the original photo, then add back your own gray border. I put together an example of this process below.
A possible command for this method would be:
convert original.jpg mask.png -compose CopyOpacity -composite \
-compose src-over new-border.png -composite clean-result.png
... broken down ...
convert original.jpg mask.png: start Imagemagick with original image and bring in mask.png as the second layer (mask.png is a white rounded-rectangle shape of the photo on a black background, but the shape is slightly smaller than that of the original - the result will remove the original's gray and black border).
-compose CopyOpacity -composite: use mask.png to "knock out" shape from original.png
-compose src-over: reset composite method to a simple overlay
new-border.png -composite: overlay a gray border (png is a 3 px wide border, 1px on each side of mask edge on a transparent background)
clean-result.png: the output image
I created mask.png and new-border.png in Photoshop. You could use Imagemagick's vector tools and do this all in one command using just original.jpg, but it wouldn't be easy.
The result of the above:
On a final note, I'm not sure whether you're using PHP's Imagick or the Imagemagick from the command line. Several years ago I tried using Imagick but quickly became frustrated from the lack of documentation compared to the command line (perhaps that's changed, though). Instead, I execute the commands from PHP (e.g., from exec() or passthru()). Some or many others will probably tell you that you should never execute shell commands from PHP, but as long as you carefully escape any arguments I have yet to see a convincing argument against doing so. Then you'll have the entire Imagemagick documentation at your disposal (http://www.imagemagick.org/Usage/).
Cheers.

Categories