c# - (UWP) 将网格另存为 png

标签 c# uwp uwp-xaml

我正在开发一个 UWP 应用程序,它有一个带有子元素、Image 和 TextBlock 的网格。我有两件事想要实现并且需要帮助。

  1. 如何使用预定义名称将 Grid 元素及其子内容作为图像(最好是 PNG)保存在本地文件夹中?

  2. 如何取回保存的图片,然后将其作为附件与其他兼容应用共享?

例子:

    <StackPanel Orientation="Vertical">
        <Grid Name="myGrid"
              HorizontalAlignment="Stretch"
              Background="Black">

            <Image Name="myImage"
                   Source="Assets/image1.png"
                   Stretch="Uniform"/>

            <TextBlock Name="myTextBlock"
                       HorizontalAlignment="Center"
                       VerticalAlignment="Center"
                       TextWrapping="Wrap"
                       Text="Sample user text"/>
        </Grid>

        <Button Name="saveButton"
                Content="Save"
                Margin="10,10,0,0"
                Click="saveButton_Click" />

        <Button Name="shareButton"
                Content="Share"
                Margin="10,10,0,0"
                Click="shareButton_Click" />
    </StackPanel>

编辑:在 saveButton_Click 事件中尝试了这段代码。似乎不起作用。

    RenderTargetBitmap rtb = new RenderTargetBitmap();
    await rtb.RenderAsync(myGrid);

    var pixelBuffer = await rtb.GetPixelsAsync();
    var pixels = pixelBuffer.ToArray();

    var displayInformation = DisplayInformation.GetForCurrentView();

    var stream = new InMemoryRandomAccessStream();
    var encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.PngEncoderId, stream);
    encoder.SetPixelData(BitmapPixelFormat.Bgra8,
                         BitmapAlphaMode.Premultiplied,
                         (uint)rtb.PixelWidth,
                         (uint)rtb.PixelHeight,
                         displayInformation.RawDpiX,
                         displayInformation.RawDpiY,
                         pixels);

    await encoder.FlushAsync();
    stream.Seek(0);

    FileStream filestream = File.Create("C:\\Users\\pcUser\\Desktop\\testimage.png", (int)stream.Size);

EDIT2:尝试了这段代码。它似乎有点工作,但我只得到一个黑色图像,这可能是因为它只保存 myGrid,而不是 child 内容。

    RenderTargetBitmap rtb = new RenderTargetBitmap();
    await rtb.RenderAsync(quoteGrid);

    var pixelBuffer = await rtb.GetPixelsAsync();
    var pixels = pixelBuffer.ToArray();

    var displayInformation = DisplayInformation.GetForCurrentView();

    var stream = new InMemoryRandomAccessStream();
    var encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.PngEncoderId, stream);
    encoder.SetPixelData(BitmapPixelFormat.Bgra8,
                         BitmapAlphaMode.Premultiplied,
                         (uint)rtb.PixelWidth,
                         (uint)rtb.PixelHeight,
                         displayInformation.RawDpiX,
                         displayInformation.RawDpiY,
                         pixels);

    await encoder.FlushAsync();
    stream.Seek(0);

    var wbm = new WriteableBitmap(rtb.PixelWidth, rtb.PixelHeight);
    await wbm.SetSourceAsync(stream);

    StorageFolder folder = ApplicationData.Current.LocalFolder;
    if (folder != null)
    {
        StorageFile file = await folder.CreateFileAsync("testImage" + ".png", CreationCollisionOption.ReplaceExisting);
        using (var storageStream = await file.OpenAsync(FileAccessMode.ReadWrite))
        {
            encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.PngEncoderId, storageStream);
            var pixelStream = wbm.PixelBuffer.AsStream();
            await pixelStream.ReadAsync(pixels, 0, pixels.Length);
            encoder.SetPixelData(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Premultiplied, (uint)wbm.PixelWidth, (uint)wbm.PixelHeight, displayInformation.RawDpiX, displayInformation.RawDpiY, new byte[pixelStream.Length]);
            await encoder.FlushAsync();
        }
    }

最佳答案

How do I save the Grid element along with it's child contents as an image(preferably PNG) in the local folder with a predefined name?

我已经检查了你的代码。您不需要使用 WriteableBitmap,只需将文件流传递给 BitmapEncoder.CreateAsync 方法即可。详情请查看以下代码:

private async void saveButton_Click(object sender, RoutedEventArgs e)
{
        RenderTargetBitmap rtb = new RenderTargetBitmap();
        await rtb.RenderAsync(myGrid);

        var pixelBuffer = await rtb.GetPixelsAsync();
        var pixels = pixelBuffer.ToArray();
        var displayInformation = DisplayInformation.GetForCurrentView();
        var file = await ApplicationData.Current.LocalFolder.CreateFileAsync("testImage" + ".png", CreationCollisionOption.ReplaceExisting);
        using (var stream = await file.OpenAsync(FileAccessMode.ReadWrite))
        {
            var encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.PngEncoderId, stream);
            encoder.SetPixelData(BitmapPixelFormat.Bgra8,
                                 BitmapAlphaMode.Premultiplied,
                                 (uint)rtb.PixelWidth,
                                 (uint)rtb.PixelHeight,
                                 displayInformation.RawDpiX,
                                 displayInformation.RawDpiY,
                                 pixels);
            await encoder.FlushAsync();
        }
}

How do I retrieve this saved image back and then include it as an attachment to share with other compatible apps?

对于您的情况,您将图片保存在本地文件夹中。所以如果你想得到它,你需要使用存储 API。例如:

var file = await ApplicationData.Current.LocalFolder.GetFileAsync("testImage.png");

关于“将其作为附件分享给其他兼容应用”,可以引用官方Sharing content source app sample了解详情。

关于c# - (UWP) 将网格另存为 png,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41354024/

相关文章:

c# - 如何在uwp中使用ssl证书

uwp - 如何确定 AppService 何时因 UWP 应用挂起或完全信任进程关闭而关闭?

连续操作 inkstrorkecontainer.clear() 和 addlines() 导致 UWP 中出现异常

c# - 如何使用 C# 迭代 "Related Links"

c# - 如何从 RSS 提要项中获取所有可能的图像 URL?

uwp - 如何将字节复制到 Windows::Storage::Streams::Buffer 或 Buffer 以通过 Windows::Storage::Streams::DataWriter::Write Buffer() 输出

c# - 防止在 UWP 中单击按钮之间失去焦点

mvvm - 设置UWP组合框的SelectedItem

c# - 将 xml 元素的内容读取为 double

c# - 为什么 System.IO.File 在文件确实存在时返回 false?