2017-04-03 6 views
1

Universal Windows App에서 .pgm 이미지를 표시해야합니다. XAML 이미지 컨트롤은 .pgm 이미지를 직접 지원하지 않으므로이를 해결해야합니다.Universal Windows App (C#, XAML)에서 Portable Graymap (PGM) 이미지 표시

인터넷에서 C#으로 .pgm 파일을 여는 많은 예제가 있지만이 모든 것은 Universal Windows 플랫폼에서 지원되지 않는 Bitmap 개체를 사용합니다 (System.Drawing 및 System.Windows.Media 라이브러리는 지원되지 않습니다). 사용).

이미지 너비와 높이를 읽고 바이트 배열의 픽셀 (회색 음영을 나타내는 0-255 값 포함)을 읽는 코드가 있습니다.

다음 단계는 결국 XAML Image.Source에 전달 될 수있는 모든 개체를 사용하여 바이트 [] 배열에서 이미지를 그립니다 (적절한 시간 내에 수행).

내가하고 관리하는 가장 좋은

this 을 표시했지만 실제 사진이 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 이미지에서 생성 된 배열은 픽셀을 설명하는 데 한 바이트 만 사용됩니다. 간단히 배열을 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을 사용하여 pgm 파일에서로드하는 PgmByteData을 저장하려고했습니다. 그리고 그것은 잘 작동합니다.

회색 음영을 나타내는 0-255 값을 포함하는 바이트 배열의 픽셀입니다. 따라서 BitmapPixelFormat.Gray8BitmapPixelFormat으로 사용할 수 있습니다. 구름은 SoftwareBitmap을 다음 코드로 생성합니다.

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

현재, 화상 제어 만 BGRA8 부호화 및 프리가 승산 된 이미지 또는 사용하는 알파 채널을 지원한다. 이미지를 표시하기 전에 올바른 형식인지 테스트하고 그렇지 않은 경우 SoftwareBitmap 정적 Convert 메서드를 사용하여 이미지를 지원되는 형식으로 변환하십시오.

자세한 내용은 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

관련 문제