Ver la Versión Completa : [ CONSULTA ] Recortar una imagen para crear piezas de puzle
Brausoft
22/06/16, 12:22:57
Buenas
Necesito recortar una imagen programaticamente para crear piezas de puzle.
Para recortar las piezas tengo un patrón con colores con las formas de las piezas:
http://i.stack.imgur.com/zDAji.png
Necesito crear una imagen para cada pieza.
A partir de una imagen con el patron de una sola pieza (de 1 color la zona de la pieza y en transparente el resto de la imagen) he consegido recortar la imagen con ese patrón para obtener una pieza
http://i.stack.imgur.com/Xnv4p.png
usando el siguiente codigo
Bitmap bitmap = Bitmap.createBitmap(mascara2.getWidth(), mascara2.getHeight(), Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(bitmap);
c.drawBitmap(cuadro, 0, 0, null);
Paint maskPaint = new Paint();
maskPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
c.drawBitmap(mascara2, 0, 0, maskPaint);
canvas.drawBitmap(bitmap, 0, 0, null)
Pero eso me obligaria a usar una imagen de patron para cada pieza en vez de una sola imagen con el patron de todas las piezas
¿Sabeis como se puede recortar en una imagen las zonas que esten en otra imagen de un color determinado?
Gracias
mocelet
22/06/16, 14:20:06
Tengo apuntado en la libreta hacer un juego de puzzles, aunque todavía no me había parado a escribir el código de las piezas.
En mi caso preferiría hacer el diseño del puzzle en código también, o al menos con un formato que no sea una imagen y que permita incluso una generación dinámica de la rejilla. Tendría distintos tipos de piezas y terminaciones, aunque sin garantizar que en un mismo puzzle no se repiten diseños de pieza.
Tenerlo en imagen tiene ventajas pero da muchos quebraderos de cabeza porque al final tienes que modelar cada pieza como un objeto con distintas características como su posición, con quién encaja a cada lado, si está girada o no, etc.
Contestando a la pregunta... hay mucho tratamiento de imagen ahí. Una forma un poco "bruta" de hacerlo es copiar la imagen de las piezas e ir pixel a pixel (Bitmap getPixel y setPixel), miras si es el color que quieres y lo dejas, miras si es otro y lo pones transparente. Vas apuntando el mínimo y máximo en eje X e Y donde te has ido encontrando pixeles del color de la pieza. Cuando acabes tendrás el rectángulo que contiene la pieza, recortas ese trozo y, sabiendo su posición, haces la máscara como más arriba con la imagen.
Para cada pieza tendrás que ir guardando el tamaño de su rectángulo y su posición, con eso puedes saber fácilmente si está cerca de su "posición correcta" cuando el usuario la suelte.
P.D: En este caso tendrás que asegurarte de que cada pieza tiene un color único en toda la imagen (i.e. la del ejemplo no vale). También puedes ayudar un poco al código diciéndole los rectángulos, así se evita mirar más pixeles. Menos automático pero más optimizado si tardara mucho.
P.D.2: El método anterior puede mejorarse también primero recortando el rectángulo con la pieza y luego ya borrando todo lo que no sea del color.
Brausoft
22/06/16, 16:38:23
Gracias!!!!
Lo del usar getPixel lo habia pensado pero creo que seria bastante costoso ya que para una imagen de 800x600 habria que ejecutar el getPixel y el setPixel 480.000 veces cada uno para crear todas las piezas
Lo de utilizar colores distintos inicialmente tambien lo habia pensado, pero basta con que no se repitan en piezas adyacentes. Para recotar las piezas cogeria de la imagen del patron solo un rectangulo de un ancho y un alto un 50% mayor al de la pieza para cada lado por lo que no se evaluarian colores mas que de las piezas adyacentes. Con 4 colores creo que seria suficiente.
Hice alguna aproximacion tambien de definir la superficie de la pieza programaticamente (sin utilizar ninguna imagen como patron) pero me quedo muy cutre, no tenia el mismo aspecto de las piezas de un puzle real.
mocelet
22/06/16, 17:06:18
Mmmh... dejando a un lado que los procesadores pueden ejecutar millones de instrucciones por segundo, es fácilmente optimizable el problema para que no haya que repetir trabajo y solo hagan falta dos pasadas independientemente del número de piezas.
Que sean colores diferentes facilita muchísimo la vida porque en una única pasada podrías detectar el rectángulo exacto que contiene a cada una de las piezas. Cada vez que encuentres un color que no has visto antes es que pertenece a otra pieza. En vez de llevar un max y min de cada coordenada para una pieza vas actualizando una lista donde guardas el max y min para cada color que has ido encontrando. Con un solo recorrido de la imagen identificas cuántas piezas (colores) hay y dónde están (rectángulo que la contiene).
Luego es ir borrando lo que no sea del color de la pieza en cada rectángulo, y ya no tienes por qué recorrer toda la imagen varias veces para hacer la máscara, solo los recortes.
Así, en la práctica, solo recorres dos veces la imagen, una para trocearla y otra crear la máscara con cada trozo.
P.D: Sigue sin convencerme lo de la imagen entera por el tema del antialiasing y los dientes de sierra. Es mejor que tengas los "moldes" de las piezas donde los bordes tengan cierto relieve o al menos un componente alpha degradado que disimule los dientes de sierra. Así queda un aspecto de pieza más real. Y aunque en código puede hacerse el antialising, el bevel, el emboss y todos los efectos pertinentes, si los tienes en un png lo haces a tu gusto con un editor gráfico. Van a quedar muy planas las piezas si solo las recortas, más si las recortas a baja resolución.
Brausoft
23/06/16, 11:03:19
Gracias!
Lo que comentas en la P.D te refieres a tener ya las piezas recortadas en imagenes? o tener moldes en imagenes?
Si es tener ya las piezas recortadas la pega seria que si quieres tener 10 puzles (10 imagenes distintas) tendrias que tener todas las piezas recortadas de todos los puzles
Si es tener los moldes con los efectos de relieve no tengo muy claro como seria para recortar las imagenes.
Lo que comentas del hacer los efectos de relieve por codigo tambien es interesante ¿como seria?
mocelet
23/06/16, 11:33:32
Sí, con el P.D. me refería a tener las piezas por separado y prescindir del mapa de colores. Tener, no sé, 10 tipos de pieza por ejemplo que te permitan hacer los puzzles que quieras. El puzzle estaría definido por un array mismamente con el tipo de pieza que va en cada lugar. Tiene la limitación de que es inevitable que un diseño de pieza se repita. La ventaja es que ya le puedes dar los efectos a la pieza con cualquier editor gráfico porque cada diseño es un gráfico png distinto y de paso te ahorras el tema de detectar con código la separación entre piezas.
Los efectos de relieve y demás es tirar del Canvas, se pueden hacer maravillas cuando das con los métodos adecuados y las máscaras adecuadas.
Brausoft
23/06/16, 16:37:28
No entiendo muy bien como recortarias con esas piezas (que ya tienen los efectos de relieve) la imagen del puzle (la que hay tiene que componer el jugador con todas las piezas)
Con el bloque de codigo que puse en el primer post es sencillo recortar una pieza a partir de la imagen con su figura pero dicha imagen ha de tener un color (el que sea) y el resto ser transparente
mocelet
23/06/16, 17:45:58
Recortarlo es igual porque no hace falta que sea del mismo color la pieza, simplemente que no sea completamente transparente.
Sí que llevas razón en que luego hay que mezclar el recorte con el png de la pieza para que se convierta en la pieza con efecto. Aquí ya es trabajo con máscaras y acertar con el modo correcto, en un editor gráfico que soporte capas podrías ir probando a ver qué modo de blending/mezcla da mejor resultado.
Un efecto burdo y rápido es el modo DARKEN (oscurecer), supuesto que tu modelo de pieza fuera blanco con un bordecito gris claro, al mezclar el modelo con el recorte tendrías este efecto:
http://fotones.de/image.php?di=J37B
Si el borde te lo curras más con un degradado ya parece que la pieza tenga los bordes curvos como ocurre en las piezas de verdad.
mocelet
23/06/16, 17:46:35
Perdón, edité el mensaje de antes y le di a respuesta rápida sin querer, parezco un novato XDD
Brausoft
28/06/16, 16:03:04
Gracias mocelet!!!
Para dar relieve he hecho algunas pruebas usando EmbossMaskFilter queda perfecto sobre una imagen de un solo color pero mal cuando es una una imagen normal
vBulletin® v3.8.1, Copyright ©2000-2025, Jelsoft Enterprises Ltd.