Lesson 156. Drawing. AvoidXfermode

Lesson 156. Drawing. AvoidXfermode


In this lesson:

– we use AvoidXfermode

Another lesson about working with color. When you overlay one image to another, we can specify a specific color and overlay mode. And accordingly, the overlay will either occur only on pixels of the specified color (TARGET mode), or only on all other pixels (AVOID mode). AvoidXfermode is used for this purpose. Although deprecated, but interesting enough, so let’s talk about it.

Let’s make an example in which we draw a red rectangle over the blue ones.

Let’s create a project:

Project name: P1561_AvoidXfermode
Build Target: Android 4.4
Application name: AvoidXfermode
Package name: ru.startandroid.develop.p1561avoidxfermode
Create Activity: MainActivity

MainActivity.java:

package ru.startandroid.develop.p1561avoidxfermode;

import android.app.Activity;
import android.content.Context;
import android.graphics.AvoidXfermode;
import android.graphics.AvoidXfermode.Mode;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.os.Bundle;
import android.view.View;

public class MainActivity extends Activity {

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(new DrawView(this));
  }

  class DrawView extends View {

    Paint paint;

    Rect rect;

    Bitmap bitmap;
    Mode mode = Mode.AVOID;

    public DrawView(Context context) {
      super(context);
      paint = new Paint(Paint.ANTI_ALIAS_FLAG);
      rect = new Rect(0, 0, 50, 100);
      createBitmap();
    }

    @Override
    protected void onDraw(Canvas canvas) {
      canvas.drawARGB(80, 102, 204, 255);
      canvas.drawBitmap(bitmap, 0, 0, paint);
    }

    void createBitmap() {
      // создание bitmap
      bitmap = Bitmap.createBitmap(1100, 700, Bitmap.Config.ARGB_8888);
      Canvas bitmapCanvas = new Canvas(bitmap);

      // создание кисти для использования AvoidXfermode
      Paint redPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
      redPaint.setStyle(Paint.Style.FILL_AND_STROKE);
      redPaint.setColor(Color.RED);

      // рисование прямоугольников
      drawBitmap(bitmapCanvas, redPaint);

      // настройка AvoidXfermode для кисти
      redPaint.setXfermode(new AvoidXfermode(Color.BLUE, 0, mode));
      // рисование прямоугольников
      drawBitmap(bitmapCanvas, redPaint);

      redPaint.setXfermode(new AvoidXfermode(Color.BLUE, 127, mode));
      drawBitmap(bitmapCanvas, redPaint);

      redPaint.setXfermode(new AvoidXfermode(Color.BLUE, 255, mode));
      drawBitmap(bitmapCanvas, redPaint);
    }

    void drawBitmap(Canvas bitmapCanvas, Paint redPaint) {
      Paint bitmapPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
      bitmapPaint.setStyle(Paint.Style.FILL_AND_STROKE);

      // рисование синих прямоугольников
      bitmapCanvas.save();
      bitmapCanvas.translate(25, 25);
      for (int i = 0; i < 20; i++) {
        bitmapPaint.setColor(Color.rgb(i * 10, i * 10, 255));
        bitmapCanvas.drawRect(rect, bitmapPaint);
        bitmapCanvas.translate(50, 0);
      }
      bitmapCanvas.restore();

      // рисование красного прямоугольника кистью с AvoidXfermode
      bitmapCanvas.drawRect(10, 75, 1035, 150, redPaint);

      bitmapCanvas.translate(0, 150);
    }

  }

}

In the constructor DrawView call the createBitmap method to create a bitmap. I create it in ARGB_8888 format and all the drawing and overlaying of rectangles will be done on it, and then I'll just draw it on the outline. This is necessary because if you draw rectangles directly on the edge, the AvoidXfermode mechanism does not work. I suspect this is due to a lack of "bit" of the standard canvas.

In the method createBitmap create a bitmap, create a red brush and use it 4 times in the drawBitmap method to draw rectangles. First time without AvoidXfermode, then three times using AvoidXfermode.

When creating AvoidXfermode, you must specify three parameters:

- the color that will be taken into account when applying

- degree of tolerance (0-255)

- overlay mode (AVOID, TARGET)

When we run the example, we will dwell on these parameters in more detail.

In the method drawBitmap we display many rectangles with different blue gradations, and then draw red over them with the brush (the first one without AvoidXfermode, and the next three times with it).

Let's start with an example.

We see 4 overlays of a red rectangle on blue, but all these overlays are slightly different. Let's see why.

1)

Without using AvoidXfermode. That is all as it should be, the red lay over the blue.

2)

For the red brush we used AvoidXfermode (Color.BLUE, 0, Mode.AVOID)

Parameters used: blue, 0, AVOID mode. This means that the overlay will avoid (AVOID parameter) blue (Color.BLUE parameter). And not only blue itself, but all the colors associated with it (parameter 0).

This is visible in the image. Red avoids blue when applied. That is, it simply does not lie on top of the blue.

3)

For the red brush we used AvoidXfermode (Color.BLUE, 127, Mode.AVOID)

Parameters used: blue, 127, AVOID mode. This means that the overlay will avoid (AVOID parameter) blue (Color.BLUE parameter). Not only blue itself, but also the closest ones to it (parameter 127).

This is visible in the image. Red when applied avoids blue and close to blue. That is, if 0 meant that all shades of blue would work, then the tolerance value of 127 already gives some degree of freedom and the very distant shades of blue already fully allow the imposition of red.

4)

For the red brush we used AvoidXfermode (Color.BLUE, 255, Mode.AVOID)

Parameters used: blue, 255, AVOID mode. This means that the overlay will avoid (AVOID parameter) blue (Color.BLUE parameter). And only blue (parameter 255).

This is visible in the image. Red when avoiding only avoids the blue, and in other gradations, it appears.

change the mode

Mode mode = Mode.TARGET;

Now there will be a reverse effect. Red when applied will only be displayed where there is blue.

run the program

We analyze 4 results

1)

Everything is standard because they used a brush without AvoidXfermode

2)

For the red brush we used AvoidXfermode (Color.BLUE, 0, Mode.TARGET)

Parameters used: blue, 0, TARGET mode. This means that the overlay will work (TARGET parameter) only in blue (Color.BLUE parameter). And only in pure blue (parameter 0).

This is visible in the image. Red when applied lay only in pure blue. And beyond the blue rectangle, the overlay did not work.

3)

For the red brush we used AvoidXfermode (Color.BLUE, 127, Mode.TARGET)

Parameters used: blue, 127, TARGET mode. This means that the overlay will work (TARGET parameter) only in blue (Color.BLUE parameter). Not only in pure blue, but also in colors close to it (parameter 127).

This is visible in the image. Red when applied lay on the blue color and on its nearest shades. Outside, the red did not lie down.

4)

For the red brush we used AvoidXfermode (Color.BLUE, 255, Mode.TARGET)

Parameters used: blue, 255, TARGET mode. This means that the overlay will work (TARGET parameter) only in blue (Color.BLUE parameter). Not only in pure blue, but even in remotely similar colors (parameter 255).

This is visible in the image. Red when applied lay on the blue color and all its shades. Outside, the red did not lie down.

In the next lesson:

- we read Bitmap
- output to the outline
- we receive information




Discuss in the forum [0 replies]

Leave a Comment