拍照/选择相册,图片压缩旋转处理

news/2024/11/17 6:43:06/

最近做项目需要用到拍照和选择相册照片,并显示出来imageview 上,然后压缩上传到服务器中,这本是一个非常常见的功能,但对于图片的处理确实一个技术活,稍微不注意会出现oom,图片压缩也要处理的刚刚好,不能浪费用户的流量,也不能过分的压缩使图片失真,这真的不简单,好在开源中国的安卓端app以开源,本人特意从开源中国整理了这个demo,分享给大家。

进入相册选择照片:注意6.0之后要申请运行时权限,即api23。

 Intent intent;if (Build.VERSION.SDK_INT < 19) {intent = new Intent();intent.setAction(Intent.ACTION_GET_CONTENT);intent.setType("image/*");startActivityForResult(Intent.createChooser(intent, "选择图片"), ImageUtils.REQUEST_CODE_GETIMAGE_BYSDCARD);} else {intent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);intent.setType("image/*");startActivityForResult(Intent.createChooser(intent, "选择图片"), ImageUtils.REQUEST_CODE_GETIMAGE_BYSDCARD);}

或者拍照:

  private void toCamera() {// 判断是否挂载了SD卡String savePath = "";String storageState = Environment.getExternalStorageState();if (storageState.equals(Environment.MEDIA_MOUNTED)) {savePath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/oschina/Camera/";File savedir = new File(savePath);if (!savedir.exists()) {savedir.mkdirs();}}// 没有挂载SD卡,无法保存文件if (TextUtils.isEmpty(savePath)) {// AppContext.showToastShort("无法保存照片,请检查SD卡是否挂载");return;}String timeStamp = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date());String fileName = timeStamp + ".jpg";// 照片命名File out = new File(savePath, fileName);Uri uri = Uri.fromFile(out);//tweet.setImageFilePath(savePath + fileName); // 该照片的绝对路径mPhotoPath=savePath + fileName;Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);startActivityForResult(intent, ImageUtils.REQUEST_CODE_GETIMAGE_BYCAMERA);}

在onActivity获取图片信息:

 @Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) {super.onActivityResult(requestCode, resultCode, data);if (resultCode != Activity.RESULT_OK)return;if (requestCode == ImageUtils.REQUEST_CODE_GETIMAGE_BYSDCARD) {if (data == null)return;Uri selectedImageUri = data.getData();if (selectedImageUri != null) {String path = ImageUtils.getImagePath(selectedImageUri, this);setImageFromPath(path);}} else if (requestCode == ImageUtils.REQUEST_CODE_GETIMAGE_BYCAMERA) {//setImageFromPath(tweet.getImageFilePath());setImageFromPath(mPhotoPath);}}

通过返回的uri获取图片路径

 /*** 通过Uri获取文件路径* 支持图片媒体,文件等* <p/>* Author qiujuer@live.cn** @param uri     Uri* @param context Context* @return 文件路径*/@SuppressLint({"NewApi", "Recycle"})public static String getImagePath(Uri uri, Context context) {String selection = null;String[] selectionArgs = null;// Uri is different in versions after KITKAT (Android 4.4), we need toif (Build.VERSION.SDK_INT >= 19 && DocumentsContract.isDocumentUri(context.getApplicationContext(), uri)) {String authority = uri.getAuthority();if ("com.android.externalstorage.documents".equals(authority)) {// isExternalStorageDocumentfinal String docId = DocumentsContract.getDocumentId(uri);final String[] split = docId.split(":");return Environment.getExternalStorageDirectory() + "/" + split[1];} else if ("com.android.providers.downloads.documents".equals(authority)) {// isDownloadsDocumentfinal String id = DocumentsContract.getDocumentId(uri);uri = ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));} else if ("com.android.providers.media.documents".equals(authority)) {// isMediaDocumentfinal String docId = DocumentsContract.getDocumentId(uri);final String[] split = docId.split(":");final String type = split[0];if ("image".equals(type)) {uri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;} else if ("video".equals(type)) {uri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;} else if ("audio".equals(type)) {uri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;}selection = "_id=?";selectionArgs = new String[]{split[1]};}}if ("content".equalsIgnoreCase(uri.getScheme())) {String[] projection = {MediaStore.Images.Media.DATA};Cursor cursor = null;try {cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs, null);if (cursor != null) {int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);if (cursor.moveToFirst()) {return cursor.getString(column_index);}}} catch (Exception e) {e.fillInStackTrace();} finally {if (cursor != null)cursor.close();}} else if ("file".equalsIgnoreCase(uri.getScheme())) {return uri.getPath();}return null;}

根据图片地址去获取bitmap这时需要自己传入图片的大小即高度和宽度,根据自己的需求去传。

Bitmap bitmap = BitmapCreate.bitmapFromStream(new FileInputStream(path), 512, 512);

图片压缩

/*** 获取一个指定大小的bitmap<br>* 实际调用的方法是bitmapFromByteArray(data, 0, data.length, w, h);** @param is        从输入流中读取Bitmap* @param reqWidth  目标宽度* @param reqHeight 目标高度*/public static Bitmap bitmapFromStream(InputStream is, int reqWidth,int reqHeight) {if (reqHeight == 0 || reqWidth == 0) {try {return BitmapFactory.decodeStream(is);} catch (OutOfMemoryError e) {}}byte[] data = FileUtils.input2byte(is);return bitmapFromByteArray(data, 0, data.length, reqWidth, reqHeight);}/*** 获取一个指定大小的bitmap** @param data      Bitmap的byte数组* @param offset    image从byte数组创建的起始位置* @param length    the number of bytes, 从offset处开始的长度* @param reqWidth  目标宽度* @param reqHeight 目标高度*/public static Bitmap bitmapFromByteArray(byte[] data, int offset,int length, int reqWidth, int reqHeight) {if (reqHeight == 0 || reqWidth == 0) {try {return BitmapFactory.decodeByteArray(data, offset, length);} catch (OutOfMemoryError e) {}}BitmapFactory.Options options = new BitmapFactory.Options();options.inJustDecodeBounds = true;options.inPurgeable = true;BitmapFactory.decodeByteArray(data, offset, length, options);options = calculateInSampleSize(options, reqWidth, reqHeight);return BitmapFactory.decodeByteArray(data, offset, length, options);}/*** 图片压缩处理(使用Options的方法)* <br>* <b>说明</b> 使用方法:* 首先你要将Options的inJustDecodeBounds属性设置为true,BitmapFactory.decode一次图片 。* 然后将Options连同期望的宽度和高度一起传递到到本方法中。* 之后再使用本方法的返回值做参数调用BitmapFactory.decode创建图片。* <br>* <b>说明</b> BitmapFactory创建bitmap会尝试为已经构建的bitmap分配内存* ,这时就会很容易导致OOM出现。为此每一种创建方法都提供了一个可选的Options参数* ,将这个参数的inJustDecodeBounds属性设置为true就可以让解析方法禁止为bitmap分配内存* ,返回值也不再是一个Bitmap对象, 而是null。虽然Bitmap是null了,但是Options的outWidth、* outHeight和outMimeType属性都会被赋值。** @param reqWidth  目标宽度,这里的宽高只是阀值,实际显示的图片将小于等于这个值* @param reqHeight 目标高度,这里的宽高只是阀值,实际显示的图片将小于等于这个值*/public static BitmapFactory.Options calculateInSampleSize(final BitmapFactory.Options options, final int reqWidth,final int reqHeight) {// 源图片的高度和宽度final int height = options.outHeight;final int width = options.outWidth;int inSampleSize = 1;if (height > reqHeight || width > reqWidth) {// 计算出实际宽高和目标宽高的比率final int heightRatio = Math.round((float) height/ (float) reqHeight);final int widthRatio = Math.round((float) width / (float) reqWidth);// 选择宽和高中最小的比率作为inSampleSize的值,这样可以保证最终图片的宽和高// 一定都会大于等于目标的宽和高。inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;}// 设置压缩比例options.inSampleSize = inSampleSize;options.inJustDecodeBounds = false;return options;}

将压缩后的bitmap存在sdcard中,待会儿要上传到服务器中。

  /*** 图片写入文件** @param bitmap*            图片* @param filePath*            文件路径* @return 是否写入成功*/public static boolean bitmapToFile(Bitmap bitmap, String filePath) {boolean isSuccess = false;if (bitmap == null) {return isSuccess;}File file = new File(filePath.substring(0,filePath.lastIndexOf(File.separator)));if (!file.exists()) {file.mkdirs();}OutputStream out = null;try {out = new BufferedOutputStream(new FileOutputStream(filePath),8 * 1024);isSuccess = bitmap.compress(Bitmap.CompressFormat.PNG, 100, out);} catch (FileNotFoundException e) {e.printStackTrace();} finally {closeIO(out);}return isSuccess;}

将压缩后的bitmap 根据需求进一步缩放,显示在imageview上。

 /*** 放大缩小图片** @param bitmap* @param w* @param h* @return*/public static Bitmap zoomBitmap(Bitmap bitmap, int w, int h) {Bitmap newbmp = null;if (bitmap != null) {int width = bitmap.getWidth();int height = bitmap.getHeight();Matrix matrix = new Matrix();float scaleWidht = ((float) w / width);float scaleHeight = ((float) h / height);matrix.postScale(scaleWidht, scaleHeight);newbmp = Bitmap.createBitmap(bitmap, 0, 0, width, height, matrix,true);}return newbmp;}

在拍照的过程中,有的机型照片会倒转,这是需要处理一下即可

/*** 读取图片属性:旋转的角度* @param path 图片绝对路径* @return degree旋转的角度*/public static int readPictureDegree(String path) {int degree  = 0;try {ExifInterface exifInterface = new ExifInterface(path);int orientation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);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;}} catch (IOException e) {e.printStackTrace();}return degree;}/*** 旋转图片* @param angle* @param bitmap* @return*/public static Bitmap rotaingImageView(int angle , Bitmap bitmap) {//旋转图片 动作Matrix matrix = new Matrix();matrix.postRotate(angle);System.out.println("angle2=" + angle);// 创建新的图片Bitmap resizedBitmap = Bitmap.createBitmap(bitmap, 0, 0,bitmap.getWidth(), bitmap.getHeight(), matrix, true);return resizedBitmap;}

这些代码百分之七八十来自开源中国。感谢原作者。

源码下载


http://www.ppmy.cn/news/789662.html

相关文章

javasxript图片预加载兼容代码(IE7/IE8/IE9/火狐/谷歌/苹果)

代码很简单 //图片预加载 function readyImage(url,callback){var img new Image(); img.srcurl;if(img.complete){ var imgWh [img.width,img.height];callback(i,imgWh);}else{img.onload function(){var imgWh [img.width,img.height];callback(i,imgWh);}} } 我看很…

A7架构

以Cortex-A7 MPCore processor来进行说明&#xff0c;这是一款主打低功耗的多核处理器&#xff0c;采用ARMv7-A架构&#xff0c;最多支持4个core。 每个core都有L1级的Cache&#xff0c;分为instruction cache&#xff0c;data cache。四个core分别连接到SCU(Snoop Control Uni…

CSS3 3D相册

今天来做一个基于CSS3 3D属性的3D相册效果。 1 基本布局 首先来完成基本布局&#xff0c;从效果图中可以看到&#xff0c;所有图片一开始均位于同一位置&#xff0c;然后经过不同的角度的旋转以及平移到不同的位置&#xff0c;达到一个”旋转散开”的效果。所以基本的思路就是…

xapian的使用

1、先来看一下Xapian的介绍&#xff1a; Xapian的官方网站是http://www.xapian.org&#xff0c;这是一个非常优秀的开源搜索引擎项目&#xff0c;搜索引擎其实只是一个通俗的说法&#xff0c;正式的说法其实是IR&#xff08;Information Retrieval&#xff09;系统。Xapian的Li…

HTML-网页-3D旋转相册-创意相册

HTML-网页-3D旋转相册 代码&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>3D旋转相册</title><style>*{margin: 0;padding: 0;}html,body{height: 100%;}body{overflow: h…

Android 7.0 适配相机及裁剪图片

Android 7.0调用相机及裁剪图片,还有动态权限 简书&#xff1a;Android 7.0 文件读取适配&#xff0c;及适配相机及裁剪图片 Demo挂载在码云上 码云链接 Github代码 华为荣耀V8和小米5测试通过&#xff0c;其他机子没机会测试。。。。 因为公司项目需要能修改头像功能&…

HTML旋转相册

✅作者简介&#xff1a;大家好我是每天都要敲代码&#xff0c;一位材料转码农的选手&#xff0c;希望一起努力&#xff0c;一起进步&#xff01; &#x1f4c3;个人主页&#xff1a;每天都要敲代码的个人主页 &#x1f4ac;在我们学习的过程中&#xff0c;肯定需要刷题&#xf…

H5实现拍照及相册图片上传

最近在做一个H5的小型电商项目&#xff0c;其中有一个是现金刷卡之后需要上传凭证图片的&#xff0c;因此也就需要在H5中实现可以上传图片。 我们都知道&#xff0c;input标签的type为file是可以上传图片的&#xff0c;本来想着这么简单&#xff0c;有啥难的&#xff0c;可是到…