UWP中如何从Base64字符串还原图像?
问题:Base64字符串还原图像失败
我正在开发一款支持Windows Ink绘图与图片粘贴的笔记应用,希望将图片与墨迹保存至单个文件,因此将图像转换为Base64字符串以便序列化。但在从该字符串还原图像时遇到问题:
图像转Base64字符串的代码
var decoder = await BitmapDecoder.CreateAsync(imageStream); var pixels = await decoder.GetPixelDataAsync(); var bytes = pixels.DetachPixelData(); base64String = Convert.ToBase64String(bytes);
尝试还原图像的代码(无法正常工作,图像未添加到redCanvas)
var bytes = Convert.FromBase64String(base64String); BitmapImage bitmapImage = new BitmapImage(); using (InMemoryRandomAccessStream stream = new InMemoryRandomAccessStream()) { await stream.WriteAsync(bytes.AsBuffer()); stream.Seek(0); bitmapImage.SetSource(stream); } Image image = new Image(); image.Source = bitmapImage; // Add the image to a second canvas redCanvas.Children.Add(image);
粘贴图片并生成Base64字符串的完整代码
private async Task myButton_ClickAsync(object sender, RoutedEventArgs e) { var dataPackageView = Windows.ApplicationModel.DataTransfer.Clipboard.GetContent(); if (dataPackageView.Contains(StandardDataFormats.Bitmap)) { IRandomAccessStreamReference imageReceived = null; imageReceived = await dataPackageView.GetBitmapAsync(); if (imageReceived != null) { using (var imageStream = await imageReceived.OpenReadAsync()) { var bitmapImage = new BitmapImage(); bitmapImage.SetSource(imageStream); var decoder = await BitmapDecoder.CreateAsync(imageStream); var pixels = await decoder.GetPixelDataAsync(); var bytes = pixels.DetachPixelData(); base64String = Convert.ToBase64String(bytes); TextBox_Image_Base64.Text = base64; Image image = new Image(); // Add the image to a list of Images ListImages.Add(image); blueCanvas.Children.Add(image); image.Source = bitmapImage; TextBlock_Status.Text = "Status : Image is retrieved from the clipboard and pasted successfully."; } } } else { TextBlock_Status.Text = "Status : Bitmap format is not available in clipboard"; } }
请问如何解决从Base64字符串还原图像的问题?
解决方案
问题核心是你仅保存了图像的原始像素数据,没有包含图像格式编码信息。GetPixelDataAsync()返回的是未编码的像素字节(比如RGBA原始数据),而BitmapImage需要完整的编码图像流(如PNG、JPG格式)才能识别,直接写入原始像素字节无法被解析。
修正方案1:保存完整图像编码流(推荐)
不需要解码像素,直接把原始图像流转换为Base64,还原时直接复用原有逻辑即可。
修改图像转Base64的代码
using (var imageStream = await imageReceived.OpenReadAsync()) { // 读取完整图像流到字节数组 var buffer = new byte[imageStream.Size]; await imageStream.ReadAsync(buffer.AsBuffer(), (uint)imageStream.Size, InputStreamOptions.None); base64String = Convert.ToBase64String(buffer); // 保留原有显示图像、更新状态等逻辑 }
还原图像代码(无需修改)
var bytes = Convert.FromBase64String(base64String); BitmapImage bitmapImage = new BitmapImage(); using (InMemoryRandomAccessStream stream = new InMemoryRandomAccessStream()) { await stream.WriteAsync(bytes.AsBuffer()); stream.Seek(0); bitmapImage.SetSource(stream); } Image image = new Image(); image.Source = bitmapImage; redCanvas.Children.Add(image);
修正方案2:若必须保存像素数据,还原时重新编码
如果因需求必须保存原始像素数据,需要在还原时将像素数据重新编码为标准图像格式,同时需提前保存图像的元数据(宽度、高度、像素格式等)。
还原图像的代码修改
var bytes = Convert.FromBase64String(base64String); // 需提前保存图像元数据,以下为示例值,实际从存储的元数据中读取 uint width = 1920; uint height = 1080; BitmapPixelFormat pixelFormat = BitmapPixelFormat.Rgba8; BitmapAlphaMode alphaMode = BitmapAlphaMode.Straight; BitmapImage bitmapImage = new BitmapImage(); using (InMemoryRandomAccessStream stream = new InMemoryRandomAccessStream()) { // 创建PNG编码器 var encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.PngEncoderId, stream); encoder.SetPixelData(pixelFormat, alphaMode, width, height, 96, 96, bytes); await encoder.FlushAsync(); stream.Seek(0); bitmapImage.SetSource(stream); } Image image = new Image(); image.Source = bitmapImage; redCanvas.Children.Add(image);
额外注意事项
- 方案1更高效简洁,适合绝大多数场景,保存的Base64体积与原图像一致,还原逻辑无需额外处理。
- 方案2需要额外存储图像元数据,否则无法正确编码还原。
- 原粘贴代码中
TextBox_Image_Base64.Text = base64;存在变量名错误,应改为base64String,避免运行时异常。
内容的提问来源于stack exchange,提问作者Magnus
相关产品推荐
相关产品推荐

