Android图形处理--PorterDuff.Mode那些事儿

PorterDuff.Mode及Xfermode详解 在android SDK Paint类中有一个很重要的方法setXfermode(源码如上),这个方法用于设置图像的过渡模式,所谓过渡是指图像的饱和度、颜色值等参数的计算结果的图像表现。在SDK中Xfermode有三个子类:AvoidXfermode, PixelXorXfermode和PorterDuffXfermode,前两个类在API 16被遗弃了,而且不是本文的主题内容,所以这里不作介 阅读详情

我们在绘制图形图像的时候经常会用到 PorterDuff.Mode,它对我们绘制图形有很大的帮助,如果我们对它不甚了解甚至根本不理解,那会是很麻烦的事情,我这篇博客就是来给大家介绍一下 PorterDuff.Mode。

1、基本介绍

在介绍 PorterDuff.Mode 之前,我们首先要了解一下 Xfermode。Xfermode 被许多人称为过渡模式,就是指图像的饱和度、颜色值等参数的计算结果的图像表现。Xfermode 是用来做图形渲染的,可以通过修改 Paint 的 Xfermode 来影响在 Canvas 已有的图像上面绘制新的颜色的方式 。

Xfermode 包含三个子类:AvoidXfermode、PixelXorXfermode 和 PorterDuffXfermode,前两个已经被弃用了,我们就不管它们了。

PorterDuffXfermode 是一个非常强大的转换模式,使用它,可以使用图像合成的 18条 Porter-Duff 规则的任意一条来控制 Paint 与已有的 Canvas 图像进行交互的方式。

看到这个名字大家都应该知道了,这肯定和我们要讲的 PorterDuff.Mode 有关,有什么关系就要说到 PorterDuff.Mode 的本质是什么,在 PorterDuff 里有个枚举变量 Mode,它有18个值,分别对应了一条图形混合的模式。

我们通过在 PorterDuffXfermode 里设置 PorterDuff.Mode,再把 PorterDuffXfermode 传给 Paint,就能实现很多我们想要的图形效果。

2、各种模式效果

PorterDuff.Mode 的效果相当惊人,但只有充分了解每种模式的作用,我们才能百战不怠。

public enum Mode {
    /** [0, 0] */
    CLEAR       (0),
    /** [Sa, Sc] */
    SRC         (1),
    /** [Da, Dc] */
    DST         (2),
    /** [Sa + (1 - Sa)*Da, Rc = Sc + (1 - Sa)*Dc] */
    SRC_OVER    (3),
    /** [Sa + (1 - Sa)*Da, Rc = Dc + (1 - Da)*Sc] */
    DST_OVER    (4),
    /** [Sa * Da, Sc * Da] */
    SRC_IN      (5),
    /** [Sa * Da, Sa * Dc] */
    DST_IN      (6),
    /** [Sa * (1 - Da), Sc * (1 - Da)] */
    SRC_OUT     (7),
    /** [Da * (1 - Sa), Dc * (1 - Sa)] */
    DST_OUT     (8),
    /** [Da, Sc * Da + (1 - Sa) * Dc] */
    SRC_ATOP    (9),
    /** [Sa, Sa * Dc + Sc * (1 - Da)] */
    DST_ATOP    (10),
    /** [Sa + Da - 2 * Sa * Da, Sc * (1 - Da) + (1 - Sa) * Dc] */
    XOR         (11),
    /** [Sa + Da - Sa*Da,
         Sc*(1 - Da) + Dc*(1 - Sa) + min(Sc, Dc)] */
    DARKEN      (16),
    /** [Sa + Da - Sa*Da,
         Sc*(1 - Da) + Dc*(1 - Sa) + max(Sc, Dc)] */
    LIGHTEN     (17),
    /** [Sa * Da, Sc * Dc] */
    MULTIPLY    (13),
    /** [Sa + Da - Sa * Da, Sc + Dc - Sc * Dc] */
    SCREEN      (14),
    /** Saturate(S + D) */
    ADD         (12),
    OVERLAY     (15);

