Cleaning the left side of an image - imagemagick

Using imagemagick, I want to clean the left side of an image, i.e. make white without cropping. For example cleaning the left-most vertical strip of 25 pixels wide. I figured out how to crop to a given geometry, but I couldn't figure out how to clean without cropping.

Here is my start image, made like this:
convert -size 256x256 gradient:cyan-yellow image.png
Method 1
One way to do it would be to use -fx and set all pixels where the x-coordinate is less than 25 to 1.0 (i.e. white) and leave all other pixels as they are:
convert image.png -fx "i<25?1:u" result.png
Method 2
Another, faster way to do it might be to clone the original image, and scale it down to 25 pixels wide, fill it with white and composite that over the original image:
convert image.png \
\( +clone -scale 25x! -fill white -colorize 100 \) \
-composite result.png
The result is the same.
Method 3
A third way to do it might be to crop the image 25 pixels in from the left side, then splice 25 white pixels back on the left side:
convert image.png -crop +25+0 -background white -gravity west -splice 25x result.png
Method 4
Bit of a kludge, but nearer to what you asked. Here, I guess that your image height doesn't exceed 10,000 pixels and draw a rectangle:
convert image.png -fill white -draw "rectangle 0,0 24,9999" result.png
I guess the proper way to do this is to get the height first then use it:
#!/bin/bash
h=$(convert image.png -format "%[fx:h-1]" info:)
convert image.png -fill white -draw "rectangle 0,0 24,$h" result.png

Related

ImageMagick count how many identical or almost identical color pixels are on the edges left and right of image

This is an example PNG image:
it's 50x40 but enlarged here to see it better.
The hex of bottom left and bottom right pixels is F9E4B7
I need to know how many pixels there are on vertical edges from the bottom left and right with almost this color, like 1% fuzz because they are not all exactly F9E4B7 but some are very slightly different.
In this case it would be 20px of each side:
I'll mark the areas which need to be counted just to make it perfectly clear:
I also need to be able to count how many pixels are exactly F9E4B7, which in this case would be 15 left and 20 right, I'll mark the slightly different areas so it's clear where the counter needs to stop:
The way to do that in Imagemagick is to use fuzz to change all your pixels close to that color to white and the rest black. The crop the first or last column and use -fx to get the count from mean*width*height. So for example for the left full column of the whole image, one has
Unix Imagemagick 6 syntax:
convert tan.png -alpha off \
-fuzz 1% -fill white -opaque "#F9E4B7" -fill black +opaque white \
-gravity west -crop 1x+0+0 -format "%[fx:round(mean*w*h)]\n" info:
Windows Imagemagick Syntax:
convert tan.png -alpha off ^
-fuzz 1% -fill white -opaque "#F9E4B7" -fill black +opaque white ^
-gravity west -crop 1x+0+0 -format "%[fx:round(mean*w*h)]\n" info:
Result:
108
To get the right side, use -gravity east.
For exact count, use -fuzz 0
For Imagemagick 7, change convert to magick

ImageMagick gradient ratio

