''' <summary>
''' Returns a new copy of the bitmap passed in. The new copy is rotated
''' to the specified degree and resized to fit its new bounding box.
''' </summary>
''' <remarks>
''' The Original Bitmap should be the bitmap that has never been rotated.
''' If you keep rotating the same image the image will become distorted.
''' </remarks>
Private Function RotateAndResize(ByRef Original_Bitmap As Bitmap, ByRef Angle As Double) As Bitmap
'First store our original points into an array so we can pass
'them to the matrix to get our new rotated points.
Dim BoxCorners As Point() = {New Point(0, 0), _
New Point(Original_Bitmap.Width, 0), _
New Point(Original_Bitmap.Width, Original_Bitmap.Height), _
New Point(0, Original_Bitmap.Height)}
Dim M As New Matrix
'Apply a rotation transform and rotate our original corners.
M.RotateAt(Angle, New PointF(Original_Bitmap.Width / 2, Original_Bitmap.Height / 2))
M.TransformPoints(BoxCorners)
'Now get the size of the new box.
Dim left, right, top, bottom As Integer
For i = 0 To UBound(BoxCorners)
If BoxCorners(i).X < left Then
left = BoxCorners(i).X
ElseIf BoxCorners(i).X > right Then
right = BoxCorners(i).X
End If
If BoxCorners(i).Y < top Then
top = BoxCorners(i).Y
ElseIf BoxCorners(i).Y > bottom Then
bottom = BoxCorners(i).Y
End If
Next
'Initialize a new bitmap, get the new x and y start cooridinates which
'is half the of new box size - the old box size, set the
'graphics object to the new image.
Dim RotatedBitmap = New Bitmap(right - left, bottom - top)
Dim x As Integer = Math.Abs(RotatedBitmap.Width - Original_Bitmap.Width) / 2
Dim y As Integer = Math.Abs(RotatedBitmap.Height - Original_Bitmap.Height) / 2
Dim g As Graphics = Graphics.FromImage(RotatedBitmap)
'reset the matrix, rotate it to our new box: set the graphics tranform, and
'draw the image.
M.Reset()
M.RotateAt(Angle, New PointF(RotatedBitmap.Width / 2, RotatedBitmap.Height / 2))
g.Transform = M
g.DrawImage(Original_Bitmap, New Rectangle(x, y, Original_Bitmap.Width, Original_Bitmap.Height))
M.Dispose()
g.Dispose()
'Our new rotated and resized bitmap.
Return RotatedBitmap
End Function Dani AI
Generated
Good baseline — 's approach of transforming the four image corners and using that bounding box to create a new Bitmap is the correct high-level method for arbitrary-angle rotation. The original 90–270 problem is a common symptom when min/max variables are left uninitialized or when integer rounding drops needed precision. Switching the corner array to PointF, normalizing the angle, and preserving the original image's resolution and pixel format make the result more robust and higher quality.
Practical, non-invasive improvements:
- Use PointF for corner coordinates so the Matrix's float results are not truncated before computing min/max.
- Preserve source resolution and pixel format on the new bitmap:
Dim rotated = New Bitmap(width, height, original.PixelFormat) rotated.SetResolution(original.HorizontalResolution, original.VerticalResolution) - Prefer Using blocks for Graphics/Matrix to ensure disposal (avoid manual Dispose calls scattered through code).
- Short-circuit exact multiples of 90° with Image.RotateFlip for a lossless, faster path. Normalize the angle (Angle = ((Angle Mod 360) + 360) Mod 360) before testing.
Quality, alpha, and performance notes:
- For best visual results set Graphics.InterpolationMode, SmoothingMode and PixelOffsetMode appropriately (e.g., HighQualityBicubic for photos). Clear the destination with Color.Transparent when using alpha-backed PixelFormats.
- Avoid ByRef for the input Bitmap/Angle unless intentional; return a new Bitmap and let callers dispose of unused Bitmaps.
- Remember to round offsets consistently (Math.Round / Math.Floor) when converting float positions to integer pixel coordinates to avoid off-by-one shifts.
These changes keep the same algorithm while fixing edge cases, preserving image metadata, and reducing subtle artifacts.
Member #857553
Edit.
I made this for no reason. Turns out I needed it. After putting it to the test it has some issues. It doesn't work for angles 90 - 270.
This fixes it.
Private Function RotateAndResize(ByRef Original_Bitmap As Bitmap, ByRef Angle As Double) As Bitmap
Dim BoxCorners As Point() = {New Point(0, 0), _
New Point(Original_Bitmap.Width, 0), _
New Point(Original_Bitmap.Width, Original_Bitmap.Height), _
New Point(0, Original_Bitmap.Height)}
Dim M As New Matrix
M.RotateAt(Angle, New PointF(Original_Bitmap.Width / 2, Original_Bitmap.Height / 2))
M.TransformPoints(BoxCorners)
Dim left As Integer = Integer.MaxValue
Dim right As Integer = Integer.MinValue
Dim top As Integer = Integer.MaxValue
Dim bottom As Integer = Integer.MinValue
For i = 0 To UBound(BoxCorners)
If BoxCorners(i).X < left Then left = BoxCorners(i).X
If BoxCorners(i).X > right Then right = BoxCorners(i).X
If BoxCorners(i).Y < top Then top = BoxCorners(i).Y
If BoxCorners(i).Y > bottom Then bottom = BoxCorners(i).Y
Next
Dim RotatedBitmap = New Bitmap(right - left, bottom - top)
Dim x As Integer = (RotatedBitmap.Width - Original_Bitmap.Width) / 2
Dim y As Integer = (RotatedBitmap.Height - Original_Bitmap.Height) / 2
Dim g As Graphics = Graphics.FromImage(RotatedBitmap)
M.Reset()
M.RotateAt(Angle, New PointF(RotatedBitmap.Width / 2, RotatedBitmap.Height / 2))
g.Transform = M
g.DrawImage(Original_Bitmap, New Rectangle(x, y, Original_Bitmap.Width, Original_Bitmap.Height))
M.Dispose()
g.Dispose()
Return RotatedBitmap
End Function Be a part of the DaniWeb community
We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.