高斯模糊Android
来源:互联网 发布:ubuntu 关闭swap 编辑:程序博客网 时间:2024/05/17 06:29
高斯模糊Android
前提:当前的需求是要求用户每次下滑状态栏的时候看到的都是目前打开应用的模糊化的背景.下面的介绍主要是围绕实现这个需求来的.
下面记录几使用和见过的方法,以便后续直接使用.
方法1:
获取当前屏幕截图(使用SurfaceControl.screenshot),进行高速模式处理,如果获取结果为null 就使用壁纸来代替(为考虑是宽屏壁纸或者不归宿壁纸会出现压缩的情况),获取之后使用LayerDrawable来将得到的Drawable 作为当前应用程序的背景,这样不仅到达的模糊的效果,有保存了不会看不见当前程序的内容.(防止壁纸和当前程序内容颜色相近的时候容易出现看不清的问题)方法2:
获取系统壁纸,裁剪,将裁剪之后的壁纸和一张半透明的图片(尺寸要注意)进行合成,这里不是用的LayerDrawable来直接使用的,是使用的Canvas来实现的.再将合成之后的壁纸来进行高斯模糊.备注:方法2实际在使用的过程中需要裁剪壁纸,这个是不能置裁剪的,需要先将copy 一份Bitmap 对象,才进行操作.而且后续合成和模糊化处理的时候容易出现内存溢出现象.这里可以使用下面的方法来解决,当然及时调用Bitmap的receyle()方法来回收也是必要.
newBitmap = bmp.copy(Bitmap.Config.ARGB_4444, true);//采用ARGB_4444 减少内存使用
由于这2中方法是在不同项目中分别使用到的,各种各的利弊,可以结合实际情况来整合2个方法来实现相关需求.
方法3:
上面的方法主要是使用的java 来实现的,也就是获取bitmap 的方法不一样,实际模糊处理的方法是完全一样的.也就是都使用的RenderScript和ScriptIntrinsicBlur来处理的.后面借鉴别人的成果发现还有使用C来实现模糊处理的部分,这样暂时不对比性能的差异.同时本方法也是使用SurfaceControl.screenshot 来获取bitmap资源.
备注:需要添加 <uses-permission android:name="android.permission.READ_FRAME_BUFFER" /> 同时需要系统签名
方法1具体源码如下:
private static final int BLUR_RADIUS = 3;private static final int SCALE_RATIO = 8;
public void blur(){
Bitmap mBackBitmap = getScreenshot(context, BLUR_RADIUS);
Drawable backgroundDrawable = null;
if (mBackBitmap != null) {
backgroundDrawable = new BitmapDrawable(mBackBitmap);
} else {
Log.i(TAG, "mBackBitmap is null.");
WallpaperManager wallpaperManager = WallpaperManager.getInstance(mDialogContext);
backgroundDrawable = wallpaperManager.getDrawable();
}
if (backgroundDrawable != null) {
getWindow().getDecorView().setBackground(new LayerDrawable(new Drawable[]{backgroundDrawable,
context.getResources().getDrawable(R.drawable.ali_poweroff_background)}));
}
}
private Bitmap getScreenshot(Context context, int radius) {
long start = System.currentTimeMillis();
Display display = ((WindowManager) context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
DisplayMetrics displayMetrics = new DisplayMetrics();
Matrix displayMatrix = new Matrix();
display.getRealMetrics(displayMetrics);
final int w = displayMetrics.widthPixels;
final int h = displayMetrics.heightPixels;
float[] dims = {w, h};
float degrees = getDegreesForRotation(display.getRotation());
boolean requiresRotation = (degrees > 0);
if (requiresRotation) {
// Get the dimensions of the device in its native orientation
displayMatrix.reset();
displayMatrix.preRotate(-degrees);
displayMatrix.mapPoints(dims);
dims[0] = Math.abs(dims[0]);
dims[1] = Math.abs(dims[1]);
}
Bitmap bp = SurfaceControl.screenshot((int) dims[0], (int) dims[1]);
if (bp == null) return null;
//clip bitmap
Bitmap ss = Bitmap.createBitmap((int) dims[0]/SCALE_RATIO, (int) dims[1]/SCALE_RATIO, Bitmap.Config.ARGB_8888);
if (ss == null) return null;
Canvas c = new Canvas(ss);
c.clipRect(0, 0, dims[0] / SCALE_RATIO, dims[1] / SCALE_RATIO);
Rect srcRect = new Rect(0, 0, bp.getWidth(), bp.getHeight());
Rect dstRect = new Rect(0, 0, ss.getWidth(), ss.getHeight());
c.drawBitmap(bp, srcRect, dstRect, null);
c.setBitmap(null);
bp.recycle();
bp = ss;
//rotate bitmap
if (requiresRotation) {
ss = Bitmap.createBitmap(w / SCALE_RATIO, h / SCALE_RATIO, Bitmap.Config.ARGB_8888);
if (ss == null) return null;
c = new Canvas(ss);
c.translate(ss.getWidth() / 2, ss.getHeight() / 2);
c.rotate(degrees);
c.translate(-dims[0] / (2 * SCALE_RATIO), -dims[1] / (2 * SCALE_RATIO));
c.drawBitmap(bp, 0, 0, null);
c.setBitmap(null);
bp.recycle();
bp = ss;
}
//blur bitmap
Bitmap bitmap = bp.copy(bp.getConfig(), true);
final RenderScript rs = RenderScript.create(context);
final Allocation input = Allocation.createFromBitmap(rs, bp, Allocation.MipmapControl.MIPMAP_NONE,
Allocation.USAGE_SCRIPT);
final Allocation output = Allocation.createTyped(rs, input.getType());
final ScriptIntrinsicBlur script = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs));
script.setRadius(radius);
script.setInput(input);
script.forEach(output);
output.copyTo(bitmap);
long end = System.currentTimeMillis();
Log.d(TAG, "Take time " + (end - start));
return bitmap;
}
private float getDegreesForRotation(int value) {
switch (value) {
case Surface.ROTATION_90:
return 360f - 90f;
case Surface.ROTATION_180:
return 360f - 180f;
case Surface.ROTATION_270:
return 360f - 270f;
}
return 0f;
}
drawable:ali_poweroff_background
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<gradient android:name="poweroff_background"
android:startColor="#e5000000"
android:endColor="#7f000000"
android:angle="90"
/>
</shape>
方法2源码如下:
private Bitmap blur_wallpaper = null;
public void applyBlur() {
Log.d(TAG,"applyBlur ------- ");
if(null != blur_wallpaper && !blur_wallpaper.isRecycled()){//先回收上一次保存壁纸的变量
Log.d(TAG,"applyBlur blur_wallpaper isRecycled");
setBackgroundResource(R.drawable.backgoud_bulr);
blur_wallpaper.recycle();
blur_wallpaper = null;
}
if(wallpaperManager == null){
wallpaperManager = WallpaperManager.getInstance(this.getContext());
}
Drawable wallpaperDrawable = wallpaperManager.getDrawable();
Bitmap bmp = ((BitmapDrawable) wallpaperDrawable).getBitmap();
Bitmap newBitmap = bmp;
if(null == newBitmap){
Log.d(TAG,"applyBlur newBitmap is null" );
if(blur_wallpaper == null){
setBackgroundResource(R.drawable.backgoud_bulr_default);
blur_wallpaper = ((BitmapDrawable)getResources().getDrawable(R.drawable.backgoud_bulr_default)).getBitmap();
}
return;
}else if(!newBitmap.isMutable()){
int w = bmp.getWidth();
int h = bmp.getHeight();
Log.d(TAG,"applyBlur w=" + w + " h=" + h);
Log.d(TAG,"applyBlur not isMutable");
try {
newBitmap = bmp.copy(Bitmap.Config.ARGB_4444, true);//采用ARGB_4444 减少内存使用
} catch (Exception e) {
Log.d(TAG,"bitmap copy error,out of memory");
if(null != bmp && !bmp.isRecycled()){
//bmp.recycle();
bmp = null;
}
if(null != newBitmap && !newBitmap.isRecycled()){
newBitmap.recycle();
newBitmap = null;
}
setBackgroundResource(R.drawable.backgoud_bulr_default);
blur_wallpaper = ((BitmapDrawable)getResources().getDrawable(R.drawable.backgoud_bulr_default)).getBitmap();
Log.d(TAG,"use default background");
return ;
}
}
newBitmap = mPictureUtil.setAndcropWallpaper(mContext, newBitmap);
if(null == newBitmap){
Toast.makeText(mContext, R.string.update_status_bar_ground_error, Toast.LENGTH_SHORT).show();
setBackgroundResource(R.drawable.backgoud_bulr_default);
blur_wallpaper = ((BitmapDrawable)getResources().getDrawable(R.drawable.backgoud_bulr_default)).getBitmap();
Log.d(TAG,"use default background----");
return;
}
Canvas canvas = new Canvas(newBitmap);
Drawable backgoud_bulr = this.getResources().getDrawable(R.drawable.backgoud_bulr);//半透明的黑色背景
Bitmap bitmap_backgoud_bulr = ((BitmapDrawable)backgoud_bulr).getBitmap();
canvas.drawBitmap(bitmap_backgoud_bulr, 0, 0, null );
canvas.save(Canvas.ALL_SAVE_FLAG);
//存储新合成的图片
canvas.restore();
if(bmp != null && !bmp.isRecycled()){
Log.d(TAG,"applyBlur bmp.isRecycled");
// bmp.recycle();
bmp = null;
}
if(bitmap_backgoud_bulr != null && !bitmap_backgoud_bulr.isRecycled()){
Log.d(TAG,"applyBlur bitmap_backgoud_bulr.isRecycled");
bitmap_backgoud_bulr.recycle();
bitmap_backgoud_bulr = null;
backgoud_bulr = null;
}
blur_wallpaper = mPictureUtil.blur(mContext, newBitmap);
Drawable background = new BitmapDrawable(getResources(), blur_wallpaper);
setBackground(background);
if(null != newBitmap && !newBitmap.isRecycled()){
Log.d(TAG,"blur bkg.isRecycled");
newBitmap.recycle();
newBitmap = null;
}
}
/**
* @Title: PictureUtil.java
* @Package com.doov.systemui.utils
* @Description: TODO(用一句话描述该文件做什么)
* @author
* @date 2015年8月7日 下午3:54:46
* @version V1.0
*/
package com.doov.systemui.utils;
import android.annotation.TargetApi;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Matrix;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.renderscript.Allocation;
import android.renderscript.Element;
import android.renderscript.RenderScript;
import android.renderscript.ScriptIntrinsicBlur;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.WindowManager;
/**
* @ClassName: PictureUtil
* @Description:图片处理
* @author zhang.le
* @date 2015年8月7日 下午3:54:46
*
*/
public class PictureUtil {
private static final String TAG = "PictureUtil";
public final static int mScal = 2;
private final boolean DEBUG = true;
/**
*
*高斯模式处理
* @param context
* @param bkg
* @return Bitmap 返回类型
*/
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
public Bitmap blur(Context context,Bitmap bkg) {
long startMs = System.currentTimeMillis();
float radius = 25;
bkg = small(bkg);
bkg = bkg.copy(bkg.getConfig(), true);
final RenderScript rs = RenderScript.create(context);
final Allocation input = Allocation.createFromBitmap(rs, bkg, Allocation.MipmapControl.MIPMAP_NONE, Allocation.USAGE_SCRIPT);
final Allocation output = Allocation.createTyped(rs, input.getType());
final ScriptIntrinsicBlur script = ScriptIntrinsicBlur.create(rs,
Element.U8_4(rs));
script.setRadius(radius);
script.setInput(input);
script.forEach(output);
output.copyTo(bkg);
rs.destroy();
script.destroy();
input.destroy();
output.destroy();
Log.d(TAG, "blur take away:" + (System.currentTimeMillis() - startMs) + "ms");
return bkg;
}
private static Bitmap small(Bitmap bitmap) {
Matrix matrix = new Matrix();
matrix.postScale(1f/mScal, 1f/mScal); // 长和宽放大缩小的比例
Bitmap resizeBmp = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(),
bitmap.getHeight(), matrix, true);
return resizeBmp;
}
/**
*
* 裁剪图片
* @param context
* @param wallpaper
* @return Bitmap
*/
public Bitmap setAndcropWallpaper(Context context,Bitmap wallpaper) {
Bitmap targetBitmap = null;
if (wallpaper != null) {
try {
int wallpaperWidth = wallpaper.getWidth();
int wallpaperHeight = wallpaper.getHeight();
DisplayMetrics dm = new DisplayMetrics();
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
wm.getDefaultDisplay().getMetrics(dm);
int screenWidth = dm.widthPixels;// 1080
int screenHeight = dm.heightPixels;// 1920
float defaultScreen = (float)screenHeight / (float)screenWidth;
Log.d(TAG, "defaultScreen=" + defaultScreen);
if (defaultScreen < 1) {
defaultScreen = (float)screenWidth / (float)screenHeight;
}
float bitmapSize = (float)wallpaperHeight /(float)wallpaperWidth;
int disWidth = 0;
int disHeight = 0;
int captureBitmapWidth = wallpaperWidth;
int captureBitmapHeight = wallpaperHeight;
Log.d(TAG, "defaultScreen=" + defaultScreen + " bitmapSize="
+ bitmapSize);
if (defaultScreen > bitmapSize) { // bitmapHeight is min , capture bitmapWidth
captureBitmapWidth = (int) ((screenWidth * wallpaperHeight) / screenHeight);
disWidth = wallpaperWidth - captureBitmapWidth;
} else if (defaultScreen < bitmapSize) {
captureBitmapHeight = (int) ((wallpaperWidth * screenHeight) / screenWidth);
disHeight = wallpaperHeight - captureBitmapHeight;
}
if (DEBUG) {
Log.d(TAG, "setAndcropWallpaper ----- disWidth="
+ disWidth + ",disHeight=" + disHeight
+ ",captureBitmapWidth=" + captureBitmapWidth
+ ",captureBitmapHeight=" + captureBitmapHeight
+ " screenWidth=" + screenWidth + " screenHeight="
+ screenHeight);
}
if (disWidth < 0 || disHeight < 0) {
return null;
}
targetBitmap = Bitmap.createBitmap(wallpaper, disWidth / 2,
disHeight / 2, captureBitmapWidth, captureBitmapHeight);
float scaleWidth = (float) ((float) captureBitmapWidth / screenWidth);
float scaleHeight = (float) ((float) captureBitmapHeight / screenHeight);
Log.d(TAG, "scaleWidth=" + scaleWidth + " scaleHeight="
+ scaleHeight);
if ((targetBitmap != null)
&& (scaleWidth != 1 || scaleHeight != 1)) {
Matrix matrix = new Matrix();
/**
* 处理之后的图片小于屏幕尺寸 处理原始的图片比例和屏幕比例是一致,但尺寸比屏幕大
*/
if (scaleWidth != 0.0f && scaleHeight != 0.0f
&& (scaleWidth != 1.0f || scaleHeight != 1.0f)) {//
scaleWidth = 1.0f / scaleWidth;
scaleHeight = 1.0f / scaleHeight;
Log.d(TAG, "---scaleWidth=" + scaleWidth + " scaleHeight=" + scaleHeight);
}
matrix.postScale(scaleWidth, scaleHeight);
int width = targetBitmap.getWidth();
int height = targetBitmap.getHeight();
Log.d(TAG, "---width=" + width + " height=" + height);
targetBitmap = Bitmap.createBitmap(targetBitmap, 0, 0,
screenWidth > width ? width : screenWidth,
screenHeight > height ? height : screenHeight,
matrix, true);
}
} catch (OutOfMemoryError e) {
e.printStackTrace();
}
}
return targetBitmap;
}
}
方法3源码
PhoneStatusBar.java
protected static final int MSG_SCREEN_SHOT = 2031;
public boolean interceptTouchEvent(MotionEvent event) {
//......
//zhangle add start
int action = event.getAction();
if (MotionEvent.ACTION_DOWN == action) {
if (!mExpandedVisible) {
boolean hasScreenShotMsg = myHandler.hasMessages(MSG_SCREEN_SHOT);
LogD.d(TAG, "interceptTouchEvent hasScreenShotMsg = " + hasScreenShotMsg);
if (!hasScreenShotMsg) {
Log.d(TAG, " sendEmptyMessage MSG_SCREEN_SHOT currentTimeMillis = " + System.currentTimeMillis());
myHandler.sendEmptyMessage(MSG_SCREEN_SHOT);
}
}
}
//zhangel add end
return false;
}
以上修改是保证每次点击状态栏的时候可以获取最新的截图.具体原因参考SystemUI 流程相关的笔记.
NotificationPanelView.java
添加以下代码
private Bitmap mScreenShotBg;
protected void setScreenShotBitmap(Bitmap bitmap) {
mScreenShotBg = bitmap;
}
public void recyleScreenShotBg(){
if (mScreenShotBg != null) {
mScreenShotBg.recycle();
mScreenShotBg = null;
}
}
@Override
public void draw(Canvas canvas) {
if (canvas == null) {
return;
}
if (mScreenShotBg != null) {
Bitmap bp = mScreenShotBg;
Rect dstRect = new Rect(0, 0, getWidth(), (int) getFullHeight());
Paint paint = new Paint();
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC));
canvas.drawBitmap(bp, new Rect(0, 0, bp.getWidth(), bp.getHeight()), dstRect, paint);
}
super.draw(canvas);
}
同时在 onDetachedFromWindow 里面末尾添加recyleScreenShotBg(),来回收内存.
下面主要是使用Handler 发送消息来使用SurfaceControl.screenshot 获取bitmap 资源来供JNI处理.
PhoneStatusBar.java
//zhangle add start
private Handler myHandler = new Handler(){
@Override
public void dispatchMessage(Message msg) {
switch (msg.what) {
case MSG_SCREEN_SHOT:
Xlog.d(TAG, "MSG_SCREEN_SHOT.");
Bitmap screenShotBitmap = screenshotFocusedWindow(mDisplayMetrics.widthPixels,
mDisplayMetrics.heightPixels);
if (screenShotBitmap != null) {
mNotificationPanel.setScreenShotBitmap(screenShotBitmap);
}
break;
default:
break;
}
}
};
private Bitmap screenshotFocusedWindow(int maxWidth, int maxHeight) {
long beginScreenShot = System.currentTimeMillis();
int rot = mDisplay.getRotation();
Rect frame = new Rect();
float degrees = 0f;
switch (rot) {
case Surface.ROTATION_90:
degrees = 360f - 90f;
break;
case Surface.ROTATION_180:
degrees = 360f - 180f;
break;
case Surface.ROTATION_270:
degrees = 360f - 270f;
break;
default:
degrees = 0f;
break;
}
int mNavSize = 0;
try {
boolean showNav = mWindowManagerService.hasNavigationBar();//IWindowManager
if (showNav) {
mNavSize = mContext.getResources().getDimensionPixelSize(
R.dimen.navigation_bar_size);
}
} catch (RemoteException ex) {
// no window manager? good luck with that
Slog.e(TAG, "resolve navigationbar layout fail");
}
if (mNavSize > 0) {
if (maxHeight > maxWidth) {
maxHeight += mNavSize;
} else {
maxWidth += mNavSize;
}
}
Matrix matrix = new Matrix();
int dw = maxWidth;
int dh = maxHeight;
if (DEBUG) Log.d("screenshot", "bitmap dw =" + maxWidth + " dh = " + maxHeight);
frame.set(0, 0/* getStatusBarHeight() */, dw, dh);
float dims[] = {
dw, dh
};
boolean requiresRotation = (degrees > 0);
if (requiresRotation) {
// Get the dimensions of the device in its native orientation
matrix.reset();
matrix.preRotate(-degrees);
matrix.mapPoints(dims);
dims[0] = Math.abs(dims[0]);
dims[1] = Math.abs(dims[1]);
}
if (frame.isEmpty()) {
return null;
}
if (DEBUG) Log.d("screenshot", "bitmap width =" + dims[0] + "height = " + dims[1]);
Bitmap bp = SurfaceControl.screenshot((int) dims[0], (int) dims[1]);
// The screenshot() interface may fail. If it fail, it will return null.
// If the screenshot is null, the statusbar will be transparent.
if (bp == null) {
return null;
}
final int SCALE_RATIO = 8;
if (requiresRotation) {
// Rotate the screenshot to the current orientation
Bitmap ss = Bitmap.createBitmap(dw / SCALE_RATIO, dh / SCALE_RATIO,
Bitmap.Config.ARGB_8888);
if (DEBUG)
Log.d("screenshot", "Canvas width =" + dims[0] + " height = " + dims[1]);
if (ss == null) {
return null;
}
Canvas c = new Canvas(ss);
c.clipRect(0, frame.top / SCALE_RATIO, dw / SCALE_RATIO, dh / SCALE_RATIO);
if (mNavSize > 0) {
c.clipRect(0, 0, (dw - mNavSize) / SCALE_RATIO, dh / SCALE_RATIO);
}
c.translate(ss.getWidth() / 2, ss.getHeight() / 2);
c.rotate(degrees);
c.translate(-dims[0] / (2 * SCALE_RATIO), -dims[1] / (2 * SCALE_RATIO));
// c.drawBitmap(bp, 0, 0, null);
Rect dstRect = new Rect(0, 0, ss.getHeight(), ss.getWidth());
c.drawBitmap(bp, new Rect(0, 0, bp.getWidth(), bp.getHeight()), dstRect, null);
Paint paint = new Paint();
// Reset the screen shot color alpha for text show clearly.
// 80% black
paint.setColor(mContext.getResources().getColor(R.color.notification_background_color));
/* YUNOS END */
c.drawRect(dstRect, paint);
c.setBitmap(null);
bp.recycle();
bp = ss;
} else {
Bitmap ss = Bitmap.createBitmap(dw / SCALE_RATIO, dh / SCALE_RATIO,
Bitmap.Config.ARGB_8888);
if (ss == null) {
return null;
}
Canvas c = new Canvas(ss);
c.clipRect(0, frame.top / SCALE_RATIO, dw / SCALE_RATIO, dh / SCALE_RATIO);
if (mNavSize > 0) {
c.clipRect(0, 0, dw / SCALE_RATIO, (dh - mNavSize) / SCALE_RATIO);
}
// c.drawBitmap(bp, 0, 0, null);
Rect dstRect = new Rect(0, 0, ss.getWidth(), ss.getHeight());
c.drawBitmap(bp, new Rect(0, 0, bp.getWidth(), bp.getHeight()), dstRect, null);
Paint paint = new Paint();
// Reset the screen shot color alpha for text show clearly.
// 80% black
paint.setColor(mContext.getResources().getColor(R.color.notification_background_color));
c.drawRect(dstRect, paint);
c.setBitmap(null);
bp.recycle();
bp = ss;
}
// Invoke jni with thread safe
bp = FrostedGlassUtil.getInstance().convertToBlur(bp, 20);
return bp;
}
//zhangle add end
上面代码中的FrostedGlassUtil.getInstance().convertToBlur(bp,20),就是调用JNI的地方.
FrostedGlassUtil.java:
package com.android.systemui.utils;
import android.graphics.Bitmap;
public class FrostedGlassUtil {
private volatile static FrostedGlassUtil mFrostedGlassUtil;
/*YUNOS BEGIN*/
//##module(SystemUI)
//##date:2013/3/29 ##author:sunchen.sc@alibaba-inc.com##BugID:104943
//Invoke jni with thread safe
public static FrostedGlassUtil getInstance() {
if (mFrostedGlassUtil == null) {
synchronized (FrostedGlassUtil.class) {
if (mFrostedGlassUtil == null) {
mFrostedGlassUtil = new FrostedGlassUtil();
}
}
}
return mFrostedGlassUtil;
}
/*YUNOS END*/
public native void clearColor(Bitmap image, int color);
public native void imageBlur(Bitmap srcBitmap, Bitmap dstBitmap);
public native void boxBlur(Bitmap srcBitmap, int radius);
public native void stackBlur(Bitmap srcBitmap, int radius);
public native void oilPaint(Bitmap srcBitmap, int radius);
public native void colorWaterPaint(Bitmap srcBitmap, int radius);
/*YUNOS BEGIN*/
//##module(SystemUI)
//##date:2013/3/29 ##author:sunchen.sc@alibaba-inc.com##BugID:104943
//Invoke jni with thread safe
public synchronized Bitmap convertToBlur(Bitmap bmp, int radius) {
long beginBlur = System.currentTimeMillis();
stackBlur(bmp, radius);
return bmp;
}
static {
// load frosted glass lib
System.loadLibrary("frostedGlass");
}
/*YUNOS END*/
}
这里将JNI 下面用到的类的目录列出.
为了在编译的时候能够将生成的so库和SystemUI 关联起来,需要在SystemUI的Android.mk 中增加以下2行,其中libfrostedGlass就是上面jni 目录中的Android.mk 里面配置的so库的名称,编译jni 目前之后会生成一个libfrostedGlass.so 库.
LOCAL_JNI_SHARED_LIBRARIES := libfrostedGlass
LOCAL_REQUIRED_MODULES := libfrostedGlass
上面这2行的作用是让编译系统可以将生成的libfrostedGlass.so 拷贝到System/SystemUI/lib/arm64/下面去.
下面继续列出上面jni 部分文件的源码.
Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := libfrostedGlass
LOCAL_SRC_FILES := frostedGlass.c bitmapPort.c imageProcess.c
#LOCAL_LDLIBS := -llog -ljnigraphics
LOCAL_SHARED_LIBRARIES += \
liblog libjnigraphics
include $(BUILD_SHARED_LIBRARY)
其他jni 实现部分的源码看附件.点击打开链接
0 0
- android 高斯模糊
- android高斯模糊
- Android高斯模糊
- android高斯模糊
- Android 高斯模糊
- 高斯模糊Android
- Android高斯模糊
- android 图片高斯模糊
- Android实现高斯模糊
- android 高斯模糊实现
- android 图片高斯模糊
- Android图片高斯模糊
- Android高斯模糊(RenderScript)
- Android实现高斯模糊
- android高斯模糊图
- Android高性能高斯模糊方案
- Android高性能高斯模糊方案
- Android 自定义设置图片模糊度、高斯模糊效果
- k近邻 - 改进约会网站的匹配效果
- 性能优化检测Instruments-time profile的使用
- 运算符重载
- ZOJ - 3705 A - Applications
- QMetaObject::invokeMethod and Q_INVOKABLE
- 高斯模糊Android
- 深度学习的过往
- 简单的读取xml文件
- redis安装、设置密码及开机自启动
- 爬取豆瓣图片链接(Java)
- jsp中redirect和forward的区别
- javascript自执行函数
- SpringMVC注解
- Redis 事务