【问题标题】:Arint System.Drawing.Graphics suppose to write/modify the image its attached to?Arint System.Drawing.Graphics 假设写入/修改其附加到的图像?
【发布时间】:2018-12-29 19:50:24
【问题描述】:

当您使用图形对象时,位图(源图像)是否不应该在某些时候发生变化?运行下面的代码,我得到 5 张与源代码完全相同的图像。 1.bmp、2.bmp、3.bmp、4.bmp 和 5.bmp 与“scaleCharacter”相同,除了 4 和 5 具有更高的压缩率(更小的文件大小)

Private Function DrawCharacterMenu() As Boolean

    Try
        'Background
        Dim rect As Rectangle = New Rectangle(100, 100, 128, 128)
        Graphics.FromImage(Render).FillRectangle(Brushes.Black, rect)

        'Scale up sprite
        Dim scaleCharacter As Bitmap = ActiveCharacter.img.Clone
        Using grDest = Graphics.FromImage(scaleCharacter)
            scaleCharacter.Save("1.bmp")
            grDest.ScaleTransform(4.0F, 4.0F)
            scaleCharacter.Save("2.bmp")
            grDest.InterpolationMode = Drawing2D.InterpolationMode.NearestNeighbor
            scaleCharacter.Save("3.bmp")
            grDest.DrawImage(scaleCharacter, 0, 0)
            scaleCharacter.Save("4.bmp")
        End Using
        scaleCharacter.Save("5.bmp")

        'Draw scaled up sprite to rendering
        Graphics.FromImage(Render).DrawImage(scaleCharacter, 100, 100)

    Catch ex As Exception
        addDebugMessage("Error: Mainmenu.DrawCharacterMenu: " & ex.Message)
        Return False
    End Try

    Return True
End Function

我希望 1 与 'scaleCharacter' 相同

2 及以上要大 4 倍(32x32 到 128x128)

3 及以上以减少插值(看起来没有拉伸)

绘制到渲染上的完成的“scaleCharacter”也与原始图像相同...

【问题讨论】:

    标签: vb.net graphics


    【解决方案1】:

    你所有的图片都是一样的,因为从技术上讲你永远不会改变它们。

    1. Graphics.ScaleTransform() 仅更改绘制图元时使用的内部“世界”矩阵。 ScaleTransform(4.0F, 4.0F) 使 绘图网格 宽 4 倍,高 4 倍,但它不会改变图像本身,直到您在其上绘制一些东西。例如,如果您现在要在图像上绘制一个 20 x 10 的矩形,它将产生一个 80 x 40 大小的矩形。

      要调整实际图像的大小,您必须创建一个具有缩放大小的新位图,然后在其上绘制按比例缩放的旧图像。

    2. 更改Graphics.InterpolationMode 仅影响 绘制的对象。同样,它不会改变您的图像,直到您在其上绘制一些东西。

    3. 最后,虽然grDest.DrawImage(scaleCharacter, 0, 0) 确实更改了您的图像,但它在自身的左上角 (0, 0) 绘制了相同的图像,因此没有 可见 更改。

    您可以通过以下方式使其发挥作用:

    缩放图像:

    'Scale factor.
    Dim scaleFactor As Single = 4.0F
    
    'Create a new bitmap of the scaled size.
    Using scaledBmp As New Bitmap(scaleCharacter.Width * scaleFactor, scaleCharacter.Height * scaleFactor)
        Using g As Graphics = Graphics.FromImage(scaledBmp)
            'Draw the old image, scaled, onto the new one.
            'srcRect:  The rectangle specifying which portion of the source image (scaleCharacter) to draw.
            '          We want the full image so we specify (0, 0, source width, source height).
            'destRect: The rectangle specifying where on the destination image (scaledBmp) to draw the source image.
            '          Since we want to scale it we specify the full destination image (0, 0, dest width, dest height).
            Dim srcRect As New Rectangle(0, 0, scaleCharacter.Width, scaleCharacter.Height)
            Dim destRect As New Rectangle(0, 0, scaledBmp.Width, scaledBmp.Height)
            g.DrawImage(scaleCharacter, destRect, srcRect, GraphicsUnit.Pixel)
    
            'Save the image.
            scaledBmp.Save("2.bmp")
        End Using
    End Using
    

    使用最近邻插值缩放图像:

    'Create a new bitmap of the scaled size.
    Using scaledBmp As New Bitmap(scaleCharacter.Width * scaleFactor, scaleCharacter.Height * scaleFactor)
        Using g As Graphics = Graphics.FromImage(scaledBmp)
            'Set the interpolation mode before drawing.
            g.InterpolationMode = Drawing2D.InterpolationMode.NearestNeighbor
    
            'Draw the old image, scaled, onto the new one.
            'srcRect:  The rectangle specifying which portion of the source image (scaleCharacter) to draw.
            '          We want the full image so we specify (0, 0, source width, source height).
            'destRect: The rectangle specifying where on the destination image (scaledBmp) to draw the source image.
            '          Since we want to scale it we specify the full destination image (0, 0, dest width, dest height).
            Dim srcRect As New Rectangle(0, 0, scaleCharacter.Width, scaleCharacter.Height)
            Dim destRect As New Rectangle(0, 0, scaledBmp.Width, scaledBmp.Height)
            g.DrawImage(scaleCharacter, destRect, srcRect, GraphicsUnit.Pixel)
    
            'Save the image.
            scaledBmp.Save("3.bmp")
        End Using
    End Using
    

    【讨论】:

    • 我有一个问题,想知道你能帮忙吗?
    • 你能解释一下为什么这段代码在另一个领域对我有用吗? Try Rendering = MyMap.map Graphics.FromImage(Rendering).ScaleTransform(SizeMultiplyer, SizeMultiplyer) Graphics.FromImage(Rendering).InterpolationMode = Drawing2D.InterpolationMode.NearestNeighbor Graphics.FromImage(Rendering).DrawImage(Rendering, 0, 0 ) PictureBox1.Image = Rendering Catch ex As Exception...' 是因为我使用的是图片框涂料吗? (P.s 抱歉,我无法让代码标签工作)
    • @Will.N :这不可能工作,因为您正在创建三个不同且独立的 Graphics 对象,顺便说一句,您永远不会处理这些对象。该代码将疯狂地内存泄漏。您确定拉伸图像的不仅仅是您的PictureBox.SizeMode吗?尝试保存位图并查看结果。
    • @Will.N :顺便说一下,cmets 中的 inline code 可以通过用反引号 ( ` ) 包围它来格式化,如下所示:`这是代码` - 结果是:this is code。尽管多行代码在 cmets 中看起来不太好,但通常最好将其编辑到您的问题中或使用像 pastebin.com 这样的服务。您可以在Markdown and Formatting help 中找到更多信息。 :)
    猜你喜欢
    • 2016-03-29
    • 1970-01-01
    • 2011-07-17
    • 1970-01-01
    • 2016-11-14
    • 1970-01-01
    • 2021-01-16
    • 2021-08-13
    • 2019-06-01
    相关资源
    最近更新 更多