简体   繁体   English

在通用Windows应用程序中显示便携式灰度图(PGM)图像(c#,XAML)

[英]Displaying Portable Graymap (PGM) images in Universal Windows App (c#, XAML)

I need to display .pgm images in my Universal Windows App. 我需要在我的通用Windows应用程序中显示.pgm图像。 XAML Image control does not directly support .pgm images so I need to work around it. XAML图像控件不直接支持.pgm图像,所以我需要解决它。

There are many examples on the internet of opening .pgm files in c#, but all of these rely on using the Bitmap object which is not supported in Universal Windows Platform (the System.Drawing and System.Windows.Media libraries cannot be used). 互联网上有许多以c#开头.pgm文件的例子,但所有这些都依赖于使用通用Windows平台不支持的Bitmap对象(不能使用System.Drawing和System.Windows.Media库)。

I've got the code that reads the image width and height and reads the pixels in a byte array (containing values 0-255 representing gray shades). 我有代码读取图像的宽度和高度,并读取字节数组中的像素(包含代表灰色阴影的值0-255)。

The next step would be to draw the image from the byte[] array using any object that can eventually be passed to the XAML Image.Source (and to do it in a reasonable amount of time). 下一步是使用最终可以传递给XAML Image.Source的任何对象从byte []数组中绘制图像(并在合理的时间内完成)。

The best I managed to do was to display this but the actual picture is supposed to look like this (for some reason it shows the image 4x and the colors are wrong). 我设法做的最好的是显示这个,但实际的图片应该看起来像这样 (由于某种原因,它显示图像4x,颜色是错误的)。

The code i used: 我使用的代码:

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

Should it matter, I'm also providing the code I use to read the .pgm file to the PgmImage object, but I'm pretty sure this works fine: 它是否重要,我也提供了我用来将.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;
    }

(it's a slightly edited version of this: jamesmccaffrey.wordpress.com/2014/10/21/a-pgm-image-viewer-using-c). (这是一个略微编辑的版本:jamesmccaffrey.wordpress.com/2014/10/21/a-pgm-image-viewer-using-c)。 I should mention that I would prefer a solution that does not depend on any third-party libraries or NuGet packages, but I am desperate and therefore open to any solutions. 我应该提一下,我更喜欢不依赖于任何第三方库或Nu​​Get包的解决方案,但我绝望,因此对任何解决方案都开放。

I have tested your code and reproduced your issue. 我已经测试了您的代码并重现了您的问题。 The problem is WriteableBitmap could not be perfectly loaded by xmal control. 问题是xable控件无法完美地加载WriteableBitmap

I have tried to use SoftwareBitmap to store PgmByteData that load from pgm file. 我试图使用SoftwareBitmap来存储从pgm文件加载的PgmByteData And it Works fine. 它工作正常。

Your pixels in a byte array containing values 0-255 representing gray shades.So you could use BitmapPixelFormat.Gray8 as BitmapPixelFormat . 字节数组中的像素包含表示灰色阴影的值0-255。因此,您可以使用BitmapPixelFormat.Gray8作为BitmapPixelFormat You cloud create SoftwareBitmap as the following code. 您可以使用以下代码创建SoftwareBitmap

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

Currently, the Image control only supports images that use BGRA8 encoding and pre-multiplied or no alpha channel. 目前,Image控件仅支持使用BGRA8编码和预乘或无alpha通道的图像。 Before attempting to display an image, test to make sure it has the correct format, and if not, use the SoftwareBitmap static Convert method to convert the image to the supported format. 在尝试显示图像之前,请进行测试以确保其格式正确,如果没有,请使用SoftwareBitmap静态Convert方法将图像转换为支持的格式。

For more information please reference Use SoftwareBitmap with a XAML Image control . 有关更多信息,请参阅使用SoftwareBitmap和XAML Image控件

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;

The code sample has upload. 代码示例已上传。 Please check. 请检查。

The WritableBitmap.PixelBuffer uses a RGBA color space which means every pixel is described with four bytes in the byte array, but the array generated from the PGM image uses only one byte to describe a pixel. WritableBitmap.PixelBuffer使用RGBA颜色空间,这意味着每个像素在字节数组中用四个字节描述,但是从PGM图像生成的数组仅使用一个字节来描述像素。 By simply expanding the array 4 times (and setting the alpha value for each pixel to the max value of 255) I had managed to get the right display. 通过简单地扩展阵列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;
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 在Windows Universal App中使用C#在XAML中着墨 - Inking in XAML with C# in a Windows Universal App C#Xaml(Windows Universal App)打开新页面 - C# Xaml (Windows Universal App) open new Page C#XAML Windows通用加载对话框 - C# XAML Windows Universal Loading Dialog WinRT ListView,将itemsource作为列表 <KeyValuePair<string, string> &gt;错误XAML(Windows 8.1通用应用程序(XAML / C#)) - WinRT ListView with itemsource as List<KeyValuePair<string, string>> error XAML (Windows 8.1 Universal App (XAML/C#)) 更改所有图像坐标[Windows Store App,C#/ XAML] - Change all images coordinates [Windows Store App, C#/XAML] 客户端发出一些请求后,TCP服务器停止响应[Windows 10 Universal app,C#,XAML] - TCP server stops responding after a few requests from client [Windows 10 Universal app, C#, XAML] Windows XAML通用便携式库中的Windows Phone API在哪里? - Where are the Windows Phone APIs in Windows XAML Universal Portable Library? 在Windows通用应用程序C中流式传输图像 - streaming images in windows universal apps c# 在C#XAML应用中显示PowerBI磁贴 - Displaying a PowerBI tile in a C# XAML app Windows Universal无法在C#中引用XAML控件? - Windows Universal Can't Reference XAML Control in C#?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM