Click here to Skip to main content
15,916,215 members
Please Sign up or sign in to vote.
2.00/5 (1 vote)
See more:
I want to rotate an image in a picturebox then add it to a panel (so I can put multiple images on the panel). The problem is it always makes the image (area around the image) larger.

My code I found to rotate

VB
Dim bm_in As New Bitmap(PictureBox1.Image)

        ' Make an array of points defining the
        ' image's corners.
        Dim wid As Single = bm_in.Width
        Dim hgt As Single = bm_in.Height
        Dim corners As Point() = { _
            New Point(0, 0), _
            New Point(wid, 0), _
            New Point(0, hgt), _
            New Point(wid, hgt)}

        ' Translate to center the bounding box at the origin.
        Dim cx As Single = wid / 2
        Dim cy As Single = hgt / 2
        Dim i As Long
        For i = 0 To 3
            corners(i).X -= cx
            corners(i).Y -= cy
        Next i

        ' Rotate.
        Dim theta As Single = Single.Parse(5) * PI / 180.0
        Dim sin_theta As Single = Sin(theta)
        Dim cos_theta As Single = Cos(theta)
        Dim X As Single
        Dim Y As Single
        For i = 0 To 3
            X = corners(i).X
            Y = corners(i).Y
            corners(i).X = X * cos_theta + Y * sin_theta
            corners(i).Y = -X * sin_theta + Y * cos_theta
        Next i

        ' Translate so X >= 0 and Y >=0 for all corners.
        Dim xmin As Single = corners(0).X
        Dim ymin As Single = corners(0).Y
        For i = 1 To 3
            If xmin > corners(i).X Then xmin = corners(i).X
            If ymin > corners(i).Y Then ymin = corners(i).Y
        Next i
        For i = 0 To 3
            corners(i).X -= xmin
            corners(i).Y -= ymin
        Next i

        ' Create an output Bitmap and Graphics object.
        Dim bm_out As New Bitmap(CInt(-2 * xmin), CInt(-2 * ymin))
        Dim gr_out As Graphics = Graphics.FromImage(bm_out)

        ' Drop the last corner lest we confuse DrawImage,
        ' which expects an array of three corners.
        ReDim Preserve corners(2)

        ' Draw the result onto the output Bitmap.
        gr_out.DrawImage(bm_in, corners)

        ' Display the result.
        PictureBox1.Image = bm_out
Posted

Use a Panel instead of a PictureBox, and then add images to the Panel. Override the panel's Paint event handler, and use the e.Graphics.RotateTransform method to rotate the image.
 
Share this answer
 
Comments
wiswalld 17-Dec-11 11:30am    
I am not sure how to use the e.Graphics.RotateTransform method. I have been researching it all morning but all examples add some text or lines. Kinda new at this graphics stuff.
wiswalld 17-Dec-11 11:31am    
and do you mean use a panel as the source because now I use a picture box as the source then rotate then add the image to the panel
Sergey Alexandrovich Kryukov 18-Dec-11 14:50pm    
No! You don't need a picture box.
--SA
Sergey Alexandrovich Kryukov 18-Dec-11 14:54pm    
I added my answer to clarify things, please see.
--SA
Sergey Alexandrovich Kryukov 18-Dec-11 14:49pm    
That would work, but it's even better to use a class based on Control. Panel probably does not add any useful functionality. Inheritance is needed anyway, to access protected SetStyle. My 4.
--SA
This is another example of misuse of PictureBox. This class does not add any functionality, will only add hassles and unwanted resource consumption.
I tried to explain what to do in my past solution How do I clear a panel from old drawing[^].

See also the following answer explaining some of the required techniques:
What kind of playful method is Paint? (DataGridViewImageCell.Paint(...))[^],
Drawing Lines between mdi child forms[^],
capture the drawing on a panel[^].

—SA
 
Share this answer
 
Comments
wiswalld 20-Dec-11 12:33pm    
Here is what I have come up with but I cannot figure out how to use the bitmap as the sourcePB

Public Class Form1
Dim imagetwo As Bitmap
Dim angle As Integer = 0


Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
SetStyle(ControlStyles.DoubleBuffer, True)
SetStyle(ControlStyles.AllPaintingInWmPaint, True)
'imagetwo = New Bitmap("C:\Documents and Settings\wiswalld\My Documents\DEP Police Patch.bmp")
imagetwo = New Bitmap(PictureBox1.Image)
imagetwo.MakeTransparent(Color.Black)
'gameloop.start()

WirePBs(Me)
Dim mi As New MenuItem("Delete")
AddHandler mi.Click, AddressOf mi_Click
cm.MenuItems.Add(mi)
For Each ctl As Control In Me.Controls
If TypeOf ctl Is PictureBox Then
AddHandler ctl.Click, AddressOf sourcePB_Click
End If
Next
End Sub

Private Sub gameloop_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles gameloop.Tick
angle += 5
Me.Refresh()
End Sub

Private Sub Form1_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles Me.Paint
e.Graphics.TranslateTransform(90, 90)
e.Graphics.RotateTransform(angle)
e.Graphics.DrawImage(imagetwo, -50, -50, 100, 100)
e.Graphics.ResetTransform()
End Sub

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Me.angle += 5
Me.Refresh()
End Sub

Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
Me.PictureBox1.Image = New Bitmap("C:\Documents and Settings\wiswalld\My Documents\DEP Police Patch.bmp")
imagetwo = New Bitmap(PictureBox1.Image)
imagetwo.MakeTransparent(Color.Black)
End Sub


