Page 1 of 1

Rotation per default not around center but NorthEast corner of image

Posted: 2018-11-13T16:56:32-07:00
by leonidas
I am trying to place a rotated image onto a blank canvas.

This is the command i am using:

Code: Select all

convert "(" -size 1000x1000 xc:transparent ")" "(" "img.jpg" -virtual-pixel white -rotate -10.75 ")" -geometry +136+148 -composite out.png
I would expect the image to appear at +136+148 rotated around its center. However, it appears to be rotated around its upper right corner instead.

I confirmed this in Photoshop:

This is the resulting image (using slightly different size but same parameters as my example command given here):

Image

The 4 lines are the guides that mark the coordinates that define where the image sits. As you can see, the image is rotated -10.75 degrees. And the rotation center is the upper right corner.

Here i select the box at the correct coordinates in Photoshop:

Image

And here i rotate it after setting the rotation point to the top right:

Image

As you can see, the selection now matches the image as it was calculated by my convert command.

I have tried dealing with this for many hours. I tried switching to +distort and -distort and what not, but there i simply get either a cropped image or another wrongly positioned bounding box.

I don't know how to address this problem. What am i doing wrong? How can i tell -rotate to rotate my image around its center, not around the top right corner (why top right anyway?).

Thank you for your help!

Warm regards,
Leonidas
Version: ImageMagick 6.9.9-40 Q16 x86_64 2018-06-18 http://www.imagemagick.org

Re: Rotation per default not around center but NorthWest corner of image

Posted: 2018-11-13T17:46:37-07:00
by snibgo
You haven't provided your input image "img.jpg", so I can't reproduce your command, so don't really understand your issue. Rotation is rotation.

Assuming img.jpg is an ordinary photo of some people, I don't see how you got that output from your command.

"-rotate" should usually be followed by "+repage", unless you need the offsets.

"-geometry +136+148 -composite" will put the top-left of the second image at (136,148).

Re: Rotation per default not around center but NorthWest corner of image

Posted: 2018-11-13T18:19:27-07:00
by leonidas
I understand the confusion.

Let me explain more properly, with a better example and some files.

I have two files: Image.jpg and Overlay.png

Image.jpg is this:

Image

Overlay.png is this:

Image

It has a cutout.

The goal is to rotate and place Image.jpg underneath the cutout in Overlay.png.

To achieve this, i have the following information:

1.) Coordinates of the cutout (X:136, Y:148)
2.) The angle by which the cutout is rotated (-10.75)

I now want to build an ImageMagick command to achieve that goal.

I begin with a blank transparent canvas of 600x500, which is also the size of Overlay.png.

Code: Select all

convert -size 600x500 xc:transparent
I then add a command to place Image.jpg on the canvas at the specified coordinates:

Code: Select all

convert -size 600x500 xc:transparent "(" Image.jpg -rotate -10.75 +repage -geometry +136+148 ")"
I now tell convert to place Overlay.png on top of everything else, at coordinates X:0 Y:0, and then i add the final composite parameter and output everything to out.png.

So the final command looks like this:

Code: Select all

convert -size 600x500 xc:transparent "(" Image.jpg -rotate -10.75 +repage -geometry +136+148 ")" -composite Overlay.png -geometry +0+0 -composite out.png
This results in the following image:

Image

But in Photoshop, when i place Image.jpg on Overlay.png at the given coordinates, this is what it looks like:

Image

And when i rotate it in Photoshop using the image's centerpoint as origin of rotation, this is what i get:

Image

Which is the way it should look like.

However, when i choose the top right of the image as the origin for rotation in Photoshop, this is what i get:

Image

And this looks precisely like what ImageMagick writes into out.png.

So the question is: how can i rotate Image.jpg in such a way that it is rotated around its own center, thus resulting in Image.jpg being placed correctly underneath the cutout in my final output (out.png) ?

It looks to me that ImageMagick is rotating Image.jpg using its top right corner as origin, whereas it should use its center.

What am i missing here?

Re: Rotation per default not around center but NorthEast corner of image

Posted: 2018-11-13T18:53:00-07:00
by GeeMack
leonidas wrote: 2018-11-13T16:56:32-07:00I would expect the image to appear at +136+148 rotated around its center. However, it appears to be rotated around its upper right corner instead.
It looks like you're misunderstanding the necessary geometry to locate your overlay where you want it. You should be trying to align the left and top of the overlay with the leftmost point and topmost point of your target area. It looks like a geometry setting of somewhere around +122+118 will get you nearer the target.

Re: Rotation per default not around center but NorthEast corner of image

