为什么copyPixelsFromBuffer的颜色不正确? setPixels是正确的但很慢 [英] Why is copyPixelsFromBuffer giving incorrect color? setPixels is correct but slow

查看:184
本文介绍了为什么copyPixelsFromBuffer的颜色不正确? setPixels是正确的但很慢的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

For my android app I am getting a ByteBuffer from native code. It contains the pixel color values to create a bitmap.

原始图片-

我在位图上使用了copyPixelsFromBuffer,但是在显示位图时我得到了错误的颜色.

I used copyPixelsFromBuffer on bitmap, but I am getting incorrect color on displaying the bitmap.

这是此方法的代码-

方法1

ByteBuffer buffer = ...

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

大约时间-约0.4毫秒
结果-颜色错误-

Approx. time - ~0.4 ms
Result - Wrong colors -

方法2

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

Next I tried setPixels. It still gives wrong colors and is more than 10 times slower and uses extra memory for int[]. Please note that buffer.hasArray() is false, so I can't get array from buffer.

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毫秒
结果-颜色错误-

Approx. time - ~4.0 ms
Result - Wrong colors -

方法3

这次我使用了setPixels,但是像素值取自ByteBufferIntBuffer表示形式.颜色是正确的,但是时间仍然很长,并且还有额外的内存分配.

This time I used setPixels but with the pixel values taken from IntBuffer representation of ByteBuffer. The colors are correct but the time is still high and there is extra memory allocation.

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毫秒
结果-正确的颜色-

Approx. time - ~3.0 ms
Result - Correct colors -

有人暗示为什么我用copyPixelsFromBuffer弄错了颜色吗?我想用它代替setPixels,因为它更快并且不需要额外的内存分配.

Any hints on why I am getting wrong colors with copyPixelsFromBuffer? I want to use it instead of setPixels as it is faster and does not require extra memory allocation.

推荐答案

我发现了问题-尽管据说Bitmap.ConfigARGB_8888,但实际上是RGBA.我认为这是android开发人员文档和代码中的一个巨大错误.

I figured out the problem - even though the Bitmap.Config is said to be ARGB_8888, it really is RGBA. I think it is a huge bug in android developer documentation and code.

此问题中也提到了相同的问题-是Android的ARGB_8888位图内部格式始终是RGBA吗?

The same issue has been noted in this question - Is Android's ARGB_8888 Bitmap internal format always RGBA?

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

And the ndk documentation correctly notes the format to be ANDROID_BITMAP_FORMAT_RGBA_8888

解决方案很简单-创建具有RGBA格式的缓冲区.或在Java端切换频道,如下所示-

Solution is simple - create the buffer with RGBA format. Or on the java side switch the channels, something like below -

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

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

This is not very efficient code, but gets the job done.

这篇关于为什么copyPixelsFromBuffer的颜色不正确? setPixels是正确的但很慢的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