0

我目前正在开发 ios 上的绘画应用程序。

我使用直接绘制到 NSMutableData 缓冲区并使用我的画笔进行混合,如下所示:

- (void) combineColorDestination:(unsigned char*) dest source:(unsigned char*) src
{

const unsigned char sra     = ((unsigned char *)src)[3];
const float oneminusalpha   = 1.0f - (sra / 255.f);

int d[4];

for (int i=0;i<4;i++)
{
    d[i] = oneminusalpha * ((unsigned char *)dest)[i] +  ((unsigned char *)src)[i];

    if (d[i]>255)
        d[i] = 255;

    ((unsigned char *)dest)[i] = (unsigned char)d[i];
}

}

有什么优化建议吗?

我以前尝试过使用 neon,但我有一个我无法修复的错误(边界像素有问题)

我像这样迭代像素 2 x 2:

uint8x8_t va = vld1_u8(dest);
uint8x8_t vb = vld1_u8(src);
uint8x8_t res = vqadd_u8(va,vb);
vst1_u8(dest, res);
4

1 回答 1

2

建议?好吧。请注意,无论您在做什么多媒体操作,这些都是有效的,并且几乎不限于您的情况。

首先,在你做 NEON 之前,你应该改变你的代码,让它有一个函数可以同时改变一堆像素(至少一行,如果可以的话,一个矩形),而不是一个函数(或方法——甚至更糟)改变一个像素并被调用很多次:不知何故,我怀疑画笔只有 1x1 像素。

其次,除了列循环(和最终的行循环)之外,应该没有分支(即流控制结构)。没有for (i=0;i<4;i++);只需按顺序编写四个通道的代码(必要时使用宏)。没有if (d[i]>255);将其表达为另一种选择:dest[i] = (temp>255?255:temp);至少,如果不是用更有效的饱和方式代替它(存在使用减法、移位和掩码的技巧)。

第三,避免浮点数和整数之间的任何转换;这始终是有效的建议,但 float->int 转换在 ARM 上尤其具有破坏性。由于您正在处理整数,这意味着这里要提到浮点数。

一旦你做到了,令人惊讶的是,除了让你的代码更快之外,你实际上已经完成了 NEON 的准备工作:NEON 只有在你一次处理一堆像素时才有用,如果没有分支,如果你不要到处在浮点数和整数之间转换。因此,只有到那时我们才会谈论 NEON,如果此时甚至有必要的话。

于 2011-10-01T14:52:35.120 回答