    Mode(int nativeInt) {
        this.nativeInt = nativeInt;
}

    /**
     * @hide
     */
    public final int nativeInt;
}

这就是 PorterDuff.Mode 的定义,注释的文字是说明该模式的 alpha 通道和颜色值的计算方式,要理解各个模式的计算方式需要先弄明白公式中各个元素的具体含义:

  1. Sa:全称为Source alpha,表示源图的Alpha通道。
  2. Sc:全称为Source color,表示源图的颜色。
  3. Da:全称为Destination alpha,表示目标图的Alpha通道。
  4. Dc:全称为Destination color,表示目标图的颜色。

当 Alpha 通道的值为1时,图像完全可见;当 Alpha 通道值为0时,图像完全不可见;当 Alpha 通道的值介于0和1之间时,图像只有一部分可见。Alpha 通道描述的是图像的形状,而不是透明度。

其实每一个值都是按一定的规则对像素点的颜色值进行加减乘除操作。但,千万不要用数学计算去套这些模式的操作结果,因为数学计算的结果和显示的颜色值是有一定的差别的。但,可以按数学计算公式去估算每一个模式中颜色值的大致变化。

其中的每一个值都是对src与dst的每一个像素点的颜色值进行操作。src指前景、上层,后绘制上的;dst指后景、下层,先绘制上去的。

以 SRC_OVER 的计算方式为例:[Sa + (1 - Sa)*Da, Rc = Sc + (1 - Sa)*Dc] 。它以逗号分成两部分,前面“Sa + (1 - Sa)*Da”计算的值代表 SRC_OVER 模式的 Alpha 通道,后面“Rc = Sc + (1 - Sa)*Dc”计算的是 SRC_OVER模式的颜色值,图形混合后的图片依靠这个矢量来计算 ARGB 的值。

1、Bitmap绘制

先来上几张图片,图文并茂我认为是最好的让人理解的方法。

两个图形一圆一方通过一定的计算产生了不同的合成效果,我们在实际工作中需要做图片处理时可以参考这张图的示意快速地选择合适的 Mode。

最常用的就是第一幅图的16种,ADD 和 OVERLAY 并不常使用。

在源图像与目标图像不相交的部分,源图像可以把 Da、Dc 视作0,目标图也是如此。

1、CLEAR

清除模式,[0, 0],即图像中所有像素点的 alpha 和颜色值均为0,用这个就只有我们设置的背景。

2、SRC

[Sa, Sc],只保留源图像的 alpha 和 color ,所以绘制出来只有源图,上图中就是蓝色正方形。

3、DST

[Da, Dc],只保留了目标图像的 alpha 和 color,所以绘制出来的只有目标图,上图中就是圆形。

4、SRC_OVER

[Sa + (1 - Sa)*Da, Rc = Sc + (1 - Sa)*Dc],看上去是在目标图像上层绘制源图像,如果源图与目标图的重合部分源图不透明,则完全覆盖目标图;如果有透明的部分则会计算它们的颜色,我们说过算得就是每个像素的颜色值,所以该像素点是否有值还要看 color。

5、DST_OVER

[Sa + (1 - Sa)*Da, Rc = Dc + (1 - Da)*Sc],与 SRC_OVER 相反,此模式是目标图像被绘制在源图像的上方,公式可以看到如果目标图不透明则这个像素的颜色就是目标图像的 color;透明则计算两图的颜色。

6、SRC_IN

[Sa * Da, Sc * Da],在两者相交的地方绘制源图像,并且绘制的效果会受到目标图像对应地方透明度的影响。这个公式更好理解。

7、DST_IN

[Sa * Da, Sa * Dc],理论和 SRC_IN 相同,在两者相交的地方绘制目标图像,并且绘制的效果会受到源图像对应地方透明度的影响。

8、SRC_OUT

[Sa * (1 - Da), Sc * (1 - Da)],从名字可以看出于 SRC_IN 相反,那可以理解为在不相交的地方绘制源图像。color 是 Sc * ( 1 - Da ) ,表示如果相交处的目标色的 alpha 是完全不透明的,这时候源图像会完全被过滤掉,否则会受到相交处目标色 alpha 影响,呈现出对应色值。

