Imagemagick chop 30px off each edge (variable width and height) - imagemagick

I need to chop 30px off each side (top bottom left right). I've tried crop and also -chop 30x30 but that only seems to work on one side;
convert -verbose -density 150 -trim pdfs/test/test.pdf -quality 80 -chop 30x30 images/agents/test/temp/test.jpg

If it's an even amount on both sides of a dimension, then the command you want is -shave
convert -verbose -density 150 -trim pdfs/test/test.pdf -quality 80 -shave 30x30 images/agents/test/temp/test.jpg

Related

I want to scale the sprite 8x with padding between pixels

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

imagemagick montage - how to align images to bottom

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.

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

Cleaning the left side of an image

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

Imagemagick crop while keeping size

I want to crop the top 10 pixels of an image, but to keep the width
All exmaples I found look like
convert rose: -crop 90x60-10-10 crop_all.gif
I need to supply the 90x60 so for the result size
How can I crop with something like +0+10 and not supply a final size
I think you need this to chop 10px off the top edge:
convert rose: -chop 0x10 result.gif
Just for completeness, if you want to chop 10px off the bottom, do this:
convert rose: -gravity south -chop 0x10 result.gif
And to chop 10px off the left edge:
convert rose: -chop 10x result.gif
and 10px off the right edge:
convert rose: -gravity east -chop 10x result.gif
The reason you don't need to specify -gravity for top and left sides is that the default value for the -gravity setting is NorthWest.

Resources