Android模糊示範範例-RenderScript-附效果圖與代碼

來源:互聯網
上載者:User

標籤:resource   androi   enter   緩衝   super   分享   後台   efault   article   

本文連結    http://blog.csdn.net/xiaodongrush/article/details/31031411

參考連結    Android進階模糊技術    http://stackoverflow.com/questions/14879439/renderscript-via-the-support-library

1. 程式

    拖動紅色地區,能夠顯示出清晰的汽車部分。

拖動以下的滑塊,能夠更改模糊程度。

         

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQveGlhb2RvbmdydXNo/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" >    

2. 程式實現方法

實現思路。用FrameLayout搞了三層,最底下一層是清晰的圖片,中間一層是模糊的圖片,最上面的一層。是紅色地區,這一層是清晰的圖片。

public static class PlaceholderFragment extends Fragment { // 新版android adt-bundle預設在activity中帶一個fragment。據說android stdio早就這樣了private ImageView mOriginIv;private ImageView mBlurIv;private ImageView mClearIv;private SeekBar mRadiusSb;public PlaceholderFragment() {}@Overridepublic View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {View rootView = inflater.inflate(R.layout.fragment_main, container,false);return rootView;}@Overridepublic void onActivityCreated(Bundle savedInstanceState) {super.onActivityCreated(savedInstanceState);mOriginIv = (ImageView) getActivity().findViewById(R.id.origin_image);mBlurIv = (ImageView) getActivity().findViewById(R.id.blur_image);mClearIv = (ImageView) getActivity().findViewById(R.id.clear_image);mRadiusSb = (SeekBar) getActivity().findViewById(R.id.radius_seekbar);drawBlurImage(); // 初始化模糊層。setSeekBarChangeListen(); // 設定SeekBar回調。滑塊位置變化的時候,更新模糊層。                        // 延遲是為了保證view.getX。view.getWidth 這類方法可以去到數值,這裡僅僅是為了初始化,所以延遲運行比較好。

// 假設要是每次可視化的時候。都要讀weidht和x,那麼可以再在Activity#onWindowFocusChange中調用。Runnable runnable = new Runnable() {@Overridepublic void run() {OnMoveListener listener = new OnMoveListener() {@Overridepublic void onMoved() {mOriginIv.buildDrawingCache();clear(mOriginIv.getDrawingCache(), mClearIv, 10); // 這是拿到View繪製映像的好辦法}};MoveUtils.enableMove(mClearIv, listener);}};mClearIv.postDelayed(runnable, 500);}private void drawBlurImage() {mOriginIv.getViewTreeObserver().addOnPreDrawListener(new OnPreDrawListener() {@Overridepublic boolean onPreDraw() {mOriginIv.getViewTreeObserver().removeOnPreDrawListener(this);mOriginIv.buildDrawingCache();float radius = mRadiusSb.getProgress();if (radius < 0.1) { // RenderScript要求radius必須在0和25之間,不能等於radius = 0.1f;}if (radius > 24.9) {radius = 24.9f;}blur(mOriginIv.getDrawingCache(), mBlurIv, radius);clear(mOriginIv.getDrawingCache(), mClearIv, 10); // 這裡為了顯示邊框。偷懶了直接用了10px,實際上是5dip。在My Phonegalaxy nexus上。1dip=2px,實際上應該換算一下的。return true; // 這個是參考文章中要求的。沒試過false。}});}private void setSeekBarChangeListen() {mRadiusSb.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {@Overridepublic void onStopTrackingTouch(SeekBar arg0) {}@Overridepublic void onStartTrackingTouch(SeekBar arg0) {}@Overridepublic void onProgressChanged(SeekBar arg0, int arg1,boolean arg2) {drawBlurImage();}});}// 首先依據view的大小,從bkg產生一個剪裁後的映像;然後依據radius,將剪裁後的映像模糊處理;最後將模糊處理的映像設定到view上。 @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)private void blur(Bitmap bkg, View view, float radius) { // 剪裁圖片的過程Bitmap overlay = Bitmap.createBitmap((int) (view.getMeasuredWidth()),(int) (view.getMeasuredHeight()), Bitmap.Config.ARGB_8888);Canvas canvas = new Canvas(overlay);canvas.translate(-view.getX(), -view.getY()); // 這裡是設定座標系原點canvas.drawBitmap(bkg, 0, 0, null); // // 這裡直接在新的座標系的原點上繪製映像,假設不設定座標系的話,相當於在(view.getX(),view.getY)上繪製映像,android向右是x軸正方形,向下時y軸正方向。 // 模糊圖片的過程RenderScript rs = RenderScript.create(getActivity()); // RenderScript要求apilevel 17,這個比較噁心。v8支援包也不是特別好用。真的要搞模糊的話,還是opencv jni來搞吧。Allocation overlayAlloc = Allocation.createFromBitmap(rs, overlay);ScriptIntrinsicBlur blur = ScriptIntrinsicBlur.create(rs,overlayAlloc.getElement());blur.setInput(overlayAlloc);blur.setRadius(radius);blur.forEach(overlayAlloc);overlayAlloc.copyTo(overlay); // 設定圖片view.setBackground(new BitmapDrawable(getResources(), overlay));rs.destroy();} // 首先依據view的大小,從bkg產生一個剪裁後的映像;然後將剪裁後的映像設定到view上。private void clear(Bitmap bkg, ImageView view, int paddingPx) {Bitmap overlay = Bitmap.createBitmap((int) (view.getMeasuredWidth() - paddingPx * 2),(int) (view.getMeasuredHeight() - paddingPx * 2),Bitmap.Config.ARGB_8888);Canvas canvas = new Canvas(overlay);canvas.translate(-view.getX() - paddingPx, -view.getY() - paddingPx);canvas.drawBitmap(bkg, 0, 0, null);view.setImageDrawable(new BitmapDrawable(getResources(), overlay));}}




3. 代碼下載

