【问题标题】:Windows 8 - Save Image in XAML as local file ( inside Application folder )Windows 8 - 将 XAML 中的图像另存为本地文件(在应用程序文件夹内)
【发布时间】:2014-04-17 04:10:37
【问题描述】:

在我的 Windows 商店应用程序中,我使用 XAML 中的 Image 控件显示图片。 Image 控件的来源已设置,代码明智地使用 WriteableBitmap。我正在尝试将此图像作为 附件 发送到 email 中。有什么简单的方法吗?我正在尝试将该图像保存在本地(在应用程序中)并将该保存的图像附加到电子邮件中。但无法在本地保存。任何帮助表示赞赏。

这里是代码。

位图 = 等待 WriteableBitmapRenderExtensions.Render(dataCanvas);
image.Source = 位图;

dataCanvas 是一个 Canvas 控件,由两个图像组成,一个位置在另一个位置之上。实际上,我必须在用户脸上放置一个太阳镜顶部并将其显示为 xaml 中的另一个图像。同时通过电子邮件发送该图片。

【问题讨论】:

    标签: c# xaml windows-8 windows-runtime windows-store-apps


    【解决方案1】:

    查看 WinRT XAML 工具包中的 WriteableBitmapSaveExtensions 类,了解可用于保存 WriteableBitmap 的所有 SaveToFile() 扩展方法。

    核心是这样的:

    public static async Task SaveToFile(
        this WriteableBitmap writeableBitmap,
        StorageFile outputFile,
        Guid encoderId)
    {
        Stream stream = writeableBitmap.PixelBuffer.AsStream();
        byte[] pixels = new byte[(uint)stream.Length];
        await stream.ReadAsync(pixels, 0, pixels.Length);
    
        using (var writeStream = await outputFile.OpenAsync(FileAccessMode.ReadWrite))
        {
            var encoder = await BitmapEncoder.CreateAsync(encoderId, writeStream);
            encoder.SetPixelData(
                BitmapPixelFormat.Bgra8,
                BitmapAlphaMode.Premultiplied,
                (uint)writeableBitmap.PixelWidth,
                (uint)writeableBitmap.PixelHeight,
                96,
                96,
                pixels);
            await encoder.FlushAsync();
    
            using (var outputStream = writeStream.GetOutputStreamAt(0))
            {
                await outputStream.FlushAsync();
            }
        }
    }
    

    您可以使用方法的重载来获取编码器ID:

    public static async Task<StorageFile> SaveToFile(
        this WriteableBitmap writeableBitmap,
        StorageFolder storageFolder,
        string fileName,
        CreationCollisionOption options = CreationCollisionOption.ReplaceExisting)
    {
        StorageFile outputFile =
            await storageFolder.CreateFileAsync(
                fileName,
                options);
    
        Guid encoderId;
    
        var ext = Path.GetExtension(fileName);
    
        if (new[] { ".bmp", ".dib" }.Contains(ext))
        {
            encoderId = BitmapEncoder.BmpEncoderId;
        }
        else if (new[] { ".tiff", ".tif" }.Contains(ext))
        {
            encoderId = BitmapEncoder.TiffEncoderId;
        }
        else if (new[] { ".gif" }.Contains(ext))
        {
            encoderId = BitmapEncoder.GifEncoderId;
        }
        else if (new[] { ".jpg", ".jpeg", ".jpe", ".jfif", ".jif" }.Contains(ext))
        {
            encoderId = BitmapEncoder.JpegEncoderId;
        }
        else if (new[] { ".hdp", ".jxr", ".wdp" }.Contains(ext))
        {
            encoderId = BitmapEncoder.JpegXREncoderId;
        }
        else //if (new [] {".png"}.Contains(ext))
        {
            encoderId = BitmapEncoder.PngEncoderId;
        }
    
        await writeableBitmap.SaveToFile(outputFile, encoderId);
    
        return outputFile;
    }
    

    【讨论】:

    • 感谢 Filip 的回复,我知道我必须作为(Guid)encoderId 传递给这个方法的值是多少吗?到目前为止,我正在传递这些值, StorageFile targetFile = await KnownFolders.PicturesLibrary.CreateFileAsync("testImage" + Random + ".jpg");等待 SaveToFile(位图,targetFile,Windows.Graphics.Imaging.BitmapEncoder.JpegEncoderId);在目标位置创建图像,但只能看到前景图像(即太阳镜),看不到背景(用户的脸)。有什么帮助吗?
    • 如果您查看链接 - 有一种方法可以根据文件扩展名找出正确的编码器,但您也可以手动提供 - 检查 BitmapEncoder 类文档以获取定义不同的编码器指南。
    • 已编辑以上评论,有什么办法吗?
    • 如果我在应用程序文件夹中添加图像作为背景,一切正常。带有用户脸和太阳镜的图像可以在 xaml 中显示并保存在本地。但是,如果我使用从设备相机捕获的图像,则会在背景中显示黑屏。任何帮助表示赞赏。
    • 很遗憾,RenderTargetBitmap.Render() 结果中不包含各种媒体 - 只有基本的静态 UIElements。您可以手动捕获帧,并在视觉树渲染期间用图像替换实时相机预览。
    【解决方案2】:

    BitmapSource 的任何子类(包括WritableBitmap)都可以传递给BitmapEncoderBitmapEncoder 采用 Stream,编码的 JPEG、PNG 或其他图像写入其中。

    然后您可以使用邮件程序库来引用编码器使用的流,或者使用共享合约,并直接传递流。

    例子:

    var bitmap = new WritableBitmap();
    
    // ... draw your bitmap
    
    var tempPath = // path to where you want to save (probably in your appx temp);
    var encoder = new PngBitmapEncoder();
    
    encoder.Frames.Add(bitmap);
    
    using (var fs = new FileStream(tempPath))
    {
        encoder.Save(fs);
    }
    
    // use the image saved to tempPath
    // http://msdn.microsoft.com/en-us/library/windows/apps/xaml/hh871370.aspx
    

    【讨论】:

    • Window store 应用程序在盒子环境中运行,不提供系统级访问权限,因此您无法使用Path.GetTempPath()
    • @MuhammadUmar,这与将BitmapSource 保存到磁盘的要求没有任何关系。可以轻松地将适当的调用插入Windows.Storage.ApplicationData.Current.TemporaryFolder 作为替代。如果我们是迂腐的,WritableBitmap 甚至在 WinRT 中都不存在...
    • 我认为您必须提供适合 WinRT 的解决方案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-10
    • 2014-06-13
    • 1970-01-01
    相关资源
    最近更新 更多