Android建筑圖像過濾器,如Instagram(2)

14。打開FiltersListFragment.java并進行如下所示的修改。這里

>?FilterPack.getFilterPack()提供庫中可用過濾器的列表。

>prepareThumbnail()方法中,過濾器被填充,并且每個縮略圖項目都被添加到ThumbnailsManager以處理它們。處理后的縮略圖將添加回thumbnailItemList,后者是RecyclerView的數(shù)據(jù)資源。

>縮略圖數(shù)據(jù)集準備就緒后,調(diào)用mAdapter.notifyDataSetChanged()來渲染列表。所有這些都是在后臺線程中完成的,因為圖像處理需要一段時間,我們不應該阻止主線程。

>每當選擇新過濾器時,FiltersListFragmentListener接口都會為主活動提供回調(diào)方法。

>?MainActivity中將對所選圖像過濾器的實際處理進行處理。

FiltersListFragment.java

packageinfo.androidhive.imagefilters;

importandroid.graphics.Bitmap;

importandroid.os.Bundle;

importandroid.support.v4.app.Fragment;

importandroid.support.v7.widget.DefaultItemAnimator;

importandroid.support.v7.widget.LinearLayoutManager;

importandroid.support.v7.widget.RecyclerView;

importandroid.util.Log;

importandroid.util.TypedValue;

importandroid.view.LayoutInflater;

importandroid.view.View;

importandroid.view.ViewGroup;

importcom.zomato.photofilters.FilterPack;

importcom.zomato.photofilters.imageprocessors.Filter;

importcom.zomato.photofilters.utils.ThumbnailItem;

importcom.zomato.photofilters.utils.ThumbnailsManager;

importjava.util.ArrayList;

importjava.util.HashMap;

importjava.util.List;

importjava.util.Map;

importbutterknife.BindView;

importbutterknife.ButterKnife;

importinfo.androidhive.imagefilters.utils.BitmapUtils;

importinfo.androidhive.imagefilters.utils.SpacesItemDecoration;

publicclassFiltersListFragment extendsFragment implementsThumbnailsAdapter.ThumbnailsAdapterListener {

????@BindView(R.id.recycler_view)

????RecyclerView recyclerView;

????ThumbnailsAdapter mAdapter;

????List thumbnailItemList;

????FiltersListFragmentListener listener;

????publicvoidsetListener(FiltersListFragmentListener listener) {

????????this.listener = listener;

????}

????publicFiltersListFragment() {

????????// Required empty public constructor

????}

????@Override

????publicvoidonCreate(Bundle savedInstanceState) {

????????super.onCreate(savedInstanceState);

????}

????@Override

????publicView onCreateView(LayoutInflater inflater, ViewGroup container,

?????????????????????????????Bundle savedInstanceState) {

????????// Inflate the layout for this fragment

????????View view = inflater.inflate(R.layout.fragment_filters_list, container, false);

????????ButterKnife.bind(this, view);

????????thumbnailItemList = newArrayList<>();

????????mAdapter = newThumbnailsAdapter(getActivity(), thumbnailItemList, this);

????????RecyclerView.LayoutManager mLayoutManager = newLinearLayoutManager(getActivity(), LinearLayoutManager.HORIZONTAL, false);

????????recyclerView.setLayoutManager(mLayoutManager);

????????recyclerView.setItemAnimator(newDefaultItemAnimator());

????????intspace = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 8,

????????????????getResources().getDisplayMetrics());

????????recyclerView.addItemDecoration(newSpacesItemDecoration(space));

????????recyclerView.setAdapter(mAdapter);

????????prepareThumbnail(null);

????????returnview;

????}

????/**

?????* Renders thumbnails in horizontal list

?????* loads default image from Assets if passed param is null

?????*

?????* @param bitmap

?????*/

