美文网首页
关于图片的混合模式

关于图片的混合模式

作者: 最美下雨天 | 来源:发表于2018-09-14 11:44 被阅读22次

ComposeShader、BitmapShader
用法参考网址:https://blog.csdn.net/iispring/article/details/50500106
先来看一张图,这个是从APIDemo中粘贴的代码运行出来的,路径:

/Users/huozhenpeng/Library/Android/sdk/samples/android-23/legacy/ApiDemos/src/com/example/android/apis/graphics/Xformodes.java

image.png

这个是运用ComposeShader的demo效果,就是两张图片在不同混合模式下产生的效果,实现这个效果有两个地方需要注意

先绘制目标图像(dst),然后设置ComposeShader,再绘制原图像(src),源像素(src)在Canvas中对应位置上的像素称作目标像素

两张图片是覆盖绘制

什么意思呢?
示例中,dst是黄色圆形,src是蓝色矩形,但是dst这张图片代表的区域(大小)不只是黄色区域


image.png

dst和src是宽高相同的两张图片,只是dst在左上部分画了个黄色圆形,src在右下部分画了个蓝色矩形

看下代码:

package com.dongnao.ffmpegmusic;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.os.Build;
import android.support.annotation.Nullable;
import android.support.annotation.RequiresApi;
import android.util.AttributeSet;
import android.view.View;

/**
 * 作者 huozhenpeng
 * 日期 2018/9/14
 * 邮箱 huohacker@sina.com
 */

public class PorterView extends View {
    public PorterView(Context context) {
        this(context,null);
    }

    public PorterView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs,-1);
    }

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

    private Paint paint;
    private void init()
    {
        paint=new Paint(Paint.ANTI_ALIAS_FLAG);

    }

    private int width;
    private int height;
    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        width=w;
        height=h;
    }

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.drawColor(Color.WHITE);
        canvas.saveLayer(0,0,width,height,paint);
        canvas.drawBitmap(createDstBitmap(),0,0,paint);
        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
        canvas.drawBitmap(createSrcBitmap(),0,0,paint);
        paint.setXfermode(null);
        canvas.restore();
    }

    private Bitmap createDstBitmap()
    {
        Bitmap bitmap= Bitmap.createBitmap(width,height, Bitmap.Config.ARGB_8888);
        Canvas canvas=new Canvas();
        canvas.setBitmap(bitmap);
        Paint p = new Paint(Paint.ANTI_ALIAS_FLAG);
        p.setColor(0xFFFFCC44);
        canvas.drawCircle(width/4,height/4,width/4,p);
        return bitmap;
    }

    private Bitmap createSrcBitmap()
    {
        Bitmap bitmap= Bitmap.createBitmap(width,height, Bitmap.Config.ARGB_8888);
        Canvas canvas=new Canvas();
        canvas.setBitmap(bitmap);
        Paint p = new Paint(Paint.ANTI_ALIAS_FLAG);

        p.setColor(0xFF66AAFF);

        canvas.drawRect(width/4,height/4,width*3/4,height*3/4,p);
        return bitmap;
    }
}

显示的效果:


image.png
实现一张圆形图片

这个应用场景蛮多的,比如说app中的头像啊什么的
实现这个功能也有两种做法:
第一种用ComposeShader,第二种用BitmapShader

利用ComposeShader

原理就是,先绘制一个圆形的bitmap,设置ComposeShader为SRC_IN,再绘制一个图片(要裁剪为圆形的图片,比如头像啦)

package com.dongnao.ffmpegmusic;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ComposeShader;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.Shader;
import android.os.Build;
import android.support.annotation.Nullable;
import android.support.annotation.RequiresApi;
import android.util.AttributeSet;
import android.view.View;

/**
 * 作者 huozhenpeng
 * 日期 2018/9/14
 * 邮箱 huohacker@sina.com
 */

public class PorterView2 extends View {
    public PorterView2(Context context) {
        this(context,null);
    }

