Java实现图片滤镜的高级玩法

简介: Java实现图片滤镜的高级玩法

cv4j是一个图像处理库



github 地址:https://github.com/imageprocessor/cv4j


具体介绍,可以参考上一篇文章java实现图片的滤镜效果


目前,cv4j 已经支持了十几种滤镜的效果,并优化了之前的算法,除此之外我们还使用了 Rxjava2 来封装滤镜的操作。


image.png

多种滤镜的支持.png


组合滤镜



滤镜最初的设计是一个装饰器模式,借鉴了java的io包。

import com.cv4j.core.datamodel.ImageData;
/**
 * Created by gloomy fish on 2017/3/5.
 */
public interface CommonFilter {
    ImageData filter(ImageData imagedata);
}


如果要组合两个滤镜使用,必须采用形如下面的写法:

NatureFilter filter1 = new NatureFilter();
        ImageData imageData = filter1.filter(new ColorImage(bitmap));
        SpotlightFilter filter2 = new SpotlightFilter();
        Bitmap newBitmap = filter2.filter(imageData).toBitmap();
        image.setImageBitmap(newBitmap);


通过一个滤镜生成ImageData对象,将此对象再传入另一个滤镜,然后转换成bitmap。虽然这种写法没有问题,但是仍然感觉不爽,没有使用链式调用。因此,我写了CompositeFilters来简化多个滤镜的操作,它借助递归的思想实现组合多个滤镜。

import com.cv4j.core.datamodel.ImageData;
import java.util.ArrayList;
import java.util.List;
/**
 * 组合使用多个滤镜
 * Created by Tony Shen on 2017/3/11.
 */
public class CompositeFilters {
    List<CommonFilter> lists;
    public CompositeFilters() {
        lists = new ArrayList<>();
    }
    public CompositeFilters addFilter(CommonFilter filter) {
        lists.add(filter);
        return this;
    }
    public ImageData filter(ImageData imageData) {
        if (lists!=null && lists.size()>0) {
            return filter(imageData,lists.size());
        }
        return imageData;
    }
    private ImageData filter(ImageData imageData,int size) {
        if (size==1) {
            CommonFilter filter = lists.get(0);
            return filter.filter(imageData);
        }
        CommonFilter filter = lists.get(size-1);
        imageData = filter.filter(imageData);
        return filter(imageData,size-1);
    }
}


image.png

组合滤镜.png


使用Rxjava2来玩转滤镜



Rxjava2 出来有一段时间了,平时我喜欢用 Rxjava 来做一些封装。Rxjava2 还没有玩过,这次我就用滤镜来尝鲜了。


RxImageData是我封装对滤镜操作的类。

import android.graphics.Bitmap;
import com.cv4j.core.datamodel.ColorImage;
import com.cv4j.core.datamodel.ImageData;
import com.cv4j.core.filters.CommonFilter;
import org.reactivestreams.Publisher;
import io.reactivex.Flowable;
import io.reactivex.FlowableTransformer;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.functions.Function;
import io.reactivex.schedulers.Schedulers;
/**
 * Created by Tony Shen on 2017/3/14.
 */
public class RxImageData {
    ColorImage colorImage;
    Flowable flowable;
    private RxImageData(Bitmap bitmap) {
        this.colorImage = new ColorImage(bitmap);
        flowable = Flowable.just(colorImage);
    }
    private RxImageData(ColorImage colorImage) {
        this.colorImage = colorImage;
        flowable = Flowable.just(colorImage);
    }
    public static RxImageData imageData(Bitmap bitmap) {
        return new RxImageData(bitmap);
    }
    public static RxImageData imageData(ColorImage colorImage) {
        return new RxImageData(colorImage);
    }
    public RxImageData addFilter(final CommonFilter filter) {
        flowable = flowable.map(new Function<ImageData,ImageData>() {
            @Override
            public ImageData apply(ImageData imageData) throws Exception {
                return filter.filter(imageData);
            }
        });
        return this;
    }
    public Flowable toFlowable() {
        return flowable;
    }
    public static <T> FlowableTransformer<T, T> toMain() {
        return new FlowableTransformer<T, T>() {
            @Override
            public Publisher<T> apply(Flowable<T> upstream) {
                return upstream.subscribeOn(Schedulers.io())
                        .observeOn(AndroidSchedulers.mainThread());
            }
        };
    }
}


具体使用如下:

RxImageData.imageData(bitmap)
                .addFilter(new NatureFilter())
                .toFlowable()
                .compose(RxImageData.toMain())
                .subscribe(new Consumer<ImageData>() {
            @Override
            public void accept(ImageData imageData) throws Exception {
                image.setImageBitmap(imageData.toBitmap());
            }
        });


