通常,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. 使用sql获取primary key名称

    使用sql获取mysql主键名称: 方法1: 这种方法返回一行数据,如果只是需要主键的名称,可以使用方法2. SHOW KEYS FROM <table_name> WHERE Key_n ...

  2. 推荐的 MongoDB 安装文档

    简介: MongoDB 是一个由 C++ 语言编写的基于分布式文件存储的数据库,是目前最像关系型数据库的非关系型数据库. 最近写爬虫, 思来想去觉得还是用 MongoDB 比较方便. 一.安装 # 官 ...

  3. top命令之你不一定懂的cpu显示信息

    %st(Steal time) 是当 hypervisor 服务另一个虚拟处理器的时候,虚拟 CPU 等待实际 CPU 的时间的百分比. ------------------------------- ...

  4. 判断TrueType字体

    function IsTrueTypeFont(FontName : string) : boolean;const  PITCH_MASK: byte = $0F;  var  TxMetric: ...

  5. Delphi声明Record变量后直接初始化

    TARec = record    A1: string;    A2: string;  end; TBRec = record    A1: string;    A2: string;    A ...

  6. 常见jsp跳转总结

    这次做项目,用到几种不同的JSP跳转的方式,在此总结5中常用方法. 常用的跳转方式有以下几种: (1)href超链接标记,属于客户端跳转 (2)使用javascript完成,属于客户端跳转 (3)提交 ...

  7. dubbo hessian+dubbo协议

    Dubbo缺省协议采用单一长连接和NIO异步通讯,适合于小数据量大并发的服务调用,以及服务消费者机器数远大于服务提供者机器数的情况 Hessian协议用于集成Hessian的服务,Hessian底层采 ...

  8. DES_3DES_AES_IDES_RSA密码算法比较

    对称加密算法(也叫共享密钥) 类型 定义:发送接收使用相同的对称密钥 密钥 长度 分组长度 循环次数 安全性 DES 数据加密标准,速度较快,适用于加密大量数据的场合: 56 64 16 依赖密钥受穷 ...

  9. python,使用PIL库对图片进行操作

    在做识别验证码时,需要对验证码图片进行一些处理,所以就学习了一下PIL的知识,下面是我总结的一些常用方法. 注明:图片的操作都需要Image库,所以要使用import Image导入库 1.打开图片 ...

  10. HibernateTemplate实现CRUD操作

    ---------------------siwuxie095 HibernateTemplate 实现 CRUD 操作 1.在 SSH 框架中使用 HibernateTemplate 模板类实现 C ...