实现图片的滤镜效果

作者: 尹star | 来源:发表于2016-04-04 01:25 被阅读1529次

提到这个到不是因为要做照片处理软件的滤镜效果,而是开发过程中设计师每每只提供一张icon图标,然后说点击效果你自己用程序实现吧;或者产品经理过来说,用户头像加个点击效果吧。以往的开发过程中,设计师多半会提供两张icon图标,一张正常状态,一张选中状态,这样点击的时候会有一个动态的效果。而现在一张图去实现点击效果还真有点难为了,车到山前必有路,谁让我是老司机呢。
首先我印象中Imageview会有个透明度Alpha的属性,于是我最先想到用setAlpha()来改变图片的透明度,但实际效果并不好。后来在Stay的点拨下终于找到了比较好的解决方案,ImageView有一个setColorFilter()的API,完全适合当前场景。

  /**
     * Set a tinting option for the image.
     * 
     * @param color Color tint to apply.
     * @param mode How to apply the color.  The standard mode is
     * {@link PorterDuff.Mode#SRC_ATOP}
     * 
     * @attr ref android.R.styleable#ImageView_tint
     */
    public final void setColorFilter(int color, PorterDuff.Mode mode) {
        setColorFilter(new PorterDuffColorFilter(color, mode));
    }

    /**
     * Set a tinting option for the image. Assumes
     * {@link PorterDuff.Mode#SRC_ATOP} blending mode.
     *
     * @param color Color tint to apply.
     * @attr ref android.R.styleable#ImageView_tint
     */
    @RemotableViewMethod
    public final void setColorFilter(int color) {
        setColorFilter(color, PorterDuff.Mode.SRC_ATOP);
    }
    /**
     * Apply an arbitrary colorfilter to the image.
     *
     * @param cf the colorfilter to apply (may be null)
     *
     * @see #getColorFilter()
     */
    public void setColorFilter(ColorFilter cf) {
        if (mColorFilter != cf) {
            mColorFilter = cf;
            mColorMod = true;
            applyColorMod();
            invalidate();
        }
    }

setColorFilter有以上三种调用方式,可以直接传入色值和mode,mode缺省的默认值为PorterDuff.Mode.SRC_ATOP,具体各mode的效果可以参见http://blog.sina.com.cn/s/blog_5da93c8f01012pkj.html, setColorFilter还可以传入ColorFilter的子类。

ColorFilter有三个子类ColorMatrixColorFilter,LightingColorFilter,PorterDuffColorFilter,它的功能应该就是按照一定的规则改变图片的颜色,三个子类各有各的不同的改法规则,其中ColorMatrixColorFilter的改变法则就是ColorMatrix的改变规则,它是ColorMatrix的应用。LightingColorFilter 乘以第一个颜色的RGB通道,然后加上第二个颜色。每一次转换的结果都限制在0到255之间。PorterDuffColorFilter 可以使用数字图像合成的16条Porter-Duff 规则中的任意一条来向Paint应用一个指定的颜色。

我们就挑第一个ColorMatrixColorFilter来举例,前面已经说过,ColorMatrixColorFilter的改变法则就是ColorMatrix的改变规则,它是ColorMatrix的应用。ColorMatrix是Android源码中一个颜色矩阵类,通过对这个类的一系列操作,可以控制改变图片的色调明暗饱和度等,这也就是图片处理软件实现滤镜效果的原理。这个类把颜色定义为一个4*5的矩阵,如果用一个一纬数组表示就是这样:
[ a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t ]。

/** 
*  4x5 matrix for transforming the color+alpha components of a Bitmap. 
*  The matrix is stored in a single array, and its treated as follows: 
*  [ a, b, c, d, e, 
*    f, g, h, i, j, 
*    k, l, m, n, o,
*    p, q, r, s, t ] 
* * When applied to a color [r, g, b, a], the resulting color is computed as * (after clamping) 
*   R' = a*R + b*G + c*B + d*A + e; 
*   G' = f*R + g*G + h*B + i*A + j; 
*   B' = k*R + l*G + m*B + n*A + o; 
*   A' = p*R + q*G + r*B + s*A + t; 
*/

这里是源码里的注释,已经解释的很清楚了,RGBA的运算公式也清晰明了,所以实际调用过程中,我们可以通过传入需要的参数来控制RGBA的值,进而改变图片的色彩。

/** 
* Set this colormatrix to identity: 
* [ 1 0 0 0 0   - red vector 
*   0 1 0 0 0   - green vector
*   0 0 1 0 0   - blue vector 
*   0 0 0 1 0 ] - alpha vector 
*/

这里是一张图片的默认色彩属性值,我们只需要根据需求去调校各参数值,就能实现图片的滤镜效果了。再回到最开始的诉求,我是想通过程序实现单张图片的点击效果,但是设计师只提供了一张图,那么我只需要在手指按下的时候去给当前图片加个滤镜,抬起时再移除即可。简单粗暴点,直接上代码。

/**
 * Created by yx on 16/4/3.
 */
public class DiscolorImageView extends ImageView{


    /**
     * 变暗
     */
    private final float[] SELECTED_DARK = new float[]
            {1, 0, 0, 0, -80,
            0, 1, 0, 0, -80,
            0, 0, 1, 0, -80,
            0, 0, 0, 1, 0};
    /**
     * 变亮
     */