image.png

借助rxjava2操作滤镜.png


如果想要使用组合滤镜,RxImageData可以不断地使用addFilter()方法来添加不同的滤镜。不得不说,Rxjava2 的性能非常出色。


色彩滤镜



image.png

粉色风格的MM.png


上面的效果图片是使用ColorFilter来实现的,ColorFilter已经支持多达12种颜色的风格。


总结



cv4j 是贾志刚和我一起开发的图像处理库,目前还处于很早期的版本。这周,我们除了新增一些滤镜和优化算法之外,还增加了对 Rxjava2 的支持哦。未来,我们还会继续增加一些滤镜功能。在做完常见的滤镜之后,我们会开始做空间卷积功能(图片增强、锐化、模糊等等)。

相关文章
|
19天前
|
Java
Java开发实现图片URL地址检验,如何编码?
【10月更文挑战第14天】Java开发实现图片URL地址检验,如何编码?
46 4
|
19天前
|
Java
Java开发实现图片地址检验,如果无法找到资源则使用默认图片,如何编码?
【10月更文挑战第14天】Java开发实现图片地址检验,如果无法找到资源则使用默认图片,如何编码?
49 2
|
26天前
|
算法 Java Linux
java制作海报二:java使用Graphics2D 在图片上合成另一个照片,并将照片切割成头像,头像切割成圆形方法详解
这篇文章介绍了如何使用Java的Graphics2D类在图片上合成另一个照片,并将照片切割成圆形头像的方法。
43 1
java制作海报二:java使用Graphics2D 在图片上合成另一个照片,并将照片切割成头像,头像切割成圆形方法详解
|
19天前
|
Java 数据安全/隐私保护
Java ffmpeg 实现视频加文字/图片水印功能
【10月更文挑战第22天】在 Java 中使用 FFmpeg 实现视频加文字或图片水印功能,需先安装 FFmpeg 并添加依赖(如 JavaCV)。通过构建 FFmpeg 命令行参数,使用 `drawtext` 滤镜添加文字水印,或使用 `overlay` 滤镜添加图片水印。示例代码展示了如何使用 JavaCV 实现文字水印。
|
25天前
|
前端开发 小程序 Java
java基础:map遍历使用;java使用 Patten 和Matches 进行正则匹配;后端传到前端展示图片三种情况,并保存到手机
这篇文章介绍了Java中Map的遍历方法、使用Pattern和matches进行正则表达式匹配,以及后端向前端传输图片并保存到手机的三种情况。
17 1
|
26天前
|
算法 Java Linux
java制作海报四:java BufferedImage 转 InputStream 上传至OSS。png 图片合成到模板(另一个图片)上时,透明部分变成了黑色
这篇文章主要介绍了如何将Java中的BufferedImage对象转换为InputStream以上传至OSS,并解决了png图片合成时透明部分变黑的问题。
45 1
|
26天前
|
算法 搜索推荐 Java
java 后端 使用 Graphics2D 制作海报,画echarts图,带工具类,各种细节:如头像切割成圆形,文字换行算法(完美实验success),解决画上文字、图片后不清晰问题
这篇文章介绍了如何使用Java后端技术,结合Graphics2D和Echarts等工具,生成包含个性化信息和图表的海报,并提供了详细的代码实现和GitHub项目链接。
91 0
java 后端 使用 Graphics2D 制作海报,画echarts图,带工具类,各种细节:如头像切割成圆形,文字换行算法(完美实验success),解决画上文字、图片后不清晰问题
|
2月前
|
Java
Java-FileInputStream和FileOutputStream的使用,txt文件及图片文件的拷贝
这篇文章介绍了Java中FileInputStream和FileOutputStream的使用,包括如何读取和写入txt文件以及如何拷贝图片文件。
Java-FileInputStream和FileOutputStream的使用,txt文件及图片文件的拷贝
|
2月前
|
存储 缓存 监控
Java——图片文件位于 bin 目录下,下载新图片会导致应用程序重启
【9月更文挑战第22天】在Java应用中,若图片位于bin目录下且下载新图片导致应用重启,可能是因为部署方式不当或资源监控机制过于敏感。解决方法包括:更改图片存储位置至独立目录;配置应用服务器减少资源监控敏感度;使用独立资源服务器托管静态资源;优化代码减少资源重复加载。具体方案需根据应用实际情况和技术栈调整。
|
26天前
|
算法 小程序 Java
java制作海报三:获取微信二维码详情,并改变大小,合成到海报(另一张图片)上
这篇文章介绍了如何使用Java获取微信小程序的二维码,并将其调整大小后合成到海报(另一张图片)上。
36 0