backbuffer使用您在创建WriteableBitmap时指定的像素格式,还有一个BackBufferStride属性,您可以使用它来创建一个合适的存储映射函数。

添加一些方法来设置和获取特定情况下的像素是很容易的,方法是在静态类中定义两个新的扩展方法,创建静态类只是为了承载扩展方法:

public static class bitmapextensions
{

setPixel方法首先检查x和y坐标是否在正确的范围内,格式是否为Brga32(您可以扩展该方法来处理其他格式):

public static void setPixel(this WriteableBitmap wbm, int x, int y, Color c)
{
   if (y > wbm.PixelHeight - 1 || x > wbm.PixelWidth - 1) return;
   if (y < 0 || x < 0) return;
  if (!wbm.Format.Equals(PixelFormats.Bgra32))return;

然后它会得到backbuffer的详细信息:

   wbm.Lock();
  IntPtr buff = wbm.BackBuffer;
  int Stride = wbm.BackBufferStride;

然后计算存储映射函数来访问x、y位置的像素,并将指定的颜色分割存储为像素格式对应的4个字节:

  unsafe
  {
      byte* pbuff = (byte*)buff.ToPointer();
      int loc=y *Stride  + x*4;
      pbuff[ loc]=c.B;
      pbuff[loc+1]=c.G;
      pbuff[loc+2]=c.R;
      pbuff[loc+3]=c.A;
  }

最后我们将像素标记为dirty并解锁WriteableBitmap:

  wbm.AddDirtyRect(new Int32Rect(x,y,1,1));
  wbm.Unlock();
}

getPixel方法非常类似,只是它汇编并返回一个Color struct:

public static Color getPixel( this WriteableBitmap wbm, int x, int y)
{
  if (y > wbm.PixelHeight - 1 || x > wbm.PixelWidth - 1)  return Color.FromArgb(0, 0, 0, 0);
  if (y < 0 || x < 0) return Color.FromArgb(0, 0, 0, 0);
  if (!wbm.Format.Equals(PixelFormats.Bgra32))  return Color.FromArgb(0, 0, 0, 0);;
  IntPtr buff = wbm.BackBuffer;
  int Stride = wbm.BackBufferStride;
  Color c;
  unsafe
  {
      byte* pbuff = (byte*)buff.ToPointer();
      int loc = y * Stride + x * 4;
      c=Color.FromArgb(pbuff[loc+3],pbuff[loc+2],pbuff[loc+1],pbuff[loc]);
  }
  return c;
}

请注意,由于我们只是访问位而不更改它们,因此没有必要将某个区域锁定或标记为dirty。
这两个扩展方法很容易使用,但是如果要操作大量像素,可能需要考虑使用更直接的方法。通过Pixel属性直接访问并分配预先计算的整数颜色值总是比使用一般方法和对象要快。

定义了这些扩展方法后,我们现在可以给出一个访问像素的例子:

wbmap.setPixel(5,10 , Colors.Red);
Color c= wbmap.getPixel(5, 10);

最后,作为一个动态图像的例子,下面根据一个简单的公式,绘制了一个依赖于像素位置的颜色范围:

private void button1_Click(object sender, RoutedEventArgs e)
{
  WriteableBitmap wbmap = new WriteableBitmap(256, 256, 300, 300, PixelFormats.Bgra32, null);
  for (int x = 0; x < 256; x++)
  {
      for (int y = 0; y < 256; y++)
      {
         wbmap.setPixel( x,y,Color.FromArgb(255,(byte) (x*x+y), (byte) (y*y+x),(byte)(x+y)));
      }
  }
  image1.Source = wbmap;
}

WriteableBitmap(三) 扩展的更多相关文章

  1. 扩展KMP算法

    一 问题定义 给定母串S和子串T,定义n为母串S的长度,m为子串T的长度,suffix[i]为第i个字符开始的母串S的后缀子串,extend[i]为suffix[i]与字串T的最长公共前缀长度.求出所 ...

  2. SharePoint 2013 自定义扩展菜单

    在对SharePoint进行开发或者功能扩展的时候,经常需要对一些默认的菜单进行扩展,以使我们开发的东西更适合SharePoint本身的样式.SharePoint的各种功能菜单,像网站设置.Ribbo ...

  3. LINQ学习系列-----1.3 扩展方法

