2013-08-06 3 views
2

, 새의 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일까요? (그리고 아마도 모든 일?)

편집 - 생성 부분 (g.FillRectangles(Brushes.White, Rect)은 꽤 많은 시간이 소요도)이 피할 수없는 가정으로 C#을

+0

당신이 정확히 달성하기를 원합니까? (입력/출력) – varocarbas

+0

@varocarbas, 조각으로 나뉘어져있는 전체 비트 맵을 저장하려고합니다. – Fredou

+0

예, 입력 이미지 또는 색상 배열이 표시되지 않습니다. 기본적으로 빈 비트 맵에서 픽셀의 위치/크기에 영향을줍니다. 그것이 입/출력에 대한 나의 질문입니다. 예를 들어 image1.png와 image2.png를 입력으로 가져 와서 imageEnd.png에 병합하고자하는 경우 모든 작업을 수행 할 필요가 없습니다. 이미지의 크기를 다시 줄이려면이 중 하나를 수행 할 필요가 없습니다.이 루프를 가속시키는 가장 좋은 방법은 정확한 조건에 따라 가능한 다른 접근 방식을 사용하는 것입니다. – varocarbas

답변

1

와우 내가 안전하지 않은 코드를 좋아하는, 말 여기

에서 C#을 내 문제를 해결 내 질문에 빠른 코드 약 70 배를 인 코드이며, 무엇을

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; 
     } 
    } 
} 
1

에서 vb.net에서 질문, 대답, 최고의 당신이 할 수있는 일은 두 번째 그래프 생성 과정 (또한 board)을 피하고 _board에서 정보를 복사하는 것입니다. 새로운 세대보다 복사 속도가 훨씬 빠르지 만 소스 정보 (_board)가 대상 형식 (.SetPixel에 의존하여 board)과 일치하지 않으므로 다음을 결정하는 기능을 만들어야합니다. 제공된 정보 (현재 사각형)로부터 현재 픽셀 (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 방법을 사용하는 것이 좋습니다.

의견을 통해 말했듯이, 이것이 내가 현재 상황에서 할 수있는 모든 것입니다. 최선의 해결책을 찾는데 도움이되기를 바랍니다. 이 worthed 때

+1

각 개별 픽셀을 수행한다는 아이디어를 얻었고 솔루션을 만들었습니다. 코드에 대한 제 대답을 살펴보십시오. 감사! +1 – Fredou

+0

@ Fredou 귀하의 문제를 해결할 수있어서 기쁩니다. +1. 귀하의 코드를 테스트하지는 못했지만 정상적으로 작동한다고 생각합니다. 작은 하나지만 : 당신의 코드는 C#이고 질문은 VB.NET으로 태그가 붙어 있습니다. – varocarbas

+0

vb.net과 C# 둘 다 사용되는 이유를 설명하는 작은 편집으로 태그를 업데이트했습니다. – Fredou