如何使用Graphics.RotateTransform旋转JPEG而不剪切

时间:2014-04-24 18:43:26

标签: .net vb.net image

我需要将JPEG图像旋转90度,不幸的是,System.Drawing.Image.RotateFlip产生的文件与我的终端程序不兼容。因此,作为替代方案,我正在尝试使用Graphics.RotateTransform。当前代码似乎应该可以工作,但是图像在旋转时会被剪裁。

This is the image我正在用于测试。

以下是我用来旋转图片的代码:

Public Shared Sub ProcessJpeg()
    Dim filePath As String = "C:\test.JPG"
    Dim img As Bitmap = Nothing
    img = New Bitmap(filePath)
    img = RotateImage(img, 90.0F)
    img.Save(Replace(filePath, ".JPG", "_new.JPG"))
End Sub

Shared Function RotateImage(b As Bitmap, angle As Single) As Bitmap
    'create a new empty bitmap to hold rotated image
    Dim returnBitmap As New Bitmap(b.Width, b.Height)
    'make a graphics object from the empty bitmap
    Dim g As Graphics = Graphics.FromImage(returnBitmap)
    'move rotation point to center of image
    g.TranslateTransform(CSng(b.Width) / 2, CSng(b.Height) / 2)
    'rotate
    g.RotateTransform(angle)
    'move image back
    g.TranslateTransform(-CSng(b.Width) / 2, -CSng(b.Height) / 2)
    'draw passed in image onto graphics object
    g.DrawImage(b, New Rectangle(New Point(0, 0), New Size(b.Width, b.Height)))
    Return returnBitmap
End Function

RotateImage函数来自here

我认为解决方案是简单地反转b.Width和b.Height在RotateImage函数的第三行到最后一行,但这只会让事情变得更糟。

或者,如果有更好的方法来旋转JPEG(除了System.Drawing.Image.RotateFlip),我很乐意听到它。

1 个答案:

答案 0 :(得分:3)

为了不剪切旋转的图像,必须使目标矩形足够大以保持旋转。

以10×5大小的矩形为例。当它旋转时,会有天使渲染大于10x5的图像。如果旋转90度,则只需翻转尺寸。

我以前用过的方法是: 1.创建一个最大尺寸的正方形 (10x5需要大约12x12的正方形。) 2.将图像旋转到正方形的中心。 3.将新方形图像向下剪切到旋转图像的实际大小。

请注意,以下代码适用于任何角度。

此代码将为您提供所需尺寸的正方形。

Public Function SquareRectangle(ByVal Newr As System.Drawing.Rectangle) As System.Drawing.Rectangle
    Dim Biggest = Newr.Size.Height
    If Newr.Size.Width > Biggest Then
        Biggest = Newr.Size.Width
    End If
    SquareRectangle = New System.Drawing.Rectangle(0, 0, Biggest, Biggest)
End Function

然后 - 此代码将图像放在该正方形的中心。

Public Function CenterBitmap(ByVal OrignalImage As System.Drawing.Bitmap, ByVal SqsR As System.Drawing.Rectangle) As System.Drawing.Bitmap
    CenterBitmap = New System.Drawing.Bitmap(SqsR.Size.Width, SqsR.Size.Height)
    Dim WPadding = SqsR.Size.Width - OrignalImage.Size.Width
    Dim HPadding = SqsR.Size.Height - OrignalImage.Size.Height
    Dim Graphics As System.Drawing.Graphics = System.Drawing.Graphics.FromImage(CenterBitmap)
    Dim PlaceR As New System.Drawing.Rectangle(CInt(WPadding / 2), CInt(HPadding / 2), OrignalImage.Size.Width, OrignalImage.Size.Height)
    Graphics.PageUnit = System.Drawing.GraphicsUnit.Pixel
    Graphics.DrawImage(OrignalImage, PlaceR)
End Function

然后 - 旋转正方形后 - 此代码将计算出该正方形内旋转位图的实际大小。

Public Function BoundingBox(ByRef Dimentions As System.Drawing.Size, ByVal Degrees As Single) As System.Drawing.Rectangle
    ' determine the size needed to hold a rotated rectangle
    Dim Rad As Single = CSng((Degrees * Math.PI) / 180)

    Dim HalfX As Single = CSng(Dimentions.Width / 2)
    Dim HalfY As Single = CSng(Dimentions.Height / 2)
    Dim SinRad As Single = CSng(Math.Sin(Rad))
    Dim CosRad As Single = CSng(Math.Cos(Rad))
    Dim HalfXSinRad As Single = HalfX * SinRad
    Dim HalfXCosRad As Single = HalfX * CosRad
    Dim HalfYSinRad As Single = HalfY * SinRad
    Dim HalfYCosRad As Single = HalfY * CosRad

    Dim pXSpYC = HalfXSinRad + HalfYCosRad
    Dim pXSnYC = HalfXSinRad + -HalfYCosRad
    Dim pXCpYS = HalfXCosRad + HalfYSinRad
    Dim pXCnYS = HalfXCosRad + -HalfYSinRad
    Dim nXSpYC = -HalfXSinRad + HalfYCosRad
    Dim nXSnYC = -HalfXSinRad + -HalfYCosRad
    Dim nXCpYS = -HalfXCosRad + HalfYSinRad
    Dim nXCnYS = -HalfXCosRad + -HalfYSinRad

    Dim x_min = Math.Min(Math.Min(nXCpYS, pXCpYS), Math.Min(pXCnYS, nXCnYS))
    Dim x_max = Math.Max(Math.Max(nXCpYS, pXCpYS), Math.Max(pXCnYS, nXCnYS))

    Dim y_min = Math.Min(Math.Min(pXSpYC, nXSpYC), Math.Min(nXSnYC, pXSnYC))
    Dim y_max = Math.Max(Math.Max(pXSpYC, nXSpYC), Math.Max(nXSnYC, pXSnYC))

    BoundingBox = New System.Drawing.Rectangle
    BoundingBox.Height = CInt(y_max - y_min)
    BoundingBox.Width = CInt(x_max - x_min)

End Function