前言
Xfermode国外有大神称之为过渡模式, 这种翻译比较贴切但恐怕不易理解,大家也可以直接称之为图像混合模式
一、图像混合模式
在之前的Paint的使用当中我们提到了高级渲染和滤镜,那么今天我们来学习最后一个内容点Xfermode,我们能通过使用Xfermode能够完成图像组合的效果
1.XFermode
在使用Paint的时候,我们能通过使用Xfermode能够完成图像组合的效果将绘制的图形的像素和Canvas上对应位置的像素按照一定的规则进行混合,形成新的像素,再更新到Canvas中形成最终的图形,那图具体效果见下图
看到上述图形,其实这个时候我们能够很明显的知道我们的XFermode其实实际上就是在使用图形之间的相互组合以达到自己的想要的目的, 他提供了16种组合模式
- ADD: 饱和相加,对图像饱和度进行相加,不常用
- CLEAR: 清除图像
- DARKEN: 变暗,较深的颜色覆盖较浅的颜色,若两者深浅程度相同则混合
- DST: 只显示目标图像
- DST_ATOP: 在源图像和目标图像相交的地方绘制【目标图像】,在不相交的地方绘制【源图像】,相交处的效果受到源图像和目标图像alpha的影响
- DST_IN: 只在源图像和目标图像相交的地方绘制【目标图像】,绘制效果受到源图像对应地方透明度影响
- DST_OUT: 只在源图像和目标图像不相交的地方绘制【目标图像】,在相交的地方根据源图像的alpha进行过滤,源图像完全不透明则完全过滤,完全透明则不过滤
- DST_OVER: 将目标图像放在源图像上方
- LIGHTEN: 变亮,与DARKEN相反,DARKEN和LIGHTEN生成的图像结果与Android对颜色值深浅的定义有关
- MULTIPLY: 正片叠底,源图像素颜色值乘以目标图像素颜色值除以255得到混合后图像像素颜色值
- OVERLAY: 叠加
- SCREEN: 滤色,色调均和,保留两个图层中较白的部分,较暗的部分被遮盖
- SRC: 只显示源图像
- SRC_ATOP: 在源图像和目标图像相交的地方绘制【源图像】,在不相交的地方绘制【目标图像】,相交处的效果受到源图像和目标图像alpha的影响
- SRC_IN: 只在源图像和目标图像相交的地方绘制【源图像】
- SRC_OUT: 只在源图像和目标图像不相交的地方绘制【源图像】,相交的地方根据目标图像的对应地方的alpha进行过滤,目标图像完全不透明则完全过滤,完全透明则不过滤
- SRC_OVER: 将源图像放在目标图像上方
- XOR: 在源图像和目标图像相交的地方之外绘制它们,在相交的地方受到对应alpha和色值影响,如果完全不透明则相交处完全不绘制
这个方法跟之前讲到的setColorFilter蛮相似的。 但是我们可以看到谷歌官方所提供的和我们自己写的还是有一些差异, 那么我们需要来了解到XFermode的本质到底是什么,上面开篇我们有提到过,XFermode是将绘制的图形的像素和Canvas上对应位置的像素按照一定的规则进行混合,那么我们需要知道他到底是怎么进行混合,如何进行计算的?
这个时候我门走到源码当中,查看API文档发现其果然有三个子类:AvoidXfermode
, PixelXorXfermode
和PorterDuffXfermode
这三个子类实现的功能要比setColorFilter的三个子类复杂得多。
由于AvoidXfermode
, PixelXorXfermode
都已经被标注为过时了,所以这次主要研究的是仍然在使用的PorterDuffXfermode
/**
* <p>Specialized implementation of {@link Paint}'s
* {@link Paint#setXfermode(Xfermode) transfer mode}. Refer to the
* documentation of the {@link PorterDuff.Mode} enum for more
* information on the available alpha compositing and blending modes.
*/
public class PorterDuffXfermode extends Xfermode {
/**
* Create an xfermode that uses the specified porter-duff mode.
*
* @param mode The porter-duff mode that is applied
*/
public PorterDuffXfermode(PorterDuff.Mode mode) {
porterDuffMode = mode.nativeInt;
}
}
那么在这里我们可以看到其实实际上这个类非常简单, 我门可以认为他就是一个常量类标注了16种模式, 而在这里真正的模式实在mode当中(下面粗略看一下就行)
public class PorterDuff {
/**
* {@usesMathJax}
*
* <h3>Porter-Duff</h3>
*
* <p>The name of the parent class is an homage to the work of Thomas Porter and
* Tom Duff, presented in their seminal 1984 paper titled "Compositing Digital Images".
* In this paper, the authors describe 12 compositing operators that govern how to
* compute the color resulting of the composition of a source (the graphics object
* to render) with a destination (the content of the render target).</p>
*
* <p>"Compositing Digital Images" was published in <em>Computer Graphics</em>
* Volume 18, Number 3 dated July 1984.</p>
*
* <p>Because the work of Porter and Duff focuses solely on the effects of the alpha
* channel of the source and destination, the 12 operators described in the original
* paper are called alpha compositing modes here.</p>
*
* <p>For convenience, this class also provides several blending modes, which similarly
* define the result of compositing a source and a destination but without being
* constrained to the alpha channel. These blending modes are not defined by Porter
* and Duff but have been included in this class for convenience purposes.</p>
*
* <h3>Diagrams</h3>
*
* <p>All the example diagrams presented below use the same source and destination
* images:</p>
*
* <table summary="Source and Destination" style="background-color: transparent;">
* <tr>
* <td style="border: none; text-align: center;">
* <img src="{@docRoot}reference/android/images/graphics/composite_SRC.png" />
* <figcaption>Source image</figcaption>
* </td>
* <td style="border: none; text-align: center;">
* <img src="{@docRoot}reference/android/images/graphics/composite_DST.png" />
* <figcaption>Destination image</figcaption>
* </td>
* </tr>
* </table>
*
* <p>The order of drawing operations used to generate each diagram is shown in the
* following code snippet:</p>
*
* <pre class="pretty print"
* Paint paint = new Paint();
* canvas.drawBitmap(destinationImage, 0, 0, paint);
*
* PorterDuff.Mode mode = // choose a mode
* paint.setXfermode(new PorterDuffXfermode(mode));
*
* canvas.drawBitmap(sourceImage, 0, 0, paint);
* </pre>
*
* <h3>Alpha compositing modes</h3>
*
* <table summary="Alpha compositing modes" style="background-color: transparent;">
* <tr>
* <td style="border: none; text-align: center;">
* <img src="{@docRoot}reference/android/images/graphics/composite_SRC.png" />
* <figcaption>{@link #SRC Source}</figcaption>
* </td>
* <td style="border: none; text-align: center;">
* <img src="{@docRoot}reference/android/images/graphics/composite_SRC_OVER.png" />
* <figcaption>{@link #SRC_OVER Source Over}</figcaption>
* </td>
* <td style="border: none; text-align: center;">
* <img src="{@docRoot}reference/android/images/graphics/composite_SRC_IN.png" />
* <figcaption>{@link #SRC_IN Source In}</figcaption>
* </td>
* <td style="border: none; text-align: center;">
* <img src="{@docRoot}reference/android/images/graphics/composite_SRC_ATOP.png" />
* <figcaption>{@link #SRC_ATOP Source Atop}</figcaption>
* </td>
* </tr>
* <tr>
* <td style="border: none; text-align: center;">
* <img src="{@docRoot}reference/android/images/graphics/composite_DST.png" />
* <figcaption>{@link #DST Destination}</figcaption>
* </td>
* <td style="border: none; text-align: center;">
* <img src="{@docRoot}reference/android/images/graphics/composite_DST_OVER.png" />
* <figcaption>{@link #DST_OVER Destination Over}</figcaption>
* </td>
* <td style="border: none; text-align: center;">
* <img src="{@docRoot}reference/android/images/graphics/composite_DST_IN.png" />
* <figcaption>{@link #DST_IN Destination In}</figcaption>
* </td>
* <td style="border: none; text-align: center;">
* <img src="{@docRoot}reference/android/images/graphics/composite_DST_ATOP.png" />
* <figcaption>{@link #DST_ATOP Destination Atop}</figcaption>
* </td>
* </tr>
* <tr>
* <td style="border: none; text-align: center;">
* <img src="{@docRoot}reference/android/images/graphics/composite_CLEAR.png" />
* <figcaption>{@link #CLEAR Clear}</figcaption>
* </td>
* <td style="border: none; text-align: center;">
* <img src="{@docRoot}reference/android/images/graphics/composite_SRC_OUT.png" />
* <figcaption>{