我需要在我的通用Windows应用程序中显示.pgm图像 . XAML图像控件不直接支持.pgm图像,所以我需要解决它 .
在互联网上有很多例子在c#中打开.pgm文件,但所有这些都依赖于使用通用Windows平台不支持的Bitmap对象(不能使用System.Drawing和System.Windows.Media库) .
我有代码读取图像的宽度和高度,并读取字节数组中的像素(包含代表灰色阴影的值0-255) .
下一步是使用最终可以传递给XAML Image.Source的任何对象从byte []数组中绘制图像(并在合理的时间内完成) .
我设法做的最好的是显示this,但实际的图片应该看起来像this(由于某种原因,它显示图像4x,颜色是错误的) .
我使用的代码:
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) . 我应该提一下,我更喜欢不依赖于任何第三方库或NuGet包的解决方案,但我绝望,因此对所有解决方案都持开放态度 .
2 回答
我已经测试了您的代码并重现了您的问题 . 问题是
WriteableBitmap
无法通过xmal控件完美加载 .我试图使用
SoftwareBitmap
来存储从pgm文件加载的PgmByteData
. 它工作正常 .字节数组中的像素包含表示灰色阴影的值0-255 . 因此,您可以使用BitmapPixelFormat.Gray8作为
BitmapPixelFormat
. 您将 Cloud 创建为SoftwareBitmap
,如下面的代码所示 .有关更多信息,请参阅Use SoftwareBitmap with a XAML Image control .
code sample已上传 . 请检查 .
WritableBitmap.PixelBuffer使用RGBA颜色空间,这意味着每个像素在字节数组中用四个字节描述,但是从PGM图像生成的数组仅使用一个字节来描述像素 . 通过简单地扩展阵列4次(并将每个像素的alpha值设置为最大值255),我设法得到了正确的显示 .