locked
how to rotate a picture object? RRS feed

  • Question

  • I have two images on top of an image on a form, let's call them Image2 and Image3 that I would like to rotate by degrees with command buttons, let's call them Image2R , Image2L, Image3R , Image3L I would prefer to just rotate the object and not redraw an image, and return that value to a text box so when I come back to that record it gives me that data and rotation, Thanks in advance for any help
    Monday, January 14, 2013 3:08 PM

Answers

  • Public Class Form1
        Private _Image1 As Image = SystemIcons.Application.ToBitmap
        Private _Image2 As Image = SystemIcons.Shield.ToBitmap
        Private _Image1Location As New Point(10, 10)
        Private _Image2Location As New Point(60, 60)
        Private _Image1Angle As Single
        Private _Image2Angle As Single
     
        Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
            Me.DoubleBuffered = True
        End Sub
     
        Protected Overrides Function IsInputKey(keyData As System.Windows.Forms.Keys) As Boolean
            Select Case keyData
                Case Keys.Left, Keys.Right
                    Return True
                Case Else
                    Return MyBase.IsInputKey(keyData)
            End Select
        End Function
     
        Protected Overrides Sub OnKeyDown(e As System.Windows.Forms.KeyEventArgs)
            MyBase.OnKeyDown(e)
            Select Case e.KeyCode
                Case Keys.Left
                    _Image1Angle += 2
                    If _Image1Angle > 360 Then
                        _Image1Angle -= 360
                    End If
                    _Image2Angle += 3
                    If _Image2Angle > 360 Then
                        _Image2Angle -= 360
                    End If
                Case Keys.Right
                    _Image1Angle -= 2
                    If _Image1Angle < 0 Then
                        _Image1Angle += 360
                    End If
                    _Image2Angle -= 3
                    If _Image2Angle < 0 Then
                        _Image2Angle += 360
                    End If
            End Select
            Invalidate()
        End Sub
     
        Protected Overrides Sub OnPaint(e As System.Windows.Forms.PaintEventArgs)
            MyBase.OnPaint(e)
     
            Dim bounds1 As New Rectangle(_Image1Location, _Image1.Size)
            Dim bounds2 As New Rectangle(_Image2Location, _Image2.Size)
     
            e.Graphics.SmoothingMode = Drawing2D.SmoothingMode.AntiAlias
            e.Graphics.PixelOffsetMode = Drawing2D.PixelOffsetMode.HighQuality
     
    
            e.Graphics.TranslateTransform(bounds1.X + (bounds1.Width / 2), bounds1.Y + (bounds1.Height / 2))
            e.Graphics.RotateTransform(_Image1Angle)
            e.Graphics.TranslateTransform(-(bounds1.X + (bounds1.Width / 2)), -(bounds1.Y + (bounds1.Height / 2)))
            e.Graphics.DrawImage(_Image1, _Image1Location)
     
            e.Graphics.ResetTransform()
     
            e.Graphics.TranslateTransform(bounds2.X + (bounds2.Width / 2), bounds2.Y + (bounds2.Height / 2))
            e.Graphics.RotateTransform(_Image2Angle)
            e.Graphics.TranslateTransform(-(bounds2.X + (bounds2.Width / 2)), -(bounds2.Y + (bounds2.Height / 2)))
            e.Graphics.DrawImage(_Image2, _Image2Location)
        End Sub
    End Class
     


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

    • Proposed as answer by Paul Ishak Tuesday, January 15, 2013 8:02 PM
    • Marked as answer by Paul Ishak Friday, January 18, 2013 2:52 AM
    Monday, January 14, 2013 4:20 PM
  • Hi cdnnewbie

    If you can define the upperLeft, upperRight, and lowerLeft points using maths, you can cast the image using the "destinationPoints" method. I was interested to see how it would perform - so I made this little example program. Please try it.

    The key lines of code that reveal this method are: -

    Dim destinationPoints As Point() = {UL, UR, LL}

    e.Graphics.DrawImage(BM, destinationPoints)

    Public Class Form9
        Dim IW, IH As Integer ' image width and height
        Dim CP As Point ' image centre point
        Dim D As Single ' degrees offset of image
        Dim BM, BG As Bitmap
        Dim T As Font
        Dim UL, UR, LL As Point 'upperleft, upperright and lowerleft points to cast image
        Dim R(2) As Double ' for use in maths
    
        Private Sub Form9_Load(sender As Object, e As System.EventArgs) Handles Me.Load
    
            'make an image for the sake of this exercise
            IW = 180 : IH = 100
            BM = New Bitmap(IW, IH)
            Dim GR As Graphics
            GR = Graphics.FromImage(BM)
            Dim C(2) As Color
            C(0) = Color.FromArgb(180, 180, 120)
            C(1) = Color.FromArgb(180, 120, 180)
            C(2) = Color.FromArgb(128, 0, 0, 0)
            Dim grbrsh As New Drawing2D.LinearGradientBrush(New Rectangle(30, 17, 120, 67), _
            C(0), C(1), Drawing2D.LinearGradientMode.Horizontal)
            GR.FillRectangle(New SolidBrush(C(2)), New Rectangle(0, 0, 180, 100))
            GR.FillEllipse(grbrsh, New Rectangle(30, 17, 120, 67))
            T = New Font("Courier New", 28, FontStyle.Regular, GraphicsUnit.Pixel)
            GR.DrawString("Opal", T, Brushes.White, 52, 34)
            GR.DrawString("Opal", T, Brushes.Black, 54, 36)
            GR.DrawRectangle(Pens.Black, 0, 0, 179, 99)
    
            ' make background image for the sake of this exercise
            BG = New Bitmap(90, 60)
            GR = Graphics.FromImage(BG)
            C(0) = Color.FromArgb(0, 0, 80)
            C(1) = Color.FromArgb(255, 170, 70)
            grbrsh = New Drawing2D.LinearGradientBrush(New Rectangle(0, 0, 90, 60), _
            C(0), C(1), Drawing2D.LinearGradientMode.Horizontal)
            GR.FillRectangle(grbrsh, New Rectangle(0, 0, 90, 60))
            GR.DrawLine(Pens.Red, 40, 0, 40, 59)
            GR.DrawLine(Pens.Yellow, 50, 0, 50, 59)
            GR.DrawLine(Pens.Blue, 0, 25, 89, 25)
            GR.DrawLine(Pens.White, 0, 35, 89, 35)
            GR.Dispose() : grbrsh.Dispose() : ReDim C(0)
    
            ' set form details
            Me.Width = 606 : Me.Height = 428
            Me.DoubleBuffered = True
            Me.BackgroundImageLayout = ImageLayout.Stretch
            Me.BackgroundImage = BG
            Me.KeyPreview = True
            CP.X = 300 : CP.Y = 200
    
            'preparing vectors to destination points 
            R(0) = -Math.Atan(IW / IH)  'direction to UL
            R(1) = Math.Sqrt(IW ^ 2 + IH ^ 2) / 2 'distance to UL
        End Sub
    
        Private Sub Form9_KeyDown(sender As Object, e As System.Windows.Forms.KeyEventArgs) Handles Me.KeyDown
            Select Case e.KeyCode
                Case Keys.Left
                    D -= 3.75F
                Case Keys.Right
                    D += 3.75F
            End Select
            e.Handled = True
            If D < -180 Then D += 360
            If D > 180 Then D -= 360
            Me.Invalidate()
        End Sub
    
        Private Sub Form9_Paint(sender As Object, e As System.Windows.Forms.PaintEventArgs) Handles Me.Paint
            e.Graphics.DrawString(Format(D, "##0.#") & Chr(176), T, Brushes.Black, 470, 20)
            R(2) = R(0) + (Math.PI * D / 180)
            UL.X = CP.X + CInt(Math.Sin(R(2)) * R(1))
            UL.Y = CP.Y - CInt(Math.Cos(R(2)) * R(1))
            R(2) = -R(0) + (Math.PI * D / 180)
            UR.X = CP.X + CInt(Math.Sin(R(2)) * R(1))
            UR.Y = CP.Y - CInt(Math.Cos(R(2)) * R(1))
            R(2) = Math.PI - R(0) + (Math.PI * D / 180)
            LL.X = CP.X + CInt(Math.Sin(R(2)) * R(1))
            LL.Y = CP.Y - CInt(Math.Cos(R(2)) * R(1))
            Dim destinationPoints As Point() = {UL, UR, LL}
            e.Graphics.DrawImage(BM, destinationPoints)
        End Sub
    End Class


    Leon C Stanley - - A dinky di VB'er - -

    • Proposed as answer by Paul Ishak Tuesday, January 15, 2013 8:02 PM
    • Marked as answer by Paul Ishak Friday, January 18, 2013 2:53 AM
    Tuesday, January 15, 2013 10:37 AM