How do I adjust the color ratio of a gradient?
I currently use the following to create my gradient.
convert -size 200x600 gradient:none-black output.png
Although at least one acceptable solution has been provided, here are a couple other ideas...
Example 1: This command creates a red-blue gradient of the finished dimensions, crops it into a top and bottom half, resizes them to 40 and 60 percent of the input height, and appends them back to make a single image. What started as the color at the exact vertical center is now at 40% down from the top with clean gradients going up and down from there.
convert -size 200x600 gradient:red-blue -crop 1x2# \
\( -clone 0 -resize 100x40% \) \( -clone 1 -resize 100x60% \) \
-delete 0,1 -append result.png
That splits the gradient image into a top and bottom half, then inside parentheses it resizes each to the required proportion. After that it deletes the 50/50 crops from before the parentheses, appends the two resized remaining images, and writes the output.
Example 2: This next example starts by creating the red-blue gradient in the final dimensions, then sets variables to hold the top color, the exact middle color, and the bottom color.
Then inside the first parentheses it clones and crops the image to 60% its original height. It uses "-sparse-color" to fill that with a gradient from "color1" to "color2".
Inside the second parentheses it clones and crops the image to 40% its original height, and using "-sparse-color" again it fills it with a gradient from "color2" to "color3".
After creating those two gradients, delete the original, append the other two together, and write the output.
convert -size 200x600 gradient:red-blue \
-set option:color1 "%[pixel:p{0,0}]" \
-set option:color2 "%[pixel:p{0,h/2}]" \
-set option:color3 "%[pixel:p{0,h}]" \
\( -clone 0 -extent 100x60% \
-sparse-color barycentric "0,0 %[color1] 0,%[h] %[color2]" \) \
\( -clone 0 -extent 100x40% \
-sparse-color barycentric "0,0 %[color2] 0,%[h] %[color3]" \) \
-delete 0 -append result.png
Maybe you want this, where you get to the half-red/half-blue colour just 20% of the way down the height of the image. It is done by creating two gradients of different lengths and putting them back-to-back:
midcolour="rgb(127,0,127)"
convert -size 100x20 gradient:red-"$midcolour" \
-size 100x80 gradient:"$midcolour"-blue \
-append result.png
Another way is to put 3 single pixels together in a row and then resize that up to what you want. I know you want the middle to be 40% red and 60% blue, but, for ease of viewing, I'll make it lime green:
convert -size 1x1 xc:red xc:lime xc:blue -append -resize 100x100\! result.png
You would change lime to something like "rgb(100,0,155)".
I am not quite sure I understand. But if you want to start with 90% transparent (10% opaque black) and end with black. You can do:
convert -size 200x600 gradient:"graya(0,0.1)-black" output.png
graya means gray with alpha. So graya(0,0.1) is gray(0) or black with 0.1 fraction opacity, so 90% transparent.
Perhaps this is what you want:
Normal 50-50:
convert -size 200x600 gradient:red-blue red_blue1.png
60-40:
rr=`convert xc: -format "%[fx:0.6*255]" info:`
bb=`convert xc: -format "%[fx:0.4*255]" info:`
convert -size 200x600 gradient:"rgb($rr,0,$bb)-rgb(0,0,255)" red_blue2.png
Or perhaps this is what you want:
bb=`convert xc: -format "%[fx:0.1*255]" info:`
convert -size 200x600 gradient:"rgb(255,0,$bb)-rgb(0,0,255)" red_blue3.png
I have an Imagemagick bash shell script called, multigradient, which may do what you want. It allows you to create gradients of many colors each with stops to set where they start. For example:
multigradient -w 200 -h 600 -s "blue 0 red 80" -d to-top result.png
The first color must start at 0, but the direction can be many options. Here I go from bottom to top with pure blue at the bottom and pure red starting at 80 up from the bottom going to the top
(See)

How to create an image border?

