Java實現(xiàn)圖片濾鏡的高級玩法

cv4j是一個圖像處理庫

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

具體介紹,可以參考上一篇文章java實現(xiàn)圖片的濾鏡效果
目前,cv4j 已經(jīng)支持了十幾種濾鏡的效果,并優(yōu)化了之前的算法,除此之外我們還使用了 Rxjava2 來封裝濾鏡的操作。

多種濾鏡的支持.png

組合濾鏡

濾鏡最初的設(shè)計是一個裝飾器模式,借鑒了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對象,將此對象再傳入另一個濾鏡,然后轉(zhuǎn)換成bitmap。雖然這種寫法沒有問題,但是仍然感覺不爽,沒有使用鏈?zhǔn)秸{(diào)用。因此,我寫了CompositeFilters來簡化多個濾鏡的操作,它借助遞歸的思想實現(xiàn)組合多個濾鏡。

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);
    }

}
組合濾鏡.png

使用Rxjava2來玩轉(zhuǎn)濾鏡

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());
            }
        });
借助rxjava2操作濾鏡.png

如果想要使用組合濾鏡,RxImageData可以不斷地使用addFilter()方法來添加不同的濾鏡。不得不說,Rxjava2 的性能非常出色。

色彩濾鏡

粉色風(fēng)格的MM.png

上面的效果圖片是使用ColorFilter來實現(xiàn)的,ColorFilter已經(jīng)支持多達(dá)12種顏色的風(fēng)格。

總結(jié)

cv4j 是賈志剛和我一起開發(fā)的圖像處理庫,目前還處于很早期的版本。這周,我們除了新增一些濾鏡和優(yōu)化算法之外,還增加了對 Rxjava2 的支持哦。未來,我們還會繼續(xù)增加一些濾鏡功能。在做完常見的濾鏡之后,我們會開始做空間卷積功能(圖片增強、銳化、模糊等等)。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 173,268評論 25 708
  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫、插件、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 12,229評論 4 61
  • 今天看到了一篇文章有保留價值,存檔于我自己的文集中: 契約精神的一點啟示 (2017-08-31 11:09:15...
    明潔閱讀 878評論 0 1
  • 啊啊啊啊!我要瘋了!!!!媽逼的不想學(xué)習(xí)!!!!!!!!
    你再也不是我心中的你了閱讀 181評論 0 0
  • jQuery 能做什么? jQuery是一款快速而簡潔的javascript的庫,核心是構(gòu)建與css選擇器上,用來...
    YM雨蒙閱讀 246評論 0 0