Voy a postear este hilo porque tengo algunos problemas con las imágenes en Java. Me gustaría ser capaz de convertir una imagen en un byte[] matriz y, a continuación, ser capaz de hacer la operación inversa, así que puedo cambiar el RGB de cada píxel, a continuación, hacer una nueva foto. Quiero usar esta solución porque setRGB() y getRGB() de BufferedImage puede ser demasiado lento para grandes imágenes (corríjanme si estoy equivocado).

He leído algunos posts aquí para obtener un byte[] array ( como aquí ), de manera que cada píxel está representado por 3 o 4 células de la matriz que contiene el rojo, el verde y el azul (valores con el valor de alfa, cuando hay 4 células), lo cual es bastante útil y fácil de usar para mí. Este es el código que uso para obtener esta matriz (almacenado en un PixelArray clase 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 todavía no he encontrado ningún método eficiente para convertir este byte[] matriz a una nueva imagen, si quería transformar la imagen (por ejemplo, quitar el azul/verde de valores y solo en el mantenimiento de la roja). He intentado las soluciones :

1) Hacer un DataBuffer objeto, a continuación, hacer un SampleModel, para finalmente crear un WritableRaster y, a continuación, BufferedImage (con modelo de color y Hashtable objetos). No funcionaba porque al parecer no tienen toda la información que necesito (tengo ni idea de lo que la tabla Hash para BufferedImage() constructor).

2) el Uso de un ByteArrayInputStream. Esto no funciona porque el byte[] matriz de espera con ByteArrayInputStream no tiene nada que hacer con la mía : representa cada uno de los bytes del archivo, y no la de cada componente de cada píxel (con 3-4 bytes para cada píxel)…

Podría alguien ayudarme?

InformationsquelleAutor Jef Grailet | 2012-10-03

5 Comentarios

  1. 32

    Intente esto:

    private BufferedImage createImageFromBytes(byte[] imageData) {
        ByteArrayInputStream bais = new ByteArrayInputStream(imageData);
        try {
            return ImageIO.read(bais);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
    
    • Es que realmente la manera más eficiente? Acabo de crear un nuevo BufferedImage, obtener la byte[] de la misma manera como en el primer post, y el uso System.ArrayCopy. No tiende a salir de la sincronización cuando ambos intentan escribir el byte[] y a los Gráficos de objetos de la imagen.
    • En una prueba rápida, su método devuelve null porque mi ImageIO no tiene un ImageInputStreamSPI la comprensión de las primas de corriente.
    • Puede algún moderador por favor eliminar esta como aceptado la respuesta, ya que eso está mal.
  2. 10

    He probado los enfoques mencionados aquí, pero por alguna razón ninguno de ellos funcionaba. El uso de ByteArrayInputStream y ImageIO.read(...) devuelve null, mientras que byte[] array = ((DataBufferByte) image.getRaster().getDataBuffer()).getData(); devuelve una copia de los datos de la imagen, no es una referencia directa a ellos (véase también aquí).

    Sin embargo, los siguientes trabajó para mí. Supongamos que las dimensiones y el tipo de los datos de la imagen son conocidos. Vamos también byte[] srcbuf ser el buffer de los datos que se convertirán en BufferedImage. Entonces,

    1. Crear una imagen en blanco, por ejemplo

      img=new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR);
      
    2. Convertir los datos de la matriz de Raster y uso setData para rellenar la imagen, es decir,

      img.setData(Raster.createRaster(img.getSampleModel(), new DataBufferByte(srcbuf, srcbuf.length), new Point() ) );
      
    • Esto funcionó para mí.
  3. 6
    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 salir de la sincronización cuando intenta utilizar el objeto de Gráficos de la imagen resultante. Si usted necesita para dibujar en la parte superior de la imagen, la construcción de una segunda imagen (que puede ser persistente, es decir, no se construye a cada momento, pero la re-usa) y drawImage el primero en él.

    • Del mismo modo, si la imagen es de tipo TYPE_INT_ARGB, tiene acceso a la matriz como int[] array = ((DataBufferInt) image.getRaster().getDataBuffer()).getData(). Cada número entero representa un píxel en la imagen: Bits 24-31 son alfa, 16-23 son de color rojo, 8-15 son de color verde, 0-7 son de color azul.
  4. 3

    Varias personas upvoted el comentario de que el aceptado la respuesta es errónea.

    Si la aceptan respuesta no funciona, puede ser porque la Imagen.IO no tiene soporte para el tipo de imagen que estamos tratando (por ejemplo, tiff).

    Agregar esto a su pom (aka poner jai-imageio-core-1.3.1.jar en su ruta de clase):

        <!-- 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 compatibilidad para:

    • wbmp
    • bmp
    • pcx
    • pnm
    • raw
    • tiff
    • gif (escribir)

    Usted puede consultar la lista de formatos compatibles con:

         for(String format : ImageIO.getReaderFormatNames())
            System.out.println(format);
    

    Tenga en cuenta que usted sólo tiene que colocar por ejemplo jai-imageio-core-1.3.1.jar en su classpath para hacer que funcione.

    Otros proyectos que añadir soporte adicional incluyen:

    • tener para el suministro de las dimensiones de la imagen no es muy sensato – hay otros jai-imageio implementaciones que trabajar, también, pero algunos de ellos necesitan (dependiente de la plataforma) binarios y la mayoría no están en maven central (si eso es un problema para mí).
    • Gracias por señalar. Necesitaba JP2 formato a convertir. Yo realmente necesitaba esta dependencia: <dependency> <groupId>com.github.jai-imageio</groupId> <artifactId>jai-imageio-jpeg2000</artifactId> <version>1.3.0</version> </dependency>
  5. 0

    El enfoque mediante el uso de ImageIO.leer directamente no es adecuado en algunos casos. En mi caso, la materia prima byte[] no contiene ninguna información sobre la anchura y la altura y el formato de la imagen. Por el sólo uso de ImageIO.leer, es imposible para el programa para la construcción de una imagen válida.

    Es necesario pasar la información básica de la imagen a BufferedImage objeto:

     BufferedImage outBufImg = new BufferedImage(anchura, altura, bufferedImage.TYPE_3BYTE_BGR); 
    

    A continuación, ajuste los datos para el objeto BufferedImage mediante setRGB o setData. (Cuando se utiliza setRGB, parece que debemos convertir byte [], int[] en primer lugar. Como resultado, puede causar problemas de rendimiento si la imagen de la fuente de datos es grande. Tal vez setData es una mejor idea para grandes byte[] escribió fuente de datos.)

Dejar respuesta

Please enter your comment!
Please enter your name here