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 的支持哦。未来,我们还会继续增加一些滤镜功能。在做完常见的滤镜之后,我们会开始做空间卷积功能(图片增强、锐化、模糊等等)。

相关文章
|
16天前
|
存储 安全 Java
基于Java爬取微博数据(四) 获取 图片 or 视频
【5月更文挑战第14天】基于Java爬取微博数据(四) 图片 or 视频 下载
|
21天前
|
存储 Java 容器
Java一分钟之-高级集合框架:LinkedList与TreeSet
【5月更文挑战第17天】这篇博客对比了Java集合框架中的LinkedList和TreeSet。LinkedList是双向链表,适合中间插入删除,但遍历效率低且占用空间大;TreeSet基于红黑树,保证元素有序且不重复,插入删除速度较LinkedList慢但查找快。选择时需根据操作需求和性能考虑。
25 2
|
6天前
|
存储 Java 开发者
探索Java中的异常处理:从基础到高级
【6月更文挑战第1天】本文将深入探讨Java中的异常处理机制,从基本概念到高级应用。我们将通过实例和代码示例,详细解释如何捕获和处理异常,以及如何使用自定义异常来提高代码的健壮性和可读性。无论你是Java初学者还是有经验的开发者,这篇文章都将为你提供有价值的知识和技巧。
16 4
|
6天前
|
Java 开发者 UED
掌握Java多线程编程:从基础到高级
【5月更文挑战第31天】本文深入探讨了Java多线程编程的核心概念,包括线程的创建、生命周期、同步机制以及高级并发工具。通过实际示例和代码片段,读者将学会如何有效地管理和协调线程,以编写高效且稳定的并发应用程序。
|
17天前
|
存储 Java 容器
Java一分钟之-高级集合框架:LinkedList与TreeSet
【5月更文挑战第21天】本文对比了Java集合框架中的LinkedList和TreeSet。LinkedList是双向链表,实现List接口,适合中间插入删除,但遍历效率低;TreeSet基于红黑树,实现Set接口,保证元素有序且无重复,插入删除速度较LinkedList慢,但查找排序快。选择时应根据具体需求考虑操作频率和排序需求。
30 1
|
3天前
|
Java 测试技术 数据处理
Java一分钟之-TestNG:高级测试框架
【6月更文挑战第4天】TestNG是Java的高级测试框架,扩展了JUnit,支持数据驱动、参数化、测试分组、依赖和并行测试,提高自动化测试效率。本文介绍了TestNG的核心特性,如`@DataProvider`和`@Parameters`注解,以及常见问题和解决策略,如正确使用测试生命周期方法和处理数据驱动测试中的数据。通过示例展示了如何进行数据驱动测试,帮助读者更好地理解和应用TestNG。
23 0
Java一分钟之-TestNG:高级测试框架
|
8天前
|
文字识别 Java API
Java图片信息识别
【5月更文挑战第26天】Java图片信息识别
20 1
|
9天前
|
安全 Java 程序员
深入理解Java并发编程:从基础到高级深入理解操作系统中的进程调度策略
【5月更文挑战第29天】 Java并发编程是Java开发中不可忽视的一部分,它涉及到多线程、同步、锁等概念。本文将带你从Java并发编程的基础概念出发,逐步深入到高级应用,让你全面掌握Java并发编程的技巧。
|
11天前
|
存储 安全 Java
Java中的异常处理:从基础到高级网络安全与信息安全:防范漏洞与强化意识
【5月更文挑战第27天】本文主要探讨了Java中的异常处理机制,从基础的try-catch-finally结构,到高级的自定义异常和异常链。我们将深入理解异常的概念,学习如何有效地处理异常,以及如何使用异常来提高代码的可读性和可维护性。 【5月更文挑战第27天】随着信息技术的迅猛发展,网络已成为社会运行的重要基础。然而,伴随而来的网络安全威胁也日益增多,尤其是安全漏洞的出现和利用,严重威胁着个人、企业乃至国家的信息资产安全。本文旨在分享关于网络安全漏洞的识别与防护方法、加密技术的应用以及提升个人和企业的安全意识等方面的关键知识,以帮助读者构建更为坚固的网络安全防线。
|
14天前
|
Java 大数据 API
Java编程的魅力:深入探索与高级应用
Java,作为跨平台、面向对象的高级编程语言,以其安全性和高效API在企业级应用、大数据、云计算及物联网领域占有一席之地。本文探讨Java的魅力,包括其简洁语法、面向对象特性(如封装、继承、多态)、异常处理、泛型与集合框架的使用。通过实例展示了如何利用多线程和网络编程构建分布式系统,强调了Java在并发和网络通信中的实力。