Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Can't figure out how to rotate around coordinates, and there is some error in docs #366

Open
Nakilon opened this issue May 8, 2023 · 7 comments
Labels

Comments

@Nakilon
Copy link
Contributor

Nakilon commented May 8, 2023

I need to rotate this image around the center of the circle with known coordinates

temp

[x,y,angle]
[398, 290, -2.4995608216061647]
img.rotate(angle * 180 / Math::PI, idx: x, idy: y, odx: x, ody: y)

but it looks wrong, the position has shifted

temp

how do I do it without shifting the resulting circle?

Also the https://www.libvips.org/API/current/libvips-resample.html#vips-rotate doc has the ody arg twice.

vips-8.11.3-Wed Aug 11 09:29:27 UTC 2021
Vips::VERSION "2.1.4"
@Nakilon Nakilon added the bug label May 8, 2023
@Nakilon
Copy link
Contributor Author

Nakilon commented May 8, 2023

After playing around I suppose rotation shifts the image, i.e. you don't know the odx/ody ahead, because it all shifts to hold the top left corner pixel inside the image. It feels wrong.

jcupitt added a commit to libvips/libvips that referenced this issue May 9, 2023
@jcupitt
Copy link
Member

jcupitt commented May 9, 2023

Hi @Nakilon,

Also the https://www.libvips.org/API/current/libvips-resample.html#vips-rotate doc has the ody arg twice.

Oops! Thanks, I patched it.

I'll make you a rotate example, I have some code somewhere.

@jcupitt
Copy link
Member

jcupitt commented May 9, 2023

Sorry, just to be clear, you'd like an image the same width and height as the input, and with the circle in the same position, but the circle should be rotated so the leaf points roughly upwards, is that right?

@jcupitt
Copy link
Member

jcupitt commented May 9, 2023

Here's a thing that does ^^^ my guess.

#!/usr/bin/ruby

require 'vips'

x, y, angle = 398, 290, -2.4995608216061647

image = Vips::Image.new_from_file ARGV[0]

# add an alpha so we can see the image edges
image = image.add_alpha

# the [[a, b], [c, d]] affine transform we want (simple rotate)
a = Math.cos(angle)
b = -Math.sin(angle)
c = -b
d = a

# point (x, y) in the input goes to this coordinate in the output
x_after = a * x + b * y
y_after = c * x + d * y

# therefore to keep (x, y) in the same place, we need to move the output area
# by the difference
dx = x_after - x
dy = y_after - y

image = image.affine [a, b, c, d], oarea: [dx, dy, image.width, image.height]

image.write_to_file ARGV[1]

I see:

$ ./naklion.rb ~/pics/naklion.png x2.png

To make:

x2

You don't need the alpha, but it's an easy way to see where the image edges are.

@jcupitt
Copy link
Member

jcupitt commented May 9, 2023

... perhaps rotate should have an oarea parameter. It would make this a little simpler.

@Nakilon
Copy link
Contributor Author

Nakilon commented May 9, 2023

Yes, you understood right. Thank you. I predicted it would need to calculate these sinuses by yourself. And yes, it's very inconvinient. As a user of this method I don't expect the rotation to change the size of image, because it's kind of unpredictable.
After have no luck with it I ended up with just pixel-by-pixel projecting by myself ..(

Vips::Image.bandjoin( img.bandsplit.map do |band|
  array = band.to_a
  Vips::Image.new_from_array( array.map.with_index do |row, i|
    row.map.with_index do |c, j|
      (inner+outer)/2 < Math.hypot(x-j, y-i) ? c : ((
        ii = i - y
        jj = j - x
        array[jj * Math::sin(angle) + ii * Math::cos(angle) + y]\
             [jj * Math::cos(angle) - ii * Math::sin(angle) + x]
      ))
    end
  end ).cast :uchar
end )

otherwise I would need kind of reverse engineer this transformation method.

@Nakilon
Copy link
Contributor Author

Nakilon commented May 9, 2023

The goal was to transform this
image
to this
image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants