How to center images in gif using convert from imagamagick? - bash

My goal is to create gif image from jpg which I will rotate on angle A with delay D imagemagick. So, i've got this code:
for (( i=0; i < 360; i+=$a )) do
name=%(printf "%03d" $i)
convert $image -rotate $i "temp/$name.jpg"
done
convert -delay $d "temp/*.jpg" out.gif
The problem is that images in out.gif is not centered. How can i center them?
(image should be rotated relative to the center)

The problem is that images in out.gif is not centered.
It just seems that way when you look at the final gif. However, the image already rotates around its center. Example: I have the image 1.png and rotate it in steps of 15°.
convert 1.png -rotate 15 2.png
convert 1.png -rotate 30 3.png
convert 1.png -rotate 45 4.png
Now let's have a look at the images 1-4.
As we can see, the image rotates around its center, but the image dimension changes.
When we convert those four images into one gif animation, we have to set a fixed dimension for the whole animation and a position of each frame on the canvas. Without giving further information, ImageMagick uses the first frame's dimension as the dimension of the animation and places each frame at the top left. Since the first frame (rotation 0°) is the smallest, the other frames get cropped. The following illustration shows what will get cropped.
To solve the problem, we have two options:
When creating the animation, center each frame.
When rotating, crop the result such that all frames have the same size.
I would go with 2. ImageMagick has the operator -distort SRT <ANGLE> which rotates and crops in one step. Using this operator will also look smoother in animations, see here. Replace your -rotate $i with -distort SRT $i.

The ImageMagick "-rotate" operator will increase the output dimensions so the entire input image still fits within the output. That produces results with various dimensions for different angles of rotation. Using the plus form of "+distort SRT" will have the same effect.
And "-distort SRT" will rotate the image on center inside its input dimensions, but that will clip off the corners as they rotate outside the original frame.
There is a way to rotate an image several times, pivoting on the center point, and in a viewport that accommodates the entire image even when rotated.
By setting the input image name "$image", the number of frames "$f", and the delay per frame "$d", a command like this can do everything your "for" loop is doing while eliminating the writing and reading of temporary files. It looks more complicated than it really is...
image=input.jpg
f=20
d=50
convert -delay $d -dispose previous "$image" -background none -virtual-pixel none \
-duplicate $f +delete -set option:distort:viewport "%[fx:hypot(w,h)]x%[fx:hypot(w,h)]" \
-distort SRT "%[fx:w/2],%[fx:h/2] 1 %[fx:360/n*t] %[fx:hypot(w,h)/2],%[fx:hypot(w,h)/2]" \
out.gif
That command will read the input "$image", duplicate it to create a total of "$f" frames, set the delay to "$d", rotate each image "360/$f" degrees more than the previous, and output the final result as an animated GIF.

Related

Merging two transparent gifs as layers

I've found this page on the imagemagick forum: Merging 2 gifs, one is animated and transparent which links to the imagemagick docs on Animation Modification; specifically, the example here:
convert canvas_prev.gif -coalesce \
-gravity NorthEast -draw 'image over 5,5 0,0 "rose:"' \
-layers Optimize draw_over.gif
Here's my attempt. I have these two gifs (i might be feeling a little morbid). The white in the first is actually transparent.
when I run
convert eyes.gif -coalesce -draw ' image over 0,0 0,0 "trump.gif" ' combine.gif
I get this:
which is not the complete effect I desire. The trump animation is no longer playing at all.
I want to see something more like this (this is created in Phaser JS, but this gives me no way to export the result as a new image other than manually recording a screencast):
One way to do it, yet not sure if it's the best, is as follows:
convert both animations into sprite-sheets of same dimensions
paste one image over the another
cut result into smaller frames and convert it into animated GIF
The commands should look like this:
montage -background none t.gif -tile x1# -geometry +0+0 tt.png
montage e.gif[0-16,0-9] -tile x1# -geometry +0+0 ee.png
magick convert -delay 10 -loop 0 ee.png tt.png -coalesce -flatten \
-crop 150x150 +repage output.gif
Tricky part is the second line with eyes image. It has only 17 frames while skull has 27. So the sprite sheet size must be adjusted.
I works, however I am not quite happy with this as solution requires manual entering of some parameters (frames selection and output image dimensions).

How can I stretch the edge colors of elements in an image with alpha channel?

