首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >WriteableBitmap到PNG

WriteableBitmap到PNG
EN

Stack Overflow用户
提问于 2015-11-18 14:39:01
回答 2查看 1.5K关注 0票数 0

我正在编写一个简单的WindowsStore应用程序,我无法找到如何将WriteableBitmap保存到某些PNG图像格式的内存流中,以获取这个PNG图像的字节。

到目前为止,我能找到的是如何在WP7.1上做到这一点,但是它不起作用。

任何人都能共享一个片段或指向有用的资源吗?

更新:

我使用WriteableBitmap来绘制它。

我有这个扩展方法。

代码语言:javascript
复制
public static async Task<byte[]> ConvertToPngBytes(this WriteableBitmap bitmap)
{
   using (IRandomAccessStream memoryStream = new InMemoryRandomAccessStream())
   {
      BitmapEncoder encode = await BitmapEncoder.CreateAsync(BitmapEncoder.PngEncoderId, memoryStream);
      byte[] buf = bitmap.PixelBuffer.ToArray();
      encode.SetPixelData(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Straight, (uint)bitmap.PixelWidth, (uint)bitmap.PixelHeight, 96.0, 96.0, buf);
      await encode.FlushAsync();
      await memoryStream.FlushAsync();

      var stream = memoryStream.AsStream();
      byte[] result = new byte[stream.Length];
      stream.Read(result, 0, result.Length);
      return result;
   }
}

它挂在await encode.FlushAsync();

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-11-19 18:50:02

结果是,BitmapEncoder需要一个填充了png数据的流。我在互联网上找到的每一个示例代码都需要一个现有的PNG文件,或者用一个选择器创建一个文件等等。我只想将我的WriteableBitmap保存到一个PNG格式的字节数组中。

作为解决方案,我创建了一个1x1像素的PNG文件,并将其字节复制到一个字节数组中。我不能用这个字节数组做一些操作,而且不需要从文件中读写任何东西。

以下是解决办法:

代码语言:javascript
复制
static readonly byte[] PngBytes = {
    137, 80, 78, 71, 13, 10, 26, 10, 0, 0, 0, 13, 73, 72, 68, 82, 0, 0, 0, 1, 0, 0, 0, 1,
    8, 6, 0, 0, 0, 31, 21, 196, 137, 0, 0, 0, 1, 115, 82, 71, 66, 0, 174, 206, 28, 233, 0,
    0, 0, 4, 103, 65, 77, 65, 0, 0, 177, 143, 11, 252, 97, 5, 0, 0, 0, 9, 112, 72, 89, 115,
    0, 0, 14, 195, 0, 0, 14, 195, 1, 199, 111, 168, 100, 0, 0, 0, 24, 116, 69, 88, 116, 83,
    111, 102, 116, 119, 97, 114, 101, 0, 112, 97, 105, 110, 116, 46, 110, 101, 116, 32, 52,
    46, 48, 46, 51, 140, 230, 151, 80, 0, 0, 0, 13, 73, 68, 65, 84, 24, 87, 99, 248, 255, 
    255, 255, 127, 0, 9, 251, 3, 253, 5, 67, 69, 202, 0, 0, 0, 0, 73, 69, 78, 68, 174, 66,
    96, 130
};

public static async Task<byte[]> ConvertToPngBytes(this WriteableBitmap bitmap)
{
    using (var memoryStream = new InMemoryRandomAccessStream())
    {
        await memoryStream.WriteAsync(PngBytes.AsBuffer());
        memoryStream.Seek(0);

        BitmapEncoder encode = await BitmapEncoder.CreateAsync(BitmapEncoder.PngEncoderId,
            memoryStream);
        byte[] buffer = bitmap.PixelBuffer.ToArray();
        encode.SetPixelData(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Straight, 
            (uint)bitmap.PixelWidth, (uint)bitmap.PixelHeight, 96.0, 96.0, buffer);
        await encode.FlushAsync();
        var stream = memoryStream.AsStream();
        stream.Seek(0, SeekOrigin.Begin);
        byte[] result = new byte[stream.Length];
        stream.Read(result, 0, result.Length);
        return result;
    }
}
票数 1
EN

Stack Overflow用户

发布于 2015-11-18 15:09:54

我做了类似的事情

代码语言:javascript
复制
                    StorageFile photoFile = await StorageFile.GetFileFromPathAsync(Windows.ApplicationModel.Package.Current.InstalledLocation.Path + @"\Images\CurrentFace.jpg");
                    using (IRandomAccessStream fileStream = await photoFile.OpenAsync(Windows.Storage.FileAccessMode.ReadWrite))
                    {
                        BitmapEncoder encode = await BitmapEncoder.CreateAsync(BitmapEncoder.JpegEncoderId, fileStream); //Here try PNG
                        byte[] buf = displaySource.PixelBuffer.ToArray();
                        encode.SetPixelData(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Straight, (uint)displaySource.PixelWidth
                        , (uint)displaySource.PixelHeight, 96.0, 96.0, buf);
                        await encode.FlushAsync();
                        await fileStream.FlushAsync();
                    }

我没有使用写位图,所以我的答案是不完整的,但是从文件加载流要比从写位图加载流要容易得多。我曾经做过类似于writablebitmap.pixelbuffer.asstream()的事情,但这不起作用,因为流将丢失没有在像素缓冲区中的关键信息

这里还有我要保存到文件中的代码。注意:必须有一个已经存在的要保存到的文件,所以您只需将一个空白的.png放在目录中,然后将您的真实图像保存到其中。可以将writableBitmap存储在框架元素中,然后调用此函数。

代码语言:javascript
复制
    async Task<RenderTargetBitmap> SaveToFileAsync(FrameworkElement uielement, StorageFile file)
    {
        if (file != null)
        {
            CachedFileManager.DeferUpdates(file);

            Guid encoderId = GetBitmapEncoder(file.FileType);

            try
            {
                using (var stream = await file.OpenAsync(FileAccessMode.ReadWrite))
                {
                    return await CaptureToStreamAsync(uielement, stream, encoderId);
                }
            }
            catch (Exception ex)
            {
                //DisplayMessage(ex.Message);
            }

            var status = await CachedFileManager.CompleteUpdatesAsync(file);
        }

        return null;
    }

        async Task<RenderTargetBitmap> CaptureToStreamAsync(FrameworkElement uielement, IRandomAccessStream stream, Guid encoderId)
    {
        try
        {
            var renderTargetBitmap = new RenderTargetBitmap();
            await renderTargetBitmap.RenderAsync(uielement);

            var pixels = await renderTargetBitmap.GetPixelsAsync();

            var logicalDpi = DisplayInformation.GetForCurrentView().LogicalDpi;
            var encoder = await BitmapEncoder.CreateAsync(encoderId, stream);
            encoder.SetPixelData(
                BitmapPixelFormat.Bgra8,
                BitmapAlphaMode.Ignore,
                (uint)renderTargetBitmap.PixelWidth,
                (uint)renderTargetBitmap.PixelHeight,
                logicalDpi,
                logicalDpi,
                pixels.ToArray());

            await encoder.FlushAsync();

            return renderTargetBitmap;
        }
        catch (Exception ex)
        {
            //DisplayMessage(ex.Message);
        }

        return null;
    }

您的更新代码无法工作,因为必须将BitmapEncoder分配给具有图片数据的流。当您使用等待BitmapEncoder.CreateAsync()时,您使用的是没有数据的memoryStream (它刚刚初始化)。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/33782882

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档