Image blur for Android picture processing

Source: Internet
Author: User
Tags gety image processing library vmin

This article will give you an introduction to the high-efficiency approach to Android image processing, we have the need to refer to the time.

First of all, I want to explain the effect of this example (I will not make a GIF, if anyone would, I would like to teach me): Through the fingers of the picture to slide up and down, to achieve the gradual blur effect of the picture.

Look for the Internet to find the following (infringement please notify Delete):



Let me explain the idea of effect making.

The first is the fuzzy processing of the image, the most common fuzzy processing method is Gaussian blur, Gaussian blur specifies a radius radius, for each pixel on the picture, centered on it, there is a radius of a long square (except for the boundary point, but can be calculated in a symmetrical way), For each point on this square, the weights (weights are calculated from the normal distribution function) are multiplied and then averaged, replacing the value of the center point with that mean.

Gaussian blur efficiency is low, processing time is very long, GitHub has a fast fuzzy algorithm, next we will use.

In addition, Android actually provides an efficient image processing library renderscript, using this library we can also quickly blur the image.

Here's what I wrote, a picture of a fuzzy processing class

public class Bitmapblurhelper {//Zoom factor public final static int scale = 8; /** * Blur function * @param context * @param sentbitmap * @param radius * @return */public static BITM        AP Doblur (Context context, Bitmap Sentbitmap, float radius) {if (sentbitmap==null) return null; if (radius <= 0 | | radius >) radius = 25f;//range between 1-25 if (radius<=6&&version. Sdk_int > 16) {//tested, radius greater than 6, fastblur more efficient, and renderscript above api11 use Bitmap Bitmap = Bitmap.createscaledbit Map (Sentbitmap, Sentbitmap.getwidth ()/scale,sentbitmap.getheight ()/scale,false);//Zoom the picture first, increase the blur speed final RENDERSCRI            PT rs = renderscript.create (context);                    Final Allocation input = Allocation.createfrombitmap (rs, Bitmap, Allocation.MipmapControl.MIPMAP_NONE,            Allocation.usage_script);            Final Allocation output = allocation.createtyped (RS, Input.gettype ()); Final Scriptintrinsicblur script = ScriptintrinSicblur.create (RS, Element.u8_4 (RS));            Script.setradius (RADIUS);            Script.setinput (input);            Script.foreach (output);            Output.copyto (bitmap);            Rs.destroy ();        return bitmap;        }else{//fast Blur return Fastblur (Sentbitmap,radius); }}/** * fast blur algorithm * @param sbitmap * @param radiusf * @return * Stack Blur v1.0 from * http:/ /www.quasimondo.com/stackblurforcanvas/stackblurdemo.html * Java Author:mario Klingemann <mario at quasimondo.com&     Gt * Http://incubator.quasimondo.com * created Feburary, 2004 * Android Port:yahel Bouaziz <yahel at Kayenko.  com> * http://www.kayenko.com * ported April 5th, * This is a compromise between Gaussian Blur and Box Blur * It creates much better looking blurs than Box blur, but is * 7x faster than my Gaussian blur Implementatio N. * I called it Stack Blur because this describes best how this * filTER works Internally:it creates a kind of moving stack * of colors whilst scanning through the image. thereby it * just have to add one new block of color to the right side * of the stack and remove the leftmost color . The remaining * colors on the topmost layer of the stack is either added on * or reduced by one, depending on if     They is on the ' right ' or * on the ' left side of the stack. * If You is using this algorithm in your code please add * the following line: * * Stack Blur algorithm by Ma        Rio Klingemann <[email protected]> * * public static Bitmap Fastblur (Bitmap sbitmap, float radiusf) { Bitmap Bitmap = Bitmap.createscaledbitmap (Sbitmap, Sbitmap.getwidth ()/scale,sbitmap.getheight ()/scale,false);//        Zoom the image first, increase the blur speed int radius = (int) radiusf;        if (RADIUS < 1) {return (NULL);        } int w = Bitmap.getwidth ();        int h = bitmap.getheight ();        int[] pix = new int[w * h]; BiTmap.getpixels (pix, 0, W, 0, 0, W, h);        int wm = W-1;        int HM = H-1;        int WH = w * h;        int div = radius + radius + 1;        int r[] = new INT[WH];        int g[] = new INT[WH];        int b[] = new INT[WH];        int rsum, gsum, Bsum, x, Y, I, p, yp, Yi, yw;        int vmin[] = new Int[math.max (W, h)];        int divsum = (div + 1) >> 1;        Divsum *= divsum;        int dv[] = new int[256 * Divsum];        for (i = 0; i < * divsum; i++) {Dv[i] = (i/divsum);        } yw = Yi = 0;        int[][] stack = new INT[DIV][3];        int stackpointer;        int Stackstart;        Int[] Sir;        int RBS;        int r1 = radius + 1;        int routsum, goutsum, boutsum;        int rinsum, ginsum, binsum;            for (y = 0; y < h; y++) {rinsum = Ginsum = Binsum = Routsum = Goutsum = Boutsum = Rsum = gsum = bsum = 0; for (i =-radius; I <= radius; i++) {p = pix[yi + math.min (WM, Math).Max (i, 0))];                Sir = stack[i + radius];                Sir[0] = (P & 0xff0000) >> 16;                SIR[1] = (P & 0x00ff00) >> 8;                SIR[2] = (P & 0x0000ff);                RBS = R1-math.abs (i);                Rsum + = sir[0] * RBS;                Gsum + = sir[1] * RBS;                Bsum + = sir[2] * RBS;                    if (i > 0) {rinsum + = sir[0];                    Ginsum + = sir[1];                Binsum + = sir[2];                    } else {routsum + = sir[0];                    Goutsum + = sir[1];                Boutsum + = sir[2];            }} stackpointer = radius;                for (x = 0; x < W; + +) {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[0];                Goutsum-= sir[1];                Boutsum-= sir[2];                if (y = = 0) {Vmin[x] = math.min (x + radius + 1, WM);                } p = Pix[yw + vmin[x]];                Sir[0] = (P & 0xff0000) >> 16;                SIR[1] = (P & 0x00ff00) >> 8;                SIR[2] = (P & 0x0000ff);                Rinsum + = sir[0];                Ginsum + = sir[1];                Binsum + = sir[2];                Rsum + = Rinsum;                Gsum + = Ginsum;                Bsum + = Binsum;                Stackpointer = (stackpointer + 1)% Div;                sir = stack[(stackpointer)% div];                Routsum + = sir[0];                Goutsum + = sir[1];                Boutsum + = sir[2];                Rinsum-= sir[0];                Ginsum-= sir[1];                Binsum-= sir[2];            yi++;        } yw + = W;} for (x = 0; x < W; + +) {rinsum = Ginsum = Binsum = Routsum = Goutsum = Boutsum = Rsum = Gsum = BS            um = 0;            YP =-radius * W;                for (i =-radius; I <= radius; i++) {Yi = Math.max (0, YP) + x;                Sir = stack[i + radius];                Sir[0] = R[yi];                SIR[1] = G[yi];                SIR[2] = B[yi];                RBS = R1-math.abs (i);                Rsum + = r[yi] * RBS;                Gsum + = g[yi] * RBS;                Bsum + = b[yi] * RBS;                    if (i > 0) {rinsum + = sir[0];                    Ginsum + = sir[1];                Binsum + = sir[2];                    } else {routsum + = sir[0];                    Goutsum + = sir[1];                Boutsum + = sir[2];                } if (I < HM) {YP + = W;            }} yi = x;            Stackpointer = radius; for (y = 0; y < H y++) {//Preserve alpha channel: (0xff000000 & Pix[yi]) pix[yi] = (0xff000000 & P Ix[yi]) | (Dv[rsum] << 16) | (Dv[gsum] << 8) |                Dv[bsum];                Rsum-= routsum;                Gsum-= goutsum;                Bsum-= boutsum;                Stackstart = Stackpointer-radius + div;                sir = Stack[stackstart% div];                Routsum-= sir[0];                Goutsum-= sir[1];                Boutsum-= sir[2];                if (x = = 0) {Vmin[y] = math.min (y + r1, HM) * W;                } p = x + vmin[y];                Sir[0] = r[p];                SIR[1] = g[p];                SIR[2] = b[p];                Rinsum + = sir[0];                Ginsum + = sir[1];                Binsum + = sir[2];                Rsum + = Rinsum;                Gsum + = Ginsum;                Bsum + = Binsum;                Stackpointer = (stackpointer + 1)% Div; sir = Stack[stackPointer];                Routsum + = sir[0];                Goutsum + = sir[1];                Boutsum + = sir[2];                Rinsum-= sir[0];                Ginsum-= sir[1];                Binsum-= sir[2];            Yi + = w;        }} bitmap.setpixels (pix, 0, W, 0, 0, W, h);    return (bitmap); }}

From the above code we can see that I first scaled the picture, and this was done to speed up the blurring process.

If we do not scale the image in advance, whether it is called fast blur or Renderscript, will require a long time to calculate, for the maximum blur effect, the former needs more than 2000ms, the latter need to need more than 500ms, this efficiency is obviously unacceptable.

Our fuzzy coefficient range is 1-25, because the coefficient requirement of renderscript is this range (the reason is unknown, but the exception is thrown out).

For the picture to zoom, I found a magical place, is the fast blur efficiency actually catch up with the efficiency of renderscript, in radius of 6, renderscript higher, within 20ms, and fast blur need 200ms within, but after 6, Fast Blur is only within 20ms, and Renderscript is more than 20ms, and the gap increases with radius.

So in the code, we use the two according to the boundary of 6, and the other renderscript requires more than API 11 to be used.


OK, the origin of the image of the fuzzy processing method, we now want to achieve the dynamic effect of the picture, the simple idea is to monitor the movement of the fingers, and then each time the image is blurred.

The difficulty with this approach is that the GPU is drawing faster than the fuzzy algorithm, which means that the fuzzy calculation takes a long time, which causes the program to lag.


My idea is to first take the picture to the maximum blur, get a picture of the most blurred, and then the clear picture (below) and blur picture (above) overlay, in the process of finger movement, modify the transparency of blurred image, so as to achieve from clear to transparent transition effect.

How to achieve picture overlay? I used the Layerdrawable class and constructed a blurdrawable class

/**  * Blur drawable */public class blurdrawable{    //Top/Bottom Two-layer picture    private drawable[] array = new DRAWABLE[2];    Cascade Pictures    Private layerdrawable la;    /**     * @param context     * @param res     * @param bitmap     *    /Public blurdrawable (context context, Resources Res, Bitmap Bitmap) {        array[0] = new bitmapdrawable (res,bitmap);        ARRAY[1] = new Bitmapdrawable (Res,bitmapblurhelper.doblur (context,bitmap,25));//production of blurred picture        Array[1].setalpha (0);        La = new layerdrawable (array);        La.setlayerinset (0, 0, 0, 0, 0);//Cascade        La.setlayerinset (1, 0, 0, 0, 0);    }    /**     * Returns the picture after stack     * @return     *    /Public layerdrawable getblurdrawable () {        return LA;    }    /**     * Gets the blur factor, which is essentially transparency     * @return *     /public    int Getblur () {        return Array[1].getalpha ();    }    /**     * Set the blur factor     * @param alpha *     /public    void Setblur (int alpha) {        array[1].setalpha (alpha);    }}


The above code is very simple, I believe you can also understand, the last is to set drawable for ImageView, and then add a Onclicklistener

        Mblurimage = (ImageView) Findviewbyid (r.id.img);        Final Bitmap bp = Bitmapfactory.decoderesource (Getresources (), R.DRAWABLE.SSD);        Final blurdrawable blurdrawable = new Blurdrawable (this, getresources (), BP);               Mblurimage.setimagedrawable (Blurdrawable.getblurdrawable ());            Mblurimage.setontouchlistener (New View.ontouchlistener () {private float mlasty;                    @Override public boolean OnTouch (View V, motionevent event) {switch (event.getaction ()) {                        Case MotionEvent.ACTION_DOWN:mLastY = Event.gety ();                    Break                        Case MotionEvent.ACTION_MOVE:float y = event.gety ();                        float Alphadelt = (y-mlasty)/50;                        int alpha = (int) (Blurdrawable.getblur () + Alphadelt);                        LOG.I ("Time", Alpha + "");                 if (Alpha > 255) {           Alpha = 255;                        } else if (Alpha < 0.0) {alpha = 0;                        } blurdrawable.setblur (Alpha);                    Break                Case MotionEvent.ACTION_UP:break;            } return true;         }        });

Since the range of transparency is 0-255, our blur coefficients are also from 0 to 255

Only at the end of the action_move process, it is possible to modify the transparency of the blurdrawable, and the transparency change method I also provide


Ok, so far, the transparency effect is realized, we look at the copy code to see, personally think this code is a good example of image obfuscation.

Reprint Please specify the source Oh!

Copyright NOTICE: This article for Bo Master original article, without Bo Master permission not reproduced.

Image blur for Android picture processing

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.