Posted: 2018-11-13T19:03:41-07:00
by snibgo
leonidas wrote:1.) Coordinates of the cutout (X:136, Y:148)
Where is that coordinate? It isn't any of the corners of the cutout, or a corner of the bounding box of the cutout.

The left side of the bounding box is at x=123, and the top edge is at y=119. The photo is slightly larger than the cutout, so we can allow a couple of pixels so antialiasing isn't a problem:

Code: Select all

magick ViZsLrf.png ( Tskxwbn.jpg -rotate -10.75 +repage ) -geometry +121+117 -compose DstOver -composite out.png

Re: Rotation per default not around center but NorthEast corner of image

Posted: 2018-11-13T19:06:12-07:00
by fmw42
The geometry offset you are using moves the top left corner of the rotated image after its background has been added and not the top left corner of the Input where it gets rotated. So that is why you are not getting the right result.

You would be better using -gravity center and figuring out where to move the center of the rotated image with its background to the center of your transparent box.

Alternately, pick the 4 corner points of the transparent box and the 4 corners of your input image and do an Affine or Perspective distortion to put the image inside the box.


For example, I picked control points, but not too carefully. So you can adjust a bit. This is bash unix syntax.

Code: Select all

box1="122,186"
box2="466,118"
box3="510,345"
box4="166,411"
WxH=`convert -ping "Image.jpg" -format "%wx%h" info:`
ww=`echo "$WxH" | cut -dx -f1`
hh=`echo "$WxH" | cut -dx -f2`
ww=$((ww-1))
hh=$((hh-1))
echo "$ww; $hh;"
in1="0,0"
in2="$ww,0"
in3="$ww,$hh"
in4="0,$hh"
convert overlay.png \
\( Image.jpg -virtual-pixel none +distort Perspective \
"$in1 $box1  $in2 $box2  $in3 $box3  $in4 $box4" \) \
-layers merge +repage \
out.png
Image

This actually overlays the input onto the overlay image.

See https://imagemagick.org/Usage/distorts/#perspective

Re: Rotation per default not around center but NorthEast corner of image

Posted: 2018-11-14T03:05:21-07:00
by leonidas
Thank you for your responses. I'll see if i can derive an automatism from what was posted.

Generally i should have added that i wouldn't have a problem fixing this for this one example by changing coordinates, but this is all done by automated scripts and they are fed with coordinates and angles for cutouts under which to place certain images, so the goal is to have a way to correctly calculate where to place the rotated images. Therefore a fixed value is not really what i was looking for.

To answer snibgo's question: The coordinates are where the cutout was placed before it was rotated around its center be -10.75 degrees. It may be possible that in my example there are a few pixel inaccuracies but in general the values are right. The examples are just there to depict the issue.

In my backend, the user uploads a PNG with cutouts predefined, then draws rectangular areas that can be rotated. These are placed over the cutouts with a bit of a bleed and that whole information is saved as a template. In the frontend, users then upload photos and can place them on any of those zones (underneath the cutouts). I preview it all via CSS3 which works perfectly well, but in the end i must generate a single JPG for print, merging all those layers together, and this is where i have the problems applying the rotation accordingly.

Sorry btw. for double-posting (here & StackOverflow) but after 9 hours of fruitlessly trying to get to the desired result, i had lost so much time from the scale of this project that i wanted to find an answer really quick.

Thanks for your support.

Re: Rotation per default not around center but NorthEast corner of image

Posted: 2018-11-14T03:56:23-07:00
by leonidas
Quite honestly, when i try to even wrap my head around how to calculate this, my brain goes into temporary shutdown and all i get is white noise ..

Generally i understand it this way:

The best solution for me is to calculate the center of the bounding box of the rotated Image.jpg and calculate the center of the bounding box of my cutout zone, then place Image.jpg with its center onto the center of the cutout zone bounding box. But how would i go about calculating the center?

Theoretically, this is what i can come up with:

1.) Take cutout zone rectangle coords (unrotated) as polygon
2.) Rotate cutout zone poly via a function
3.) Determine bounding box of rotated polygon
4.) Get width and height of bounding box, divide each value by two to get the coordinates of the center of the rotated polygon
5.) Generate rotated version of Image.jpg with separate command into a separate file
6.) Place that Image.jpg onto Overlay.png using the center coordinates calculated before and with -gravity center set.

Is this correct?

Re: Rotation per default not around center but NorthEast corner of image

Posted: 2018-11-14T05:37:15-07:00
by snibgo
leonidas wrote:Is this correct?
I wouldn't bother with steps (1) and (2), but go straight to (3):