     萬惡的CSDN上傳了代碼。好幾個小時了還沒審核完。。。

http://download.csdn.net/detail/u011267546/7502603     注意代碼的minsdk我設定的比較高,是API Level17。沒辦法。RenderScript的支援庫沒搞定。

4. 幾個問題

     RenderScript     儘管有support-v8支援庫。可是我搞了會,也沒編譯成功。

也看到有文章說在2.3.5上RenderScript有問題的。所以感覺不是特別靠譜,還是jni+opencv自己搞起來比較好。網上opencv相關的模糊演算法非常多。

另外假設映像非常大,模糊處理比較耗時。最好是非同步進行。

      getWidth。getHeight,getLeft的調用時機      onStart、onReusme這些都不行,僅僅能在onWindowFoucsChange。

本文的示範範例是初始化的時候調用。所以能夠延遲一會運行,假設要是每次從後台切換到前台,就要調用的話。那麼要在onWindowFoucsChange中調用。

     使用canvas剪裁bitmap     注意座標系。android向右是x軸正方形。向下時y軸正方向。

private void clear(Bitmap bkg, ImageView view, int paddingPx) {Bitmap overlay = Bitmap.createBitmap((int) (view.getMeasuredWidth() - paddingPx * 2),(int) (view.getMeasuredHeight() - paddingPx * 2),Bitmap.Config.ARGB_8888);Canvas canvas = new Canvas(overlay);canvas.translate(-view.getX() - paddingPx, -view.getY() - paddingPx);canvas.drawBitmap(bkg, 0, 0, null);view.setImageDrawable(new BitmapDrawable(getResources(), overlay));}
      擷取圖片繪製緩衝

mOriginIv.buildDrawingCache();clear(mOriginIv.getDrawingCache(), mClearIv, 10);
      讓View能夠拖動
     
寫了一個簡單的方法,通過View的Tag+onTouchEvent,實現View能夠拖動。

package com.example.blurtest;import android.view.MotionEvent;import android.view.View;import android.view.View.OnTouchListener;public class MoveUtils {private static final int STATE_IDLE = 0;private static final int STATE_MOVING = 1;private static final int MIN_GAP = 5;private static class Info {public int state = STATE_IDLE;public float lastX = -1;public float lastY = -1;public OnMoveListener listener;}private static Info getInfo(View view) {if (view.getTag() == null) {view.setTag(new Info());}return (Info) (view.getTag());}private static void tryToMove(View view, MotionEvent ev) {Info info = getInfo(view);if (info.state != STATE_MOVING) {return;}float x = ev.getX() - info.lastX;float y = ev.getY() - info.lastY;if (Math.abs(x) < MIN_GAP && Math.abs(y) < MIN_GAP) {return;}view.setX(view.getX() + x);view.setY(view.getY() + y);view.invalidate();info.listener.onMoved();}public static void enableMove(View target, OnMoveListener listener) {Info info = new Info();info.listener = listener;target.setTag(info);target.setOnTouchListener(new OnTouchListener() {@Overridepublic boolean onTouch(View view, MotionEvent ev) {Info info = getInfo(view);int action = ev.getAction() & MotionEvent.ACTION_MASK;switch (action) {case MotionEvent.ACTION_DOWN:info.state = STATE_MOVING;info.lastX = ev.getX();info.lastY = ev.getY();view.setTag(info);break;case MotionEvent.ACTION_MOVE:tryToMove(view, ev);break;case MotionEvent.ACTION_UP:info.state = STATE_IDLE;info.lastX = ev.getX();info.lastY = ev.getY();view.setTag(info);default:break;}return true;}});}public static interface OnMoveListener {public void onMoved();}}

    

Android模糊示範範例-RenderScript-附與代碼

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.