Private Sub Button1_MouseWheel(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Button1.MouseWheel
Me.angle += 5
Me.Refresh()
End Sub



Private pb As PictureBox = Nothing
Dim currentPicBox As PictureBox
Private cm As New ContextMenu()
Private targetPB As PictureBox
Private Sub WirePBs(ByVal cont As Control)
For Each ctl As Control In cont.Controls
If TypeOf ctl Is PictureBox Then
Dim pb As PictureBox = DirectCast(ctl, PictureBox)
'sizers.Add(New PBsizer(pb, pb.Parent))
ElseIf ctl.HasChildren Then
WirePBs(ctl)
End If
Next
End Sub
Private startX, startY As Integer

Private Sub targetPB_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs)
If e.Button = Windows.Forms.MouseButtons.Left Then
startX = e.X
startY = e.Y
ElseIf e.Button = Windows.Forms.MouseButtons.Right Then
targetPB = sender
End If
End Sub

Private Sub targetPB_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs)
If e.Button = Windows.Forms.MouseButtons.Left Then
Dim pb As PictureBox = CType(sender, PictureBox)
pb.Location = New Point(pb.Left + e.X - startX, pb.Top + e.Y - startY)
End If
End Sub

Private Sub mi_Click(ByVal sender As Object, ByVal e As System.EventArgs)
MainPanel.Controls.Remove(targetPB)
End Sub

Private Sub sourcePB_Click(ByVal sender As Object, ByVal e As System.EventArgs)
Dim pb As New PictureBox
pb.SizeMode = PictureBoxSizeMode.AutoSize
'pb.Image = CType(sender, PictureBox).Image
pb.Image = imagetwo
pb.Location = New Point(MainPanel.Width / 2 - pb.Width / 2, MainPanel.Height / 2 - pb.Height / 2)
pb.ContextMenu = cm
AddHandler pb.MouseDown, AddressOf targetPB_MouseDown
AddHandler pb.MouseMove, AddressOf targetPB_Mou
wiswalld 20-Dec-11 12:34pm    
I took out some stuff I had thrown in there

Public Class Form1
Dim imagetwo As Bitmap
Dim angle As Integer = 0

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
SetStyle(ControlStyles.DoubleBuffer, True)
SetStyle(ControlStyles.AllPaintingInWmPaint, True)
'imagetwo = New Bitmap("C:\Documents and Settings\wiswalld\My Documents\DEP Police Patch.bmp")
imagetwo = New Bitmap(PictureBox1.Image)
imagetwo.MakeTransparent(Color.Black)
'gameloop.start()

WirePBs(Me)
Dim mi As New MenuItem("Delete")
AddHandler mi.Click, AddressOf mi_Click
cm.MenuItems.Add(mi)
For Each ctl As Control In Me.Controls
If TypeOf ctl Is PictureBox Then
AddHandler ctl.Click, AddressOf sourcePB_Click
End If
Next
End Sub

Private Sub Form1_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles Me.Paint
e.Graphics.TranslateTransform(90, 90)
e.Graphics.RotateTransform(angle)
e.Graphics.DrawImage(imagetwo, -50, -50, 100, 100)
e.Graphics.ResetTransform()
End Sub

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Me.angle += 5
Me.Refresh()
End Sub

Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
Me.PictureBox1.Image = New Bitmap("C:\Documents and Settings\wiswalld\My Documents\DEP Police Patch.bmp")
imagetwo = New Bitmap(PictureBox1.Image)
imagetwo.MakeTransparent(Color.Black)
End Sub

Private pb As PictureBox = Nothing
Dim currentPicBox As PictureBox
Private cm As New ContextMenu()
Private targetPB As PictureBox
Private Sub WirePBs(ByVal cont As Control)
For Each ctl As Control In cont.Controls
If TypeOf ctl Is PictureBox Then
Dim pb As PictureBox = DirectCast(ctl, PictureBox)
'sizers.Add(New PBsizer(pb, pb.Parent))
ElseIf ctl.HasChildren Then
WirePBs(ctl)
End If
Next
End Sub
Private startX, startY As Integer

Private Sub targetPB_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs)
If e.Button = Windows.Forms.MouseButtons.Left Then
startX = e.X
startY = e.Y
ElseIf e.Button = Windows.Forms.MouseButtons.Right Then
targetPB = sender
End If
End Sub

Private Sub targetPB_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs)
If e.Button = Windows.Forms.MouseButtons.Left Then
Dim pb As PictureBox = CType(sender, PictureBox)
pb.Location = New Point(pb.Left + e.X - startX, pb.Top + e.Y - startY)
End If
End Sub

Private Sub mi_Click(ByVal sender As Object, ByVal e As System.EventArgs)
MainPanel.Controls.Remove(targetPB)
End Sub

Private Sub sourcePB_Click(ByVal sender As Object, ByVal e As System.EventArgs)
Dim pb As New PictureBox
pb.SizeMode = PictureBoxSizeMode.AutoSize
'pb.Image = CType(sender, PictureBox).Image
pb.Image = imagetwo
pb.Location = New Point(MainPanel.Width / 2 - pb.Width / 2, MainPanel.Height / 2 - pb.Height / 2)
pb.ContextMenu = cm
AddHandler pb.MouseDown, AddressOf targetPB_MouseDown
AddHandler pb.MouseMove, AddressOf targetPB_MouseMove
MainPanel.Controls.Add(pb)
pb.BringToFront()
End Sub

End Class
wiswalld 21-Dec-11 9:22am    
So I am able to rotate the source bitmap just fine but when I put it on the other panel it is not rotated

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900