I have this code,
copy/paste in a new winform app and this will write a file on your desktop if you run it:
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
about 40% to 45% of the time spent is on
DrawImageUnscaled, about 23 seconds on my current computer while the whole thing take about 50 seconds
is there a way to speed up
DrawImageUnscaled? (and maybe the whole thing?)
EDIT - question in vb.net, answer in c#
By assuming that the generation part (
g.FillRectangles(Brushes.White, Rect), pretty time-consuming too) cannot be avoided, the best thing you can do is avoiding a second graph-generation process (also for
board) and just copying the information from
_board. Copying is much quicker than a new generation (as shown below), but you have the problem that the source information (
_board) do not match the destination format (
board by relying on
.SetPixel) and thus you will have to create a function determining the current pixel (X/Y point) from the provided information (current rectangle).
Below you can see a simple code showing the time requirement differences between both approaches:
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
Bear in mind that it is not a "properly-working code". Its whole point is showing how to copy pixels between bitmaps (by multiplying by a factor, just to get different outputs than inputs); and putting the
DrawImageUnscaled method under equivalent conditions (although the output picture is, logically, different) to get a good feeling of the differences in time requirements between both methodologies.
As said via comment, this is all what I can do under the current conditions. I hope that will be enough to help you find the best solution.