WriteableBitmap(一)

通常,WPF中的位图是不可变的。不可变的位图非常有效,如果您希望进行大量的动态更改,创建和销毁它们的开销会变得非常昂贵。在这种情况下,您需要一些更灵活的东西——WriteableBitmap。

WriteableBitmap,正如它的名字所暗示的,不是不可变的,你可以得到它的单个像素,并尽可能多地操纵它们。当您需要动态位图时,这是理想的工作方式。我们来看看WriteableBitmap,它是如何工作的,以及如何使用它来做动态的事情。

要使用WriteableBitmap,我们需要添加:using System.Windows.Media.Imaging;它包含我们需要的所有其他位图工具。

有两种方法可以创建WriteableBitmap。最常用的是简单地指定位图的大小和格式:

WriteableBitmap wbmap = new WriteableBitmap(100, 100, 300,300, PixelFormats.Bgra32, null);

它使用Bgra32像素格式指定一个100×100像素的WriteableBitmap,分辨率为300dpi×300dpi。每个像素是一个32位的int,使用一个4字节的BGRA——也就是说,像素由一个字节组成,该字节给出蓝色、绿色、红色和Alpha值。如果格式需要,最后一个参数用于指定调色板。

您可以为您创建的位图指定广泛的格式,在每种情况下,每个像素都接受给定数量的位来表示,您需要找出分配给每个像素的位如何决定其颜色。

创建WriteableBitmap的第二种方法是基于现有的BitmapSource或派生类。例如,您应该能够使用构造函数从标准位图创建WriteableBitmap:

WriteableBitmap(bitmapsource);

但是如果您尝试使用从URI加载的BitmapImage,您将得到一个null对象错误。原因是位图可能还没有下载。对于本地文件,位图加载会阻塞执行,直到加载完成:

Uri uri = new Uri(@"pack://application:,,,/Resources/mypic.jpg");
BitmapImage bmi = new BitmapImage(uri);
WriteableBitmap bmi2 = new WriteableBitmap(bmi);
image1.Source = bmi2;

在这种情况下,WriteableBitmap的创建没有任何问题。但是,如果URI是HTTP URL,负载不会阻塞执行,结果将是一个错误。

使用像素

一旦你有了WriteableBitmap,你就可以开始使用它的像素了。提供了两种方法,它们提供了在低级API中找到的与BitBlt操作等价的有限的方法。在这种情况下,您可以将一个像素矩形复制到一个数组中,也可以将一个数组中的数据复制到一个像素矩形中。在每一种情况下,数据数组都被视为一个字节流,并简单地从位图中指定的像素矩形中存储或检索。

WriteableBitmap了解它所存储的位图的格式,因此它会自动计算出每个像素使用了多少字节,以及如何找到给定坐标下的像素数据。但是,它不能知道您如何组织数组中的数据,或者在向数组读取像素时,您可能需要如何组织数据。

最简单的方案是将一行像素数据存储在与前一行相邻的数组中。也就是说,如果原始图像有p个像素,每个像素用b字节表示,那么数组中的第一行用p*b字节存储,下一行从p*b+1开始,以此类推。

可以看到,列x行y中的像素(从0开始计数)存储在字节x*b+p*b*y中。(这是存储映射函数的一个例子。)这个简单方案的唯一复杂之处在于一行像素可能不会在整个字节中结束。例如,如果你有一个黑白图像格式,你只需要1位每像素和第一行的10×10位图只需要10位存储。然而,为了简单起见,每一行都必须从一个新字节开始,因此存储第一行所需的存储空间是两个字节。

注意,在这种情况下,根据每个像素的比特数或字节数,分配给一行的存储量超出了严格的需求,也就是说,它不仅仅是p*b。 

为什么一行所需的存储空间并不总是最小值,还有其他原因——例如Windows坚持行总是从一个4字节的边界开始。 

因此,我们定义并使用“stride”。

stride S被定义为存储图像一行所需的存储量,包括确保下一行正确对齐所需的任何填充。 

在这种情况下,WriteableBitmap负责像素的内部表示,您不需要担心它使用的是什么值。但是,您必须担心在您负责的数据数组中使用的stride。在大多数情况下,您可以简单地将stride设置为存储位图的一行所需的字节数——四舍五入,以确保必要时每一行都从一个新字节开始。

