Welcome to WuJiGu Developer Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.8k views
in Technique[技术] by (71.8m points)

vb.net - How to rotate an Image preserving its original size?

I have been attempting to rotate an Image and I have had some trouble with it. The first block of code was working, but it was causing an undesirable side effect: after the rotation, the Image was scaled down so that the x dimension would match the preexisting y dimension.
So I had the Image rotated, but it was only taking up part of the canvas.

In order to solve that, I figured I should just create a larger bitmap as an intermediate step, so that when it was rotated, the Image would not need to be shrunk in order to fit.

That code is in the second block. Unfortunately when I run it, I get a generic GDI error.
Anyone know what I've done wrong?

Works:

Imports System.Drawing

If XSize < YSize Then 'Needs to be rotated
    Dim img As Image = Image.FromFile(strFilename)

    Dim b = New Bitmap(img.Height, img.Width)
    Dim gr As Graphics = Graphics.FromImage(b)
    img.RotateFlip(RotateFlipType.Rotate90FlipNone)
    gr.DrawImage(img, New Point(0, 0))
    img = Nothing
    b.Save(strFilename)
End If

This block of code does not work:

'Needs to be rotated
If XSize < YSize Then 
    Dim img As Image = Image.FromFile(strFilename)
    Dim bmpTemp As Image

    If img.Height > img.Width Then
        bmpTemp = New Bitmap(img.Height, img.Height)
    Else
        bmpTemp = New Bitmap(img.Width, img.Width)
    End If

    Dim gr2 As Graphics = Graphics.FromImage(bmpTemp)
    gr2.DrawImage(img, New Point(0, 0))

    Dim b = New Bitmap(img.Height, img.Width)
    Dim gr As Graphics = Graphics.FromImage(b)
    bmpTemp.RotateFlip(RotateFlipType.Rotate90FlipNone)
    gr.DrawImage(bmpTemp, New Point(0, 0))
    img = Nothing
    b.Save(strFilename)
End If
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Not quite clear to me how would you like to rotate the image. Is the problem the rotation axis, the new size of the rotated image, or something else?

Anyways, to the best of my guessing, the following code snippet rotates the image either around the edges of the canvas or around it's center point.

Private Function RotateImage(ByVal src As Bitmap,
                            ByVal width As Integer,
                            ByVal height As Integer,
                            ByVal angle As Single,
                            Optional ByVal CenterRotation As Boolean = False) As Bitmap

   Dim cornors As Point() = {New Point(0, 0),
                        New Point(width, 0),
                        New Point(width, height),
                        New Point(0, height)}
   Using m As New Matrix
    If Not CenterRotation Then
        m.RotateAt(angle, New PointF(width / 2, height / 2))
        m.TransformPoints(cornors)
    End If

    Dim left = Integer.MaxValue
    Dim right = Integer.MinValue
    Dim top = Integer.MaxValue
    Dim bottom = Integer.MinValue

    For i = 0 To UBound(cornors)
        If cornors(i).X < left Then left = cornors(i).X
        If cornors(i).X > right Then right = cornors(i).X
        If cornors(i).Y < top Then top = cornors(i).Y
        If cornors(i).Y > bottom Then bottom = cornors(i).Y
    Next

    Dim b As New Bitmap(right - left, bottom - top)
    Dim x = (b.Width - width) / 2
    Dim y = (b.Height - height) / 2

    Using g As Graphics = Graphics.FromImage(b)
        m.Reset()
        m.RotateAt(angle, New PointF(b.Width / 2, b.Height / 2))
        g.Transform = m
        g.InterpolationMode = InterpolationMode.HighQualityBicubic
        g.SmoothingMode = SmoothingMode.HighQuality
        g.CompositingQuality = CompositingQuality.HighQuality
        g.Clear(Color.Transparent)
        g.DrawImage(src, New Rectangle(x, y, width, height))
    End Using
    Return b
   End Using
End Function

If you also need to resize the rotated image to fit into the canvas, then you also need the following code AFTER THE FIRST ONE:

Private Function CreateThumbnail(ByVal bmp As Bitmap,
                                    ByVal canvasWidth As Integer,
                                    ByVal canvasHeight As Integer,
                                    Optional Stretch As Boolean = False) As Bitmap

    Dim bmpOut As Bitmap = Nothing

    If Stretch Then
        bmpOut = bmp.GetThumbnailImage(canvasWidth, canvasHeight, Nothing, IntPtr.Zero)
    Else
        Dim newWidth As Integer = 0
            Dim newHeight As Integer = 0

            bmpOut = New Bitmap(canvasWidth, canvasHeight)

            Dim ratioX As Double = CDbl(canvasWidth) / CDbl(bmp.Width)
            Dim ratioY As Double = CDbl(canvasHeight) / CDbl(bmp.Height)
            Dim ratio = If(ratioX < ratioY, ratioX, ratioY)

            newWidth = Convert.ToInt32(bmp.Width * ratio)
            newHeight = Convert.ToInt32(bmp.Height * ratio)

            If newWidth > bmp.Width Then
                newWidth = bmp.Width
            End If
            If newHeight > bmp.Height Then
                newHeight = bmp.Height
            End If

            Dim posX = Convert.ToInt32((canvasWidth - newWidth) / 2)
            Dim posY = Convert.ToInt32((canvasHeight - newHeight) / 2)

            Using g As Graphics = Graphics.FromImage(bmpOut)
                g.InterpolationMode = InterpolationMode.HighQualityBicubic
                g.SmoothingMode = SmoothingMode.HighQuality
                g.CompositingQuality = CompositingQuality.HighQuality
                g.Clear(Color.Transparent)
                g.DrawImage(bmp, posX, posY, newWidth, newHeight)
            End Using
        End If

    Return bmpOut
End Function

Here is a quick demo:

Image Rotation Demo

Good luck.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to WuJiGu Developer Q&A Community for programmer and developer-Open, Learning and Share
...