• WriteableBitmap(三) 扩展


    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;
    }

    pattern

  • 相关阅读:
    第三方支付架构设计之:商户回调通知系统的悲观和乐观策略
    Layui 2.0.0 正式发布:潜心之作,开箱即用的前端UI框架(确实很多内容)
    简历上的哪些内容才是 HR 眼中的干货?
    windows Hook 消息分类
    MQTT协议学习及实践(Linux服务端,Android客户端的例子)
    MQTT是IBM开发的一个即时通讯协议,构建于TCP/IP协议上,是物联网IoT的订阅协议,借助消息推送功能,可以更好地实现远程控制
    Docker Machine
    Oracle执行计划
    Spire.XLS
    Docker
  • 原文地址:https://www.cnblogs.com/TianPing/p/10372585.html
Copyright © 2020-2023  润新知