ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

Android图片纵向(竖直)模糊算法

2022-07-18 18:04:06  阅读:489  来源: 互联网

标签:int 模糊 bitmap pix 算法 竖直 0x000000ff radius Android


高斯模糊是用得最广泛的图像模糊算法,它的原理很简单,对每个点计算它周围其他点的平均色值,设置到该点上,就是模糊后的图。取周围其他点的范围称为模糊半径,模糊半径越大也就越模糊。高斯模糊算法网上很多,可以参考这个:
http://www.quasimondo.com/StackBlurForCanvas/StackBlurDemo.html

然而最近项目需要图片在竖直方向上模糊,网上找了一下没有发现相应算法,于是自己写了一个。原理跟高斯模糊相似,由于只有一个方向,比高斯模糊少了一个维度,因此简单很多:

  1. 把图像Bitmap每一列的像素的ARGB(透明度和红绿蓝)值取出来
  2. 透明度不变,红绿蓝值分别根据模糊半径,跟竖直方向上相邻的点算平均值
  3. 将计算后的ARGB值合成新的像素,创建新的Bitmap
public static Bitmap verticalBlur(Bitmap sentBitmap, int radius, boolean canReuseInBitmap) {
        Bitmap bitmap;
        if (canReuseInBitmap) {
            bitmap = sentBitmap;
        } else {
            bitmap = sentBitmap.copy(sentBitmap.getConfig(), true);
        }

        int w = bitmap.getWidth();
        int h = bitmap.getHeight();
        int hm = h - 1;
        if (radius < 1) return bitmap;
        if(radius > hm / 2) radius = hm / 2;

        int[] pix = new int[w * h];
        bitmap.getPixels(pix, 0, w, 0, 0, w, h);


        int[] a = new int[h];
        int[] r = new int[h];
        int[] g = new int[h];
        int[] b = new int[h];

        for(int i = 0; i < w; i++) {
            a[0] = pix[i] & 0xff000000;
            r[0] = pix[i] >> 16 & 0x000000ff;
            g[0] = pix[i] >> 8 & 0x000000ff;
            b[0] = pix[i] & 0x000000ff;
            for(int j = 1; j < h; j++) {
                int p = pix[i + j * w];
                a[j] = (p & 0xff000000);
                r[j] = (p >> 16 & 0x000000ff) + r[j - 1];
                g[j] = (p >> 8 & 0x000000ff) + g[j - 1];
                b[j] = (p & 0x000000ff) + b[j - 1];
            }

            for(int j = 0; j < h; j++) {
                int low = j - radius, high = j + radius;
                if(low < 0) low = 0;
                if(high > hm) high = hm;
                int len = high - low;
                int rj = ((r[high] - r[low]) / len) << 16;
                int gj = ((g[high] - g[low]) / len) << 8;
                int bj = (b[high] - b[low]) / len;
                pix[i + j * w] = a[j] | rj | gj | bj;
            }
        }

        bitmap.setPixels(pix, 0, w, 0, 0, w, h);
        return bitmap;
    }

由于是在Java层计算的,为了提高效率,有一些技巧:

bitmap.getPixels()方法将bitmap转换成一个一维数组int[], 直接操作数组是计算效率最高的

尽量使用位运算, 像素的ARGB值恰好占一个int的四个八位, 取出和合成它们用 &| 就行

重复计算一个数组中相邻几项的和只需要累加一次. 比如有数组A, 要计算从A[i]到A[j]的和, 先创建数组B, B[0] = A[0], B[1] = B[0] + A[1], B[i] = B[i - 1] + A[i]..., 这样累加一次后,从A[i]到A[j]的和就等于B[j] - B[i - 1].

这样模糊一张500*500的图片大概需要十几ms. 效果如下:
模糊半径小

模糊半径大

标签:int,模糊,bitmap,pix,算法,竖直,0x000000ff,radius,Android
来源: https://www.cnblogs.com/rome753/p/16491422.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有