Skip to content

Commit 5ab56ae

Browse files
authored
Merge pull request #199 from hlindset/use-rot-for-right-angle-rotate
Use `Operation.rot/2` for right-angle rotations
2 parents ff902fa + cdec892 commit 5ab56ae

4 files changed

Lines changed: 50 additions & 1 deletion

File tree

lib/image.ex

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5907,6 +5907,12 @@ defmodule Image do
59075907
a list of 3 or 4 float values depending on the image
59085908
color space.
59095909
5910+
## Discrete rotation
5911+
5912+
When `angle` is a multiple of 90, and all displacement options
5913+
are unset, `nil`, `0` or `0.0`, the rotation will be done as a
5914+
discrete operation in order to preserve source pixel values.
5915+
59105916
## Notes
59115917
59125918
The displacement parameters cause the image canvas to be
@@ -5935,10 +5941,41 @@ defmodule Image do
59355941

59365942
def rotate(%Vimage{} = image, angle, options \\ []) when is_number(angle) do
59375943
with {:ok, options} <- Options.Rotate.validate_options(options) do
5938-
Operation.rotate(image, angle, options)
5944+
rot_angle = rot_angle(angle, options)
5945+
5946+
if rot_angle do
5947+
Operation.rot(image, rot_angle)
5948+
else
5949+
Operation.rotate(image, angle, options)
5950+
end
5951+
end
5952+
end
5953+
5954+
defp rot_angle(angle, options) do
5955+
if Options.Rotate.no_displacement?(options) do
5956+
to_rot_angle(angle)
59395957
end
59405958
end
59415959

5960+
defp to_rot_angle(angle) when is_integer(angle) and rem(angle, 90) == 0 do
5961+
angle
5962+
|> Integer.mod(360)
5963+
|> rot_angle_from_degrees()
5964+
end
5965+
5966+
defp to_rot_angle(angle) when is_float(angle) and angle == trunc(angle) do
5967+
angle
5968+
|> trunc()
5969+
|> to_rot_angle()
5970+
end
5971+
5972+
defp to_rot_angle(_angle), do: nil
5973+
5974+
defp rot_angle_from_degrees(0), do: :VIPS_ANGLE_D0
5975+
defp rot_angle_from_degrees(90), do: :VIPS_ANGLE_D90
5976+
defp rot_angle_from_degrees(180), do: :VIPS_ANGLE_D180
5977+
defp rot_angle_from_degrees(270), do: :VIPS_ANGLE_D270
5978+
59425979
@doc """
59435980
Rotate an image clockwise (to the
59445981
right) by a number of degrees.

lib/image/options/rotate.ex

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,4 +64,16 @@ defmodule Image.Options.Rotate do
6464
defp invalid_option(option) do
6565
"Invalid option or option value: #{inspect(option)}"
6666
end
67+
68+
@doc false
69+
def no_displacement?(options) do
70+
empty_displacement?(options, :idx) and
71+
empty_displacement?(options, :idy) and
72+
empty_displacement?(options, :odx) and
73+
empty_displacement?(options, :ody)
74+
end
75+
76+
defp empty_displacement?(options, key) do
77+
Keyword.get(options, key, 0) in [nil, 0, 0.0]
78+
end
6779
end
-186 Bytes
Loading
-1006 Bytes
Loading

0 commit comments

Comments
 (0)