I am currently doing the following to overlay a large image onto another:
$ convert orig.png overlay.png -gravity center -composite new.png
overlay.png is large and really just a semi-transparent texture.
But in some cases I'd like to have a 1 pixel sized margin around the overlay. So:
+--------------+
| +--------+ |
| | Overlay| |
| +--------+ |
+--------------+
Is this possible?
Yes it is, for example you can add a border to overlay.png image and then compose the result with orig.png image.
To add a white 1px margin you can use these commands:
convert overlay.png -bordercolor White -border 1x1 overlay_border.png
convert orig.png overlay_border.png -gravity center -composite new.png
Related
There is a small sprite:
# mario sprite in base64 writing to file:
magick 'inline:data:image/png;base64,
iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAACXBIWXMAAA7EAAAO
xAGVKw4bAAAA00lEQVQ4ja1UwRGDMAyTe7zLJmWUzMoodBO6gHmkhsRWcukVvYID
kiKbiKoqbsTjTjIAmLq7IvXzwGHahJ5sUKBJKKhf3rcVAPB8pZ5BTihyEcxLomuD
Fxhqyryk06WtDZ93LSB+bMqYvBtPBsQYA2FP3YPl2XUIAIpcsCZ5eRM18slvALyL
CoFAu5EApCn7tsbx+hY0U55llmkYG7NefuhzKAVFUv1Mm8L+EgKWa5zDQbIWqiNn
riuvID8g1r4c2Hi6Ghvg6sg/mqEIDv+9v2+/sQ8vtmAvY/Wf0QAAAABJRU5ErkJg
gg==' mario.png
I want to scale it 8x:
convert -scale 800% -quality 100 mario.png mario-big.png
But scale with padding between pixels. To have an indent of 1 pixel between four adjacent eight times larger pixels. Or overlay a grid over the enlarged image.
How can I do this, please tell me?
Example:
As an alternative approach, how about using -fx to make a grid? For example:
convert -size 64x64 canvas: -fx "i % 9 == 0 | j % 9 == 0" x.png
Will set a pixel white when either the column (that's i) or row number (that's j) is on a multiple of 9. I see:
Now using Mark's suggestion, just expand your sprite by 9 with nearest neighbor, then use a ternary operator to pick either the image (image pixels are u) or white (1.0):
convert mario.png \
-scale 900% \
-fx "(i % 9 == 0 | j % 9 == 0) ? 1.0 : u" \
result.png
With this test image:
I see:
It'll work for any size image, though it'll be pretty slow if the image is large.
Updated Answer
I'm not sure how to change the 2px spacing to 1px in my original answer. Here's another method which we can probably speed up and improve if it gets the results you want. I'm using my image below as it's a an easier size to see, but you can adjust the numbers to match your own image. I am also using the "wrong" colours so you can see where each one ends up, but again, you can change my mad colours to white:
Chop into rows, each row being 50px tall
Iterate over rows, chopping each into 50px wide chunks and recombining with 1px yellow spacing
Smush the new rows together vertically with 1px cyan spacing
The code looks like this:
#!/bin/bash
# Chop into rows, each row being 50px tall
magick artistic-swirl.jpg -crop x50 row-%02d.png
# Iterate over rows, chopping each into 50px wide chunks and recombining with 1px spacing
for f in row-*png ; do
echo $f
magick "$f" -crop 50x -background yellow +smush 1 "$f"
done
# Smush the new rows together vertically with 1px spacing
magick row-*png -background cyan -smush 1 result.png
Note that +smush N joins images side-by-side with N px spacing in the background colour, but that -smush N joins images above-and-below with N px spacing.
Here's what I get applying that to your image:
#!/bin/bash
# Chop into rows, each row being 50px tall
magick mario.png -scale 800% -crop x8 row-%02d.png
# Iterate over rows, chopping each into 50px wide chunks and recombining with 1px spacing
for f in row-*png ; do
echo $f
magick "$f" -crop 8x -background yellow +smush 1 "$f"
done
# Smush the new rows together vertically with 1px spacing
magick row-*png -background cyan -smush 1 -bordercolor blue -border 1 result.png
Original Answer
Not at a computer to test, but if you scale your image up to the correct size as you are currently doing, you should then be able to crop the image into tens/hundreds of individual 8x8 images and pipe them to a montage command to lay them out on a white background with a 1px spacing between all the individual 8x8 blocks.
Something like:
magick 'inline:data:...' -scale 800% -crop 8x8 miff:- | magick montage -background white -geometry +1+1 -tile Nx miff:- result.png
where N is the number of 8x8 blocks you want in each row.
Note that miff:- is an ImageMagick internal lossless transmission format.
Back at a computer, I'll do something similar with this image:
magick artistic-swirl.jpg -scale 500x500 -crop 50x50 miff:- | magick montage -background yellow -geometry +5+5 -tile 10x miff:- result.png
I want to create a montage, using ImageMagick, where all the images are aligned to the bottom. The images have different heights, and -gravity South doesn't behave as I expect.
Image 1 is 100px high.
Image 2 is 200px high.
If I use :
montage *.png -tile 2x1 -background None -geometry +20+0 -gravity South out/montage.png
I get:
If I add a third image, of 50px high, and run
montage *.png -tile 3x1 -geometry +20+0 -gravity South montage2.jpg
I get:
I understand what's happening here - the canvas is expanding from the bottom. Is there any way to get it to grow from the top, so that the image looks like:
You can just use +smush (documentation) for that:
convert -background white -gravity south [abc].png +smush 10 result.png
If using Imagemagick v7, replace convert with magick.
I am trying to overlay image1 over image2. I want to make a color in image1 semi-transparent. So far I have only been able to overlay image1 over image2 using
composite -gravity north image2.png image1.png image3.png
How do I make a color (grey in this case) in image1 semi-transparent before overlaying it over image2?
I am using:
Version: ImageMagick 7.0.8-23 Q16 x86_64 2019-01-09
Thnx
Let's make an overlay (image2.png) first, with 3 progressively lighter shades of grey starting with 80/255 on the left, 128/255 in the middle and 200/255 on the right:
convert -size 200x438 xc:"gray(80,80,80)" xc:gray xc:"gray(200,200,200)" +append image2.png
Assuming our starting image is this:
We can now make precisely mid-grey into semi-transparent mid-grey and overlay like this:
convert bean.jpg \( image2.png -fill "rgba(128,128,128,0.5)" -opaque gray \) -composite result.png
Or, if we want to also affect the grey(80), we can incorporate some fuzz:
convert bean.jpg \( image2.png -fill "rgba(128,128,128,0.5)" -fuzz 20% -opaque gray \) -composite result.png
Note that at Version 7 of ImageMagick, the commands changed:
Version 6 | Version 7
=================================
identify | magick identify
convert | magick
mogrify | magick mogrify
composite | magick composite
montage | magick montage
compare | magick compare
animate | magick animate
stream | magick stream
The order of parameters is also stricter, favouring:
magick [settings] INPUT [settings] [operators] OUTPUT
over:
convert [settings] [operators] INPUT [settings] [operators] OUTPUT
What I mean is that you are expected to load an image prior to applying operators to it, rather than to build up a list of operators and then load an image and hope ImageMagick remembers what you said you wanted done if you ever loaded anything.
I want to split an image on the basis of color of the line.
I'm using hough line detector to detect a line and mark it with red color.
Now,i want to split the image on the basis of line which has been overlayed using line detection algorithm.
Image with line detection overlay
i want to split the above image into two.
You can do that in Imagemagick with some Unix shell commands as follows. The basic idea is to average the image to one column, then search the column for the y coordinate of the red pixel. Then use that to crop the image into two parts.
INPUT:
width=$(convert -ping tRbWW.png -format "%w" info:)
height=$(convert -ping tRbWW.png -format "%h" info:)
y=$(convert tRbWW.png -alpha off -scale 1x! -fuzz 20% -fill red -opaque red txt:- | grep "red" | head -n 1 | cut -d: -f1 | cut -d, -f2)
height1=$((y+1))
height2=$((height-y+1))
convert tRbWW.png \
\( -clone 0 -gravity north -crop ${width}x${height1}+0+0 +repage +write top.png \) \
\( -clone 0 -gravity south -crop ${width}x${height2}+0+0 +repage +write bottom.png \) \
null:
Top:
Bottom:
After I rotate or deskew an image with Imagemagick there's a white background in the corners, where the rotation took place. Example:
convert image.png -rotate 10 out.png
Output: http://imgur.com/8bZQ6
Is there a way I could somehow fill up those white corners with some texture or at least a color that blends in with the image? Cropping is not an option.
I've found this great solution for simple rotation:
convert image.png -virtual-pixel Edge +distort SRT 10 out.png
Output: http://imgur.com/edMS0
But unfortunately it doesn't work with the -deskew command...
So, does anyone know how to fill up those corners in a similar way for the -deskew (and -rotate) command? The point is to mask the fact the image was rotated as best as possible.
I'll go ahead and answer my own question, but I'm still hoping for a better solution.
You can set the -background color, which works with rotate and deskew.
Here's a solution that uses the average image color:
convert image.png -background `convert image.png -resize 1x1 txt:- | tail -1 | cut -b 30-50` -rotate 10 out.png
Output: http://imgur.com/YCqkC
And a better solution that takes some border pixels:
convert image.png -background `convert image.png -resize 100x1! \( +clone -crop 1x1+0+0 \) +append -crop 2x1+99+0 -resize 1x1 txt:- | tail -1 | cut -b 30-50` -rotate 10 out.png
Output: http://imgur.com/4wDPO
There's some bash scripting (inside the backticks), so these solutions are unix only.
Try this:
convert image.png -background transparent -rotate 10 out.png