????publicvoidprepareThumbnail(finalBitmap bitmap) {

????????Runnable r = newRunnable() {

????????????publicvoidrun() {

????????????????Bitmap thumbImage;

????????????????if(bitmap == null) {

????????????????????thumbImage = BitmapUtils.getBitmapFromAssets(getActivity(), MainActivity.IMAGE_NAME, 100, 100);

????????????????} else{

????????????????????thumbImage = Bitmap.createScaledBitmap(bitmap, 100, 100, false);

????????????????}

????????????????if(thumbImage == null)

????????????????????return;

????????????????ThumbnailsManager.clearThumbs();

????????????????thumbnailItemList.clear();

????????????????// add normal bitmap first

????????????????ThumbnailItem thumbnailItem = newThumbnailItem();

????????????????thumbnailItem.image = thumbImage;

????????????????thumbnailItem.filterName = getString(R.string.filter_normal);

????????????????ThumbnailsManager.addThumb(thumbnailItem);

????????????????List filters = FilterPack.getFilterPack(getActivity());

????????????????for(Filter filter : filters) {

????????????????????ThumbnailItem tI = newThumbnailItem();

????????????????????tI.image = thumbImage;

????????????????????tI.filter = filter;

????????????????????tI.filterName = filter.getName();

????????????????????ThumbnailsManager.addThumb(tI);

????????????????}

????????????????thumbnailItemList.addAll(ThumbnailsManager.processThumbs(getActivity()));

????????????????getActivity().runOnUiThread(newRunnable() {

????????????????????@Override

????????????????????publicvoidrun() {

????????????????????????mAdapter.notifyDataSetChanged();

????????????????????}

????????????????});

????????????}

????????};

????????newThread(r).start();

????}

????@Override

????publicvoidonFilterSelected(Filter filter) {

????????if(listener != null)

????????????listener.onFilterSelected(filter);

????}

????publicinterfaceFiltersListFragmentListener {

????????voidonFilterSelected(Filter filter);

????}

}

7.添加圖像編輯控件片段

現(xiàn)在我們將添加圖像控件片段來控制亮度,對比度飽和度。

15。按照與上一步相同的步驟再創(chuàng)建一個名為EditImageFragment.java的片段。打開此片段fragment_edit_image.xml的布局文件,并執(zhí)行如下修改。

在這個布局中,我們將添加三個SeekBar小部件來控制圖像亮度,對比度和飽和度。

fragment_edit_image.xml

http://schemas.android.com/apk/res/android"

xmlns:tools="http://schemas.android.com/tools"

????android:layout_width="match_parent"

????android:layout_height="match_parent"

????android:gravity="center_vertical"

????android:orientation="vertical"

????android:paddingLeft="@dimen/margin_horizontal"

????android:paddingRight="@dimen/margin_horizontal"

????tools:context="info.androidhive.imagefilters.EditImageFragment">

????????android:layout_width="match_parent"

????????android:layout_height="wrap_content"

????????android:orientation="horizontal"

????????android:paddingBottom="@dimen/padding_10"

????????android:paddingTop="@dimen/padding_10">

????????????android:layout_width="@dimen/lbl_edit_image_control"

????????????android:layout_height="wrap_content"

????????????android:text="@string/lbl_brightness"/>

????????????android:id="@+id/seekbar_brightness"

????????????android:layout_width="0dp"

????????????android:layout_height="wrap_content"

????????????android:layout_weight="1"/>

????????android:layout_width="match_parent"

????????android:layout_height="wrap_content"

????????android:orientation="horizontal"

????????android:paddingBottom="@dimen/padding_10"

????????android:paddingTop="@dimen/padding_10">

????????????android:layout_width="@dimen/lbl_edit_image_control"

????????????android:layout_height="wrap_content"

????????????android:text="@string/lbl_contrast"/>

????????????android:id="@+id/seekbar_contrast"

????????????android:layout_width="0dp"

????????????android:layout_height="wrap_content"

????????????android:layout_weight="1"/>

????????android:layout_width="match_parent"

????????android:layout_height="wrap_content"

????????android:orientation="horizontal"

????????android:paddingBottom="@dimen/padding_10"

????????android:paddingTop="@dimen/padding_10">

????????????android:layout_width="@dimen/lbl_edit_image_control"

????????????android:layout_height="wrap_content"

????????????android:text="@string/lbl_saturation"/>

