Click here to Skip to main content
15,884,176 members
Articles / Multimedia / GDI+

Rotating PictureBox Control

Rate me:
Please Sign up or sign in to vote.
4.39/5 (17 votes)
29 Jul 2005CPOL4 min read 179.5K   5.2K   27   29
A PictureBox control that lets you rotate images.

Sample Image - rimage.jpg

Introduction

How many times have you wanted to rotate an image in a PictureBox control? I know I've wanted to do it on many occasions.

This control makes it simple to rotate your images. Referencing it is easy in code - the namespace is System.Windows.Forms so you can easily declare one as RImage.

Properties/Methods

This control inherits everything so any property/method a PictureBox has, this control will have as well - however, there are several properties that will allow you other options that were built into the control.

  • Public Property ShowThrough() As Boolean
  • Public Property Direction() As DirectionEnum
  • Public Property Rotation() As Integer
  • Public Property TransparentColor() As Color

ShowThrough will determine whether or not space not used by the image will be transparent and show the control below it. This is accomplished using regions.

Direction as you notice is declared as DirectionEnum. This enumeration was created for the control. It tells the control which way to rotate the image: Clockwise, or Counter_Clockwise.

Rotation is the angle of rotation of the image. It is in degrees. The range is 0 to 359; however, inputting a number outside of the range will scale it to the appropriate angle that is in the range.

TransparentColor will allow you to set a transparent color for the image. The demo project has an image included with a Lime background. If the TransparentColor property is set to Lime - that color in the image will be painted transparent. Unfortunately, it doesn't show the controls below it through, just the parent's background color.

Adding the Control

Right-click on an empty area of your toolbox and choose Add/Remove Items. At the dialog screen on the .NET Framework Components tab, choose Browse and navigate to the DLL file. Once you've done this, hit OK.

You've now added the control to the toolbox.

Using the Control

Using the control is simple. It works almost exactly like the PictureBox control. Add one to your form, and give it an image. Once it has an image, ShowThrough will start working (if there is no image, OnPaint quits before it can set the transparent region) if it is set.

Now just set your Direction from the drop-down box in the Properties window and enter an angle for your Rotation.

If you'd like to set a transparent color for your image - you can do that with TransparentColor in the Properties window.

How it works

All of the rotation is handled in the OnPaint event. I start by getting the current corners of the image.

VB
Dim bm_in As New Bitmap(MyBase.Image)

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)}

Next I grab the center of the image - the point we want to rotate around - and subtract from each of the corners.

VB
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

Now we need to get the Sine of theta, and the Cosine of theta - which means we need theta.

VB
Dim theta As Single = CSng((_degree) * _direction) * PI / 180
Dim sin_theta As Single = Sin(theta)
Dim cos_theta As Single = Cos(theta)

Here is where the magic comes in, we need to apply the rotation formulas to all the corners.

VB
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 = (Y * cos_theta) + (X * sin_theta)
Next

OK, we've got the rotated corners, let's fix the offset we created when finding the rotation point, and for that we'll need the minimum x and y values.

VB
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

For i = 0 To 3
    corners(i).X -= xmin
    corners(i).Y -= ymin
Next

Now we can actually output the rotated image, but first I create a region using a function to create it based on these corners.

VB
Dim bm_out As New Bitmap(CInt(-2 * xmin), CInt(-2 * ymin))
Dim bgr As Graphics = Graphics.FromImage(bm_out)
Dim rg As Region = CreateTransRegion(corners)
Dim tp As Point = corners(3)
ReDim Preserve corners(2)
bgr.DrawImage(bm_in, corners)

Now we have the rotated image in an output buffer, plus a region to allow transparency for the parts of the control that won't draw the image. Now comes the implementation of the SizeMode. For StretchImage, we'll need the width and height of the rotated image - this is easy as it's stored in the corners array at index 3 - and for stretching or centering we'll need a new region.

VB
Dim gr_out As Graphics = pe.Graphics
gr_out.FillRectangle(New SolidBrush(Me.BackColor), 0, 0, Me.Width, Me.Height)
bm_in.MakeTransparent(_transColor)
If _sizemode = PictureBoxSizeMode.StretchImage Then
    Dim maxW As Integer = tp.X
    Dim maxH As Integer = tp.Y
    For t As Integer = 0 To 2
        If maxW < corners(t).X Then maxW = corners(t).X
        If maxH < corners(t).Y Then maxH = corners(t).Y
    Next
    'get hscale
    Dim hscale As Double = Me.Width / maxW
    'get vscale
    Dim vscale As Double = Me.Height / maxH
    'convert points
    corners(0) = New Point(corners(0).X * hscale, corners(0).Y * vscale)
    corners(1) = New Point(corners(1).X * hscale, corners(1).Y * vscale)
    corners(2) = New Point(corners(2).X * hscale, corners(2).Y * vscale)
    gr_out.DrawImage(bm_out, 0, 0, Me.Width, Me.Height)
    Dim np(3) As Point
    np(0) = corners(0)
    np(1) = corners(1)
    np(2) = corners(2)
    np(3) = New Point(tp.X * hscale, tp.Y * vscale)
    rg = CreateTransRegion(np)

We don't need quite so much for centering the image.

