c# - 从位图数组创建大位图的快速方法?

标签 c# vb.net bitmap gdi+ unsafe

我有这个代码,

复制/粘贴到新的winform应用程序中,如果运行它,这将在桌面上写入一个文件:test123abcd.png

Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
    Dim SquareSize = 5
    Dim GridX = 2500
    Dim GridY = 2500
    Dim SquareCount = GridX * GridY - 1
    Dim sw As New Stopwatch

    Dim Rect(4) As Rectangle
    Rect(0) = New Rectangle(0, 3, 3, 1)
    Rect(1) = New Rectangle(3, 0, 1, 3)
    Rect(2) = New Rectangle(3, 3, 3, 1)
    Rect(3) = New Rectangle(0, 0, 1, 3)

    Dim fullsw = Stopwatch.StartNew
    Using board = New Bitmap(SquareSize * (GridX + 1), SquareSize * (GridY + 1), Imaging.PixelFormat.Format32bppPArgb)
        Using graph = Graphics.FromImage(board)
            Using _board = New Bitmap(SquareSize, SquareSize, Imaging.PixelFormat.Format32bppPArgb)
                Using g As Graphics = Graphics.FromImage(_board)
                    For i = 0 To SquareCount
                        g.Clear(If((i And 1) = 1, Color.Red, Color.Blue))
                        g.FillRectangles(Brushes.White, Rect)
                        sw.Start()
                        graph.DrawImageUnscaled(_board, ((i Mod GridX) * SquareSize), ((i \ GridY) * SquareSize))
                        sw.Stop()
                    Next
                End Using
            End Using
        End Using
        fullsw.Stop()
        board.Save(Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory) & "\test123abcd.png", Imaging.ImageFormat.Png)
    End Using

    MessageBox.Show("Full SW: " & fullsw.ElapsedMilliseconds & Environment.NewLine &
                    "DrawImageUnscaled SW: " & sw.ElapsedMilliseconds)
End Sub

大约 40% 到 45% 的时间花在 DrawImageUnscaled 上,在我当前的计算机上大约需要 23 秒,而整个过程大约需要 50 秒

有没有办法加快DrawImageUnscaled的速度? (也许是整个事情?)

编辑 - vb.net 中的问题,c# 中的答案

最佳答案

假设生成部分(g.FillRectangles(Brushes.White, Rect),也相当耗时)无法避免,您能做的最好的事情就是避免第二个图表 -生成过程(也适用于 board),只需从 _board 复制信息。复制比新一代要快得多(如下所示),但是您会遇到源信息(_board)与目标格式(board)不匹配的问题,通过依赖.SetPixel),因此您必须创建一个函数,根据提供的信息(当前矩形)确定当前像素(X/Y 点)。

下面您可以看到一个简单的代码,显示两种方法之间的时间要求差异:

Dim SquareSize As Integer = 5
Dim _board As Bitmap = Bitmap.FromFile("in.png")
Dim board As Bitmap = New Bitmap(_board.Width * SquareSize, _board.Height * SquareSize)

For x As Integer = 0 To _board.Width - 1
    For y As Integer = 0 To _board.Height - 1
        board.SetPixel(x * SquareSize, y * SquareSize, _board.GetPixel(x, y))
    Next
Next

board.Save("out1.png", Imaging.ImageFormat.Png)


board = New Bitmap(_board.Width, _board.Height)

Using board
    Using graph = Graphics.FromImage(board)
        Using _board
            Using g As Graphics = Graphics.FromImage(_board)
                For x As Integer = 0 To _board.Width - 1
                    For y As Integer = 0 To _board.Height - 1
                        graph.DrawImageUnscaled(_board, x, y)
                    Next
                Next
            End Using
        End Using
    End Using
    board.Save("out2.png", Imaging.ImageFormat.Png)
End Using

请记住,它不是“正常工作的代码”。它的重点是展示如何在位图之间复制像素(通过乘以一个因子,只是为了获得与输入不同的输出);并将 DrawImageUnscaled 方法置于同等条件下(尽管输出图片在逻辑上是不同的),以便更好地了解两种方法之间的时间要求差异。

正如评论中所说,这是我在当前条件下所能做的。我希望这足以帮助您找到最佳解决方案。

关于c# - 从位图数组创建大位图的快速方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18083318/

相关文章:

c# - Xamarin UWP Release模式错误 - ILT005 返回退出代码 1

c# - 如何使用 C# 取消删除文件?

c#:从对象 [] 数组调用存储对类对象的引用的通用方法

vb.net - 未为类型 '=' 和类型 'DBNull' 定义运算符 'Integer'

c - 从 AVI 文件解析 BITMAPINFO 结构

c# - Entity Framework 4.3.1 始终在更新数据库上运行所有迁移

c# - 将 SqlCommand 转换为 T-SQL 命令

c# - 比较时,没有关键字段的 VB.NET 匿名类型与 C# 匿名类型有何不同?

android - 从路径创建 BitmapDrawable

android - 内存不足 !为我的游戏使用大量位图时,位图 Vm 内存超出预算错误