????????????android:id="@+id/seekbar_saturation"

????????????android:layout_width="0dp"

????????????android:layout_height="wrap_content"

????????????android:layout_weight="1"/>

16。打開EditImageFragment.java并進行如下修改。

>onCreateView方法中,Seekbar小部件使用初始值和最大值進行初始化。對于亮度,值可以在-100 / +100之間。在對比度飽和度采取浮動值。

>每當Seekbar值發(fā)生更改時,EditImageFragmentListener接口都會提供回調(diào)方法。

>在回調(diào)時,MainActivity再次處理亮度,對比度飽和度

EditImageFragment.java

packageinfo.androidhive.imagefilters;

importandroid.os.Bundle;

importandroid.support.v4.app.Fragment;

importandroid.util.Log;

importandroid.view.LayoutInflater;

importandroid.view.View;

importandroid.view.ViewGroup;

importandroid.widget.SeekBar;

importbutterknife.BindView;

importbutterknife.ButterKnife;

publicclassEditImageFragment extendsFragment implementsSeekBar.OnSeekBarChangeListener {

????privateEditImageFragmentListener listener;

????@BindView(R.id.seekbar_brightness)

????SeekBar seekBarBrightness;

????@BindView(R.id.seekbar_contrast)

????SeekBar seekBarContrast;

????@BindView(R.id.seekbar_saturation)

????SeekBar seekBarSaturation;

????publicvoidsetListener(EditImageFragmentListener listener) {

????????this.listener = listener;

????}

????publicEditImageFragment() {

????????// Required empty public constructor

????}

????@Override

????publicvoidonCreate(Bundle savedInstanceState) {

????????super.onCreate(savedInstanceState);

????}

????@Override

????publicView onCreateView(LayoutInflater inflater, ViewGroup container,

?????????????????????????????Bundle savedInstanceState) {

????????View view = inflater.inflate(R.layout.fragment_edit_image, container, false);

????????ButterKnife.bind(this, view);

????????// keeping brightness value b/w -100 / +100

????????seekBarBrightness.setMax(200);

????????seekBarBrightness.setProgress(100);

????????// keeping contrast value b/w 1.0 - 3.0

????????seekBarContrast.setMax(20);

????????seekBarContrast.setProgress(0);

????????// keeping saturation value b/w 0.0 - 3.0

????????seekBarSaturation.setMax(30);

????????seekBarSaturation.setProgress(10);

????????seekBarBrightness.setOnSeekBarChangeListener(this);

????????seekBarContrast.setOnSeekBarChangeListener(this);

????????seekBarSaturation.setOnSeekBarChangeListener(this);

????????returnview;

????}

????@Override

????publicvoidonProgressChanged(SeekBar seekBar, intprogress, booleanb) {

????????if(listener != null) {

????????????if(seekBar.getId() == R.id.seekbar_brightness) {

????????????????// brightness values are b/w -100 to +100

????????????????listener.onBrightnessChanged(progress - 100);

????????????}

????????????if(seekBar.getId() == R.id.seekbar_contrast) {

????????????????// converting int value to float

????????????????// contrast values are b/w 1.0f - 3.0f

????????????????// progress = progress > 10 ? progress : 10;

????????????????progress += 10;

????????????????floatfloatVal = .10f * progress;

????????????????listener.onContrastChanged(floatVal);

????????????}

????????????if(seekBar.getId() == R.id.seekbar_saturation) {

????????????????// converting int value to float

????????????????// saturation values are b/w 0.0f - 3.0f

????????????????floatfloatVal = .10f * progress;

????????????????listener.onSaturationChanged(floatVal);

????????????}

????????}

????}

????@Override

????publicvoidonStartTrackingTouch(SeekBar seekBar) {

????????if(listener != null)

????????????listener.onEditStarted();

????}

????@Override

????publicvoidonStopTrackingTouch(SeekBar seekBar) {

????????if(listener != null)

????????????listener.onEditCompleted();

????}

????publicvoidresetControls() {

????????seekBarBrightness.setProgress(100);

????????seekBarContrast.setProgress(0);

????????seekBarSaturation.setProgress(10);

????}

????publicinterfaceEditImageFragmentListener {

????????voidonBrightnessChanged(intbrightness);

????????voidonSaturationChanged(floatsaturation);

????????voidonContrastChanged(floatcontrast);

????????voidonEditStarted();

????????voidonEditCompleted();

????}

}

