Android
RenderScript
Sök…
Introduktion
RenderScript är ett skriptspråk som låter dig skriva högpresterande grafisk rendering och rå datakod. Det tillhandahåller ett sätt att skriva prestanda kritisk kod som systemet senare sammanställer till inbyggd kod för processorn som det kan köras på. Detta kan vara CPU, en flerkärnig CPU eller till och med GPU. Vilket den slutligen kör på beror på många faktorer som inte är lättillgängliga för utvecklaren, men beror också på vilken arkitektur den interna plattformskompilatorn stöder.
Komma igång
RenderScript är ett ramverk som tillåter högpresterande parallellberäkning på Android. Skript som du skriver kommer att köras över alla tillgängliga processorer (t.ex. CPU, GPU etc) parallellt så att du kan fokusera på den uppgift du vill utföra istället för hur den schemaläggs och körs.
Skript skrivs på ett C99-baserat språk (C99 är en gammal version av C-programmeringsspråkstandarden). För varje skript skapas en Java-klass som gör att du enkelt kan interagera med RenderScript i din Java-kod.
Ställa in ditt projekt
Det finns två olika sätt att komma åt RenderScript i din app, med Android Framework-biblioteken eller Support Library. Även om du inte vill rikta in sig på enheter före API-nivå 11 bör du alltid använda Support Library-implementeringen eftersom det garanterar enhetskompatibilitet på många olika enheter. För att kunna använda supportbibliotekets implementering måste du åtminstone använda verktyg för att bygga version 18.1.0
!
Låter nu konfigurera build.gradle-filen för din applikation:
android {
compileSdkVersion 24
buildToolsVersion '24.0.1'
defaultConfig {
minSdkVersion 8
targetSdkVersion 24
renderscriptTargetApi 18
renderscriptSupportModeEnabled true
}
}
-
renderscriptTargetApi
: Detta bör ställas in på den version av den tidigaste API-nivån som ger all RenderScript-funktionalitet du behöver. -
renderscriptSupportModeEnabled
: Detta möjliggör användning av Support Library RenderScript-implementering.
Hur RenderScript fungerar
Ett typiskt RenderScript består av två saker: kärnor och funktioner. En funktion är precis som den låter som - den accepterar en ingång, gör något med den ingången och returnerar en utgång. En Kernel är där den verkliga kraften i RenderScript kommer från.
En kärna är en funktion som körs mot varje element i en Allocation
. En Allocation
kan användas för att skicka data som en Bitmap
eller en byte
matris till ett RenderScript
och de används också för att få ett resultat från en kärna. Kärnor kan antingen ta en Allocation
som inmatning och en annan som utgång eller så kan de ändra data inuti en Allocation
.
Du kan skriva dina ena kärnor, men det finns också många fördefinierade kärnor som du kan använda för att utföra vanliga operationer som en gaussisk bildsuddighet.
Som redan nämnts för varje RenderScript-fil genereras en klass för att interagera med den. Dessa klasser börjar alltid med prefixet ScriptC_
följt av namnet på RenderScript-filen. Om din RenderScript-fil till example
kallas example
kommer den genererade Java-klassen att kallas ScriptC_example
. Alla fördefinierade skript börjar bara med prefixet Script
- till exempel kallas ScriptIntrinsicBlur
Gaussian Image Blur för ScriptIntrinsicBlur
.
Skriva ditt första RenderScript
Följande exempel är baserat på ett exempel på GitHub. Den utför grundläggande bildmanipulation genom att modifiera en bilds mättnad. Du kan hitta källkoden här och kolla in den om du vill leka med den själv. Här är en snabb gif av hur resultatet ska se ut:
RenderScript-pannplatta
RenderScript-filer finns i mappen src/main/rs
i ditt projekt. Varje fil har filändelsen .rs
och måste innehålla två #pragma
uttalanden högst upp:
#pragma version(1)
#pragma rs java_package_name(your.package.name)
#pragma version(1)
: Detta kan användas för att ställa in den version av RenderScript du använder. För närvarande finns det bara version 1.#pragma rs java_package_name(your.package.name)
: Detta kan användas för att ställa in paketnamnet på Java-klassen som genererats för att interagera med just detta RenderScript.
Det finns ett annat #pragma
du vanligtvis ska ställa in i var och en av dina RenderScript-filer och det används för att ställa in flytpunktens precision. Du kan ställa in flytpunktens precision på tre olika nivåer:
-
#pragma rs_fp_full
: Detta är den striktaste inställningen med högsta precision och det är också standardvärdet om du inte anger något. Du bör använda detta om du behöver hög flytpunktsprecision. -
#pragma rs_fp_relaxed
: Detta säkerställer inte riktigt lika hög flytpunktsnoggrannhet, men på vissa arkitekturer möjliggör det ett gäng optimeringar som kan göra att dina skript körs snabbare. -
#pragma rs_fp_imprecise
: Detta säkerställer ännu mindre precision och bör användas om flytpunktsprecision inte riktigt betyder något för ditt skript.
De flesta skript kan bara använda #pragma rs_fp_relaxed
såvida du inte verkligen behöver hög flytpunktsprecision.
Globala variabler
Nu precis som i C-kod kan du definiera globala variabler eller konstanter:
const static float3 gMonoMult = {0.299f, 0.587f, 0.114f};
float saturationLevel = 0.0f;
Variabeln gMonoMult
är av typen float3
. Detta betyder att det är en vektor som består av 3 flottörnummer. Den andra float
heter saturationValue
är inte konstant, därför kan du ställa in den vid körning till ett värde du gillar. Du kan använda variabler som detta i dina kärnor eller funktioner och därför är de ett annat sätt att ge inmatning till eller ta emot utdata från dina RenderScripts. För varje inte konstant variabel kommer en getter- och setter-metod att genereras i den tillhörande Java-klassen.
kärnor
Men låt oss nu börja implementera kärnan. I det här exemplet kommer jag inte att förklara den matematik som används i kärnan för att ändra bildens mättnad, utan istället kommer att fokusera på hur man implementerar en kärnan och hur man använder den. I slutet av detta kapitel kommer jag snabbt att förklara vad koden i den här kärnan faktiskt gör.
Kärnor i allmänhet
Låt oss ta en titt på källkoden först:
uchar4 __attribute__((kernel)) saturation(uchar4 in) {
float4 f4 = rsUnpackColor8888(in);
float3 dotVector = dot(f4.rgb, gMonoMult);
float3 newColor = mix(dotVector, f4.rgb, saturationLevel);
return rsPackColorTo8888(newColor);
}
Som du ser ser det ut som en normal C-funktion med ett undantag: __attribute__((kernel))
mellan __attribute__((kernel))
. Det här är det som säger RenderScript att den här metoden är en kärna. En annan sak som du kanske märker är att den här metoden accepterar en uchar4
parameter och returnerar ett annat uchar4
värde. uchar4
är - som float3
variabeln vi diskuterade i kapitlet tidigare - en vektor. Det innehåller 4 uchar
värden som bara är bytevärden i området från 0 till 255.
Du kan komma åt dessa enskilda värden på många olika sätt, till exempel in.r
skulle returnera byten som motsvarar den röda kanalen för en pixel. Vi använder en uchar4
eftersom varje pixel består av fyra värden - r
för röd, g
för grön, b
för blå och a
för alfa - och du kan få åtkomst till dem med den här korta listan. Med RenderScript kan du också ta valfritt antal värden från en vektor och skapa en annan vektor med dem. Till exempel skulle in.rgb
returnera ett uchar3
värde som bara innehåller de röda, gröna och blå delarna av pixeln utan alfavärdet.
Vid körning kommer RenderScript att kalla den här kärnmetoden för varje pixel i en bild, varför returvärdet och parametern bara är ett uchar4
värde. RenderScript kör många av dessa samtal parallellt på alla tillgängliga processorer, varför RenderScript är så kraftfullt. Detta innebär också att du inte behöver oroa dig för tråd eller säkerhet, du kan bara implementera vad du vill göra för varje pixel och RenderScript tar hand om resten.
När du ringer en Kernel i Java tillhandahåller du två Allocation
, en som innehåller inmatningsdata och en annan som kommer att ta emot utdata. Din Kernel metoden kommer att kallas för varje värde i inmatnings Allocation
och kommer att skriva resultatet till utgången Allocation
.
RenderScript Runtime API-metoder
I kärnan ovan används några metoder som tillhandahålls ur lådan. RenderScript tillhandahåller många sådana metoder och de är viktiga för nästan allt du tänker göra med RenderScript. Bland dem finns metoder för att utföra matematiska operationer som sin()
och hjälpmetoder som mix()
som blandar två värden enligt andra värden. Men det finns också metoder för mer komplexa operationer när man hanterar vektorer, kvartärer och matriser.
Den officiella RenderScript Runtime API-referensen är den bästa resursen där ute om du vill veta mer om en viss metod eller letar efter en specifik metod som utför en vanlig åtgärd som att beräkna dot-produkten i en matris. Du kan hitta den här dokumentationen här .
Implementering av kärnan
Låt oss nu titta på detaljerna för vad den här kärnan gör. Här är den första raden i kärnan:
float4 f4 = rsUnpackColor8888(in);
Den första raden kallar den inbyggda metoden rsUnpackColor8888()
som omvandlar uchar4
värdet till ett float4
värde. Varje färgkanal transformeras också till intervallet 0.0f - 1.0f
där 0.0f
motsvarar ett bytevärde på 0
och 1.0f
till 255
. Huvudsyftet med detta är att göra all matematik i den här kärnan mycket enklare.
float3 dotVector = dot(f4.rgb, gMonoMult);
Den här nästa rad använder den inbyggda metoden dot()
att beräkna punktprodukten för två vektorer. gMonoMult
är ett konstant värde som vi definierade några kapitel ovan. Eftersom båda vektorerna måste vara av samma längd för att beräkna prickprodukten och också eftersom vi bara vill påverka färgkanalerna och inte en alfakanal för en pixel använder vi den korta .rgb
att få en ny float3
vektor som bara innehåller röda, gröna och blå färgkanaler. De av oss som fortfarande kommer ihåg från skolan hur dot-produkten fungerar kommer snabbt att märka att dot-produkten ska returnera bara ett värde och inte en vektor. Men i koden ovan tilldelar vi resultatet till en float3
vektor. Detta är återigen en funktion i RenderScript. När du tilldelar ett endimensionellt nummer till en vektor kommer alla element i vektorn att ställas in på detta värde. Till exempel tilldelar följande 2.0f
till var och en av de tre värdena i float3
vektorn:
float3 example = 2.0f;
Så resultatet av punktprodukten ovan tilldelas varje element i float3
vektorn ovan.
Nu kommer den del där vi faktiskt använder den globala variabeln saturationLevel
att ändra bildens mättnad:
float3 newColor = mix(dotVector, f4.rgb, saturationLevel);
Detta använder den inbyggda mix()
att blanda originalfärgen med punktproduktvektorn vi skapade ovan. Hur de blandas tillsammans bestäms av den globala saturationLevel
variabeln. Så en saturationLevel
på 0.0f
orsakar att den resulterande färgen inte har någon del av de ursprungliga färgvärdena och kommer endast att bestå av värden i dotVector
vilket resulterar i en svartvit eller grå färgad bild. Ett värde på 1.0f
gör att den resulterande färgen helt består av de ursprungliga färgvärdena och värden över 1.0f
multiplicerar originalfärgerna för att göra dem mer ljusa och intensiva.
return rsPackColorTo8888(newColor);
Detta är den sista delen i kärnan. rsPackColorTo8888()
omvandlar float3
vektorn tillbaka till ett uchar4
värde som sedan returneras. De resulterande bytevärdena är fastklämda till ett intervall mellan 0 och 255, så att 1.0f
högre än 1.0f
resulterar i ett bytevärde på 255 och värden lägre än 0.0
kommer att resultera i ett bytevärde på 0
.
Och det är hela Kernel-implementeringen. Nu finns det bara en del kvar: Hur man kallar en kärnan i Java.
Ringer RenderScript i Java
Grunderna
Som redan nämnts ovan för varje RenderScript-fil genereras en Java-klass som låter dig interagera med dina skript. Dessa filer har prefixet ScriptC_
följt av namnet på RenderScript-filen. För att skapa en instans av dessa klasser behöver du först en instans av RenderScript
klassen:
final RenderScript renderScript = RenderScript.create(context);
Den statiska metoden create()
kan användas för att skapa en RenderScript
instans från ett Context
. Du kan sedan instansera Java-klassen som genererades för ditt skript. Om du ringde RenderScript-filen saturation.rs
kallas ScriptC_saturation
:
final ScriptC_saturation script = new ScriptC_saturation(renderScript);
På den här klassen kan du nu ställa in mättnadsnivån och ringa kärnan. Sättaren som genererades för variabeln saturationLevel
kommer att ha prefixet set_
följt av variabelns namn:
script.set_saturationLevel(1.0f);
Det finns också en getter förinställd med get_
som låter dig få den mättnadsnivå som för närvarande är inställd:
float saturationLevel = script.get_saturationLevel();
Kärnor som du definierar i ditt RenderScript förinställs med forEach_
följt av namnet på Kernel-metoden. Kernel vi har skrivit förväntar en ingångs Allocation
och en utgång Allocation
som dess parametrar:
script.forEach_saturation(inputAllocation, outputAllocation);
Ingångs Allocation
behöver innehålla den inmatade bilden, och efter forEach_saturation
metoden har avslutat den utgående fördelning kommer att innehålla de modifierade bilddata.
När du har en Allocation
kan du kopiera data från och till dessa Allocations
med metoderna copyFrom()
och copyTo()
. Till exempel kan du kopiera en ny bild till din ingång `Allokering genom att ringa:
inputAllocation.copyFrom(inputBitmap);
På samma sätt kan du hämta resultatbilden genom att ringa copyTo()
på utgången Allocation
:
outputAllocation.copyTo(outputBitmap);
Skapa tilldelningsinstanser
Det finns många sätt att skapa en Allocation
. När du har en Allocation
kan du kopiera nya data från och till de Allocations
med copyTo()
och copyFrom()
som förklarats ovan, men för att skapa dem från början måste du veta med vilken typ av data du exakt arbetar med. Låt oss börja med input Allocation
:
Vi kan använda den statiska metoden createFromBitmap()
för att snabbt skapa vår input Allocation
från en Bitmap
:
final Allocation inputAllocation = Allocation.createFromBitmap(renderScript, image);
I det här exemplet ingångsbilden förändras aldrig så vi behöver aldrig ändra ingångs Allocation
igen. Vi kan återanvända det varje gång saturationLevel
ändras för att skapa en ny utgång Bitmap
.
Skapa utgångs Allocation
är lite mer komplicerat. Först måste vi skapa det som kallas en Type
. En Type
används för att berätta en Allocation
med vilken typ av data den hanterar. Vanligtvis använder man klassen Type.Builder
att snabbt skapa en lämplig Type
. Låt oss ta en titt på koden först:
final Type outputType = new Type.Builder(renderScript, Element.RGBA_8888(renderScript))
.setX(inputBitmap.getWidth())
.setY(inputBitmap.getHeight())
.create();
Vi arbetar med en normal 32 bit (eller med andra ord 4 byte) per pixel Bitmap
med 4 färgkanaler. Det är därför vi väljer Element.RGBA_8888
att skapa Type
. Sedan använder vi metoderna setX()
och setY()
att ställa in setY()
bredd och höjd till samma storlek som ingångsbilden. Metoden create()
skapar sedan Type
med de parametrar som vi angav.
När vi har rätt Type
vi skapa Allocation
med den statiska metoden createTyped()
:
final Allocation outputAllocation = Allocation.createTyped(renderScript, outputType);
Nu är vi nästan klara. Vi behöver också en utgång Bitmap
där vi kan kopiera data från utgången Allocation
. För att göra detta använder vi den statiska metoden createBitmap()
att skapa en ny tom Bitmap
med samma storlek och konfiguration som den inmatade Bitmap
.
final Bitmap outputBitmap = Bitmap.createBitmap(
inputBitmap.getWidth(),
inputBitmap.getHeight(),
inputBitmap.getConfig()
);
Och med det har vi alla pusselbitar för att köra vårt RenderScript.
Fullständigt exempel
Låt oss nu sammansätta allt detta i ett exempel:
// Create the RenderScript instance
final RenderScript renderScript = RenderScript.create(context);
// Create the input Allocation
final Allocation inputAllocation = Allocation.createFromBitmap(renderScript, inputBitmap);
// Create the output Type.
final Type outputType = new Type.Builder(renderScript, Element.RGBA_8888(renderScript))
.setX(inputBitmap.getWidth())
.setY(inputBitmap.getHeight())
.create();
// And use the Type to create am output Allocation
final Allocation outputAllocation = Allocation.createTyped(renderScript, outputType);
// Create an empty output Bitmap from the input Bitmap
final Bitmap outputBitmap = Bitmap.createBitmap(
inputBitmap.getWidth(),
inputBitmap.getHeight(),
inputBitmap.getConfig()
);
// Create an instance of our script
final ScriptC_saturation script = new ScriptC_saturation(renderScript);
// Set the saturation level
script.set_saturationLevel(2.0f);
// Execute the Kernel
script.forEach_saturation(inputAllocation, outputAllocation);
// Copy the result data to the output Bitmap
outputAllocation.copyTo(outputBitmap);
// Display the result Bitmap somewhere
someImageView.setImageBitmap(outputBitmap);
Slutsats
Med den här introduktionen bör du vara redo att skriva dina egna RenderScript-kärnor för enkel bildmanipulation. Det finns dock några saker du måste tänka på:
- RenderScript fungerar bara i applikationsprojekt : För närvarande kan RenderScript-filer inte ingå i ett biblioteksprojekt.
- Se upp för minnet : RenderScript är mycket snabbt, men det kan också vara minnesintensivt. Det bör aldrig finnas mer än en instans av
RenderScript
när som helst. Du bör också återanvända så mycket som möjligt. Normalt behöver du bara skapa dinaAllocation
gång och kan återanvända dem i framtiden. Detsamma gäller för utmatningBitmaps
eller dina skriptinstanser. Återanvända så mycket som möjligt. - Gör ditt arbete i bakgrunden : Återigen är RenderScript mycket snabbt, men inte direkt på något sätt. Alla kärnor, särskilt komplexa, bör köras från UI-tråden i en
AsyncTask
eller något liknande. Men för det mesta behöver du inte oroa dig för minnesläckor. Alla RenderScript-relaterade klasser använder bara applikationensContext
och orsakar därför inte minnesläckor. Men du måste fortfarande oroa dig för de vanliga saker som läckaView
,Activity
eller någonContext
som du använder själv! - Använd inbyggda grejer : Det finns många fördefinierade skript som utför uppgifter som suddighet, blandning, konvertering, storleksändring. Och det finns många fler inbyggda metoder som hjälper dig att implementera dina kärnor. Chansen är stor att om du vill göra något finns det antingen ett skript eller en metod som redan gör det du försöker göra. Uppfinna inte hjulet igen.
Om du snabbt vill komma igång och leka med verklig kod rekommenderar jag att du tittar på exemplet GitHub-projekt som implementerar exakt exemplet som talas om i den här tutorialen. Du hittar projektet här . Ha kul med RenderScript!
Oskärpa en bild
Detta exempel visar hur man använder Renderscript API för att oskärpa en bild (med hjälp av Bitmap). Detta exempel använder ScriptInstrinsicBlur tillhandahållet av Android Renderscript API (API> = 17).
public class BlurProcessor {
private RenderScript rs;
private Allocation inAllocation;
private Allocation outAllocation;
private int width;
private int height;
private ScriptIntrinsicBlur blurScript;
public BlurProcessor(RenderScript rs) {
this.rs = rs;
}
public void initialize(int width, int height) {
blurScript = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs));
blurScript.setRadius(7f); // Set blur radius. 25 is max
if (outAllocation != null) {
outAllocation.destroy();
outAllocation = null;
}
// Bitmap must have ARGB_8888 config for this type
Type bitmapType = new Type.Builder(rs, Element.RGBA_8888(rs))
.setX(width)
.setY(height)
.setMipmaps(false) // We are using MipmapControl.MIPMAP_NONE
.create();
// Create output allocation
outAllocation = Allocation.createTyped(rs, bitmapType);
// Create input allocation with same type as output allocation
inAllocation = Allocation.createTyped(rs, bitmapType);
}
public void release() {
if (blurScript != null) {
blurScript.destroy();
blurScript = null;
}
if (inAllocation != null) {
inAllocation.destroy();
inAllocation = null;
}
if (outAllocation != null) {
outAllocation.destroy();
outAllocation = null;
}
}
public Bitmap process(Bitmap bitmap, boolean createNewBitmap) {
if (bitmap.getWidth() != width || bitmap.getHeight() != height) {
// Throw error if required
return null;
}
// Copy data from bitmap to input allocations
inAllocation.copyFrom(bitmap);
// Set input for blur script
blurScript.setInput(inAllocation);
// process and set data to the output allocation
blurScript.forEach(outAllocation);
if (createNewBitmap) {
Bitmap returnVal = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
outAllocation.copyTo(returnVal);
return returnVal;
}
outAllocation.copyTo(bitmap);
return bitmap;
}
}
Varje skript har en kärna som bearbetar data och de åberopas vanligtvis via forEach
metoden.
public class BlurActivity extends AppCompatActivity {
private BlurProcessor blurProcessor;
@Override
public void onCreate(Bundle savedInstanceState) {
// setup layout and other stuff
blurProcessor = new BlurProcessor(Renderscript.create(getApplicationContext()));
}
private void loadImage(String path) {
// Load image to bitmap
Bitmap bitmap = loadBitmapFromPath(path);
// Initialize processor for this bitmap
blurProcessor.release();
blurProcessor.initialize(bitmap.getWidth(), bitmap.getHeight());
// Blur image
Bitmap blurImage = blurProcessor.process(bitmap, true); // Use newBitamp as false if you don't want to create a new bitmap
}
}
Detta avslutade exemplet här. Det rekommenderas att göra behandlingen i en bakgrundstråd.
Oskärpa en vy
BlurBitmapTask.java
public class BlurBitmapTask extends AsyncTask<Bitmap, Void, Bitmap> {
private final WeakReference<ImageView> imageViewReference;
private final RenderScript renderScript;
private boolean shouldRecycleSource = false;
public BlurBitmapTask(@NonNull Context context, @NonNull ImageView imageView) {
// Use a WeakReference to ensure
// the ImageView can be garbage collected
imageViewReference = new WeakReference<>(imageView);
renderScript = RenderScript.create(context);
}
// Decode image in background.
@Override
protected Bitmap doInBackground(Bitmap... params) {
Bitmap bitmap = params[0];
return blurBitmap(bitmap);
}
// Once complete, see if ImageView is still around and set bitmap.
@Override
protected void onPostExecute(Bitmap bitmap) {
if (bitmap == null || isCancelled()) {
return;
}
final ImageView imageView = imageViewReference.get();
if (imageView == null) {
return;
}
imageView.setImageBitmap(bitmap);
}
public Bitmap blurBitmap(Bitmap bitmap) {
// https://plus.google.com/+MarioViviani/posts/fhuzYkji9zz
//Let's create an empty bitmap with the same size of the bitmap we want to blur
Bitmap outBitmap = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(),
Bitmap.Config.ARGB_8888);
//Instantiate a new Renderscript
//Create an Intrinsic Blur Script using the Renderscript
ScriptIntrinsicBlur blurScript = ScriptIntrinsicBlur.create(renderScript, Element.U8_4(renderScript));
//Create the in/out Allocations with the Renderscript and the in/out bitmaps
Allocation allIn = Allocation.createFromBitmap(renderScript, bitmap);
Allocation allOut = Allocation.createFromBitmap(renderScript, outBitmap);
//Set the radius of the blur
blurScript.setRadius(25.f);
//Perform the Renderscript
blurScript.setInput(allIn);
blurScript.forEach(allOut);
//Copy the final bitmap created by the out Allocation to the outBitmap
allOut.copyTo(outBitmap);
// recycle the original bitmap
// nope, we are using the original bitmap as well :/
if (shouldRecycleSource) {
bitmap.recycle();
}
//After finishing everything, we destroy the Renderscript.
renderScript.destroy();
return outBitmap;
}
public boolean isShouldRecycleSource() {
return shouldRecycleSource;
}
public void setShouldRecycleSource(boolean shouldRecycleSource) {
this.shouldRecycleSource = shouldRecycleSource;
}
}
Användande:
ImageView imageViewOverlayOnViewToBeBlurred
.setImageDrawable(ContextCompat.getDrawable(this, android.R.color.transparent));
View viewToBeBlurred.setDrawingCacheQuality(View.DRAWING_CACHE_QUALITY_LOW);
viewToBeBlurred.setDrawingCacheEnabled(true);
BlurBitmapTask blurBitmapTask = new BlurBitmapTask(this, imageViewOverlayOnViewToBeBlurred);
blurBitmapTask.execute(Bitmap.createBitmap(viewToBeBlurred.getDrawingCache()));
viewToBeBlurred.setDrawingCacheEnabled(false);