Android图库选图旋转异常与图片质量下降问题修复咨询
解决相机拍照/图库选图的质量下降与旋转问题
一、图片质量下降的解决方法
问题根源
- 相机拍照时,
data.getExtras().get("data")返回的是系统压缩后的缩略图,分辨率极低,直接使用必然导致画质模糊。 - 代码中多次对Bitmap进行缩放(
ThumbnailUtils.extractThumbnail+createScaledBitmap),反复压缩会让图片细节大量丢失。 - 图库选图用的
MediaStore.Images.Media.getBitmap是过时API,解码原图时没有做优化,也会间接影响画质。
修复步骤
1. 相机拍照改为获取原图
首先在启动相机前,先创建一个临时文件用来保存原图:
// 成员变量 private Uri cameraImageUri; // 启动相机的方法 private void startCamera() { Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); if (takePictureIntent.resolveActivity(getPackageManager()) != null) { File photoFile = null; try { photoFile = createImageFile(); } catch (IOException ex) { // 处理文件创建失败逻辑 } if (photoFile != null) { cameraImageUri = FileProvider.getUriForFile(this, "你的应用包名.fileprovider", photoFile); takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, cameraImageUri); startActivityForResult(takePictureIntent, 2); } } } // 创建临时图片文件 private File createImageFile() throws IOException { String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date()); String imageFileName = "JPEG_" + timeStamp + "_"; File storageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES); return File.createTempFile(imageFileName, ".jpg", storageDir); }
然后在onActivityResult的相机分支,读取这个文件获取原图:
// 相机分支修改后 if (requestCode == 2) { Bitmap imgCam = null; try { imgCam = BitmapFactory.decodeStream(getContentResolver().openInputStream(cameraImageUri)); } catch (IOException e) { e.printStackTrace(); } if (imgCam == null) return; // 修正图片方向 imgCam = rotateBitmapByExif(imgCam, cameraImageUri.getPath()); // 仅做一次目标尺寸缩放 imgCam = Bitmap.createScaledBitmap(imgCam, imgSize, imgSize, true); cropBitmap = Utils.processBitmap(imgCam, TF_OD_API_INPUT_SIZE); imgHinh.setImageBitmap(imgCam); loading = new ProgressDialog(this); loading.show(); initBox(); Bitmap finalImgCam = imgCam; new CountDownTimer(2000,1000) { public void onFinish() { classifyImage(finalImgCam); loading.dismiss(); } public void onTick(long millisUntilFinished) {} }.start(); }
2. 图库选图优化解码逻辑
替换过时API,用BitmapFactory.Options优化解码,避免不必要的内存占用和画质损失:
// 图库分支修改后 else if (requestCode == 3) { Uri dat = data.getData(); Bitmap imgChoose = null; try { BitmapFactory.Options options = new BitmapFactory.Options(); options.inPreferredConfig = Bitmap.Config.ARGB_8888; options.inSampleSize = calculateInSampleSize(options, imgSize, imgSize); InputStream inputStream = getContentResolver().openInputStream(dat); imgChoose = BitmapFactory.decodeStream(inputStream, null, options); // 修正图片方向 imgChoose = rotateBitmapByExif(imgChoose, getRealPathFromUri(dat)); } catch (IOException e) { e.printStackTrace(); } if (imgChoose == null) return; imgChoose = Bitmap.createScaledBitmap(imgChoose, imgSize, imgSize, true); cropBitmap = Utils.processBitmap(imgChoose, TF_OD_API_INPUT_SIZE); imgHinh.setImageBitmap(imgChoose); loading = new ProgressDialog(this); loading.show(); initBox(); Bitmap finalImgChoose = imgChoose; new CountDownTimer(2000,1000) { public void onFinish() { classifyImage(finalImgChoose); loading.dismiss(); } public void onTick(long millisUntilFinished) {} }.start(); } // 计算采样率,避免内存溢出 private int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) { final int height = options.outHeight; final int width = options.outWidth; int inSampleSize = 1; if (height > reqHeight || width > reqWidth) { final int halfHeight = height / 2; final int halfWidth = width / 2; while ((halfHeight / inSampleSize) >= reqHeight && (halfWidth / inSampleSize) >= reqWidth) { inSampleSize *= 2; } } return inSampleSize; } // 获取Uri对应的真实文件路径 private String getRealPathFromUri(Uri uri) { String[] projection = {MediaStore.Images.Media.DATA}; Cursor cursor = getContentResolver().query(uri, projection, null, null, null); if (cursor == null) return null; int columnIndex = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA); cursor.moveToFirst(); String path = cursor.getString(columnIndex); cursor.close(); return path; }
二、三星手机图片旋转的解决方法
问题根源
图片拍摄时会在Exif信息中记录方向(比如竖屏拍照时标记为旋转90度),部分品牌手机系统会自动修正这个方向,但三星部分机型需要手动读取Exif信息并旋转图片。
修复步骤
编写工具方法读取Exif方向并旋转Bitmap:
// 读取Exif方向并修正图片角度 private Bitmap rotateBitmapByExif(Bitmap bitmap, String imagePath) { ExifInterface exif = null; try { exif = new ExifInterface(imagePath); } catch (IOException e) { e.printStackTrace(); return bitmap; } int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL); Matrix matrix = new Matrix(); switch (orientation) { case ExifInterface.ORIENTATION_ROTATE_90: matrix.postRotate(90); break; case ExifInterface.ORIENTATION_ROTATE_180: matrix.postRotate(180); break; case ExifInterface.ORIENTATION_ROTATE_270: matrix.postRotate(270); break; default: return bitmap; } return Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true); }
内容的提问来源于stack exchange,提问作者James Black
相关产品推荐
相关产品推荐