I have an PNG with an alpha channel. First I want to find all elements in the png, then I want to stretch the last color on the border about 5 to 10 pixels out
The stretching has to be in all directions from the center of each object on the image (like triangle, rectangle...)
It is important that I keep the color of each pixel on the edge
Is this possible? Goal is in the future to automate the process with ImageMagick.
I have had a play with distort and it is probably the way to go but needs more investigation. I was working on a smaller image and the code is basically a proof of concept.
I think edge is the key option and with this example I reduced the size of the resized image all round by 20px in the distort.
I do not know how you would get the angled edges though.I know you do not want to distort the original but it may give you some ideas as to how to get the result you want.
convert "1.png" -trim -matte -virtual-pixel edge -mattecolor none -interpolate Spline +distort BilinearForward "0,0 20,20 400,0 380,20 400,95 380,55 0,95 20,55" -trim +repage "result.png"
I am not quite sure what is going on at the edges of your image, but this should get you started...
First, I trim off any transparent edges (with -trim) so we get to the actual pattern you seek to extend. Then clone the image and dispose of everything except the top row of pixels (with -crop). Then scale that row up till it is 800 pixels tall. Then exchange the tall top row with the original image in the processing order (using +swap) and append the original image below the height-extended top row.
convert cells.png -trim +repage \( +clone -crop x1+0+0 -scale x800! \) +swap -append result.png

Resize without whitespace surrounding on images using graphicsmagick or imagemagick

I'm using graphicsmagick to resize an image to a thumbnail, but it's adding a white surrounding border padding.
The command I'm using is:
gm convert matrix.jpg -resize "80x80>" -gravity center -extent 80x80 thumbnail.jpeg
As you can see, there is some white padding around the image, but I don't want this. Ideally I'd like (the entire image not just a crop of it) to fill the desired 80x80 output size.
How can this be achieved in either imagemagick or graphicsmagick?
I used ImageMagick with this image. This solution requires to know the size of the input image.
Input
The image has 145 pixels horizontally and 200 pixels vertically.
Crop
Crop from the top of the image:
convert -crop 145x145+0+0 -resize 80x80 matrix.jpg thumbnail.jpeg
I used 145x145 in order to extract a square from the original image. +0+0 is the offset of the extracted square, hereby the top left.
Crop with the center of the image:
convert -crop 145x145+0+27 -resize 80x80 matrix.jpg thumbnail.jpeg
The vertical offset is set to 27 because we have to remove 55 (200 - 145) pixels on top or bottom, so we need to remove 27 (55 ÷ 2) pixels on the top and 28 pixels on the bottom.
Crop with the bottom of the image:
convert -crop 145x145+0+55 -resize 80x80 matrix.jpg thumbnail.jpeg
Resizing without crop
convert -resize 80x80\! matrix.jpg thumbnail.jpeg
The ! flag (escaped with \! as suggested in the documentation) after the resize parameters forces ImageMagick to ignore the aspect ratio.
If you want to keep the original aspect ratio, without image distortion, you can use the ImageMagick -trim option to get rid of the white padding:
convert "matrix.jpg" -resize "80x80" -gravity center -extent 80x80
-trim "thumbnail.jpg"
This will produce a 58x80 uncropped image with the same aspect ratio as the original. It is 58x80 because ImageMagick uses the larger dimension of the original to compute the scale factor (in this case 80/200) and scales the smaller dimension by that same factor to preserve aspect ratio.
If you want an uncropped image of exactly 80x80 pixels, this is a different aspect ratio than the original. The output image will have distortion, and #AL's resizing without crop option will work.
convert "matrix.jpg" -resize "80x80!" -gravity center -extent 80x80
"thumbnail.jpg"
Tested in Windows 7 with ImageMagick 6.8.9. #AL syntax is probably Linux.

Crop thumbnail in imagemagick - specify center at X, Y position

I would like to generate thumbnails for my website. Now I am using the following to process folder (based on this answer):
mogrify -interlace Plane -thumbnail 280x210^
-gravity center -extent 280x210 -quality 85% *.jpg
This will create thumbnails with given size (resize and crop).
I also have single image version of this command:
convert test.jpg -interlace Plane -thumbnail 280x210^
-gravity center -extent 280x210 -quality 85% testout.jpg
I'm also using facedetect to get positions of faces from the original image (before creating thumbnails). For photos with faces I have calculated average X, Y position of faces center.
Now, I would like to use this position in the command above to crop pictures smarter. Currently image is cropped from both sides (-gravity center), but I would like to use my coordinates so faces are displayed when image is cropped.
Is there a way how I can feed this into imagemagick?
You could use -shave to remove part of the image, so that the face moves to the center, then apply your original command.

Image resizing, maintaing image size - beginner question

Im attempting to resize an image from 480x800 to 320x240. Below are the results. The original image has an oval shaped circle whereas the resized image has a more spherical shape. Is it possible to resize the original image so that the circle and rectangle are in their original proportions but smaller?
Can imagemagick or gimp (or other software) achieve this ?
Here's Imagemagick solution.
1) If you want large image to just fit 320x240 box and leave proportions, use:
convert test.png -size 320x240 resized.png
That will produce image sized 144x240.
http://www.imagemagick.org/Usage/resize/#resize
2) If you want large image to completely fill a specific image size, use:
convert test.png -resize 320x240\> \
-size 320x240 xc:blue +swap -gravity center -composite \
resized.jpg
That will produce image sized 320x240 with resized big image in center and blue fill on sides.
http://www.imagemagick.org/Usage/resize/#space_fill

Resources