Paint API - Detailed explanation of Xfermode and PorterDuff (2)
Introduction to this section:
In the previous section, we learned about the two deceased (outdated) sons of Xfermode: AvoidXfermode, PixelXorXfermode, Although it is somewhat useful, it has been eliminated after all. In this section, we will learn about the third son of Xfermode who is still alive: PorterDuffXfermode;
Let’s first pay attention to the official API document: PorterDuffXfermode ! The document contains very little content. We can see its construction method:
has only one parameter: PorterDuff.Mode mode, and Android provides us with 16 image mixing modes. , it can be simpler It is understood that two layers can be combined into different results and displayed according to different modes! The results of the 16 mixing modes are as follows:
There are two layers here: the picture drawn first is target picture (DST), and the picture drawn later is Source image (SRC)!
Of course, in the document we found that the available modes are not 16, but 18. Two new modes, ADD and OVERLAY, have been added!
Well, it’s useless to say too much. Code is the most practical. In this section, we write the code to verify these 18 modes!
PS: The name PorterDuff is actually a combination of two names: Tomas Proter and Tom Duff, who were the first to The god-level person who first proposed the concept of graphic mixing on SIGGRAPH. If you are interested, please Baidu~
Write an example to verify the above picture:
Okay, let’s write an example to verify the above picture, and compare and analyze the results by modifying different modes!
Code implementation:
Step 1: Let’s first write a tool class to get the screen width and height! ScreenUtil.java:
/** * Created by Jay on 2015/10/23 0023. */ public class ScreenUtil { /** * 获取屏幕宽高,sdk17后不建议采用 * * @param context */ public static int[] getScreenHW(Context context) { WindowManager manager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); Display display = manager.getDefaultDisplay(); int width = display.getWidth(); int height = display.getHeight(); int[] HW = new int[] { width, height }; return HW; } /** * 获取屏幕宽高,建议采用 * * @param context */ public static int[] getScreenHW2(Context context) { WindowManager manager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); DisplayMetrics dm = new DisplayMetrics(); manager.getDefaultDisplay().getMetrics(dm); int width = dm.widthPixels; int height = dm.heightPixels; int[] HW = new int[] { width, height }; return HW; } /** * 获取屏幕的宽度 * * @param context * @return */ public static int getScreenW(Context context) { return getScreenHW2(context)[0]; } /** * 获取屏幕的高度 * * @param context * @return */ public static int getScreenH(Context context) { return getScreenHW2(context)[1]; } }
Step 2: Write our custom View class and experiment here! Calculate their positions, then set the lower layer (fixed writing method), then set the lower brush setXfermode, and then It's just drawn on the canvas. What you don't understand may be the calculation of the drawing position. In fact, it's not the case. How do you decide the position? It will be all right! Then let’s take a look at the results one by one. You only need to modify the value of PD_MODE
to set it to a different mode!Operation renderings
:1) PorterDuff.Mode.ADD:
Saturation Overlay
2) PorterDuff.Mode.CLEAR:
The drawn will not Submit it to the canvas, and the result... I don’t know why, normally there is nothing..
3) PorterDuff.Mode.DARKEN:
Take two layers All areas, the intersection part is darker in color
4) PorterDuff.Mode.DST:
Only retains the alpha and color of the target image, so only the target image is drawn
5) PorterDuff.Mode.DST_ATOP:
The target image is drawn where the source image and the target image intersect, and the source image is drawn where they do not intersect.
6) PorterDuff.Mode.DST_IN:
The target image is drawn where the two intersect, and the drawing effect will be affected by the transparency of the original image
7) PorterDuff.Mode.DST_OUT:
Draw the target graph at disjoint places
8) PorterDuff.Mode.DST_OVER:
The target graph is drawn above
9) PorterDuff.Mode. LIGHTEN:
Take all areas of the two layers and light up the intersection color
10) PorterDuff.Mode.MULTIPLY:
Take the two layers The color of the intersection after overlay
11) PorterDuff.Mode.OVERLAY:
Overlay
12) PorterDuff.Mode.SCREEN:
Take all areas of the two layers, and the intersection part becomes transparent
13) PorterDuff.Mode.SRC:
Only retain the alpha and color of the source image, so draw it Only source image
14) PorterDuff.Mode.SRC_ATOP:
The source image is drawn where the source image and the target image intersect, and the target image is drawn where they do not intersect
15) PorterDuff.Mode. SRC_IN:
Draw the source image where the two intersect
16) PorterDuff.Mode.SRC_OUT:
Draw the source image where they do not intersect
17) PorterDuff.Mode.SRC_OVER:
Draw the source image above
18) PorterDuff.Mode.XOR:
Draw the source and target images as they are in disjoint places
Download the sample code for this section:
Summary of this section:
Well, in this section I wrote a simple View to verify the different effects of these 18 different PorterDuff.Mode. Hehe, it’s quite time-consuming, but it will definitely seem much clearer to readers, right~ Of course, these are just some preliminary insights!
PorterDuffXfermodePorterDuff.Mode is very important for our custom controls! In this section we have a preliminary understanding. In the next section we will pick a few examples to practice!
If you want to see a more detailed introduction about PorterDuff.Mode, please see: Android Paint's setXfermode PorterDuffXfermode explanation, a good article written by others! Well, that’s it. I’ll have a physical exam tomorrow morning. That’s all I’ll write today~