/** Private method for grabbing a "screenshot" of screen content */ private void drawOffscreenBitmap() { // Grab global visible rect for later use // mView.getGlobalVisibleRect(mRectVisibleGlobal); // Calculate scaled off-screen bitmap width and height int width = Math.round(mView.getWidth() * BITMAP_SCALE_FACTOR); int height = Math.round(mView.getHeight() * BITMAP_SCALE_FACTOR); // Width and height must be > 0 width = Math.max(width, 1); height = Math.max(height, 1); // Allocate new off-screen bitmap only when needed if (mBitmap == null || mBitmap.getWidth() != width || mBitmap.getHeight() != height) { mBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); mAllocationBitmap = Allocation.createFromBitmap(mRS, mBitmap); mAllocationBitmapTmp = Allocation.createFromBitmap(mRS, mBitmap); mSizeStruct.width = width; mSizeStruct.height = height; // Due to adjusting width into multiple of 4 calculate scale matrix // only here mMatrixScale.setScale((float) width / mView.getWidth(), (float) height / mView.getHeight()); mMatrixScale.invert(mMatrixScaleInv); } // Translate values for off-screen drawing // int dx = -(Math.min(0, mView.getLeft()) + mRectVisibleGlobal.left); // int dy = -(Math.min(0, mView.getTop()) + mRectVisibleGlobal.top); // // Replaced dx and dy with View.getLocationInWindow() coordinates // because translate was bad for using BlurLinearLayout and // BlurRelativeLayout as children for other Views than root View. mView.getLocationInWindow(mLocationInWindow); // Restore canvas to its original state mCanvas.restoreToCount(1); mCanvas.setBitmap(mBitmap); // Using scale matrix will make draw call to match // resized off-screen bitmap size mCanvas.setMatrix(mMatrixScale); // Off-screen bitmap does not cover the whole screen // Use canvas translate to match its position on screen mCanvas.translate(-mLocationInWindow[0], -mLocationInWindow[1]); // Clip rect is the same as we have // TODO: Why does this not work on API 18? // mCanvas.clipRect(mRectVisibleGlobal); // Save current canvas state mCanvas.save(); // Start drawing from the root view mView.getRootView().draw(mCanvas); }
private Bitmap BlurImage(Bitmap input, int radius) { RenderScript rsScript = RenderScript.create(getActivity()); Allocation alloc = Allocation.createFromBitmap(rsScript, input); ScriptIntrinsicBlur blur = ScriptIntrinsicBlur.create(rsScript, Element.U8_4(rsScript)); blur.setRadius(radius); blur.setInput(alloc); Bitmap result = Bitmap.createBitmap(input.getWidth(), input.getHeight(), input.getConfig()); Allocation outAlloc = Allocation.createFromBitmap(rsScript, result); blur.forEach(outAlloc); outAlloc.copyTo(result); rsScript.destroy(); return result; }
protected boolean prepare() { final int width = mBlurredView.getWidth(); final int height = mBlurredView.getHeight(); if (mBlurringCanvas == null || mDownSampleFactorChanged || mBlurredViewWidth != width || mBlurredViewHeight != height) { mDownSampleFactorChanged = false; mBlurredViewWidth = width; mBlurredViewHeight = height; int scaledWidth = width / mDownSampleFactor; int scaledHeight = height / mDownSampleFactor; // The following manipulation is to avoid some RenderScript artifacts at the edge. scaledWidth = scaledWidth - scaledWidth % 4 + 4; scaledHeight = scaledHeight - scaledHeight % 4 + 4; if (mBlurredBitmap == null || mBlurredBitmap.getWidth() != scaledWidth || mBlurredBitmap.getHeight() != scaledHeight) { mBitmapToBlur = Bitmap.createBitmap(scaledWidth, scaledHeight, Bitmap.Config.ARGB_8888); if (mBitmapToBlur == null) { return false; } mBlurredBitmap = Bitmap.createBitmap(scaledWidth, scaledHeight, Bitmap.Config.ARGB_8888); if (mBlurredBitmap == null) { return false; } } mBlurringCanvas = new Canvas(mBitmapToBlur); mBlurringCanvas.scale(1f / mDownSampleFactor, 1f / mDownSampleFactor); mBlurInput = Allocation.createFromBitmap( mRenderScript, mBitmapToBlur, Allocation.MipmapControl.MIPMAP_NONE, Allocation.USAGE_SCRIPT); mBlurOutput = Allocation.createTyped(mRenderScript, mBlurInput.getType()); } return true; }
public static Bitmap blendRenderScript(RenderScript rs, Bitmap bitmap1, Bitmap bitmap2) { if (Build.VERSION.SDK_INT >= 17) { final Allocation input1 = Allocation.createFromBitmap( rs, bitmap1, Allocation.MipmapControl.MIPMAP_NONE, Allocation.USAGE_SCRIPT); final Allocation input2 = Allocation.createFromBitmap( rs, bitmap2, Allocation.MipmapControl.MIPMAP_NONE, Allocation.USAGE_SCRIPT); final ScriptIntrinsicBlend blendScript = ScriptIntrinsicBlend.create(rs, Element.U8_4(rs)); blendScript.forEachAdd(input1, input2); input2.copyTo(bitmap1); return bitmap1; } else { throw new IllegalStateException("Renderscript needs sdk >= 17"); } }
@Override protected void createFilter( android.content.res.Resources res, float scaleFactor, int quality, Allocation in) { RenderScript rsCtx = getRenderScriptContext(); Type.Builder tb_float = new Type.Builder(rsCtx, Element.F32_4(rsCtx)); tb_float.setX(in.getType().getX()); tb_float.setY(in.getType().getY()); mScript = new ScriptC_grad(rsCtx, res, R.raw.grad); }
private void runSelectiveAdjust(Allocation in, Allocation out) { int width = in.getType().getX(); int height = in.getType().getY(); LaunchOptions options = new LaunchOptions(); int ty; options.setX(0, width); for (ty = 0; ty < height; ty += STRIP_SIZE) { int endy = ty + STRIP_SIZE; if (endy > height) { endy = height; } options.setY(ty, endy); mScript.forEach_selectiveAdjust(in, out, options); if (checkStop()) { return; } } }
public static Drawable createBlurredImageFromBitmap( Bitmap bitmap, Context context, int inSampleSize) { RenderScript rs = RenderScript.create(context); final BitmapFactory.Options options = new BitmapFactory.Options(); options.inSampleSize = inSampleSize; ByteArrayOutputStream stream = new ByteArrayOutputStream(); bitmap.compress(Bitmap.CompressFormat.JPEG, 100, stream); byte[] imageInByte = stream.toByteArray(); ByteArrayInputStream bis = new ByteArrayInputStream(imageInByte); Bitmap blurTemplate = BitmapFactory.decodeStream(bis, null, options); final android.support.v8.renderscript.Allocation input = android.support.v8.renderscript.Allocation.createFromBitmap(rs, blurTemplate); final android.support.v8.renderscript.Allocation output = android.support.v8.renderscript.Allocation.createTyped(rs, input.getType()); final android.support.v8.renderscript.ScriptIntrinsicBlur script = android.support.v8.renderscript.ScriptIntrinsicBlur.create( rs, android.support.v8.renderscript.Element.U8_4(rs)); script.setRadius(8f); script.setInput(input); script.forEach(output); output.copyTo(blurTemplate); Drawable dr = new BitmapDrawable(blurTemplate); return dr; }
/** Set blur radius in screen pixels. Value is mapped in range [1, 254]. */ public void setBlurRadius(int radius) { // Map radius into scaled down off-screen bitmap size radius = Math.round(radius * BITMAP_SCALE_FACTOR); // Setup radius struct mRadiusStruct.radius = Math.max(1, Math.min(254, radius)); mRadiusStruct.div = mRadiusStruct.radius + mRadiusStruct.radius + 1; mRadiusStruct.divsum = (mRadiusStruct.div + 1) >> 1; mRadiusStruct.divsum *= mRadiusStruct.divsum; // Prepare dv allocation mAllocationDv = Allocation.createSized(mRS, Element.U8(mRS), 256 * mRadiusStruct.divsum); mScriptStackBlur.set_initializeDv_divsum(mRadiusStruct.divsum); mScriptStackBlur.forEach_initializeDv(mAllocationDv); }
/** Applies blur to current off-screen bitmap */ public void applyBlur() { // Copy current bitmap into allocation mAllocationBitmap.copyFrom(mBitmap); // Set script variables mScriptStackBlur.bind_dv(mAllocationDv); mScriptStackBlur.set_bitmap(mAllocationBitmap); mScriptStackBlur.set_bitmapTmp(mAllocationBitmapTmp); mScriptStackBlur.set_sizeStruct(mSizeStruct); mScriptStackBlur.set_radiusStruct(mRadiusStruct); // On first step iterate over y = [0, mBitmap.getHeight] mLaunchOptions.setX(0, 1); mLaunchOptions.setY(0, mBitmap.getHeight()); mScriptStackBlur.forEach_blurHorizontal(mAllocationBitmap, mLaunchOptions); // On second step iterate over x = [0, mBitmap.getWidth] mLaunchOptions.setX(0, mBitmap.getWidth()); mLaunchOptions.setY(0, 1); mScriptStackBlur.forEach_blurVertical(mAllocationBitmap, mLaunchOptions); // Copy bitmap allocation back to off-screen bitmap mAllocationBitmap.copyTo(mBitmap); }
private static void blurRenderScript(Bitmap bitmap, float radius) { Allocation inAllocation = Allocation.createFromBitmap( renderScript, bitmap, Allocation.MipmapControl.MIPMAP_NONE, Allocation.USAGE_SCRIPT); Allocation outAllocation = Allocation.createTyped(renderScript, inAllocation.getType()); blurShader.setRadius(radius); blurShader.setInput(inAllocation); blurShader.forEach(outAllocation); outAllocation.copyTo(bitmap); }
public static Bitmap blurBitmap(Bitmap bitmapToBlur, Context context) { RenderScript rs = RenderScript.create(context); // use this constructor for best performance, because it uses USAGE_SHARED mode which reuses // memory final Allocation input = Allocation.createFromBitmap(rs, bitmapToBlur); final Allocation output = Allocation.createTyped(rs, input.getType()); final ScriptIntrinsicBlur script = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs)); script.setRadius(16f); script.setInput(input); script.forEach(output); output.copyTo(bitmapToBlur); return bitmapToBlur; }
public static Bitmap apply(Context context, Bitmap sentBitmap, int radius) { final Bitmap bitmap = sentBitmap.copy(sentBitmap.getConfig(), true); final RenderScript rs = RenderScript.create(context); final Allocation input = Allocation.createFromBitmap( rs, sentBitmap, 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); sentBitmap.recycle(); rs.destroy(); input.destroy(); output.destroy(); script.destroy(); return bitmap; }
protected void blur() { mBlurInput.copyFrom(mBitmapToBlur); mBlurScript.setInput(mBlurInput); mBlurScript.forEach(mBlurOutput); mBlurOutput.copyTo(mBlurredBitmap); }