Convertir la matriz de bytes de 4 bits en escala de grises a Bitmap Android
Estoy recuperando una imagen en bruto de una cámara y las especificaciones de la imagen son los siguientes:
- Resolución de 80 x 60
- Escala de grises de 4 bits
Recupero la imagen como una matriz de bytes y tienen una matriz que es 2400 (1/2 * 80 * 60) bytes de largo. El siguiente paso es convertir la matriz de bytes en un mapa de bits. Ya he usado el
- Cómo guardar una imagen transparente en Android usando ALPHA_8
- Cómo cambiar la opacidad de un mapa de bits?
- Mapa de bits a NinePatch a nuevo mapa de bits escalado
- Lienzo: intentando usar un mapa de bits reciclado android.graphics.Bitmap en android
- ¿Por qué esto no funciona a veces?
BitmapFactory.decodeByteArray(bytes, 0, bytes.length)
Pero que no devolvió una imagen visualizable. Miré este poste y copié el código abajo en mi uso de Androide, pero conseguí un "amortiguador no bastante grande para los pixeles" error del tiempo de ejecución.
byte [] Src; //Comes from somewhere... byte [] Bits = new byte[Src.length*4]; //That's where the RGBA array goes. int i; for(i=0;i<Src.length;i++) { Bits[i*4] = Bits[i*4+1] = Bits[i*4+2] = ~Src[i]; //Invert the source bits Bits[i*4+3] = -1;//0xff, that's the alpha. } //Now put these nice RGBA pixels into a Bitmap object Bitmap bm = Bitmap.createBitmap(Width, Height, Bitmap.Config.ARGB_8888); bm.copyPixelsFromBuffer(ByteBuffer.wrap(Bits));
En la parte inferior del hilo, el cartel original tenía el mismo error que tengo actualmente. Sin embargo, su problema fue corregido con el código pegado arriba. ¿Alguien tiene alguna sugerencia sobre cómo convertir la imagen en bruto o la matriz RGBA en un mapa de bits?
¡Muchas gracias!
ACTUALIZAR:
He seguido la sugerencia de Geobits y este es mi nuevo código
byte[] seperatedBytes = new byte[jpegBytes.length * 8]; for (int i = 0; i < jpegBytes.length; i++) { seperatedBytes[i * 8] = seperatedBytes[i * 8 + 1] = seperatedBytes[i * 8 + 2] = (byte) ((jpegBytes[i] >> 4) & (byte) 0x0F); seperatedBytes[i * 8 + 4] = seperatedBytes[i * 8 + 5] = seperatedBytes[i * 8 + 6] = (byte) (jpegBytes[i] & 0x0F); seperatedBytes[i * 8 + 3] = seperatedBytes[i * 8 + 7] = -1; //0xFF }
Ahora, puedo obtener un mapa de bits con este comando
Bitmap bm = BitmapFactory.decodeByteArray(seperatedBytes, 0, seperatedBytes.length);
Pero el mapa de bits tiene un tamaño de 0 KB.
La imagen que estoy recibiendo es una imagen cruda de esta cámara . Desafortunadamente, recuperar una imagen JPEG pre-comprimida no es una opción porque necesito escala de grises de 4 bits.
- Cómo imprimir una imagen con el tamaño de papel completo (80MM) en la impresora térmica (EPSON)
- Android: establece ImageView en la URL
- Cargar imagen de contacto en mapa de bits
- No se puede comprimir un mapa de bits reciclado
- Cambiar el tamaño de la imagen en la notificación de estilo bigpicture
- Cómo crear ImageView redimensionable en Android
- Android: Dibuja varios mapas de bits en otro mapa de bits
- Cómo mosaico de un mapa de bits en una lona
Si la imagen que entra es sólo en 2400 bytes, eso significa que hay dos píxeles por byte (4 bits cada uno). Sólo está dando el búfer de bytes 2400 * 4 = 9600
bytes cuando un ARGB_8888 necesita 4 bytes por píxel, o 60 * 80 * 4 = 19200
.
Necesita dividir cada byte entrante en un valor de nibble superior / inferior, luego aplicarlo a los siguientes 8 bytes (excluyendo alfa). Puede ver esta respuesta para un ejemplo de cómo dividir bytes.
Básicamente:
- Dividir el byte entrante
i
en dos nibbles,ia
yib
- Aplicar
ia
a los bytes salientesi*8
a(i*8)+2
- Aplicar
ib
a los bytes salientes(i*8)+4
a(i*8)+6
- Los bytes
(i*8)+3
y(i*8)+7
son alfa (0xFF
)
Una vez que tenga el tamaño adecuado byte buffer, usted debe ser capaz de utilizar decodeByteArry()
sin problemas.
Si te entiendo correctamente tienes una matriz de bytes, cuyos bytes contienen 2 valores de escala de grises cada uno. Yo diría que un valor de escala de grises puede ser considerado como un valor de intensidad simple, ¿no?
Así que lo primero que tiene que hacer es separar sus valores de escala de grises en bytes individuales cada uno, ya que BitmapFactory.decodeByteArray probablemente no puede manejar sus "medio bytes". Esto puede hacerse fácilmente mediante operaciones de bits. Para obtener el primer valor de 4 bits de su byte `0bxxxxxxxx`, debe cambiar a la derecha 4 veces:` 0bxxxxxxxx >> 4`, lo que daría lugar a `0b0000xxxx`. El segundo valor se puede obtener de forma bit a bit o con el patrón `0b00001111`:` 0b00001111 ^ 0bxxxxxxxx` que conduciría a `0b0000xxxx`. (Para obtener información detallada sobre las operaciones de bits, consulte aquí: Operaciones de bits )
Esos dos valores ahora se pueden almacenar en una nueva matriz de bytes. Si lo hace por cada par de half-bytes, obtendrá una matriz de bytes completos y un tamaño doble al final.
No estoy seguro de si esto ya es suficiente para 'BitmapFactory.decodeByteArray' o si tiene que repetir cada byte 4 veces para cada RGBA-Channel, lo que aumentaría el tamaño de su matriz de bytes de nuevo por cuatro veces el tamaño original . Espero no haber notado nada y mis sugerencias ayudan;)