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

`全网最细!! 入门必看Git教程链接:https://gitee.com/all-about-git`

全网 Git 入门教程 gitee.com。如果显示The requested URL returned error: 403错误,那就表示没有和window本地建立token令牌

qq_37855368的博客 3748

PorterDuff.Mode详解

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

u010080945的博客 1309

python k线顶分型_【缠论】分型、笔的定义及其程序化

K线包含关系处理和分型的定义如果一个K线的高低点全在另一K线的范围里,称之为包含关系。针对这种K线,需要进行一些处理,去除包含关系,处理方法:向上时,把两K线的高点当高点,而两K线低点中的较高者当成低点;反之,当向下时,把两K线的低点当低点,而两K线高点中的较低者当成高点,这样就把两K线合并成一新的K线。经过这样的处理,所有K线图都可以处理成没有包含关系的图形。两K线的包含关系,可以分成四种:1)...

weixin_39717152的博客 2824

Python+OpenCV实战:雨天车牌识别准确率提升300%的5个关键技巧

本文针对雨天车牌识别准确率骤降的难题,分享了五个基于Python和OpenCV的实战技巧。通过暗通道先验去雾、雨纹抑制、光照不变量颜色空间转换、多尺度自适应阈值分割以及融合传统特征与轻量级深度学习的混合识别策略,系统性地提升了算法在恶劣天气下的鲁棒性。这些方法能有效解决图像模糊、对比度低、字符断裂粘连等问题,为智能交通等实际应用提供可靠解决方案。

k8l9m0n的博客 716

逐一认识PorterDuff.Mode

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

行云间 3740

OPA(运放)与MOS管组成的恒流源电路

电路图 这是一种由运放组成的恒流源电路。 原理分析: 1. OPA OPA (集成运算放大器)具有开源增益高,输入阻抗大,输出阻抗小的特点。 2. MOS管工作原理 我们知道三极管是利用 Ib 的电流控制 IC 的电流,属于电流控制电流器件。 而MOS则是利用Ugs的电压去控制电流 Id 的,所以说 MOS 管是电压控制电流的器件。 对于N沟道增强型的MOS管,当Ugs>Ugs(th)时,MOS就会开始导通,如果在D极和S极之间加上一定的电压,就会有电流Id产生。 在一定的Uds下,D极电流Id的

暖暖_的_纠结的博客 3万+

PorterDuff及Xfermode 贝塞尔曲线

贝塞尔曲线 PorterDuff及Xfermode

许浑的博客 1510

Ubuntu下OpenOCD+GDB的安装、编译及使用

目标开发板(芯片):stm32mp157aaa 仿真器:ST-Link 操作系统:Ubuntu 18.04 调试软件:OpenOCD OpenOCD的安装 首先下载OpenOCD有多种方式,可以GitHub上下载,目录下打开终端,输入 git clone git://git.code.sf.net/p/openocd/code openocd 下载完整的OpenOCD的文件夹。进入到OpenOCD的目录下,开始安装。 接着,OpenOCD适用于微处理器的debug和烧写,需要下载相关库 sud

蓝冰露的博客 9524

智能汽车域控制器FOTA升级方案探讨

上文提到的Entry属性,包括Active 属性, Bootable 属性, Successful 属性, Retrycnt 属性 ,Active 属性用于标志槽的优先级,bootloader优先选择Active 属性=1的槽启动,Bootable 属性标志槽可否可启动,Successful 属性标志槽是否成功启动过,Retrycnt 属性标志槽可尝试启动的次数。芯片启动后,首先进入Bootloader阶段,此阶段将读取存储系统的分区属性,根据属性值进行逻辑判断,并确定进入哪个分区,详见流程图。

huibian1234的博客 1570

Android PorterDuff.Mode

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

Oliver Lau的博客 689

PointPillars代码详解及实现

SourceURL:file://文字文稿1和2D图像的深度学习目标检测很不相同,点云数据具有两个显著特征,为了将图像领域卷积神经网络做模式识别的经验引入三维点云中,一些深度学习方法采用了三维卷积方法或者是将点云投射为2维深度图,还有一类方法是使用鸟瞰视角Bird’s Eye View,来组织点云数据的输入,相比于2维深度图,鸟瞰图不存在遮挡问题但是数据分布更加稀疏造成网络特征学习效率低下。

m0_47313541的博客 661

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

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

孙群 5万+

零基础学simulink仿真建模--基于Simulink进行近端策略优化(PPO)路径规划的仿真建模

特点高效性与稳定性:通过引入剪裁机制,在更新策略时限制步长,从而提高了训练过程的稳定性和效率。适用于多种动作空间:可以处理连续和离散的动作空间问题。无需模型:不需要预先知道环境的确切模型,适合复杂或未知环境。挑战收敛速度与稳定性:确保算法能够在合理的时间内找到近似最优解,并保持训练过程的稳定性。探索与利用平衡:在探索新路径和利用已知信息之间取得平衡。计算资源:对于大规模状态空间和动作空间,计算资源需求较高。首先明确要模拟的任务内容。目标(例如到达指定地点、避开障碍物等)。

amy_mhd的博客 249

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

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

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

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

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

PorterDuff及Xfermode详解

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

y444400的专栏 1134

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

pscad IEEE标准系统搭建说明

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

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、付费专栏及课程。

余额充值