下面是Android实现局部模糊效果的完整攻略:
1. 前置条件
- Android Studio开发环境
- 模糊效果库:
rendererscript
或Glide
等 - 图片资源
2. 实现流程
2.1 定义模糊效果
使用rendererscript
定义模糊效果,可通过以下步骤实现:
- 在项目中
app/src/main
目录下新建RenderScript文件夹,并在其中创建rs文件 - 在rs文件中定义模糊效果,具体代码如下:
#pragma version(1)
#pragma rs java_package_name(com.example.myapplication.renderscript)
#pragma rs_fp_relaxed
rs_allocation gInput;
uchar4 __attribute__((kernel)) root(uchar4 in, uint32_t x, uint32_t y) {
float4 f4 = rsUnpackColor8888(in);
const float3 weights = {0.299f, 0.587f, 0.114f};
const float _VignetteOuterRadius = 0.8f;
const float _VignetteInnerRadius = 0.5f;
const int _BlurRadius = 25;
float3 grayscale = dot(weights, f4.rgb);
float abs = sqrt((x - rsAllocationGetDimX(gInput)/2.0)*(x - rsAllocationGetDimX(gInput)/2.0)
+ (y - rsAllocationGetDimY(gInput)/2.0)*(y - rsAllocationGetDimY(gInput)/2.0))/
hypot(rsAllocationGetDimX(gInput), rsAllocationGetDimY(gInput))/sqrt(2);
float factor = smootherstep(_VignetteOuterRadius, _VignetteInnerRadius, abs);
float4 sum = 0;
int kernelSize = 1 + 2 * _BlurRadius;
float kernel[kernelSize];
for(int i = 0; i < kernelSize; i++) {
kernel[i] = 1.0 / (sqrt(2 * 3.1415926) * _BlurRadius) * exp(-0.5 * ((i - _BlurRadius) / _BlurRadius) * ((i - _BlurRadius) / _BlurRadius));
sum += rsUnpackColor8888(*(const uchar4 *) rsGetElementAt(gInput, x + i - _BlurRadius, y));
}
sum /= sum.w;
return rsPackColorTo8888(mix(grayscale.rgb, sum.rgb, factor), f4.a);
}
其中,代码定义了灰度值、虚化半径、Vignette特效和高斯滤波等参数。
2.2 引入模糊效果库
在app工程的build.gradle中添加模糊库的引用,具体代码如下:
defaultConfig {
...
renderscriptTargetApi 19
renderscriptSupportModeEnabled true
}
dependencies {
implementation 'androidx.renderscript:renderscript:1.0.0'
implementation 'jp.wasabeef:glide-transformations:3.0.1'
}
其中,renderscript第一行指定了renderscript的target版本为19,第二行开启renderscript的support库。
2.3 实现局部模糊效果
通过引用模糊效果库,可以在线程中把图片转化为Drawable类型,并将其转化为模糊效果后的样式。具体代码如下:
Glide.with(this).load(R.drawable.image)
.apply(RequestOptions.bitmapTransform(new BlurTransformation(getResources().getDimensionPixelSize(R.dimen.radius))))
.into(mResult);
其中,Radius为模糊半径,可以在DIMEN文件中定义。
至此,Android实现局部模糊效果的流程已经介绍完毕。
2.4 具体实现示例一
通过Glide实现局部模糊效果:
- 在app的build.gradle中引入Glide库,具体代码如下:
dependencies {
...
implementation 'com.github.bumptech.glide:glide:4.9.0'
annotationProcessor 'com.github.bumptech.glide:compiler:4.9.0'
}
- 在xml文件中加入ImageView组件,并将其引用:
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/result"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="fitXY" />
- 加载图片并转化为Drawable类型:
Glide.with(this).load(R.drawable.image)
.apply(RequestOptions.bitmapTransform(new BlurTransformation(getResources().getDimensionPixelSize(R.dimen.radius))))
.into(mResult);
- 代码具体实现完整示例:
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import android.widget.ImageView;
import com.bumptech.glide.Glide;
import com.bumptech.glide.request.RequestOptions;
import jp.wasabeef.glide.transformations.BlurTransformation;
public class MainActivity extends AppCompatActivity {
private ImageView mResult;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mResult = findViewById(R.id.result);
Glide.with(this).load(R.drawable.owl)
.apply(RequestOptions.bitmapTransform(new BlurTransformation(getResources().getDimensionPixelSize(R.dimen.radius))))
.into(mResult);
}
}
2.5 具体实现示例二
通过RenderScript实现局部模糊效果:
- 在app/src/main中新建文件夹
RenderScript
,并在其中新建文件BlurEffect.rs
#pragma version(1)
#pragma rs java_package_name(com.example.myapplication)
rs_allocation gIn;
rs_allocation gOut;
float gRadius;
void root(const uchar4* pIn, uchar4* pOut, uint32_t x, uint32_t y) {
float4 sum = {0.0f, 0.0f, 0.0f, 0.0f};
float4 temp;
float factor;
uint32_t i, j;
uint32_t index;
const int radius = (int)gRadius;
const int width = rsAllocationGetDimX(gIn);
const int height = rsAllocationGetDimY(gIn);
for (j=-radius; j<=radius; j++) {
for (i=-radius; i<=radius; i++) {
temp = rsUnpackColor8888(*(pIn + (min(max(x+i, 0), width-1) + min(max(y+j, 0), height-1)*width)));
factor = exp(-(float)(i*i + j*j) / (gRadius*gRadius));
sum += temp * factor;
}
}
*pOut = rsPackColorTo8888(sum);
}
- 在xml文件中加入ImageView组件,并将其引用:
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/result"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="fitXY" />
- 绘制显示局部模糊效果的图片:
RenderScript rsScript = RenderScript.create(this);
final Allocation input = Allocation.createFromBitmap(rsScript, originalBitmap, Allocation.MipmapControl.MIPMAP_NONE, Allocation.USAGE_SCRIPT);
final Allocation output = Allocation.createTyped(rsScript, input.getType());
final ScriptC_BlurEffect blurEffect = new ScriptC_BlurEffect(rsScript);
blurEffect.set_gIn(input);
blurEffect.set_gOut(output);
blurEffect.set_gRadius(radius);
blurEffect.forEach_root(input, output);
output.copyTo(destBitmap);
ImageView imageview = findViewById(R.id.result);
imageview.setImageBitmap(destBitmap);
- 完整示例代码:
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import android.util.Log;
import android.widget.ImageView;
import androidx.renderscript.Allocation;
import androidx.renderscript.Element;
import androidx.renderscript.RenderScript;
import jp.wasabeef.blurry.Blurry;
public class MainActivity extends AppCompatActivity {
private final int radius = 30;
private ImageView imageView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
imageView = findViewById(R.id.result);
Bitmap originalBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.owl);
Bitmap destBitmap = Bitmap.createBitmap(originalBitmap.getWidth(), originalBitmap.getHeight(), originalBitmap.getConfig());
RenderScript rsScript = RenderScript.create(this);
final Allocation input = Allocation.createFromBitmap(rsScript, originalBitmap, Allocation.MipmapControl.MIPMAP_NONE, Allocation.USAGE_SCRIPT);
final Allocation output = Allocation.createTyped(rsScript, input.getType());
final ScriptC_BlurEffect blurEffect = new ScriptC_BlurEffect(rsScript);
blurEffect.set_gIn(input);
blurEffect.set_gOut(output);
blurEffect.set_gRadius(radius);
blurEffect.forEach_root(input, output);
output.copyTo(destBitmap);
ImageView imageview = findViewById(R.id.result);
imageview.setImageBitmap(destBitmap);
}
}
这就是实现局部模糊效果的完整流程和示例。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Android实现局部模糊效果 - Python技术站