【问题标题】:How to rotate JPEG using Graphics.RotateTransform without clipping如何使用 Graphics.RotateTransform 旋转 JPEG 而无需剪辑
【发布时间】:2014-06-10 05:30:35
【问题描述】:

我需要将 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

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

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

【问题讨论】:

  • not compatible with my end program 是什么意思?
  • 我的软件导出 CAD 模型的 JPEG 图像并将图像旋转 90 度(根据客户说明)。然后,客户将 JPEG 导入单独的 ERP 程序,该程序将 JPEG 放入 PDF 报告中。由于某些让我们都难过的奇怪原因,如果使用 System.Drawing.RotateFlip 旋转了图像,则图像不会显示在 PDF 中。所以我的任务是找出另一种旋转图像的方法。
  • 请注意:您的保存方法未指定 jpeg 格式。
  • 我假设您是在暗示 .jpeg 和 .jpg 是不同的文件格式?如果是这种情况,请纠正我。在我的研究中,我了解到 .jpeg 和 .jpg 是可以互换的。
  • 你最终是对的,LarsTech。这就是问题所在。谢谢。

标签: .net vb.net image


【解决方案1】:

为了不剪裁旋转的图像,您必须使目标矩形足够大以容纳旋转。

以 10 x 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

【讨论】:

  • 我生成的图像应该是 2550 x 3300。但是 Graphics.DrawImage() 不会产生这个结果。生成的图像仍然是 3300 x 2550,我不知道为什么。
  • DrawImage 本身不会改变尺寸。
猜你喜欢
  • 1970-01-01
  • 2018-09-09
  • 1970-01-01
  • 2018-12-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-01
  • 2011-08-04
相关资源
最近更新 更多