All replies

  • What part do you need help with?

    Note that an "image" can't be "on a form".  You can have a PictureBox or
    other control on a form, and that control can display an image.  Or you can draw
    the image to the form in the form's paint event (or OnPaint override).

    Since you can't rotate a control, you'll need to draw the image rotated using
    GDI and a matrix transformation.  Where you do the drawing depends on how you
    display the image.  You will either do the drawing directly on the form, or you
    will do it within another control.

    You will have to explain how "records" and "data" relate to the program (how
    do you relate a record to an image? what data does the record specify about the
    image)?


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

    Monday, January 14, 2013 3:41 PM
  • If they are in a picturebox, or an image type in general, I know you can flip and turn(rotate) images, you don't have to do both, you can do a flip or rotate, or both.  However, it only works in 90 degrees intervals.

    This is how.

    PictureBox1.Image.RotateFlip()

    It works with any image...if you need more rotations that aren't at 90 degrees intervals, I don't have the answer, maybe someone else can help, but even so, rotating at any other degrees makes things look distorted normally, on other apps that can do it, as it doesn't know where to place the pixels since it's no longer square, and usually don't do such a good job displaying it anymore.
    Monday, January 14, 2013 3:58 PM
  • Public Class Form1
        Private _Image1 As Image = SystemIcons.Application.ToBitmap
        Private _Image2 As Image = SystemIcons.Shield.ToBitmap
        Private _Image1Location As New Point(10, 10)
        Private _Image2Location As New Point(60, 60)
        Private _Image1Angle As Single
        Private _Image2Angle As Single
     
        Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
            Me.DoubleBuffered = True
        End Sub
     
        Protected Overrides Function IsInputKey(keyData As System.Windows.Forms.Keys) As Boolean
            Select Case keyData
                Case Keys.Left, Keys.Right
                    Return True
                Case Else
                    Return MyBase.IsInputKey(keyData)
            End Select
        End Function
     
        Protected Overrides Sub OnKeyDown(e As System.Windows.Forms.KeyEventArgs)
            MyBase.OnKeyDown(e)
            Select Case e.KeyCode
                Case Keys.Left
                    _Image1Angle += 2
                    If _Image1Angle > 360 Then
                        _Image1Angle -= 360
                    End If
                    _Image2Angle += 3
                    If _Image2Angle > 360 Then
                        _Image2Angle -= 360
                    End If
                Case Keys.Right
                    _Image1Angle -= 2
                    If _Image1Angle < 0 Then
                        _Image1Angle += 360
                    End If
                    _Image2Angle -= 3
                    If _Image2Angle < 0 Then
                        _Image2Angle += 360
                    End If
            End Select
            Invalidate()
        End Sub
     
        Protected Overrides Sub OnPaint(e As System.Windows.Forms.PaintEventArgs)
            MyBase.OnPaint(e)
     
            Dim bounds1 As New Rectangle(_Image1Location, _Image1.Size)
            Dim bounds2 As New Rectangle(_Image2Location, _Image2.Size)
     
            e.Graphics.SmoothingMode = Drawing2D.SmoothingMode.AntiAlias
            e.Graphics.PixelOffsetMode = Drawing2D.PixelOffsetMode.HighQuality
     
    
            e.Graphics.TranslateTransform(bounds1.X + (bounds1.Width / 2), bounds1.Y + (bounds1.Height / 2))
            e.Graphics.RotateTransform(_Image1Angle)
            e.Graphics.TranslateTransform(-(bounds1.X + (bounds1.Width / 2)), -(bounds1.Y + (bounds1.Height / 2)))
            e.Graphics.DrawImage(_Image1, _Image1Location)
     
            e.Graphics.ResetTransform()
     
            e.Graphics.TranslateTransform(bounds2.X + (bounds2.Width / 2), bounds2.Y + (bounds2.Height / 2))
            e.Graphics.RotateTransform(_Image2Angle)
            e.Graphics.TranslateTransform(-(bounds2.X + (bounds2.Width / 2)), -(bounds2.Y + (bounds2.Height / 2)))
            e.Graphics.DrawImage(_Image2, _Image2Location)
        End Sub
    End Class
     


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

    • Proposed as answer by Paul Ishak Tuesday, January 15, 2013 8:02 PM
    • Marked as answer by Paul Ishak Friday, January 18, 2013 2:52 AM
    Monday, January 14, 2013 4:20 PM
  • Hi cdnnewbie

    If you can define the upperLeft, upperRight, and lowerLeft points using maths, you can cast the image using the "destinationPoints" method. I was interested to see how it would perform - so I made this little example program. Please try it.

    The key lines of code that reveal this method are: -

    Dim destinationPoints As Point() = {UL, UR, LL}

    e.Graphics.DrawImage(BM, destinationPoints)

    Public Class Form9
        Dim IW, IH As Integer ' image width and height
        Dim CP As Point ' image centre point
        Dim D As Single ' degrees offset of image
        Dim BM, BG As Bitmap
        Dim T As Font
        Dim UL, UR, LL As Point 'upperleft, upperright and lowerleft points to cast image
        Dim R(2) As Double ' for use in maths
    
        Private Sub Form9_Load(sender As Object, e As System.EventArgs) Handles Me.Load
    
            'make an image for the sake of this exercise
            IW = 180 : IH = 100
            BM = New Bitmap(IW, IH)
            Dim GR As Graphics
            GR = Graphics.FromImage(BM)
            Dim C(2) As Color
            C(0) = Color.FromArgb(180, 180, 120)
            C(1) = Color.FromArgb(180, 120, 180)
            C(2) = Color.FromArgb(128, 0, 0, 0)
            Dim grbrsh As New Drawing2D.LinearGradientBrush(New Rectangle(30, 17, 120, 67), _
            C(0), C(1), Drawing2D.LinearGradientMode.Horizontal)
            GR.FillRectangle(New SolidBrush(C(2)), New Rectangle(0, 0, 180, 100))
            GR.FillEllipse(grbrsh, New Rectangle(30, 17, 120, 67))
            T = New Font("Courier New", 28, FontStyle.Regular, GraphicsUnit.Pixel)
            GR.DrawString("Opal", T, Brushes.White, 52, 34)
            GR.DrawString("Opal", T, Brushes.Black, 54, 36)
            GR.DrawRectangle(Pens.Black, 0, 0, 179, 99)
    
            ' make background image for the sake of this exercise
            BG = New Bitmap(90, 60)
            GR = Graphics.FromImage(BG)
            C(0) = Color.FromArgb(0, 0, 80)
            C(1) = Color.FromArgb(255, 170, 70)
            grbrsh = New Drawing2D.LinearGradientBrush(New Rectangle(0, 0, 90, 60), _
            C(0), C(1), Drawing2D.LinearGradientMode.Horizontal)
            GR.FillRectangle(grbrsh, New Rectangle(0, 0, 90, 60))
            GR.DrawLine(Pens.Red, 40, 0, 40, 59)
            GR.DrawLine(Pens.Yellow, 50, 0, 50, 59)
            GR.DrawLine(Pens.Blue, 0, 25, 89, 25)
            GR.DrawLine(Pens.White, 0, 35, 89, 35)
            GR.Dispose() : grbrsh.Dispose() : ReDim C(0)
    
            ' set form details
            Me.Width = 606 : Me.Height = 428
            Me.DoubleBuffered = True
            Me.BackgroundImageLayout = ImageLayout.Stretch
            Me.BackgroundImage = BG
            Me.KeyPreview = True
            CP.X = 300 : CP.Y = 200
    
            'preparing vectors to destination points 
            R(0) = -Math.Atan(IW / IH)  'direction to UL
            R(1) = Math.Sqrt(IW ^ 2 + IH ^ 2) / 2 'distance to UL
        End Sub
    
        Private Sub Form9_KeyDown(sender As Object, e As System.Windows.Forms.KeyEventArgs) Handles Me.KeyDown
            Select Case e.KeyCode
                Case Keys.Left
                    D -= 3.75F
                Case Keys.Right
                    D += 3.75F
            End Select
            e.Handled = True
            If D < -180 Then D += 360
            If D > 180 Then D -= 360
            Me.Invalidate()
        End Sub
    
        Private Sub Form9_Paint(sender As Object, e As System.Windows.Forms.PaintEventArgs) Handles Me.Paint
            e.Graphics.DrawString(Format(D, "##0.#") & Chr(176), T, Brushes.Black, 470, 20)
            R(2) = R(0) + (Math.PI * D / 180)
            UL.X = CP.X + CInt(Math.Sin(R(2)) * R(1))
            UL.Y = CP.Y - CInt(Math.Cos(R(2)) * R(1))
            R(2) = -R(0) + (Math.PI * D / 180)
            UR.X = CP.X + CInt(Math.Sin(R(2)) * R(1))
            UR.Y = CP.Y - CInt(Math.Cos(R(2)) * R(1))
            R(2) = Math.PI - R(0) + (Math.PI * D / 180)
            LL.X = CP.X + CInt(Math.Sin(R(2)) * R(1))
            LL.Y = CP.Y - CInt(Math.Cos(R(2)) * R(1))
            Dim destinationPoints As Point() = {UL, UR, LL}
            e.Graphics.DrawImage(BM, destinationPoints)
        End Sub
    End Class


    Leon C Stanley - - A dinky di VB'er - -

    • Proposed as answer by Paul Ishak Tuesday, January 15, 2013 8:02 PM
    • Marked as answer by Paul Ishak Friday, January 18, 2013 2:53 AM
    Tuesday, January 15, 2013 10:37 AM
  • You cannot rotate an object in the sense of .Net (and therefore VB)

    An object is just a placeholder for an address in .Net

    http://msdn.microsoft.com/en-us/library/system.object.aspx

     Therefore methods in controls which rotates are in fact redrawing the presentation of the image, not the image itself. 

    Be aware (forum bug)you ask for forms, but forms is not the desktop presentation way of Microsoft anymore. For Windows 8 App programming for instance it is XAML (WPF) 

    For those searching for answer on that:

    http://msdn.microsoft.com/en-us/library/windows/desktop/ms535401(v=vs.85).aspx


    Success
    Cor

    Tuesday, January 15, 2013 12:40 PM
  • this looks like it will do what I want, I would like to try it but I am naive to the fact as where this code goes. I copied it to the form, but I got errors

    Thanks so much for being patient

    Morris

    Tuesday, January 15, 2013 4:13 PM
  • You probably need to define the errors you received and post them so peeps can understand what the problem is. Obviously that code needs to be renamed for the Form name you are using.

    You've taught me everything I know but not everything you know.

    Tuesday, January 15, 2013 7:19 PM
  • That's what the matrix transformations are for... 

    All you do is call TranslateTransform on the Graphics object to put the origin at the center of the destination bounds for the image, then call RotateTransform to rotate the graphics by the degrees desired, and finally call TranslateTransform one more time to put the origin back at the upper-left.  Then you just draw your image as normal onto the rotated surface.  You technically can skip the last transformation if you account for the new origin when determining where to draw the image.

    If you are going to do a number of different transformations for different painting operations then you can create instances of Matrix, adjust each as required, and then apply each to the graphics object as needed.


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

    Tuesday, January 15, 2013 7:47 PM
  • Perhaps you could just concentrate on these two lines: -

    Dim destinationPoints As Point() = {UL, UR, LL}

    e.Graphics.DrawImage(BM, destinationPoints)

    Write a small program yourself and experiment to see what it can do.

    The other methods are also well worth experimenting with - the TranslateTransform method.


    Leon C Stanley - - A dinky di VB'er - -

    Tuesday, January 15, 2013 11:04 PM