Ver la Versión Completa : [ CONSULTA ] Pintar imagen de forma dinamica
LEAJIM_454
29/04/15, 01:51:14
Hola, tal como dice el titulo me gustaria saber como puedo pintar una imagen, no se si habra alguna libreria, un ejemplo de una imagen seria esta:
http://mewarnai.us/images/645663-para-colorear-de-las-series-de-disney-dibujos-en-blanco-y-negro.gif
Pero que pueda hacerlo con una paleta de colores y luego pulsar sobre una zona que quiera pintar, en todo caso que lo haga un niño. Agradesco su ayuda de antemano.
mocelet
29/04/15, 18:57:19
Por el título pensaba que era otra cosa. Lo que quieres es colorear áreas de una imagen. No es trivial...
Partiendo de que has pulsado en algún punto y que lo blanco es blanco de verdad (un JPG por la compresión podría darte niveles de gris en los bordes y te estropea el invento, un PNG no porque no tiene pérdidas) hay dos opciones principalmente:
1 - A partir de ese punto ir mirando todos los pixeles adyacentes, y los adyacentes de los adyacentes... Si sigue siendo blanco lo coloreas, si es negro dejas de mirar adyacentes (ya has llegado al borde). Computacionalmente puede ser un problema, pero tienes algunas implementaciones de algoritmos algo más rápidas como el FloodFill que presentan aquí (http://stackoverflow.com/questions/8070401/android-flood-fill-algorithm/17426163#17426163). Siempre puedes trabajar con una imagen a menor resolución para que vaya más rápido, pero entonces igual tienes problemas de bordes de sierra.
2 - Yo lo que haría si quisiera hacer un juego de colorear (algún día xD) es tener dos imágenes, la que ve el usuario en blanco y negro y otra del mismo tamaño pero con las áreas pintadas cada una de un color diferente (un mapa de colores). Es decir, si hay 27 cosas que pueden pintarse, cada una un color. Cuando el usuario pulse en la imagen en blanco y negro, tú miras qué color tiene esa coordenada en el mapa. Sabiendo el color, con un simple bucle que recorra todos los pixeles del mapa ya sabes qué píxeles corresponden al área que pulsó el usuario y sabiendo sus coordenadas los pintas en la imagen del usuario del color que quieras. O, más eficiente, con el empleo de máscaras y filtros de la clase Paint (que se pinte de un color la imagen original solo en los pixeles que la imagen-mapa tenga cierto color).
El método 1 te ahorra mucho trabajo de crear los mapas de colores, pero tiene varios inconvenientes de rendimiento y un gran problema con algunos dibujos: solo detecta espacios uniformes. En el dibujo que pones, por ejemplo, el brazo doblado corta el ala en dos. Con el método 1 serían dos áreas diferentes, pero en realidad es el ala, debería colorearse entera y dejar el brazo encima como está. Con el mapa de colores las dos partes del ala tendrían el mismo color, con pulsar cualquiera, el ala entera se colorearía.
Para el método 2 no sé si habrá alguna biblioteca, se puede hacer en pocas líneas de código (tener los dos Bitmap, consultar color de coordenada en mapa, aplicar máscara, pintar del color que quieras el original), pero hay que leerse muy bien la documentación de las máscaras, filtros, etc., o hacerlo "a lo burro" que es recorrer todos los pixeles y pintarlos uno a uno (altamente ineficiente...).
Ya nos dirás qué tal :)
LEAJIM_454
30/04/15, 23:12:14
Gracias mocelet, opté por la primera opcion y encontre una libreria, todo va bien a excepcion de el ontouchlistener por que mi bitmap es de 1024x1024 pero el imageview apenas de 300x200 y cuando pulso envia coordenadas erroneas al bitmap y no sé como arreglarlo, gracias por toda la ayuda, te dejo el codigo aqui:
package com.example.asd;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.graphics.drawable.BitmapDrawable;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ImageView;
import android.widget.Toast;
import com.threekkapps.library.bitmap.JniBitmap;
public class MainActivity extends ActionBarActivity implements OnClickListener{
private int[] values;
private int x,y;
private Bitmap bm;
private BitmapDrawable ob;
private ImageView IV;
override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
values = new int[2];
IV = (ImageView)findViewById(R.id.IV);
// bm = BitmapFactory.decodeResource(getResources(), R.drawable.forme);
BitmapDrawable BMD = (BitmapDrawable)IV.getDrawable();
bm = BMD.getBitmap();
ob = new BitmapDrawable(getResources(), bm);
IV.setOnClickListener(this);
IV.setOnTouchListener(new View.OnTouchListener() {
override
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
x=(int) event.getX();
y=(int) event.getY();
return false;
}
});
}
override
public void onClick(View v) {
v.getLocationOnScreen(values);
switch (v.getId()) {
case R.id.IV:
BitmapDrawable BMD = (BitmapDrawable)IV.getDrawable();
bm = BMD.getBitmap();
ob = new BitmapDrawable(getResources(), bm);
JniBitmap.floodFill(bm,x,y,Color.GREEN,0);
IV.setBackgroundDrawable(ob);
Toast.makeText(this, x+" "+y, Toast.LENGTH_SHORT).show();
break;
default:
break;
}
}
override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
mocelet
30/04/15, 23:40:04
Tienes que calcular el factor de escalado y transformar las coordenadas. Como siempre, en stackoverflow alguien lo ha escrito... http://stackoverflow.com/questions/4933612/how-to-convert-coordinates-of-the-image-view-to-the-coordinates-of-the-bitmap
LEAJIM_454
07/05/15, 21:57:03
Tienes que calcular el factor de escalado y transformar las coordenadas. Como siempre, en stackoverflow alguien lo ha escrito... http://stackoverflow.com/questions/4...-of-the-bitmap
Gracias, todos estos dias intentando hacerlo y nada, probé lo que me dijiste y sigue siendo el mismo resultado se pintan las areas incorrectas si tiene algo de tiempo aqui le dejo el codigo:
package com.example.asd;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.Rect;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ImageView;
import android.widget.Toast;
import com.threekkapps.library.bitmap.JniBitmap;
public class MainActivity extends ActionBarActivity implements OnClickListener{
private int[] values;
private int x,y;
private Bitmap bm;
private BitmapDrawable ob;
private ImageView IV;
private int originalImageOffsetX, originalImageOffsetY;
override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
values = new int[2];
IV = (ImageView)findViewById(R.id.IV);
// bm = BitmapFactory.decodeResource(getResources(), R.drawable.forme);
BitmapDrawable BMD = (BitmapDrawable)
IV.getDrawable();
bm = BMD.getBitmap();
ob = new BitmapDrawable(getResources(), bm);
IV.setOnClickListener(this);
IV.setOnTouchListener(new View.OnTouchListener() {
override
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
x=(int) event.getX();
y=(int) event.getY();
///////////////////////////////////////////////////////
ImageView imageView = (ImageView)findViewById(R.id.IV);
Drawable drawable = imageView.getDrawable();
Rect imageBounds = drawable.getBounds();
//original height and width of the bitmap
int intrinsicHeight = drawable.getIntrinsicHeight();
int intrinsicWidth = drawable.getIntrinsicWidth();
//height and width of the visible (scaled) image
int scaledHeight = imageBounds.height();
int scaledWidth = imageBounds.width();
//Find the ratio of the original image to the scaled image
//Should normally be equal unless a disproportionate scaling
//(e.g. fitXY) is used.
float heightRatio = intrinsicHeight / scaledHeight;
float widthRatio = intrinsicWidth / scaledWidth;
//do whatever magic to get your touch point
//MotionEvent event;
//get the distance from the left and top of the image bounds
int scaledImageOffsetX = (int) (event.getX() - imageBounds.left);
int scaledImageOffsetY = (int) (event.getY() - imageBounds.top);
//scale these distances according to the ratio of your scaling
//For example, if the original image is 1.5x the size of the scaled
//image, and your offset is (10, 20), your original image offset
//values should be (15, 30).
originalImageOffsetX = (int) (scaledImageOffsetX * widthRatio);
originalImageOffsetY = (int) (scaledImageOffsetY * heightRatio);
Toast.makeText(getApplicationContext(), originalImageOffsetX+" "+originalImageOffsetY+" "+heightRatio+" "+widthRatio, Toast.LENGTH_SHORT).show();
///////////////////////////////////////////////////////
return false;
}
});
}
override
public void onClick(View v) {
v.getLocationOnScreen(values);
switch (v.getId()) {
case R.id.IV:
BitmapDrawable BMD = (BitmapDrawable)IV.getDrawable();
bm = BMD.getBitmap();
ob = new BitmapDrawable(getResources(), bm);
JniBitmap.floodFill(bm,originalImageOffsetX,origin alImageOffsetY,Color.GREEN,0);
IV.setBackgroundDrawable(ob);
Toast.makeText(this, x+" "+y, Toast.LENGTH_SHORT).show();
break;
default:
break;
}
}
override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
mocelet
07/05/15, 22:27:47
Hay dos aspectos que tienes que probar por separado:
1 - ¿Falla el cálculo del punto? (ya que tienes un toast, puedes mirar si los valores son correctos)
2 - Si especificas el punto "a mano", ¿se pinta bien o tampoco? (en ese caso el problema no es del cálculo sino del pintado)
LEAJIM_454
07/05/15, 23:39:09
Es el calculo el que falla no el pintado, el pintado va de maravilla si las coordenadas las pongo de manera fija y no dinamica como extraer los puntos, no se como hacer para que calcule de manera correcta ¿Qué es lo que estoy haciendo mal?, gracias de nuevo Mocelet.
vBulletin® v3.8.1, Copyright ©2000-2025, Jelsoft Enterprises Ltd.