您只需要担心其他问题,比如从一个4字节的边界开始,如果它是由系统的其他部分强加的,比如从使用特定步幅的源获取数据。

 

转载于:https://www.cnblogs.com/TianPing/p/10372555.html

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: WriteableBitmap 是一个可以通过像素级别的操作来修改图像的类,它通常用于实时绘制和编辑图像。虽然它可以用于显示视频,但是它并不是用于播放视频的最佳选择,因为它在视频播放方面的性能相对较弱。 要使用 WriteableBitmap 显示视频,首先需要解码视频文件或捕获视频流,并将视频帧转换为 WriteableBitmap 对象。这可以通过使用视频库(如 MediaFoundation 或 FFmpeg)来实现。然后,可以将 WriteableBitmap 对象绑定到一个图像控件(如 Image 控件)的源属性上,以显示视频。 在每次接收到新的视频帧时,需要将其转换为 WriteableBitmap 对象的像素数据。可以通过 Lock 方法来锁定 WriteableBitmap,并通过返回的指针访问像素数据。然后,将视频帧的像素数据复制到 WriteableBitmap 对象中,然后通过调用 Unlock 方法解锁 WriteableBitmap。 要实现视频的播放,可以使用一个循环来不断地获取新的视频帧,并更新 WriteableBitmap 的像素数据。这将创建一个动画效果,使视频连续播放。 需要注意的是,使用 WriteableBitmap 来显示视频可能会导致性能和资源消耗方面的问题,特别是在处理大型视频文件或高分辨率视频时。此外,WriteableBitmap 并不提供视频播放控制(如播放、暂停和跳转)等功能,因此如果需要更强大的视频播放功能,建议使用专门的视频播放库或框架。 ### 回答2: WriteableBitmap是Windows Presentation Foundation (WPF) 中用于处理图像和图形的类。它可以用于在用户界面中显示视频。 要使用WriteableBitmap显示视频,首先需要将视频文件加载到内存中。可以使用MediaElement控件来加载和播放视频文件。然后,将视频文件的每一帧转换为WriteableBitmap对象。可以通过MediaElement的视频播放事件来获得每一帧的图像数据。 在获得每一帧的图像数据后,可以将其赋值给WriteableBitmap的Pixels属性,这样就能将视频帧显示在用户界面中。需要注意的是,WriteableBitmap的宽度和高度需要与视频帧的宽度和高度匹配,这样才能正确地显示图像。 为了实现视频的流畅播放,可以使用一个定时器来定期更新WriteableBitmap的图像数据。每个时间间隔,将会更新WriteableBitmap的Pixels属性以显示新的视频帧。 另外,为了提高性能,可以使用后台线程运行视频解码和图像处理的任务。这样可以避免在主线程上执行这些任务时引起的用户界面卡顿问题。 总之,使用WriteableBitmap可以很好地展示视频。通过将视频帧转换为WriteableBitmap对象,并定期更新其图像数据,可以实现视频的流畅播放和显示。 ### 回答3: WriteableBitmap 是一个在 WPF 和 UWP 应用程序中用于处理图像的类。尽管它没有直接支持视频播放功能,但仍然可以使用 WriteableBitmap 来创建一个简单的视频播放器。 首先,我们需要从视频文件中以逐帧方式将图像提取出来。可以使用 FFmpeg 或其他视频处理库来实现这一点。一旦我们获得一个图像帧,我们就可以使用 WriteableBitmap 的方法将其加载到内存中。 在 WPF 应用程序中,可以使用一个计时器或者后台线程来定时加载下一帧图像。在每个时间间隔内,我们将加载下一帧图像并在 WriteableBitmap 上绘制。可以使用 WriteableBitmap 的一些绘图方法(如 DrawLine、DrawRectangle、DrawText 等)来显示图像。 另一种方法是使用 XAML 中的 `Image` 控件,将 WriteableBitmap 绑定到 Source 属性上,然后在每个时间间隔内更新 WriteableBitmap。 但需要注意的是,使用 WriteableBitmap 显示视频可能会导致性能问题,特别是对于较大的视频文件或高分辨率的视频。因此,最好在后台线程中进行图像处理,并仅加载当前帧,以节省内存和提高性能。 此外, WriteableBitmap 不能直接处理音频,所以如果需要同时播放视频和音频,需要使用其他库或组件来处理音频。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值