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字节的边界开始,如果它是由系统的其他部分强加的,比如从使用特定步幅的源获取数据。
WriteableBitmap(一)的更多相关文章
- WriteableBitmap 给透明的控件截图的问题
在WP开发中,我们经常会用到截取某一部分区域,然后分享到微博等等,Writeablebitmap 是一个很好的辅助,但是它本身也有一个限制:只有一个 SaveJpeg 方法,因此透明的区域无法保存,都 ...
- UWP&WP8.1 重新绘制图片 WriteableBitmap用法 图片转byte[]数组,byte[]数组转图片
---恢复内容开始--- WriteableBitmap 是UWP和WP8.1绘制图片的,重组图片的最重要方法.方法较为简单,方法多样性. 通过查看文档,WriteableBitmap的继承性是 ...
- Silverlight中将WriteableBitmap互转byte数组
//WriteableBitmap to ARGB ; , result, , len); , bmp.Pixels, , buffer.Length); }
- 【转】【WPF】WriteableBitmap应用及图片数据格式转换
使用 WriteableBitmap 类基于每个框架来更新和呈现位图.这对于生成算法内容(如分形图像)和数据可视化(如音乐可视化工具)很有用. WriteableBitmap 类使用两个缓冲区.“后台 ...
- Windows Phone 使用 WriteableBitmap后台生成图片
这几天项目是遇到一个需求,需要后台把几个元素生成到一张图片上,并保存到文件中 private void cutscreen_Click(object sender, EventArgs e) { Gr ...
- win10 uwp 读取保存WriteableBitmap 、BitmapImage
我们在UWP,经常使用的图片,数据结构就是 BitmapImage 和 WriteableBitmap.关于 BitmapImage 和 WriteableBitmap 区别,我就不在这里说.主要说的 ...
- WriteableBitmap/BitmapImage/MemoryStream/byte[]相互转换
1 WriteableBitmap/BitmapImage/MemoryStream/byte[]相互转换 2012-12-18 17:27:04| 分类: Windows Phone 8|字号 订 ...
- WriteableBitmap(三) 扩展
backbuffer使用您在创建WriteableBitmap时指定的像素格式,还有一个BackBufferStride属性,您可以使用它来创建一个合适的存储映射函数. 添加一些方法来设置和获取特定情 ...
- WriteableBitmap(二) 实例
使用前面定义的WriteableBitmap,我们可以很容易地创建一个足够容纳整个100 x 100图像的数组: byte[] pixels = new byte[wbmap.PixelHeight* ...
随机推荐
- redis之RDB持久化与AOF持久化
Redis是一个键值对数据库服务器,服务器中通常包含着任意个非空数据库,而每个非空数据库中又可以包含任意个键值对,为了方便起见,我们将服务器中的非空数据库以及它们的键值对统称为数据库状态. 因为Red ...
- 在Eclipes中查看源代码和大纲快速定位
1 在Eclipes中查看源代码,快捷键使用clrl+光标,选择你要查看的方法和属性查看源代码.例如你想看StringBuilder这个类源代码 StringBuilder allow = new S ...
- python中库学习
一.numpy NumPy的主要对象是同种元素的多维数组.这是一个所有的元素都是一种类型.通过一个正整数元组索引的元素表格(通常是元素是数字).在NumPy中维度(dimensions)叫做轴(axe ...
- conductor元数据定义
Task Definition conductor维护工作任务类型的注册表. 必须在工作流中使用之前注册任务类型. 例如: { "name": "encode_task& ...
- cmd 获取 拖拽文件名
1. @echo off & setlocal enableDelayedExpansion set a= set /p a=Please drag your txt file for spl ...
- mysql安装笔记-rpm
基本内容: 1.需要解决两个依赖 2.需要解决一个包冲突 3.安装mysql服务,以及客户端client 4.修改root的随机密码 5.授予root用户,从任何机器访问任何数据库的任何表的权限 1. ...
- Bom对象介绍
1.windows对象 1.windows对象 1_1.alert:显示一段消息和确认按钮的弹出的警告框 我们平时用的alert的全称就是 window.alert("hahah" ...
- 复制带随机指针的链表 · Copy List with Random Pointer
[抄题]: 给出一个链表,每个节点包含一个额外增加的随机指针可以指向链表中的任何节点或空的节点. 返回一个深拷贝的链表. [思维问题]: [一句话思路]: 完完全全地复制,否则不好操作. 1-> ...
- Excel单元格内容批量加前缀
比如83190001在A1单元格,要在A列单元内容前面批量加0,在B1输入公式="0"&A1然后向下复制再把B列复制的结果再复制一下:然后到新的一列粘贴,在“粘贴选项”中选 ...
- mysql优化概述2
一.索引的概念 利用关键字,就是记录的部分数据(某个字段,某些字段,某个字段的一部份),建立与记录位置的对应关系,就是索引.索引的关键字一定是排序的. 二.索引的类型 mysql支持四种索引: 1.主 ...