diff --git a/Program.cs b/Program.cs index cc493d3..56d4a27 100644 --- a/Program.cs +++ b/Program.cs @@ -290,6 +290,36 @@ public class StraightenTool : ITool { } if (input.IsKeyPressed(Keys.Enter)) { + Matrix2 rotation = Matrix2.CreateRotation(MathHelper.DegreesToRadians(photo.RotationDegreeHundredths / 100f)); + Vector2 center = new(photo.Size.X / 2f, photo.Size.Y / 2f); + + float[] xCoords = new float[4]; + float[] yCoords = new float[4]; + List corners = Util.RectangleCorners(new Rectangle(0, 0, photo.Size.X, photo.Size.Y)); + for (int i = 0; i < 4; i++) { + Vector2i corner = corners[i]; + Vector2 rotated = Util.RotateAboutCenter(corner, center, rotation); + xCoords[i] = rotated.X; + yCoords[i] = rotated.Y; + } + Array.Sort(xCoords); + Array.Sort(yCoords); + for (int i = 3; i >= 0; i--) { + xCoords[i] -= xCoords[0]; + yCoords[i] -= yCoords[0]; + } + // FIXME: we can get a bigger crop using a better algorithm -- this is + // too conservative. Also, preserve aspect ratio? Maybe we need to + // commit this as a separate crop immediately so that further crops are + // working on an image that isn't weirdly rotated. Or keep the + // straighten-crop as a separate operation from an ordinary crop. + int left = (int) Math.Ceiling(xCoords[1]); + int right = (int) Math.Floor(xCoords[2]); + int top = (int) Math.Ceiling(yCoords[1]); + int bottom = (int) Math.Floor(yCoords[2]); + + photo.CropRectangle = Rectangle.FromLTRB(left, top, right, bottom); + return ToolStatus.Done; } @@ -377,6 +407,12 @@ public static class Util { return result; } + public static Vector2 RotateAboutCenter(Vector2 vec, Vector2 center, Matrix2 transform) { + Vector2 centerRelative = vec - center; + centerRelative *= transform; + return centerRelative + center; + } + public static Image MakeImage(float width, float height) { return new((int) Math.Ceiling(width), (int) Math.Ceiling(height)); } @@ -1158,20 +1194,14 @@ public class Game : GameWindow { GL.Viewport(0, 0, e.Width, e.Height); } - private Vector2 RotateAboutCenter(Vector2 vec, Vector2 center, Matrix2 transform) { - Vector2 centerRelative = vec - center; - centerRelative *= transform; - return centerRelative + center; - } - private void SetVertices(float left, float top, float width, float height, float rotationDegrees) { Matrix2 transform = Matrix2.CreateRotation(MathHelper.DegreesToRadians(rotationDegrees)); Vector2 center = new(left + width / 2, top + height / 2); - Vector2 topLeft = RotateAboutCenter(new Vector2(left, top), center, transform); - Vector2 topRight = RotateAboutCenter(new Vector2(left + width, top), center, transform); - Vector2 bottomRight = RotateAboutCenter(new Vector2(left + width, top + height), center, transform); - Vector2 bottomLeft = RotateAboutCenter(new Vector2(left, top + height), center, transform); + Vector2 topLeft = Util.RotateAboutCenter(new Vector2(left, top), center, transform); + Vector2 topRight = Util.RotateAboutCenter(new Vector2(left + width, top), center, transform); + Vector2 bottomRight = Util.RotateAboutCenter(new Vector2(left + width, top + height), center, transform); + Vector2 bottomLeft = Util.RotateAboutCenter(new Vector2(left, top + height), center, transform); // top left vertices[0] = topLeft.X;