Created
August 15, 2015 19:03
-
-
Save gfpacheco/eb996194d9faaafd1922 to your computer and use it in GitHub Desktop.
Picasso blur transformation compatible with older version of Android
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.gfpacheco; | |
import android.annotation.TargetApi; | |
import android.content.Context; | |
import android.graphics.Bitmap; | |
import android.os.Build; | |
import android.support.v8.renderscript.Allocation; | |
import android.support.v8.renderscript.Element; | |
import android.support.v8.renderscript.RenderScript; | |
import android.support.v8.renderscript.ScriptIntrinsicBlur; | |
import com.squareup.picasso.Transformation; | |
public class BlurTransformation implements Transformation { | |
private final Context mContext; | |
private final int mRadius; | |
public BlurTransformation(Context context, int radius) { | |
mContext = context; | |
mRadius = radius; | |
} | |
@Override | |
public Bitmap transform(Bitmap source) { | |
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { | |
return blur(source); | |
} else { | |
return blur2(source); | |
} | |
} | |
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1) | |
private Bitmap blur(Bitmap original) { | |
RenderScript rs = RenderScript.create(mContext); | |
final Allocation input = Allocation.createFromBitmap(rs, original); | |
final Allocation output = Allocation.createTyped(rs, input.getType()); | |
final ScriptIntrinsicBlur script = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs)); | |
script.setRadius((float) mRadius); | |
script.setInput(input); | |
script.forEach(output); | |
output.copyTo(original); | |
return original; | |
} | |
private Bitmap blur2(Bitmap original) { | |
Bitmap bitmap = original.copy(original.getConfig(), true); | |
if (mRadius < 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 = mRadius + mRadius + 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 < 256 * 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 = mRadius + 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 = -mRadius; i <= mRadius; i++) { | |
p = pix[yi + Math.min(wm, Math.max(i, 0))]; | |
sir = stack[i + mRadius]; | |
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 = mRadius; | |
for (x = 0; x < w; x++) { | |
r[yi] = dv[rSum]; | |
g[yi] = dv[gSum]; | |
b[yi] = dv[bSum]; | |
rSum -= rOutSum; | |
gSum -= gOutSum; | |
bSum -= bOutSum; | |
stackStart = stackPointer - mRadius + div; | |
sir = stack[stackStart % div]; | |
rOutSum -= sir[0]; | |
gOutSum -= sir[1]; | |
bOutSum -= sir[2]; | |
if (y == 0) { | |
vMin[x] = Math.min(x + mRadius + 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; x++) { | |
rInSum = gInSum = bInSum = rOutSum = gOutSum = bOutSum = rSum = gSum = bSum = 0; | |
yp = -mRadius * w; | |
for (i = -mRadius; i <= mRadius; i++) { | |
yi = Math.max(0, yp) + x; | |
sir = stack[i + mRadius]; | |
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 = mRadius; | |
for (y = 0; y < h; y++) { | |
// Preserve alpha channel: ( 0xff000000 & pix[yi] ) | |
pix[yi] = (0xff000000 & pix[yi]) | (dv[rSum] << 16) | (dv[gSum] << 8) | dv[bSum]; | |
rSum -= rOutSum; | |
gSum -= gOutSum; | |
bSum -= bOutSum; | |
stackStart = stackPointer - mRadius + 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; | |
} | |
@Override | |
public String key() { | |
return "blur" + mRadius; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment