Android实战Bitmap图片的截屏模糊处理传递使用

Posted claireyuancy

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android实战Bitmap图片的截屏模糊处理传递使用相关的知识,希望对你有一定的参考价值。

项目中遇到了这样一个需求:

当某个条件满足时就截取当前屏幕。并跳转到另外一个页面,同一时候将这个截屏图片作为下一个页面的背景图片,同一时候背景图片须要模糊处理

接下来就一步一步解决这个问题:

1、截取无状态栏的当前屏幕图片。请參考takeScreenShot方法

2、使图片高斯模糊的方法请參考blurBitmap方法

      注意:RenderScript是android在API 11之后增加的,用于高效的图片处理,包含模糊、混合、矩阵卷积计算等

public class ScreenShotUtil {

    // 获取指定Activity的截屏,保存到png文件
    String filenameTemp = "/mnt/sdcard/temp";

    /**
     * takeScreenShot:
     * TODO 截屏    去掉标题栏
     * @param activity
     */
    public static Bitmap takeScreenShot(Activity activity) {
        // View是你须要截图的View
        View view = activity.getWindow().getDecorView();
        view.setDrawingCacheEnabled(true);
        view.buildDrawingCache();
        Bitmap b1 = view.getDrawingCache();

        // 获取状态栏高度
        Rect frame = new Rect();
        activity.getWindow().getDecorView().getWindowVisibleDisplayFrame(frame);
        int statusBarHeight = frame.top;
        LogHelper.i("TAG", "" + statusBarHeight);

        // 获取屏幕长和高
        int width = activity.getWindowManager().getDefaultDisplay().getWidth();
        int height = activity.getWindowManager().getDefaultDisplay().getHeight();
        // 去掉标题栏
        // Bitmap b = Bitmap.createBitmap(b1, 0, 25, 320, 455);
        Bitmap b = Bitmap.createBitmap(b1, 0, statusBarHeight, width, height - statusBarHeight);
        view.destroyDrawingCache();
        return b;
    }

    /**
     * TODO  用于高效的图片处理,包含模糊、混合、矩阵卷积计算等
     * @param bitmap
     * @param context
     */
    @SuppressLint("NewApi")
    public static Bitmap blurBitmap(Bitmap bitmap, Context context) {

        // Let‘s create an empty bitmap with the same size of the bitmap we want
        // to blur
        Bitmap outBitmap = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(),
                Config.ARGB_8888);

        // Instantiate a new Renderscript
        RenderScript rs = RenderScript.create(context);//RenderScript是Android在API 11之后增加的

        // Create an Intrinsic Blur Script using the Renderscript
        ScriptIntrinsicBlur blurScript = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs));

        // Create the Allocations (in/out) with the Renderscript and the in/out
        // bitmaps
        Allocation allIn = Allocation.createFromBitmap(rs, bitmap);
        Allocation allOut = Allocation.createFromBitmap(rs, outBitmap);

        // Set the radius of the blur
        blurScript.setRadius(25.f);

        // Perform the Renderscript
        blurScript.setInput(allIn);
        blurScript.forEach(allOut);

        // Copy the final bitmap created by the out Allocation to the outBitmap
        allOut.copyTo(outBitmap);

        // recycle the original bitmap
        bitmap.recycle();

        // After finishing everything, we destroy the Renderscript.
        rs.destroy();

        return outBitmap;

    }
}

3、传递bitmap

刚開始我是这么传递的

bundle.putParcelable("bitmap", ScreenShotUtil.takeScreenShot(theLayout.getActivity()));

继续以下操作:就是将bitmap封装到bundle中,然后封装到intent中启动下一个Activity

ActivityUtil.startActivity(theLayout.getActivity(), LiveEndActivity.class, bundle, false);

/**
     * 开启另外一个activity
     * 
     * @param activity
     * @param cls 另外的activity类
     * @param bundle 传递的bundle对象
     * @param isFinish true表示要关闭activity false表示不要关闭activity
     */
    public static void startActivity(Activity activity, Class<?> cls, Bundle bundle, boolean isFinish) {
        Intent intent = new Intent(activity, cls);
        if (bundle != null) {
            intent.putExtras(bundle);
        }
        activity.startActivity(intent);
        if (isFinish) {
            activity.finish();
        }
        activity.overridePendingTransition(R.anim.push_left_in, R.anim.push_left_out);
    }
然后在LiveEndActivity中这么解析
Bitmap bitmap = intent.getExtras().getParcelable("bitmap");
结果:无法得到预期效果

关键是不报错。debug的时候能够看到我们的确截屏成功,可是Bitmap对象就是没有传递过去,并且不是启动下一个Activity

