问题
I have been attempting to rotate an image in vb.net and have had some trouble with it. The first block of code was working, but it was causing an undesireable side effect where after the rotation the image had been scaled down such that the x dimension would fit in the pre-existing 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?
Thanks
Works:
If XSize < YSize Then 'Needs to be rotated
Dim img As System.Drawing.Image
img = System.Drawing.Image.FromFile(strFilename)
Dim b = New System.Drawing.Bitmap(img.Height, img.Width)
Dim gr As Graphics = Graphics.FromImage(b)
img.RotateFlip(System.Drawing.RotateFlipType.Rotate90FlipNone)
gr.DrawImage(img, New Point(0, 0))
img = Nothing
b.Save(strFilename)
End If
This block of code does not work:
If XSize < YSize Then 'Needs to be rotated
Dim img As System.Drawing.Image
img = System.Drawing.Image.FromFile(strFilename)
Dim bmpTemp As System.Drawing.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 System.Drawing.Bitmap(img.Height, img.Width)
Dim gr As Graphics = Graphics.FromImage(b)
bmpTemp.RotateFlip(System.Drawing.RotateFlipType.Rotate90FlipNone)
gr.DrawImage(bmpTemp, New Point(0, 0))
img = Nothing
b.Save(strFilename)
End If
回答1:
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:
Good luck.
来源:https://stackoverflow.com/questions/57858537/rotating-an-image-in-vb-net