zoukankan      html  css  js  c++  java
  • Android Camera多屏幕适配解决预览照片拉伸

    通常,拍照预览页面的照片拉伸主要与下面两个因素有关:

    1.     Surfaceview的大小

    2.     Camera中的Preview的大小

    如下图:

        图中preview显示的是手机支持的预览尺寸,picture显示的是手机支持设置图片尺寸,screen显示的是屏幕尺寸,surface显示的是surfaceview尺寸,default pre:手机缺省情况下的预览尺寸,default pic:手机缺省请款下的图片尺寸。reqPreview:手机设置的预览尺寸,reqPicSize:手机设置的图片尺寸。
     

     

    如图,该手机surfaceview大小为1280*720(横屏,比例为:16:9)预览尺寸大小为960*720(横屏,比例为4:3)。从上面的二维码可以看到产生了明显的拉伸。正因为surfaceview的宽高比例跟camera preview的宽高比例不一样才会产生这样的效果。

    如果surfaceview尺寸比例跟预览尺寸比例相同,那便不会产生变形,如下图:

    设置surfaceview大小为 1280*720(横屏,比例为:4:3)预览尺寸大小为2048*1152(横屏,比例为4:3)便不会拉伸变形。

    上面只是针对一种屏幕进行设置,而且每台手机所支持的预览尺寸是不一样的,所以这样子固定死的话很可能会产生程序崩溃,而崩溃的原因是因为该手机不支持你所支持的尺寸。

    那么问题就来了,怎么样才能够达到适配多台手机,界面不产生拉伸变形,而且程序又不崩溃?

    思路如下:

    1.     先将获取手机支持预览的尺寸列表通过方法parmeters.getSupportedPreviewSizes()来得到返回类型为List<Size>的值,

    2.     先进行屏幕方向的一个判断,因为预览列表里面的尺寸都是w>h(即横屏),如果屏幕是竖屏则需要先将宽高进行调换,这样方便接下来的比较。

    3.     先用for循环将预览尺寸列表每个元素宽高与surfaceview的宽高进行比较,如果存在宽高尺寸都与surfaceview宽高尺寸相同的size则将该宽高设置为预览尺寸。

    4.     如果步骤2找不到相同尺寸就得进行该步骤,将尺寸列表的宽高比例和surfaceview的比例作比较,找到一个相同或相近的。(一般来说,只要surfaceview的尺寸和屏幕尺寸相同,就可以找到相同的比例)然后将该尺寸的size设置为预览尺寸。

    接下来是上代码

      

    /**
         * 通过对比得到与宽高比最接近的尺寸(如果有相同尺寸,优先选择)
         * 
         * @param surfaceWidth
         *            需要被进行对比的原宽
         * @param surfaceHeight
         *            需要被进行对比的原高
         * @param preSizeList
         *            需要对比的预览尺寸列表
         * @return 得到与原宽高比例最接近的尺寸
         */
        protected Camera.Size getCloselyPreSize(int surfaceWidth, int surfaceHeight,
                List<Size> preSizeList) {
            
            int ReqTmpWidth;
            int ReqTmpHeight;
            // 当屏幕为垂直的时候需要把宽高值进行调换,保证宽大于高
            if (mIsPortrait) {
                ReqTmpWidth = surfaceHeight;
                ReqTmpHeight = surfaceWidth;
            } else {
                ReqTmpWidth = surfaceWidth;
                ReqTmpHeight = surfaceHeight;
            }
            //先查找preview中是否存在与surfaceview相同宽高的尺寸
            for(Camera.Size size : preSizeList){
                if((size.width == ReqTmpWidth) && (size.height == ReqTmpHeight)){
                    return size;
                }
            }
            
            // 得到与传入的宽高比最接近的size
            float reqRatio = ((float) ReqTmpWidth) / ReqTmpHeight;
            float curRatio, deltaRatio;
            float deltaRatioMin = Float.MAX_VALUE;
            Camera.Size retSize = null;
            for (Camera.Size size : preSizeList) {
                curRatio = ((float) size.width) / size.height;
                deltaRatio = Math.abs(reqRatio - curRatio);
                if (deltaRatio < deltaRatioMin) {
                    deltaRatioMin = deltaRatio;
                    retSize = size;
                }
            }
    
            return retSize;
        }

    其中 参数 width 和height 是 SurfaceView 的宽和高,可以在surfaceChanged方法中找到:

    package com.yfqsdie.tower.preview;
    
    import com.yfqsdie.tower.util.CameraUtil;
    
    import android.content.Context;
    import android.graphics.PixelFormat;
    import android.hardware.Camera;
    import android.os.Handler;
    import android.util.AttributeSet;
    import android.view.SurfaceHolder;
    import android.view.SurfaceView;
    
    /**
     * Created by renlei
     * DATE: 15-11-5
     * Time: 下午4:52
     */
    public class MySurfacePreview extends SurfaceView implements SurfaceHolder.Callback {
        private SurfaceHolder surfaceHolder;
        private Handler mHandler;
    
        public MySurfacePreview(Context context, AttributeSet attrs) {
            super(context, attrs);
            surfaceHolder = getHolder();
            surfaceHolder.setFormat(PixelFormat.TRANSPARENT);//translucent半�?�明 transparent透明
            surfaceHolder.addCallback(this);
        }
    
        @Override
        public void surfaceCreated(SurfaceHolder holder) {
            CameraUtil.getInstance().doOpenCamera(Camera.CameraInfo.CAMERA_FACING_BACK);
        }
    
        @Override
        public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
            System.out.print("width="+width+" height="+height+" format="+format);
    //        CameraUtil.getInstance().doStartPreview(surfaceHolder);
            CameraUtil.getInstance().doStartPreview(surfaceHolder,width,height);  //spire modify 2017-09-27 解决变形问题
            if (mHandler != null) {
                mHandler.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        mHandler.sendEmptyMessage(CameraUtil.PREVIEW_HAS_STARTED);
                    }
                }, 1000);
            }
        }
    
        @Override
        public void surfaceDestroyed(SurfaceHolder holder) {
            CameraUtil.getInstance().doStopPreview();
        }
    
        public void setmHandler(Handler handler) {
            this.mHandler = handler;
        }
    }
     
  • 相关阅读:
    hiveserver2 with kerberos authentication
    python Basic usage
    python Quicksort demo
    Python HeapSort
    mrunit for wordcount demo
    CCDH证书
    Hadoop question list
    Hadoop Yarn core concepts
    Hadoop Resource
    Hadoop could not find or load main class
  • 原文地址:https://www.cnblogs.com/aspirant/p/7602151.html
Copyright © 2011-2022 走看看