然后去网上找方法调研

结论:不能直接传递大于40k的图片

解决的方法:把bitmap存储为byte数组,然后再继续传递

       Bitmap bitmap = ScreenShotUtil.takeScreenShot(theLayout.getActivity());
       ByteArrayOutputStream baos=new ByteArrayOutputStream();  
       bitmap.compress(Bitmap.CompressFormat.PNG, 100, baos);  
       byte [] bitmapByte =baos.toByteArray();  
       bundle.putByteArray("bitmap", bitmapByte);
       // bundle.putParcelable("bitmap", ScreenShotUtil.takeScreenShot(theLayout.getActivity()));
                   
       ActivityUtil.startActivity(theLayout.getActivity(), LiveEndActivity.class, bundle, false);

然后在下一个Activity中这么解析

 byte[] bis =intent.getExtras().getByteArray("bitmap");
            Bitmap bitmap=BitmapFactory.decodeByteArray(bis, 0, bis.length); 

4、假如我们须要将这张图片设置为我们当前Activity的背景图片。我们能够这么做

 if (bitmap != null) {
       bitmap = ScreenShotUtil.blurBitmap(bitmap,getApplicationContext());//高斯模糊处理
       getWindow().getDecorView().setBackgroundDrawable(new BitmapDrawable(bitmap));
 }

问题基本攻克了。认为实用的能够參考一下!

更新补充:

2015.08.23

     * blurBitmap方法在4.2及以上的版本号就能够轻松出效果了。可是在低版本号就会出异常:
     * java.lang.NoClassDefFoundError: android.renderscript.ScriptIntrinsicBlur。
     * 解决方法:详见http://blog.csdn.net/yangxin_540/article/details/47207727
     * 可是我在使用该解决方法时easy出现其他so库 native方法异常的问题

所以找到了第二种方法

/**
     * blurImageAmeliorate:模糊效果
     * http://blog.csdn.net/sjf0115/article/details/7266998
     * @param bmp
     * @return
     */
    public static Bitmap blurImageAmeliorate(Bitmap bmp)  
    {  
        long start = System.currentTimeMillis();  
        // 高斯矩阵  
        int[] gauss = new int[] { 1, 2, 1, 2, 4, 2, 1, 2, 1 };  
          
        int width = bmp.getWidth();  
        int height = bmp.getHeight();  
        Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);  
          
        int pixR = 0;  
        int pixG = 0;  
        int pixB = 0;  
          
        int pixColor = 0;  
          
        int newR = 0;  
        int newG = 0;  
        int newB = 0;  
          
        int delta = 75; // 值越小图片会越亮,越大则越暗  
          
        int idx = 0;  
        int[] pixels = new int[width * height];  
        bmp.getPixels(pixels, 0, width, 0, 0, width, height);  
        for (int i = 1, length = height - 1; i < length; i++)  
        {  
            for (int k = 1, len = width - 1; k < len; k++)  
            {  
                idx = 0;  
                for (int m = -1; m <= 1; m++)  
                {  
                    for (int n = -1; n <= 1; n++)  
                    {  
                        pixColor = pixels[(i + m) * width + k + n];  
                        pixR = Color.red(pixColor);  
                        pixG = Color.green(pixColor);  
                        pixB = Color.blue(pixColor);  
                          
                        newR = newR + (int) (pixR * gauss[idx]);  
                        newG = newG + (int) (pixG * gauss[idx]);  
                        newB = newB + (int) (pixB * gauss[idx]);  
                        idx++;  
                    }  
                }  
                  
                newR /= delta;  
                newG /= delta;  
                newB /= delta;  
                  
                newR = Math.min(255, Math.max(0, newR));  
                newG = Math.min(255, Math.max(0, newG));  
                newB = Math.min(255, Math.max(0, newB));  
                  
                pixels[i * width + k] = Color.argb(255, newR, newG, newB);  
                  
                newR = 0;  
                newG = 0;  
                newB = 0;  
            }  
        }  
          
        bitmap.setPixels(pixels, 0, width, 0, 0, width, height);  
        long end = System.currentTimeMillis();  
        return bitmap;  
    }  

以下假设还有什么问题。我会继续更新!












以上是关于Android实战Bitmap图片的截屏模糊处理传递使用的主要内容,如果未能解决你的问题,请参考以下文章

Android View转换为Bitmap,实现截屏效果

android 高斯模糊怎么还原

android源码解析(二十六)-->截屏事件流程

使用java awt最简单的截屏程序

Android进阶之路 - 花样百出的截屏需求

屏幕截图