java實現圖片濾鏡的高級玩法
cv4j是一個圖像處理庫
目前,cv4j 已經支持了十幾種濾鏡的效果,并優化了之前的算法,除此之外我們還使用了 Rxjava2 來封裝濾鏡的操作。
多種濾鏡的支持.png
組合濾鏡
濾鏡最初的設計是一個裝飾器模式,借鑒了java的io包。
import com.cv4j.core.datamodel.ImageData;
/**
- Created by gloomy fish on 2017/3/5.
*/
public interface CommonFilter {
ImageData filter(ImageData imagedata);
}</code></pre>
如果要組合兩個濾鏡使用,必須采用形如下面的寫法:
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);
}
}</code></pre>

組合濾鏡.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());
}
};
}
}</code></pre>
具體使用如下:
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());
}
});</code></pre>

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

粉色風格的MM.png
上面的效果圖片是使用ColorFilter來實現的,ColorFilter已經支持多達12種顏色的風格。
總結
cv4j 是 賈志剛 和我一起開發的圖像處理庫,目前還處于很早期的版本。這周,我們除了新增一些濾鏡和優化算法之外,還增加了對 Rxjava2 的支持哦。未來,我們還會繼續增加一些濾鏡功能。在做完常見的濾鏡之后,我們會開始做空間卷積功能(圖片增強、銳化、模糊等等)。
來自:http://www.jianshu.com/p/f0ebe183c2cc