haXe中对BitmapData进行批量像素级运算

来源:互联网 发布:外贸搜索客户软件 编辑:程序博客网 时间:2024/04/29 09:31

NME中大部分的位图滤镜(flash.filters.*)都未实现,所以有些特效不得不自己编写代码来进行批量像素处理。

用getPixel32()和setPixel32()当然是最简单的,但效率很低。因此这里使用getPixels()把批量像素复制到字节数组,进行完运算,再用setPixels()覆盖回到位图。

下面的代码目的是根据一张掩码位图mask对原始位图bmp逐像素进行浮雕化处理,也就是根据每个mask像素对原始位图的像素进行加亮或暗化处理。

处理完的像素输出到一个新的字节数组obuf中,最后再设置回原始位图中覆盖原像素。

分别测试了两种方法,一种以输入输出流的方式使用ByteArray,第二种则以数组方式使用,从性能角度看,第二种应该更优。

在此段代码中有若干个API的表现在flash和cpp目标不一致,总结如下:

1. flash中用getPixels获得的ByteArray默认读写指针位置在最末,读取之前需要重置,cpp则不必;如果采用数组方式,则可完全忽略指针位置问题

2. flash中ByteArray.readByte()返回的是有符号整数即-128~127,需要用&运算转成无符号整数;而在cpp目标中返回的是0~255

3. 因为cpp目标中ByteArray继承于Bytes,因此比flash中的对应类要更灵活一些

4. 在flash和cpp中ByteArray都可以用数组访问运算符[]来随机访问元素,但在flash中,ByteArray.length可读写,cpp中,ByteArray.length只读,因此第二段代码中用了条件编译

 

具体的解说见下面代码中的注释。

 

=============== 第一种方法,使用流式操作 ================

  // BitmapData.getPixels()返回的字节数组中每个像素用4个字节表示,以ARGB排列

  // 掩码图和原位图大小相等,为width*height

  var mbuf: ByteArray = mask.getPixels(new Rectangle(0, 0, width, height));
  var bbuf: ByteArray = bmp.getPixels(new Rectangle(0, 0, width, height));
  var obuf = new ByteArray(); //用于输出的新像素数组
  // flash中用getPixels获得的ByteArray默认读写指针位置在最末,读取之前需要重置

  mbuf.position = bbuf.position = 0; 

  // 每个像素由四个字节组成,因此下面循环是对每个像素的每个颜色分量依次处理的

  for (i in 0...mbuf.length) {

    // flash中ByteArray.readByte()返回的是有符号整数即-128~127,需要用&运算转成无符号整数
    var mb = mbuf.readByte() & 0xFF, bb = bbuf.readByte() & 0xFF;
    if ((i & 0x3) == 0) { // 即i % 4 == 0,这里用位运算减少开销

      // 如果掩码像素中的alpha为0,则最终图对应像素也为透明
      obuf.writeByte(mb);
    } else if (mb > 100 && mb < 130) { 

      // 对于居于此灰色范围的掩码像素,不对原图像素做亮暗处理,直接进行复制

      obuf.writeByte(bb);
    } else { 

      // 对于高于或低于灰色范围的掩码像素,对原图按掩码比例进行亮化或暗化
      var v = (bb * mb) >> 7;  // 右移7位相当于除以128
      obuf.writeByte(v > 255 ? 255 : v); // 每个RGB颜色分量的值不能超过255
    }
  }
  obuf.position = 0; // 用输出字节数组创建新位图前别忘了要重置读写指针位置
  bmp.setPixels(new Rectangle(0, 0, width, height), obuf);

 

=============== 第二种方法,使用[]操作符 ================

  var mbuf = mask.getPixels(new Rectangle(0, 0, width, height));
  var bbuf = bmp.getPixels(new Rectangle(0, 0, width, height));
#if flash
  var obuf = new ByteArray();
  obuf.length = mbuf.length;
#else
  var obuf = new ByteArray(mbuf.length);
#end
  for (i in 0...mbuf.length) {
    var mb = mbuf[i], bb = bbuf[i];

    if ((i & 0x3) == 0) { 

      obuf[i] = mb; 

    } else if (mb > 100 && mb < 130) {
      obuf[i] = bb; 
    } else { 
      var v = (bb * mb) >> 7;
      obuf[i] = v > 255 ? 255 : v;
    }
  }
  bmp.setPixels(new Rectangle(0, 0, width, height), obuf);

原创粉丝点击