专栏首页Java与Android技术栈Java实现图片的滤镜效果滤镜实现总结

Java实现图片的滤镜效果滤镜实现总结

滤镜

滤镜;主要是用来实现图像的各种特殊效果。它在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 是贾志刚和我一起开发的图像处理库,目前还处于很早期的版本。我们每天都会对这个库做一些提交。整个库在架构上和图像算法上都还有很大的提升空间。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 模拟油画和铅笔画的滤镜效果

    然后使用油画风格的滤镜OilPaintFilter看看效果,OilPaintFilter的使用方式就一句话:)

    fengzhizi715
  • App基于手机壳颜色换肤?先尝试一下用 KMeans 来提取图像中的主色

    上周,某公司的产品经理提了一个需求:根据用户手机壳颜色来改变 App 主题颜色。可能是由于这天马行空的需求激怒了程序员,导致程序员和产品经理打了起来,最后双双被...

    fengzhizi715
  • 基于边缘保留滤波实现人脸磨皮的算法

    快速边缘保留滤波是通过积分图像实现局部均方差的边缘保留模糊算法,计算简单而且可以做到计算量跟半径无关。 首先局部均方差滤波中计算局部均值的公式如下:

    fengzhizi715
  • 2015-偶数求和

    有一个长度为n(n<=100)的数列,该数列定义为从2开始的递增有序偶数,现在要求你按照顺序每m个数求出一个平均值,如果最后不足m个,则以实际数量求平均值。编程...

    用户2038589
  • 洛谷P1437 [HNOI2004]敲砖块(dp)

    在一个凹槽中放置了 n 层砖块、最上面的一层有n 块砖,从上到下每层依次减少一块砖。每块砖

    attack
  • 搜索专题

    POJ  Best Sequence http://poj.org/problem?id=1699 题意:给你n个字符窜,求其所能拼接的最短长度。 分析:预处理...

    用户1624346
  • 1061 判断题 (15 分)

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 ...

    韩旭051
  • 1072 开学寄语 (20 分)

    可爱见见
  • 05:Cave Cows 1 洞穴里的牛之一

    总时间限制: 10000ms单个测试点时间限制: 1000ms内存限制: 262144kB描述 很少人知道其实奶牛非常喜欢到洞穴里面去探险。     洞窟里有N...

    attack
  • CodeForces 1143A The Doors

    ShenduCC

扫码关注云+社区

领取腾讯云代金券