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 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 sizefor (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 requirementif (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 sizes = parameters.getSupportedPreviewSizes();Size size = getOptimalPreviewSize(sizes, dm.heightPixels, dm.widthPixels);

 

 

   黑屏以及PictureCallback无响应 都有可能是 设置了不合适的相片尺寸 (setPictureSize) 

 

   如果想预览的内容即等于生成的相片的内容,可能需要 将 预览尺寸与相片尺寸设置相同,或者比例相同

 

   但事不与人愿,一般来说将相片尺寸设置成 相片尺寸 不会有太大的问题,但在某些情况下是不行的。因为预览尺寸里有的尺寸 有可能 在相片尺寸中不存在,这个时候会出现 预览黑屏 或者  相机回调无响应

    

   博主解决办法为:先获取“最适合” 屏幕的 相片尺寸,再按相片尺寸来取最“合适”的预览尺寸,根据预览的尺寸再来调整SurfaceView的尺寸

 

   具体操作为:

   

Camera c = Camera.open();Camera.Parameters parameters = c.getParameters();//先找最合适的照片尺寸List pictureSizes = parameters.getSupportedPictureSizes();Size pictureSize = getOptimalPreviewSize(pictureSizes, dm.heightPixels, dm.widthPixels);parameters.setPictureSize(pictureSize.width, pictureSize.height);//再找最合适的预览尺寸List 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 get(Class clazz){return (T)Application.object;}public static void clear(){Application.object = null;}

    

   具体使用为:

    

//先塞值Application.set(bMap);//回调页面中再取值Bitmap bMap = Application.get(Bitmap.class);

 

 

更多相关文章

  1. Android的MediaRecorder架构介绍
  2. Android资源文件 - 使用资源存储字符串 颜色 尺寸 整型 布尔值
  3. Android(安卓)计算控件尺寸
  4. Android(安卓)studio不能在布局预览的问题
  5. android中的多媒体应用camera
  6. android camera 通过onPreviewFrame采集视频
  7. Drawable Resources
  8. [转]Android设备的屏幕尺寸规格
  9. 一款APP设计的从0到1之:Android设计规范篇

随机推荐

  1. BlockCanary原理解析(Android端UI卡顿监
  2. Android(安卓)常用知识点整理(含链接)
  3. android Configuration系统设置 .
  4. android中如何捕获home键
  5. Android(安卓)Service教程
  6. [已解决]Android(安卓)ListView EditView
  7. Android不同的Activity怎么联系
  8. Android(安卓)onAttach 的使用
  9. Android的3种Notification实现方式详解
  10. Android遇到的错误记录