modo veloce per creare una grande bitmap da una matrice di bitmap?

Ho questo codice,

copia / incolla in una nuova app Winform e questo scriverà un file sul desktop se lo esegui: 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 

circa il 40% al 45% del tempo trascorso è su DrawImageUnscaled , circa 23 secondi sul mio computer corrente mentre l’intera operazione dura circa 50 secondi

c’è un modo per velocizzare DrawImageUnscaled ? (e forse il tutto?)

MODIFICA – domanda in vb.net, rispondi in c #

Supponendo che la parte di generazione ( g.FillRectangles(Brushes.White, Rect) , piuttosto lunga anche in termini di tempo) non possa essere evitata, la cosa migliore che si può fare è evitare un secondo processo di generazione del grafico (anche per la board ) e semplicemente copiare le informazioni da _board . La copia è molto più veloce di una nuova generazione (come mostrato di seguito), ma si ha il problema che le informazioni di origine ( _board ) non corrispondono al formato di destinazione ( board basandosi su .SetPixel ) e quindi si dovrà creare una funzione determinante il pixel corrente (punto X / Y) dalle informazioni fornite (rettangolo corrente).

Qui sotto puoi vedere un semplice codice che mostra le differenze tra i due requisiti:

 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 

Ricorda che non è un “codice funzionante”. Il suo intero punto mostra come copiare i pixel tra bitmap (moltiplicando per un fattore, solo per ottenere output diversi dagli input); e mettendo il metodo DrawImageUnscaled in condizioni equivalenti (anche se l’immagine in uscita è, logicamente, diversa) per avere una buona percezione delle differenze nei requisiti di tempo tra le due metodologie.

Come detto tramite commento, questo è tutto ciò che posso fare nelle condizioni attuali. Spero che sarà sufficiente per aiutarti a trovare la soluzione migliore.

wow Mi piace il codice non sicuro quando è stato valutato, ho risolto il problema con c # alla fine

ecco il codice, che è circa 70 volte più veloce per il codice nella mia domanda

 using System; using System.Drawing; using System.Drawing.Imaging; namespace BmpFile { public class BmpTest { private const int PixelSize = 4; public static long Test(int GridX, int GridY, int SquareSize, Rectangle[][] Rect) { Bitmap bmp = new Bitmap(GridX * SquareSize, GridY * SquareSize, PixelFormat.Format32bppArgb); BitmapData bmd = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), System.Drawing.Imaging.ImageLockMode.ReadWrite, bmp.PixelFormat); int Stride = bmd.Stride; int Height = bmd.Height; int Width = bmd.Width; int RectFirst = Rect.GetUpperBound(0); int RectSecond; int Offset1, Offset2, Offset3; int i, j, k, l, w, h; int FullRow = SquareSize * Stride; int FullSquare = SquareSize * PixelSize; var sw = System.Diagnostics.Stopwatch.StartNew(); unsafe { byte* row = (byte*)bmd.Scan0; //draw all rectangles for (i = 0; i < = RectFirst; ++i) { Offset1 = ((i / GridX) * FullRow) + ((i % GridX) * FullSquare) + 3; RectSecond = Rect[i].GetUpperBound(0); for (j = 0; j <= RectSecond; ++j) { Offset2 = Rect[i][j].X * PixelSize + Rect[i][j].Y * Stride; w=Rect[i][j].Width; h=Rect[i][j].Height; for (k = 0; k <= w; ++k) { Offset3 = k * PixelSize; for (l = 0; l <= h; ++l) { row[Offset1 + Offset2 + Offset3 + (l * Stride)] = 255; } } } } //invert color for (int y = 0; y < Height; y++) { Offset1 = (y * Stride) + 3; for (int x = 0; x < Width; x++) { if (row[Offset1 + x * PixelSize] == 255) { row[Offset1 + x * PixelSize] = 0; } else { row[Offset1 + x * PixelSize] = 255; } } } } sw.Stop(); bmp.UnlockBits(bmd); bmp.Save(Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + @"\test.png", ImageFormat.Png); bmp.Dispose(); return sw.ElapsedMilliseconds; } } }