从相机检索原始像素数据数组(byte[]),并将其作为事件通知到主页。
像素格式是这样的:-
这是我到目前为止的代码,它在图像控制中没有显示任何内容。
// Behind code of Main Page //////////////////////////////////////////////////////
// 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; }
}
// View Model ///////////////////////////////////////////////
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>
我用上面的代码尝试了它,但它在主页中没有显示任何内容...... 有人帮助我吗?
我不确定
Microsoft.UI.Xaml.Media.Imaging.WriteableBitmap
是否支持每个像素1字节数据。
你可以尝试下一个吗?
public async Task GetBitmapAsync3(byte[] data, int width, int height)
{
byte[] outputData= new byte[width * height * 4];
int inputIndex = 0;
int outputIndex = 0;
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
byte value = data[inputIndex++];
outputData[outputIndex++] = value;
outputData[outputIndex++] = value;
outputData[outputIndex++] = value;
outputData[outputIndex++] = 255;
}
}
WriteableBitmap newImage = new WriteableBitmap(width, height);
using var stream = newImage.PixelBuffer.AsStream();
await stream.WriteAsync(outputData);
await stream.FlushAsync();
stream.Close();
ViewModel.WriteableBitmap = newImage;
}
您可以使用this库将字节数组解释为位图数据(免责声明:我是作者)。
使用与技术无关的核心包将数组视为 8 位灰度位图:
using KGySoft.Drawing.Imaging;
// ...
// interpreting the byte array as a grayscale bitmap
var myArrayBackedBitmap = BitmapDataFactory.CreateBitmapData(myByteArray,
new Size(612, 512),
stride: 612,
pixelFormat: KnownPixelFormat.Format8bppGrayScale);
// now you can use you can Get/Set pixels, draw other images into your bitmap, etc.
如果您使用 WinUI 3 特定软件包,您可以简单地将托管位图转换为 WinUI 3
WriteableBitmap
:
var myWinUI3Bitmap = await myArrayBackedBitmap.ToWriteableBitmapAsync();
性能考虑:
请注意,
ToWriteableBitmap
始终创建一个新的WriteableBitmap
实例,这可能会影响性能,因为它既不是一次性的也不是托管的(与WinUI中的几乎所有内容一样,它是一个“远程”COM对象)。重用单个 WriteableBitmap
实例可能会更好:
// A field allocated once
private WriteableBitmap _renderingTarget;
// [...]
// instead of ToWriteableBitmap, just draw the grayscale bitmap always into the same bitmap.
using (var targetBitmapData = _renderingTarget.GetReadWriteBitmapData())
await myArrayBackedBitmap.DrawIntoAsync(_renderingTarget);
// Here, after the end using block the target WriteableBitmap is invalidated
// so the possible bindings can refresh themselves
也请随意查看 this 库的 WinUI 特定示例。