android - online - painting app
¿Cómo configurar el color combinado para el área superpuesta de dos objetos de color diferentes? (6)
Estoy creando diferentes vistas personalizadas con dos colores diferentes. De acuerdo con las características de mi aplicación, el usuario arrastrará esos objetos en la pantalla, cuando los objetos se superpongan. Quiero diferenciar el área superpuesta, cómo configurar el color combinado para el Área superpuesta. Mira la imagen de abajo. Aquí estoy usando un lienzo para crear esas vistas personalizadas. Dos círculos son dos vistas diferentes.
EDITAR: Si uso opacidad 128, puedo ver el color de fondo, pero quiero la combinación de colores de colores de objetos superpuestos.
Creo que puedes estar buscando dibujar en un modo de mezcla. Android te permitirá hacer esto, solo mira este primer enlace. Operaciones compuestas en Android Canvas
Aquí están todas las opciones de composición http://developer.android.com/reference/android/graphics/PorterDuffXfermode.html
Y sus explicaciones de Mozilla https://developer.mozilla.org/en/Canvas_tutorial/Compositing
He creado una Actividad de muestra con dos vistas DemoDrawShapeActivity donde en view2 uso canvas.clipPath y canvas.translate
para trabajar esto establezco la versión 4 de SDK mínimo
protected void onDraw(Canvas canvas) {
Paint paint = new Paint();
paint.setColor(Color.RED);
path2.addCircle(getWidth()/2, getHeight()/2, getWidth()/2, Direction.CCW);
canvas.drawPath(path2, paint);
canvas.clipPath(path2);
canvas.save();
canvas.translate(-getTranslationX()+view1.getTranslationX(), -getTranslationY()+view1.getTranslationY());
paint.setColor(Color.BLUE|Color.RED);
canvas.drawPath(path1, paint);
canvas.restore();
}
puede editar paint.setColor (Color.BLUE | Color.RED); Para obtener el color necesario de acuerdo a su lógica.
Estoy usando setTranslationX setTranslationY para mover las vistas.
public boolean onTouchEvent(MotionEvent event) {
switch(event.getActionMasked()){
case MotionEvent.ACTION_UP:
touched[0]=touched[1]=false;
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_MOVE:
if(touched[1]){
view2.setTranslationX(event.getX()-view2.getWidth()/2);
view2.setTranslationY(event.getY()-view2.getHeight()/2);
}else if(touched[0]){
view1.setTranslationX(event.getX()-view1.getWidth()/2);
view1.setTranslationY(event.getY()-view1.getHeight()/2);
view2.invalidate();
}
}
return true;
}
He hecho otro example para 6 objetos.
Puntos clave:
El método onDraw no se anulará para las Vistas de objetos, y el fondo también se establecerá en transparencia
setBackgroundColor (Color.TRANSPARENT);
Pero, se cambiará el nombre del método onDraw, ya que se llamará a onDrawEx desde la vista de superposición.
public void onDrawEx (Canvas canvas) {
La vista de superposición pasará un lienzo personalizado para dibujar. Antes de pasar a la vista de objeto, será necesario traducir.
mOverlayView = new View(this){ @Override protected void onDraw(Canvas canvas) { Bitmap bitmap = Bitmap.createBitmap(getWidth(), getHeight(), Config.ARGB_8888); Canvas canvasBitmap = new Canvas(bitmap); ViewGroup viewGroup = (ViewGroup)getParent(); for(int i = 0 ; i < viewGroup.getChildCount()-1;i++){ ObjectView objectView = (ObjectView) viewGroup.getChildAt(i); canvasBitmap.save(); canvasBitmap.translate(objectView.getTranslationX(), objectView.getTranslationY()); objectView.onDrawEx(canvasBitmap); canvasBitmap.restore(); } canvas.drawBitmap(bitmap, 0, 0, new Paint()); } };
use el mPaint.setXfermode (nuevo PorterDuffXfermode (Mode.ADD)); para añadir colores. Pero todos los objetos deben usar colores como 0xFF000030,0xFF0000C0,0xFF003000,0xFF00C000,0xFF300000,0xC00000, entonces solo para todos los posibles solapamientos podemos obtener diferentes colores. Esto depende de tu número máximo de objetos.
int k = 0 ; for(int i = 0 ; i < 2;i++,k++){ int color = 0xFF000000|(0x000030<<i*2); frameLayout.addView(new ObjectView(this,color,k*50,k*50,k), new FrameLayout.LayoutParams(50, 50)); } for(int i = 0 ; i < 2;i++,k++){ int color = 0xFF000000|(0x003000<<i*2); frameLayout.addView(new ObjectView(this,color,k*50,k*50,k), new FrameLayout.LayoutParams(50, 50)); } for(int i = 0 ; i < 2;i++,k++){ int color = 0xFF000000|(0x300000<<i*2); frameLayout.addView(new ObjectView(this,color,k*50,k*50,k), new FrameLayout.LayoutParams(50, 50)); }
Aquí me he modified para soportar la versión 8.
utilizar
mPaint.setXfermode(new PixelXorXfermode(0x00000000));
para
mPaint.setXfermode(new PorterDuffXfermode(Mode.ADD));
Utilicé parámetros de diseño para la traducción.
La mezcla de colores que está buscando a veces se llama Mezcla de colores intuitiva , o el Sistema de colores RYB :
RYB :
Una cita de this artículo de Nathan Gossett y Baoquan Chen sobre los algoritmos para la mezcla de color intuitiva resume cómo funciona el sistema de color intuitivo:
"En este modelo, rojo, amarillo y azul se utilizan como colores primarios puros. Rojo y amarillo se mezclan para formar naranja, amarillo y azul para formar verde, y azul y rojo se mezclan para formar púrpura [...]. Estos son los colores que un espectador inexperto esperaría obtener usando pintura para niños [...]. Además, muchas personas no piensan en el blanco como la mezcla de todos los colores, sino en la ausencia de color (un lienzo en blanco). el supuesto sería que mezclar muchos colores juntos daría como resultado un color marrón oscuro turbio ".
RYB no se implementa en los modos de mezcla de Android y no se puede simular realmente mezclando modos de mezcla alfa / diferentes.
La mayoría de las aplicaciones de gráficos de computadora hacen uso de los espacios de color RGB o CMYK :
CMYK :
CMY se basa en color sustractivo. La mezcla de color sustractiva significa que, comenzando con el blanco, a medida que agregamos color, el resultado se vuelve más oscuro. CMYK se utiliza para mezclar colores en imágenes destinadas a la impresión en, por ejemplo, Photoshop e Illustrator.
RGB :
RGB se basa en el color aditivo. Los colores en una pantalla de computadora se crean con luz usando el método de color aditivo. La mezcla de colores aditivos comienza con el negro y, a medida que se agrega más color, el resultado se vuelve más claro y termina en blanco.
Este sitio analiza CMYK y RGB con más detalle.
Ni en RGB ni en CMYK, la mezcla de azul y amarillo produce mezclas de color intuitivas de color verde o, en general, intuitivas. Implementar un sistema de color RYB en Android sería bastante complicado. El documento de Nathan Gossett y Baoquan Chen citado anteriormente propone una solución con un algoritmo implementado en C al final del documento. Este algoritmo podría implementarse en una mezcla personalizada en Android. Drawable.setColorFilter()
usa PorterDuffColorfilter
que extiende ColorFilter
. La subclasificación de ColorFilter
como se explica en this pregunta SO, debería realizarse en código nativo utilizando el NDK.
Solución de mezcla de colores CMYK
En caso de que esté interesado en utilizar una mezcla de colores CMYK como solución alternativa, he incluido un ejemplo básico de cómo se puede hacer a continuación. En este ejemplo, un círculo de color cian y un círculo de color amarillo se mezclarán para producir una intersección verde.
A partir de estos archivos de imagen .png creados en Adobe Illustrator:
con valor de color hexadecimal 0x00ffff (cian) y 0xffff00 (amarillo).
Agréguelos a su carpeta dibujable con los nombres cyancircle.png y yellowcircle.png.
Configure su diseño main.xml de la siguiente manera:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
android:background="#ffffff"
android:padding="30dp">
<ImageView
android:id="@+id/bluecircle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/cyancircle">
</ImageView>
<ImageView
android:id="@+id/yellowcircle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/yellowcircle"
android:layout_marginTop="30dp">
</ImageView>
</RelativeLayout>
Crea tu actividad:
import android.app.Activity;
import android.graphics.PorterDuff;
import android.os.Bundle;
import android.widget.ImageView;
public class PorterDuffTestActivity extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
ImageView yellowCircle = (ImageView)findViewById(R.id.yellowcircle);
yellowCircle.getDrawable().setColorFilter(0x88ffff00, PorterDuff.Mode.MULTIPLY);
}
}
Salida:
La limitación de este método es que el valor alfa de la forma superior se debe establecer en 50% (el "88" en "0x88ffff00"). Para el amarillo, esto funciona razonablemente bien, pero para otros colores, el efecto alfa puede no ser aceptable (el color puede parecer otro color, por ejemplo, el rojo se vuelve rosa con valores alfa bajos sobre fondo blanco). El modo de fusión que finalmente sea aceptable para usted depende del conjunto de colores que vaya a usar y tomará un poco de experimentación. También tenga en cuenta que el color de fondo puede afectar los colores de los círculos en el modo de fusión. En este ejemplo, el fondo se establece en blanco.
La solución más sencilla que puedo pensar sería utilizar simplemente el canal alfa estableciendo cada uno de opacidad de 0,5, ya sea en código o en xml. Luego, los colores deben fundirse entre sí cuando se superponen. Sin embargo, esto significa que los colores en las secciones que no se superponen se desvanecerán un poco, y dependiendo del fondo que tenga detrás de las formas, puede que no se vea bien si son transparentes.
Puedes tomar la ayuda de esto ...
http://www.learnopengles.com/android-lesson-five-an-introduction-to-blending/
y
www.pushing-pixels.org/category/android/page/6