项目中遇到了这样一个需求:
当某个条件满足时就截取当前屏幕,并跳转到另外一个页面,同时将这个截屏图片作为下一个页面的背景图片,同时背景图片需要模糊处理
接下来就一步一步解决问题:
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
* 但是我在使用该解决方法时容易出现其它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;
}