2017-04-03 56 views
1

我需要在我的通用Windows應用程序中顯示.pgm圖像。 XAML圖像控件不直接支持.pgm圖像,所以我需要解決它。在通用Windows應用程序(c#,XAML)中顯示便攜式灰度圖(PGM)圖像

在c#中打開.pgm文件的互聯網上有很多例子,但所有這些都依賴於使用通用Windows平臺不支持的Bitmap對象(System.Drawing和System.Windows.Media庫不能使用)。

我已經得到了讀取圖像寬度和高度的代碼,並讀取字節數組中的像素(包含代表灰色陰影的值0-255)。

下一步將使用任何可以最終傳遞給XAML Image.Source(並在合理的時間內完成)的對象從byte []數組中繪製圖像。

我能夠做到的最好的是顯示this 但實際的圖片應該看起來像this(由於某種原因,它顯示的圖像和4倍的顏色是錯誤的)。

我使用的代碼:

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

應該有關係,我也提供我用讀.PGM文件到PgmImage對象的代碼,但我敢肯定,這工作得很好:

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

(它是這一個稍微修改版本:jamesmccaffrey.wordpress.com/2014/10/21/a-pgm-image-viewer-using-c)。 我應該提到,我更喜歡不依賴任何第三方庫或Nu​​Get軟件包的解決方案,但我絕望,因此對任何解決方案都開放。

回答

0

WritableBitmap.PixelBuffer使用RGBA顏色空間,這意味着每個像素都用字節數組中的四個字節來描述,但從PGM圖像生成的數組只使用一個字節來描述一個像素。 通過簡單地擴展數組4次(並將每個像素的alpha值設置爲最大值255),我設法獲得了正確的顯示。

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

我測試了你的代碼並重現了你的問題。問題是WriteableBitmap無法通過xmal控制完美加載。

我試圖使用SoftwareBitmap來存儲PgmByteData從pgm文件加載。它工作正常。

您的像素在字節數組中包含值0-255代表灰色陰影。因此,您可以使用BitmapPixelFormat.Gray8作爲BitmapPixelFormat。您的雲創建SoftwareBitmap作爲以下代碼。

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

目前,圖像控制僅支持使用BGRA8編碼和預乘以圖像或沒有alpha通道。嘗試顯示圖像之前,請測試以確保其格式正確,如果不正確,則使用SoftwareBitmap靜態轉換方法將圖像轉換爲支持的格式。

欲瞭解更多信息,請參閱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; 

code sample已上傳。請檢查。

+0

謝謝尼科爲您提供快速和詳細的答案。我還通過擴展byte []來適應BGRA編碼,找到了自己的解決方案。我已經發布了代碼作爲答案;也許有人會覺得它有用。 – zvjeverica

相關問題