package quickutils.core.categories; import android.annotation.SuppressLint; import android.annotation.TargetApi; import android.app.Activity; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.ColorMatrix; import android.graphics.ColorMatrixColorFilter; import android.graphics.Matrix; import android.graphics.Paint; import android.graphics.Point; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; 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 android.util.Log; import android.view.Display; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import quickutils.core.QuickUtils; import quickutils.core.interfaces.OnEventListener; import quickutils.core.services.DownloadImageTask; public class image { /** * Convert drawable resource to bitmap * * @param drawable drawable resource to be converted * @return a bitmap */ public static Bitmap convertImageResourceToBitmap(int drawable) { return BitmapFactory.decodeResource(QuickUtils.getContext().getResources(), drawable); } /** * Convert drawable to bitmap * * @param drawable drawable to be converted * @return a bitmap */ public static Bitmap convertDrawableToBitmap(Drawable drawable) { if (drawable instanceof BitmapDrawable) { return ((BitmapDrawable) drawable).getBitmap(); } int width = drawable.getIntrinsicWidth(); width = width > 0 ? width : 1; int height = drawable.getIntrinsicHeight(); height = height > 0 ? height : 1; Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(bitmap); drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight()); drawable.draw(canvas); return bitmap; } /** * Get a bitmap by a given URL * * @param imageURL given URL * @param callback callback */ public static void getBitmapByImageURL(String imageURL, final OnEventListener callback) { new DownloadImageTask<Bitmap>(imageURL, new OnEventListener<Bitmap>() { @Override public void onSuccess(Bitmap bitmap) { callback.onSuccess(bitmap); } @Override public void onFailure(Exception e) { callback.onFailure(e); } }).execute(); } public static File saveBitmapDownscaled(Bitmap bitmap, String filename, String path, boolean recycle, int maxWidth, int maxHeight) { float heightScaleFactor = 1; float widthScaleFactor = 1; float scaleFactor = 1; if (bitmap.getHeight() > maxHeight) { heightScaleFactor = (float) maxHeight / (float) bitmap.getHeight(); } if (bitmap.getWidth() > maxWidth) { widthScaleFactor = (float) maxWidth / (float) bitmap.getWidth(); } if (heightScaleFactor < 1 || widthScaleFactor < 1) { scaleFactor = math.min(heightScaleFactor, widthScaleFactor); } bitmap = Bitmap.createScaledBitmap(bitmap, (int) (bitmap.getWidth() * scaleFactor), (int) (bitmap.getHeight() * scaleFactor), true); return saveBitmap(bitmap, filename, path, recycle); } public static File saveBitmap(Bitmap bitmap, String filename, String path, boolean recycle) { FileOutputStream out = null; try { File f = new File(path, filename); if (!f.exists()) { f.createNewFile(); } out = new FileOutputStream(f); if (bitmap.compress(Bitmap.CompressFormat.PNG, 90, out)) { return f; } } catch (Exception e) { QuickUtils.log.e("Could not save bitmap", e); } finally { try { out.close(); } catch (Throwable ignore) { } if (recycle) { bitmap.recycle(); } } return null; } public static Bitmap flip(Bitmap src) { Matrix m = new Matrix(); m.preScale(-1, 1); return Bitmap.createBitmap(src, 0, 0, src.getWidth(), src.getHeight(), m, false); } @TargetApi(Build.VERSION_CODES.KITKAT) public static int sizeOf(Bitmap data) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB_MR1) { return data.getRowBytes() * data.getHeight(); } else if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) { return data.getByteCount(); } else { return data.getAllocationByteCount(); } } /** * @param bmp input bitmap * @param contrast 0..10 1 is default * @param brightness -255..255 0 is default * @return new bitmap */ public static Bitmap changeBitmapContrastBrightness(Bitmap bmp, float contrast, float brightness) { ColorMatrix cm = new ColorMatrix(new float[] { contrast, 0, 0, 0, brightness, 0, contrast, 0, 0, brightness, 0, 0, contrast, 0, brightness, 0, 0, 0, 1, 0 }); Bitmap ret = Bitmap.createBitmap(bmp.getWidth(), bmp.getHeight(), bmp.getConfig()); Canvas canvas = new Canvas(ret); Paint paint = new Paint(); paint.setColorFilter(new ColorMatrixColorFilter(cm)); canvas.drawBitmap(bmp, 0, 0, paint); return ret; } /** * Stores an image on the storage * * @param image the image to store. * @param pictureFile the file in which it must be stored */ public static void storeImage(Bitmap image, File pictureFile) { if (pictureFile == null) { QuickUtils.log.d("Error creating media file, check storage permissions: "); return; } try { FileOutputStream fos = new FileOutputStream(pictureFile); image.compress(Bitmap.CompressFormat.PNG, 90, fos); fos.close(); } catch (FileNotFoundException e) { QuickUtils.log.d("File not found: " + e.getMessage()); } catch (IOException e) { QuickUtils.log.d("Error accessing file: " + e.getMessage()); } } /** * Get the screen height. * * @param context * @return the screen height */ @SuppressWarnings("deprecation") @SuppressLint("NewApi") public static int getScreenHeight(Activity context) { Display display = context.getWindowManager().getDefaultDisplay(); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2) { Point size = new Point(); display.getSize(size); return size.y; } return display.getHeight(); } /** * Get the screen width. * * @param context * @return the screen width */ @SuppressWarnings("deprecation") @SuppressLint("NewApi") public static int getScreenWidth(Activity context) { Display display = context.getWindowManager().getDefaultDisplay(); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2) { Point size = new Point(); display.getSize(size); return size.x; } return display.getWidth(); } /** * Apply a blur to a Bitmap * * @param sentBitmap Bitmap to be converted * @param radius Desired Radius, 0 < r < 25 * @return a copy of the image with a blur */ public static Bitmap blur(Bitmap sentBitmap, int radius) { if (radius < 0) { radius = 0; QuickUtils.log.w("radius must be 0 < r < 25 , forcing radius=0"); } else if (radius > 25) { radius = 25; QuickUtils.log.w("radius must be 0 < r < 25 , forcing radius=25"); } if (Build.VERSION.SDK_INT > 16) { Bitmap bitmap = sentBitmap.copy(sentBitmap.getConfig(), true); final RenderScript rs = RenderScript.create(QuickUtils.getContext()); 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 /* e.g. 3.f */); script.setInput(input); script.forEach(output); output.copyTo(bitmap); return bitmap; } // Stack Blur v1.0 from // http://www.quasimondo.com/StackBlurForCanvas/StackBlurDemo.html // // Java Author: Mario Klingemann <mario at quasimondo.com> // http://incubator.quasimondo.com // created Feburary 29, 2004 // Android port : Yahel Bouaziz <yahel at kayenko.com> // http://www.kayenko.com // ported april 5th, 2012 // 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 implementation. // // 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 has 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 are either added on // or reduced by one, depending on if they are on the right or // on the left side of the stack. // // If you are using this algorithm in your code please add // the following line: // // Stack Blur Algorithm by Mario Klingemann <mario@quasimondo.com> Bitmap bitmap = sentBitmap.copy(sentBitmap.getConfig(), true); if (radius < 1) { return (null); } int w = bitmap.getWidth(); int h = bitmap.getHeight(); int[] pix = new int[w * h]; Log.e("pix", w + " " + h + " " + pix.length); 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 < 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 = 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 = (int) (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; x++) { 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; x++) { rinsum = ginsum = binsum = routsum = goutsum = boutsum = rsum = gsum = bsum = 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 = (int) (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 & pix[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; } } Log.e("pix", w + " " + h + " " + pix.length); bitmap.setPixels(pix, 0, w, 0, 0, w, h); return (bitmap); } }