项目场景:
调用系统相机拍照、选择相册照片
问题描述:
部分手机(例如:三星、LG)调用系统相机拍照会模糊和旋转问题,选择的照片也会旋转问题
调用代码:
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);startActivityForResult(intent,CAMERA_CODE);
onActivityResult里面从data里获取图片:data.getExtras().get(“data”)
原因分析:
模糊:在部分的三星等手机直接采用此Intent跳转方式,拍照后从data里获取的只是一个缩略图不是真实的原本的图片,要想获得真实的图片需要拍照时指定一个存储路径,将原图保存,然后onActivityResult里从路径里面取原图
旋转:拍照后旋转可能是手机的通过这种方式调用相机拍照设置的默认方向的原因,不管系统默认的是怎样的角度,通过ExifInterface获取图片信息就将旋转的角度再转回来即可,一般是顺时针旋转90度
解决方案:
模糊:
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);if (intent.resolveActivity(getPackageManager()) != null) {File photoFile = null;try {photoFile = createImageFile();} catch (IOException e) {e.printStackTrace();}if (photoFile != null) {mCurrentPhotoUri = FileProvider.getUriForFile(OcrUpdateInfoActivity.this,getPackageName() + ".provider", photoFile);intent.putExtra(MediaStore.EXTRA_OUTPUT, mCurrentPhotoUri);intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {List<ResolveInfo> resInfoList = getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);for (ResolveInfo resolveInfo : resInfoList) {String packageName = resolveInfo.activityInfo.packageName;grantUriPermission(packageName, mCurrentPhotoUri,Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);}}startActivityForResult(intent, CAMERA_CODE);}}@SuppressWarnings("ResultOfMethodCallIgnored")private File createImageFile() throws IOException {// Create an image file nameString timeStamp =new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()).format(new Date());String imageFileName = String.format("JPEG_%s.jpg", timeStamp);File storageDir;storageDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);if (!storageDir.exists()) storageDir.mkdirs();storageDir = new File(storageDir, "xxx");if (!storageDir.exists()) storageDir.mkdirs();// Avoid joining path components manuallyFile tempFile = new File(storageDir, imageFileName);// Handle the situation that user's external storage is not readyif (!Environment.MEDIA_MOUNTED.equals(EnvironmentCompat.getStorageState(tempFile))) {return null;}return tempFile;}
接下来onActivityResult里面不从data里获取图片,而是通过使用mCurrentPhotoUri 获取存放路径和bitmap
旋转:
int degree = readPictureDegree(path);
if (degree != 0) {resultBitmap = rotaingImageView(degree, bitmap);
}/*** 读取照片旋转角度** @param path 照片路径* @return 角度*/public 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 Bitmap rotaingImageView(int angle, Bitmap bitmap) {Bitmap returnBm = null;// 根据旋转角度,生成旋转矩阵Matrix matrix = new Matrix();matrix.postRotate(angle);try {// 将原始图片按照旋转矩阵进行旋转,并得到新的图片returnBm = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);} catch (OutOfMemoryError e) {}if (returnBm == null) {returnBm = bitmap;}if (bitmap != returnBm) {bitmap.recycle();}return returnBm;}
根据ExifInterface 里的信息判断图片是否有旋转角度,不等于0就去将bitmap旋转就行了。