Android Studio开发相机APP拍照画质过低及图库显示问题求助
解决相机APP低分辨率问题 + 图库显示实现方案
嘿,作为刚入坑Android开发的新手,碰到相机拍出来的照片分辨率只有177×144、远低于手机支持的3MP的问题,肯定超头疼吧!我来帮你一步步搞定这两个需求——提升照片画质,还有让拍摄的照片在图库中显示~
一、先搞定低分辨率的核心问题
你拍出来的照片尺寸这么小,大概率是没给相机指定合适的拍照/预览分辨率,默认用了系统提供的最小尺寸。下面是具体的修复步骤:
1. 获取并设置相机支持的最佳分辨率
不管你用的是旧的Camera API还是新的CameraX,都不能依赖默认的分辨率,得手动挑选合适的尺寸。这里先以新手常用的旧Camera API为例:
- 先获取相机支持的所有拍照尺寸列表,然后挑最大的(或者最接近3MP的,3MP大概对应2048×1536左右):
// 假设你已经获取到了Camera实例camera Camera.Parameters params = camera.getParameters(); List<Camera.Size> pictureSizes = params.getSupportedPictureSizes(); // 筛选出分辨率最大的拍照尺寸 Camera.Size bestPicSize = pictureSizes.get(0); for (Camera.Size size : pictureSizes) { if (size.width * size.height > bestPicSize.width * bestPicSize.height) { bestPicSize = size; } } // 同时要设置预览尺寸,最好和拍照尺寸比例一致,避免画面拉伸 List<Camera.Size> previewSizes = params.getSupportedPreviewSizes(); Camera.Size bestPreviewSize = findMatchingPreviewSize(previewSizes, bestPicSize); // 把选中的尺寸应用到相机参数 params.setPictureSize(bestPicSize.width, bestPicSize.height); params.setPreviewSize(bestPreviewSize.width, bestPreviewSize.height); camera.setParameters(params);
- 上面用到的
findMatchingPreviewSize方法,用来匹配和拍照尺寸比例最接近的预览尺寸,避免画面变形:
private Camera.Size findMatchingPreviewSize(List<Camera.Size> previewSizes, Camera.Size picSize) { float picRatio = (float) picSize.width / picSize.height; Camera.Size bestMatch = previewSizes.get(0); float minRatioDiff = Float.MAX_VALUE; for (Camera.Size size : previewSizes) { float previewRatio = (float) size.width / size.height; float diff = Math.abs(previewRatio - picRatio); if (diff < minRatioDiff) { minRatioDiff = diff; bestMatch = size; } } return bestMatch; }
2. 检查JPEG压缩质量
有时候即使分辨率设置对了,过度压缩也会让画质看起来很差,记得设置JPEG质量:
params.setJpegQuality(90); // 范围0-100,数值越高画质越好,文件也会稍大
3. 别用缩略图保存!
很多新手会犯的错误:用takePicture回调里的byte[] data直接保存,这个data其实是缩略图!要保存全尺寸图片,得写入到文件里:
camera.takePicture(null, null, new Camera.PictureCallback() { @Override public void onPictureTaken(byte[] data, Camera camera) { File picFile = getOutputMediaFile(); if (picFile != null) { savePictureToFile(data, picFile); // 这里后面再加图库更新的代码 } } }); // 获取图片存储的路径 private File getOutputMediaFile() { File mediaDir = new File(Environment.getExternalStoragePublicDirectory( Environment.DIRECTORY_PICTURES), "MyCameraApp"); if (!mediaDir.exists() && !mediaDir.mkdirs()) { Toast.makeText(this, "创建存储目录失败", Toast.LENGTH_SHORT).show(); return null; } String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()).format(new Date()); return new File(mediaDir.getPath() + File.separator + "IMG_" + timeStamp + ".jpg"); } // 把图片写入文件 private void savePictureToFile(byte[] data, File file) { try (FileOutputStream fos = new FileOutputStream(file)) { fos.write(data); } catch (IOException e) { e.printStackTrace(); Toast.makeText(this, "保存图片失败", Toast.LENGTH_SHORT).show(); } }
二、让照片在图库中显示
拍完照后,系统图库不会自动扫描到新文件,得手动通知媒体库更新:
在savePictureToFile执行完成后,添加以下代码:
// 通知媒体库扫描新图片 MediaScannerConnection.scanFile(this, new String[]{file.getAbsolutePath()}, new String[]{"image/jpeg"}, new MediaScannerConnection.OnScanCompletedListener() { @Override public void onScanCompleted(String path, Uri uri) { Toast.makeText(MyCameraActivity.this, "照片已保存到图库", Toast.LENGTH_SHORT).show(); } });
新手必看的权限提示
别忘了在AndroidManifest.xml里加必要的权限,而且Android 6.0以上还要动态申请:
<!-- 相机权限 --> <uses-permission android:name="android.permission.CAMERA" /> <uses-feature android:name="android.hardware.camera" /> <!-- 存储权限 --> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
动态申请权限的代码可以放在Activity的onCreate里:
if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED || ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE}, 100); // 请求码随便设,只要唯一就行 }
额外小建议
如果你是刚学Android,非常推荐用CameraX来开发相机功能,它比旧的Camera API更简单,兼容性也更好。设置分辨率只需要几行代码:
ImageCapture imageCapture = new ImageCapture.Builder() .setTargetResolution(new Size(2048, 1536)) // 直接指定3MP左右的分辨率 .setJpegQuality(90) .build();
内容的提问来源于stack exchange,提问作者Lavesh Pillay




