arrays - create - ¿Cómo convertir un byte[] a un BufferedImage en Java?
java bufferedimage to byte[] (5)
Estoy publicando este hilo porque tengo algunas dificultades para lidiar con las imágenes en Java. Me gustaría poder convertir una imagen en una matriz de bytes [], y luego poder hacer la operación inversa, así que puedo cambiar el RGB de cada píxel y luego crear una nueva imagen. Quiero usar esta solución porque setRGB () y getRGB () de BufferedImage pueden ser demasiado lentos para imágenes grandes (corríjame si me equivoco).
Leí algunas publicaciones aquí para obtener una matriz de bytes [] ( como aquí ) de modo que cada píxel esté representado por 3 o 4 celdas de la matriz que contiene los valores rojo, verde y azul (con el valor alfa adicional, cuando hay son 4 celdas), que es bastante útil y fácil de usar para mí. Aquí está el código que utilizo para obtener esta matriz (almacenada en una clase de PixelArray que he creado):
public PixelArray(BufferedImage image)
{
width = image.getWidth();
height = image.getHeight();
DataBuffer toArray = image.getRaster().getDataBuffer();
array = ((DataBufferByte) toArray).getData();
hasAlphaChannel = image.getAlphaRaster() != null;
}
Mi gran problema es que no he encontrado ningún método eficaz para convertir esta matriz de bytes [] a una nueva imagen, si quisiera transformar la imagen (por ejemplo, eliminar los valores azul / verde y solo mantener el rojo). Probé esas soluciones:
1) Crear un objeto DataBuffer, luego crear un SampleModel, para finalmente crear un WritableRaster y luego BufferedImage (con objetos adicionales ColorModel y Hashtable). No funcionó porque aparentemente no tengo toda la información que necesito (no tengo idea de cuál es el constructor Hashtable for BufferedImage ()).
2) Utilizando un ByteArrayInputStream. Esto no funcionó porque la matriz de bytes [] esperada con ByteArrayInputStream no tiene nada que ver con la mía: representa cada byte del archivo, y no cada componente de cada píxel (con 3-4 bytes para cada píxel) ...
¿Alguien podría ayudarme?
El enfoque utilizando ImageIO.read directamente no es correcto en algunos casos. En mi caso, el byte en bruto [] no contiene ninguna información sobre el ancho, la altura y el formato de la imagen. Al usar solo ImageIO.read, es imposible que el programa construya una imagen válida.
Es necesario pasar la información básica de la imagen al objeto BufferedImage:
BufferedImage outBufImg = new BufferedImage(width, height, bufferedImage.TYPE_3BYTE_BGR);
Luego configure los datos para el objeto BufferedImage usando setRGB o setData. (Cuando se usa setRGB, parece que primero debemos convertir el byte [] en int []. Como resultado, puede causar problemas de rendimiento si los datos de la imagen de origen son grandes. Tal vez setData sea una mejor idea para los datos de origen escritos de big byte []) .)
He intentado los enfoques mencionados aquí, pero por alguna razón ninguno de los dos funcionó. El uso de ByteArrayInputStream
e ImageIO.read(...)
devuelve un valor nulo, mientras que byte[] array = ((DataBufferByte) image.getRaster().getDataBuffer()).getData();
devuelve una copia de los datos de la imagen, no una referencia directa a ellos (consulte también here ).
Sin embargo, lo siguiente funcionó para mí. Supongamos que se conocen las dimensiones y el tipo de datos de imagen. Sea también byte[] srcbuf
el búfer de los datos a convertir en BufferedImage
. Entonces,
Crear una imagen en blanco, por ejemplo.
img=new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR);
Convierta la matriz de datos a
Raster
y usesetData
para llenar la imagen, es decir,img.setData(Raster.createRaster(img.getSampleModel(), new DataBufferByte(srcbuf, srcbuf.length), new Point() ) );
Prueba esto:
private BufferedImage createImageFromBytes(byte[] imageData) {
ByteArrayInputStream bais = new ByteArrayInputStream(imageData);
try {
return ImageIO.read(bais);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
Varias personas votaron el comentario de que la respuesta aceptada es incorrecta.
Si la respuesta aceptada no funciona, puede deberse a que Image.IO no tiene soporte para el tipo de imagen que está intentando (por ejemplo, tiff).
Agregue esto a su pom (también conocido como jai-imageio-core-1.3.1.jar en su classpath):
<!-- https://mvnrepository.com/artifact/com.github.jai-imageio/jai-imageio-core -->
<dependency>
<groupId>com.github.jai-imageio</groupId>
<artifactId>jai-imageio-core</artifactId>
<version>1.3.1</version>
</dependency>
Para agregar soporte para:
- wbmp
- bmp
- pcx
- pnm
- crudo
- pelea
- gif (escribir)
Puedes consultar la lista de formatos soportados con:
for(String format : ImageIO.getReaderFormatNames())
System.out.println(format);
Tenga en cuenta que solo tiene que colocar, por ejemplo, jai-imageio-core-1.3.1.jar en su classpath para que funcione.
Otros proyectos que agregan apoyo adicional incluyen:
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR);
byte[] array = ((DataBufferByte) image.getRaster().getDataBuffer()).getData();
System.arraycopy(pixelArray, 0, array, 0, array.length);
Este método tiende a desincronizarse cuando intenta utilizar el objeto Graphics de la imagen resultante. Si necesita dibujar encima de su imagen, construya una segunda imagen (que puede ser persistente, es decir , no se construye cada vez sino que se reutiliza) y drawImage
la primera imagen en ella.