Android开发探索Android技术知识Android开发

StyleImageView简析

2016-11-10  本文已影响0人  EchoZhou

轮子地址:https://github.com/chengdazhi/StyleImageView

简介

这是程大治同学写的一个用于操作ImageView,View Background,Drawable和Bitmap的Android图像处理类开源库,可以调节图片的亮度对比度,并有预设的多种滤镜效果可供使用。本文将对其Demo中的使用方法做简单的分析和介绍,下文提到的所有代码均来自于styler_test这个模块。


代码示例如下:

image = (ImageView) findViewById(R.id.image);
styler = newStyler.Builder(image,Styler.Mode.NONE).build();
styler.setMode(Styler.Mode.BLACK_AND_WHITE).updateStyle();

简单来说,就是先创建一个ImageView,再通过Styler的Builder创建Styler对象,最后调用 styler 的各个方法( setSaturation,setContrast,setMode,setSaturation 等)并 updateStyle,就可以实现ImageView的各种不同效果。上述示例中将Styler设置为 BLACK_AND_WHITE 模式,便可以将图片转为黑白效果。

效果实现原理

让我们通过 Styler.updateStyle() 作为切入点反推整个实现效果的流程。其实现代码如下:

    public void updateStyle() {
        if (drawableHolder.getDrawable() == null) {
            return;
        }
        final float[] matrix = calculateMatrix(mode, brightness, contrast, saturation);
        if (enableAnimation) {
            animateMatrix(oldMatrix, matrix, new AnimatorListenerAdapter() {
                @Override
                public void onAnimationEnd(Animator animation) {
                    super.onAnimationEnd(animation);
                    setDrawableStyleByMatrix(matrix);
                }
            });
        } else {
            setDrawableStyleByMatrix(matrix);
        }
    }

先忽略动画效果的实现,则这个方法只做了两件事:调用了 calculateMatrixsetDrawableStyleByMatrix 这两个方法。通过名字上来看后者应该和产生效果直接相关(名字中带有Drawable),而且前者的返回值也只是作为他的参数使用,所以我们先来看看 setDrawableStyleByMatrix 的实现。

    private void setDrawableStyleByMatrix(float[] matrix) {
        if (drawableHolder.getDrawable() == null) {
            return;
        }
        drawableHolder.getDrawable().setColorFilter(new ColorMatrixColorFilter(new ColorMatrix(matrix)));
        oldMatrix = matrix.clone();
    }

可见这里调用了 DrawablesetColorFilter 方法,可见各种图像处理效果都是在这里实现的。setColorFilterDrawable 类的一个方法,他可以通过输入一个颜色变换矩阵,来实现 Drawable 的各种颜色转换。这篇博文详细讲述了 ColorFilter 的原理。
于是可知各种不同的效果来自与不同的输入 matrix ,如何计算生成这一参数就成了实现效果的关键。回过头来看先前 calculateMatrix 方法的实现。

    private static float[] calculateMatrix(int mode, int brightness, float contrast, float saturation) {
        return applyBrightnessAndContrast(getMatrixByMode(mode, saturation), brightness, contrast);
    }

    private static float[] applyBrightnessAndContrast(float[] matrix, int brightness, float contrast) {
        float t = (1.0F - contrast) / 2.0F * 255.0F;
        for (int i = 0; i < 3; i++) {
            for (int j = i * 5; j < i * 5 + 3; j++) {
                matrix[j] *= contrast;
            }
            matrix[5 * i + 4] += t + brightness;
        }
        return matrix;
    }

首先通过 getMatrixByMode 方法获取各种模式下的初始颜色转换矩阵,然后在算上亮度和对比度,便计算出了最后的矩阵。关于颜色转换矩阵的概念,上文给出的博文链接中也有详细的介绍。至于初始矩阵是怎么来的,我就不得而知了,可能是有生成效果的工具,或者是网上有现成的数据。
到此效果实现的基本原理也已经基本介绍完毕,动画的实现原理其实也并不复杂,就是通过起始状态的颜色矩阵和最终状态的颜色矩阵用插值器计算出每一帧过渡用的颜色矩阵,读者可自行阅读源码体会。

小结

StyleImageView 这个库活用了 DrawablesetColorFilter 方法,通过配置各种效果的颜色变换矩阵和两个矩阵之间的插值计算,实现了多种图片处理效果和流畅的过渡动画。
他的原理并不复杂,代码写的也清晰简洁,实现的效果却非常惊艳,并且调用集成非常方便,读来确实是一种享受。

PS:

是的,这是本人第一次正式阅读他人的开源代码,真的被程大治同学清晰的代码所吸引。“好码如文档,不言自明。”如果你和我一样,每天面对着自己写的乱成一团的业务逻辑代码,那就会明白我并没有收轮子作者的5毛。(发帖后24小时内到帐,括号里的内容不要发)

上一篇下一篇

猜你喜欢

热点阅读