Reverse Frames in Sprite Sheet - Imagemagick - imagemagick

How do i reverse the frames of an sprite sheet with each frame of size 30x30 and horizontally aligned using Imagemagick?
Example:
http://i.stack.imgur.com/OIoYc.png ->>> http://i.stack.imgur.com/7WR9v.png (edited)

You can do that like this...
First, create three little 30x30 images in Red, Green and Blue:
convert -size 30x30! xc:red red.png
convert -size 30x30! xc:green green.png
convert -size 30x30! xc:blue blue.png
then append them side by side:
convert +append red.png green.png blue.png image.png
to get this:
Now crop that into 30x30 pixel frames, and reverse the order of the frames, then re-append them together into the output image.
convert -crop 30x30 image.png -reverse +append out.png
Note:
For future reference, if anyone wants to do the same thing but vertically instead of horizontally, just change +append to -append.

Related

imagemagick montage: insert images of different sizes

I have an image a.png of size 800x600, and two images b.png and c.png of size 400x300 each. I want to montage (insert) the three images without size changes into a png image of size 800x900, such that a.png is at the top, and b.png and c.png side-by-side underneath.
How can I do this with imagemagick convert or montage?
Generate sample images, 1/10th the real size:
magick -size 80x60 -background red -gravity center label:"A" a.png
magick -size 40x30 -background lime -gravity center label:"B" b.png
magick -size 40x30 -background blue -gravity center label:"C" c.png
Now, you can load A, and inside parentheses, load B and C and place side-by-side as a new image, then append that result below A:
magick a.png \( b.png c.png +append \) -append result.png
Or, if you dislike the parentheses, you can join B and C side-by-side into a single image, load A, swap the order so A is at the top and then append the combined image below:
magick b.png c.png +append a.png +swap -append result.png
Note the distinction between:
+append meaning "append to the right", and
-append meaning "append below".
Note that, in addition to +append and -append, there are the newer tools called +smush and -smush which do exactly the same but take a parameter which is the number of pixels to offset the appending. So if you do +smush 5 it will do the same as +append but leave 5 pixels of background colour showing in the new gap between the images. If you use a negative offset, it will append in the same place but overlap the two images by the offset.
Here's an example, I make the background magenta and smush B and C with a 10 pixel gap. Then change the background to yellow before smushing the result below A with a 15 pixel offset.
magick -background magenta b.png c.png +smush 10 a.png +swap -background yellow -smush 15 result.png
If still using v6 ImageMagick, replace magick with convert.

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

How to split an image with a grid and preserve transparency bounding box

