Android Bitmap 使用 ScriptIntrinsicBlur、Toolkit 实现模糊

Android Bitmap 使用 ScriptIntrinsicBlur、Toolkit 实现模糊

本文首发地址 https://blog.csdn.net/CSqingchen/article/details/43817975
最新更新地址 https://gitee.com/chenjim/chenjimblog

软件修改Bitmap像素点实现模糊

此方法无sdk版本要求,但是效率非常非常差,没有可使用性。
具体源码可以参考后文附的完整实例

使用 RenderScript 模糊

ScriptIntrinsicBlur 要求 android sdk 版本最低 17, Android 12(API 31) 开始废弃
设备和组件制造商已停止提供硬件加速支持,预计将在未来的版本中完全取消对 RenderScript 的支持。

详细使用代码如下:

/**
 * 通过调用系统高斯模糊api的方法模糊
 *
 * @param bitmap    source bitmap
 * @param outBitmap out bitmap
 * @param radius    0 < radius <= 25
 * @param context   context
 * @return out bitmap
 */
public static Bitmap blurBitmap(Bitmap bitmap, Bitmap outBitmap, float radius, 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);

    //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(radius);

    //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;
}

使用 Toolkit 模糊

Toolkit 是 ScriptIntrinsicBlur 的替代方案之一,效率更高
Toolkit.kt 只是一个 JAVA 接口,主要实现是在JNI中
以模糊为例,其部分实现代码如下 ,参见 Blur.cpp

/**
 * Full blur of a line of U_8 data.
 *
 * @param outPtr Where to store the results
 * @param xstart The index of the section we're starting to blur.
 * @param xend  The end index of the section.
 * @param currentY The index of the line we're blurring.
 */
void BlurTask::kernelU1(void *outPtr, uint32_t xstart, uint32_t xend, uint32_t currentY) {
    float buf[4 * 2048];
    const uint32_t stride = mSizeX * mVectorSize;

    uchar *out = (uchar *)outPtr;
    uint32_t x1 = xstart;
    uint32_t x2 = xend;

    float *fout = (float *)buf;
    int y = currentY;
    if ((y > mIradius) && (y < ((int)mSizeY - mIradius -1))) {
        const uchar *pi = mIn + (y - mIradius) * stride;
        OneVFU1(fout, pi, stride, mFp, mIradius * 2 + 1, mSizeX, mUsesSimd);
    } else {
        x1 = 0;
        while(mSizeX > x1) {
            OneVU1(mSizeY, fout, x1, y, mIn, stride, mFp, mIradius);
            fout++;
            x1++;
        }
    }

    x1 = xstart;
    while ((x1 < x2) &&
           ((x1 < (uint32_t)mIradius) || (((uintptr_t)out) & 0x3))) {
        OneHU1(mSizeX, out, x1, buf, mFp, mIradius);
        out++;
        x1++;
    }

    while(x2 > x1) {
        OneHU1(mSizeX, out, x1, buf, mFp, mIradius);
        out++;
        x1++;
    }
}

只需要下载 renderscript-intrinsics-replacement-toolkit ,编译 renderscript-toolkit 模块 ,引用即可
也可直接下载已经编译好的文件 renderscript-toolkit-debug-1.0.0.aar 引用

implementation (project(":renderscript-toolkit"))   
//或者如下方式,引入下载的aar
implementation (files("libs/renderscript-toolkit-debug-1.0.0.aar"))

使用方法如下

Toolkit.blur(inputBitmap, radius, null)

Toolkit 和 RenderScript 效率对比

结果如下,可以看到 Toolkit 在部分场景已经超越 RenderScript,特别是在处理小图时

D  FastBlur 1898X3069 cost time: 1055
D  RSBlur 1898X3069 cost time: 42
D  Toolkit 1898X3069 cost time: 29

以上内容源码地址 https://gitee.com/chenjim/android-blur/

Toolkit 是不是最终的方案呢?
如果对性能有更高的要求,还可以使用 Vulkan、RenderEffect 继续优化

本文首发地址 https://blog.csdn.net/CSqingchen/article/details/43817975

Bitmap缩放处理

对于模糊处理,bitmap尺寸越小,处理的越迅速。
为了达到需要的模糊效果,通常我们需要对输入 bitmap 缩放的处理,缩放代码如下:

