【问题标题】:C# / WinRT: How to save image to fileC#/WinRT:如何将图像保存到文件
【发布时间】:2014-01-16 00:18:28
【问题描述】:

我是一名 iOS 开发人员,正在学习 Windows 应用商店应用程序开发,之前没有任何 Microsoft 技术经验。

我需要将图像保存到文件中。我认为这很容易,但我已经做了一天,我没有什么可以展示的。这在 Windows 中非常困难,或者由于对平台/API 的无知而遗漏了一些东西。

我需要保存的图片来源是Windows.UI.Xaml.Media.Imaging.RenderTargetBitmap。 RenderTargetBitmap 可以将图像作为 Windows.UI.Xaml.Controls.Image 的源或作为 IBuffer 返回。

我可以验证 RenderTargetBitmap 是否正确渲染图像。但是,我无法将图像保存到文件中。我希望 Image 有一个 Save() 方法,但它没有。所以我想我需要以某种方式使用 IBuffer 。我接近了,我能够将缓冲区保存到磁盘,但它是未编码的,所以我无法打开它。

所以,接下来,我尝试将缓冲区转换为流,并使用 BitmapEncoder 将其编码为 PNG。那行得通,但这让我在 IRandomAccessStream 中留下了我的 PNG 数据。我不知道如何将 IRandomAccessStream 保存到文件中。

我尝试了 5-10 种不同的复杂方法,例如通过类型转换地狱尝试将 IRandomAccessStream 转换为 IBuffer,以便我可以在文件流上使用 .WriteAsync()。我尝试在 IRandomAccessStream 上的 DataReader 提供的文件流上使用 DataWriter,但遇到了类型不匹配的问题。等等等等。

那么,如何保存我的文件?到目前为止,这是我得到的:

private async void saveButton_Click(object sender, RoutedEventArgs e)
{

    //Create a new temporary image for saving
    //Image tempImage = new Image();

    //Create a render object
    RenderTargetBitmap renderTargetBitmap = new RenderTargetBitmap();
    //Render the app's display buffer
    await renderTargetBitmap.RenderAsync(null);
    //Set the temp image to the contents of the app's display buffer
    //tempImage.Source = renderTargetBitmap;

    //Create a new file picker, set the default name, and extenstion
    FileSavePicker savePicker = new FileSavePicker();
    savePicker.SuggestedFileName = "New LightTable.png";
    savePicker.FileTypeChoices.Add("Image", new List<string>(){".png"});

    //Get the file the user selected
    StorageFile saveFile = await savePicker.PickSaveFileAsync();

    //Only move on if the user actually selected a file
    if (saveFile != null)
    {
        //Get a buffer of the pixels captured from the screen
        Windows.Storage.Streams.IBuffer buffer = await renderTargetBitmap.GetPixelsAsync();

        //Get a stream of the data in the buffer
        System.IO.Stream stream = buffer.AsStream();

        //Convert the stream into a IRandomAccessStream because I don't know what I'm doing.
        Windows.Storage.Streams.IRandomAccessStream raStream = stream.AsRandomAccessStream();

        //Attempt to encode the stream into a PNG
        BitmapEncoder encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.PngEncoderId, raStream);

        //Get a stream for the file the user selected
        Windows.Storage.Streams.IRandomAccessStream fileStream = await saveFile.OpenAsync(Windows.Storage.FileAccessMode.ReadWrite);

        //FIND SOME WAY TO SAVE raStream TO fileStream
        //Something like:
        // await fileStream.WriteAsync(raStream.AsStreamForRead());

    }

}

要么我只是错过了最后:如何将我的 raStream 写入文件,要么我的方法完全关闭。

感谢您的帮助。请记住,我现在只使用 Microsoft 技术进行开发一周。我没有 .NET、Silverlight 或其他 MS 技术经验。从 iOS 上的 UIImage 控件保存编码图像是一个单一的方法调用,所以我正在盘旋的解决方案的剪切复杂性让我觉得我错过了一些我不知道的非常简单的东西。

【问题讨论】:

    标签: c# windows xaml windows-runtime windows-8.1


    【解决方案1】:

    您需要将像素数据设置到 StorageFile 流中。示例见http://basquang.wordpress.com/2013/09/26/windows-store-8-1-save-visual-element-to-bitmap-image-file/

    【讨论】:

    • 这在我的应用程序中不起作用。我收到 SetPixelData 方法调用引发的“值不在范围内”异常。我认为这与 DPI 值有关。我尝试将 DPI 值设置为 DisplayInformation.LogicalDPI 但没有帮助。你有什么想法。我知道这是如此接近。谢谢。
    • 好的,我想通了。由于 Windows 缩放事物以处理多种分辨率的所有疯狂方式,我遇到了问题。一旦我得到正确图像的尺寸,一切都很好。
    • “值不在范围内”通常是指在管理图像时“达到内存限制”...
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-31
    • 2021-02-01
    • 1970-01-01
    相关资源
    最近更新 更多