Android 实时滤镜 高斯模糊(带源码)

最近在做一个这样一个需求,一个控件可以实时预览摄像头的内容,并且对此图像进行高斯模糊处理,现在来记录一下。 
              1. 这里写图片描述

基本的实现思路

1,摄像头实时预览的数据会回调给onPreviewFrame(byte[] data, Camera camera) ,通过这个获取YUV格式的数据。 
2,将YUV转换成RGB数组。 
3,cpu计算rgb数组或者gpu来处理图像。(这里用的cpu计算) 
github上有一个GPU实现高斯滤镜的开源项目,但是我觉得它的高斯模糊实现的不够好。 
android-gpuimage

开始onPreviewFrame(data)YUV420SP转RGBdoBlur()CPU计算结束
一,YUV420SP

在onPreviewFrame文档中有这么一段话。

<code class="language-java hljs  has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background: transparent;"> <span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**
     * Callback interface used to deliver copies of preview frames as
     * they are displayed.
     *
     *<span class="hljs-javadoctag" style="color: rgb(102, 0, 102); box-sizing: border-box;"> @see</span> #setPreviewCallback(Camera.PreviewCallback)
     *<span class="hljs-javadoctag" style="color: rgb(102, 0, 102); box-sizing: border-box;"> @see</span> #setOneShotPreviewCallback(Camera.PreviewCallback)
     *<span class="hljs-javadoctag" style="color: rgb(102, 0, 102); box-sizing: border-box;"> @see</span> #setPreviewCallbackWithBuffer(Camera.PreviewCallback)
     *<span class="hljs-javadoctag" style="color: rgb(102, 0, 102); box-sizing: border-box;"> @see</span> #startPreview()
     */</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">interface</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">PreviewCallback</span>
    {</span>
        <span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**
         * Called as preview frames are displayed.  This callback is invoked
         * on the event thread {@link #open(int)} was called from.
         *
         * <p>If using the {@link android.graphics.ImageFormat#YV12} format,
         * refer to the equations in {@link Camera.Parameters#setPreviewFormat}
         * for the arrangement of the pixel data in the preview callback
         * buffers.
         *
         *<span class="hljs-javadoctag" style="color: rgb(102, 0, 102); box-sizing: border-box;"> @param</span> data the contents of the preview frame in the format defined
         *  by {@link android.graphics.ImageFormat}, which can be queried
         *  with {@link android.hardware.Camera.Parameters#getPreviewFormat()}.
         *  If {@link android.hardware.Camera.Parameters#setPreviewFormat(int)}
         *             is never called, the default will be the YCbCr_420_SP
         *             (NV21) format.
         *<span class="hljs-javadoctag" style="color: rgb(102, 0, 102); box-sizing: border-box;"> @param</span> camera the Camera service object.
         */</span>
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> onPreviewFrame(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">byte</span>[] data, Camera camera);
    };</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li></ul>

默认输出的格式YUV420SP,注释中的YCbCr就是YUV。 
YUV,分为三个分量,“Y”表示明亮度(Luminance或Luma),也就是灰度值; 
而“U”和“V” 表示的则是色度(Chrominance或Chroma),作用是描述影像色彩及饱和度,用于指定像素的颜色。

下面是拥有8个像素的YUV数组[4*2],YUV420SP即4个Y对应一个UV,如图,Y1,Y2,Y9,Y10对应U1,V1。 
yuv420sp存储示例

二,YUV420SP转RGB

最主要是下面的转换公式:

<code class="hljs markdown has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background: transparent;">//ITU-R BT.601 conversion

R = 1.164<span class="hljs-emphasis" style="box-sizing: border-box;">*(Y-16)+1.596*</span>(Cr-128)
G = 1.164<span class="hljs-emphasis" style="box-sizing: border-box;">*(Y-16)-0.392*</span>(Cb-128)-0.813*(Cr-128)
B = 1.164<span class="hljs-emphasis" style="box-sizing: border-box;">*(Y-16)+2.017*</span>(Cb-128)
</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li></ul>

或者

<code class="hljs perl has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background: transparent;">R<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">''</span> = Y + <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1.140</span><span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">*V</span>
G<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">''</span> = Y - <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>.<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">394</span><span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">*U</span> - <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>.<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">581</span><span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">*V</span>
B<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">''</span> = Y + <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2.032</span><span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">*U</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li></ul>

只是工业标准不同而已。下面截取android-gpu-image上面的代码并添加一些注释,网上有很多转换的方法,但是这个方法性能非常ok,耗时在10-20ms。为了最大可能获取性能,代码中乘法等都变成了位操作和加法的方式。

<code class="language-c hljs  has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> YUVtoARBG(JNIEnv * env, jobject obj, jbyteArray yuv420sp, jint width, jint height, jintArray rgbOut)
{
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span>             sz;
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span>             i;
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span>             j;
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span>             Y;
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span>             Cr = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span>             Cb = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span>             pixPtr = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;  <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//Y所占的空间</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span>             jDiv2 = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;  <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//uv前面行所占的空间</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span>             R = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span>             G = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span>             B = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span>             cOff;
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> w = width;
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> h = height;
    sz = w * h;

    jint *rgbData = (jint*) ((*env)->GetPrimitiveArrayCritical(env, rgbOut, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>));
    jbyte* yuv = (jbyte*) (*env)->GetPrimitiveArrayCritical(env, yuv420sp, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>);

    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span>(j = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>; j < h; j++) {
             pixPtr = j * w;     <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//Y所占的空间</span>
             jDiv2 = j >> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>;    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//除以2向下取整</span>
             <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span>(i = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>; i < w; i++) {
                     Y = yuv[pixPtr];
                     <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span>(Y < <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>) Y += <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">255</span>;
                      <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//用位运算判断是奇数还是偶数</span>
                     <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span>((i & <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0x1</span>) != <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>) {
                             cOff = sz + jDiv2 * w + (i >> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>) * <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>;  <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//计算 UV的位置  (i>>1)*2就是为了变成偶数  向下取整  因为U的游标都是偶数位</span>
                             Cb = yuv[cOff];
                             <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span>(Cb < <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>) Cb += <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">127</span>; <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">else</span> Cb -= <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">128</span>;
                             Cr = yuv[cOff + <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>];
                             <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span>(Cr < <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>) Cr += <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">127</span>; <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">else</span> Cr -= <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">128</span>;
                     }

                     <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//ITU-R BT.601 conversion</span>
                     <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//</span>
                     <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//     R = 1.164*(Y-16)+1.596*(Cr-128)</span>
                     <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//     G = 1.164*(Y-16)-0.392*(Cb-128)-0.813*(Cr-128)</span>
                     <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//     B = 1.164*(Y-16)+2.017*(Cb-128)</span>
                     <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//</span>

                     Y = Y + (Y >> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span>) + (Y >> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">5</span>) + (Y >> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">7</span>);    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//Y=Y+Y*0.125+0.03125+0.00078</span>
                     R = Y + Cb + (Cb >> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>) + (Cb >> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">4</span>) + (Cb >> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">5</span>);
                     <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span>(R < <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>) R = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>; <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">else</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span>(R > <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">255</span>) R = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">255</span>;
                     G = Y - Cb + (Cb >> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span>) + (Cb >> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">4</span>) - (Cr >> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>) + (Cr >> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span>);
                     <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span>(G < <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>) G = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>; <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">else</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span>(G > <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">255</span>) G = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">255</span>;
                     B = Y + (Cr << <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>) + (Cr >> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">6</span>);
                     <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span>(B < <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>) B = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>; <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">else</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span>(B > <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">255</span>) B = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">255</span>;
                     rgbData[pixPtr++] = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0xff000000</span> + (R << <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">16</span>) + (G << <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">8</span>) + B;
             }
    }

    (*env)->ReleasePrimitiveArrayCritical(env, rgbOut, rgbData, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>);
    (*env)->ReleasePrimitiveArrayCritical(env, yuv420sp, yuv, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>);
}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li><li style="box-sizing: border-box; padding: 0px 5px;">34</li><li style="box-sizing: border-box; padding: 0px 5px;">35</li><li style="box-sizing: border-box; padding: 0px 5px;">36</li><li style="box-sizing: border-box; padding: 0px 5px;">37</li><li style="box-sizing: border-box; padding: 0px 5px;">38</li><li style="box-sizing: border-box; padding: 0px 5px;">39</li><li style="box-sizing: border-box; padding: 0px 5px;">40</li><li style="box-sizing: border-box; padding: 0px 5px;">41</li><li style="box-sizing: border-box; padding: 0px 5px;">42</li><li style="box-sizing: border-box; padding: 0px 5px;">43</li><li style="box-sizing: border-box; padding: 0px 5px;">44</li><li style="box-sizing: border-box; padding: 0px 5px;">45</li><li style="box-sizing: border-box; padding: 0px 5px;">46</li><li style="box-sizing: border-box; padding: 0px 5px;">47</li><li style="box-sizing: border-box; padding: 0px 5px;">48</li><li style="box-sizing: border-box; padding: 0px 5px;">49</li><li style="box-sizing: border-box; padding: 0px 5px;">50</li><li style="box-sizing: border-box; padding: 0px 5px;">51</li><li style="box-sizing: border-box; padding: 0px 5px;">52</li><li style="box-sizing: border-box; padding: 0px 5px;">53</li><li style="box-sizing: border-box; padding: 0px 5px;">54</li><li style="box-sizing: border-box; padding: 0px 5px;">55</li><li style="box-sizing: border-box; padding: 0px 5px;">56</li><li style="box-sizing: border-box; padding: 0px 5px;">57</li></ul>
三,高斯模糊

至于原理请看:高斯模糊 
这里用的FastBlur,之前考虑了RenderScript ,后来发现在实际使用中,最下方会出现闪烁的现象,故放弃。

<code class="language-java hljs  has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">static</span> Bitmap <span class="hljs-title" style="box-sizing: border-box;">doBlur</span>(Bitmap sentBitmap, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> radius, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">boolean</span> canReuseInBitmap) {

        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// Stack Blur v1.0 from</span>
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// http://www.quasimondo.com/StackBlurForCanvas/StackBlurDemo.html</span>
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//</span>
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// Java Author: Mario Klingemann <mario at quasimondo.com></span>
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// http://incubator.quasimondo.com</span>
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// created Feburary 29, 2004</span>
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// Android port : Yahel Bouaziz <yahel at kayenko.com></span>
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// http://www.kayenko.com</span>
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// ported april 5th, 2012</span>

        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// This is a compromise between Gaussian Blur and Box blur</span>
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// It creates much better looking blurs than Box Blur, but is</span>
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 7x faster than my Gaussian Blur implementation.</span>
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//</span>
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// I called it Stack Blur because this describes best how this</span>
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// filter works internally: it creates a kind of moving stack</span>
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// of colors whilst scanning through the image. Thereby it</span>
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// just has to add one new block of color to the right side</span>
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// of the stack and remove the leftmost color. The remaining</span>
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// colors on the topmost layer of the stack are either added on</span>
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// or reduced by one, depending on if they are on the right or</span>
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// on the left side of the stack.</span>
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//</span>
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// If you are using this algorithm in your code please add</span>
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// the following line:</span>
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//</span>
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// Stack Blur Algorithm by Mario Klingemann <mario@quasimondo.com></span>

        Bitmap bitmap;
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (canReuseInBitmap) {
            bitmap = sentBitmap;
        } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">else</span> {
            bitmap = sentBitmap.copy(sentBitmap.getConfig(), <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">true</span>);
        }

        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (radius < <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>) {
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> (<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>);
        }

        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> w = bitmap.getWidth();
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> h = bitmap.getHeight();

        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span>[] pix = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span>[w * h];
        bitmap.getPixels(pix, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, w, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, w, h);

        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> wm = w - <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>;
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> hm = h - <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>;
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> wh = w * h;
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> div = radius + radius + <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>;

        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> r[] = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span>[wh];
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> g[] = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span>[wh];
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> b[] = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span>[wh];
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> rsum, gsum, bsum, x, y, i, p, yp, yi, yw;
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> vmin[] = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span>[Math.max(w, h)];

        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> divsum = (div + <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>) >> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>;
        divsum *= divsum;
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> dv[] = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span>[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">256</span> * divsum];
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span> (i = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>; i < <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">256</span> * divsum; i++) {
            dv[i] = (i / divsum);
        }

        yw = yi = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;

        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span>[][] stack = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span>[div][<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span>];
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> stackpointer;
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> stackstart;
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span>[] sir;
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> rbs;
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> r1 = radius + <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>;
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> routsum, goutsum, boutsum;
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> rinsum, ginsum, binsum;

        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span> (y = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>; y < h; y++) {
            rinsum = ginsum = binsum = routsum = goutsum = boutsum = rsum = gsum = bsum = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span> (i = -radius; i <= radius; i++) {
                p = pix[yi + Math.min(wm, Math.max(i, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>))];
                sir = stack[i + radius];
                sir[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>] = (p & <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0xff0000</span>) >> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">16</span>;
                sir[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>] = (p & <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0x00ff00</span>) >> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">8</span>;
                sir[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>] = (p & <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0x0000ff</span>);
                rbs = r1 - Math.abs(i);
                rsum += sir[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>] * rbs;
                gsum += sir[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>] * rbs;
                bsum += sir[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>] * rbs;
                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (i > <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>) {
                    rinsum += sir[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>];
                    ginsum += sir[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>];
                    binsum += sir[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>];
                } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">else</span> {
                    routsum += sir[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>];
                    goutsum += sir[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>];
                    boutsum += sir[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>];
                }
            }
            stackpointer = radius;

            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span> (x = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>; x < w; x++) {

                r[yi] = dv[rsum];
                g[yi] = dv[gsum];
                b[yi] = dv[bsum];

                rsum -= routsum;
                gsum -= goutsum;
                bsum -= boutsum;

                stackstart = stackpointer - radius + div;
                sir = stack[stackstart % div];

                routsum -= sir[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>];
                goutsum -= sir[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>];
                boutsum -= sir[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>];

                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (y == <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>) {
                    vmin[x] = Math.min(x + radius + <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>, wm);
                }
                p = pix[yw + vmin[x]];

                sir[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>] = (p & <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0xff0000</span>) >> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">16</span>;
                sir[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>] = (p & <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0x00ff00</span>) >> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">8</span>;
                sir[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>] = (p & <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0x0000ff</span>);

                rinsum += sir[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>];
                ginsum += sir[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>];
                binsum += sir[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>];

                rsum += rinsum;
                gsum += ginsum;
                bsum += binsum;

                stackpointer = (stackpointer + <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>) % div;
                sir = stack[(stackpointer) % div];

                routsum += sir[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>];
                goutsum += sir[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>];
                boutsum += sir[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>];

                rinsum -= sir[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>];
                ginsum -= sir[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>];
                binsum -= sir[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>];

                yi++;
            }
            yw += w;
        }
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span> (x = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>; x < w; x++) {
            rinsum = ginsum = binsum = routsum = goutsum = boutsum = rsum = gsum = bsum = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;
            yp = -radius * w;
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span> (i = -radius; i <= radius; i++) {
                yi = Math.max(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, yp) + x;

                sir = stack[i + radius];

                sir[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>] = r[yi];
                sir[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>] = g[yi];
                sir[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>] = b[yi];

                rbs = r1 - Math.abs(i);

                rsum += r[yi] * rbs;
                gsum += g[yi] * rbs;
                bsum += b[yi] * rbs;

                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (i > <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>) {
                    rinsum += sir[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>];
                    ginsum += sir[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>];
                    binsum += sir[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>];
                } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">else</span> {
                    routsum += sir[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>];
                    goutsum += sir[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>];
                    boutsum += sir[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>];
                }

                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (i < hm) {
                    yp += w;
                }
            }
            yi = x;
            stackpointer = radius;
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span> (y = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>; y < h; y++) {
                <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// Preserve alpha channel: ( 0xff000000 & pix[yi] )</span>
                pix[yi] = (<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0xff000000</span> & pix[yi]) | (dv[rsum] << <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">16</span>) | (dv[gsum] << <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">8</span>) | dv[bsum];

                rsum -= routsum;
                gsum -= goutsum;
                bsum -= boutsum;

                stackstart = stackpointer - radius + div;
                sir = stack[stackstart % div];

                routsum -= sir[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>];
                goutsum -= sir[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>];
                boutsum -= sir[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>];

                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (x == <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>) {
                    vmin[y] = Math.min(y + r1, hm) * w;
                }
                p = x + vmin[y];

                sir[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>] = r[p];
                sir[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>] = g[p];
                sir[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>] = b[p];

                rinsum += sir[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>];
                ginsum += sir[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>];
                binsum += sir[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>];

                rsum += rinsum;
                gsum += ginsum;
                bsum += binsum;

                stackpointer = (stackpointer + <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>) % div;
                sir = stack[stackpointer];

                routsum += sir[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>];
                goutsum += sir[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>];
                boutsum += sir[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>];

                rinsum -= sir[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>];
                ginsum -= sir[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>];
                binsum -= sir[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>];

                yi += w;
            }
        }

        bitmap.setPixels(pix, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, w, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, w, h);

        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> (bitmap);
    }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li><li style="box-sizing: border-box; padding: 0px 5px;">34</li><li style="box-sizing: border-box; padding: 0px 5px;">35</li><li style="box-sizing: border-box; padding: 0px 5px;">36</li><li style="box-sizing: border-box; padding: 0px 5px;">37</li><li style="box-sizing: border-box; padding: 0px 5px;">38</li><li style="box-sizing: border-box; padding: 0px 5px;">39</li><li style="box-sizing: border-box; padding: 0px 5px;">40</li><li style="box-sizing: border-box; padding: 0px 5px;">41</li><li style="box-sizing: border-box; padding: 0px 5px;">42</li><li style="box-sizing: border-box; padding: 0px 5px;">43</li><li style="box-sizing: border-box; padding: 0px 5px;">44</li><li style="box-sizing: border-box; padding: 0px 5px;">45</li><li style="box-sizing: border-box; padding: 0px 5px;">46</li><li style="box-sizing: border-box; padding: 0px 5px;">47</li><li style="box-sizing: border-box; padding: 0px 5px;">48</li><li style="box-sizing: border-box; padding: 0px 5px;">49</li><li style="box-sizing: border-box; padding: 0px 5px;">50</li><li style="box-sizing: border-box; padding: 0px 5px;">51</li><li style="box-sizing: border-box; padding: 0px 5px;">52</li><li style="box-sizing: border-box; padding: 0px 5px;">53</li><li style="box-sizing: border-box; padding: 0px 5px;">54</li><li style="box-sizing: border-box; padding: 0px 5px;">55</li><li style="box-sizing: border-box; padding: 0px 5px;">56</li><li style="box-sizing: border-box; padding: 0px 5px;">57</li><li style="box-sizing: border-box; padding: 0px 5px;">58</li><li style="box-sizing: border-box; padding: 0px 5px;">59</li><li style="box-sizing: border-box; padding: 0px 5px;">60</li><li style="box-sizing: border-box; padding: 0px 5px;">61</li><li style="box-sizing: border-box; padding: 0px 5px;">62</li><li style="box-sizing: border-box; padding: 0px 5px;">63</li><li style="box-sizing: border-box; padding: 0px 5px;">64</li><li style="box-sizing: border-box; padding: 0px 5px;">65</li><li style="box-sizing: border-box; padding: 0px 5px;">66</li><li style="box-sizing: border-box; padding: 0px 5px;">67</li><li style="box-sizing: border-box; padding: 0px 5px;">68</li><li style="box-sizing: border-box; padding: 0px 5px;">69</li><li style="box-sizing: border-box; padding: 0px 5px;">70</li><li style="box-sizing: border-box; padding: 0px 5px;">71</li><li style="box-sizing: border-box; padding: 0px 5px;">72</li><li style="box-sizing: border-box; padding: 0px 5px;">73</li><li style="box-sizing: border-box; padding: 0px 5px;">74</li><li style="box-sizing: border-box; padding: 0px 5px;">75</li><li style="box-sizing: border-box; padding: 0px 5px;">76</li><li style="box-sizing: border-box; padding: 0px 5px;">77</li><li style="box-sizing: border-box; padding: 0px 5px;">78</li><li style="box-sizing: border-box; padding: 0px 5px;">79</li><li style="box-sizing: border-box; padding: 0px 5px;">80</li><li style="box-sizing: border-box; padding: 0px 5px;">81</li><li style="box-sizing: border-box; padding: 0px 5px;">82</li><li style="box-sizing: border-box; padding: 0px 5px;">83</li><li style="box-sizing: border-box; padding: 0px 5px;">84</li><li style="box-sizing: border-box; padding: 0px 5px;">85</li><li style="box-sizing: border-box; padding: 0px 5px;">86</li><li style="box-sizing: border-box; padding: 0px 5px;">87</li><li style="box-sizing: border-box; padding: 0px 5px;">88</li><li style="box-sizing: border-box; padding: 0px 5px;">89</li><li style="box-sizing: border-box; padding: 0px 5px;">90</li><li style="box-sizing: border-box; padding: 0px 5px;">91</li><li style="box-sizing: border-box; padding: 0px 5px;">92</li><li style="box-sizing: border-box; padding: 0px 5px;">93</li><li style="box-sizing: border-box; padding: 0px 5px;">94</li><li style="box-sizing: border-box; padding: 0px 5px;">95</li><li style="box-sizing: border-box; padding: 0px 5px;">96</li><li style="box-sizing: border-box; padding: 0px 5px;">97</li><li style="box-sizing: border-box; padding: 0px 5px;">98</li><li style="box-sizing: border-box; padding: 0px 5px;">99</li><li style="box-sizing: border-box; padding: 0px 5px;">100</li><li style="box-sizing: border-box; padding: 0px 5px;">101</li><li style="box-sizing: border-box; padding: 0px 5px;">102</li><li style="box-sizing: border-box; padding: 0px 5px;">103</li><li style="box-sizing: border-box; padding: 0px 5px;">104</li><li style="box-sizing: border-box; padding: 0px 5px;">105</li><li style="box-sizing: border-box; padding: 0px 5px;">106</li><li style="box-sizing: border-box; padding: 0px 5px;">107</li><li style="box-sizing: border-box; padding: 0px 5px;">108</li><li style="box-sizing: border-box; padding: 0px 5px;">109</li><li style="box-sizing: border-box; padding: 0px 5px;">110</li><li style="box-sizing: border-box; padding: 0px 5px;">111</li><li style="box-sizing: border-box; padding: 0px 5px;">112</li><li style="box-sizing: border-box; padding: 0px 5px;">113</li><li style="box-sizing: border-box; padding: 0px 5px;">114</li><li style="box-sizing: border-box; padding: 0px 5px;">115</li><li style="box-sizing: border-box; padding: 0px 5px;">116</li><li style="box-sizing: border-box; padding: 0px 5px;">117</li><li style="box-sizing: border-box; padding: 0px 5px;">118</li><li style="box-sizing: border-box; padding: 0px 5px;">119</li><li style="box-sizing: border-box; padding: 0px 5px;">120</li><li style="box-sizing: border-box; padding: 0px 5px;">121</li><li style="box-sizing: border-box; padding: 0px 5px;">122</li><li style="box-sizing: border-box; padding: 0px 5px;">123</li><li style="box-sizing: border-box; padding: 0px 5px;">124</li><li style="box-sizing: border-box; padding: 0px 5px;">125</li><li style="box-sizing: border-box; padding: 0px 5px;">126</li><li style="box-sizing: border-box; padding: 0px 5px;">127</li><li style="box-sizing: border-box; padding: 0px 5px;">128</li><li style="box-sizing: border-box; padding: 0px 5px;">129</li><li style="box-sizing: border-box; padding: 0px 5px;">130</li><li style="box-sizing: border-box; padding: 0px 5px;">131</li><li style="box-sizing: border-box; padding: 0px 5px;">132</li><li style="box-sizing: border-box; padding: 0px 5px;">133</li><li style="box-sizing: border-box; padding: 0px 5px;">134</li><li style="box-sizing: border-box; padding: 0px 5px;">135</li><li style="box-sizing: border-box; padding: 0px 5px;">136</li><li style="box-sizing: border-box; padding: 0px 5px;">137</li><li style="box-sizing: border-box; padding: 0px 5px;">138</li><li style="box-sizing: border-box; padding: 0px 5px;">139</li><li style="box-sizing: border-box; padding: 0px 5px;">140</li><li style="box-sizing: border-box; padding: 0px 5px;">141</li><li style="box-sizing: border-box; padding: 0px 5px;">142</li><li style="box-sizing: border-box; padding: 0px 5px;">143</li><li style="box-sizing: border-box; padding: 0px 5px;">144</li><li style="box-sizing: border-box; padding: 0px 5px;">145</li><li style="box-sizing: border-box; padding: 0px 5px;">146</li><li style="box-sizing: border-box; padding: 0px 5px;">147</li><li style="box-sizing: border-box; padding: 0px 5px;">148</li><li style="box-sizing: border-box; padding: 0px 5px;">149</li><li style="box-sizing: border-box; padding: 0px 5px;">150</li><li style="box-sizing: border-box; padding: 0px 5px;">151</li><li style="box-sizing: border-box; padding: 0px 5px;">152</li><li style="box-sizing: border-box; padding: 0px 5px;">153</li><li style="box-sizing: border-box; padding: 0px 5px;">154</li><li style="box-sizing: border-box; padding: 0px 5px;">155</li><li style="box-sizing: border-box; padding: 0px 5px;">156</li><li style="box-sizing: border-box; padding: 0px 5px;">157</li><li style="box-sizing: border-box; padding: 0px 5px;">158</li><li style="box-sizing: border-box; padding: 0px 5px;">159</li><li style="box-sizing: border-box; padding: 0px 5px;">160</li><li style="box-sizing: border-box; padding: 0px 5px;">161</li><li style="box-sizing: border-box; padding: 0px 5px;">162</li><li style="box-sizing: border-box; padding: 0px 5px;">163</li><li style="box-sizing: border-box; padding: 0px 5px;">164</li><li style="box-sizing: border-box; padding: 0px 5px;">165</li><li style="box-sizing: border-box; padding: 0px 5px;">166</li><li style="box-sizing: border-box; padding: 0px 5px;">167</li><li style="box-sizing: border-box; padding: 0px 5px;">168</li><li style="box-sizing: border-box; padding: 0px 5px;">169</li><li style="box-sizing: border-box; padding: 0px 5px;">170</li><li style="box-sizing: border-box; padding: 0px 5px;">171</li><li style="box-sizing: border-box; padding: 0px 5px;">172</li><li style="box-sizing: border-box; padding: 0px 5px;">173</li><li style="box-sizing: border-box; padding: 0px 5px;">174</li><li style="box-sizing: border-box; padding: 0px 5px;">175</li><li style="box-sizing: border-box; padding: 0px 5px;">176</li><li style="box-sizing: border-box; padding: 0px 5px;">177</li><li style="box-sizing: border-box; padding: 0px 5px;">178</li><li style="box-sizing: border-box; padding: 0px 5px;">179</li><li style="box-sizing: border-box; padding: 0px 5px;">180</li><li style="box-sizing: border-box; padding: 0px 5px;">181</li><li style="box-sizing: border-box; padding: 0px 5px;">182</li><li style="box-sizing: border-box; padding: 0px 5px;">183</li><li style="box-sizing: border-box; padding: 0px 5px;">184</li><li style="box-sizing: border-box; padding: 0px 5px;">185</li><li style="box-sizing: border-box; padding: 0px 5px;">186</li><li style="box-sizing: border-box; padding: 0px 5px;">187</li><li style="box-sizing: border-box; padding: 0px 5px;">188</li><li style="box-sizing: border-box; padding: 0px 5px;">189</li><li style="box-sizing: border-box; padding: 0px 5px;">190</li><li style="box-sizing: border-box; padding: 0px 5px;">191</li><li style="box-sizing: border-box; padding: 0px 5px;">192</li><li style="box-sizing: border-box; padding: 0px 5px;">193</li><li style="box-sizing: border-box; padding: 0px 5px;">194</li><li style="box-sizing: border-box; padding: 0px 5px;">195</li><li style="box-sizing: border-box; padding: 0px 5px;">196</li><li style="box-sizing: border-box; padding: 0px 5px;">197</li><li style="box-sizing: border-box; padding: 0px 5px;">198</li><li style="box-sizing: border-box; padding: 0px 5px;">199</li><li style="box-sizing: border-box; padding: 0px 5px;">200</li><li style="box-sizing: border-box; padding: 0px 5px;">201</li><li style="box-sizing: border-box; padding: 0px 5px;">202</li><li style="box-sizing: border-box; padding: 0px 5px;">203</li><li style="box-sizing: border-box; padding: 0px 5px;">204</li><li style="box-sizing: border-box; padding: 0px 5px;">205</li><li style="box-sizing: border-box; padding: 0px 5px;">206</li><li style="box-sizing: border-box; padding: 0px 5px;">207</li><li style="box-sizing: border-box; padding: 0px 5px;">208</li><li style="box-sizing: border-box; padding: 0px 5px;">209</li><li style="box-sizing: border-box; padding: 0px 5px;">210</li><li style="box-sizing: border-box; padding: 0px 5px;">211</li><li style="box-sizing: border-box; padding: 0px 5px;">212</li><li style="box-sizing: border-box; padding: 0px 5px;">213</li><li style="box-sizing: border-box; padding: 0px 5px;">214</li><li style="box-sizing: border-box; padding: 0px 5px;">215</li><li style="box-sizing: border-box; padding: 0px 5px;">216</li><li style="box-sizing: border-box; padding: 0px 5px;">217</li><li style="box-sizing: border-box; padding: 0px 5px;">218</li><li style="box-sizing: border-box; padding: 0px 5px;">219</li><li style="box-sizing: border-box; padding: 0px 5px;">220</li><li style="box-sizing: border-box; padding: 0px 5px;">221</li><li style="box-sizing: border-box; padding: 0px 5px;">222</li><li style="box-sizing: border-box; padding: 0px 5px;">223</li><li style="box-sizing: border-box; padding: 0px 5px;">224</li><li style="box-sizing: border-box; padding: 0px 5px;">225</li><li style="box-sizing: border-box; padding: 0px 5px;">226</li><li style="box-sizing: border-box; padding: 0px 5px;">227</li><li style="box-sizing: border-box; padding: 0px 5px;">228</li><li style="box-sizing: border-box; padding: 0px 5px;">229</li><li style="box-sizing: border-box; padding: 0px 5px;">230</li><li style="box-sizing: border-box; padding: 0px 5px;">231</li><li style="box-sizing: border-box; padding: 0px 5px;">232</li><li style="box-sizing: border-box; padding: 0px 5px;">233</li><li style="box-sizing: border-box; padding: 0px 5px;">234</li></ul>

为了获取进一步的性能,我们可以做以下操作: 
1,设置一个vector,当vector中存在对象时,丢弃当前帧,绘制完后,清空vector,保证vector最多只有一个对象。 
2,先对图片进行缩小处理,高斯模糊后再放大。

<code class="language-java hljs  has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background: transparent;">        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//每次只处理一个图像,若前面的图像未处理完成,舍弃当前图像,提升性能</span>
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span>(mVector.isEmpty()){
            Log.i(TAG, <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"byte data ADD"</span>);
            mVector.add(data);
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> DrawTask().execute();
        }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li></ul><div class="save_code tracking-ad" data-mod="popu_249" style="box-sizing: border-box; position: absolute; height: 60px; right: 30px; top: 5px; color: rgb(255, 255, 255); cursor: pointer; z-index: 2;"><a target=_blank target="_blank" style="box-sizing: border-box; color: rgb(12, 137, 207);"><img src="http://static.blog.csdn.net/images/save_snippets.png" style="border: none; box-sizing: border-box;" alt="" /></a></div>

因为onPreviewFrame()在主线程中,所以绘图一定要异步进行。

这里一个例子,提供大家参考:下载地址

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值