2017-04-03 11 views
1

Universal Windows Appに.pgmイメージを表示する必要があります。 XAML Imageコントロールは.pgmイメージを直接サポートしていないので、回避する必要があります。Universal Windows App(c#、XAML)でPortable Graymap(PGM)イメージを表示

インターネット上には、c#で.pgmファイルを開く例がたくさんありますが、これらはすべてUniversal WindowsプラットフォームでサポートされていないBitmapオブジェクトを使用しています(System.DrawingおよびSystem.Windows.Mediaライブラリではできません)。利用される)。

イメージの幅と高さを読み取り、バイト配列(灰色の色合いを表す0〜255の値を含む)のピクセルを読み取るコードがあります。

次の手順は、最終的にXAML Image.Sourceに渡すことができる任意のオブジェクトを使用して(そして妥当な時間内に行う)、byte []配列からイメージを描画することです。

私がやることに成功し、最良のthis を表示するようにしたが、実際の画像が(何らかの理由でそれが画像4倍を示し、色が間違っている)thisのように見えることになっています。

私が使用したコード:

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

それは問題なら、私はまた、私はPgmImageオブジェクトに.PGMファイルを読み込むために使用するコードを提供していますが、私は、これは正常に動作しますかなり確信しています:

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)。 サードパーティのライブラリやNuGetパッケージに依存しないソリューションを好むと言わざるを得ないが、私は絶望的であり、したがっていかなる解決策も開いている。

答えて

0

WritableBitmap.PixelBufferはRGBAカラースペースを使用します。これは、すべてのピクセルがバイト配列で4バイトで記述されることを意味しますが、PGMイメージから生成された配列はピクセルを記述するために1バイトのみを使用します。単に配列を4倍に拡大するだけで、各ピクセルのアルファ値を最大値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.Gray8BitmapPixelFormatとして使用できます。あなたは次のコードとしてSoftwareBitmapを作成します。

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

現在、ImageコントロールはBGRA8エンコーディングとプリ掛けまたはアルファチャンネルを使用して画像をサポートしています。イメージを表示する前に、正しい形式であることを確認し、そうでない場合は、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

あなたの素早く詳細な回答をいただきありがとうございます。私はBGRAのエンコーディングに合わせてバイト[]を拡張することで私自身の解決策を見つけました。私は答えとしてコードを投稿しました。多分誰かがそれが有用であると感じるでしょう。 – zvjeverica

関連する問題