========================================================
作者:qiujuer
博客:blog.csdn.net/qiujuer
网站:www.qiujuer.net
开源库:Genius-Android
转载请注明出处:http://blog.csdn.net/qiujuer/article/details/41777001
========================================================

在我的博客中,曾经发布了一篇高斯模糊(堆栈模糊)的文章;在其中使用了国外的一个堆栈模糊来实现对图片的模糊处理;同时弄了一个JNI C++ 的版本。

这篇文章依然是堆栈模糊;可以说最原始的地方还是堆栈模糊部分;只不过是支持多线程的。

纳尼??感情是之前那个不支持多线程?Sorry,我说错了;两个都是支持多线程调用的。不过新讲的这个是能在内部采用多线程进行分段模糊。

原来的:[Android]-图片JNI(C++\Java)高斯模糊的实现与比较

开工吧

说明:其中代码大部分来源于网络,不过都是开源的。

最原始的代码:

stackblur.cpp
// The Stack Blur Algorithm was invented by Mario Klingemann,
// mario@quasimondo.com and described here:
// http://incubator.quasimondo.com/processing/fast_blur_deluxe.php// This is C++ RGBA (32 bit color) multi-threaded version
// by Victor Laskin (victor.laskin@gmail.com)
// More details: http://vitiy.info/stackblur-algorithm-multi-threaded-blur-for-cpp// This code is using MVThread class from my cross-platform framework
// You can exchange it with any thread implementation you like// -------------------------------------- stackblur ----------------------------------------->static unsigned short const stackblur_mul[255] =
{512,512,456,512,328,456,335,512,405,328,271,456,388,335,292,512,454,405,364,328,298,271,496,456,420,388,360,335,312,292,273,512,482,454,428,405,383,364,345,328,312,298,284,271,259,496,475,456,437,420,404,388,374,360,347,335,323,312,302,292,282,273,265,512,497,482,468,454,441,428,417,405,394,383,373,364,354,345,337,328,320,312,305,298,291,284,278,271,265,259,507,496,485,475,465,456,446,437,428,420,412,404,396,388,381,374,367,360,354,347,341,335,329,323,318,312,307,302,297,292,287,282,278,273,269,265,261,512,505,497,489,482,475,468,461,454,447,441,435,428,422,417,411,405,399,394,389,383,378,373,368,364,359,354,350,345,341,337,332,328,324,320,316,312,309,305,301,298,294,291,287,284,281,278,274,271,268,265,262,259,257,507,501,496,491,485,480,475,470,465,460,456,451,446,442,437,433,428,424,420,416,412,408,404,400,396,392,388,385,381,377,374,370,367,363,360,357,354,350,347,344,341,338,335,332,329,326,323,320,318,315,312,310,307,304,302,299,297,294,292,289,287,285,282,280,278,275,273,271,269,267,265,263,261,259
};static unsigned char const stackblur_shr[255] =
{9, 11, 12, 13, 13, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 17,17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 18, 19,19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 20, 20, 20,20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 21,21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22,22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23,23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24
};/// Stackblur algorithm body
void stackblurJob(unsigned char* src,               ///< input image dataunsigned int w,                 ///< image widthunsigned int h,                  ///< image heightunsigned int radius,                ///< blur intensity (should be in 2..254 range)int cores,                        ///< total number of working threadsint core,                            ///< current thread numberint step,                          ///< step of processing (1,2)unsigned char* stack                ///< stack buffer)
{unsigned int x, y, xp, yp, i;unsigned int sp;unsigned int stack_start;unsigned char* stack_ptr;unsigned char* src_ptr;unsigned char* dst_ptr;unsigned long sum_r;unsigned long sum_g;unsigned long sum_b;unsigned long sum_a;unsigned long sum_in_r;unsigned long sum_in_g;unsigned long sum_in_b;unsigned long sum_in_a;unsigned long sum_out_r;unsigned long sum_out_g;unsigned long sum_out_b;unsigned long sum_out_a;unsigned int wm = w - 1;unsigned int hm = h - 1;unsigned int w4 = w * 4;unsigned int div = (radius * 2) + 1;unsigned int mul_sum = stackblur_mul[radius];unsigned char shr_sum = stackblur_shr[radius];if (step == 1){int minY = core * h / cores;int maxY = (core + 1) * h / cores;for(y = minY; y < maxY; y++){sum_r = sum_g = sum_b = sum_a =sum_in_r = sum_in_g = sum_in_b = sum_in_a =sum_out_r = sum_out_g = sum_out_b = sum_out_a = 0;src_ptr = src + w4 * y; // start of line (0,y)for(i = 0; i <= radius; i++){stack_ptr    = &stack[ 4 * i ];stack_ptr[0] = src_ptr[0];stack_ptr[1] = src_ptr[1];stack_ptr[2] = src_ptr[2];stack_ptr[3] = src_ptr[3];sum_r += src_ptr[0] * (i + 1);sum_g += src_ptr[1] * (i + 1);sum_b += src_ptr[2] * (i + 1);sum_a += src_ptr[3] * (i + 1);sum_out_r += src_ptr[0];sum_out_g += src_ptr[1];sum_out_b += src_ptr[2];sum_out_a += src_ptr[3];}for(i = 1; i <= radius; i++){if (i <= wm) src_ptr += 4;stack_ptr = &stack[ 4 * (i + radius) ];stack_ptr[0] = src_ptr[0];stack_ptr[1] = src_ptr[1];stack_ptr[2] = src_ptr[2];stack_ptr[3] = src_ptr[3];sum_r += src_ptr[0] * (radius + 1 - i);sum_g += src_ptr[1] * (radius + 1 - i);sum_b += src_ptr[2] * (radius + 1 - i);sum_a += src_ptr[3] * (radius + 1 - i);sum_in_r += src_ptr[0];sum_in_g += src_ptr[1];sum_in_b += src_ptr[2];sum_in_a += src_ptr[3];}sp = radius;xp = radius;if (xp > wm) xp = wm;src_ptr = src + 4 * (xp + y * w); //   img.pix_ptr(xp, y);dst_ptr = src + y * w4; // img.pix_ptr(0, y);for(x = 0; x < w; x++){dst_ptr[0] = (sum_r * mul_sum) >> shr_sum;dst_ptr[1] = (sum_g * mul_sum) >> shr_sum;dst_ptr[2] = (sum_b * mul_sum) >> shr_sum;dst_ptr[3] = (sum_a * mul_sum) >> shr_sum;dst_ptr += 4;sum_r -= sum_out_r;sum_g -= sum_out_g;sum_b -= sum_out_b;sum_a -= sum_out_a;stack_start = sp + div - radius;if (stack_start >= div) stack_start -= div;stack_ptr = &stack[4 * stack_start];sum_out_r -= stack_ptr[0];sum_out_g -= stack_ptr[1];sum_out_b -= stack_ptr[2];sum_out_a -= stack_ptr[3];if(xp < wm){src_ptr += 4;++xp;}stack_ptr[0] = src_ptr[0];stack_ptr[1] = src_ptr[1];stack_ptr[2] = src_ptr[2];stack_ptr[3] = src_ptr[3];sum_in_r += src_ptr[0];sum_in_g += src_ptr[1];sum_in_b += src_ptr[2];sum_in_a += src_ptr[3];sum_r    += sum_in_r;sum_g    += sum_in_g;sum_b    += sum_in_b;sum_a    += sum_in_a;++sp;if (sp >= div) sp = 0;stack_ptr = &stack[sp*4];sum_out_r += stack_ptr[0];sum_out_g += stack_ptr[1];sum_out_b += stack_ptr[2];sum_out_a += stack_ptr[3];sum_in_r  -= stack_ptr[0];sum_in_g  -= stack_ptr[1];sum_in_b  -= stack_ptr[2];sum_in_a  -= stack_ptr[3];}}}// step 2if (step == 2){int minX = core * w / cores;int maxX = (core + 1) * w / cores;for(x = minX; x < maxX; x++){sum_r =   sum_g =    sum_b =    sum_a =sum_in_r = sum_in_g = sum_in_b = sum_in_a =sum_out_r = sum_out_g = sum_out_b = sum_out_a = 0;src_ptr = src + 4 * x; // x,0for(i = 0; i <= radius; i++){stack_ptr    = &stack[i * 4];stack_ptr[0] = src_ptr[0];stack_ptr[1] = src_ptr[1];stack_ptr[2] = src_ptr[2];stack_ptr[3] = src_ptr[3];sum_r           += src_ptr[0] * (i + 1);sum_g           += src_ptr[1] * (i + 1);sum_b           += src_ptr[2] * (i + 1);sum_a           += src_ptr[3] * (i + 1);sum_out_r       += src_ptr[0];sum_out_g       += src_ptr[1];sum_out_b       += src_ptr[2];sum_out_a       += src_ptr[3];}for(i = 1; i <= radius; i++){if(i <= hm) src_ptr += w4; // +stridestack_ptr = &stack[4 * (i + radius)];stack_ptr[0] = src_ptr[0];stack_ptr[1] = src_ptr[1];stack_ptr[2] = src_ptr[2];stack_ptr[3] = src_ptr[3];sum_r += src_ptr[0] * (radius + 1 - i);sum_g += src_ptr[1] * (radius + 1 - i);sum_b += src_ptr[2] * (radius + 1 - i);sum_a += src_ptr[3] * (radius + 1 - i);sum_in_r += src_ptr[0];sum_in_g += src_ptr[1];sum_in_b += src_ptr[2];sum_in_a += src_ptr[3];}sp = radius;yp = radius;if (yp > hm) yp = hm;src_ptr = src + 4 * (x + yp * w); // img.pix_ptr(x, yp);dst_ptr = src + 4 * x;             // img.pix_ptr(x, 0);for(y = 0; y < h; y++){dst_ptr[0] = (sum_r * mul_sum) >> shr_sum;dst_ptr[1] = (sum_g * mul_sum) >> shr_sum;dst_ptr[2] = (sum_b * mul_sum) >> shr_sum;dst_ptr[3] = (sum_a * mul_sum) >> shr_sum;dst_ptr += w4;sum_r -= sum_out_r;sum_g -= sum_out_g;sum_b -= sum_out_b;sum_a -= sum_out_a;stack_start = sp + div - radius;if(stack_start >= div) stack_start -= div;stack_ptr = &stack[4 * stack_start];sum_out_r -= stack_ptr[0];sum_out_g -= stack_ptr[1];sum_out_b -= stack_ptr[2];sum_out_a -= stack_ptr[3];if(yp < hm){src_ptr += w4; // stride++yp;}stack_ptr[0] = src_ptr[0];stack_ptr[1] = src_ptr[1];stack_ptr[2] = src_ptr[2];stack_ptr[3] = src_ptr[3];sum_in_r += src_ptr[0];sum_in_g += src_ptr[1];sum_in_b += src_ptr[2];sum_in_a += src_ptr[3];sum_r    += sum_in_r;sum_g    += sum_in_g;sum_b    += sum_in_b;sum_a    += sum_in_a;++sp;if (sp >= div) sp = 0;stack_ptr = &stack[sp*4];sum_out_r += stack_ptr[0];sum_out_g += stack_ptr[1];sum_out_b += stack_ptr[2];sum_out_a += stack_ptr[3];sum_in_r  -= stack_ptr[0];sum_in_g  -= stack_ptr[1];sum_in_b  -= stack_ptr[2];sum_in_a  -= stack_ptr[3];}}}}class MVImageUtilsStackBlurTask : public MVThread
{
public:unsigned char* src;unsigned int w;unsigned int h;unsigned int radius;int cores;int core;int step;unsigned char* stack;inline MVImageUtilsStackBlurTask(unsigned char* src, unsigned int w, unsigned int h, unsigned int radius, int cores, int core, int step, unsigned char* stack){this->src = src;this->w = w;this->h = h;this->radius = radius;this->cores = cores;this->core = core;this->step = step;this->stack = stack;}inline void run(){stackblurJob(src, w, h, radius, cores, core, step, stack);}};/// Stackblur algorithm by Mario Klingemann
/// Details here:
/// http://www.quasimondo.com/StackBlurForCanvas/StackBlurDemo.html
/// C++ implemenation base from:
/// https://gist.github.com/benjamin9999/3809142
/// http://www.antigrain.com/__code/include/agg_blur.h.html
/// This version works only with RGBA color
void               stackblur(unsigned char* src,                ///< input image dataunsigned int w,                 ///< image widthunsigned int h,                  ///< image heightunsigned int radius,                ///< blur intensity (should be in 2..254 range)int cores = 1                        ///< number of threads (1 - normal single thread))
{if (radius > 254) return;if (radius < 2) return;unsigned int div = (radius * 2) + 1;unsigned char* stack = new unsigned char [div * 4 * cores];if (cores == 1){// no multithreadingstackblurJob(src, w, h, radius, 1, 0, 1, stack);stackblurJob(src, w, h, radius, 1, 0, 2, stack);}else{MVImageUtilsStackBlurTask** workers = new MVImageUtilsStackBlurTask*[cores];for (int i = 0; i < cores; i++){workers[i] = new MVImageUtilsStackBlurTask(src, w, h, radius, cores, i, 1, stack + div * 4 * i);workers[i]->start();}for (int i = 0; i < cores; i++)workers[i]->wait();for (int i = 0; i < cores; i++){workers[i]->step = 2;workers[i]->start();}for (int i = 0; i < cores; i++){workers[i]->wait();delete workers[i];}delete[] workers;}delete[] stack;
}

这个是C++的代码。

在网上发现了一个开源的 Android 模糊的例子,其中有该代码的 Java 版本。

JavaBlurProcess.java
import android.graphics.Bitmap;import java.util.ArrayList;
import java.util.concurrent.Callable;class JavaBlurProcess implements BlurProcess {private static final short[] stackblur_mul = {512, 512, 456, 512, 328, 456, 335, 512, 405, 328, 271, 456, 388, 335, 292, 512,454, 405, 364, 328, 298, 271, 496, 456, 420, 388, 360, 335, 312, 292, 273, 512,482, 454, 428, 405, 383, 364, 345, 328, 312, 298, 284, 271, 259, 496, 475, 456,437, 420, 404, 388, 374, 360, 347, 335, 323, 312, 302, 292, 282, 273, 265, 512,497, 482, 468, 454, 441, 428, 417, 405, 394, 383, 373, 364, 354, 345, 337, 328,320, 312, 305, 298, 291, 284, 278, 271, 265, 259, 507, 496, 485, 475, 465, 456,446, 437, 428, 420, 412, 404, 396, 388, 381, 374, 367, 360, 354, 347, 341, 335,329, 323, 318, 312, 307, 302, 297, 292, 287, 282, 278, 273, 269, 265, 261, 512,505, 497, 489, 482, 475, 468, 461, 454, 447, 441, 435, 428, 422, 417, 411, 405,399, 394, 389, 383, 378, 373, 368, 364, 359, 354, 350, 345, 341, 337, 332, 328,324, 320, 316, 312, 309, 305, 301, 298, 294, 291, 287, 284, 281, 278, 274, 271,268, 265, 262, 259, 257, 507, 501, 496, 491, 485, 480, 475, 470, 465, 460, 456,451, 446, 442, 437, 433, 428, 424, 420, 416, 412, 408, 404, 400, 396, 392, 388,385, 381, 377, 374, 370, 367, 363, 360, 357, 354, 350, 347, 344, 341, 338, 335,332, 329, 326, 323, 320, 318, 315, 312, 310, 307, 304, 302, 299, 297, 294, 292,289, 287, 285, 282, 280, 278, 275, 273, 271, 269, 267, 265, 263, 261, 259};private static final byte[] stackblur_shr = {9, 11, 12, 13, 13, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 17,17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 18, 19,19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 20, 20, 20,20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 21,21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22,22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23,23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24};@Overridepublic Bitmap blur(Bitmap original, float radius) {int w = original.getWidth();int h = original.getHeight();int[] currentPixels = new int[w * h];original.getPixels(currentPixels, 0, w, 0, 0, w, h);int cores = StackBlurManager.EXECUTOR_THREADS;ArrayList<BlurTask> horizontal = new ArrayList<BlurTask>(cores);ArrayList<BlurTask> vertical = new ArrayList<BlurTask>(cores);for (int i = 0; i < cores; i++) {horizontal.add(new BlurTask(currentPixels, w, h, (int) radius, cores, i, 1));vertical.add(new BlurTask(currentPixels, w, h, (int) radius, cores, i, 2));}try {StackBlurManager.EXECUTOR.invokeAll(horizontal);} catch (InterruptedException e) {return null;}try {StackBlurManager.EXECUTOR.invokeAll(vertical);} catch (InterruptedException e) {return null;}return Bitmap.createBitmap(currentPixels, w, h, Bitmap.Config.ARGB_8888);}private static void blurIteration(int[] src, int w, int h, int radius, int cores, int core, int step) {int x, y, xp, yp, i;int sp;int stack_start;int stack_i;int src_i;int dst_i;long sum_r, sum_g, sum_b,sum_in_r, sum_in_g, sum_in_b,sum_out_r, sum_out_g, sum_out_b;int wm = w - 1;int hm = h - 1;int div = (radius * 2) + 1;int mul_sum = stackblur_mul[radius];byte shr_sum = stackblur_shr[radius];int[] stack = new int[div];if (step == 1){int minY = core * h / cores;int maxY = (core + 1) * h / cores;for(y = minY; y < maxY; y++){sum_r = sum_g = sum_b =sum_in_r = sum_in_g = sum_in_b =sum_out_r = sum_out_g = sum_out_b = 0;src_i = w * y; // start of line (0,y)for(i = 0; i <= radius; i++){stack_i    = i;stack[stack_i] = src[src_i];sum_r += ((src[src_i] >>> 16) & 0xff) * (i + 1);sum_g += ((src[src_i] >>> 8) & 0xff) * (i + 1);sum_b += (src[src_i] & 0xff) * (i + 1);sum_out_r += ((src[src_i] >>> 16) & 0xff);sum_out_g += ((src[src_i] >>> 8) & 0xff);sum_out_b += (src[src_i] & 0xff);}for(i = 1; i <= radius; i++){if (i <= wm) src_i += 1;stack_i = i + radius;stack[stack_i] = src[src_i];sum_r += ((src[src_i] >>> 16) & 0xff) * (radius + 1 - i);sum_g += ((src[src_i] >>> 8) & 0xff) * (radius + 1 - i);sum_b += (src[src_i] & 0xff) * (radius + 1 - i);sum_in_r += ((src[src_i] >>> 16) & 0xff);sum_in_g += ((src[src_i] >>> 8) & 0xff);sum_in_b += (src[src_i] & 0xff);}sp = radius;xp = radius;if (xp > wm) xp = wm;src_i = xp + y * w; //   img.pix_ptr(xp, y);dst_i = y * w; // img.pix_ptr(0, y);for(x = 0; x < w; x++){src[dst_i] = (int)((src[dst_i] & 0xff000000) |((((sum_r * mul_sum) >>> shr_sum) & 0xff) << 16) |((((sum_g * mul_sum) >>> shr_sum) & 0xff) << 8) |((((sum_b * mul_sum) >>> shr_sum) & 0xff)));dst_i += 1;sum_r -= sum_out_r;sum_g -= sum_out_g;sum_b -= sum_out_b;stack_start = sp + div - radius;if (stack_start >= div) stack_start -= div;stack_i = stack_start;sum_out_r -= ((stack[stack_i] >>> 16) & 0xff);sum_out_g -= ((stack[stack_i] >>> 8) & 0xff);sum_out_b -= (stack[stack_i] & 0xff);if(xp < wm){src_i += 1;++xp;}stack[stack_i] = src[src_i];sum_in_r += ((src[src_i] >>> 16) & 0xff);sum_in_g += ((src[src_i] >>> 8) & 0xff);sum_in_b += (src[src_i] & 0xff);sum_r    += sum_in_r;sum_g    += sum_in_g;sum_b    += sum_in_b;++sp;if (sp >= div) sp = 0;stack_i = sp;sum_out_r += ((stack[stack_i] >>> 16) & 0xff);sum_out_g += ((stack[stack_i] >>> 8) & 0xff);sum_out_b += (stack[stack_i] & 0xff);sum_in_r  -= ((stack[stack_i] >>> 16) & 0xff);sum_in_g  -= ((stack[stack_i] >>> 8) & 0xff);sum_in_b  -= (stack[stack_i] & 0xff);}}}// step 2else if (step == 2){int minX = core * w / cores;int maxX = (core + 1) * w / cores;for(x = minX; x < maxX; x++){sum_r =    sum_g =    sum_b =sum_in_r = sum_in_g = sum_in_b =sum_out_r = sum_out_g = sum_out_b = 0;src_i = x; // x,0for(i = 0; i <= radius; i++){stack_i    = i;stack[stack_i] = src[src_i];sum_r           += ((src[src_i] >>> 16) & 0xff) * (i + 1);sum_g           += ((src[src_i] >>> 8) & 0xff) * (i + 1);sum_b           += (src[src_i] & 0xff) * (i + 1);sum_out_r       += ((src[src_i] >>> 16) & 0xff);sum_out_g       += ((src[src_i] >>> 8) & 0xff);sum_out_b       += (src[src_i] & 0xff);}for(i = 1; i <= radius; i++){if(i <= hm) src_i += w; // +stridestack_i = i + radius;stack[stack_i] = src[src_i];sum_r += ((src[src_i] >>> 16) & 0xff) * (radius + 1 - i);sum_g += ((src[src_i] >>> 8) & 0xff) * (radius + 1 - i);sum_b += (src[src_i] & 0xff) * (radius + 1 - i);sum_in_r += ((src[src_i] >>> 16) & 0xff);sum_in_g += ((src[src_i] >>> 8) & 0xff);sum_in_b += (src[src_i] & 0xff);}sp = radius;yp = radius;if (yp > hm) yp = hm;src_i = x + yp * w; // img.pix_ptr(x, yp);dst_i = x;               // img.pix_ptr(x, 0);for(y = 0; y < h; y++){src[dst_i] = (int)((src[dst_i] & 0xff000000) |((((sum_r * mul_sum) >>> shr_sum) & 0xff) << 16) |((((sum_g * mul_sum) >>> shr_sum) & 0xff) << 8) |((((sum_b * mul_sum) >>> shr_sum) & 0xff)));dst_i += w;sum_r -= sum_out_r;sum_g -= sum_out_g;sum_b -= sum_out_b;stack_start = sp + div - radius;if(stack_start >= div) stack_start -= div;stack_i = stack_start;sum_out_r -= ((stack[stack_i] >>> 16) & 0xff);sum_out_g -= ((stack[stack_i] >>> 8) & 0xff);sum_out_b -= (stack[stack_i] & 0xff);if(yp < hm){src_i += w; // stride++yp;}stack[stack_i] = src[src_i];sum_in_r += ((src[src_i] >>> 16) & 0xff);sum_in_g += ((src[src_i] >>> 8) & 0xff);sum_in_b += (src[src_i] & 0xff);sum_r    += sum_in_r;sum_g    += sum_in_g;sum_b    += sum_in_b;++sp;if (sp >= div) sp = 0;stack_i = sp;sum_out_r += ((stack[stack_i] >>> 16) & 0xff);sum_out_g += ((stack[stack_i] >>> 8) & 0xff);sum_out_b += (stack[stack_i] & 0xff);sum_in_r  -= ((stack[stack_i] >>> 16) & 0xff);sum_in_g  -= ((stack[stack_i] >>> 8) & 0xff);sum_in_b  -= (stack[stack_i] & 0xff);}}}}private static class BlurTask implements Callable<Void> {private final int[] _src;private final int _w;private final int _h;private final int _radius;private final int _totalCores;private final int _coreIndex;private final int _round;public BlurTask(int[] src, int w, int h, int radius, int totalCores, int coreIndex, int round) {_src = src;_w = w;_h = h;_radius = radius;_totalCores = totalCores;_coreIndex = coreIndex;_round = round;}@Override public Void call() throws Exception {blurIteration(_src, _w, _h, _radius, _totalCores, _coreIndex, _round);return null;}}
}

该代码与C++的代码同出一源。下面来简要分析一下。

分析

入口:
 public Bitmap blur(Bitmap original, float radius) {int w = original.getWidth();int h = original.getHeight();int[] currentPixels = new int[w * h];original.getPixels(currentPixels, 0, w, 0, 0, w, h);int cores = StackBlurManager.EXECUTOR_THREADS;ArrayList<BlurTask> horizontal = new ArrayList<BlurTask>(cores);ArrayList<BlurTask> vertical = new ArrayList<BlurTask>(cores);for (int i = 0; i < cores; i++) {horizontal.add(new BlurTask(currentPixels, w, h, (int) radius, cores, i, 1));vertical.add(new BlurTask(currentPixels, w, h, (int) radius, cores, i, 2));}try {StackBlurManager.EXECUTOR.invokeAll(horizontal);} catch (InterruptedException e) {return null;}try {StackBlurManager.EXECUTOR.invokeAll(vertical);} catch (InterruptedException e) {return null;}return Bitmap.createBitmap(currentPixels, w, h, Bitmap.Config.ARGB_8888);}

方法进入后,首先得到图片的像素点集合;而后 New 两个 List ,分别存储 BlurTask

看看 BlurTask :
 private static class BlurTask implements Callable<Void> {private final int[] _src;private final int _w;private final int _h;private final int _radius;private final int _totalCores;private final int _coreIndex;private final int _round;public BlurTask(int[] src, int w, int h, int radius, int totalCores, int coreIndex, int round) {_src = src;_w = w;_h = h;_radius = radius;_totalCores = totalCores;_coreIndex = coreIndex;_round = round;}@Override public Void call() throws Exception {blurIteration(_src, _w, _h, _radius, _totalCores, _coreIndex, _round);return null;}}

可以看出  BlurTask 是用于进行 线程池的回调类;其主要调用了方法  blurIteration进行模糊。

同时给方法,传入的参数有:

  • 像素点集合
  • 模糊半径
  • 最大内核数
  • 当前内核
步骤

而后回到第一步处:

int cores = StackBlurManager.EXECUTOR_THREADS;

其实是调用的:

Runtime.getRuntime().availableProcessors();

该方法用于返回当前虚拟机的核数;用此方法可以 最大效率的进行多线程的分配。

而后:

     for (int i = 0; i < cores; i++) {horizontal.add(new BlurTask(currentPixels, w, h, (int) radius, cores, i, 1));vertical.add(new BlurTask(currentPixels, w, h, (int) radius, cores, i, 2));}

可以看出往列表中加上,对应的线程回调操作;分别是 步骤1,和步骤2

而后:

     try {StackBlurManager.EXECUTOR.invokeAll(horizontal);} catch (InterruptedException e) {return null;}try {StackBlurManager.EXECUTOR.invokeAll(vertical);} catch (InterruptedException e) {return null;}

该方法中: StackBlurManager.EXECUTOR 其实是:

Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());

可以看出其实是建立了一个线程池,线程池的运行线程数为当前虚拟机的核数。

然后把步骤1的集合丢进线程池并等待执行完成;而后丢进步骤2.

其实从其命名就能看出:

  • 步骤1其实是模糊水平方向
  • 步骤2其实是模糊垂直方向

具体是不是可以看看 blurIteration 方法。

由于方法太长就简化了一下:

 private static void blurIteration(int[] src, int w, int h, int radius, int cores, int core, int step) {...if (step == 1){int minY = core * h / cores;int maxY = (core + 1) * h / cores;for(y = minY; y < maxY; y++){...}}// step 2else if (step == 2){int minX = core * w / cores;int maxX = (core + 1) * w / cores;for(x = minX; x < maxX; x++) <span style="white-space:pre">  </span>{<span style="white-space:pre">       </span>...<span style="white-space:pre"> </span>}}}

可以看出 分别进行了模糊水平与垂直。

同时,在模糊时:分为了许多部分,具体取决于虚拟核数。

在这里有必要说明一点就是;在模糊时只能先模糊第一步,而后才能模糊第二部。

意思就是说第一步与第二步是不能同时进行的;如果不赞同;可以啊把上面的两个列表改成一个同时进行多线程你就知道模糊的效果了。

测试

这里截图就不进行截图了,不过根据我的测试;该模糊方法在多线程下优势较为明显;也就是说手机核数越高其模糊速度越快。

如果该方法顺序执行,不使用多线程;那么其模糊所耗费时间约比我上一章中介绍的方法多1/4的时间。

下面其实,该开源项目做的很完善,同时包含了 Java,JNI C,RenderScript  三种方式进行模糊:

由于代码较多就不一一贴出来了。我打包上传了;需要的朋友可以自行下载。

源码

[Android] 图片JNI(C++\Java)高斯模糊 多线程 源码

========================================================
作者:qiujuer
博客:blog.csdn.net/qiujuer
网站:www.qiujuer.net
开源库:Genius-Android
转载请注明出处:http://blog.csdn.net/qiujuer/article/details/41777001
========================================================

[Android] 图片JNI(C++\Java)高斯模糊 多线程相关推荐

  1. android jni java调用c,Android与JNI(一) ---- Java调用C 静态调用

    第一.通过eclipse新建一个工程名为HelloJni的android工程,并编译. 第二.右键工程-->Android Tools --> Add Native Support,出现如 ...

  2. Android之jni调用java函数总结

    1.先看之前jni的如何实现动态注册 先看我之间的例子 http://blog.csdn.net/u011068702/article/details/71375920 Android之JNI动态注册 ...

  3. 关于 Delphi跨平台开发Android调用 JNI JAR java 的说明和注意事项

    2Pascal-新时代的Pascal-关于 调用 JNI JAR java 的说明和注意事项,调用第 靠写不下了 - Powered by Discuz! 关于 调用 JNI JAR 的说明和注意事项 ...

  4. Android NDK JNI C++ 13 pthread多线程

    这一篇将初步介绍NDK开发中多线程方面相关操作,具体步骤如下: 多线程采用 POSIX 的pthread方式实现. <1> : 新建一个Android工程 androidpthreadjn ...

  5. android 图片上传java,php服务器

    项目上传图片到后台,前端总是传不上去,翻阅代码,详细查看,原来是php的头和java的不同. 总体的思路是,可以拍照上传,也可以本地上传.利用onActivityResult,从返回的Intent中得 ...

  6. Android 调用JNI出错 java.lang.UnsatisfiedLinkError: No implementation found for

    主要原因就是包名不一致,自己在编译libmupdf.so 文件时Mupdf android项目中jni/mupdf.c文件里面的包名是 项目中是com.artifex.mupdf 这是最简单的解释方法 ...

  7. android 图片拉伸动画,java,Android_Android的属性动画的拉伸效果前后两次效果不一致,求解?,java,Android - phpStudy...

    Android的属性动画的拉伸效果前后两次效果不一致,求解? 开发过程中需要做五个点的上下拉伸效果,奇怪的是第一次进行拉伸的时候是正常的,但是第二次开始就不对了,加打印看也没问题啊,实在是找不到原因, ...

  8. 【我的Android进阶之旅】Android调用JNI出错 java.lang.UnsatisfiedLinkError: No implementation found for的解决方法

    一.错误描述 今天使用第三方的so库时候,调用JNI方法时出现了错误.报错如下所示: 11-01 16:39:20.979 4669-4669/com.netease.xtc.cloudmusic E ...

  9. Android 图片高斯模糊解决方案

    Android 图片高斯模糊解决方案 近年来,图片高斯模糊备受设计师的青睐,在各大知名APP中,如微信.手机QQ.网易云音乐等等都有对背景高斯图模糊的设计,在Adnroid 中,现在常用的图片高斯模糊 ...

  10. Android系统JNI使用(JAVA调用C语言接口)一

    目录 第一篇:Android系统JNI使用(JAVA调用C语言接口)一 什么是JNI JNI是Java Native Interface的缩写,它提供了若干的API实现了Java和其他语言的通信主要是 ...

最新文章

  1. 解决vs2015使用fopen、fprintf等函数报错的问题
  2. ECSTORE 关于FILTER条件所代表的含义
  3. C语言试题四十一之请编写一个函数,用来删除字符串中的所有空格。
  4. javascript/jquery获取图片的原始大小
  5. 备份Linux系统的数据到坚果云
  6. 5 天 6 亿 3000 万数据泄露,怎么做才能跑赢骗子?
  7. 版mysql客户端工具_【小白福利—初级DBA入门必看】MySQL常用工具介绍(三)——客户端工具MySQL...
  8. 第十二周项目2 - 摩托车继承自行车和机动车
  9. SET-Priority_Queue
  10. C语言 数据结构 结构体 LinkList
  11. iphone 竖屏的视频转换为横屏
  12. 【STC15系列】SYK-0806-A2S1 工业自动化控制之【05-定时器控制的流水灯】
  13. 基于TI AM5728 + Artix-7 FPGA开发板(DSP+ARM) 5G通信测试手册
  14. 无法更新到Win8.1的原因与解决办法
  15. 四面深信服(长沙)软件测试工程师10k,大概是长沙双休犯法吧笑
  16. echarts饼图圆环图数据为0时字体重叠
  17. CodeForces - 743B
  18. python报错“cannot import name ft2font”
  19. java中返回值空值(null)处理
  20. Mac必备软件13款,强烈推荐

热门文章

  1. smartMeter
  2. 强化学习各概念整理(value/policy-based、on/off-policy、model-based/free、offline)
  3. 【BZOJ 1036】树的统计【树链剖分模板】
  4. 实数系的连续性的含义
  5. NoSQLAttack针对 mongoDB 的攻击工具
  6. 操作系统面试常问问题
  7. 看完不后悔系列,SQL语句执行慢怎么办,原因总结!!
  8. 计算机主机光驱弹不出来怎么办,win7系统电脑按下光驱按钮托盘就是弹不出来怎么办...
  9. oracle dba_tables degree default,oracle中如何将表的并行度设定为DEFAULT?如下:
  10. STM32中assert_param的使用