2017-04-03 1 views
1

Ich muss .pgm Bilder in meiner Universal Windows App anzeigen. XAML Image Control unterstützt .pgm Bilder nicht direkt, daher muss ich es umgehen. Im Internet gibt es viele Beispiele zum Öffnen von .pgm-Dateien in C#, aber alle verwenden das Bitmap-Objekt, das von der Universal Windows Platform nicht unterstützt wird (die Bibliotheken System.Drawing und System.Windows.Media können nicht verwendet werden).Portable Graymap (PGM) Bilder in der Universal Windows App (C#, XAML) anzeigen

Ich habe den Code, der die Breite und Höhe des Bildes liest und liest die Pixel in einem Byte-Array (mit Werten 0-255 für Graustufen).

Der nächste Schritt wäre, das Bild aus dem Array byte [] mit einem beliebigen Objekt zu zeichnen, das schließlich an die XAML Image.Source übergeben werden kann (und dies in einer angemessenen Zeitspanne).

Das Beste, was ich zu tun war, gelang this aber das eigentliche Bild soll wie this (aus irgendeinem Grund zeigt das Bild 4x und die Farben sind falsch es) sehen ist, angezeigt werden soll.

Der Code i verwendet:

public int width; 
    public int height; 
    public int maxVal; //255 
    public byte[] pixels; 

    public async Task<WriteableBitmap> ToWriteableBitmap() 
    { 
     WriteableBitmap writeableBitmap = new WriteableBitmap(width, height); 
     using (Stream stream = writeableBitmap.PixelBuffer.AsStream()) 
     { 
      await stream.WriteAsync(pixels, 0, pixels.Length); 
     } 
     return writeableBitmap; 
    } 

es egal Sollte ich die Bereitstellung auch den Code Ich verwende die .pgm Datei in das PgmImage Objekt zu lesen, aber ich bin mir ziemlich sicher, dass dies funktioniert:

public static async Task<PgmImage> LoadFromFile(string file) 
    { 
     FileStream ifs = null; 
     await Task.Run(() => 
     { 
      Task.Yield(); 
      ifs = new FileStream(file, FileMode.Open, FileAccess.Read); 
     }); 
     BinaryReader br = new BinaryReader(ifs); 

     string magic = NextNonCommentLine(br); 
     //if (magic != "P5") 
     // throw new Exception("Unknown magic number: " + magic); 

     string widthHeight = NextNonCommentLine(br); 
     string[] tokens = widthHeight.Split(' '); 
     int width = int.Parse(tokens[0]); 
     int height = int.Parse(tokens[1]); 

     string sMaxVal = NextNonCommentLine(br); 
     int maxVal = int.Parse(sMaxVal); 

     byte[] pixels = new byte[height * width]; 
     for (int i = 0; i < height * width; i++) 
     { 
      pixels[i] = br.ReadByte(); 
     } 
     return new PgmImage(width, height, maxVal, pixels); 
    } 

    static string NextAnyLine(BinaryReader br) 
    { 
     string s = ""; 
     byte b = 0; // dummy 
     while (b != 10) // newline 
     { 
      b = br.ReadByte(); 
      char c = (char)b; 
      s += c; 
     } 
     return s.Trim(); 
    } 

    static string NextNonCommentLine(BinaryReader br) 
    { 
     string s = NextAnyLine(br); 
     while (s.StartsWith("#") || s == "") 
      s = NextAnyLine(br); 
     return s; 
    } 

(es ist eine leicht bearbeitete Version davon: jamesmccaffrey.wordpress.com/2014/10/21/a-pgm-image-viewer-using-c). Ich sollte erwähnen, dass ich eine Lösung bevorzugen würde, die nicht auf Bibliotheken von Drittanbietern oder NuGet-Pakete angewiesen ist, aber ich bin verzweifelt und daher für alle Lösungen offen.

Antwort

0

Der WritableBitmap.PixelBuffer verwendet einen RGBA-Farbraum, was bedeutet, dass jedes Pixel mit vier Bytes im Byte-Array beschrieben wird, das vom PGM-Bild erzeugte Array jedoch nur ein Byte zur Beschreibung eines Pixels verwendet. Indem ich das Array viermal expandierte (und den Alpha-Wert für jedes Pixel auf den Maximalwert von 255 einstellte), hatte ich es geschafft, das richtige Display zu bekommen.

public async Task<WriteableBitmap> ToWriteableBitmap() 
    { 
     WriteableBitmap writeableBitmap = new WriteableBitmap(width, height); 

     byte[] expanded = new byte[pixels.Length * 4]; 
     int j = 0; 
     for (int i = 0; i< pixels.Length; i++) 
     { 
      expanded[j++] = pixels[i]; 
      expanded[j++]= pixels[i]; 
      expanded[j++] = pixels[i]; 
      expanded[j++] = 255; //Alpha 
     } 

     using (Stream stream = writeableBitmap.PixelBuffer.AsStream()) 
     { 
      await stream.WriteAsync(expanded, 0, expanded.Length); 
     } 
     return writeableBitmap; 
    } 
0

Ich habe Ihren Code getestet und reproduziert Ihr Problem. Das Problem ist WriteableBitmap konnte nicht perfekt von xmal Steuerung geladen werden.

Ich habe versucht, SoftwareBitmap zu verwenden, PgmByteData zu speichern, die von pgm-Datei laden. Und es funktioniert gut.

Ihre Pixel in einem Byte-Array mit Werten von 0-255, die Graustufen darstellen. So könnten Sie BitmapPixelFormat.Gray8 als BitmapPixelFormat verwenden. Sie Cloud erstellen SoftwareBitmap als den folgenden Code.

SoftwareBitmap softwareBitmap = new SoftwareBitmap(BitmapPixelFormat.Gray8, (int)width, (int)height); 
      softwareBitmap.CopyFromBuffer(pgmByteData.AsBuffer()); 

Derzeit unterstützt die Bildsteuerung nur Bilder, die Codierung und BGRA8 vormultipliziert oder keinen Alphakanal verwendet werden. Bevor Sie versuchen, ein Bild anzuzeigen, prüfen Sie, ob es das richtige Format hat. Wenn nicht, verwenden Sie die statische Konvertierungsmethode von SoftwareBitmap, um das Bild in das unterstützte Format zu konvertieren.

Für weitere Informationen verweisen Sie bitte Use SoftwareBitmap with a XAML Image control.

if (softwareBitmap.BitmapPixelFormat != BitmapPixelFormat.Bgra8 || 
    softwareBitmap.BitmapAlphaMode == BitmapAlphaMode.Straight) 
{ 
    softwareBitmap = SoftwareBitmap.Convert(softwareBitmap, BitmapPixelFormat.Bgra8, BitmapAlphaMode.Premultiplied); 
} 

var source = new SoftwareBitmapSource(); 
await source.SetBitmapAsync(softwareBitmap); 

// Set the source of the Image control 
imageControl.Source = source; 

Die code sample hat hochgeladen. Bitte prüfe.

+0

Vielen Dank Nico für Ihre schnelle und detaillierte Antwort. Ich hatte auch meine eigene Lösung gefunden, indem ich das Byte [] auf die BGRA-Kodierung ausdehnte. Ich habe den Code als Antwort gepostet; vielleicht wird jemand es nützlich finden. – zvjeverica

Verwandte Themen