2011-03-01 5 views
6

Sto provando a utilizzare SharpDX per creare un semplice programma 2D simile a labirinto con DirectX.Caricamento/Creazione di un'immagine in SharpDX in un programma .NET

A tal fine voglio creare bitmap che io possa rendere su schermo per le pareti, corridoi, al di fuori del labirinto, ecc

Tuttavia, non riesco a capire come sia carico un file immagine esistente nella classe Bitmap nella libreria SharpDX o come creare una nuova classe Bitmap da zero.

Poiché si dice che tutte le classi siano mappate direttamente sui tipi di DirectX, immagino che questo significhi solo che ho bisogno di saperne di più su DirectX, ma speravo che ci fosse un semplice esempio da qualche parte che potesse mostrarmi cosa devo fare.

Se devo creare una nuova Bitmap da zero e disegnare su di essa, posso farlo, non è difficile ottenere i pixel di cui ho bisogno, tuttavia non riesco nemmeno a capire quella parte.

Qualcuno ha esperienza con la libreria SharpDX e può darmi alcuni suggerimenti?

risposta

8

Si dovrebbe chiedere direttamente questa domanda alla scheda "Problema" sul progetto Sharpdx, in quanto sarei in grado di darvi una risposta rapida da lì (siete fortunati che a volte sto controllando il suo utilizzo dalla rete;)). Se lo chiedessi ufficialmente, potrei migliorare la libreria e tenere traccia della tua richiesta nel database dei problemi.

Per quanto riguarda il problema specifico, non è chiaro quale tipo di API DirectX si sta utilizzando. Suppongo che tu stia usando Direct2D?

Se sì, non esiste alcuna API per caricare direttamente un SharpDX.Direct2D1.Bitmap da un file (aggiungerò questo metodo all'API). Ho appena caricato un bitmap sample che sta eseguendo questo.

/// <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); 
     } 
    } 
} 

Come hai detto, SharpDX sta dando accesso alle DirectX API-basso livello prima (a differenza ad esempio XNA che sta dando un'API di livello superiore), quindi è sicuramente bisogno di capire in che modo il programma DirectX prima in ordine usare SharpDX.

0

Indietro quando stavo usando SlimDX, ho incontrato lo stesso problema (caricando una bitmap usando Direct2D) e ho trovato una soluzione simile che elimina il ciclo incorporato e richiede un po 'meno codice; convertirlo in SharpDX era una questione semplice. (Vorrei poterti dire dove ho trovato l'originale, ma sono anni e apparentemente non ho documentato la fonte. Potrebbe essere uscito dagli esempi SlimDX per quanto ne so.)

Ho lasciato gli spazi dei nomi intatto in modo da sapere esattamente dove ogni tipo è definito. Inoltre, alcuni dei parametri (in particolare quelli per PixelFormat) sono flessibili; gioca con loro e usa qualunque cosa funzioni per te.

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

Come si può vedere, si blocca il flusso di bitmap tanto quanto l'approccio di Alexandre (che viene utilizzato nel progetto di esempio SharpDX associato), ma invece di copiare manualmente ogni pixel, il costruttore si copia il torrente dietro le quinte . Non ho confrontato le prestazioni con il metodo proposto da Alexandre, quindi non posso dirti quale metodo è più veloce, ma questo è abbastanza veloce per i miei scopi, e il codice è pulito.

(Ci scusiamo per la mancanza di evidenziazione della sintassi,. Il codice di < > tag per qualche motivo mi spezza il frammento in sezioni)