9、DST_OUT

[Da * (1 - Sa), Dc * (1 - Sa)],可以类比SRC_OUT , 在不相交的地方绘制目标图像,相交处根据源图像alpha进行过滤,完全不透明处完全过滤,完全透明则不过滤,半透明则受到相交处源图像 alpha 影响,呈现出对应色值。

10、SRC_ATOP

[Da, Sc * Da + (1 - Sa) * Dc],从公式看,源图像没有和目标图像相交的部分因为 Da 和 Dc 没有值,视作0,所以那个部分就不会被绘制。因此这个模式就是在源图像和目标图像相交处绘制源图像,不相交的地方只绘制目标图像的部分,并且相交处的效果会受到源图像和目标图像alpha的影响。

11、DST_ATOP

[Sa, Sa * Dc + Sc * (1 - Da)],源图像和目标图像相交处绘制目标图像,不相交的地方绘制源图像的部分,并且相交处的效果会受到源图像和目标图像alpha的影响。

12、XOR

[Sa + Da - 2 * Sa * Da, Sc * (1 - Da) + (1 - Sa) * Dc],在不相交的地方按原样绘制源图像和目标图像,相交的地方受到对应 alpha 和 color 的值影响,按公式进行计算,如果都完全不透明则相交处完全不绘制。

13、DARKEN

[Sa + Da - Sa*Da, Sc*(1 - Da) + Dc*(1 - Sa) + min(Sc, Dc)],min(Sc,Dc) 表示选择 Sc 和 Dc 中更接近 0 的值,也就是更暗的颜色。所以该模式处理过后,会感觉效果变暗,即进行对应像素的比较,取较暗值,如果色值相同则进行混合。

从公式上看,色值上如果都不透明则取较暗值,非完全不透明情况下使用上面算法进行计算,受到源图和目标图对应色值和 alpha 值影响。

14、LIGHTEN

[Sa + Da - Sa*Da, Sc*(1 - Da) + Dc*(1 - Sa) + max(Sc, Dc)],可以和 DARKEN 对比起来看,DARKEN 的目的是变暗,LIGHTEN 的目的则是变亮,如果在均完全不透明的情况下,色值取源色值和目标色值中的较大值,否则按上面算法进行计算。

15、MULTIPLY

[Sa * Da, Sc * Dc],类似于PS中的“正片叠底”效果,即查看每个通道中的颜色信息,并将基色与混合色复合。结果色总是较暗的颜色,这是二进制的与运算,黑色是0,白色是1,任何颜色与黑色复合产生黑色,任何颜色与白色复合保持不变,当用黑色或白色以外的颜色绘画时,绘画工具绘制的连续描边产生逐渐变暗的颜色。

16、SCREEN

[Sa + Da - Sa * Da, Sc + Dc - Sc * Dc],滤色,滤色模式与我们所用的显示屏原理相同,所以也有版本把它翻译成屏幕;简单的说就是保留两个图层中较白的部分,较暗的部分被遮盖;当一层使用了滤色(屏幕)模式时,图层中纯黑的部分变成完全透明,纯白部分完全不透明,其他的颜色根据颜色级别产生半透明的效果。

17、ADD

Saturate(S + D),饱和度叠加

18、OVERLAY

像素是进行 Multiply(正片叠底)混合还是 Screen(屏幕)混合,取决于底层颜色,但底层颜色的高光与阴影部分的亮度细节会被保留。

推荐简书的一篇文章,各个击破搞明白PorterDuff.Mode,这里面的经过混合模式处理后的图片效果比官方提供给我们的上面的图要好的多,理解起来要简单的多,对模式的说明也让我想通了很多,我这里的说明就是在他的基础上再加上我的解释,让其详细了一些,大家可以看看。

2、Canvas直接绘制

这里要注意一下,我们上面的说明是围绕于目标图和源图都是 Bitmap 的情况下,如果是 Canvas 直接绘制的话,模式的功能就是下面这幅图:

大致的意思是与上面相同的,在下面的例子也会出现直接用 Canvas 绘制的,大家来对照这幅图就能理解啦。

3、代码演示

我们学习 PorterDuff.Mode 就是为了将它运用到我们实际的开发当中,所以我们当然要知道在哪些地方能用到 PorterDuff.Mode,我总结了一些它的用法:

1、自定义loading样式

我相信大家在下载的时候很多时候都能看到下面的效果:

这里写图片描述

我们把这个当做下载文件的进度,当蓝色填满了整个图形,那就代表下载完成了,是不是觉得效果很不错,要实现这个效果很简单,我们只要用到 PorterDuff 的一种模式就能轻而易举的达到,我们来看代码:

public class LogoLoadingView extends View {

    private int width, height;
    private Paint paint;
    private Bitmap bitmap;
    private int currentTop;
    private RectF rectF;
    private PorterDuffXfermode porterDuffXfermode;

    public LogoLoadingView(Context context) {
        this(context, null);
    }

    public LogoLoadingView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public LogoLoadingView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {

        paint = new Paint();
        //设置抗锯齿
        paint.setAntiAlias(true);
        //设置填充样式
        paint.setStyle(Paint.Style.FILL);
        //设定是否使用图像抖动处理,会使绘制出来的图片颜色更加平滑和饱满,图像更加清晰
        paint.setDither(true);
        //加快显示速度,本设置项依赖于dither和xfermode的设置
        paint.setFilterBitmap(true);
        //从资源文件中解析获取Bitmap
        bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher);

        width = 200;
        height = 200;

        bitmap = Bitmap.createScaledBitmap(bitmap, width, height, true);

        porterDuffXfermode = new PorterDuffXfermode(PorterDuff.Mode.SRC_IN);

        /**
         * 设置当前矩形的高度为0
         */
        currentTop = bitmap.getHeight();
        rectF = new RectF(0, currentTop, bitmap.getWidth(), bitmap.getHeight());
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        rectF.top = currentTop;

        /*
         * 将绘制操作保存到新的图层(更官方的说法应该是离屏缓存)
         */
        int sc = canvas.saveLayer(0, 0, width, height, paint, Canvas.ALL_SAVE_FLAG);

        //绘制目标图像(设置的安卓图标)
        canvas.drawBitmap(bitmap, 0, 0, null);

        paint.setXfermode(porterDuffXfermode);
        paint.setColor(Color.BLUE);

        //绘制
        canvas.drawRect(rectF, paint);
        paint.setXfermode(null);
        /**
         * 还原画布,与canvas.saveLayer配套使用
         */
        canvas.restoreToCount(sc);
        if (currentTop > 0) {
            currentTop -= 2;
            postInvalidate();
        }
    }
}

大部分的工作都是用来初始化我们的画笔,这些个方法的效果就不详细说了,我们得到图片后,因为原本的图片比较小,所以我用 createScaledBitmap() 调整为我想要的大小。我们在这里要用到的是 SRC_IN 模式,上面说过它的效果是在目标图与源图相交的部分,不透明就以源图的颜色为准。因为我们要在图形上填充颜色,所以目标图应该是 Android 机器人。

在这里使用 PorterDuff.Mode 是 SRC_IN,因为这里我们是直接在 Canvas 上绘制矩形,所以对照的是 Canvas 的那幅图,这里 SRC_IN 的效果和 SRC_ATOP 一样。

我们要做的是让颜色逐渐填满图形,所以最开始矩形的高度应该是0。因为我们屏幕的坐标系中,Y 轴的坐标向下越来越大,所以我们设置矩形 top 为图形的 height,其实是把位置定在了图形的最下方。top 和 bottom 值相同,矩形高度就为0了。

在 onDraw() 方法中绘制,先绘制的是目标图,然后设置好 PorterDuff.Mode,再绘制矩形。要让颜色从图形底部填充,要改的就是矩形 top 的值,往上就 Y 轴坐标减小,所以我们让 top 逐渐减小,再让它重新绘制即可。