    public PorterView2(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs,-1);
    }

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

    private Paint paint;
    private void init()
    {
        paint=new Paint(Paint.ANTI_ALIAS_FLAG);

    }

    private int width;
    private int height;
    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        width=w;
        height=h;
    }

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.drawColor(Color.WHITE);
        canvas.saveLayer(0,0,width,height,paint);
        canvas.drawBitmap(createDstBitmap(),0,0,paint);
        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
        canvas.drawBitmap(createSrcBitmap(),0,0,paint);
        paint.setXfermode(null);
        canvas.restore();
    }

    private Bitmap createDstBitmap()
    {
        Bitmap bitmap= Bitmap.createBitmap(width,height, Bitmap.Config.ARGB_8888);
        Canvas canvas=new Canvas();
        canvas.setBitmap(bitmap);


        Paint p = new Paint(Paint.ANTI_ALIAS_FLAG);
        p.setColor(0xFFFFCC44);
        canvas.drawCircle(width/2,height/2,width/2,p);
        return bitmap;
    }

    private Bitmap createSrcBitmap()
    {
        Bitmap bitmap= Bitmap.createBitmap(width,height, Bitmap.Config.ARGB_8888);
        Canvas canvas=new Canvas();
        canvas.setBitmap(bitmap);
        Paint p = new Paint(Paint.ANTI_ALIAS_FLAG);
        Bitmap source=BitmapFactory.decodeResource(getResources(),R.mipmap.a);
        //图片有时候会太小,一般会给设置BitmapShader
        p.setShader(new BitmapShader(source, Shader.TileMode.REPEAT, Shader.TileMode.REPEAT));
        canvas.drawRect(0,0,width,height,p);

        return bitmap;
    }

    private Bitmap createSrcBitmap2()
    {
        Bitmap bitmap= Bitmap.createBitmap(width,height, Bitmap.Config.ARGB_8888);
        Canvas canvas=new Canvas();
        canvas.setBitmap(bitmap);
        Paint p = new Paint(Paint.ANTI_ALIAS_FLAG);
        Bitmap source=BitmapFactory.decodeResource(getResources(),R.mipmap.a);

        Rect rectSrc=new Rect(0,0,source.getWidth(),source.getHeight());
        Rect rectDst=new Rect(0,0,width,height);

        canvas.drawBitmap(source,rectSrc,rectDst,p);

        return bitmap;
    }
}

注意我们一般用createSrcBitmap2(),就是为了防止实际要裁剪的图片过大或者过小。
看下效果
createSrcBitmap()


image.png

createSrcBitmap2()


image.png
利用BitmapShader

利用BitmapShader就比较简单了,原理是利用BitmapShader填充画笔,然后用画笔绘制圆形

package com.dongnao.ffmpegmusic;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.Shader;
import android.os.Build;
import android.support.annotation.Nullable;
import android.support.annotation.RequiresApi;
import android.util.AttributeSet;
import android.view.View;

/**
 * 作者 huozhenpeng
 * 日期 2018/9/14
 * 邮箱 huohacker@sina.com
 */

public class PorterView3 extends View {
    public PorterView3(Context context) {
        this(context,null);
    }

    public PorterView3(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs,-1);
    }

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

    private Paint paint;
    private void init()
    {
        paint=new Paint(Paint.ANTI_ALIAS_FLAG);
        Bitmap source=BitmapFactory.decodeResource(getResources(),R.mipmap.a);
        paint.setShader(new BitmapShader(source, Shader.TileMode.MIRROR, Shader.TileMode.MIRROR));

    }

    private int width;
    private int height;
    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        width=w;
        height=h;
    }

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.drawColor(Color.WHITE);
        canvas.drawCircle(width/2,height/2,width/2,paint);
    }

}

这种情况需要src比较大时才会呈现比较好的效果,而且一般会使用bitmapShader.setLocalMatrix(shaderMatrix)对bitmapShader做变换,开源库CircleImageView就是这么做的。

相关文章

  • 关于图片的混合模式

    ComposeShader、BitmapShader用法参考网址:https://blog.csdn.net/ii...

  • iOS图片混合模式

    这里列一下图片的混合模式 具体什么样的效果需要动手试试了。

  • CSS3混合模式mix-blend-mode简介

    一、关于混合模式 熟悉PS的人都应该知道混合模式: SVG以及Canvas中也有混合模式,本质上都是一样的。 二、...

  • PSCC基础操作(六)图片合成

    简单两张图片合成,能做出很好看的效果。 图层混合模式 分类 正常:图像打开的一般模式加深:混合白色减淡:混合黑色叠...

  • 2020-03-05 TDDP 插件笔记

    TDDP_PictureBlendModes.js 可以调整图片的混合模式 TDDP_ManageDashing....

  • 不抠图而达到抠图的小技巧

    今天,教大家利用图层混合模式进行抠图。 利用图层的混合模式抠图,是间接的抠图方法,可以不破坏图像,而是过滤掉图片的...

  • 设计模式

    构造函数模式 混合模式 混合模式就是构造函数模式和原型模式的混合,在混合模式中,构造函数用于定义实例属性,而原型模...

  • 每日一练丨打卡~PS混合选项+关于美丑的练习

    效果图: 只看效果,图片有点模糊可以忽略掉~ 主要技能: PS图层样式-混合选项,主要利用混合模式来调整效果。 在...

  • 混合模式

    混合模式的作用就是将两张图片进行无缝结合,类似于PS中的图片融合。可以通过Paint.setXfermode()设...

  • ps学习笔记20黑白照片上色

    主要操作就这些,剩下的其实就是调整细节。 最后 组的穿透模式 就是组里图片能不能作为组外的混合色 混合颜色带

网友评论

      本文标题:关于图片的混合模式

      本文链接:https://www.haomeiwen.com/subject/fzongftx.html