zoukankan      html  css  js  c++  java
  • 【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;  
        }  

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



  • 相关阅读:
    XSS跨站脚本攻击
    PHP 获取客户端ip地址
    Markdown基本语法
    浅谈CSRF攻击方式
    VC++ 中 trycatchfinally 语句 如何在获取正常信息是写一些操作语句
    VC创建Excel报表
    VS2008环境使用MFC操作读取excel文件
    VC常见错误总结(一)
    VC操作Excel文件编程相关内容总结
    VC2010对Excel的操作
  • 原文地址:https://www.cnblogs.com/claireyuancy/p/6938026.html
Copyright © 2011-2022 走看看