UWP C#保存视频帧为16位JPEG XR格式的问题求助
解决16位JPEG XR编码错误的方案
问题根源
你当前的代码错误在于:WriteableBitmap加载的视频帧是8位BGRA格式(每个像素4字节),但当你将BitmapPixelFormat改为Rgba16时,传入的像素数据仍然是8位的字节数组——16位格式每个像素需要8字节(RGBA各2字节),字节数不匹配直接导致编码器报错。
方案一:转换8位像素数据为16位格式
手动将Bgra8的像素数据扩展为Bgra16格式,再传给编码器:
// 获取8位像素数据(原代码不变) const int BytesPerPixel8 = 4; Stream stream = writableBitmap.PixelBuffer.AsStream(); byte[] pixels8 = new byte[(int)frameWidth * (int)frameHeight * BytesPerPixel8]; await stream.ReadAsync(pixels8, 0, pixels8.Length); // 转换为16位Bgra格式 const int BytesPerPixel16 = 8; byte[] pixels16 = new byte[(int)frameWidth * (int)frameHeight * BytesPerPixel16]; for (int i = 0; i < pixels8.Length; i += BytesPerPixel8) { // 每个8位通道扩展为16位(0-255 → 0-65535) ushort blue = (ushort)(pixels8[i] * 257); ushort green = (ushort)(pixels8[i+1] * 257); ushort red = (ushort)(pixels8[i+2] * 257); ushort alpha = (ushort)(pixels8[i+3] * 257); // 写入16位数据(小端字节序) Buffer.BlockCopy(BitConverter.GetBytes(blue), 0, pixels16, i*2, 2); Buffer.BlockCopy(BitConverter.GetBytes(green), 0, pixels16, i*2+2, 2); Buffer.BlockCopy(BitConverter.GetBytes(red), 0, pixels16, i*2+4, 2); Buffer.BlockCopy(BitConverter.GetBytes(alpha), 0, pixels16, i*2+6, 2); } // 编码16位JXR using (var writeStream = await saveAsTarget.OpenAsync(FileAccessMode.ReadWrite)) { var encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.JpegXREncoderId, writeStream); encoder.SetPixelData( BitmapPixelFormat.Bgra16, // 使用匹配的16位格式 BitmapAlphaMode.Premultiplied, (uint)writableBitmap.PixelWidth, (uint)writableBitmap.PixelHeight, 96.0, 96.0, pixels16); await encoder.FlushAsync(); }
方案二:用SoftwareBitmap直接处理16位格式(更可靠)
跳过WriteableBitmap,用SoftwareBitmap直接转换图像格式,避免手动操作像素数组:
// 获取视频帧流后,先解码为SoftwareBitmap var decoder = await BitmapDecoder.CreateAsync(imageStream); var softwareBitmap8 = await decoder.GetSoftwareBitmapAsync(); // 转换为16位BGRA格式 var softwareBitmap16 = SoftwareBitmap.Convert(softwareBitmap8, BitmapPixelFormat.Bgra16, BitmapAlphaMode.Premultiplied); // 编码保存 using (var writeStream = await saveAsTarget.OpenAsync(FileAccessMode.ReadWrite)) { var encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.JpegXREncoderId, writeStream); encoder.SetSoftwareBitmap(softwareBitmap16); await encoder.FlushAsync(); }
注意事项
- JXR编码器支持的16位格式包括
Bgra16和Rgba16,确保SetPixelData或SetSoftwareBitmap的格式与编码器要求匹配; - 如果不需要Alpha通道,可以使用
Rgb48格式(每个像素6字节),进一步减小文件体积。
内容的提问来源于stack exchange,提问作者Zemax
相关产品推荐
相关产品推荐

