如何旋转保留原始尺寸的图像?

时间:2019-09-09 17:20:04

标签: vb.net image graphics bitmap

我一直在尝试旋转图像,但遇到了一些麻烦。第一个代码块在工作,但是却引起了不良后果:旋转之后,图像按比例缩小,因此x尺寸将与先前存在的y尺寸匹配。
因此,我旋转了图像,但它只占用了画布的一部分。

为了解决这个问题,我认为我应该只创建一个更大的位图作为中间步骤,这样,当旋转它时,就不需要缩小图像来适应它。

该代码在第二个块中。不幸的是,当我运行它时,出现一个通用的GDI错误。
有人知道我做错了吗?

作品:

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

此代码块不起作用:

'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

1 个答案:

答案 0 :(得分:1)

我不太清楚您想如何旋转图像。问题是旋转轴,旋转图像的新尺寸还是其他?

无论如何,据我所知,以下代码片段围绕画布的边缘或其中心点旋转图像。

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

如果还需要调整旋转图像的大小以适合画布,那么在第一个之后还需要以下代码:

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

这是一个快速演示:

Image Rotation Demo

祝你好运。