package com.enrique.stackblur;

import android.content.Context;
import android.graphics.Bitmap;
import android.support.v8.renderscript.*;


/**
 * @see JavaBlurProcess
 * Blur using renderscript.
 * This should be very fast, even though it uses gausian blurring, it can be run on the gpu,
 * and uses hand-optimised assembly to be as fast as possible.
 */
class RSBlurProcess implements BlurProcess {
	private RenderScript _rs;

	public RSBlurProcess(Context context) {
		_rs = RenderScript.create(context);
	}

	@Override
	public Bitmap blur(Bitmap original, float radius) {
		if(radius == 0)
			return original;

		int width = original.getWidth();
		int height = original.getHeight();

		double scale = 1;
		// ScriptIntrinsicBlur only allows a maximum blur of 25 px
		while(radius > 25) {
			radius /= 2;
			scale /= 2;
		}

		int newWidth = (int)(width * scale);
		// ScriptIntrinsicBlur requires width to be a multiple of 4
		// See https://plus.google.com/+RomanNurik/posts/TLkVQC3M6jW
		newWidth += 4 - newWidth % 4;
		scale = (double)newWidth / width;
		int newHeight = (int) (height * scale);

		Bitmap scaledOriginal = Bitmap.createScaledBitmap(original, newWidth, newHeight, false);
		Bitmap scaledOutput = Bitmap.createBitmap(newWidth, newHeight, original.getConfig());

		ScriptIntrinsicBlur blur = ScriptIntrinsicBlur.create(_rs, Element.U8_4(_rs));
		Allocation tmpIn = Allocation.createFromBitmap(_rs, scaledOriginal);
		Allocation tmpOut = Allocation.createFromBitmap(_rs, scaledOutput);

		blur.setRadius(radius);
		blur.setInput(tmpIn);
		blur.forEach(tmpOut);
		tmpOut.copyTo(scaledOutput);

		if(scale == 1)
			return scaledOutput;
		else
			return Bitmap.createScaledBitmap(scaledOutput, width, height, true);
	}
}

@@ -403,16 +403,22 @@
 private 
+final 
 RenderSc
@@ -426,16 +426,55 @@
 ipt _rs;
+%0A%09private final boolean _preserveAlpha;
 %0A%0A%09publi
@@ -514,42 +514,167 @@
 %7B%0A%09%09
-_rs = RenderScript.create(context)
+this(context, true);%0A%09%7D%0A%0A%09public RSBlurProcess(Context context, boolean preserveAlpha) %7B%0A%09%09_rs = RenderScript.create(context);%0A%09%09_preserveAlpha = preserveAlpha
 ;%0A%09%7D
@@ -1781,124 +1781,689 @@
 %0A%0A%09%09
-if(scale == 1)%0A%09%09%09return scaledOutput;%0A%09%09else%0A%09%09%09return Bitmap.createScaledBitmap(scaledOutput, width, height, true)
+Bitmap output = Bitmap.createScaledBitmap(scaledOutput, width, height, true);%0A%09%09if(scaledOriginal != original)%0A%09%09%09scaledOriginal.recycle();%0A%09%09if(scaledOutput != output)%0A%09%09%09scaledOutput.recycle();%0A%09%09if(_preserveAlpha) %7B%0A%09%09%09int%5B%5D originalPixels = new int%5Bwidth * height%5D;%0A%09%09%09int%5B%5D outputPixels = new int%5Bwidth * height%5D;%0A%09%09%09output.getPixels(outputPixels, 0, width, 0, 0, width, height);%0A%09%09%09original.getPixels(originalPixels, 0, width, 0, 0, width, height);%0A%09%09%09for (int i = 0; i %3C width * height; i++) %7B%0A%09%09%09%09outputPixels%5Bi%5D = (outputPixels%5Bi%5D & 0x00ffffff) %7C (originalPixels%5Bi%5D & 0xff000000);%0A%09%09%09%7D%0A%09%09%09output.setPixels(outputPixels, 0, width, 0, 0, width, height);%0A%09%09%7D%0A%0A%09%09return output
 ;%0A%09%7D

Support alpha preservation when blurring with renderscript