Is there a way to darken an image except for a rounded rectangle in ImageMagick? - imagemagick

To demonstrate.
Original:
After ImageMagick:
I have some ideas:
Duplicate the image, crop the duplicate, then flatten the images together
Reverse mask?
Does anyone have any suggestions?

Although this has been successfully answered, I'll offer another simple approach using IMv6...
convert pasta.jpg -fill white \
\( +clone -evaluate set 25% -draw "roundrectangle 20,20 80,80 15,15" \) \
-compose multiply -composite result.png
After reading in the input image, in parentheses it clones the input and uses -evaluate to set the entire clone to 25% gray. A white "roundrectangle" is drawn on that gray image in the area you want to preserve. The mask looks like this...
Then after the parentheses, that mask and the input image are composited with -compose multiply. That leaves the white rectangle area as it was in the original input, and the rest of the image is multiplied by 0.25, leaving it darkened. The result...
This command should work just the same in IMv7 by changing "convert" to "magick". And it should work as well on Windows CLI by changing the continued-line backslashes "\" to carets "^", and removing any backslashes before the parentheses, so this "\(...\)" to this "(...)".

You can do that in Imagemagick by darkening the whole image, creating a round rectangle mask image, then composite the original with the darkened using the mask image.
Input:
convert pasta.jpg \
\( -clone 0 -brightness-contrast -75,0 \) \
\( -clone 0 -fill white -colorize 100 -fill black -draw "roundrectangle 20,20 80,80 15,15" -alpha off \) \
-compose over -composite \
pasta_rect.jpg
Result:

Related

ImageMagick - change the background color of the selected bounding box

I already have the normalized vertices of my selected bounding box (e.g xmin: 0.68, ymin: 0.47, xmax: 0.94, ymax: 0.82) and I want to save this box in an other .jpg file. Furthermore, in the original image I want to make this highlighted box all white. Is this possible using Imagemagick?
Starting with this:
and knowing the top-left corner of the monument is at 400,10 and the bottom-right is at 500,200, you can extract the monument to a file with:
magick photo.jpg -crop 100x190+400+10 extract.jpg
and overpaint in white with:
magick photo.jpg -fill white -draw "rectangle 400,10 500,200" overpainted.jpg
Or, for extra fun, overpaint in semi-transparent white with:
magick photo.jpg -fill "rgba(255,255,255,0.5)" -draw "rectangle 400,10 500,200" overpainted.jpg
You can do both operations in one go with:
magick photo.jpg \( +clone -fill white -draw "rectangle 400,10 500,200" -write overpainted.jpg +delete \) -crop 100x190+400+10 extract.jpg
Using ImageMagick version 6, the command below will create two output images. (An example command for ImageMagick version 7 is further down in the reply.)
The first output image will be cropped from the input image using the bounding box starting at w*0.68xh*0.47 and ending at w*0.94xh*0.82.
The second output will be the input with a white section corresponding to the sub-image cropped out to make the first image.
convert input.png \
-set option:distort:viewport "%[fx:(w*0.94)-(w*0.68)]x%[fx:(h*0.82)-(h*0.47)]" \
\( +clone -distort affine "0,0 -%[fx:w*0.68],-%[fx:h*0.47]" \
-write result1.png -fill white -colorize 100 \) \
-set page "%[fx:u.w]x%[fx:u.h]+%[fx:t*(u.w*0.68)]+%[fx:t*(u.h*0.47)]" \
-flatten result2.png
That starts by reading the input image and calculating the viewport, the dimensions of the sub-image to crop, according to the bounding box dimensions you've provided.
Then inside the parentheses it creates a clone and does a "-distort affine" which, in effect, crops the image and locates it properly in that viewport. It writes that result to the first output image "result1.png". Then, still inside the parentheses, it fills that cropped piece with white.
After that it sets the paging geometry so that white piece can eventually be composited back into its original location over the input image.
It finishes by flattening the white piece onto the input image, and writes the second output image "result2.png".
The same thing can be done using ImageMagick version 7 with a slightly less complicated command...
magick input.png \
\( +clone \
-crop "%[fx:(w*0.94)-(w*0.68)]x%[fx:(h*0.82)-(h*0.47)]+%[fx:w*0.68]+%[fx:h*0.47]" \
-write result1.png -fill white -colorize 100 \) \
-flatten result2.png
That does the calculations directly in the "-crop" operation, and the paging geometry is saved in the cropped piece so it can be flattened back to its original position without resetting the geometry.
Those are in *nix syntax. To make it work in Windows change the continued line backslashes "\" to carets "^", and eliminate those backslashes that escape the parentheses "\(...\)".
Here is one other variation in ImageMagick 6. It crops the image and saves it and then deletes it. Then it use -region to write white into that bounding box.
This is Unix syntax. For Windows, remove \ from parenthesis and change end of line \ to ^.
Input:
convert img.jpg \
\( +clone -crop 100x190+400+10 +repage +write result1.jpg +delete \) \
-region 100x190+400+10 -fill white -colorize 100 +region result2.jpg

Replace/repaint all pixels with one color in image with interpolated from neighboring pixels

I have a GIF image generated by a program where each output value is represented by its color via attached color palette. I need to replace one value, i.e. color from image with interpolated from neighboring pixels. Since I don't have possibility to alter programs output, I need to modify the output image. The resulting image will be saved in the PNG or GIF format.
I can easily extract (mask) all pixels that need repainting, since they have fixed color, but I was unable to find solution on how to replace a color of one/all pixels in imagemagick with interpolated color from neighboring pixels.
Is there a way to do this in imagemagick?
The raw values of the pixels are proportional to the physical value, so it would be great if the interpolation could be done on raw values that are then later transformed to the color via supplied color palette.
Attached image shows the original (left) and processed manually in GIMP (right).
One technique is to replace the offending color with the background, and then use a combination of erode & dilate morphology to remove the paths.
Given...
convert input.png \
-fill white -fuzz 10% -opaque black \
-morphology Erode Diamond \
-morphology Dilate Diamond \
output.png
It's not a true interpolate from nearest neighbors, but close. Also note the rounding errors across edges.
Updated
Or as Fred pointed out in the comments, just use -morphology Smooth Diamond instead of Erode + Dilate
convert input.png \
-fill white -fuzz 10% -opaque black \
-morphology Smooth Diamond \
output.png
Adding a bit to xenoid's suggestion, you want to create a mask image and use that to composite the median filter with the original, so that only the region about the line is changed. Using emcconville's image and ImageMagick:
convert img.png \
\( -clone 0 -statistic median 3x3 \) \
\( -clone 0 -fuzz 10% -fill white +opaque black -fill black +opaque white -negate \) \
-compose over -composite \
result.png
An alternate, but slightly longer approach, is to put the mask into the alpha channel of the filtered image and then composite it over the original, which produces exactly the same result:
convert img.png \
\( -clone 0 -statistic median 3x3 \) \
\( -clone 0 -fuzz 10% -fill white +opaque black -fill black +opaque white -negate \) \
\( -clone 1 -clone 2 -alpha off -compose copy_opacity -composite \) \
-delete 1,2 \
-compose over -composite \
result.png
Unfortunately, there is a slight dark residual to the upper left between the red and green. I tried increasing both the fuzz value and the filter size, but that did not seem to help. I am not sure why.

Imagemagick arbitrary size/ratio gradient

Is it possible to apply a smooth diagonal gradient overlay from left bottom corner to right upper corner preserving original colors as below?
Might sound as a simple task but the actual image size is not known in prior.
Perhaps this is what you want. Using Imagemagick 6, I create a diagonal gradient with blue in the lower left corner and red in upper right corner and then blend 20%/80% with the original with the gradient.
Imagemagick automatically gets the dimensions of the (cloned/copied) image from %w and %h using the -sparse-color barycentric syntax for creating a gradient. See https://imagemagick.org/Usage/canvas/#diagonal_gradients
input:
convert input.jpg \
\( +clone -sparse-color barycentric '0,%h blue %w,0 red' +write gradient.jpg \) \
-define compose:args=20,80 -compose blend -composite \
result.jpg
In the above, I saved the gradient image just to show it has been created properly:
Alternately, you can set the alpha channel of the gradient to 20% and use compose over.
convert input.jpg \
\( +clone -sparse-color barycentric '0,%h blue %w,0 red' -alpha set -channel alpha -evaluate set 20% +channel \) \
-compose over -composite \
result2.jpg

"Diff" an image using ImageMagick with emphasis

Follow up on “Diff” an image using ImageMagick
When you are working with forms (as opposed to images), the changes are very hard to see with this technique. I wanted to show some type of yellow highlight maybe 10-20 pixels "bigger" (padding) around the actual pixels that changed.
So instead of just this
Something more like this
It seems like I am just missing something here in the stack that can make this work.
convert '(' file1.png -flatten -grayscale Rec709Luminance ')' \
'(' file2.png -flatten -grayscale Rec709Luminance ')' \
... here ? ...
'(' -clone 0-1 -compose darken -composite ')' \
... or here ? ...
-channel RGB -combine diff.png
I can also run this as separate commands and does not need to be fast, most of this is going to be run offline.
I also tried studying the technique here (specifically how the thumbnail scaling gives you the effect I want as the pixels get expanded) but this code is using the library instead of the ImageMagick command line tools. Line 248 => "make the red as visible as possible"
https://github.com/vslavik/diff-pdf/blob/master/diff-pdf.cpp#L218
An example form is the standard W-9. I made 2 subtle changes
PART II .. moved the 2. left about 2 pixels
PART II .. on 4., moved word is to the right 2 pixels
and the compare pumps out this (changes in red that you can barely see)
Thank you for any help
You can use -morphology dilate in Imagemagick to increase the size of the red areas. For example, using your two forms:
convert JW0wZ.png 1nHWT.png -compose difference -composite -morphology dilate disk:10 +level-colors black,red result.gif
UPDATE:
If you want the background transparent, then try
convert JW0wZ.png 1nHWT.png -compose difference -composite -morphology dilate disk:10 +level-colors "black,red" -fuzz 20% -transparent black result.png
Or better
convert JW0wZ.png 1nHWT.png -compose difference -composite -morphology dilate disk:10 -alpha copy -background red -alpha shape result2.png
Update 2: Here is how to overlay a 50% yellow marking onto you two originals. Change the value as desired. I create a difference image and dilate the white. Then I create a 50% yellow image. Then I composite each of the originals with the yellow using the difference image as a mask. See https://www.imagemagick.org/Usage/compose/#compose
convert JW0wZ.png 1nHWT.png \
\( -clone 0,1 -compose difference -composite -morphology dilate disk:10 \) \
\( -clone 0 -fill yellow -colorize 100 -channel a -evaluate set 50% +channel \) \
\( -clone 0,3,2 -compose over -composite +write 1.png \) \
\( -clone 1,3,2 -compose over -composite +write 2.png \) \
null:
To view this, if on Unix and have X11 installed, you can do
animate -delay 20 -resize 50% 1.png 2.png

Rounding corners of pictures with ImageMagick

in my Rails app I want to have a similar profile section like Facebook where uploaded images are automatically thumbnailed and corner-rounded. I'm using the convert utility to downsize images into thumbnails, but is there an option to round their corners too? Thanks.
Universal solution
This solution works with transparent and non-transparent pictures. To add 15 pixels radius rounded corners to original_picture.png which is a 100x100 picture:
convert -size 100x100 xc:none -draw "roundrectangle 0,0,100,100,15,15" mask.png
convert original_picture.png -matte mask.png \
-compose DstIn -composite picture_with_rounded_corners.png
This solution was given by PM here: https://stackoverflow.com/a/1916256/499917
Elegant solution, does not work with transparent pictures
This solution works without any intermediate picture. How nice! But it will disrupt your original picture's transparency. So use only when you are sure that your picture is not transparent.
Suppose you want rounded corners with 15px radius:
convert original_picture.png \
\( +clone -alpha extract \
-draw 'fill black polygon 0,0 0,15 15,0 fill white circle 15,15 15,0' \
\( +clone -flip \) -compose Multiply -composite \
\( +clone -flop \) -compose Multiply -composite \
\) -alpha off -compose CopyOpacity -composite picture_with_rounded_corners.png
For convenience, here is what you will typically do in Ruby or some other languages:
in_pic = "original_picture.png"
out_pic = "picture_with_rounded_corners.png"
radius = 15
cmd = "convert #{in_pic} \\( +clone -alpha extract " +
"-draw 'fill black polygon 0,0 0,#{radius} #{radius},0 fill white circle #{radius},#{radius} #{radius},0' " +
"\\( +clone -flip \\) -compose Multiply -composite " +
"\\( +clone -flop \\) -compose Multiply -composite " +
"\\) -alpha off -compose CopyOpacity -composite #{out_pic}"
`#{cmd}`
Source: http://www.imagemagick.org/Usage/thumbnails/#rounded
Facebook doesn't modify pictures to have rounded corners. Instead, they use HTML and CSS to apply this image over each user picture: http://www.facebook.com/images/ui/UIRoundedImage.png
If you inspect UIRoundedImage.png, you'll find that each "square" consists of a transparent center, and opaque corners that are meant to match the background on which the user picture will rest. For instance, if the user picture is on a white background, then white opaque rounded corners will be overlaid on the user picture.
The CSS technique for using just a specific part of UIRoundedImage.png is called "CSS sprites". You can read more about it here: http://www.alistapart.com/articles/sprites/
Here are some rounded corners examples: http://www.imagemagick.org/Usage/thumbnails/#rounded_border. You'll need to create a mask of some sort (either by hand or using the drawing tools) and then overlay it onto your image.
Here's the code I wrote to round corners with ImageMagick using Perl. It should port to Ruby fairly easily:
http://article.gmane.org/gmane.comp.video.graphicsmagick.apis/322

Resources