Given an input with transparent cutouts, this finds the bounding box of each:

Code: Select all

magick ^
  ViZsLrf.png ^
  +repage ^
  -strip ^
  -alpha extract ^
  -fill Black +opaque White ^
  -define connected-components:verbose=true ^
  -connected-components 4 ^
  NULL:

  0: 600x500+0+0 293.4,243.9 218667 srgb(255,255,255)
  1: 389x294+122+118 316.0,264.5 81333 srgb(0,0,0)
Each bounding box is "srgb(0,0,0)". Here, we have only one. The BB is 389x294 pixels, with top-left corner at (+122,+118). Hence the centre is at ( 122 + (389-1)/2 , 294 + (118-1)/2 )


You also need to deal with colour profiles. The sample inputs you supplied have two different embedded profiles. When compositing the two images, IM will not automatically convert either to the other, or both to some common standard. Hence the output will contain wrong pixels in one part of the image.

You need to decide what you want to do about that. A possible strategy is:

1. If the images use the same profile, do nothing.

2. If one profile has a larger gamut than the other (eg AdobeRGB is larger than sRGB) then convert to the larger one.

3. Otherwise, convert both to a sRGB profile.

Step (2) is difficult.

A simpler strategy is: always use "-profile sRGB.icc" (or some other sRGB profile). This will assign the profile when an image has no embedded profile; otherwise it will convert to that profile.

Re: Rotation per default not around center but NorthWest corner of image

Posted: 2018-11-14T10:58:52-07:00
by GeeMack
leonidas wrote: 2018-11-13T18:19:27-07:00So the question is: how can i rotate Image.jpg in such a way that it is rotated around its own center, thus resulting in Image.jpg being placed correctly underneath the cutout in my final output (out.png) ?
Using your examples "image.jpg" and "overlay.png", you can find the location of the cutout and properly place the image under the overlay with a command like this...

Code: Select all

convert overlay.png -background none \
   \( +clone -alpha extract -trim -set option:offset +%[fx:page.x]+%[fx:page.y] +delete \) \
   \( image.jpg -rotate -10.7 -set page %[offset] \) -set page %[fx:u.w]x%[fx:u.h] \
   +swap -layers merge result.png
That reads in the "overlay.png", and inside parentheses it makes a clone of it, extracts the alpha channel, and trims the result to find the offset of the cutout. It saves the offset to a variable named "offset".

Then inside another set of parentheses it reads in the "image.jpg", rotates it the known -10.7 degrees, and uses the variable "offset" to set the paging offset on the rotated "image.jpg".

Then outside the parentheses it uses the width and height of "overlay.png" to set the paging dimensions for "imgage.jpg".

It finishes by swapping the order of the images to put "image.jpg" underneath, then merging the two layers to create the output.

Depending on the comparison of sizes of the input image and the hole to fill, this might require a tweak of a pixel or two in that offset information to get a precise location. It's a simple matter to modify one or both of the FX expressions like for example, "%[fx:page.x-2]" would make a -2 pixel adjustment to the width offset.

The command above is in IM6 *nix syntax and works with IM 6.8.9-9 on my Windows 10 Ubuntu bash shell. Substitute the end-of-line backslashes "\" with carets "^" and get rid of the backslashes "\(" on the parentheses to make it a Windows command. In a Windows BAT script you need to double the percent signs "%%" on the FX expressions and IM variables. If you're using IM version 7, use the command "magick" instead of "convert".

Re: Rotation per default not around center but NorthEast corner of image

Posted: 2018-11-14T14:03:02-07:00
by fmw42
Here is an alternate to GeeMack's excellent ImageMagick solution. This computes the center of the original input.jpg, and the center of the transparent region in the Overlay.png. Then it uses +distort SRT to translate and rotate the image before finally compositing with -layers merge.

Code: Select all

convert Overlay.png \
\( +clone -alpha extract -trim -set option:center "%[fx:page.x+w/2],%[fx:page.y+h/2]" +delete \) \
\( Image.jpg -virtual-pixel none +distort SRT "%[fx:w/2],%[fx:h/2] 1 -10.7 %[center]" \) \
+swap -layers merge +repage out2.png
Image

The second line is much line GeeMack's, but it computes the center of the transparent region's bounding box and saves that in the "center" argument and then deletes the trimmed image.

The third line computes the center of the Input.jpg image (before rotation). It then uses +distort SRT to translate from the input center, (scale=1) and rotate -10.7 and translate to the center of the transparent region's bounding box.

See https://imagemagick.org/Usage/distorts/#srt