在Android位图上优化每像素混合

5
我正在尝试在两张图片上应用混合滤镜(在这种情况下是HardLight)。由于基本的Android库不支持HardLight,所以我需要手动处理每个像素。第一次运行效果良好,但速度较慢。从基本的500x500图像和500x500过滤器生成一个500x500的图像需要太长时间。这段代码还用于生成缩略图(72x72),是应用程序核心的重要部分。我希望能获得如何加速此过程的建议或提示。
如果假设两个图像都没有alpha通道可以获得巨大的性能提升,那也是可以的。注意:示例中未使用BlendMode和alpha值(BlendMode将选择混合类型,在这种情况下我硬编码了HardLight)。
public Bitmap blendedBitmap(Bitmap source, Bitmap layer, BlendMode blendMode, float alpha) {
    Bitmap base = source.copy(Config.ARGB_8888, true);
    Bitmap blend = layer.copy(Config.ARGB_8888, false);

    IntBuffer buffBase = IntBuffer.allocate(base.getWidth() * base.getHeight());
    base.copyPixelsToBuffer(buffBase);
    buffBase.rewind();

    IntBuffer buffBlend = IntBuffer.allocate(blend.getWidth() * blend.getHeight());
    blend.copyPixelsToBuffer(buffBlend);
    buffBlend.rewind();

    IntBuffer buffOut = IntBuffer.allocate(base.getWidth() * base.getHeight());
    buffOut.rewind();

    while (buffOut.position() < buffOut.limit()) {
        int filterInt = buffBlend.get();
        int srcInt = buffBase.get();

        int redValueFilter = Color.red(filterInt);
        int greenValueFilter = Color.green(filterInt);
        int blueValueFilter = Color.blue(filterInt);

        int redValueSrc = Color.red(srcInt);
        int greenValueSrc = Color.green(srcInt);
        int blueValueSrc = Color.blue(srcInt);

        int redValueFinal = hardlight(redValueFilter, redValueSrc);
        int greenValueFinal = hardlight(greenValueFilter, greenValueSrc);
        int blueValueFinal = hardlight(blueValueFilter, blueValueSrc);

        int pixel = Color.argb(255, redValueFinal, greenValueFinal, blueValueFinal);

        buffOut.put(pixel);
    }

    buffOut.rewind();

    base.copyPixelsFromBuffer(buffOut);
    blend.recycle();

    return base;
}

private int hardlight(int in1, int in2) {
    float image = (float)in2;
    float mask = (float)in1;
    return ((int)((image < 128) ? (2 * mask * image / 255):(255 - 2 * (255 - mask) * (255 - image) / 255)));

}

你好,你能帮我解决如何在这个函数中使用alpha的问题吗? - Paulo Cesar
3个回答

2

浮点运算通常比整数运算慢,虽然我不能确定Android是否也是如此。我想知道为什么你要将输入转换为浮点数,而这些操作看起来完全可以使用整数进行计算?

将公式内联到循环中可能会加速运行速度,而不是调用函数。或许不一定会有提升,但值得尝试并进行基准测试。


尝试了不同的方法后,我成功地通过使用int数组而不是缓冲区(使用getPixels()setPixels()),并且在hardlight中不将值转换为浮点数,从而获得了约40%的性能提升。除此之外,我认为你可以获得最佳性能的方法是将该计算提升到本地级别,也许实现一个自定义的Xfermode。 - Kevin Dion
嗯,切换到getPixels()/setPixels(),我发现计算时间增加了一倍,除非我误解了你的意思? - MarkPowell
@MarkPowell,我认为@Kevin是在支持int数组,并反对getPixels/setPixels。如果你有更多问题,你需要通过@Kevin开始你的评论来直接向他提问。 - Mark Ransom

1

如果您可以牺牲最终图像质量/精度的3个比特/像素,我们可以通过使用按位运算符重写函数hardlight()来获得约25%的性能提升:

int hardlight(int image, int mask) {
    return (((image < 128) ? 
           ( (((mask << 1) * image) >> 8) ):
           (255^( (((255^mask) << 1) * (255^image)) >> 8))));
}

谢谢,通过这个改进,整体速度提高了大约10%。不过,我们还需要看一下是否可以接受每像素3位的牺牲。 - MarkPowell
好的。遗憾的是,性能提升只有10%,而不是像我的Windows机器一样达到25%。我怀疑Android位运算符的优化程度比Windows平台/MS VS C/C++编译器要低。或者主要的性能瓶颈不在hardlight函数,而是在其他地方。 - Agnius Vasiliauskas

0

之前有一个类似的问题(链接)。我不确定原帖作者是否解决了他的问题。

在我的情况下,为了实现“photoshop混合”,我通过将半透明阴影叠加到单一颜色上来实现。这只是我的平面设计师找出如何制作阴影叠加的问题。它非常有效,我完全忽略了必须迭代位图像素的问题(我使用getPixels()和setPixels())。困难的部分确实在我的设计师那里,但是一旦他弄清楚了,他就生成了许多外观极佳的图像。

我基本上使用了一个alpha掩码(用于生成动态颜色)与阴影叠加。我很想学习通过代码解决问题的方法,祝你好运!

编辑:此外,我不熟悉BlendMode。您没有在您的方法中使用它。这是什么,一个自定义类吗?


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接