I want to create something like a border around an image with ImageMagick. I want the border to be related to the original size of the image.
Ex:
A 5% border on a 1000x100px image should give me an image of 1050x105px
A 10% border on a 500x400px image should give me an image of 550x440px
So for a 5% white border I got this code after lots of trial and error. But it seems way over complicated:
convert infile.png \
null: \
\( -clone 0 -resize 105% -fill \#fff -colorize 100% \) \
-swap 0,2 -geometry +0+0 -gravity center -layers composite \
outfile.png
How could I simplify this? What am I missing?
NOTE: I do not want to specify static width of the border since I have multiple input images of multiple sizes.
With ImageMagick you can specify the size of a border as a percent of the width and height. Run a command like this on a 500x400 image to see how it works...
convert input.png -border 5x10% result.png
That should produce an output image with the dimensions 550x480. Keep in mind the percentage you specify is added to each edge, so a 5% border will make a 500 pixel wide image 550 pixels wide.
To add a total of 10% to both the width and height you would use a command like this...
convert input.png -border 5% result.png
You could use -extent like this:
convert -size 1000x100 xc:blue -gravity center -background red -extent 105%x105% result.png
Check
identify result.png
result.png PNG 1050x105 1050x105+0+0 8-bit sRGB 2c 350B 0.000u 0:00.000
Use any of your own images in place of -size 1000x100 xc:blue

Image Magick: dimmed caption with border

I am using Image Magick to overlay a dimmed caption to an image, with IM automatically choosing the best fontsize:
convert -background '#0008' -fill white -geometry +0+330 -size 370x60 caption:$title $image +swap -composite $imageOutput
My problem is that there is not enough space around the text, I would like to add some "padding". I usually do that with the -border option but if I add this to my command above, the caption is not dimmed anymore.
Do you have a solution to create a dimmed caption with enough room around the text?
I have a solution, but it's a bit of a kludge because I had trouble extending or bordering a semi-transparent background. In the end, I just constructed the caption on a black background and bordered it in black, then I tweaked the alpha channel afterwards:
convert -background black -bordercolor black -fill white \
-size 370x60 caption:"This is the title" \
-trim -border 20 -channel A -fx '(lightness/2)+.5' \
-geometry +0+200 background.gif +swap -composite result.png
The only tricky part is -channel A -fx .... The first part means that we are only affecting/modifying the alpha/opacity channel. The 0.5 means that all pixels become at least 50% opaque, and (lightness/2) means that absolutely white pixels, i.e. your lettering, (which will have a lightness of 1) become fully opaque because 0.5+(1/2) totals to one. The point of this is to preserve the anti-aliasing around the edges of the letters to some degree.

how do i place a 4 * 6 image on a letter page at the top

I am using imagemagick to convert files and reposition them, i have a 4 * 6 png which i need to position on a letter canvas on the top half of the page.
I have the below command which i am using, but its confusing. can anyone suggest how i can achieve what i want.
this is what i have tried, can any one guide me on this.
convert -rotate -270 -page Letter me-9370120111400937899958.png on-9370120111400937899958.pdf
I have also tried this, but the overlayed image is not moving and is stuck to the bottom
%x{convert -page Letter -rotate -270 "/var/folders/rp/rk2q4l7j4ds_w37vwvgx46tr0000gn/T/a8.png" -geometry +50+50 "/var/folders/rp/rk2q4l7j4ds_w37vwvgx46tr0000gn/T/a8.pdf"}
I have tried reading on this link http://www.imagemagick.org/script/command-line-processing.php#geometry but could not figure out.
Updated Answer
It occurred to me later that you may have meant this:
convert -page letter -gravity north \( a.jpg -background yellow -splice 0x10 \) a.pdf
Obviously change yellow to none and increase the 0x10 to 0x20 to move further down the page, and add -rotate 90 before the splice maybe.
Original Answer
Not sure exactly what you mean, but I think this will get you started. Let's try some options. I will make the canvas yellow so you can see it and the file you want to position on top will be red.
So let's try some options...
First, let's move the image across to the right by zero pixels and down from the top-left by 40 pixels - the default position (or gravity) is NorthWest so we are positioning relative to that.
convert -size 612x792 xc:yellow a.jpg -geometry +0+40 -composite result.jpg
If you want the image centred, use -gravity north and position relative to that - a little closer to the edge this time maybe:
convert -size 612x792 xc:yellow -gravity north a.jpg -geometry +0+10 -composite result.jpg
If you want the background rotated:
convert -size 792x612 xc:yellow -gravity north a.jpg -geometry +0+40 -composite result.jpg
If you want just the overlay rotated, do that in "aside processing":
convert -size 612x792 xc:yellow -gravity north \( a.jpg -rotate 90 \) -geometry +0+40 -composite result.jpg
If you want the canvas white, change yellow to white. If you want the canvas transparent, change yellow to none.

Resources