/**
 * 比例压缩图片
 *
 * @param sourceBitmap 源bitmap
 * @param scaleFactor  大于1,将bitmap缩小
 * @return 缩小scaleFactor倍后的bitmap
 */
public static Bitmap compressBitmap(Bitmap sourceBitmap, float scaleFactor) {
    Bitmap overlay = Bitmap.createBitmap((int) (sourceBitmap.getWidth() / scaleFactor),
            (int) (sourceBitmap.getHeight() / scaleFactor), Config.ARGB_8888);
    Canvas canvas = new Canvas(overlay);
    canvas.translate(0, 0);
    canvas.scale(1 / scaleFactor, 1 / scaleFactor);
    Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);
    canvas.drawBitmap(sourceBitmap, 0, 0, paint);
    return overlay;
}

改变图片的对比度/明暗度

详细说明见代码注释,示例代码

/**
 * 改变图片对比度,达到使图片明暗变化的效果
 *
 * @param srcBitmap source bitmap
 * @param contrast  图片亮度,0:全黑;小于1,比原图暗;1.0f原图;大于1比原图亮
 * @return bitmap
 */
public static Bitmap darkBitmap(Bitmap srcBitmap, float contrast) {

    float offset = (float) 0.0; //picture RGB offset

    int imgHeight, imgWidth;
    imgHeight = srcBitmap.getHeight();
    imgWidth = srcBitmap.getWidth();

    Bitmap bmp = Bitmap.createBitmap(imgWidth, imgHeight, Config.ARGB_8888);
    ColorMatrix cMatrix = new ColorMatrix();
    cMatrix.set(new float[]{contrast, 0, 0, 0, offset,
            0, contrast, 0, 0, offset,
            0, 0, contrast, 0, offset,
            0, 0, 0, 1, 0});

    Paint paint = new Paint();
    paint.setColorFilter(new ColorMatrixColorFilter(cMatrix));

    Canvas canvas = new Canvas(bmp);
    canvas.drawBitmap(srcBitmap, 0, 0, paint);

    return bmp;
}

以上就是基于 ScriptIntrinsicBlur 和 Toolkit 对 Bitmap 模糊实现,希望对你有所帮助。
如果你在使用过程遇到问题,可以留言讨论。
如果你觉得本文写的还不错,欢迎点赞+收藏。


相关文章
Android Bitmap 使用 ScriptIntrinsicBlur、Toolkit 实现模糊
Android Bitmap 使用Vukan、RenderEffect、GLSL实现模糊)

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Android实现模糊背景的方式有很多种,其中一个比较常见的方式是使用RenderScript库。具体实现步骤如下: 1. 创建一个新的RenderScript资源文件,例如blur.rs。 2. 在blur.rs文件中编写模糊处理的脚本。例如,可以使用高斯模糊算法来实现模糊效果。 3. 在Java代码中创建一个RenderScript对象,并将模糊处理的脚本加载到RenderScript中。 4. 创建一个Bitmap对象,并使用BitmapFactory从资源文件中加载需要模糊的图片。 5. 将Bitmap对象转换为Allocation对象,并将其传递给RenderScript对象进行模糊处理。 6. 将处理后的Allocation对象重新转换为Bitmap对象,并将其设置为需要模糊的View的背景。 具体的代码实现可以参考以下示例: ``` // 创建RenderScript对象 RenderScript rs = RenderScript.create(context); // 加载模糊处理脚本 ScriptIntrinsicBlur script = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs)); // 创建一个Bitmap对象 Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.background); // 将Bitmap对象转换为Allocation对象 Allocation input = Allocation.createFromBitmap(rs, bitmap); // 将Allocation对象传递给RenderScript对象进行模糊处理 script.setInput(input); script.setRadius(25.0f); Allocation output = Allocation.createTyped(rs, input.getType()); script.forEach(output); // 将处理后的Allocation对象重新转换为Bitmap对象 Bitmap blurredBitmap = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), bitmap.getConfig()); output.copyTo(blurredBitmap); // 将处理后的Bitmap对象设置为需要模糊的View的背景 view.setBackground(new BitmapDrawable(context.getResources(), blurredBitmap)); ``` 注意:以上代码只是一个示例,具体实现方式可能会因为应用场景的不同而有所差异。同时,模糊处理可能会影响应用的性能,需要根据具体情况进行优化。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

清霜辰

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值