通常,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字节的边界开始,如果它是由系统的其他部分强加的,比如从使用特定步幅的源获取数据。

WriteableBitmap(一)的更多相关文章

  1. WriteableBitmap 给透明的控件截图的问题

    在WP开发中,我们经常会用到截取某一部分区域,然后分享到微博等等,Writeablebitmap 是一个很好的辅助,但是它本身也有一个限制:只有一个 SaveJpeg 方法,因此透明的区域无法保存,都 ...

  2. UWP&WP8.1 重新绘制图片 WriteableBitmap用法 图片转byte[]数组,byte[]数组转图片

    ---恢复内容开始--- WriteableBitmap 是UWP和WP8.1绘制图片的,重组图片的最重要方法.方法较为简单,方法多样性. 通过查看文档,WriteableBitmap的继承性是    ...

  3. Silverlight中将WriteableBitmap互转byte数组

    //WriteableBitmap to ARGB ;    , result, , len);    , bmp.Pixels, , buffer.Length); }

  4. 【转】【WPF】WriteableBitmap应用及图片数据格式转换

    使用 WriteableBitmap 类基于每个框架来更新和呈现位图.这对于生成算法内容(如分形图像)和数据可视化(如音乐可视化工具)很有用. WriteableBitmap 类使用两个缓冲区.“后台 ...

  5. Windows Phone 使用 WriteableBitmap后台生成图片

    这几天项目是遇到一个需求,需要后台把几个元素生成到一张图片上,并保存到文件中 private void cutscreen_Click(object sender, EventArgs e) { Gr ...

  6. win10 uwp 读取保存WriteableBitmap 、BitmapImage

    我们在UWP,经常使用的图片,数据结构就是 BitmapImage 和 WriteableBitmap.关于 BitmapImage 和 WriteableBitmap 区别,我就不在这里说.主要说的 ...

  7. WriteableBitmap/BitmapImage/MemoryStream/byte[]相互转换

    1 WriteableBitmap/BitmapImage/MemoryStream/byte[]相互转换 2012-12-18 17:27:04|  分类: Windows Phone 8|字号 订 ...

  8. WriteableBitmap(三) 扩展

    backbuffer使用您在创建WriteableBitmap时指定的像素格式,还有一个BackBufferStride属性,您可以使用它来创建一个合适的存储映射函数. 添加一些方法来设置和获取特定情 ...

  9. WriteableBitmap(二) 实例

    使用前面定义的WriteableBitmap,我们可以很容易地创建一个足够容纳整个100 x 100图像的数组: byte[] pixels = new byte[wbmap.PixelHeight* ...

随机推荐

  1. html5中的SessionStorage 和localStorage

    html5中的Web Storage包括了两种存储方式:sessionStorage和localStorage. sessionStorage用于本地存储一个会话(session)中的数据,这些数据只 ...

  2. shell脚本面试题

    Q:1 Shell脚本是什么.它是必需的吗? 答:一个Shell脚本是一个文本文件,包含一个或多个命令.作为系统管理员,我们经常需要使用多个命令来完成一项任务,我们可以添加这些所有命令在一个文本文件( ...

  3. AnimatorOverrideController

    [AnimatorOverrideController] 有N个角色,这N个角色的状态机一样,只是动画不一样.这时候,新建一个AnimatorController,设置状态机.然后为这N个角色建立N个 ...

  4. webElement.text()获取到内容为空

    使用webElement.text()方法获取字符串时,有时候会获取失败--获取到的内容为空 使用 webElement.getAttribute("attributeName") ...

  5. Mysql两个time类型计算时间相减

    round((UNIX_TIMESTAMP(finishtime)-UNIX_TIMESTAMP(starttime))/60) 得到的时间是分钟数

  6. Xcrysden-2

    XCrySDen -- (X-Window) CRYstalline Structures and DENsities Introduction to use. XCrySDen is a cryst ...

  7. Majority Element(ARRAY-BINARY SEARCH)

    QUESTION Given an array of size n, find the majority element. The majority element is the element th ...

  8. vmware搭建vSAN提示磁盘不合格或者看不到磁盘的解决办法

    1.如果磁盘不合格,或者在创建磁盘组的时候看不到该磁盘,一般的原因都是该磁盘有其他分区,可以使用下面的方法来解决 a.首先开启esxi主机的ssh功能 b.登陆到esxi的后台 c. ls /dev/ ...

  9. 获取客户端真实IP地址

    Java-Web获取客户端真实IP: 发生的场景:服务器端接收客户端请求的时候,一般需要进行签名验证,客户端IP限定等情况,在进行客户端IP限定的时候,需要首先获取该真实的IP. 一般分为两种情况: ...

  10. 用SQL2000还原bak文件

    1.右击SQL Server 2000实例下的“数据库”文件夹.就是master等数据库上一级的那个图标.选择“所有任务”,“还原数据库” 2.在“还原为数据库”中填上你希望恢 复的数据库名字.这个名 ...