android 自定义相机 取矩形内内容 注意事项
android 自定义相机 遇到的几种情况
?
1.预览图相拉伸
2.预览黑屏
3.PictureCallback无响应
4.finish当前页面报错
?
首先 预览图相拉伸 ?是由于?SurfaceView ?的尺寸 ?与 ?PreviewSize(预览尺寸) 比例不相同导致的。
?
解决办法 设置 预览尺寸
?
//设置预览尺寸 Camera.Parameters parameters = c.getParameters(); parameters.setPreviewSize(size.width, size.height); //设置SurfaceView尺寸 Size size = mCamera.getParameters().getPreviewSize(); float scale = this.getWidth()/Float.parseFloat(size.height+""); this.getLayoutParams().height = (int) (size.width*scale);
?这样能解决 预览拉伸的问题
?
?当然 这里 涉及到 怎么样取 合适的 预览尺寸 ,以下的网上的一个参考
? ??
/** * 获取最适合屏幕的照片 尺寸 * * @param sizes * @param w * @param h * @return */ private static Size getOptimalPreviewSize(List<Size> sizes, int w, int h) { final double ASPECT_TOLERANCE = 0.1; double targetRatio = (double) w / h; if (sizes == null) return null; Size optimalSize = null; double minDiff = Double.MAX_VALUE; int targetHeight = h; // Try to find an size match aspect ratio and size for (Size size : sizes) { double ratio = (double) size.width / size.height; if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) continue; if (Math.abs(size.height - targetHeight) < minDiff) { optimalSize = size; minDiff = Math.abs(size.height - targetHeight); } } // Cannot find the one match the aspect ratio, ignore the requirement if (optimalSize == null) { minDiff = Double.MAX_VALUE; for (Size size : sizes) { if (Math.abs(size.height - targetHeight) < minDiff) { optimalSize = size; minDiff = Math.abs(size.height - targetHeight); } } } return optimalSize; }
?
?
? ?具体获取“最适合的尺寸”
? ?
//先取到所有的预览尺寸,再按屏幕的宽高来获取“最适合”的尺寸 //当然如果你的SurfaceView 不是按屏幕宽高来的 你需要以SurfaceView宽高为准 //注意 因为 预览的时候 需要 旋转90度。所以这里的宽是高 高 即是宽 List<Camera.Size> sizes = parameters.getSupportedPreviewSizes(); Size size = getOptimalPreviewSize(sizes, dm.heightPixels, dm.widthPixels);
?
?
? ?黑屏以及PictureCallback无响应 都有可能是 设置了不合适的相片尺寸 (setPictureSize)?
?
? ?如果想预览的内容即等于生成的相片的内容,可能需要 将 预览尺寸与相片尺寸设置相同,或者比例相同
?
? ?但事不与人愿,一般来说将相片尺寸设置成 相片尺寸 不会有太大的问题,但在某些情况下是不行的。因为预览尺寸里有的尺寸 有可能 在相片尺寸中不存在,这个时候会出现 预览黑屏 或者 ?相机回调无响应
? ??
? ?博主解决办法为:先获取“最适合” 屏幕的 相片尺寸,再按相片尺寸来取最“合适”的预览尺寸,根据预览的尺寸再来调整SurfaceView的尺寸
?
? ?具体操作为:
? ?
Camera c = Camera.open(); Camera.Parameters parameters = c.getParameters(); //先找最合适的照片尺寸 List<Camera.Size> pictureSizes = parameters.getSupportedPictureSizes(); Size pictureSize = getOptimalPreviewSize(pictureSizes, dm.heightPixels, dm.widthPixels); parameters.setPictureSize(pictureSize.width, pictureSize.height); //再找最合适的预览尺寸 List<Camera.Size> sizes = parameters.getSupportedPreviewSizes(); Size size = getOptimalPreviewSize(sizes, pictureSize.width, pictureSize.height); parameters.setPreviewSize(size.width, size.height); c.setParameters(parameters); //再调整SurfaceView 宽高,注意 调整宽高得在SurfaceView能获取宽高的时候 //博主是在surfaceCreated方法中调整的 Size size = mCamera.getParameters().getPreviewSize(); float scale = this.getWidth()/Float.parseFloat(size.height+""); this.getLayoutParams().height = (int) (size.width*scale);
??
? ?既然 ?预览的尺寸比较与相片的尺寸比例相同,那取SurfaceView中的部分内容当然是很容易了。
?
? 首先肯定在SurfaceView层上画了一个矩形 或者 别的啥形,按图片的实际尺寸 等比缩放,然后用bitmap裁 ? 剪即可
?
? ?
? 关键代码
? ?
PictureCallback callback = new PictureCallback() { @Override public void onPictureTaken(byte[] data, Camera camera) { mCamera.setPreviewCallback(null); mCamera.stopPreview(); releaseCamera(); //旋转90度 Bitmap bMap = BitmapFactory.decodeByteArray(data, 0, data.length); Bitmap bMapRotate; Matrix matrix = new Matrix(); matrix.reset(); matrix.postRotate(90); bMapRotate = Bitmap.createBitmap(bMap, 0, 0, bMap.getWidth(), bMap.getHeight(),matrix,false); //截取矩形内照片 ViewfinderView vf = (ViewfinderView) findViewById(R.id.viewfinder_view); float scale = bMapRotate.getWidth()/Float.valueOf(vf.getWidth()); int width = (int) (vf.rwidth*scale); int height = (int) (vf.rheight*scale); bMapRotate = Bitmap.createBitmap(bMapRotate, (int)(vf.leftOffset*scale), (int)(vf.topOffset*scale), width, height); bMap = bMapRotate; // Intent intent = new Intent(); // intent.putExtra("data", data); //设置返回数据 // CameraActivity.this.setResult(RESULT_OK); CameraActivity.this.finish(); } };
?
?
? ? 这里可能会出现finish无响应的问题,如果 将 裁剪完的bitmap 直接放入 ?intent中,虽然没看到报啥错,但是finish当然页面 无反应,clone 一个bitmap再传 问题依旧,博主将bitmap转成byte[] 解决了问题,但是图片过大的时候又会出现新的问题,事务过大。没法传。当然你也可能先存成文件,再传一个文件路径过去,但是如果回跳的页面中用到了bitmap 这个时候又得将file ?decodefile成bitmap 感觉无用功很多。?实现没办法只能推荐用静态变量的方法。博主解决为在Application中添加几个静态方法
? ? ??
private static Object object; public static void set(Object obj){ Application.object = obj; } public static Object get(){ return Application.object; } @SuppressWarnings("unchecked") public static <T> T get(Class<T> clazz){ return (T)Application.object; } public static void clear(){ Application.object = null; }
? ??
? ?具体使用为:
? ??
//先塞值 Application.set(bMap); //回调页面中再取值 Bitmap bMap = Application.get(Bitmap.class);
?
?
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。