2、整合图片

有时候我们会想把两张图片融合在一起,得到看起来很炫酷的样子,这样的效果也是可以用 PorterDuff.Mode 做出来的:

我这里下载了两张图片:

我们要做的就是让莲花出现在背景图上。

public class SrcTopView extends View {

    private Paint mPaint;// 画笔
    private Bitmap bitmapDis, bitmapSrc;// 位图
    private PorterDuffXfermode porterDuffXfermode;// 图形混合模式

    private int x, y;// 位图绘制时左上角的起点坐标
    private int screenW, screenH;// 屏幕尺寸

    public SrcTopView(Context context) {
        this(context, null);
    }

    public SrcTopView(Context context, AttributeSet attrs) {
        super(context, attrs);

        // 实例化混合模式
        porterDuffXfermode = new PorterDuffXfermode(PorterDuff.Mode.SRC_ATOP);

        // 初始化画笔
        initPaint();

        // 初始化资源
        initRes(context);
    }

    /**
     * 初始化画笔
     */
    private void initPaint() {

        mPaint = new Paint();

        mPaint.setAntiAlias(true);

        mPaint.setStyle(Paint.Style.FILL);

        mPaint.setDither(true);

        mPaint.setFilterBitmap(true);
    }

    /**
     * 初始化资源
     */
    private void initRes(Context context) {
        // 获取位图
        bitmapDis = BitmapFactory.decodeResource(context.getResources(), R.drawable.picture1);
        bitmapSrc = BitmapFactory.decodeResource(context.getResources(), R.drawable.picture2);

        int[] screenSize = MeasureUtil.getScreenSize(context);

        // 获取屏幕尺寸
        screenW = screenSize[0];
        screenH = screenSize[1];

        /*
         * 计算位图绘制时左上角的坐标使其位于屏幕中心
         * 屏幕坐标x轴向左偏移位图一半的宽度
         * 屏幕坐标y轴向上偏移位图一半的高度
         */
        x = screenW / 2;
        y = screenH / 2;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.drawColor(Color.WHITE);

        int sc = canvas.saveLayer(0, 0, screenW, screenH, null, Canvas.ALL_SAVE_FLAG);

        // 先绘制dis目标图
        canvas.drawBitmap(bitmapDis, x - bitmapDis.getWidth() / 2,
                y - bitmapDis.getHeight() / 2, mPaint);

        // 设置混合模式
        mPaint.setXfermode(porterDuffXfermode);

        // 再绘制src源图
        canvas.drawBitmap(bitmapSrc, x - bitmapSrc.getHeight() / 2,
                y - bitmapSrc.getWidth() / 2, mPaint);

        // 还原混合模式
        mPaint.setXfermode(null);

        // 还原画布
        canvas.restoreToCount(sc);
    }
}
public class MeasureUtil {

    public static int[] getScreenSize(Context context) {
        DisplayMetrics metrics = new DisplayMetrics();
        metrics = context.getResources().getDisplayMetrics();

        int[] sizes = new int[] {
                metrics.widthPixels, metrics.heightPixels
        };

        return sizes;
    }
}

我们用 MeasureUtil 获得屏幕的宽高,在绘制 Bitmap 的时候设置好 left 和 top 的坐标,要注意的就是这个了,实现是很简单的。

3、裁图得到圆形圆角

我们也可以使用 PorterDuff.Mode 来让图片变成圆形或者出现圆角:

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    setLayerType(LAYER_TYPE_SOFTWARE, null); //关闭硬件加速

    Bitmap src = BitmapFactory.decodeResource(getResources(), R.drawable.picture1);

    int radiu = Math.min(src.getHeight(), src.getWidth()) / 2;
    canvas.drawCircle(src.getWidth() / 2, src.getHeight() / 2, radiu, mPaint);

    //设置Xfermode
    mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));

    //源图
    canvas.drawBitmap(src, 0, 0, mPaint);

    //还原Xfermode
    mPaint.setXfermode(null);
}