    这篇内容继续接着昨天的Lambda表达式的源码继续下去.昨天讲了Lambda表达式,此篇讲扩展方法,这两点都是Linq带来的新特性.    一.扩展方法介绍   废话不多说,先上源码截图: 上图中Ge ...

  4. 三.RabbitMQ之异步消息队列(Work Queue)

    上一篇文章简要介绍了RabbitMQ的基本知识点,并且写了一个简单的发送和接收消息的demo.这一篇文章继续介绍关于Work Queue(工作队列)方面的知识点,用于实现多个工作进程的分发式任务. 一 ...

  5. Python基础之文件处理、函数、内置函数 (三)

    内置函数 一 详细见python文档,请点击 文件操作 操作文件时,一般需要经历如下步骤: 打开文件 操作文件 一.打开文件 文件句柄 = file('文件路径', '模式') 注:python中打开 ...

  6. 扩展-Easyui Datagrid相同连续列合并扩展(一)

    一.autoMergeCellAndCells实现效果 调用方法: function onLoadSuccess(data){     $(this).datagrid("autoMerge ...

  7. C语言之三字棋的简单实现及扩展

    C语言之三字棋的简单实现及扩展 在我们学习完数组之后,我们完全可以利用数组相关知识来写一个微小型的游戏,比如说今天所说的--三子棋. 大纲: 文件组成 实现   完整代码展示   扩展 即: 一.文件 ...

  8. Spring的三种注入

    在学习Spring的过程中,其中一个很重要的就是依赖注入DI,在此总结一下 注入方式有三种: 一.构造器注入 二.Set方式注入(重点) 三.扩展方式注入 构造器注入: a.默认使用无参构造函数创建对 ...

  9. Jquery双向select控件Bootstrap Dual Listbox

    效果预览: 一. 下载插件 github地址:https://github.com/istvan-ujjmeszaros/bootstrap-duallistbox 也可以在这个网站中下载:http: ...

  10. [C1] C1FlexGrid 行列增删&单元格合并拆分

    上一篇中实现了 C1FlexGrid的撤销还原功能,这篇是要仿 Excel 做一个行列删除以及单元格的自由合并拆分,楼主怕在原工程里复杂的说不清道不明,所以干脆提取出来做了一个 Demo 来说明实现过 ...

随机推荐

  1. Mysql 获取当月和上个月第一天和最后一天的解决方案

    #获取当前日期select curdate(); #获取当月最后一天select last_day(curdate()): #获取本月的第一天select date_add(curdate(),int ...

  2. Java 使用getClass().getResourceAsStream()方法获取资源

    之前想获取一个资源文件做一些处理,使用getClass().getResourceAsStream()一直拿不到文件. 具体的用法. 1 InputStream is = this.getClass( ...

  3. python中时间差中seconds和total_seconds

    在python中经常会用到计算两个时间差,两个日期类型进行相减可以获取到时间差 经常会使用seconds来获取,其实seconds获取的是时间差的秒数,遗漏了天 seconds是获取时间部分的差值,而 ...

  4. scala spark 调用hivecontext

    import org.apache.spark.rdd.RDD def save(data: RDD[ModelReplay], modelKey: String, dt: String): Unit ...

  5. tensor flow 视频

    http://v.youku.com/v_show/id_XMTYxMjQ2NTYyNA==.html?spm=a2h1n.8251843.playList.5!19~5~A.siMjNW&f ...

  6. Ansible 从MySQL数据库添加或删除用户

    mysql_user - 从MySQL数据库添加或删除用户. 概要 要求(在执行模块的主机上) 选项 例子 笔记 状态 支持 概要 从MySQL数据库添加或删除用户. 要求(在执行模块的主机上) My ...

  7. HttpClient 超时时间

    setSoTimeout(MilSec):连接超时时间.如果在连接过程中有数据传输,超时时间重新计算. setConnectTimeout(MilSec):获取连接超时时间.如果该参数没有设置,那么默 ...

  8. LOG4J spring与mybatis整合

    1.导入包log4j-1.2.17.jar <dependency>            <groupId>log4j</groupId>            ...

  9. ALTER数据库

    alter table dbo.Sheet1$ alter column UserId int null

  10. 几种常见的Web服务器

    Apache与Tomcat的区别 ,几种常见的web/应用服务器 APACHE是一个web服务器环境程序 启用他可以作为web服务器使用 不过只支持静态网页 如(asp,php,cgi,jsp)等动态 ...