2017-12-25 9 views
1

내 안드로이드 애플 리케이션을 위해 나는 ByteBuffer 네이티브 코드를 얻고있다. 비트 맵을 생성하기위한 픽셀 색상 값을 포함합니다.copyPixelsFromBuffer가 잘못된 색상을 나타내는 이유는 무엇입니까? setPixels는 정확하지만 느리다.

원본 이미지 -

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 MS
결과 - 잘못된 색상 -
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 MS
결과 - 잘못된 색상 -

enter image description here

접근 3

이 내가 setPixels 사용 시간 만 ByteBufferIntBuffer 표현에서 가져온 픽셀 값. 색상은 정확하지만 시간은 여전히 ​​길며 추가 메모리가 할당됩니다.

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 MS
결과 - 올바른 색상 -

enter image description here

내가 copyPixelsFromBuffer으로 잘못된 색상을 받고있는 이유에 대한 어떤 힌트? 더 빠르며 여분의 메모리 할당이 필요하지 않으므로 setPixels 대신 사용하고 싶습니다.

+1

색 공간 문제가 의심 스럽지만 세 번째 시도가 올바르게 작동하는 방법을 알 수 없습니다. 접근법 3의 결과로부터 새로운 버퍼를 생성하기 위해'bitmap.copyPixelsToBuffer()'를 사용하고 두 버퍼 간의 차이점을 검사하는 것은 좋은 실험 일 수 있습니다. 이렇게하면 문제를 진단하는 데 도움이됩니다. –

+1

그냥 뭔가 다른 생각 : 버퍼의 바이트 순서가'ByteOrder.LITTLE_ENDIAN'으로 설정되어 있는지 확인하십시오. 거기에 불일치가 있으면 이상한 색상 효과가 발생할 수 있습니다. –

+0

고맙습니다 @TedHopp,'copyPixelsToBuffer()'를 사용하여 버퍼를 비교하는 팁이 매우 유용했습니다. 문제는 깨달았습니다. 버퍼는 ARGB이지만 비트 맵에는 RGBA가 필요합니다. –

답변

1

Bitmap.ConfigARGB_8888이라고해도 실제로는 RGBA입니다. 나는 이것이 안드로이드 개발자 문서 및 코드의 거대한 버그라고 생각합니다.

같은 문제

이 질문에 언급 된 - Is Android's ARGB_8888 Bitmap internal format always RGBA?

그리고 NDK 문서가 제대로 형식이 ANDROID_BITMAP_FORMAT_RGBA_8888

솔루션은 간단로 노트 - RGBA 형식과 버퍼를 작성합니다. 또는 자바 쪽에서 아래처럼 채널을 전환하십시오. -

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

이것은 매우 효율적인 코드는 아니지만 작업을 완료합니다.

관련 문제