得到圆角也就是改变一个方法的事情:

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    setLayerType(LAYER_TYPE_SOFTWARE, null); //关闭硬件加速

    Bitmap src = BitmapFactory.decodeResource(getResources(), R.drawable.picture1);

    //得到目标图
    RectF rectF = new RectF(0, 0, src.getWidth(), src.getHeight());
    canvas.drawRoundRect(rectF, 70, 70, mPaint);

    //设置Xfermode
    mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));

    //源图
    canvas.drawBitmap(src, 0, 0, mPaint);

    //还原Xfermode
    mPaint.setXfermode(null);
}

关于 PorterDuff.Mode 的介绍就讲到这里,在刚了解它的时候,我们可能不能第一时间想到使用,这就需要我们大家的努力练习啦。

结束语:本文仅用来学习记录,参考查阅。

自定义View之基础篇——PorterDuff 前言 本章主要介绍颜色渲染器PorterDuff。 PorterDuff其实来自两个人名:Tomas Porter和Tom Duff。利用PorterDuff.Mode,我们可以实现图片的任意叠加混合,eg.实现画图中的橡皮擦功能、显示圆形图片等等   1、核心代码 以圆和矩形为例。dst为下层,是先画的图形(这里我选择的是灰色的圆);src为上层,后画的图形(我选用的是蓝色矩形)。实验... 阅读详情

相关推荐

深入理解Android绘图中的PorterDuffXfermode

深入理解Android绘图中的PorterDuffXfermode前言概要示例一(不设置Xfermode)插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定义列表如何创建一个注脚注释也是必不可少的KaTeX数学公式新的甘特图功能,丰富你的文章UML 图表FLowchart流程图导出与导入导出导入 前言 本人现在是一名大三...

weixin_43932465的博客 1169

Android自定义View系列:PorterDuff.Mode

文章目录1 PorterDuff.Mode的作用和背景2 PorterDuff.Mode的颜色策略2.1 Alpha合成2.1.1 1 PorterDuff.Mode的作用和背景 PorterDuff.Mode 是用来指定两个图像共同绘制时的颜色策略的。它是一个枚举,不同的Mode可以指定不同的策略。颜色策略的意思,就是说把源图像绘制到目标图像处时应该怎样确定二者结合后的颜色。 PorterDuf...

Vincent的博客 5093

Python离线断网情况下安装numpy、pandas和matplotlib等常用第三方包

联网情况下在命令终端CMD中输入“pip install numpy”即可自动安装,pandas和matplotlib同理一样方法进行自动安装。 工作的电脑不能上外网,所以不能通过直接输入pip命令来安装。 环境:电脑上已经安装了Python(没有安装的请参考其他教程)。 Python离线断网情况下安装numpy、pandas和matplotlib等常用第三方包的步骤如下: ...

dayou7738的博客 4942

PorterDuff.Mode详解

PorterDuff.Mode主要用于设置画笔模式,Google文档中SRC、DST的定义

u010080945的博客 1309

彻底卸载Ubuntu双系统,并完美回收100G空间给D盘

本文记录了安全卸载Ubuntu双系统并回收磁盘空间的全过程。作者首先通过Windows命令行彻底清除Ubuntu启动项,避免GRUB引导报错;随后在磁盘管理中删除Linux分区,将100G未分配空间合并至相邻的D盘。针对C盘空间不足问题,作者采用Dism++清理系统文件,并将用户文档、聊天记录等迁移至扩容后的D盘。最终实现了引导纯净、空间合理分配的目标,特别强调分区扩展必须遵循"相邻原则",建议通过间接迁移而非直接扩容来优化系统盘空间管理。

2403_85993278的博客 1512

S7-1200控制S120变频器

