2012-04-10 10 views
7

¿Cuál es la forma más rápida de obtener el valor RGB de cada píxel de BufferedImage?Se necesita una forma más rápida de obtener el valor RGB para cada píxel de una imagen almacenada en memoria intermedia

Ahora estoy obteniendo los valores RGB usando dos bucles for como se muestra en el siguiente código, pero tardó demasiado tiempo en obtener esos valores ya que el bucle anidado ejecuta un total de 479999 veces para mi imagen. Si utilizo una imagen de 16 bits, ¡este número sería incluso mayor!

Necesito una forma más rápida de obtener los valores de píxel.

Este es el código actualmente estoy tratando de trabajar con:

BufferedImage bi=ImageIO.read(new File("C:\\images\\Sunset.jpg")); 

int countloop=0; 

for (int x = 0; x <bi.getWidth(); x++) { 
    for (int y = 0; y < bi.getHeight(); y++) { 
     Color c = new Color(bi.getRGB(x, y)); 
     System.out.println("red=="+c.getRed()+" green=="+c.getGreen()+" blue=="+c.getBlue()+" countloop="+countloop++);                                     
    } 
} 
+0

'incluso puede aumentar cuando voy a utilizar 16 bits image' - ¿Por qué el número de iteraciones depende de los bits por píxel? ¿Y cuál es el caso de uso para eso? Tenga en cuenta que la creación de objetos 'Color', así como la impresión en la consola lleva un tiempo. Si desea acceder a todos los píxeles de 479999, no puede deshacerse de un bucle (podría fusionarlos en uno, pero eso no debería marcar una gran diferencia). – Thomas

+2

La salida ralentiza el bucle completo. Pruébalo sin. –

+2

Podría ir mucho más rápido sin la impresión –

Respuesta

12

No sé si esto podría ayudar y no he probado todavía pero se puede obtener los valores RGB de esta manera:

BufferedImage bi=ImageIO.read(new File("C:\\images\\Sunset.jpg")); 
int[] pixel; 

for (int y = 0; y < bi.getHeight(); y++) { 
    for (int x = 0; x < bi.getWidth(); x++) { 
     pixel = bi.getRaster().getPixel(x, y, new int[3]); 
     System.out.println(pixel[0] + " - " + pixel[1] + " - " + pixel[2] + " - " + (bi.getWidth() * y + x)); 
    } 
} 

Como se puede ver que no tiene que inicializar una nuevo Color dentro del lazo. También invertí los bucles de ancho/alto como lo sugiere onemasse para recuperar el contador de los datos que ya tengo.

2

¿Usted intentó BufferedImage.getRGB(int, int ,int ,int, int[] , int , int)?

Algo así como:

int[] rgb = bi.getRGB(0,0, bi.getWidth(), bi.getHeight(), new int[bi.getWidth() * bi.getHeight(), bi.getWidth()]) 

no probamos, así que no sé si es más rápido.

editar Después de haber mirado @ el código, probablemente no lo es, pero vale la pena intentarlo.

3

Debes repetir las filas en el bucle externo y las columnas en el interior. De esa forma evitará los errores de caché.

+2

¿No es eso lo que ya está haciendo? – Singh

5

Cambiando de un grupo de getRGB individuales a un getRGB grande para copiar toda la imagen en una matriz, el tiempo de ejecución cayó en un orden de magnitud de 33,000 milisegundos a 3,200 milisegundos, mientras que el tiempo creaba la matriz solo 31 milisegundos.

Sin dudas, una gran lectura de una matriz e indexación directa de la matriz es mucho más rápida que muchas lecturas individuales.

La diferencia de rendimiento aparece relacionada con el uso de una instrucción de punto de corte al final de la clase. Mientras que el punto de corte estaba fuera del ciclo, cada línea de código dentro de la clase parece ser probada para el punto de corte. Cambiar a obtener individual NO mejora la velocidad.

Como el código sigue siendo correcto, el resto de la respuesta puede seguir siendo útil.

Antiguo comunicado

colorRed=new Color(bi.getRGB(x,y)).getRed(); 

leer la declaración para copiar una imagen de bits en una matriz

int[] rgbData = bi.getRGB(0,0, bi.getWidth(), bi.getHeight(), 
       null, 0,bi.getWidth());   

El getRGB en una matriz pone todos los valores de 3 colores en un solo elemento de la matriz, colores tan individuales leer debe extraerse girando y un "y". La coordenada y debe multiplicarse por el ancho de la imagen.

código para leer los colores individuales de la matriz

colorRed=(rgbData[(y*bi.getWidth())+x] >> 16) & 0xFF; 

colorGreen=(rgbData[(y*bi.getWidth())+x] >> 8) & 0xFF; 

colorBlue=(rgbData[(y*bi.getWidth())+x]) & 0xFF; 
0

he encontrado una solución aquí https://alvinalexander.com/blog/post/java/getting-rgb-values-for-each-pixel-in-image-using-java-bufferedi

BufferedImage bi = ImageIO.read(new File("C:\\images\\Sunset.jpg")); 

for (int x = 0; x < bi.getWidth(); x++) { 
    for (int y = 0; y < bi.getHeight(); y++) { 
     int pixel = bi.getRGB(x, y); 
     int red = (pixel >> 16) & 0xff; 
     int green = (pixel >> 8) & 0xff; 
     int blue = (pixel) & 0xff; 
     System.out.println("red: " + red + ", green: " + green + ", blue: " + blue);                                     
    } 
} 
+0

¿es un algoritmo más rápido? –

Cuestiones relacionadas