之前做过很多图像处理的项目、涉及到图像处理包括图像获取(根据路径或从相册获取后从uri获取路径)、压缩(参数路径或Bitmap)、旋转角度、图像保存等等。。。
整理一下,方便以后拿过来就用图像的压缩,比如身份证图像指定压缩到100KB以内,为了精确则采用直接循环判断压缩字节数组。全部方法代码如下:
import android.content.ContentResolver; import android.content.Context; import android.database.Cursor; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Matrix; import android.media.ExifInterface; import android.net.Uri; import android.os.Environment; import android.provider.MediaStore; import android.text.TextUtils; import com.zhengtong.app.zxing.utils.FileUtil; import com.zhengtong.util.LogUtils; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; /** * Created by weileek on 2015-7-19. */ public class BitmapUtils { private static final File parentPath = Environment.getExternalStorageDirectory(); private static String storagePath = ""; private static final String DST_FOLDER_NAME = "pic_temp"; public static String tmpPath = ""; //图片按比例大小压缩方法(根据路径获取图片并压缩): public static String getImageByPath(String srcPath) throws Exception{ //开始读入图片,此时把options.inJustDecodeBounds 设回true了 BitmapFactory.Options newOpts = new BitmapFactory.Options(); newOpts.inJustDecodeBounds = true; //打开图片获取分辨率 Bitmap bitmap = BitmapFactory.decodeFile(srcPath, newOpts); newOpts.inJustDecodeBounds = false; //传过来图片分辨率的宽度和高度 int w = newOpts.outWidth; int h = newOpts.outHeight; //这里设置高度为800f //这里设置宽度为480f float hh = 320.0F; float ww = 320.0F; //缩放比。由于是固定比例缩放,只用高或者宽其中一个数据进行计算即可 //be=1表示不缩放 int be = 1; //如果宽度大的话根据宽度固定大小缩放 if ((w > h) && (w > ww)) be =(int) Math.rint(newOpts.outWidth / ww); //如果高度高的话根据宽度固定大小缩放 else if ((w < h) && (h > hh)) { be = (int)Math.rint (newOpts.outHeight / hh); } if (be <= 0) be = 1; //设置缩放比例 newOpts.inSampleSize = be; //重新读入图片,注意此时已经把options.inJustDecodeBounds 设回false了 bitmap = BitmapFactory.decodeFile(srcPath, newOpts); //压缩好比例大小后再进行质量压缩 ByteArrayOutputStream baos = new ByteArrayOutputStream(); //质量压缩方法,这里100表示不压缩,把压缩后的数据存放到baos中 bitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos); int options = 90; //循环判断如果压缩后图片是否大于90kb,大于继续压缩 while (Base64.encode(baos.toByteArray()).length / 1024 > 50) { //重置baos即清空baos baos.reset(); //这里压缩options%,把压缩后的数据存放到baos中 bitmap.compress(Bitmap.CompressFormat.JPEG, options, baos); //每次都减少10 options -= 5; } LogUtils.e("照片上传时候的大小---->", Base64.encode(baos.toByteArray()).length/ 1024 + ""); return new String(Base64.encode(baos.toByteArray()),"utf-8"); } /** * 从相册获取图片后,从uri获取路径 */ public static String getFilePathFromUrl(Context context, Uri uri) { String path = null; String scheme = uri.getScheme(); if (ContentResolver.SCHEME_CONTENT.equals(scheme)) { String projection[] = {MediaStore.Images.ImageColumns.DATA}; Cursor c = context.getContentResolver().query(uri, projection, null, null, null); if (c != null && c.moveToFirst()) { path = c.getString(0); } if (c != null) c.close(); } else if (ContentResolver.SCHEME_FILE.equals(scheme)) { path = uri.getPath(); } return path; } /*** * 图片的缩放方法 * * @param bgimage :源图片资源 * //@param newWidth :缩放后宽度 * //@param newHeight :缩放后高度 double newWidth, double newHeight * @return 返回base64后的字符串 * new String(Base64.encode(baos.toByteArray()), "utf-8"); */ public static String zoomImage(Bitmap bgimage) throws Exception { // 获取这个图片的宽和高 float width = bgimage.getWidth(); float height = bgimage.getHeight(); // 创建操作图片用的matrix对象 Matrix matrix = new Matrix(); // 计算宽高缩放率 // float scaleWidth = ((float) newWidth) / width; // float scaleHeight = ((float) newHeight) / height; float scaleWidth = ((float) 320) / width; float scaleHeight = ((float) 320) / height; //选择一个合适的压缩比,防止图片压缩变形 if( scaleWidth > scaleHeight){ scaleHeight = scaleWidth; } else{ scaleWidth = scaleHeight; } // 缩放图片动作 matrix.postScale(scaleWidth, scaleHeight); Bitmap bitmap = Bitmap.createBitmap(bgimage, 0, 0, (int) width, (int) height, matrix, true); ByteArrayOutputStream baos = new ByteArrayOutputStream(); //质量压缩方法,这里100表示不压缩,把压缩后的数据存放到baos中 bitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos); int options = 90; /*循环判断如果压缩后图片是否大于60kb,大于继续压缩 2015-12-30 华为mate7,出现大于100KB的情况,故修改 */ while (Base64.encode(baos.toByteArray()).length / 1024 >80) { //重置baos即清空baos baos.reset(); //这里压缩options%,把压缩后的数据存放到baos中 bitmap.compress(Bitmap.CompressFormat.JPEG, options, baos); //每次都减少5 options -= 5; } LogUtils.e("照片上传时候的大小---------->", Base64.encode(baos.toByteArray()).length / 1024.0 + "kb"); return new String(Base64.encode(baos.toByteArray()), "utf-8"); } /** * 从文件中解图 解大图内存不足时尝试5此, samplesize增大 * * @param * @param max 宽或高的最大值, <= 0 , 能解多大解多大, > 0, 最大max, 内存不足解更小 */ public static Bitmap getBitmapFromFileLimitSize(String filePath, int max) { if (TextUtils.isEmpty(filePath) || !new File(filePath).exists()) { return null; } Bitmap bm = null; BitmapFactory.Options options = new BitmapFactory.Options(); options.inSampleSize = 1; if (max > 0) { options.inJustDecodeBounds = true; // 获取这个图片的宽和高 options.inJustDecodeBounds = false; /* 将需要压缩的尺寸为 600,450 */ options.inSampleSize = calculateInSampleSize(options, max, max); LogUtils.e("options.inSampleSize --->", options.inSampleSize + ""); // options.inSampleSize = 2; } bm = rotateBitmap(BitmapFactory.decodeFile(filePath, options), filePath); LogUtils.d("getBitmapFromFileLimitSize压缩后的图片的宽高", "宽==" + options.outWidth + "\t高==" + options.outHeight); return bm; } /** * 保存图片到文件 */ public static boolean saveBmpToFile(Bitmap bmp, String path, Bitmap.CompressFormat format) { if (bmp == null || bmp.isRecycled()) return false; OutputStream stream = null; try { File file = new File(path); File filePath = file.getParentFile(); if (!filePath.exists()) { filePath.mkdirs(); } if (!file.exists()) { try { file.createNewFile(); } catch (IOException e) { e.printStackTrace(); return false; } } stream = new FileOutputStream(path); return bmp.compress(format, 80, stream); } catch (FileNotFoundException e) { e.printStackTrace(); return false; } finally { if (null != stream) { try { stream.close(); } catch (IOException e) { e.printStackTrace(); } } } // return bmp.compress(format, 80, stream); } /** * 获取图片旋转角度 */ //判断图片的旋转角度 public static int getExifOrientation(String filepath) { int degree = 0; ExifInterface exif = null; try { exif = new ExifInterface(filepath); } catch (IOException ex) { //Log.e("---->", ex.getMessage()); } if (exif != null) { 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; default: break; } } } return degree; } /** * 旋转图片 */ public static Bitmap rotateBitmap(Bitmap b, String filepath) { int degrees = getExifOrientation(filepath) ; if (degrees != 0 && b != null) { Matrix m = new Matrix(); m.setRotate(degrees, (float) b.getWidth() / 2, (float) b.getHeight() / 2); try { Bitmap b2 = Bitmap.createBitmap(b, 0, 0, b.getWidth(), b.getHeight(), m, true); if (b != b2) { b.recycle(); b = b2; } } catch (OutOfMemoryError ex) { } } return b; } /** * 压缩图片 * * @param options BitmapFactory.Options * @param reqWidth 要求的宽度 * @param reqHeight 要求的高度 * @return 返回 bitmap */ public static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) { final int height = options.outHeight; final int width = options.outWidth; int inSampleSize = 1; LogUtils.d("取得图片的长宽---> ", "宽--->" + width + " 高---> " + height); if (height > reqHeight || width > reqWidth) { final int heightRatio = (int) Math.rint((float) height / (float) reqHeight); final int widthRatio = (int) Math.rint((float) width / (float) reqWidth); inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio; } return inSampleSize; } /** * @return */ private static String initPath() throws Exception { if (storagePath.equals("")) { storagePath = parentPath.getAbsolutePath() + "/" + DST_FOLDER_NAME; File f = new File(storagePath); if (!f.exists()) { f.mkdir(); } } return storagePath; } /** * ����Bitmap��sdcard * * @param b */ public static String saveBitmap(Bitmap b) { String path = ""; try { path = initPath(); } catch (Exception e) { LogUtils.d("Exception---> ", e.getMessage()); } // long dataTake = System.currentTimeMillis(); String imgCaptureFace = "zt_imgCaptureFace"; String jpegName = path + "/" + imgCaptureFace + ".jpg"; BitmapUtils.saveBmpToFile(b, jpegName, Bitmap.CompressFormat.JPEG); tmpPath = jpegName; return jpegName; } public static String saveBitmap(Bitmap b, String name) { String path = ""; try { path = initPath(); } catch (Exception e) { LogUtils.d("Exception---> ", e.getMessage()); } long dataTake = System.currentTimeMillis(); String jpegName = path + "/" + name + "_" + dataTake + ".jpg"; BitmapUtils.saveBmpToFile(b, jpegName, Bitmap.CompressFormat.JPEG); return jpegName; } }