Quiero hacer una copia (de un área rectangular) de los valores ARGB de una fuente BufferedImage
en un destino BufferedImage
. No se debe hacer ninguna composición: si copio un píxel con un valor ARGB de 0x8000BE50 (valor alfa a 128), entonces el píxel de destino debe ser exactamente 0x8000BE50, anulando por completo el píxel de destino.Java: ¿cómo hacer una copia rápida de los píxeles de BufferedImage? (prueba unitaria incluida)
Tengo una pregunta muy precisa e hice una prueba unitaria para mostrar lo que necesito. La prueba unitaria es completamente funcional y autónoma, está pasando bien y está haciendo exactamente lo que yo quiero.
Sin embargo, quiero un eficiente método demás rápido y más memoria para reemplazar copySrcIntoDstAt (...).
Ese es el punto de mi pregunta: no busco cómo "llenar" la imagen de una manera más rápida (lo que hice es solo un ejemplo para tener una prueba unitaria). Todo lo que quiero es saber lo que sería rápido y eficiente con la memoria manera de hacerlo (es decir, rápido y sin crear objetos innecesarios).
La implementación de la prueba de concepto que hice obviamente es muy eficiente en cuanto a la memoria, pero es lenta (haciendo una getRGB
y una setRGB
por cada píxel).
Esquemáticamente, lo he entendido: (donde A indica píxeles correspondientes de la imagen de destino antes de la copia)
AAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAA
Y yo quiero tener esto:
AAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAABBBBAAA
AAAAAAAAAAAAABBBBAAA
AAAAAAAAAAAAAAAAAAAA
donde 'B 'representa los píxeles de src imagen.
Tenga en cuenta que estoy buscando un reemplazo exacto del método copySrcIntoDstAt (...), no para un enlace/cita API.
import org.junit.Test;
import java.awt.image.BufferedImage;
import static org.junit.Assert.*;
public class TestCopy {
private static final int COL1 = 0x8000BE50; // alpha at 128
private static final int COL2 = 0x1732FE87; // alpha at 23
@Test
public void testPixelsCopy() {
final BufferedImage src = new BufferedImage( 5, 5, BufferedImage.TYPE_INT_ARGB);
final BufferedImage dst = new BufferedImage(20, 20, BufferedImage.TYPE_INT_ARGB);
convenienceFill(src, COL1);
convenienceFill(dst, COL2);
copySrcIntoDstAt(src, dst, 3, 4);
for (int x = 0; x < dst.getWidth(); x++) {
for (int y = 0; y < dst.getHeight(); y++) {
if (x >= 3 && x <= 7 && y >= 4 && y <= 8) {
assertEquals(COL1, dst.getRGB(x,y));
} else {
assertEquals(COL2, dst.getRGB(x,y));
}
}
}
}
// clipping is unnecessary
private static void copySrcIntoDstAt(
final BufferedImage src,
final BufferedImage dst,
final int dx,
final int dy
) {
// TODO: replace this by a much more efficient method
for (int x = 0; x < src.getWidth(); x++) {
for (int y = 0; y < src.getHeight(); y++) {
dst.setRGB(dx + x, dy + y, src.getRGB(x,y));
}
}
}
// This method is just a convenience method, there's
// no point in optimizing this method, this is not what
// this question is about
private static void convenienceFill(
final BufferedImage bi,
final int color
) {
for (int x = 0; x < bi.getWidth(); x++) {
for (int y = 0; y < bi.getHeight(); y++) {
bi.setRGB(x, y, color);
}
}
}
}
+1 muy agradable ... nunca pensé usando varios * * System.arraycopy sería el camino a seguir. ¡Supongo que cada Imagen Buffered siempre tiene un ráster y que no hay creación de objetos aquí, ¿cierto? Es realmente agradable, pero al mismo tiempo parece un poco raro: esperaba algo preexistente haciendo el trabajo sin tener que hacer un * por * loop y System.arraycopy manualmente. Pero, sí, muy bien (lo intenté por cierto y parece estar bien :) – SyntaxT3rr0r
@WizardOfOds Gracias, subrayó "más rápido y más eficiente en la memoria", siempre se requiere algún tipo de bucle para mover las compensaciones. Manipular las estructuras internas sin hacer copias y crear objetos. Dudo que haya un método que no sea JNI y que funcione mejor. – stacker