为什么copyPixelsFromBuffer提供的颜色不正确? setPixels正确但速度慢

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了为什么copyPixelsFromBuffer提供的颜色不正确? setPixels正确但速度慢相关的知识,希望对你有一定的参考价值。

对于我的android应用程序,我从本机代码获取ByteBuffer。它包含用于创建位图的像素颜色值。

原始图片 -

enter image description here

我在位图上使用了copyPixelsFromBuffer,但是在显示位图时我得到的颜色不正确。

以下是此方法的代码 -

方法1

ByteBuffer buffer = ...

Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
buffer.rewind();
bitmap.copyPixelsFromBuffer(buffer);

约。时间 - 约0.4毫秒 结果 - 颜色错误 - enter image description here

方法2

接下来我尝试了setPixels。它仍然提供错误的颜色,速度慢10倍以上,并为int[]使用额外的内存。请注意buffer.hasArray()false,所以我无法从缓冲区获取数组。

ByteBuffer buffer = ...

Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
buffer.rewind();

int[] pixels = new int[width * height];

for (int i = 0; i < width * height; i++) {
    int a = buffer.get();
    int r = buffer.get();
    int g = buffer.get();
    int b = buffer.get();
    pixels[i] = a << 24 | r << 16 | g << 8 | b;
}
bitmap.setPixels(pixels, 0, width, 0, 0, width, height);

约。时间 - 约4.0毫秒 结果 - 颜色错误 -

enter image description here

方法3

这次我使用了setPixels,但是使用IntBufferByteBuffer表示的像素值。颜色是正确的,但时间仍然很长,并有额外的内存分配。

ByteBuffer buffer = ...
IntBuffer intBuffer = buffer.asIntBuffer();

Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
buffer.rewind();

int[] pixels = new int[width * height];

for (int i = 0; i < width * height; i++) {
    pixels[i] = intBuffer.get();
}
bitmap.setPixels(pixels, 0, width, 0, 0, width, height);

约。时间 - 约3.0毫秒 结果 - 正确的颜色 -

enter image description here

有关为何我使用copyPixelsFromBuffer错误颜色的任何提示?我想用它而不是setPixels,因为它更快,不需要额外的内存分配。

答案

我发现了问题 - 即使Bitmap.Config据说是ARGB_8888,它确实是RGBA。我认为这是android开发人员文档和代码中的一个巨大错误。

在这个问题中已经注意到同样的问题 - Is Android's ARGB_8888 Bitmap internal format always RGBA?

并且ndk文档正确地指出了格式为ANDROID_BITMAP_FORMAT_RGBA_8888

解决方案很简单 - 使用RGBA格式创建缓冲区。或者在java端切换频道,如下所示 -

for (int i = 0; i < width * height; i++) {
    Byte a = buffer.get();
    Byte r = buffer.get();
    Byte g = buffer.get();
    Byte b = buffer.get();
    bufferCopy.put(r);
    bufferCopy.put(g);
    bufferCopy.put(b);
    bufferCopy.put(a);
}

这不是非常有效的代码,但可以完成工作。

以上是关于为什么copyPixelsFromBuffer提供的颜色不正确? setPixels正确但速度慢的主要内容,如果未能解决你的问题,请参考以下文章

Java有了synchronized,为什么还要提供Lock

Java有了synchronized,为什么还要提供Lock

第17期面试官:Java中提供了synchronized,为什么还要提供Lock呢?高并发

Java:既然有了synchronized,为什么还要提供Lock?

为啥 JUnit 不提供 assertNotEquals 方法?

云服务提供商是什么