2011-03-01 17 views
6

Próbuję użyć SharpDX do stworzenia prostego programu 2D podobnego do labiryntu przy użyciu DirectX.Ładowanie/Tworzenie obrazu w SharpDX w programie .NET

W tym celu chcę utworzyć bitmap, że mogę render na ekranie do ściany, korytarze, poza labirynt itp

Jednak nie wydaje się dowiedzieć się, jak też obciążenie istniejący plik obrazu do klasy Bitmap w bibliotece SharpDX lub jak utworzyć nową taką klasę Bitmap od zera.

Ponieważ wszystkie klasy są mapowane bezpośrednio na typy DirectX, myślę, że to po prostu oznacza, że ​​muszę nauczyć się więcej DirectX, ale miałem nadzieję, że istnieje prosty przykład gdzieś, który mógłby pokazać mi, co muszę zrobić.

Jeśli muszę skonstruować nową bitmapę od nowa i narysować ją, mogę to zrobić, nie jest trudno uzyskać potrzebne piksele, ale nie mogę nawet wymyślić tej części.

Czy ktoś ma jakiekolwiek doświadczenia z biblioteką SharpDX i może mi podać wskazówki?

Odpowiedz

8

Powinieneś zadać to pytanie bezpośrednio w zakładce "Problem" w projekcie Sharpdx, ponieważ byłbym w stanie dać ci szybką odpowiedź (masz szczęście, że czasami sprawdzam jego użycie z sieci;)). Jeśli pytasz o to oficjalnie, mógłbym ulepszyć bibliotekę i zachować zapis twoich żądań w bazie danych o problemach.

Jeśli chodzi o konkretny problem, nie jest jasne, jakiego rodzaju API DirectX używasz. Zakładam, że używasz Direct2D?

Jeśli tak, nie ma interfejsu API do bezpośredniego załadowania pliku SharpDX.Direct2D1.Bitmap z pliku (dodam tę metodę do interfejsu API). Właśnie przesłałem bitmap sample, który to wykonuje.

/// <summary> 
/// Loads a Direct2D Bitmap from a file using System.Drawing.Image.FromFile(...) 
/// </summary> 
/// <param name="renderTarget">The render target.</param> 
/// <param name="file">The file.</param> 
/// <returns>A D2D1 Bitmap</returns> 
public static Bitmap LoadFromFile(RenderTarget renderTarget, string file) 
{ 
    // Loads from file using System.Drawing.Image 
    using (var bitmap = (System.Drawing.Bitmap)System.Drawing.Image.FromFile(file)) 
    { 
     var sourceArea = new System.Drawing.Rectangle(0, 0, bitmap.Width, bitmap.Height); 
     var bitmapProperties = new BitmapProperties(new PixelFormat(Format.R8G8B8A8_UNorm, AlphaMode.Premultiplied)); 
     var size = new System.Drawing.Size(bitmap.Width, bitmap.Height); 

     // Transform pixels from BGRA to RGBA 
     int stride = bitmap.Width * sizeof(int); 
     using (var tempStream = new DataStream(bitmap.Height * stride, true, true)) 
     { 
      // Lock System.Drawing.Bitmap 
      var bitmapData = bitmap.LockBits(sourceArea, ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppPArgb); 

      // Convert all pixels 
      for (int y = 0; y < bitmap.Height; y++) 
      { 
       int offset = bitmapData.Stride*y; 
       for (int x = 0; x < bitmap.Width; x++) 
       { 
        // Not optimized 
        byte B = Marshal.ReadByte(bitmapData.Scan0, offset++); 
        byte G = Marshal.ReadByte(bitmapData.Scan0, offset++); 
        byte R = Marshal.ReadByte(bitmapData.Scan0, offset++); 
        byte A = Marshal.ReadByte(bitmapData.Scan0, offset++); 
        int rgba = R | (G << 8) | (B << 16) | (A << 24); 
        tempStream.Write(rgba); 
       } 

      } 
      bitmap.UnlockBits(bitmapData); 
      tempStream.Position = 0; 

      return new Bitmap(renderTarget, size, tempStream, stride, bitmapProperties); 
     } 
    } 
} 

Jak powiedział SharpDX daje dostęp do DirectX API raw-niskim poziomie (w przeciwieństwie na przykład XNA, który daje większą API poziom), więc na pewno trzeba zrozumieć, jak programu surowego DirectX w celu używać SharpDX.

0

Powrót, gdy używałem SlimDX, natknąłem się na ten sam problem (ładowanie mapy bitowej za pomocą Direct2D) i znalazłem podobne rozwiązanie, które eliminuje wbudowaną pętlę i wymaga nieco mniej kodu; przekonwertowanie go na SharpDX było proste. (Chciałbym móc powiedzieć, gdzie znalazłem oryginał, ale minęły lata i najwyraźniej nie udokumentowałem źródła, może to być prosto z próbek SlimDX ze wszystkiego, co wiem.)

Opuściłem przestrzenie nazw nienaruszone, dzięki czemu wiesz dokładnie, gdzie zdefiniowany jest każdy typ. Ponadto niektóre parametry (szczególnie te dla PixelFormat) są elastyczne; baw się z nimi i używaj wszystkiego, co działa dla ciebie.

 
private Bitmap Load(string filename) 
{ 
    System.Drawing.Bitmap bmp = (System.Drawing.Bitmap)System.Drawing.Image.FromFile(filename); 

    System.Drawing.Imaging.BitmapData bmpData = 
     bmp.LockBits(
      new System.Drawing.Rectangle(0, 0, bmp.Width, bmp.Height), 
      System.Drawing.Imaging.ImageLockMode.ReadOnly, 
      System.Drawing.Imaging.PixelFormat.Format32bppPArgb); 

    SharpDX.DataStream stream = new SharpDX.DataStream(bmpData.Scan0, bmpData.Stride * bmpData.Height, true, false); 
    SharpDX.Direct2D1.PixelFormat pFormat = new SharpDX.Direct2D1.PixelFormat(SharpDX.DXGI.Format.B8G8R8A8_UNorm, AlphaMode.Premultiplied); 
    SharpDX.Direct2D1.BitmapProperties bmpProps = new SharpDX.Direct2D1.BitmapProperties(pFormat); 

    SharpDX.Direct2D1.Bitmap result = 
     new SharpDX.Direct2D1.Bitmap(
      m_renderTarget, 
      new SharpDX.Size2(bmp.Width, bmp.Height), 
      stream, 
      bmpData.Stride, 
      bmpProps); 

    bmp.UnlockBits(bmpData); 

    stream.Dispose(); 
    bmp.Dispose(); 

    return result; 
} 

Jak widać, to blokuje strumień bitmapy ile podejścia Alexandre (która jest używana w powiązanym przykładowy projekt SharpDX), ale zamiast ręcznie kopiując każdy piksel, sam konstruktor kopiuje strumień za kulisami . Nie porównałem wydajności z metodą, którą zaproponował Alexandre, więc nie mogę powiedzieć, która metoda jest szybsza, ale ta jest wystarczająco szybka dla moich celów, a kod jest czysty.

(przepraszam za brak podświetlanie składni,. Kod < > tag z jakiegoś powodu łamie mi fragment na sekcje)

Powiązane problemy