8.實現(xiàn)主界面(組合片段)

現(xiàn)在我們準備好了片段,讓我們看看如何將它們組合起來以實現(xiàn)我們的最終輸出。

17。打開主活動activity_main.xmlcontent_main.xml以及NonSwipeableViewPagerTabLayout的布局文件。

activity_main.xml中

http://schemas.android.com/apk/res/android"

xmlns:app="http://schemas.android.com/apk/res-auto"

xmlns:tools="http://schemas.android.com/tools"

????android:layout_width="match_parent"

????android:layout_height="match_parent"

????tools:context="info.androidhive.imagefilters.MainActivity">

????????android:layout_width="match_parent"

????????android:layout_height="wrap_content"

????????android:theme="@style/AppTheme.AppBarOverlay">

????????????android:id="@+id/toolbar"

????????????android:layout_width="match_parent"

????????????android:layout_height="?attr/actionBarSize"

????????????android:background="@android:color/white"

????????????app:popupTheme="@style/AppTheme.PopupOverlay"/>

content_main.xml

http://schemas.android.com/apk/res/android"

xmlns:app="http://schemas.android.com/apk/res-auto"

xmlns:tools="http://schemas.android.com/tools"

????android:layout_width="match_parent"

????android:layout_height="match_parent"

????android:background="@android:color/white"

????android:orientation="vertical"

????app:layout_behavior="@string/appbar_scrolling_view_behavior"

????tools:context="info.androidhive.imagefilters.MainActivity"

????tools:showIn="@layout/activity_main">

????????android:id="@+id/image_preview"

????????android:layout_width="match_parent"

????????android:layout_height="360dp"

????????android:scaleType="centerCrop"/>

????????android:id="@+id/viewpager"

????????android:layout_width="match_parent"

????????android:layout_height="120dp"

????????android:layout_above="@+id/tabs"

????????android:layout_below="@+id/image_preview"

????????app:layout_behavior="@string/appbar_scrolling_view_behavior"/>

????????android:id="@+id/tabs"

????????android:layout_width="match_parent"

????????android:layout_height="wrap_content"

????????android:layout_alignParentBottom="true"

????????app:tabGravity="fill"

????????app:tabMode="fixed"/>

18。打開MainActivity.java并執(zhí)行如下所示的更改。

>調(diào)用System.loadLibrary(“NativeImageProcessor”)來初始化本機庫。

>?FiltersListFragmentEditImageFragments加到ViewPager在setupViewPager()方法。

>?onFilterSelected()當在被選擇的過濾器將被稱為FiltersListFragment。處理選定的過濾器,并顯示最終圖像imagePreview。

>?onBrightnessChanged(),onSaturationChanged()onContrastChanged()方法將在EditImageFragments中的Seekbar值更改時調(diào)用。

>從工具欄中選擇“保存”選項后,最終圖像將保存到圖庫。

MainActivity.java

packageinfo.androidhive.imagefilters;

importandroid.Manifest;

importandroid.content.Intent;

importandroid.graphics.Bitmap;

importandroid.net.Uri;

importandroid.os.Bundle;

importandroid.support.design.widget.CoordinatorLayout;

importandroid.support.design.widget.Snackbar;

importandroid.support.design.widget.TabLayout;

importandroid.support.v4.app.Fragment;

importandroid.support.v4.app.FragmentManager;

importandroid.support.v4.app.FragmentPagerAdapter;

importandroid.support.v4.view.ViewPager;

importandroid.support.v7.app.AppCompatActivity;

importandroid.support.v7.widget.Toolbar;

importandroid.text.TextUtils;

importandroid.util.Log;

importandroid.view.Menu;

importandroid.view.MenuItem;

importandroid.view.View;

importandroid.widget.ImageView;

importandroid.widget.Toast;

