通常,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. 搭建Turbine时,报错误:Property or field 'default' cannot be found on object of type 'com.netflix.appinfo.InstanceInfo'

    Spring Boot + Eureka Server + Hystrix with Turbine: empty turbine.stream 配置的时候遇到了问题: Property or fie ...

  2. MonoDevelop 设置

    菜单:Tools->Options Text Editor Behavior Automatic behaviors × enable on the fly code formatting Sy ...

  3. node系列:全局与本地

    查看:默认和当前的 全局与本地 全局路径:npm config get prefix 本地路径:npm config get cache 修改 修改就会创建对应目录(文件夹) 修改本地路径:npm c ...

  4. [图解tensorflow源码] 入门准备工作

     tensorflow使用了自动化构建工具bazel.脚本语言调用c或cpp的包裹工具swig.使用EIGEN作为矩阵处理工具.Nvidia-cuBLAS GPU加速计算库.结构化数据存储格式prot ...

  5. Openning SharePoint - 80 website gives HTTP 404 Error, The webpage cannot be found ! on SharePoint 2013

    ask: I tried to open the SharePoint - 80 throw Browse in IIS, but I get HTTP 404 Error (The webpage ...

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

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

  7. python3 django连接mysql,同步表结构

    第一步:安装PyMySQ代替MySQLdb pip3 install PyMySQL 然后在工程目录的__init__.py中填写下面两句话   import pymysql pymysql.inst ...

  8. js input监听兼容事件

    $('#phoneNumber').on('input',function() { var valueP = $(this).attr('value'); if(valueP.length == 11 ...

  9. Json解析数据的简单使用

    简单的记一下Json解析的简单实用: 使用场景:后台传到客户端的Json数据,类似于: string jsonObject="{'Name':'Jack','Age':25}"; ...

  10. impulse···········

    impulse - Bing dictionary US['ɪm.pʌls]UK['ɪmpʌls] n.冲动:冲量:推动力:刺激 v.推动 网络脉冲:冲击 变形Plural Form:impulses ...