I have some png images that I want to split it into parts, like by grid or size.
But each part should have the same bounding box (transparency) as original image.
Example:
Splitting image into 2 parts.
Original: 200 × 89
Output:
part_1.png, 200 × 89
part_2.png, 200 × 89
Can ImageMagick do this? Or any other app or method.
My actual goal is to split into 100+ slices images.
EDIT:
Another goal to have an indents for each slice. Say indent = 10px.
Example:
Input: 200 x 100
Output:
part_1.png, 200 x 100
part_2.png, 200 x 100
And just as example, to visually compare input and output: combined output images in Photoshop as layer added one onto another
200 x 100 :
Also this is showing input image added onto combined(so it's better to see what was cropped and how):
In ImageMagick, you can split an image into many parts with the -crop command. For your example above with two parts, you can do that with the following commands. ImageMagick will append -0, -1 ... to the output file names.
ImageMagick 6:
dim=`convert image.png -format "%wx%h" info:`
convert \( -size $dim xc:none \) null: \( image.png -crop 50x100% \) -layers composite result.png
ImageMagick 7:
magick \( image.png -set option:dim "%wx%h" -crop 50x100% \) null: \( -size "%[dim]" xc:none \) -reverse -layers composite result.png
The results are:
See
http://www.imagemagick.org/Usage/crop/#crop
http://www.imagemagick.org/Usage/crop/#crop_percent
http://www.imagemagick.org/Usage/crop/#crop_tile
http://www.imagemagick.org/Usage/crop/#crop_quad
http://www.imagemagick.org/Usage/crop/#crop_equal
http://www.imagemagick.org/script/command-line-options.php#layers
Note that -crop keeps the virtual canvas information if you do not add +repage afterwards. So to put the individual images back into their original placement, you have to composite them onto a transparent background the size of the input. That is done in one command using -layers composite using the null: separator.
Here is another way to add transparent areas between parts of a crop in ImageMagick. Crop the image into pieces, chop off the parts you want to remove, then pipe to montage to add the spacing back.
Input:
Here I make this into a 4x4 grid of images with 10 pixel spacing:
convert lena.png -crop 25%x25% +repage -gravity east -chop 10x0 -gravity south -chop 0x10 +repage miff:- | montage - -background none -tile 4x4 -geometry +5+5 result.png
To answer your new question, you can do that with a script loop. On a Unix-like platform, assuming your images do not have spaces, you can do the following:
cd path/to/current_folder
list=`ls *.png`
for img in $list; do
name=`convert $img -format "%t" info:`
dim=`convert $img -format "%wx%h" info:`
convert \( -size $dim xc:none \) null: \( $img -crop 50x100% \) -layers composite -scene 1 path/to/new_folder/${name}_%d.png
done
If you want leading 0s in the output, say 3, use path/to/new_folder/${name}_%03d.png.
Note that to start with 1 rather than 0, I have added -scene 1.
Sorry, I do not know how to script for Windows.
Please always provide your ImageMagick version and platform.
In ImageMagick, the best way to put transparent areas into your image is with a binary mask that is put into the alpha channel of your image.
convert input.png \( -size 200x89 xc:white -size 10x89 xc:black -gravity center -composite \) -alpha off -compose copy_opacity -composite result.png
You can add as many blank areas as you want by adding more white areas to the mask or by tiling out one region of black and one region of white to create the mask with regular spacing of black and white.
Edited to add this ImageMagick 6 example which splits the input image into 4 pieces, 25% of the original width and 100% of its height, then creates a transparent canvas for each piece the same dimensions of the input image, and locates the pieces at their original offsets on those canvases.
convert input.png -set option:distort:viewport %[w]x%[h] -crop 25x100% \
-virtual-pixel none -distort affine "0,0 %[fx:s.page.x],%[fx:s.page.y]" out%03d.png
The output file names will be numbered starting from zero like "out000.png", etc.
Original message...
Here's a simple command using ImageMagick 7 that can crop an image into any number of pieces, and output all the pieces at their original offsets on transparent backgrounds of the original input dimensions...
magick input.png -crop 100x1# -background none \
-extent "%[fx:s.page.width]x%[fx:s.page.height]-%[fx:s.page.x]-%[fx:s.page.y]" out%03d.png
That "-crop 100x1#" tells it to split the image into a grid 100 pieces wide by 1 piece high. You could just as well specify the crop sizes as percents or numbers of pixels.
Edited again to add:
This following command will split the input image into the individual pieces specified with the "-crop" operator, then shave 5 pixels from every side of each piece, then apply a 5 pixel transparent border to every side of each piece. It will still remember the original locations of the pieces within the input canvas, so the "-distort affine ..." can extend the canvases and place the pieces where they were in the input image.
convert input.png -set option:distort:viewport %[w]x%[h] \
-bordercolor none -background none -virtual-pixel none \
-crop 25x100% -shave 5x5 -border 5x5 \
-distort affine "0,0 %[fx:s.page.x],%[fx:s.page.y]" out%03d.png
To use this command with IM7 you need to change "convert" to "magick".
Given the changes of requirements provided by Kamikaze, here is one way to achieve the split with indent in ImageMagick, assuming I understand correctly.
dim=`convert image.png -format "%wx%h" info:`
convert \( -size $dim xc:none \) null: \( image.png -crop 50x100% -shave 5x5 \) -geometry +5+5 -layers composite result.png
To check, I flatten over a blue background:
convert result-0.png result-1.png -background blue -flatten result.png

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 convert rotate crop

The rotate option in ImageMagick's convert tool rotates the image but adds background color to fill the gaps.
I'm looking for a way to rotate and then crop the largest rectangle containing content of the image. Is it possible with convert?
Edited by Mark Setchell...
So, if your original rectangle is a checkerboard created like this:
convert -size 512x512 pattern:checkerboard a.png
and you rotate it through 20 degrees like this
convert -background fuchsia -rotate 20 a.png b.png
you want the largest rectangle that fits on the checkerboard and contains no pink?
You can get an approximation of your expected result by using +repage and replacing -rotate with -distort ScaleRotateTranslate:
convert -background fuchsia -distort ScaleRotateTranslate 20 +repage a.png b.png
After creating the image as indicated:
convert -size 512x512 pattern:checkerboard a.png
This seems to do the work:
angle=20
ratio=`convert a.png -format \
"%[fx:aa=$angle*pi/180; min(w,h)/(w*abs(cos(aa))+h*abs(sin(aa)))]" \
info:`
crop="%[fx:floor(w*$ratio)]x%[fx:floor(h*$ratio)]"
crop="$crop+%[fx:ceil((w-w*$ratio)/2)]+%[fx:ceil((h-h*$ratio)/2)]"
convert a.png -set option:distort:viewport "$crop" \
+distort SRT $angle +repage rotate_internal.png
From here.

Resources