Java实现图片的滤镜效果

作者: fengzhizi715 | 来源:发表于2017-03-08 14:50 被阅读1164次

    滤镜

    滤镜;主要是用来实现图像的各种特殊效果。它在Photoshop中具有非常神奇的作用。滤镜通常需要同通道图层等联合使用,才能取得最佳艺术效果。

    在移动端或者在web开发时处理图片都是一件麻烦的事儿。我调研过很多library,特别是在移动端处理图片时动不动都需要使用 C++ 或者 OpenCV。这对于 Java 程序员来说,具有很高的门槛。甚至在调试时,遇到错误都会无法下手进行处理。其实,随着手机设备性能的不断提高,使用 Java 同样能完成这些事情。

    实现

    这是原图,可以选择滤镜来美化图片。


    原图.png

    这是几种滤镜的效果


    滤镜效果.jpg

    首先,我们的库叫 cv4j,cv 是 Computer Vision 的意思,同时也用于致敬 OpenCV。
    https://github.com/imageprocessor/cv4j

    以SepiaTone滤镜为例,我们自己私下叫它怀旧风格的滤镜

    SepiaTone.png
    import com.cv4j.core.datamodel.ImageData;
    import com.cv4j.image.util.Tools;
    
    public class SepiaToneFilter implements CommonFilter {
    
        @Override
        public ImageData filter(ImageData src) {
            int width = src.getWidth();
            int height = src.getHeight();
    
            int offset = 0;
            for(int row=0; row<height; row++) {
                offset = row * width;
                int tr = 0, tg = 0, tb = 0;
                for (int col = 0; col < width; col++) {
                    tr = (src.getPixels()[offset] >> 16) & 0xff;
                    tg = (src.getPixels()[offset] >> 8) & 0xff;
                    tb = src.getPixels()[offset] & 0xff;
                    int fr = (int) colorBlend(noise(), (tr * 0.393) + (tg * 0.769) + (tb * 0.189), tr);
                    int fg = (int) colorBlend(noise(), (tr * 0.349) + (tg * 0.686) + (tb * 0.168), tg);
                    int fb = (int) colorBlend(noise(), (tr * 0.272) + (tg * 0.534) + (tb * 0.131), tb);
    
                    src.getPixels()[offset] = (255 << 24) | (Tools.clamp(fr) << 16) | (Tools.clamp(fg) << 8) | Tools.clamp(fb);
                    offset++;
                }
            }
            return src;
        }
        
        private double noise() {
            return Math.random()*0.5 + 0.5;
        }
        
        private double colorBlend(double scale, double dest, double src) {
            return (scale * dest + (1.0 - scale) * src);
        }
    }
    

    ImageData是我们自己定义的图像数据结构。所有的滤镜都是通过ImageData来传递。

    import android.graphics.Bitmap;
    
    public interface ImageData {
    
        int CV4J_IMAGE_TYPE_RGB = 0;
        int CV4J_IMAGE_TYPE_GRAY = 2;
        int CV4J_IMAGE_TYPE_HSV = 4;
        int CV4J_IMAGE_TYPE_BINARY = 8;
    
        int[] getPixels();
    
        int getWidth();
    
        int getHeight();
    
        int getType();
    
        byte[] getChannel(int index);
    
        void putPixels(int[] pixels);
    
        int getPixel(int row, int col);
    
        void setPixel(int row, int col, int rgb);
    
        int[] getPixelByRowNumber(int rowIndex);
    
        void convert2Gray();
    
        Bitmap toBitmap();
    }
    

    ImageData是一个接口,目前它的实现类只有ColorImage。
    所以使用一个滤镜,通常只要这样写的就ok了。

    ColorImage colorImage = new ColorImage(bitmap);
    CommonFilter filter = new SepiaToneFilter();
    colorImage = (ColorImage) filter.filter(colorImage);
    imageView.setImageBitmap(colorImage.toBitmap());
    

    性能是我们一直关心的话题,我在模拟器上跑了demo app,通过 AOP 的方法打印了 demo app 中一些滤镜在使用时花费的时间。


    滤镜花费的时间.jpeg

    在demo app中,滤镜实例化是借助Class.forName()肯定比直接使用new 某个滤镜类要慢一些。


    滤镜实例化使用Class.forName.jpeg

    总结

    cv4j 是贾志刚和我一起开发的图像处理库,目前还处于很早期的版本。我们每天都会对这个库做一些提交。整个库在架构上和图像算法上都还有很大的提升空间。

    相关文章

      网友评论

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

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