package com.richardradics.commons.util; import android.annotation.TargetApi; import android.content.ContentResolver; import android.content.Context; import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Matrix; import android.graphics.Point; import android.net.Uri; import android.os.Build; import android.os.Environment; import android.util.Log; import java.io.BufferedOutputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.InputStream; import java.io.OutputStream; import android.content.Context; import android.graphics.BitmapFactory; import com.richardradics.commons.util.io.CloseableUtils; import com.richardradics.commons.util.io.FileUtils; /** * Created by Richard Radics on 2015.02.11.. */ /** * Utility for the {@link android.graphics.Bitmap}. */ @SuppressWarnings("unused") // Public APIs public final class BitmapUtil { public static final String TAG = BitmapUtil.class.getSimpleName(); private BitmapUtil() { throw new AssertionError(); } /** * Recycle the bitmap with null checks. * If the bitmap is already recycled, do nothing. * * @param bitmap to recycle. */ public static void recycle(Bitmap bitmap) { if (bitmap == null || bitmap.isRecycled()) { return; } bitmap.recycle(); } /** * Get width and height of the bitmap specified with the {@link android.net.Uri}. * * @param resolver the resolver. * @param uri the uri that points to the bitmap. * @return the size. */ public static Point getSize(ContentResolver resolver, Uri uri) { InputStream is = null; try { BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; is = resolver.openInputStream(uri); BitmapFactory.decodeStream(is, null, options); int width = options.outWidth; int height = options.outHeight; return new Point(width, height); } catch (FileNotFoundException e) { Log.e(TAG, "target file (" + uri + ") does not exist.", e); return null; } finally { CloseableUtils.close(is); } } /** * Get width and height of the bitmap specified with the {@link java.io.File}. * * @param path the bitmap file path. * @return the size. */ public static Point getSize(File path) { return getSize(path.getAbsolutePath()); } /** * Get width and height of the bitmap specified with the file path. * * @param path the bitmap file path. * @return the size. */ public static Point getSize(String path) { BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; BitmapFactory.decodeFile(path, options); int width = options.outWidth; int height = options.outHeight; return new Point(width, height); } /** * Get width and height of the bitmap specified with the byte array. * * @param byteArray the bitmap itself. * @return the size. */ public static Point getSize(byte[] byteArray) { return getSize(byteArray, 0, byteArray.length); } /** * Get width and height of the bitmap specified with the byte array. * * @param byteArray the bitmap itself. * @param offset offset index. * @param length array length. * @return the size. */ public static Point getSize(byte[] byteArray, int offset, int length) { BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; BitmapFactory.decodeByteArray(byteArray, offset, length, options); int width = options.outWidth; int height = options.outHeight; return new Point(width, height); } /** * Get width and height of the bitmap specified with the resource id. * * @param context the context. * @param resId the resource id of the drawable. * @return the drawable bitmap size. */ public static Point getSize(Context context, int resId) { return getSize(context.getResources(), resId); } /** * Get width and height of the bitmap specified with the resource id. * * @param res resource accessor. * @param resId the resource id of the drawable. * @return the drawable bitmap size. */ public static Point getSize(Resources res, int resId) { BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; BitmapFactory.decodeResource(res, resId, options); int width = options.outWidth; int height = options.outHeight; return new Point(width, height); } public static byte[] getBitmapAsByteArray(Bitmap bitmap) { ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); bitmap.compress(Bitmap.CompressFormat.PNG, 0, outputStream); return outputStream.toByteArray(); } public static Bitmap getByteArrayAsBitmap(byte[] bytesImage){ return BitmapFactory.decodeByteArray(bytesImage, 0, bytesImage.length); } /** * Compress the bitmap to the byte array as the specified format and quality. * * @param bitmap to compress. * @param format the format. * @param quality the quality of the compressed bitmap. * @return the compressed bitmap byte array. */ public static byte[] toByteArray(Bitmap bitmap, Bitmap.CompressFormat format, int quality) { ByteArrayOutputStream out = null; try { out = new ByteArrayOutputStream(); bitmap.compress(format, quality, out); return out.toByteArray(); } finally { CloseableUtils.close(out); } } /** * Shrink the bitmap to the specified scale. * * @param bitmap to shrink. * @param scale the shrink scale, must be < 1.0. * @return the shrunk bitmap. */ public static Bitmap shrink(Bitmap bitmap, float scale) { if (scale >= 1.0f) { return bitmap.copy(bitmap.getConfig(), false); } Matrix matrix = new Matrix(); matrix.postScale(scale, scale); return Bitmap.createBitmap(bitmap, 0, 0, (int) (scale * bitmap.getWidth()), (int) (scale * bitmap.getHeight()), matrix, true); } /** * Expand the bitmap to the specified scale. * * @param bitmap to expand. * @param scale the expand scale, must be > 1.0. * @return the expanded bitmap. */ public static Bitmap expand(Bitmap bitmap, float scale) { if (scale <= 1.0f) { return bitmap.copy(bitmap.getConfig(), false); } Matrix matrix = new Matrix(); matrix.postScale(scale, scale); return Bitmap.createBitmap(bitmap, 0, 0, (int) (scale * bitmap.getWidth()), (int) (scale * bitmap.getHeight()), matrix, true); } /** * Store the bitmap on the external storage path. * * @param context the context. * @param bitmap to store. * @param type type of the bitmap. * @param path file path. * @param filename file name. * @param format bitmap format. * @param quality the quality of the compressed bitmap. * @return the compressed bitmap file. */ @TargetApi(Build.VERSION_CODES.FROYO) public static File storeOnExternalStorage(Context context, Bitmap bitmap, String type, String path, String filename, Bitmap.CompressFormat format, int quality) { if (!Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) { // we cannot save a bitmap on the external storage on media not mounted. return null; } File dir = new File(context.getExternalFilesDir(type), path); FileUtils.makeDirsIfNeeded(dir); File file = new File(dir, filename); if (!storeAsFile(bitmap, file, format, quality)) { return null; } return file; } /** * Store the bitmap on the cache directory path. * * @param context the context. * @param bitmap to store. * @param path file path. * @param filename file name. * @param format bitmap format. * @param quality the quality of the compressed bitmap. * @return the compressed bitmap file. */ public static File storeOnCacheDir(Context context, Bitmap bitmap, String path, String filename, Bitmap.CompressFormat format, int quality) { File dir = new File(context.getCacheDir(), path); FileUtils.makeDirsIfNeeded(dir); File file = new File(dir, filename); if (!storeAsFile(bitmap, file, format, quality)) { return null; } return file; } /** * Store the bitmap on the application private directory path. * * @param context the context. * @param bitmap to store. * @param filename file name. * @param format bitmap format. * @param quality the quality of the compressed bitmap. * @return the compressed bitmap file. */ public static boolean storeOnApplicationPrivateDir(Context context, Bitmap bitmap, String filename, Bitmap.CompressFormat format, int quality) { OutputStream out = null; try { out = new BufferedOutputStream(context.openFileOutput(filename, Context.MODE_PRIVATE)); return bitmap.compress(format, quality, out); } catch (FileNotFoundException e) { Log.e(TAG, "no such file for saving bitmap: ", e); return false; } finally { CloseableUtils.close(out); } } /** * Store the bitmap as a file. * * @param bitmap to store. * @param format bitmap format. * @param quality the quality of the compressed bitmap. * @return the compressed bitmap file. */ public static boolean storeAsFile(Bitmap bitmap, File file, Bitmap.CompressFormat format, int quality) { OutputStream out = null; try { out = new BufferedOutputStream(new FileOutputStream(file)); return bitmap.compress(format, quality, out); } catch (FileNotFoundException e) { Log.e(TAG, "no such file for saving bitmap: ", e); return false; } finally { CloseableUtils.close(out); } } public static Bitmap rotateBitmap(Bitmap source, float angle){ Matrix matrix = new Matrix(); matrix.postRotate(angle); return Bitmap.createBitmap(source, 0, 0, source.getWidth(), source.getHeight(), matrix, true); } public static Bitmap scaleDownBitmap(Bitmap photo, int newHeight, Context context) { final float densityMultiplier = context.getResources().getDisplayMetrics().density; int h= (int) (newHeight*densityMultiplier); int w= (int) (h * photo.getWidth()/((double) photo.getHeight())); photo=Bitmap.createScaledBitmap(photo, w, h, true); return photo; } public static Bitmap getBitmapFromDrawable(Context context, int resId){ return BitmapFactory.decodeResource(context.getResources(), resId); } }