/*******************************************************************************
* Copyright 2011, 2012, 2013 fanfou.com, Xiaoke, Zhang
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************/
package com.fanfou.app.opensource.util;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
import android.graphics.BitmapFactory.Options;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PorterDuff.Mode;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.RectF;
import android.media.ExifInterface;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.provider.BaseColumns;
import android.provider.MediaStore.Images;
import android.provider.MediaStore.Images.ImageColumns;
import android.provider.MediaStore.MediaColumns;
import android.util.Log;
import android.view.OrientationEventListener;
import android.view.View;
import com.fanfou.app.opensource.AppContext;
/**
* @author mcxiaoke
* @version 1.0 2011.06.05
* @version 2.0 2011.09.23
* @version 3.0 2011.10.29
* @version 3.1 2011.11.08
* @version 3.2 2011.12.26
*
*/
final public class ImageHelper {
private static final String TAG = ImageHelper.class.getSimpleName();
public static final int IMAGE_QUALITY_HIGH = 90;
public static final int IMAGE_QUALITY_MEDIUM = 80;
public static final int IMAGE_QUALITY_LOW = 70;
public static final int IMAGE_MAX_WIDTH = 596;// 640 596
private static final int IMAGE_DIM_OFFSET = 48;
private static final int IMAGE_COMPRESS_SIZE = 64 * 1024;
// public static final int IMAGE_MAX_HEIGHT = 1200;// 1320 1192
public static final int OUTPUT_BUFFER_SIZE = 8196;
public static Bitmap captureViewToBitmap(final View view) {
Bitmap result = null;
try {
result = Bitmap.createBitmap(view.getWidth(), view.getHeight(),
Bitmap.Config.RGB_565);
view.draw(new Canvas(result));
} catch (final Exception e) {
if (AppContext.DEBUG) {
e.printStackTrace();
}
}
return result;
}
private static boolean checkFsWritable() {
// Create a temporary file to see whether a volume is really writeable.
// It's important not to put it in the root directory which may have a
// limit on the number of files.
final String directoryName = Environment.getExternalStorageDirectory()
.toString() + "/DCIM";
final File directory = new File(directoryName);
if (!directory.isDirectory()) {
if (!directory.mkdirs()) {
return false;
}
}
return directory.canWrite();
}
public static boolean checkStorageWritable() {
final String directoryName = Environment.getExternalStorageDirectory()
.toString();
final File directory = new File(directoryName);
if (!directory.isDirectory()) {
if (!directory.mkdirs()) {
return false;
}
}
final File f = new File(directoryName, ".probe");
try {
if (!f.createNewFile()) {
return false;
}
f.delete();
return true;
} catch (final IOException ex) {
return false;
}
}
// public static Bitmap resampleImage(String path, int maxDim)
// throws Exception {
//
// BitmapFactory.Options bfo = new BitmapFactory.Options();
// bfo.inJustDecodeBounds = true;
// BitmapFactory.decodeFile(path, bfo);
//
// BitmapFactory.Options optsDownSample = new BitmapFactory.Options();
// optsDownSample.inSampleSize = getClosestResampleSize(bfo.outWidth,
// bfo.outHeight, maxDim);
//
// Bitmap bmpt = BitmapFactory.decodeFile(path, optsDownSample);
//
// Matrix m = new Matrix();
//
// if (bmpt.getWidth() > maxDim || bmpt.getHeight() > maxDim) {
// BitmapFactory.Options optsScale = getResampling(bmpt.getWidth(),
// bmpt.getHeight(), maxDim);
// m.postScale((float) optsScale.outWidth / (float) bmpt.getWidth(),
// (float) optsScale.outHeight / (float) bmpt.getHeight());
// }
//
// int sdk = new Integer(Build.VERSION.SDK).intValue();
// if (sdk > 4) {
// int rotation = getExifOrientation(path);
// if (rotation != 0) {
// m.postRotate(rotation);
// }
// }
// return Bitmap.createBitmap(bmpt, 0, 0, bmpt.getWidth(),
// bmpt.getHeight(), m, true);
// }
/**
*
* @param bitmap
* @param quality
* 1 ~ 100
* @return
*/
public static byte[] compressBitmap(final Bitmap bitmap, final int quality) {
try {
final ByteArrayOutputStream baos = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, quality, baos);
return baos.toByteArray();
} catch (final Exception e) {
if (AppContext.DEBUG) {
e.printStackTrace();
}
}
return null;
}
private static File compressForUpload(final String srcFileName,
final String destFileName, final int maxWidth, int quality) {
final boolean keepOriginal = ImageHelper.keepOriginal(srcFileName,
ImageHelper.IMAGE_MAX_WIDTH);
if (keepOriginal) {
if (AppContext.DEBUG) {
Log.d(ImageHelper.TAG,
"compressForUpload keep Original,no Need Compress");
}
return new File(srcFileName);
}
final Bitmap bitmap = ImageHelper.compressImage(srcFileName, maxWidth);
if (bitmap == null) {
return null;
}
if (AppContext.DEBUG) {
Log.d(ImageHelper.TAG,
"compressForUpload bitmap=(" + bitmap.getWidth() + ","
+ bitmap.getHeight() + ")");
}
FileOutputStream fos = null;
try {
Bitmap.CompressFormat format = CompressFormat.JPEG;
if (srcFileName.toLowerCase().lastIndexOf("png") > -1) {
format = CompressFormat.PNG;
}
if (quality > ImageHelper.IMAGE_QUALITY_HIGH) {
quality = ImageHelper.IMAGE_QUALITY_HIGH;
} else if (quality < ImageHelper.IMAGE_QUALITY_LOW) {
quality = ImageHelper.IMAGE_QUALITY_LOW;
}
fos = new FileOutputStream(destFileName);
bitmap.compress(format, quality, fos);
return new File(destFileName);
} catch (final FileNotFoundException e) {
if (AppContext.DEBUG) {
e.printStackTrace();
}
return null;
} finally {
IOHelper.forceClose(fos);
}
}
public static Bitmap compressImage(final String path, final int maxDim) {
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(path, options);
int inSampleSize = 1;
for (int w = options.outWidth; w > (maxDim * 2); w /= 2) {
inSampleSize += 1;
}
if (AppContext.DEBUG) {
Log.d(ImageHelper.TAG, "compressImage original=("
+ options.outWidth + "," + options.outHeight + ")");
Log.d(ImageHelper.TAG, "compressImage inSampleSize=" + inSampleSize);
}
options.inSampleSize = inSampleSize;
options.inJustDecodeBounds = false;
final Bitmap bitmap = BitmapFactory.decodeFile(path, options);
if (bitmap != null) {
final int bw = bitmap.getWidth();
final int bh = bitmap.getHeight();
final Matrix m = new Matrix();
if ((bw > maxDim) || (bh > maxDim)) {
final float scale = (float) maxDim / (float) bw;
m.postScale(scale, scale);
if (AppContext.DEBUG) {
Log.d(ImageHelper.TAG, "compressImage matrix scale="
+ scale);
}
}
final int rotation = ImageHelper.getExifOrientation(path);
if (ImageHelper.getExifOrientation(path) != 0) {
m.postRotate(rotation);
}
if (AppContext.DEBUG) {
Log.d(ImageHelper.TAG, "compressImage matrix rotation="
+ rotation);
Log.d(ImageHelper.TAG, "compressImage bitmap=(" + bw + "," + bh
+ ")");
}
return Bitmap.createBitmap(bitmap, 0, 0, bw, bh, m, true);
}
return null;
}
private static int computeSampleSize(final InputStream stream,
final int maxW, final int maxH) {
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeStream(stream, null, options);
final double w = options.outWidth;
final double h = options.outHeight;
final int sampleSize = (int) Math.ceil(Math.max(w / maxW, h / maxH));
return sampleSize;
}
private static int computeSampleSize(final String path, final int maxW,
final int maxH) {
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(path, options);
final double w = options.outWidth;
final double h = options.outHeight;
final int sampleSize = (int) Math.ceil(Math.max(w / maxW, h / maxH));
return sampleSize;
}
/**
*
* @param bytes
* @return
*/
public static Bitmap getBitmapFromBytes(final byte[] bytes) {
try {
return BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
} catch (final Exception e) {
if (AppContext.DEBUG) {
e.printStackTrace();
}
}
return null;
}
/**
*
* @param path
* @param sampleSize
* 1 = 100%, 2 = 50%(1/2), 4 = 25%(1/4), ...
* @return
*/
public static Bitmap getBitmapFromPath(final String path,
final int sampleSize) {
try {
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = sampleSize;
return BitmapFactory.decodeFile(path, options);
} catch (final Exception e) {
if (AppContext.DEBUG) {
e.printStackTrace();
}
}
return null;
}
/**
* generate a blurred bitmap from given one
*
* referenced: http://incubator.quasimondo.com/processing/superfastblur.pde
*
* @param original
* @param radius
* @return
*/
public static Bitmap getBlurredBitmap(final Bitmap original,
final int radius) {
if (radius < 1) {
return null;
}
final int width = original.getWidth();
final int height = original.getHeight();
final int wm = width - 1;
final int hm = height - 1;
final int wh = width * height;
final int div = radius + radius + 1;
final int r[] = new int[wh];
final int g[] = new int[wh];
final int b[] = new int[wh];
int rsum, gsum, bsum, x, y, i, p, p1, p2, yp, yi, yw;
final int vmin[] = new int[Math.max(width, height)];
final int vmax[] = new int[Math.max(width, height)];
final int dv[] = new int[256 * div];
for (i = 0; i < (256 * div); i++) {
dv[i] = i / div;
}
final int[] blurredBitmap = new int[wh];
original.getPixels(blurredBitmap, 0, width, 0, 0, width, height);
yw = 0;
yi = 0;
for (y = 0; y < height; y++) {
rsum = 0;
gsum = 0;
bsum = 0;
for (i = -radius; i <= radius; i++) {
p = blurredBitmap[yi + Math.min(wm, Math.max(i, 0))];
rsum += (p & 0xff0000) >> 16;
gsum += (p & 0x00ff00) >> 8;
bsum += p & 0x0000ff;
}
for (x = 0; x < width; x++) {
r[yi] = dv[rsum];
g[yi] = dv[gsum];
b[yi] = dv[bsum];
if (y == 0) {
vmin[x] = Math.min(x + radius + 1, wm);
vmax[x] = Math.max(x - radius, 0);
}
p1 = blurredBitmap[yw + vmin[x]];
p2 = blurredBitmap[yw + vmax[x]];
rsum += ((p1 & 0xff0000) - (p2 & 0xff0000)) >> 16;
gsum += ((p1 & 0x00ff00) - (p2 & 0x00ff00)) >> 8;
bsum += (p1 & 0x0000ff) - (p2 & 0x0000ff);
yi++;
}
yw += width;
}
for (x = 0; x < width; x++) {
rsum = gsum = bsum = 0;
yp = -radius * width;
for (i = -radius; i <= radius; i++) {
yi = Math.max(0, yp) + x;
rsum += r[yi];
gsum += g[yi];
bsum += b[yi];
yp += width;
}
yi = x;
for (y = 0; y < height; y++) {
blurredBitmap[yi] = 0xff000000 | (dv[rsum] << 16)
| (dv[gsum] << 8) | dv[bsum];
if (x == 0) {
vmin[y] = Math.min(y + radius + 1, hm) * width;
vmax[y] = Math.max(y - radius, 0) * width;
}
p1 = x + vmin[y];
p2 = x + vmax[y];
rsum += r[p1] - r[p2];
gsum += g[p1] - g[p2];
bsum += b[p1] - b[p2];
yi += width;
}
}
return Bitmap.createBitmap(blurredBitmap, width, height,
Bitmap.Config.RGB_565);
}
private static int getClosestResampleSize(final int cx, final int cy,
final int maxDim) {
final int max = Math.max(cx, cy);
int resample = 1;
for (resample = 1; resample < Integer.MAX_VALUE; resample++) {
if ((resample * maxDim) > max) {
resample--;
break;
}
}
if (resample > 0) {
return resample;
}
return 1;
}
public static Uri getContentUriFromFile(final Context ctx,
final File imageFile) {
Uri uri = null;
final ContentResolver cr = ctx.getContentResolver();
// Columns to return
final String[] projection = { BaseColumns._ID, MediaColumns.DATA };
// Look for a picture which matches with the requested path
// (MediaStore stores the path in column Images.Media.DATA)
final String selection = MediaColumns.DATA + " = ?";
final String[] selArgs = { imageFile.toString() };
final Cursor cursor = cr.query(Images.Media.EXTERNAL_CONTENT_URI,
projection, selection, selArgs, null);
if (cursor.moveToFirst()) {
String id;
final int idColumn = cursor.getColumnIndex(BaseColumns._ID);
id = cursor.getString(idColumn);
uri = Uri.withAppendedPath(Images.Media.EXTERNAL_CONTENT_URI, id);
}
cursor.close();
if (uri != null) {
Log.d(ImageHelper.TAG,
"Found picture in MediaStore : " + imageFile.toString()
+ " is " + uri.toString());
} else {
Log.d(ImageHelper.TAG, "Did not find picture in MediaStore : "
+ imageFile.toString());
}
return uri;
}
public static int getExifOrientation(final String filepath) {
int degree = 0;
ExifInterface exif = null;
try {
exif = new ExifInterface(filepath);
} catch (final IOException ex) {
Log.e(ImageHelper.TAG, "cannot read exif", ex);
}
if (exif != null) {
final int orientation = exif.getAttributeInt(
ExifInterface.TAG_ORIENTATION, -1);
if (orientation != -1) {
// We only recognize a subset of orientation tag values.
switch (orientation) {
case ExifInterface.ORIENTATION_ROTATE_90:
degree = 90;
break;
case ExifInterface.ORIENTATION_ROTATE_180:
degree = 180;
break;
case ExifInterface.ORIENTATION_ROTATE_270:
degree = 270;
break;
}
}
}
return degree;
}
private static BitmapFactory.Options getResampling(final int cx,
final int cy, final int max) {
float scaleVal = 1.0f;
final BitmapFactory.Options bfo = new BitmapFactory.Options();
if (cx > cy) {
scaleVal = (float) max / (float) cx;
} else if (cy > cx) {
scaleVal = (float) max / (float) cy;
} else {
scaleVal = (float) max / (float) cx;
}
bfo.outWidth = (int) ((cx * scaleVal) + 0.5f);
bfo.outHeight = (int) ((cy * scaleVal) + 0.5f);
return bfo;
}
/**
* 圆角图片
*
* @param bitmap
* @param pixels
* @return
*/
public static Bitmap getRoundedCornerBitmap(final Bitmap bitmap,
final int pixels) {
final Bitmap output = Bitmap.createBitmap(bitmap.getWidth(),
bitmap.getHeight(), Config.ARGB_8888);
final Canvas canvas = new Canvas(output);
final int color = 0xff424242;
final Paint paint = new Paint();
final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
final RectF rectF = new RectF(rect);
final float roundPx = pixels;
paint.setAntiAlias(true);
canvas.drawARGB(0, 0, 0, 0);
paint.setColor(color);
canvas.drawRoundRect(rectF, roundPx, roundPx, paint);
paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
canvas.drawBitmap(bitmap, rect, rect, paint);
return output;
}
public static Bitmap getRoundedCornerBitmap2(final Bitmap bitmap,
final int radius) {
final Paint paintForRound = new Paint();
paintForRound.setAntiAlias(true);
paintForRound.setColor(0xff424242);
paintForRound.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
final Bitmap output = Bitmap.createBitmap(bitmap.getWidth(),
bitmap.getHeight(), Config.ARGB_8888);
final Canvas canvas = new Canvas(output);
final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
final RectF rectF = new RectF(rect);
canvas.drawARGB(0, 0, 0, 0);
paintForRound.setXfermode(null);
canvas.drawRoundRect(rectF, radius, radius, paintForRound);
paintForRound.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
canvas.drawBitmap(bitmap, rect, rect, paintForRound);
return output;
}
public static boolean hasStorage() {
return ImageHelper.hasStorage(true);
}
public static boolean hasStorage(final boolean requireWriteAccess) {
final String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state)) {
if (requireWriteAccess) {
final boolean writable = ImageHelper.checkFsWritable();
return writable;
} else {
return true;
}
} else if (!requireWriteAccess
&& Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
return true;
}
return false;
}
public static Uri insertImage(final ContentResolver cr, final File file,
final int degree) {
final long size = file.length();
final String name = file.getName();
final ContentValues values = new ContentValues(9);
values.put(MediaColumns.TITLE, name);
values.put(MediaColumns.DISPLAY_NAME, name);
values.put(ImageColumns.DATE_TAKEN, System.currentTimeMillis());
values.put(MediaColumns.MIME_TYPE, "image/jpeg");
values.put(ImageColumns.ORIENTATION, degree);
values.put(MediaColumns.DATA, file.getAbsolutePath());
values.put(MediaColumns.SIZE, size);
// return cr.insert(STORAGE_URI, values);
return null;
}
public static boolean isStorageWritable(final Context context) {
boolean mExternalStorageAvailable = false;
boolean mExternalStorageWriteable = false;
final String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state)) {
// can read and write
mExternalStorageAvailable = mExternalStorageWriteable = true;
} else if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
// can only read
mExternalStorageAvailable = true;
mExternalStorageWriteable = false;
} else {
// can neither read nor write
mExternalStorageAvailable = mExternalStorageWriteable = false;
}
final boolean goodmount = mExternalStorageAvailable
&& mExternalStorageWriteable;
return goodmount;
}
public static boolean keepOriginal(final String path, final int maxDim) {
final File file = new File(path);
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(path, options);
return (file.exists() && (file.length() < ImageHelper.IMAGE_COMPRESS_SIZE))
|| (options.outWidth <= (maxDim + ImageHelper.IMAGE_DIM_OFFSET));
}
public static Bitmap loadFromPath(final Context context, final String path,
final int maxW, final int maxH) throws IOException {
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inScaled = false;
// options.inPreferredConfig = Bitmap.Config.RGB_565;
options.inSampleSize = ImageHelper.computeSampleSize(path, maxW, maxH);
// options.inDither = false;
options.inJustDecodeBounds = false;
// options.inPurgeable = true;
final Bitmap bitmap = BitmapFactory.decodeFile(path, options);
return bitmap;
}
public static Bitmap loadFromUri(final Context context, final String uri,
final int maxW, final int maxH) throws IOException {
final BitmapFactory.Options options = new BitmapFactory.Options();
Bitmap bitmap = null;
options.inScaled = false;
options.inPreferredConfig = Bitmap.Config.RGB_565;
BufferedInputStream stream = null;
if (uri.startsWith(ContentResolver.SCHEME_CONTENT)
|| uri.startsWith(ContentResolver.SCHEME_FILE)) {
stream = new BufferedInputStream(context.getContentResolver()
.openInputStream(Uri.parse(uri)), 16384);
}
if (stream != null) {
options.inSampleSize = ImageHelper.computeSampleSize(stream, maxW,
maxH);
stream = null;
stream = new BufferedInputStream(context.getContentResolver()
.openInputStream(Uri.parse(uri)), 16384);
} else {
return null;
}
options.inDither = false;
options.inJustDecodeBounds = false;
options.inPurgeable = true;
bitmap = BitmapFactory.decodeStream(stream, null, options);
return bitmap;
}
/**
* apply filter to a bitmap
*
* @param original
* @param filter
* @return filtered bitmap
*/
// public static Bitmap applyFilter(Bitmap original, FilterBase filter) {
// return filter.filter(original);
// }
public static File prepareProfileImage(final Context context,
final File file) {
final File destFile = new File(IOHelper.getImageCacheDir(context),
"fanfouprofileimage.jpg");
return ImageHelper.compressForUpload(file.getPath(),
destFile.getPath(), 100, ImageHelper.IMAGE_QUALITY_MEDIUM);
}
public static File prepareUploadFile(final Context context,
final File file, final int quality) {
final File destFile = new File(IOHelper.getImageCacheDir(context),
"fanfouupload.jpg");
return ImageHelper.compressForUpload(file.getPath(),
destFile.getPath(), ImageHelper.IMAGE_MAX_WIDTH, quality);
}
public static void releaseBitmap(Bitmap bitmap) {
if ((bitmap != null) && !bitmap.isRecycled()) {
bitmap.recycle();
bitmap = null;
}
}
public static Bitmap resampleImage(final Context context, final Uri uri,
final int maxDim) throws Exception {
final String path = IOHelper.getRealPathFromURI(context, uri);
return ImageHelper.resampleImage(path, maxDim);
}
public static Bitmap resampleImage(final File file, final int maxDim)
throws Exception {
return ImageHelper.resampleImage(file.getAbsolutePath(), maxDim);
}
public static Bitmap resampleImage(final String path, final int maxDim)
throws Exception {
final BitmapFactory.Options bfo = new BitmapFactory.Options();
bfo.inJustDecodeBounds = true;
BitmapFactory.decodeFile(path, bfo);
final BitmapFactory.Options optsDownSample = new BitmapFactory.Options();
optsDownSample.inSampleSize = ImageHelper.getClosestResampleSize(
bfo.outWidth, bfo.outHeight, maxDim);
final Bitmap bmpt = BitmapFactory.decodeFile(path, optsDownSample);
final Matrix m = new Matrix();
if ((bmpt.getWidth() > maxDim) || (bmpt.getHeight() > maxDim)) {
final BitmapFactory.Options optsScale = ImageHelper.getResampling(
bmpt.getWidth(), bmpt.getHeight(), maxDim);
m.postScale((float) optsScale.outWidth / (float) bmpt.getWidth(),
(float) optsScale.outHeight / (float) bmpt.getHeight());
}
final int sdk = Integer.valueOf(Build.VERSION.SDK);
if (sdk > 4) {
final int rotation = ImageHelper.getExifOrientation(path);
if (rotation != 0) {
m.postRotate(rotation);
}
}
return Bitmap.createBitmap(bmpt, 0, 0, bmpt.getWidth(),
bmpt.getHeight(), m, true);
}
public static Bitmap resizeBitmap(final Bitmap input, int destWidth,
int destHeight) {
final int srcWidth = input.getWidth();
final int srcHeight = input.getHeight();
boolean needsResize = false;
float p;
if ((srcWidth > destWidth) || (srcHeight > destHeight)) {
needsResize = true;
if ((srcWidth > srcHeight) && (srcWidth > destWidth)) {
p = (float) destWidth / (float) srcWidth;
destHeight = (int) (srcHeight * p);
} else {
p = (float) destHeight / (float) srcHeight;
destWidth = (int) (srcWidth * p);
}
} else {
destWidth = srcWidth;
destHeight = srcHeight;
}
if (needsResize) {
final Bitmap output = Bitmap.createScaledBitmap(input, destWidth,
destHeight, true);
return output;
} else {
return input;
}
}
public static Bitmap resizeBitmap(final String filePath, final int width,
final int height) {
Bitmap bitmap = null;
final Options options = new Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(filePath, options);
double sampleSize = 0;
final Boolean scaleByHeight = Math.abs(options.outHeight - height) >= Math
.abs(options.outWidth - width);
if ((options.outHeight * options.outWidth * 2) >= 16384) {
sampleSize = scaleByHeight ? options.outHeight / height
: options.outWidth / width;
sampleSize = (int) Math.pow(2d,
Math.floor(Math.log(sampleSize) / Math.log(2d)));
}
options.inJustDecodeBounds = false;
options.inTempStorage = new byte[128];
while (true) {
try {
options.inSampleSize = (int) sampleSize;
bitmap = BitmapFactory.decodeFile(filePath, options);
break;
} catch (final Exception ex) {
sampleSize = sampleSize * 2;
}
}
return bitmap;
}
/**
* Rotate a bitmap.
*
* @param bmp
* A Bitmap of the picture.
* @param degrees
* Angle of the rotation, in degrees.
* @return The rotated bitmap, constrained in the source bitmap dimensions.
*/
public static Bitmap rotate(final Bitmap bmp, final float degrees) {
if ((degrees % 360) != 0) {
Log.d(ImageHelper.TAG, "Rotating bitmap " + degrees + "°");
final Matrix rotMat = new Matrix();
rotMat.postRotate(degrees);
if (bmp != null) {
final Bitmap dst = Bitmap.createBitmap(bmp, 0, 0,
bmp.getWidth(), bmp.getHeight(), rotMat, false);
return dst;
}
} else {
return bmp;
}
return null;
}
public static Bitmap rotateImageFile(final String filePath) {
final int orientation = ImageHelper.getExifOrientation(filePath);
final Bitmap source = BitmapFactory.decodeFile(filePath);
final int sw = source.getWidth();
final int sh = source.getHeight();
final Matrix matrix = new Matrix();
matrix.setRotate(orientation);
final Bitmap bitmap = Bitmap.createBitmap(source, 0, 0, sw, sh, matrix,
true);
ImageHelper.releaseBitmap(source);
return bitmap;
}
public static int roundOrientation(final int orientationInput) {
// landscape mode
int orientation = orientationInput;
if (orientation == OrientationEventListener.ORIENTATION_UNKNOWN) {
orientation = 0;
}
orientation = orientation % 360;
int retVal;
if (orientation < ((0 * 90) + 45)) {
retVal = 0;
} else if (orientation < ((1 * 90) + 45)) {
retVal = 90;
} else if (orientation < ((2 * 90) + 45)) {
retVal = 180;
} else if (orientation < ((3 * 90) + 45)) {
retVal = 270;
} else {
retVal = 0;
}
return retVal;
}
public static boolean saveBitmap(final Bitmap original,
final Bitmap.CompressFormat format, final int quality,
final File outputFile) {
if (original == null) {
return false;
}
try {
return original.compress(format, quality, new FileOutputStream(
outputFile));
} catch (final Exception e) {
if (AppContext.DEBUG) {
e.printStackTrace();
}
}
return false;
}
public static boolean saveBitmap(final Bitmap original,
final Bitmap.CompressFormat format, final int quality,
final String outputFilePath) {
if (original == null) {
return false;
}
try {
return original.compress(format, quality, new FileOutputStream(
outputFilePath));
} catch (final Exception e) {
if (AppContext.DEBUG) {
e.printStackTrace();
}
}
return false;
}
public static Bitmap scaleImageFile(final Context context, final File file,
final int size) {
final Uri uri = Uri.fromFile(file);
return ImageHelper.scaleImageFromUri(context, uri, size);
}
public static Bitmap scaleImageFromUri(final Context context,
final Uri uri, final int size) {
Bitmap bitmap = null;
InputStream is = null;
try {
is = context.getContentResolver().openInputStream(uri);
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeStream(is, null, options);
is.close();
int scale = 1;
while (((options.outWidth / scale) > size)
|| ((options.outHeight / scale) > size)) {
scale *= 2;
}
options.inJustDecodeBounds = false;
options.inSampleSize = scale;
is = context.getContentResolver().openInputStream(uri);
bitmap = BitmapFactory.decodeStream(is, null, options);
} catch (final IOException e) {
} finally {
if (is != null) {
try {
is.close();
} catch (final IOException e) {
}
}
}
return bitmap;
}
/**
* Store a picture that has just been saved to disk in the MediaStore.
*
* @param imageFile
* The File of the picture
* @return The Uri provided by the MediaStore.
*/
public static Uri storePicture(final Context ctx, final File imageFile,
String imageName) {
final ContentResolver cr = ctx.getContentResolver();
imageName = imageName.substring(imageName.lastIndexOf('/') + 1);
final ContentValues values = new ContentValues(7);
values.put(MediaColumns.TITLE, imageName);
values.put(MediaColumns.DISPLAY_NAME, imageName);
values.put(ImageColumns.DESCRIPTION, "");
values.put(ImageColumns.DATE_TAKEN, System.currentTimeMillis());
values.put(MediaColumns.MIME_TYPE, "image/jpeg");
values.put(ImageColumns.ORIENTATION, 0);
final File parentFile = imageFile.getParentFile();
final String path = parentFile.toString().toLowerCase();
final String name = parentFile.getName().toLowerCase();
values.put(Images.ImageColumns.BUCKET_ID, path.hashCode());
values.put(Images.ImageColumns.BUCKET_DISPLAY_NAME, name);
values.put("_data", imageFile.toString());
final Uri uri = cr.insert(Images.Media.EXTERNAL_CONTENT_URI, values);
return uri;
}
public static boolean writeToFile(final File file, final Bitmap bitmap) {
if ((bitmap == null) || (file == null) || file.exists()) {
return false;
}
BufferedOutputStream bos = null;
try {
bos = new BufferedOutputStream(new FileOutputStream(file),
ImageHelper.OUTPUT_BUFFER_SIZE);
return bitmap.compress(Bitmap.CompressFormat.JPEG, 100, bos);
} catch (final IOException e) {
if (AppContext.DEBUG) {
Log.d(ImageHelper.TAG, "writeToFile:" + e.getMessage());
}
} finally {
IOHelper.forceClose(bos);
}
return false;
}
public static boolean writeToFile(final String filePath, final Bitmap bitmap) {
if ((bitmap == null) || StringHelper.isEmpty(filePath)) {
return false;
}
final File file = new File(filePath);
return ImageHelper.writeToFile(file, bitmap);
}
}