WinUI3中如何将8位灰度原始像素数组(byte[])显示到Image控件
问题:8位灰度像素数组转WriteableBitmap后Image控件无显示
我从相机获取了原始8位灰度像素数组(byte[]),像素格式信息:
- 8位灰度(颜色通道数=1)
- 尺寸:宽度612,高度512,总字节数=612×512=313344字节
通过事件将数组通知到主页面后,Image控件始终无法显示内容,以下是我的代码:
主页面后台代码
// This event is called when camera image was captured from camera library private void Camera_ImageCaptured(object? sender, ImageCapturedEventArgs e) { // CameraImage is Image control of the main page _ = CameraImage.DispatcherQueue.TryEnqueue(async () => { await GetBitmapAsync3(e.ImageBuffer, e.Width, e.Height); }); } // This method is called in UI thread public async Task GetBitmapAsync3(byte[] data, int width, int height) { WriteableBitmap newImage = new WriteableBitmap(width, height); using var stream = newImage.PixelBuffer.AsStream(); stream.Write(data); await stream.FlushAsync(); stream.Close(); ViewModel.WriteableBitmap = newImage; } // parameters from camera library public class ImageCapturedEventArgs : EventArgs { public ImageCapturedEventArgs( byte[] buffer, int width, int height ); public int Height { get; set; } public int Width { get; set; } public byte[] ImageBuffer { get; set; } }
ViewModel代码
public partial class MainViewModel : ObservableRecipient { [ObservableProperty] public WriteableBitmap writeableBitmap; public int ImageWidth{ get; set; } public int ImageHeight { get; set; } public int ImageSize => ImageWidth * ImageHeight; public MainViewModel() { ImageWidth = 612; ImageHeight = 512; writeableBitmap = new WriteableBitmap(ImageWidth, ImageHeight); } }
主页面XAML代码
<UserControl.DataContext> <viewmodels:MainViewModel /> </UserControl.DataContext> <Grid x:Name="ContentArea"> <Image x:Name="CameraImage" Grid.Row="0" Grid.Column="0" Width="612" Height="512" Source="{Binding WriteableBitmap}" /> </Grid>
解决方案
问题核心:WriteableBitmap默认采用BGRA32像素格式(4字节/像素),但你传入的是8位灰度数据(1字节/像素),像素格式不匹配导致无法正确渲染。
需要将单通道灰度数据转换为BGRA32格式,每个灰度值对应B、G、R三个通道相同的值,A通道设为255(不透明)。修改后的GetBitmapAsync3方法如下:
public async Task GetBitmapAsync3(byte[] data, int width, int height) { // 初始化BGRA32格式的WriteableBitmap,每个像素占4字节 WriteableBitmap newImage = new WriteableBitmap(width, height); // 创建BGRA转换后的缓冲区 byte[] bgraData = new byte[width * height * 4]; for (int i = 0; i < data.Length; i++) { // 灰度值赋值给B、G、R通道,A通道设为255 bgraData[i * 4] = data[i]; // B bgraData[i * 4 + 1] = data[i]; // G bgraData[i * 4 + 2] = data[i]; // R bgraData[i * 4 + 3] = 255; // A } // 将转换后的数据写入PixelBuffer using var stream = newImage.PixelBuffer.AsStream(); await stream.WriteAsync(bgraData, 0, bgraData.Length); await stream.FlushAsync(); // 强制刷新WriteableBitmap,确保UI感知到像素变化 newImage.Invalidate(); // 通知UI更新 ViewModel.WriteableBitmap = newImage; }
额外注意事项:
- 补全
ImageCapturedEventArgs的构造函数,确保属性正确初始化:
public ImageCapturedEventArgs(byte[] buffer, int width, int height) { ImageBuffer = buffer; Width = width; Height = height; }
- 确认主页面与ViewModel的绑定关系正常,避免出现绑定失效问题。
内容的提问来源于stack exchange,提问作者Ken
相关产品推荐
相关产品推荐