VB
ElseIf _sizemode = PictureBoxSizeMode.CenterImage Then
    Dim wadd As Integer = CInt((Me.Width / 2) - (bm_out.Width / 2))
    Dim hadd As Integer = CInt((Me.Height / 2) - (bm_out.Height / 2))
    corners(0) = New Point(corners(0).X + wadd, corners(0).Y + hadd)
    corners(1) = New Point(corners(1).X + wadd, corners(1).Y + hadd)
    corners(2) = New Point(corners(2).X + wadd, corners(2).Y + hadd)
    gr_out.DrawImage(bm_in, corners)
    Dim np(3) As Point
    np(0) = corners(0)
    np(1) = corners(1)
    np(2) = corners(2)
    np(3) = New Point(tp.X + wadd, tp.Y + hadd)
    rg = CreateTransRegion(np)

Any other size modes just get output to 0,0, so we don't need anything special there, except for AutoSize - which just changes the control's size to match the image.

VB
Else
    gr_out.DrawImage(bm_in, corners)
End If
If _sizemode = PictureBoxSizeMode.AutoSize Then
    MyBase.Width = bm_out.Width
    MyBase.Height = bm_out.Height
End If

The last thing we take care of is the region (for transparency), but if the property ShowThrough is changed to False then we need to make sure to get rid of any existing region.

VB
Me.Region = Nothing
If _showThrough Then
    Me.Region = rg
End If

And that's it! It is certainly possible to modify it to rotate around a point other than the center (although I haven't tried).

License

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


Written By
Software Developer
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
GeneralMy vote of 4 Pin
Member 819853825-Sep-11 16:25
Member 819853825-Sep-11 16:25 
GeneralWorks great. [modified] Pin
emre20084-Nov-09 19:36
emre20084-Nov-09 19:36 
GeneralRotating Picturebox Control Pin
actpfd25-Jun-07 5:42
actpfd25-Jun-07 5:42 
GeneralRe: Rotating Picturebox Control Pin
Chris Kolkman25-Jun-07 6:39
Chris Kolkman25-Jun-07 6:39 
GeneralRe: Rotating Picturebox Control Pin
actpfd25-Jun-07 22:28
actpfd25-Jun-07 22:28 
GeneralRe: Rotating Picturebox Control Pin
Chris Kolkman26-Jun-07 3:10
Chris Kolkman26-Jun-07 3:10 
GeneralRe: Rotating Picturebox Control Pin
actpfd26-Jun-07 3:33
actpfd26-Jun-07 3:33 
GeneralRe: Rotating Picturebox Control Pin
Chris Kolkman26-Jun-07 3:46
Chris Kolkman26-Jun-07 3:46 
GeneralRe: Rotating Picturebox Control Pin
actpfd26-Jun-07 3:59
actpfd26-Jun-07 3:59 
GeneralRe: Rotating Picturebox Control Pin
Chris Kolkman26-Jun-07 4:22
Chris Kolkman26-Jun-07 4:22 
GeneralRe: Rotating Picturebox Control Pin
actpfd26-Jun-07 4:53
actpfd26-Jun-07 4:53 
GeneralRe: Rotating Picturebox Control Pin
Chris Kolkman26-Jun-07 4:53
Chris Kolkman26-Jun-07 4:53 
GeneralRe: Idid not succed to load the demo it seems to the same files as the sources Pin
Chris Kolkman19-Mar-07 9:53
Chris Kolkman19-Mar-07 9:53 
Questiondrawing a rombus within the rotated rectangle Pin
JK Rajesh29-Jan-07 1:51
JK Rajesh29-Jan-07 1:51 
QuestionHow do I calculate the angle.value of a point? Pin
furjaw23-Jun-06 17:27
furjaw23-Jun-06 17:27 
AnswerRe: How do I calculate the angle.value of a point? Pin
Chris Kolkman24-Jun-06 4:12
Chris Kolkman24-Jun-06 4:12 
GeneralI do not see the trigonometry code Pin
furjaw23-Jun-06 6:34
furjaw23-Jun-06 6:34 
GeneralRe: I do not see the trigonometry code Pin
Chris Kolkman23-Jun-06 8:45
Chris Kolkman23-Jun-06 8:45 
You are correct, all the trigonometry code is contained within the control.
GeneralTimer Tick Subroutine Not Needed Pin
furjaw23-Jun-06 6:32
furjaw23-Jun-06 6:32 
GeneralRe: Timer Tick Subroutine Not Needed Pin
Chris Kolkman23-Jun-06 8:55
Chris Kolkman23-Jun-06 8:55 
GeneralWhy not use System.Drawing.Drawing2D.Matrix Pin
Ross Presser1-Nov-05 9:56
Ross Presser1-Nov-05 9:56 
GeneralRe: Why not use System.Drawing.Drawing2D.Matrix Pin
Chris Kolkman1-Nov-05 10:25
Chris Kolkman1-Nov-05 10:25 
GeneralThis is a code website Pin
Pascal Ganaye22-Jul-05 6:28
Pascal Ganaye22-Jul-05 6:28 
GeneralRe: This is a code website Pin
Chris Kolkman26-Jul-05 4:00
Chris Kolkman26-Jul-05 4:00 
GeneralRe: This is a code website [modified] Pin
furjaw22-Jun-06 18:55
furjaw22-Jun-06 18:55 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.