PorterDuffXfermode图形混合

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u010870167/article/details/80920225

Xfermode

xfermode:用于计算机中图形编程的图形混合效果(ARGB即透明和色值的混合叠加)

android中我们经常使用Paint类实现自定义的图片和文本来实现一些效果,例如:
1. 加载动画
这里写图片描述
该功能使用Mode.SRC_IN:它的意思时两层位图重叠,在显示的时候,显示的是他们相交的部分,就是重叠在一起的部分,如果没有重叠的就不显示了,(这个不显示我觉得是色值混合的时候变成了透明,这部分暂时还不清楚,后期看看SkXfermode.h后在写这部分,现在先知其然就行了,丢脸啊………….)

2. 还有画板功能中的橡皮擦功能:使用Mode.CLEAR,这个功能是以前用一个别人写的画笔时候发现别人是这么写的.

3. 还有圆形图片和带弧度的矩形图片,以及一些其他形状的图片,当然了这写功能除了使用Paint.setXfermode()实现外,还可以以其他多种方式实现,例如使用paint.setShader(BitmapShader)这个函数和BitmapShader相配合可以实现,等…

自定义色值的RatingBar…………其他效果就不举例了,




下面先介绍一下该类的具体实现,完了之后在介绍上面这些效果的实现.

PorterDuffXfermode

Xfermode的实现类

PorterDuff.Mode

图形混合效果对外提供的具体实现类,其实也没什么东西,具体算法实现都在SkXfermode.h中,该类中只包含18中混合效果,用枚举表示.

该类中的一些名词介绍:
S(source):源源
D(destination)目标图
Sa(source_alhpa)源图透明度
Da(destination_alhpa)目标图透明度
Sc(source_color)源图色值
Dc(destination_color)目标图色值



混合模式:

  • CLEAR /* [0, 0] /
    [0,0]表示输入色值和透明度都是0.就是完全透明显示
  • SRC /* [Sa, Sc] /
    显示S
  • DST /* [Da, Dc] /
    显示D
  • SRC_OVER /* [Sa + (1 - Sa)*Da, Rc = Sc + (1 - Sa)*Dc] /
    在D上层绘制S
  • DST_OVER /* [Sa + (1 - Sa)*Da, Rc = Dc + (1 - Da)*Sc] /
    在S上层绘制D
  • SRC_IN /* [Sa Da, Sc * Da] */
    上面好像介绍过,绘制相交部分的S
  • DST_IN /* [Sa Da, Sa * Dc] */
    绘制相交部分的D
  • SRC_OUT /* [Sa (1 - Da), Sc * (1 - Da)] */
    绘制不相交部分的S
  • DST_OUT /* [Da (1 - Sa), Dc * (1 - Sa)] */
    绘制不相交部分的D
  • SRC_ATOP /* [Da, Sc Da + (1 - Sa) * Dc] */
    S和D相交处绘制S,不相交的地方绘制D
  • DST_ATOP /* [Sa, Sa Dc + Sc * (1 - Da)] */
    S和D相交处绘制D,不相交的地方绘制S
  • XOR /* [Sa + Da - 2 Sa * Da, Sc * (1 - Da) + (1 - Sa) * Dc] */
    绘制S和D,相交的地方受到对应alpha和颜色值影响,如果都完全不透明则相交处不绘制完全透明,看效果图就知道了,相交的地方如果透明,则显示叠加效果.(这个下面的效果图是完全不透明的,所以这个效果没有显示出来,可以自己写demo测试)
  • DARKEN /* [Sa + Da - Sa*Da, Sc(1 - Da) + Dc*(1 - Sa) + min(Sc, Dc)] */
    看这个词就知道了,这个应该是变暗了(相交的部分),全部输出
  • LIGHTEN /* [Sa + Da - Sa*Da, Sc(1 - Da) + Dc*(1 - Sa) + max(Sc, Dc)] */
    与上面相反,变量了(相交的部分),全部输出
  • MULTIPLY /* [Sa Da, Sc * Dc] */
    取D和S相交的部分叠加后颜色(色值变暗)
  • SCREEN /* [Sa + Da - Sa Da, Sc + Dc - Sc * Dc] */
    [!取两图层全部区域,交集部分变为白色]
  • ADD /* Saturate(S + D) /
    alpha_{out} = max(0, min(alpha_{src} + alpha_{dst}, 1))
    C_{out} = max(0, min(C_{src} + C_{dst}, 1))
    根据这个公式就知道,饱和度叠加.
  • OVERLAY
    全部显示,覆盖效果,就是上层覆盖下层

注意:上面相交的部分,如果有透明度,将类似我们一般的两个有透明效果的图层合并后的效果

我们可以在SDK文件夹看每个混合模式的效果图,路径:{@docRoot}reference/android/images/graphics/composite_,下划线后是混合模式的名称
但是……我在自己的sdk文件夹下没有找到,可能是我没有更新全吧,你们可以瞅瞅,看看有没有,如果没有的话没事,自己开个模拟器,打开APIDemo这个App,在主页面的graphics下找到与之对应的item打开就行了….就这么简单,还有更简单的看看下边:
这里写图片描述
呦,这是哪来的,百度的呗,拿来使使~

示例:

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);

注意:在写示例实现以上效果的时候先画目标图,在画源图


该说上面介绍的示例了
(1) 那个加载动画主要是sin或cos函数曲线(三阶贝塞尔曲线)和一个圆位图叠加的效果:

mCanvas.drawCircle(mWidth / 2, mHeight / 2, mWidth / 2, mPaint1);
mPaint.setXfermode(PorterDuff.Mode.SRC_IN);
mCanvas.drawPath(mPath, mPaint2);

注意,上下两层图层要有透明度,因为,我们一般的加载动画都是透明的.这样可以看到dialog下次的view.

(2) 这个我也没做过,后期写写这个功能,现在说说它的主要代码:

// 将画图层放在上层,下层为白色的位图,在上层进行绘制功能,
paint.mPaint.setXfermode(PorterDuff.Mode.DST_IN);
// paint为橡皮擦画笔
paint.setAlpha(0);
mCanvas.drawPath(mPath, paint);
// mPath为橡皮擦路径

这样就实现了橡皮擦功能,实际上上层画了一层透明线条,但是由于使用了xfermode图形混合模式,在线条地方显示的是下层的白色图层.

(3) 也是这样的原理,画一个圆形位图canvas.drawCircle()(带弧度矩形位图canvas.drawRoundRect()),和图片叠在一起,使用混合模式就可以显示出我们想要的图形了,其他形状可以使用canvas.drawPath()来实现.




好了,今天就到这后,混合算法后期研究好了再写啊!!!!!!!!!!!!!!

猜你喜欢

转载自blog.csdn.net/u010870167/article/details/80920225