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

Rotate leaves black lines along one or more sides of the image. #338

Open
etherbob opened this issue Jun 20, 2022 · 4 comments
Open

Rotate leaves black lines along one or more sides of the image. #338

etherbob opened this issue Jun 20, 2022 · 4 comments
Labels

Comments

@etherbob
Copy link

Describe the bug
Rotating in 90º increments leaves a black line on one or more sides of non-square images

To Reproduce
Steps to reproduce the behavior:

Using this image:
flip-me-for-real

path = '/path/to/flip-me-for-real.jpg'
img = Vips::Image.new_from_file(path)
img.rotate(90).write_to_file('out90.jpg')

Expected behavior

Expect image to output rotated by 90 degrees without additional image content.

Actual Behavior

actual output out90

Screen Shot 2022-06-20 at 10 38 29 AM

Desktop:

  • OS: macOS
  • Version 12.4
  • ruby-vips 2.1.4
  • libvips 8.12.2-Tue Jan 25 09:34:32 UTC 2022

** Server **

  • heroku-stack 20 (Ubuntu 20.04-based)
  • ruby-vips 2.1.4
  • libvips 8.12.2-Tue Jan 25 09:34:32 UTC 2022
@etherbob etherbob added the bug label Jun 20, 2022
@etherbob
Copy link
Author

I reported this to the image_processing gem (janko/image_processing#104) but it looks like this might be happening at a lower level than either of these gems. My doing-anything-with-c skills are very much atrophied or I'd take a swing at reproducing directly against libvips.

I also attempted to apply some of the suggestions in libvips/libvips#1051 but would be completely unsurprised to find out I missed a trick somewhere.

@jcupitt
Copy link
Member

jcupitt commented Jun 20, 2022

Hi @etherbob,

This is expected behaviour. libvips uses corner convention by default for affine transforms, so a 90 degree rotate will translate the image by 1 pixel.

Your best fix (if you want a no-border 90 degree rotate) is to use the rot90 method. This does a simple pixel swap rotation, so it can only do multiples of 90, but you'll get a borderless result. Something like:

result = image.rot90()

There's also rot180, rot270 and rot. Don't use rot45, that's just for matrix arithmetic.

If you want fractional rotations, then you could use centre convention with eg.:

result = image.rotate(90, idx: 05, idy: 0.5)

Now you'll get symmetrical edges, but the 0.5 pixel displacement will make your image a little fuzzy.

@etherbob
Copy link
Author

etherbob commented Jun 20, 2022

Thank you for the quick response @jcupitt, that did the trick. Do you think it would be possible/reasonable to have ruby-vips switch to the appropriate rot command if the angle is divisible by 90?

@jcupitt
Copy link
Member

jcupitt commented Jun 21, 2022

I think flipping between rotate methods depending on the argument value would produce some unfortunate transition effects.

I think the best solution is to have two separate methods: one to do an exact rotate in 90 degree steps, and one to do a free rotation (this is what ruby-vips does now).

Perhaps we can do more to improve rotate, I'll make an issue to look at this again for 8.14.

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