②:硬件目录下,添加实物S120设备进行组态(其它现场设备--PROFINET IO--DRIVES......②:双击S120进行IP地址和设备名称设置(注:此处要与STATER软件设置S120一致)M10.0接通时,电机开始运行,M10.0断开,电机停止,调试完成。①:将S7-1200与S120进行通讯连线。④:STATER软件下设置与组态一致的报文。①:点击添加新设备,按实物进行设备组态。②:打开OB1,编写启动停止程序。①:查看S120报文地址。②:模块下添加DO矢量。③:子模块下添加报文。

weixin_38261173的博客 4867

逐一认识PorterDuff.Mode

setXfermode(Xfermode xfermode)Xfermode被称为过渡模式,我们也可以称之为图像混合模式。Xfermode有三个实现类:AvoidXfermode, PixelXorXfermode以及PorterDuffXfermode。前两个类因为不支持硬件加速在API level 16被标记为Deprecated了,用也可以,但是需要关闭硬件加速.在最新的API中,只能看到Po

行云间 3740

用python自动复制粘贴excel表里某一列的数据到另一个表中

昨天接到人事小姐姐求助减轻复制粘贴的重复工作量,分享一下代码 半路新手上路 耶 把 2.xlsx 表里的第二列 的数据复制粘贴到 test.xlsx的第一列 python3.6.2 from openpyxl import Workbook from openpyxl import load_workbook from openpyxl.writer.excel import Exc...

weixin_33854644的博客 2万+

PorterDuff及Xfermode 贝塞尔曲线

贝塞尔曲线 PorterDuff及Xfermode

许浑的博客 1510

高速PCB设计中的信号完整性挑战:回损、插损与串扰的深度解析

本文深入探讨了高速PCB设计中的信号完整性挑战,重点分析了回损、插损与串扰三大关键问题。通过实际案例和专业技术解析,提供了降低回损的阻抗控制技巧、减少插损的板材选择建议以及抑制串扰的布线策略,帮助工程师应对5G和AI芯片时代的高速信号传输需求。

websocket5live的博客 264

vue3的面试题

vue3的面试题

jiang7701037的博客 6264

Android PorterDuff.Mode

做过图形图像处理coding的Android程序员一定用过或了解过PorterDuff.Mode这个枚举变量中的某些值,对此了解不多理解不深刻的时候是不是会很纠结到底该用那个模式呢?至少不能快速准确地用到恰当的模式,那么PorterDuff.Mode究竟是什么,它的各个枚举值有什么作用呢?这里我整理一下笔记,加深理解。 PorterDuff.Mode是什么 public Xfermod...

Oliver Lau的博客 689

【基于 CasADi 的欠驱动无人船实时非线性模型预测控制(NMPC)实现 Visual Studio 2022 C++】

本文介绍了基于CasADi和IPOPT在Visual Studio 2022 C++环境下实现的欠驱动无人船实时非线性模型预测控制(NMPC)方案。文章详细阐述了NMPC基本原理、欠驱动无人船动力学模型(包含状态变量和控制变量定义),并给出了C++实现的核心代码框架。该方案通过显式引入系统动力学模型和约束条件,在每个采样周期滚动优化控制序列,有效解决了欠驱动无人船的轨迹跟踪与避碰问题。文中还提供了VS2022配置CasADi环境的详细步骤,包括预编译包下载、工程属性设置等关键环节,为工程实现提供了完整的技术

vor234的博客 652

Android中Canvas绘图之PorterDuffXfermode使用及工作原理详解

概述类android.graphics.PorterDuffXfermode继承自android.graphics.Xfermode。在用Android中的Canvas进行绘图时,可以通过使用PorterDuffXfermode将所绘制的图形的像素与Canvas中对应位置的像素按照一定规则进行混合,形成新的像素值,从而更新Canvas中最终的像素颜色值,这样会创建很多有趣的效果。当使用PorterD

孙群 5万+

推荐系统中召回率Recall计算方式附代码

Recall(召回率)是指在所有实际有交互的用户 - 物品对中,推荐系统成功预测出的比例。具体来说,设所有有交互的用户 - 物品对为S,推荐系统预测出的用户 - 物品对为T,则Recall的计算公式为:

优快云 精品推荐 1842

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

【Android 应用开发】Xfermod 图形组合 之 SRC 类 合成模式 ( SRC | SRC_ATOP | 详细解析官方给出的透明度和颜色值计算公式 )

SRC 合成模式 SRC 合成模式详细解析 SRC_ATOP 合成模式 SRC_ATOP 合成模式详细解析

让 学习 成为一种 习惯 ( 韩曙亮 の 技术博客 ) 2674

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

PorterDuff及Xfermode详解

Xfermode有三个子类 : AvoidXfermode  指定了一个颜色和容差,强制Paint避免在它上面绘图(或者只在它上面绘图)。 PixelXorXfermode  当覆盖已有的颜色时,应用一个简单的像素异或操作。 PorterDuffXfermode  这是一个非常强大的转换模式,使用它,可以使用图像合成的16条Porter-Duff规则的任意一条来控制P

y444400的专栏 1134

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

Android 图形混合模式PorterDuffXfermode模式介绍

一、PorterDuffXfermode模式介绍PorterDuffXfermode是设置两个图层的交集区域的显示方式,分为目标图像(先画的图片)和源图像(后画的图片),图解如下:简单说目标图像是底片,源图像是封面先看一下官方的样图两个图形一圆一方通过设置不同的模式会产生不同的组合效果,在API中Android为我们提供了18种(比上图多了两种ADD和OVERLAY)模式: ADD:       ...

0729Liang 4321

Android PorterDuff.Mode.CLEAR 效果 简单实现

Android PorterDuff.Mode.CLEAR 效果 简单实现。

OneN的博客 1834

PorterDuff属性值介绍

自定义view,画笔PorterDuff属性值介绍 1.PorterDuff.Mode.CLEAR 所绘制不会提交到画布上。 2.PorterDuff.Mode.SRC 显示上层绘制图片 3.PorterDuff.Mode.DST 显示下层绘制图片 4.PorterDuff.Mode.SRC_OVER 正常绘制显示,上下层绘制叠盖。 5.PorterDuff.Mode.DST_OVER 上下层都...

qq_36500835的博客 741

Android学习记录045_PorterDuff

Android学习记录045_PorterDuff

Duckdan的博客 1007

Android 之 Paint API —— Xfermode 与 PorterDuff 详解 (二)

代码看起来好复杂是吧,其实不然,无非就是获取了屏幕宽高,然后画了一个矩形一个圆形, 计算了一下他们的位置,然后设置下图层(固定写法),接着设下下画笔setXfermode,接着 绘制到canvas上而已,你看不懂的可能是绘制位置的计算吧,其实不然,位置你喜欢怎么定 都可以!PS:这个PorterDuff的命名其实是两个人名的组合:Tomas Proter和 Tom Duff组成的,他们是最早在 最早在SIGGRAPH上提出图形混合概念的大神级人物,有兴趣的自行百度~

leyang0910的博客 599

UIApplicationDelegate协议定义的方法说明

3.16条Porter-Duff规则 1.PorterDuff.Mode.CLEAR 所绘制不会提交到画布上。2.PorterDuff.Mode.SRC 显示上层绘制图片3.PorterDuff.Mode.DST 显示下层绘制图片4.PorterDuff.Mode.SRC_OVER 正常绘制显示,上下层绘制叠盖。5.PorterDuff.Mode.DST_OVER ...

weixin_30302609的博客 223

Android 之 Paint API —— Xfermode 与 PorterDuff 详解 (三)

我们在观看了16种图片混排模式后,又自己写代码来验证了一下文档中 18种不同的混排模式,18种是新增了ADD和OVERLAY两种模式!当然,仅仅验证知道是不够的, 本节我们来写个例子,帮助我们熟悉下实际当中我们如何去使用PorterDuff.Mode为我们提供的 这些混排模式!//bitmap缓存起来,避免每次调用onDraw,分配内存。//根据缩放比例,设置bounds,相当于缩放图片了。

leyang0910的博客 496

Android图像合成模式之PorterDuff

【代码】Android图像合成模式之PorterDuff。

2401_87167563的博客 507
上一篇: Android--关于Fragment的基础介绍(二)
下一篇: Android--ToolBar基本介绍
因人而异
博客等级 码龄10年 46粉丝 88原创
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值