importcom.karumi.dexter.Dexter;

importcom.karumi.dexter.MultiplePermissionsReport;

importcom.karumi.dexter.PermissionToken;

importcom.karumi.dexter.listener.PermissionRequest;

importcom.karumi.dexter.listener.multi.MultiplePermissionsListener;

importcom.zomato.photofilters.imageprocessors.Filter;

importcom.zomato.photofilters.imageprocessors.subfilters.BrightnessSubFilter;

importcom.zomato.photofilters.imageprocessors.subfilters.ContrastSubFilter;

importcom.zomato.photofilters.imageprocessors.subfilters.SaturationSubfilter;

importjava.util.ArrayList;

importjava.util.List;

importbutterknife.BindView;

importbutterknife.ButterKnife;

importinfo.androidhive.imagefilters.utils.BitmapUtils;

publicclassMainActivity extendsAppCompatActivity implementsFiltersListFragment.FiltersListFragmentListener, EditImageFragment.EditImageFragmentListener {

????privatestaticfinalString TAG = MainActivity.class.getSimpleName();

????publicstaticfinalString IMAGE_NAME = "dog.jpg";

????publicstaticfinalintSELECT_GALLERY_IMAGE = 101;

????@BindView(R.id.image_preview)

????ImageView imagePreview;

????@BindView(R.id.tabs)

????TabLayout tabLayout;

????@BindView(R.id.viewpager)

????ViewPager viewPager;

????@BindView(R.id.coordinator_layout)

????CoordinatorLayout coordinatorLayout;

????Bitmap originalImage;

????// to backup image with filter applied

????Bitmap filteredImage;

????// the final image after applying

????// brightness, saturation, contrast

????Bitmap finalImage;

????FiltersListFragment filtersListFragment;

????EditImageFragment editImageFragment;

????// modified image values

????intbrightnessFinal = 0;

????floatsaturationFinal = 1.0f;

????floatcontrastFinal = 1.0f;

????// load native image filters library

????static{

????????System.loadLibrary("NativeImageProcessor");

????}

????@Override

????protectedvoidonCreate(Bundle savedInstanceState) {

????????super.onCreate(savedInstanceState);

????????setContentView(R.layout.activity_main);

????????ButterKnife.bind(this);

????????Toolbar toolbar = findViewById(R.id.toolbar);

????????setSupportActionBar(toolbar);

????????getSupportActionBar().setDisplayHomeAsUpEnabled(true);

????????getSupportActionBar().setTitle(getString(R.string.activity_title_main));

????????loadImage();

????????setupViewPager(viewPager);

????????tabLayout.setupWithViewPager(viewPager);

????}

????privatevoidsetupViewPager(ViewPager viewPager) {

????????ViewPagerAdapter adapter = newViewPagerAdapter(getSupportFragmentManager());

????????// adding filter list fragment

????????filtersListFragment = newFiltersListFragment();

????????filtersListFragment.setListener(this);

????????// adding edit image fragment

????????editImageFragment = newEditImageFragment();

????????editImageFragment.setListener(this);

????????adapter.addFragment(filtersListFragment, getString(R.string.tab_filters));

????????adapter.addFragment(editImageFragment, getString(R.string.tab_edit));

????????viewPager.setAdapter(adapter);

????}

????@Override

????publicvoidonFilterSelected(Filter filter) {

????????// reset image controls

????????resetControls();

????????// applying the selected filter

????????filteredImage = originalImage.copy(Bitmap.Config.ARGB_8888, true);

????????// preview filtered image

????????imagePreview.setImageBitmap(filter.processFilter(filteredImage));

????????finalImage = filteredImage.copy(Bitmap.Config.ARGB_8888, true);

????}

????@Override

????publicvoidonBrightnessChanged(finalintbrightness) {

????????brightnessFinal = brightness;

????????Filter myFilter = newFilter();

????????myFilter.addSubFilter(newBrightnessSubFilter(brightness));

????????imagePreview.setImageBitmap(myFilter.processFilter(finalImage.copy(Bitmap.Config.ARGB_8888, true)));

????}

????@Override

????publicvoidonSaturationChanged(finalfloatsaturation) {

????????saturationFinal = saturation;

????????Filter myFilter = newFilter();

????????myFilter.addSubFilter(newSaturationSubfilter(saturation));

????????imagePreview.setImageBitmap(myFilter.processFilter(finalImage.copy(Bitmap.Config.ARGB_8888, true)));

????}

????@Override

????publicvoidonContrastChanged(finalfloatcontrast) {

????????contrastFinal = contrast;

????????Filter myFilter = newFilter();

????????myFilter.addSubFilter(newContrastSubFilter(contrast));

????????imagePreview.setImageBitmap(myFilter.processFilter(finalImage.copy(Bitmap.Config.ARGB_8888, true)));

????}

????@Override

????publicvoidonEditStarted() {

????}

????@Override

????publicvoidonEditCompleted() {

????????// once the editing is done i.e seekbar is drag is completed,

????????// apply the values on to filtered image

????????finalBitmap bitmap = filteredImage.copy(Bitmap.Config.ARGB_8888, true);

????????Filter myFilter = newFilter();

????????myFilter.addSubFilter(newBrightnessSubFilter(brightnessFinal));

????????myFilter.addSubFilter(newContrastSubFilter(contrastFinal));

????????myFilter.addSubFilter(newSaturationSubfilter(saturationFinal));

????????finalImage = myFilter.processFilter(bitmap);

????}

????/**

?????* Resets image edit controls to normal when new filter

?????* is selected

?????*/

????privatevoidresetControls() {

????????if(editImageFragment != null) {

????????????editImageFragment.resetControls();

????????}

????????brightnessFinal = 0;

????????saturationFinal = 1.0f;

????????contrastFinal = 1.0f;

????}

????classViewPagerAdapter extendsFragmentPagerAdapter {

????????privatefinalList mFragmentList = newArrayList<>();

????????privatefinalList mFragmentTitleList = newArrayList<>();

????????publicViewPagerAdapter(FragmentManager manager) {

????????????super(manager);

????????}

????????@Override

????????publicFragment getItem(intposition) {

????????????returnmFragmentList.get(position);

????????}

????????@Override

????????publicintgetCount() {

????????????returnmFragmentList.size();

????????}

????????publicvoidaddFragment(Fragment fragment, String title) {

????????????mFragmentList.add(fragment);

????????????mFragmentTitleList.add(title);

????????}

????????@Override

????????publicCharSequence getPageTitle(intposition) {

????????????returnmFragmentTitleList.get(position);

????????}

????}

????// load the default image from assets on app launch

????privatevoidloadImage() {

????????originalImage = BitmapUtils.getBitmapFromAssets(this, IMAGE_NAME, 300, 300);

????????filteredImage = originalImage.copy(Bitmap.Config.ARGB_8888, true);

????????finalImage = originalImage.copy(Bitmap.Config.ARGB_8888, true);

????????imagePreview.setImageBitmap(originalImage);

????}

????@Override

????publicbooleanonCreateOptionsMenu(Menu menu) {

????????getMenuInflater().inflate(R.menu.menu_main, menu);

????????returntrue;

????}

????@Override

????publicbooleanonOptionsItemSelected(MenuItem item) {

????????intid = item.getItemId();

????????if(id == R.id.action_open) {

????????????openImageFromGallery();

????????????returntrue;

????????}

????????if(id == R.id.action_save) {

????????????saveImageToGallery();

????????????returntrue;

????????}

????????returnsuper.onOptionsItemSelected(item);

????}

????@Override

????protectedvoidonActivityResult(intrequestCode, intresultCode, Intent data) {

????????if(resultCode == RESULT_OK && requestCode == SELECT_GALLERY_IMAGE) {

????????????Bitmap bitmap = BitmapUtils.getBitmapFromGallery(this, data.getData(), 800, 800);

????????????// clear bitmap memory

????????????originalImage.recycle();

????????????finalImage.recycle();

????????????finalImage.recycle();

????????????originalImage = bitmap.copy(Bitmap.Config.ARGB_8888, true);

????????????filteredImage = originalImage.copy(Bitmap.Config.ARGB_8888, true);

????????????finalImage = originalImage.copy(Bitmap.Config.ARGB_8888, true);

????????????imagePreview.setImageBitmap(originalImage);

????????????bitmap.recycle();

????????????// render selected image thumbnails

????????????filtersListFragment.prepareThumbnail(originalImage);

????????}

????}

????privatevoidopenImageFromGallery() {

????????Dexter.withActivity(this).withPermissions(Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE)

????????????????.withListener(newMultiplePermissionsListener() {

????????????????????@Override

????????????????????publicvoidonPermissionsChecked(MultiplePermissionsReport report) {

????????????????????????if(report.areAllPermissionsGranted()) {

????????????????????????????Intent intent = newIntent(Intent.ACTION_PICK);

????????????????????????????intent.setType("image/*");

????????????????????????????startActivityForResult(intent, SELECT_GALLERY_IMAGE);

????????????????????????} else{

????????????????????????????Toast.makeText(getApplicationContext(), "Permissions are not granted!", Toast.LENGTH_SHORT).show();

????????????????????????}

????????????????????}

????????????????????@Override

????????????????????publicvoidonPermissionRationaleShouldBeShown(List permissions, PermissionToken token) {

????????????????????????token.continuePermissionRequest();

????????????????????}

????????????????}).check();

????}

????/*

????* saves image to camera gallery

????* */

????privatevoidsaveImageToGallery() {

????????Dexter.withActivity(this).withPermissions(Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE)

????????????????.withListener(newMultiplePermissionsListener() {

????????????????????@Override

????????????????????publicvoidonPermissionsChecked(MultiplePermissionsReport report) {

????????????????????????if(report.areAllPermissionsGranted()) {

????????????????????????????finalString path = BitmapUtils.insertImage(getContentResolver(), finalImage, System.currentTimeMillis() + "_profile.jpg", null);

????????????????????????????if(!TextUtils.isEmpty(path)) {

????????????????????????????????Snackbar snackbar = Snackbar

????????????????????????????????????????.make(coordinatorLayout, "Image saved to gallery!", Snackbar.LENGTH_LONG)

????????????????????????????????????????.setAction("OPEN", newView.OnClickListener() {

????????????????????????????????????????????@Override

????????????????????????????????????????????publicvoidonClick(View view) {

????????????????????????????????????????????????openImage(path);

????????????????????????????????????????????}

????????????????????????????????????????});

????????????????????????????????snackbar.show();

????????????????????????????} else{

????????????????????????????????Snackbar snackbar = Snackbar

????????????????????????????????????????.make(coordinatorLayout, "Unable to save image!", Snackbar.LENGTH_LONG);

????????????????????????????????snackbar.show();

????????????????????????????}

????????????????????????} else{

????????????????????????????Toast.makeText(getApplicationContext(), "Permissions are not granted!", Toast.LENGTH_SHORT).show();

????????????????????????}

????????????????????}

????????????????????@Override

????????????????????publicvoidonPermissionRationaleShouldBeShown(List permissions, PermissionToken token) {

????????????????????????token.continuePermissionRequest();

????????????????????}

????????????????}).check();

????}

????// opening image in default image viewer app

????privatevoidopenImage(String path) {

????????Intent intent = newIntent();

????????intent.setAction(Intent.ACTION_VIEW);

????????intent.setDataAndType(Uri.parse(path), "image/*");

????????startActivity(intent);

????}

}

運行應用程序并測試一次。您應該看到文章中顯示的漂亮界面。您可以從列表中應用不同的濾鏡,并可以控制亮度,飽和度和對比度。

已知的問題

1。當前圖像控件更改圖像控件時,亮度,對比度和飽和度不平滑。這是由于SeekBar值更改時遞歸處理/復制位圖。改進必須在原生水平上完成。

2。過濾器不像Instagram那么好。在庫的下一個版本中,我將嘗試即興創(chuàng)建過濾器。

3。過濾器不適合所有類型的圖像。例如:具有白色背景的圖像看起來與不同的濾鏡幾乎相似。

?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容