locked
Picturebox rotation RRS feed

  • Question

  • I have been trying for some time to rotate the image in a picturebox without success.

    I have looked at the RotateFlip function but it is useless as I need to rotate the image by a user-specified number of degrees. After lots of looking I came across the following code in a reply to this forum.....

    Private Sub Rotation(sender As Object, e As PaintEventArgs) Handles PictureBox1.Paint
            With e.Graphics
                .TranslateTransform(PictureBox1.Width \ 2, PictureBox1.Height \ 2)
                .RotateTransform(dgr)
                .DrawImage(PictureBox1.Image, (-PictureBox1.Width \ 2), (-PictureBox1.Height \ 2))
            End With    
    End Sub

    This code almost works. The problem I get is that it leaves behind the original image so I end up seeing the original image with the rotated version on top of it.

    I have no idea why this happens, nor how to fix it. Can anyone help please?


    • Edited by Ib51 Friday, March 30, 2018 8:53 PM
    Friday, March 30, 2018 8:52 PM

All replies

  • This should not be happening in the Paint method - the Paint method is where you render the image, not manipulate it.

    In this case you need to create a new (rotated) image from the original, then render it in the paint event.  The example below uses the picture box image as the source for the image to rotate - your source might be different.

        Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
            Dim BMP As New Bitmap(PictureBox1.Width, PictureBox1.Height)
            Dim g As Graphics = Graphics.FromImage(BMP)
            With g
                .TranslateTransform(PictureBox1.Width \ 2, PictureBox1.Height \ 2)
                .RotateTransform(dgr)
                .DrawImage(PictureBox1.Image, (-PictureBox1.Width \ 2), (-PictureBox1.Height \ 2))
            End With
            PictureBox1.Image = BMP
        End Sub
    • Proposed as answer by Reed KimbleMVP Friday, March 30, 2018 10:08 PM
    Friday, March 30, 2018 9:08 PM
  • Note that you cannot rotate the PicutreBox itself, but rather, must rotate the image within the PictureBox.

    When it comes to rotation and more advanced drawing features, it quickly becomes better to create your own custom control and custom drawing objects - then you can do anything you want.

    You might want to review the sample code I recently provided in this thread.


    Reed Kimble - "When you do things right, people won't be sure you've done anything at all"

    Friday, March 30, 2018 10:08 PM
  • WPF has controls that can be rotated, Windows Forms does not unless you write a custom control perhaps. So the answer is as Acamar posts really.

    La vida loca

    Saturday, March 31, 2018 12:06 AM
  • Thanks for your reply.  As I said, the code is from a reply to an earlier thread on this forum, not mine, so at least one other person thinks it should be done in the paint event.

    I have tried your suggested code and it does solve the problem of leaving behind the original image, but it has another issue which was also probably in the original code.  If I rotate it a complete turn I end up with a round image in the picturebox.  This must be because BMP is created the same size as the image but when the image rotates its' dimensions change so its' height and width are the diagonal length of the rectangle.  I'm going to have to calculate a new size for BMP based on the diagonal of the original, unrotated, image.

    Saturday, March 31, 2018 3:13 PM
  • Thanks for your reply.  As I said, the code is from a reply to an earlier thread on this forum, not mine, so at least one other person thinks it should be done in the paint event.

    I have tried your suggested code and it does solve the problem of leaving behind the original image, but it has another issue which was also probably in the original code.  If I rotate it a complete turn I end up with a round image in the picturebox.  This must be because BMP is created the same size as the image but when the image rotates its' dimensions change so its' height and width are the diagonal length of the rectangle.  I'm going to have to calculate a new size for BMP based on the diagonal of the original, unrotated, image.

    The problem is you are doing it upside down and backwards.

    Don't put the original in the picturebox.image property (if you want to use the paint event to draw). Do it like this example. See where I read the image in the declare? Then I draw that image in the paint event rotated and scaled. First I translate the origin to the center of the image so it rotates about the center.

    https://social.technet.microsoft.com/wiki/contents/articles/31270.vb-net-size-and-rotate-images-using-matrix-transforms-in-gdi.aspx

    Public Class Form8
        Private MyPicBmp As New Bitmap("c:\bitmaps\rusty.jpg")
    
        Private Sub PictureBox1_Paint(sender As Object, e As PaintEventArgs) Handles PictureBox1.Paint
    
            With e.Graphics
                .Clear(Color.Black)
                .TranslateTransform(CSng(MyPicBmp.Width / 2), CSng(MyPicBmp.Height / 2))
                .RotateTransform(45)
                .ScaleTransform(0.5, 0.5)
                .DrawImage(MyPicBmp, CSng(-MyPicBmp.Width / 2), CSng(-MyPicBmp.Height / 2))
            End With
    
        End Sub
    End Class


    PS The system paints the image in the picturebox.image property first, then it calls the paint event and any drawing in that event sub is added on top of the .image or .backgroundimage layers. Then finally its all combined and shown on the screen.

    So that is what you see, a smear, of whatever you did exactly. Plus you have to rotate about the origin (0,0) or you get a global moment arm rotation effect not sure what its called I think you described it.

    Saturday, March 31, 2018 3:28 PM
  • If I rotate it a complete turn I end up with a round image in the picturebox.

    That is because BMP is created from the image in the picturebox.  That's why I commented that your source for the image might be different.  The picturebox image is what you display, but the source image for the rotation is likely different - probably an image file, or perhaps a resource.  Note that when you use the original for the rotation you do not do the same rotation each time - you increment dgr by the required amount, and you apply the accumulated total rotation to the original image.

    Saturday, March 31, 2018 8:41 PM