    private final float[] SELECTED_BRIGHT = new float[]
            {1, 0, 0, 0, 80,
                    0, 1, 0, 0, 80,
                    0, 0, 1, 0, 80,
                    0, 0, 0, 1, 0};

    /**
     * 高对比度
     */

    private final float[] SELECTED_HDR = new float[]
            {5, 0, 0, 0, -250,
                    0, 5, 0, 0, -250,
                    0, 0, 5, 0, -250,
                    0, 0, 0, 1, 0};

    /**
     * 高饱和度
     */
    private final float[] SELECTED_HSAT = new float[]
            {(float) 3, (float) -2, (float) -0.2, 0, 50,
                    -1, 2, -0, 0, 50,
                    -1, -2, 4, 0, 50,
                    0, 0, 0, 1, 0};

    /**
     * 改变色调
     */
    private final float[] SELECTED_DISCOLOR = new float[]
            {(float) -0.5, (float) -0.6, (float) -0.8, 0, 0,
                    (float) -0.4, (float) -0.6, (float) -0.1, 0, 0,
                    (float) -0.3, 2, (float) -0.4, 0, 0,
                    0, 0, 0, 1, 0};

    public DiscolorImageView(Context context) {
        super(context);
        this.setOnTouchListener(VIEW_TOUCH_DISCOLOR);
    }

    public DiscolorImageView(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.setOnTouchListener(VIEW_TOUCH_DISCOLOR);
    }

    public DiscolorImageView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        this.setOnTouchListener(VIEW_TOUCH_DISCOLOR);
    }

    public OnTouchListener VIEW_TOUCH_DISCOLOR = new OnTouchListener() {


        @Override
        public boolean onTouch(View v, MotionEvent event) {
            if (event.getAction() == MotionEvent.ACTION_DOWN) {
                ImageView iv = (ImageView) v;
                iv.setColorFilter(new ColorMatrixColorFilter(SELECTED_HDR));
              //iv.setColorFilter(new ColorMatrixColorFilter(SELECTED_BRIGHT));
              //iv.setColorFilter(new ColorMatrixColorFilter(SELECTED_HDR));
              //iv.setColorFilter(new ColorMatrixColorFilter(SELECTED_HSAT));
              //iv.setColorFilter(new ColorMatrixColorFilter(SELECTED_DISCOLOR));
            } else if (event.getAction() == MotionEvent.ACTION_UP) {
                ImageView iv = (ImageView) v;
                iv.clearColorFilter();
                mPerformClick();
            } else if (event.getAction() == MotionEvent.ACTION_CANCEL) {
                ImageView iv = (ImageView) v;
                iv.clearColorFilter();
            }
            return true;

        }
    };

        private void mPerformClick() {
            DiscolorImageView.this.performClick();
        }
    }

我这里随便给出了几个滤镜效果的参数值,但是未经调教,有可能效果一塌糊涂,基本原理很简单了,又要说到onTouch事件了,按下去的时候显示滤镜效果图,抬起时移除滤镜显示原图,这样点击的时候就有了一个动态的selector效果了。如下图:

device-2016-04-06-004225.gif device-2016-04-06-004356.gif device-2016-04-06-004437.gif
参考资料:
http://blog.sina.com.cn/s/blog_5da93c8f01012pkj.htm
http://my.oschina.net/gavinjin/blog/208586

相关文章

  • Camera2 教程 3:实现简单相机预览

    在 相机滤镜2:图片动态切换滤镜章节,我们实现了通过OPENGL ES实现图片显示和简单滤镜效果;本章节,将复用上...

  • OpenGLES入门(六)

    本章实现了简单的图片组合滤镜效果,可以调整图片的饱和度和色温。 实现滤镜效果的主要是思路就两步: 1.将图片原始纹...

  • 实现图片的滤镜效果

    提到这个到不是因为要做照片处理软件的滤镜效果,而是开发过程中设计师每每只提供一张icon图标,然后说点击效果你自己...

  • OpenGL ES GLSL 马赛克

    通过使用GLSL语言我们可以实现图片滤镜的各种效果。当然想要实现一些酷炫的滤镜效果,你需要有强大的数学能力。马赛克...

  • Java实现图片的滤镜效果

    滤镜 滤镜;主要是用来实现图像的各种特殊效果。它在Photoshop中具有非常神奇的作用。滤镜通常需要同通道、图层...

  •  iOS 使用GPUImage实现滤镜效果

    GPUImage实现滤镜效果 GPUImage是一个开源的图像处理第三方库,提供了100多种滤镜效果来加工处理图片...

  • OpenGL ES 入门之旅--灰度,旋涡,马赛克滤镜

    前情提要 这篇滤镜效果的实现是在上一篇分屏滤镜的基础上来进行实现的,同样的前提是可以利用GLSL加载一张正常的图片...

  • iOS 图片模糊效果

    1.使用CoreImage中的模糊滤镜原始效果图如下:这里写图片描述 CoreImage的实现: UIImage ...

  • 滤镜下的朋友圈

    滤镜,照相机功能专业名词,主要作来实现图片的各种特殊效果。现在手机所拥有的滤镜功能,更是强大,随手一拍,便...

  • 2020-05-18

    CIFilter 实现滤镜效果 ,苹果给我们提供了将近200中滤镜效果,具体苹果官网及展示效果 CIFilter苹...

网友评论

本文标题:实现图片的滤镜效果

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